BartoszOsiej/talus-process-monitor

eBPF ransomware tracker — kernel execve/openat tracing, per-CPU perf buffers, frankentui TUI, sliding-window alerts

Rust

0

200 commits

updated Sep 18, 2026

See the code
aya
ebpf
ebpf-tracing
kernel
linux
process-monitor
ransomware
ratatui
rust
security
tui

See what people are saying (1)

SourceMessageScoreDate

Talus: eBPF ransomware detector for Linux (Rust)

1

Sep 18, 2026

README

🛡️ Talus — Endpoint Security Agent

License Rust eBPF Go Docker Enterprise

eBPF-based endpoint security agent for Linux — detect ransomware behaviour, respond at the kernel edge.

Talus is not a passive monitor. It is a detect-and-respond agent that hooks syscalls at the kernel level via eBPF tracepoints, scores per-process file-open rates in real-time, and terminates offending processes the instant a heuristic verdict fires. It processes ~500k events/sec through per-CPU perf buffers with zero-copy handoff to a userspace detection engine built in Rust.

🇵🇱 Wersja polska · Architecture · 📄 Enterprise Report (PDF) · Enterprise Maturity


Table of Contents


What It Does

CapabilityHow
Kernel-level tracingeBPF tracepoints on execve, openat, connect, accept, sendto, recvfrom, mkdir, unlinkat, kill, fchmodat
Ransomware detection1-second sliding window per PID; alerts when file-open rate exceeds configurable threshold
Automated response--auto-kill sends SIGKILL to the offending process on alert verdict
Network egress trackingParses sockaddr in-kernel — captures IPv4/IPv6/Unix addresses on connect/accept/send/recv
Event pipelineKernel perf buffer → zero-copy ring → detection engine → TUI / JSON / WebSocket / Prometheus
Process treeResolves PPID from /proc, builds hierarchical view with per-process alert counts
File rankingMost-opened files with Shannon entropy scoring (detects encrypted/randomised filenames)
Single binaryFull LTO, panic = "abort", symbol-stripped — 1.7 MB TUI, 2.5 MB with web
Kafka streamingEvents → Kafka topics with lz4 compression, partitioned by PID
ClickHouse storageBatch inserts into MergeTree for analytics retention
MemGraph graphProcess trees + file access as a graph (Cypher queries)

Architecture / Data Flow

Talus follows a pipeline architecture — kernel ingestion → userspace detection → operator response:

┌─────────────────────────────────────────────────────────────────────────┐
│                      KERNEL SPACE (eBPF programs)                       │
│                                                                         │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐                  │
│  │ sys_enter_   │  │ sys_enter_   │  │ sys_enter_   │                  │
│  │ execve       │  │ openat       │  │ connect      │ ... 10 total     │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘                  │
│         │                 │                 │                            │
│         ▼                 ▼                 ▼                            │
│  ┌─────────────────────────────────────────────────────┐               │
│  │  ProcessEvent { pid, uid, comm, filename, argv }    │               │
│  │  PerfEventArray (per-CPU, zero-copy)                │               │
│  └──────────────────────────┬──────────────────────────┘               │
└─────────────────────────────┼───────────────────────────────────────────┘
                              │
┌─────────────────────────────┼───────────────────────────────────────────┐
│                      USERSPACE (Rust)                                   │
│                              │                                           │
│  ┌───────────────────────────▼──────────────────────────┐              │
│  │  Reader thread — reads perf buffers per CPU          │              │
│  │  MPSC channel → Monitor event loop                   │              │
│  └───────────────────────────┬──────────────────────────┘              │
│                              │                                           │
│  ┌───────────────────────────▼──────────────────────────┐              │
│  │  DETECTION ENGINE                                    │              │
│  │  • Sliding window per PID (1s rolling)               │              │
│  │  • File-extension frequency tracking                 │              │
│  │  • Shannon entropy scoring on filenames              │              │
│  │  • Per-process stats (opens, execs, alerts, PPID)    │              │
│  └───────────┬─────────────────────────┬───────────────┘              │
│              │ VERDICT                  │                              │
│              ▼                          ▼                               │
│  ┌─────────────────────┐  ┌────────────────────────────┐              │
│  │  RESPONSE           │  │  OUTPUT                     │              │
│  │  kill(pid, SIGKILL) │  │  TUI (7 panels)            │              │
│  │  cgroup freeze      │  │  JSON / WebSocket           │              │
│  │  (extensible)       │  │  Prometheus /metrics        │              │
│  └─────────────────────┘  │  REST API                   │              │
│                           └────────────────────────────┘              │
└─────────────────────────────────────────────────────────────────────────┘

Pipeline stages

StageComponentThroughputMechanism
1. IngesteBPF tracepoints~500k events/sbpf_perf_event_output per-CPU
2. TransportPerfEventArrayzero-copyPerfEventArrayBuffer::read_events
3. DetectSliding window enginereal-time1s rolling window, configurable threshold
4. Respondkill(2) / cgroup< 1ms latencySIGKILL on heuristic verdict
5. PersistTUI / JSON / WebSocketlive streamREST API + Prometheus for retention

This maps directly to a Kafka-style event pipeline: kernel perf buffer = topic, reader thread = consumer, detection engine = stream processor, TUI/API = sink.


Storage & Pipeline

Talus supports pluggable storage backends for event persistence and downstream analytics:

# Stream events to Kafka
sudo talus --kafka-brokers localhost:9092 --kafka-topic talus-events

# Store events in ClickHouse for analytics
sudo talus --clickhouse http://localhost:8123

# Build process relationship graph in MemGraph
sudo talus --memgraph http://localhost:7474

# Combine all backends
sudo talus \
  --kafka-brokers localhost:9092 --kafka-topic talus-events \
  --clickhouse http://localhost:8123 \
  --memgraph http://localhost:7474

Kafka

Events are sent to a configurable topic with lz4 compression and partitioned by PID for ordering per-process:

ConfigDefaultDescription
--kafka-brokersBroker address (e.g. localhost:9092)
--kafka-topictalus-eventsTopic name

ClickHouse

Events are batch-inserted into a MergeTree table partitioned by date:

CREATE TABLE talus.events (
    ts DateTime64(3),
    kind LowCardinality(String),
    pid UInt32, uid UInt32,
    comm LowCardinality(String),
    file Nullable(String),
    extension LowCardinality(Nullable(String))
) ENGINE = MergeTree()
PARTITION BY toYYYYMMDD(ts)
ORDER BY (ts, kind, pid)

MemGraph

Process trees and file access patterns are stored as a graph:

// Find all processes that opened .enc files
MATCH (p:Process)-[r:OPENED]->(f:File)
WHERE f.path ENDS WITH '.enc'
RETURN p.pid, p.comm, f.path, r.count
ORDER BY r.count DESC

// Find exfiltration candidates (file opens + external network)
MATCH (p:Process)-[:OPENED]->(f:File), (p)-[:CONNECTED_TO]->(n:NetworkTarget)
WHERE NOT n.addr STARTS WITH '10.'
RETURN p.pid, p.comm, collect(f.path), collect(n.addr)

Network Visibility

Talus traces network syscalls at the kernel level — not just file operations. This provides full egress visibility for detecting data exfiltration, C2 communication, and lateral movement.

SyscallEvent TypeWhat's CapturedHow
connectConnectRemote IPv4/IPv6/Unix address + portsockaddr parsed via bpf_probe_read_user
acceptAcceptRemote address of incoming connectionSame mechanism
sendtoSendToDestination addresssockaddr at arg index 4
recvfromRecvFromSource addresssockaddr at arg index 4

In-kernel sockaddr parsing

The eBPF program reads raw sockaddr structures byte-by-byte from userspace:

// Read AF_INET address from sockaddr_in
bpf_probe_read_user(&family, 2, sockaddr_ptr);      // sa_family
bpf_probe_read_user(&port_be, 2, ptr + 2);          // sin_port (big-endian)
bpf_probe_read_user(&a0, 1, ptr + 4);               // sin_addr[0]
// ... formats as "192.168.1.1:443"

This runs in the kernel with zero userspace round-trips — addresses are resolved before the event even reaches userspace.

Example: detecting exfiltration

{"ts":"14:09:17.100","type":"event","kind":"Connect","pid":1234,"comm":"curl","file":"93.184.216.34:443"}
{"ts":"14:09:17.205","type":"event","kind":"SendTo","pid":1234,"comm":"curl","file":"93.184.216.34:443"}
{"ts":"14:09:17.502","type":"event","kind":"Open","pid":1234,"comm":"curl","file":"/home/user/Documents/backup.tar.gz"}

Detection & Response

Detection: sliding-window heuristic

Each PID maintains a 1-second rolling window of openat events. When the count hits the threshold (default: 50 opens/s), a verdict fires:

PID 2126 ("Cache2 I/O") opened 50 files in 1.0s  →  VERDICT: SUSPICIOUS

The threshold is configurable at runtime via the API or CLI:

# Lower threshold for high-security environments
sudo process-monitor --alert-threshold 20

# Filter by extension (e.g. detect .enc/.pdf mass opens)
sudo process-monitor --filter-ext enc

Response: automated termination

With --auto-kill, Talus sends SIGKILL to the offending process immediately on verdict:

# EDR mode: detect + respond
sudo process-monitor --alert-threshold 50 --auto-kill
// The response layer — ~30 lines of Rust
fn kill_process(pid: u32) -> bool {
    let rc = unsafe { libc::kill(pid as i32, libc::SIGKILL) };
    rc == 0
}

// Fired inside the detection engine on verdict:
if self.auto_kill {
    let result = kill_process(ev.pid);
    outputs.push(Output::Action(ResponseAction {
        ts: ev.ts.clone(),
        pid: ev.pid,
        action: format!("SIGKILL sent to PID {}", ev.pid),
        success: result,
    }));
}

This is extensible — the ResponseAction interface supports kill, cgroup freeze, network quarantine, or any custom response.

Detection: MeMLP neural engine (--memlp)

Beyond the heuristic window, Talus embeds MeMLP — a Modular embedded Multi-Layer Perceptron model built from scratch (no ndarray, no tch, no ONNX — just a few KB of dependency-free Rust). The same architecture powers the neural terrain generator in the NV2 voxel engine, re-targeted here at process behaviour.

ModuleShapeTask
ransomware10 → 24 → 16 → 3benign / suspicious / ransomware
lateral10 → 12 → 2lateral-movement suspect
persistence10 → 12 → 2autostart-persistence suspect

Every module consumes the same 10-feature behavioural embedding per PID (open rate, exec+network rate, filename Shannon entropy, ransomware-marker extension fraction, extension diversity, fs-mutation rate, destructive fraction, distinct-file spread, autostart-path hits, network fraction). Windows decay with a 1-second half-life, mirroring the heuristic window.

The engine trains online: every alert performs a backpropagation step (cross-entropy loss, gradient clipping, bounded updates) against transparent heuristic teachers, then scores the process. Checkpoints persist as JSON and reload on the next run, so the model keeps learning across restarts.

# Enable the neural engine (checkpoint auto-saves every 30s)
sudo process-monitor --memlp

# Explicit checkpoint location (loaded on start, saved on shutdown + autosave)
sudo process-monitor --memlp --memlp-checkpoint /var/lib/talus/memlp.json

Alerts carry the neural verdict in every output channel:

12:00:03 SUSPICIOUS [4132] encrypt.sh opened 50 files in 1s!  [MeMLP R:ransomware 91% L:normal 99% P:suspect 74%]
{"type":"alert","pid":4132,"comm":"encrypt.sh","opens_in_1s":50,
 "memlp":{"ransomware":{"module":"ransomware","class":2,"label":"ransomware","confidence":0.91}, ...}}

Requirements

RequirementNotes
Linux kernel 5.8+eBPF + tracepoint support
root (CAP_BPF / CAP_SYS_ADMIN)Required to load eBPF programs
Rust nightly + rust-srcBuilds eBPF with -Z build-std
bpf-linker, clangeBPF toolchain
BTF (/sys/kernel/btf/vmlinux)Recommended for CO-RE

Quick Start

# Distro-aware installer
./install.sh --system    # System-wide to /usr/local
./install.sh             # User-local to ~/.local

# Or build manually
./build.sh

# Run in EDR mode (detect + auto-respond)
sudo target/release/process-monitor --auto-kill

# Run in monitor-only mode (no auto-kill)
sudo target/release/process-monitor

Usage

# EDR mode — detect and auto-kill
sudo process-monitor --auto-kill

# Lower threshold for stricter detection
sudo process-monitor --auto-kill --alert-threshold 20

# Monitor only (no kill)
sudo process-monitor

# Filter by extension
sudo process-monitor --filter-ext pdf

# JSON output for external pipelines
sudo process-monitor --json | jq .

# Plain text log
sudo process-monitor --plain

# Web dashboard (requires --features web build)
sudo process-monitor --web 0.0.0.0:8080

# MeMLP neural detection engine (online training + JSON checkpoints)
sudo process-monitor --memlp
sudo process-monitor --memlp --memlp-checkpoint /var/lib/talus/memlp.json

# Self-diagnostic
sudo process-monitor --diagnose

CLI Reference

FlagDefaultDescription
-b, --bpf <PATH>autoPath to compiled eBPF object
--alert-threshold <N>50Alert when N+ files opened within 1s
--auto-killoffSend SIGKILL to processes that trigger alerts
--filter-ext <EXT>allFilter by file extension
--top-files <N>8Top files in TUI
--jsonoffNewline-delimited JSON output
--plainoffPlain text log
--memlpoffEnable the MeMLP neural detection engine
--memlp-checkpoint <PATH>~/.local/share/talus/memlp.jsonMeMLP checkpoint (load on start, autosave every 30s)
--diagnoseoff5-second self-diagnostic
--web <ADDR>offStart web server (requires --features web)

Build Variants

# TUI-only (default, 1.7MB)
./build.sh

# Web-featured (2.5MB) — REST API, WebSocket, Prometheus
./build.sh --web

# Both variants
./build.sh --all
VariantSizeDependencies
process-monitor-tui1.7MBaya, frankentui (ftui), chrono, crossterm
process-monitor-web2.5MB+axum, tokio, tower-http, prometheus-client

TUI Controls

KeyAction
q / EscQuit
pPause / resume
cClear all panels
/ / k/jScroll
TabNext panel
1-7Jump to panel
/Search mode
? / hHelp overlay

TUI Panels (7)

#PanelDescription
1EVENTSLive event log with search/filter
2PROCESSESHierarchical process tree with alert counts
3NETWORKReal-time connections (connect/accept/send/recv + IP:port)
4TOP FILESMost-opened files with Shannon entropy
5FILE TYPESExtension frequency with coloured bars
6ALERTSAlert history + response actions
7HEATMAPSyscall frequency visualisation

Web Dashboard

Optional build with --features web:

cargo build --release --features web
sudo process-monitor --web 0.0.0.0:8080
EndpointMethodDescription
/GETDashboard UI
/wsWebSocketLive event stream
/api/v1/statsGETGlobal statistics
/api/v1/processesGETTracked processes
/api/v1/filesGETTop opened files
/api/v1/extensionsGETExtension frequency
/api/v1/thresholdPOSTUpdate threshold at runtime
/metricsGETPrometheus metrics

Operator View (TUI + Web + Desktop)

Talus provides three operator interfaces:

  • TUI — 7-panel terminal interface for local investigation. Cyberpunk aesthetic, process trees, heatmaps, sparklines. Runs anywhere, no browser needed.
  • Web Dashboard — browser-based UI with WebSocket live stream, REST API for integration, and Prometheus metrics for Grafana/monitoring stacks.
  • Desktop App (Tauri + React) — native desktop GUI built with Tauri 2 + React 19 + Recharts. Connects to the talus backend via WebSocket and REST API. See talus-tauri/ for source.

All three consume the same detection engine — the agent is headless-capable and can run as a background daemon with JSON output piped to external SIEM/storage.


Project Structure

talus-process-monitor/
├── process-monitor/          # Userspace: detection engine + TUI + web + FFI
│   └── src/
│       ├── main.rs           # CLI, mode selection, signal handling
│       ├── monitor.rs        # eBPF loading, perf reader, detection, response
│       ├── tui.rs            # 7-panel frankentui (ftui) cyberpunk interface
│       ├── web.rs            # axum web server (--features web)
│       ├── ffi.rs            # C FFI bindings (libtalus)
│       └── storage/          # Kafka / ClickHouse / MemGraph backends
├── process-monitor-ebpf/     # Kernel side (#![no_std], aya-ebpf)
│   └── src/
│       ├── main.rs           # execve/openat → PerfEventArray
│       ├── network.rs        # connect/accept/sendto/recvfrom + sockaddr
│       └── fs.rs             # mkdir/unlink/kill/chmod tracepoints
├── frankentui/               # FrankenTUI — self-hosted terminal UI kernel
│   └── ftui-*/               # ftui-core, ftui-render, ftui-runtime, ... (crates)
├── c-ebpf/                   # Standalone C eBPF programs (ebpf.c, process_monitor.bpf.c)
├── go-agent/                 # Go CLI agent (HTTP/WebSocket client)
├── go-web/                   # Go web frontend (main.go)
├── c-api/                    # C header for libtalus
├── talus-tauri/            # Tauri desktop dashboard (React + Rust)
├── k8s/                      # Kubernetes manifests (DaemonSet, Service)
├── proto/                    # Protobuf schema (gRPC)
├── fuzz/                     # Fuzzing harness
├── demos/                    # Recorded demo tape
├── docs/                     # Landing page, reports (TEST_REPORT, VERIFICATION-EBPF, NEW_FEATURES), licensing docs
├── screenshots/              # TUI screenshots
├── build.sh                  # Build script (--web / --all / --check)
├── install.sh                # Distro-aware installer
├── install-gui.sh            # Graphical (zenity) installer
└── Cargo.toml                # Workspace definition

Tested Live on Linux

Talus has been deployed and tested on real hardware running Linux:

# Verify eBPF tracepoints exist
ls /sys/kernel/tracing/events/syscalls/sys_enter_execve/id

# Load and attach eBPF programs
sudo process-monitor --diagnose

# Watch live events in another terminal
ls -la /tmp
# → Talus shows: 14:09:16 OPEN [29645] bash → /tmp

# Test auto-kill
sudo process-monitor --alert-threshold 3 --auto-kill
# In another terminal: for i in $(seq 1 100); do touch /tmp/f$i; done
# → Talus kills the process after 3 opens in 1s

# Verify with bpftool
bpftool prog list      # shows attached tracepoints
bpftool map dump name events  # shows perf event array

Docker / Kubernetes

# Docker
docker build -t talus .
docker run --privileged -v /sys/kernel/btf:/sys/kernel/btf talus

# Kubernetes (DaemonSet on every node)
kubectl apply -f k8s/

Enterprise Maturity

Talus follows a 20-level enterprise maturity model — from open-source prototype to Fortune 500 ready.

LevelAreaStatus
L0Open Source Prototype
L1Supply Chain Security (cargo-deny, SBOM, gitleaks)
L2Build Provenance (SLSA, cosign, attestation)
L3Security Hardening (seccomp, caps, Landlock, audit)
L4Quality Gates (78 tests, clippy clean)
L5Agent Sandbox (seccomp-BPF, capability drop, Landlock)
L6Signed Audit Log (hash chain, SOC2 compliance)
L7Web Security (TLS, API auth, restricted CORS)
L8–L20Observability → Compliance → Enterprise🔜

📄 Full Enterprise Report (PDF) · Maturity Model


Security & Hardening

Talus is a security agent — it must be secure itself. Enterprise edition includes:

Agent Self-Sandboxing (sandbox.rs)

LayerMechanismWhat it does
Capability droppingprctl(PR_CAPBSET_DROP)Drops from root to 3 caps: CAP_BPF, CAP_PERFMON, CAP_NET_ADMIN
seccomp-BPFWhitelist syscall filterAllows only ~75 syscalls needed for event loop; blocks ptrace, bpf, execve, fork, open_by_handle_at, mount, init_module
Landlock LSMKernel ≥5.13 filesystem restrictionsRead-only access to /sys/kernel/debug, /proc, ~/.config/talus, BPF object path only
[sandbox] dropped 37 capabilities, kept: CAP_BPF, CAP_PERFMON, CAP_NET_ADMIN
[sandbox] seccomp-BPF filter installed (75 allowed syscalls)
[sandbox] Landlock FS restrictions applied
[sandbox] hardening applied ✓

Signed Audit Log (audit.rs)

Every license operation is recorded in a tamper-proof hash chain (SOC2/ISO27001 compliance):

Each entry = SHA-256(HMAC(machine_key, prev_hash + timestamp + event + license_id + detail))
EventWhen
ACTIVATEDLicense key activated
DEACTIVATEDLicense deactivated
EXPIREDLicense expired
MISMATCHMachine fingerprint mismatch
TRANSFERLicense transferred to another machine
talus license audit-log          # Show last 20 entries
talus license verify-audit       # Verify hash chain integrity

License Security (license.rs)

FeatureImplementation
Ed25519 signingLicense keys signed with Ed25519 keypair
Machine fingerprintLicense bound to hardware (CPU, motherboard, MAC)
Encryption at restXOR encryption with machine-derived key
File permissions0600 on license.dat, 0700 on config dir
Rate limitingMax 5 activation attempts per 5 minutes
Binary integrityXOR checksum detects key substitution
Config HMACHMAC on license.dat + .trial.dat detects tampering
Offline grace30-day grace period without internet
Downgrade protectionCannot downgrade from Enterprise
Server-side seat enforcementmax_seats checked in D1 at activation (license-server/)
Signed-key cache bindingLocal cache re-verified against the Ed25519 signature on every load — edited tier/expiry is rejected
Trial integrity tagSHA-256 tag ties the trial marker to binary + machine — copied/edited trial files are voided
Public-key-only serverThe activation worker cannot forge licenses even if fully compromised

Web Dashboard Security (web.rs)

FeatureImplementation
TLS (rustls)Self-signed cert, HTTPS only
API token authAuthorization: Bearer <token> or X-API-Token: <token>
Restricted CORSOnly https://localhost allowed
Auth on all endpointsTALUS_WEB_AUTH=1 env var enables auth on GET/POST

Watchdog (watchdog.rs)

Fail-closed heartbeat monitoring — if the eBPF pipeline crashes:

[watchdog] ⚠ ALARM: no heartbeat for 10s — eBPF pipeline may be unresponsive
[watchdog] ✓ heartbeat restored — pipeline recovered

Webhook alarm via TALUS_ALARM_WEBHOOK env var.


Licensing & Pricing

Talus is available in two editions:

FeatureCommunity (Free)Enterprise
eBPF process monitoring
TUI dashboard (7 panels)
JSON / plain text output
Ransomware detection alerts
Auto-kill (EDR response)
Web dashboard & REST API
WebSocket live stream
Prometheus /metrics
Kafka event streaming
ClickHouse analytics
MemGraph process graphs
C FFI library
Agent sandboxing (seccomp/caps/Landlock)
Signed audit log (hash chain)
TLS + API auth on dashboard
Priority support

Quick Start

# Community (free, no license needed)
sudo talus monitor

# Enterprise (requires license)
talus license activate <YOUR-LICENSE-KEY>
sudo talus monitor --auto-kill

License Management

talus license show              # View license status
talus license activate <KEY>    # Activate online
talus license deactivate        # Deactivate
talus license export-json       # Export as JSON
talus license backup license.json       # Backup
talus license restore license.json      # Restore
talus license transfer          # Transfer to another machine
talus license audit-log          # View audit trail
talus license verify             # Verify validity

30-Day Enterprise Trial

Talus includes a 30-day Enterprise trial on first run. No activation required — all Enterprise features are available during the trial period.

Getting a License

Enterprise licenses are sold directly by the author:

  • 🛒 Purchase via the payment link shared by the author (Gumroad / Lemon Squeezy / bank transfer) — see the pricing structure in docs/pricing-tiers.md (amounts are set per sale, not in the repo)
  • 📧 Contact: @BartoszOsiej — volume & team agreements (10+ seats)
  • 📜 Terms: docs/EULA.txt

How Licensing Works

talus-keygen issue ──► signed key (Ed25519) ──► customer
                                                  │
                                        talus license activate <KEY>
                                                  ▼
              Cloudflare Worker + Turso (primary, free tier) ── signature
              check, expiry, revocation, seat limits ──► activation token
              (automatic failover: talus-license-failover worker —
               same shared storage, transparent for the client)

Buying from a store (Polar / Gumroad / Lemon Squeezy)? You don't need a special Talus key at all — paste the license key you received from the store straight into talus license activate <KEY>. The activation server recognizes store purchases and translates the store key into your Talus license automatically (signing happens offline; store keys are stored only as hashes).

  • Keys are Ed25519-signed; the binary embeds only the public key
  • The activation server (license-server/) holds the public key only — the signing key never leaves the owner's machine
  • Automatic failover: activation, deactivation and store-key redemption try the primary server first, then the failover worker — both serve the same shared storage (Turso), so seats and revocations are identical everywhere. Override with TALUS_LICENSE_SERVER (primary) and TALUS_LICENSE_SERVER_FAILOVER (comma-separated endpoints; set it to an empty string to disable failover)
  • Seats are enforced server-side; moving a machine is deactivateactivate
  • Revoked or expired keys are refused at activation; local cache is re-verified against the signed key on every load

Customer walkthrough: docs/customer-activation-guide.md

Admin Panel (owner only)

The license server ships with a browser admin panel — the worker serves it at /admin. Login is two-factor: auth code (ADMIN_TOKEN) + a 6-digit TOTP code from Google Authenticator. Sessions last 12 h; a used TOTP code can never be replayed. There is also a local-only variant in admin-panel/ (token never leaves your machine). Day-to-day ops:

scripts/issue-license.sh        # issue a signed license key
scripts/revoke-license.sh       # block a key everywhere
scripts/list-activations.sh     # who activated where
scripts/health-check.sh         # is the server up
../scripts/setup-totp.sh        # one-time: enable TOTP login for /admin

Source Code License

MIT (see LICENSE for details)


📺 Demo

talus Demo

Deep Dives

Extended dossiers (architecture, verification, benchmarks, error codex) ship in this repo:

Contributors

BartoszOsiej/talus-process-monitor

eBPF ransomware tracker — kernel execve/openat tracing, per-CPU perf buffers, frankentui TUI, sliding-window alerts

Rust

0

200 commits

updated Sep 18, 2026

See the code
aya
ebpf
ebpf-tracing
kernel
linux
process-monitor
ransomware
ratatui
rust
security
tui

See what people are saying (1)

SourceMessageScoreDate

Talus: eBPF ransomware detector for Linux (Rust)

1

Sep 18, 2026

README

🛡️ Talus — Endpoint Security Agent

License Rust eBPF Go Docker Enterprise

eBPF-based endpoint security agent for Linux — detect ransomware behaviour, respond at the kernel edge.

Talus is not a passive monitor. It is a detect-and-respond agent that hooks syscalls at the kernel level via eBPF tracepoints, scores per-process file-open rates in real-time, and terminates offending processes the instant a heuristic verdict fires. It processes ~500k events/sec through per-CPU perf buffers with zero-copy handoff to a userspace detection engine built in Rust.

🇵🇱 Wersja polska · Architecture · 📄 Enterprise Report (PDF) · Enterprise Maturity


Table of Contents


What It Does

CapabilityHow
Kernel-level tracingeBPF tracepoints on execve, openat, connect, accept, sendto, recvfrom, mkdir, unlinkat, kill, fchmodat
Ransomware detection1-second sliding window per PID; alerts when file-open rate exceeds configurable threshold
Automated response--auto-kill sends SIGKILL to the offending process on alert verdict
Network egress trackingParses sockaddr in-kernel — captures IPv4/IPv6/Unix addresses on connect/accept/send/recv
Event pipelineKernel perf buffer → zero-copy ring → detection engine → TUI / JSON / WebSocket / Prometheus
Process treeResolves PPID from /proc, builds hierarchical view with per-process alert counts
File rankingMost-opened files with Shannon entropy scoring (detects encrypted/randomised filenames)
Single binaryFull LTO, panic = "abort", symbol-stripped — 1.7 MB TUI, 2.5 MB with web
Kafka streamingEvents → Kafka topics with lz4 compression, partitioned by PID
ClickHouse storageBatch inserts into MergeTree for analytics retention
MemGraph graphProcess trees + file access as a graph (Cypher queries)

Architecture / Data Flow

Talus follows a pipeline architecture — kernel ingestion → userspace detection → operator response:

┌─────────────────────────────────────────────────────────────────────────┐
│                      KERNEL SPACE (eBPF programs)                       │
│                                                                         │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐                  │
│  │ sys_enter_   │  │ sys_enter_   │  │ sys_enter_   │                  │
│  │ execve       │  │ openat       │  │ connect      │ ... 10 total     │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘                  │
│         │                 │                 │                            │
│         ▼                 ▼                 ▼                            │
│  ┌─────────────────────────────────────────────────────┐               │
│  │  ProcessEvent { pid, uid, comm, filename, argv }    │               │
│  │  PerfEventArray (per-CPU, zero-copy)                │               │
│  └──────────────────────────┬──────────────────────────┘               │
└─────────────────────────────┼───────────────────────────────────────────┘
                              │
┌─────────────────────────────┼───────────────────────────────────────────┐
│                      USERSPACE (Rust)                                   │
│                              │                                           │
│  ┌───────────────────────────▼──────────────────────────┐              │
│  │  Reader thread — reads perf buffers per CPU          │              │
│  │  MPSC channel → Monitor event loop                   │              │
│  └───────────────────────────┬──────────────────────────┘              │
│                              │                                           │
│  ┌───────────────────────────▼──────────────────────────┐              │
│  │  DETECTION ENGINE                                    │              │
│  │  • Sliding window per PID (1s rolling)               │              │
│  │  • File-extension frequency tracking                 │              │
│  │  • Shannon entropy scoring on filenames              │              │
│  │  • Per-process stats (opens, execs, alerts, PPID)    │              │
│  └───────────┬─────────────────────────┬───────────────┘              │
│              │ VERDICT                  │                              │
│              ▼                          ▼                               │
│  ┌─────────────────────┐  ┌────────────────────────────┐              │
│  │  RESPONSE           │  │  OUTPUT                     │              │
│  │  kill(pid, SIGKILL) │  │  TUI (7 panels)            │              │
│  │  cgroup freeze      │  │  JSON / WebSocket           │              │
│  │  (extensible)       │  │  Prometheus /metrics        │              │
│  └─────────────────────┘  │  REST API                   │              │
│                           └────────────────────────────┘              │
└─────────────────────────────────────────────────────────────────────────┘

Pipeline stages

StageComponentThroughputMechanism
1. IngesteBPF tracepoints~500k events/sbpf_perf_event_output per-CPU
2. TransportPerfEventArrayzero-copyPerfEventArrayBuffer::read_events
3. DetectSliding window enginereal-time1s rolling window, configurable threshold
4. Respondkill(2) / cgroup< 1ms latencySIGKILL on heuristic verdict
5. PersistTUI / JSON / WebSocketlive streamREST API + Prometheus for retention

This maps directly to a Kafka-style event pipeline: kernel perf buffer = topic, reader thread = consumer, detection engine = stream processor, TUI/API = sink.


Storage & Pipeline

Talus supports pluggable storage backends for event persistence and downstream analytics:

# Stream events to Kafka
sudo talus --kafka-brokers localhost:9092 --kafka-topic talus-events

# Store events in ClickHouse for analytics
sudo talus --clickhouse http://localhost:8123

# Build process relationship graph in MemGraph
sudo talus --memgraph http://localhost:7474

# Combine all backends
sudo talus \
  --kafka-brokers localhost:9092 --kafka-topic talus-events \
  --clickhouse http://localhost:8123 \
  --memgraph http://localhost:7474

Kafka

Events are sent to a configurable topic with lz4 compression and partitioned by PID for ordering per-process:

ConfigDefaultDescription
--kafka-brokersBroker address (e.g. localhost:9092)
--kafka-topictalus-eventsTopic name

ClickHouse

Events are batch-inserted into a MergeTree table partitioned by date:

CREATE TABLE talus.events (
    ts DateTime64(3),
    kind LowCardinality(String),
    pid UInt32, uid UInt32,
    comm LowCardinality(String),
    file Nullable(String),
    extension LowCardinality(Nullable(String))
) ENGINE = MergeTree()
PARTITION BY toYYYYMMDD(ts)
ORDER BY (ts, kind, pid)

MemGraph

Process trees and file access patterns are stored as a graph:

// Find all processes that opened .enc files
MATCH (p:Process)-[r:OPENED]->(f:File)
WHERE f.path ENDS WITH '.enc'
RETURN p.pid, p.comm, f.path, r.count
ORDER BY r.count DESC

// Find exfiltration candidates (file opens + external network)
MATCH (p:Process)-[:OPENED]->(f:File), (p)-[:CONNECTED_TO]->(n:NetworkTarget)
WHERE NOT n.addr STARTS WITH '10.'
RETURN p.pid, p.comm, collect(f.path), collect(n.addr)

Network Visibility

Talus traces network syscalls at the kernel level — not just file operations. This provides full egress visibility for detecting data exfiltration, C2 communication, and lateral movement.

SyscallEvent TypeWhat's CapturedHow
connectConnectRemote IPv4/IPv6/Unix address + portsockaddr parsed via bpf_probe_read_user
acceptAcceptRemote address of incoming connectionSame mechanism
sendtoSendToDestination addresssockaddr at arg index 4
recvfromRecvFromSource addresssockaddr at arg index 4

In-kernel sockaddr parsing

The eBPF program reads raw sockaddr structures byte-by-byte from userspace:

// Read AF_INET address from sockaddr_in
bpf_probe_read_user(&family, 2, sockaddr_ptr);      // sa_family
bpf_probe_read_user(&port_be, 2, ptr + 2);          // sin_port (big-endian)
bpf_probe_read_user(&a0, 1, ptr + 4);               // sin_addr[0]
// ... formats as "192.168.1.1:443"

This runs in the kernel with zero userspace round-trips — addresses are resolved before the event even reaches userspace.

Example: detecting exfiltration

{"ts":"14:09:17.100","type":"event","kind":"Connect","pid":1234,"comm":"curl","file":"93.184.216.34:443"}
{"ts":"14:09:17.205","type":"event","kind":"SendTo","pid":1234,"comm":"curl","file":"93.184.216.34:443"}
{"ts":"14:09:17.502","type":"event","kind":"Open","pid":1234,"comm":"curl","file":"/home/user/Documents/backup.tar.gz"}

Detection & Response

Detection: sliding-window heuristic

Each PID maintains a 1-second rolling window of openat events. When the count hits the threshold (default: 50 opens/s), a verdict fires:

PID 2126 ("Cache2 I/O") opened 50 files in 1.0s  →  VERDICT: SUSPICIOUS

The threshold is configurable at runtime via the API or CLI:

# Lower threshold for high-security environments
sudo process-monitor --alert-threshold 20

# Filter by extension (e.g. detect .enc/.pdf mass opens)
sudo process-monitor --filter-ext enc

Response: automated termination

With --auto-kill, Talus sends SIGKILL to the offending process immediately on verdict:

# EDR mode: detect + respond
sudo process-monitor --alert-threshold 50 --auto-kill
// The response layer — ~30 lines of Rust
fn kill_process(pid: u32) -> bool {
    let rc = unsafe { libc::kill(pid as i32, libc::SIGKILL) };
    rc == 0
}

// Fired inside the detection engine on verdict:
if self.auto_kill {
    let result = kill_process(ev.pid);
    outputs.push(Output::Action(ResponseAction {
        ts: ev.ts.clone(),
        pid: ev.pid,
        action: format!("SIGKILL sent to PID {}", ev.pid),
        success: result,
    }));
}

This is extensible — the ResponseAction interface supports kill, cgroup freeze, network quarantine, or any custom response.

Detection: MeMLP neural engine (--memlp)

Beyond the heuristic window, Talus embeds MeMLP — a Modular embedded Multi-Layer Perceptron model built from scratch (no ndarray, no tch, no ONNX — just a few KB of dependency-free Rust). The same architecture powers the neural terrain generator in the NV2 voxel engine, re-targeted here at process behaviour.

ModuleShapeTask
ransomware10 → 24 → 16 → 3benign / suspicious / ransomware
lateral10 → 12 → 2lateral-movement suspect
persistence10 → 12 → 2autostart-persistence suspect

Every module consumes the same 10-feature behavioural embedding per PID (open rate, exec+network rate, filename Shannon entropy, ransomware-marker extension fraction, extension diversity, fs-mutation rate, destructive fraction, distinct-file spread, autostart-path hits, network fraction). Windows decay with a 1-second half-life, mirroring the heuristic window.

The engine trains online: every alert performs a backpropagation step (cross-entropy loss, gradient clipping, bounded updates) against transparent heuristic teachers, then scores the process. Checkpoints persist as JSON and reload on the next run, so the model keeps learning across restarts.

# Enable the neural engine (checkpoint auto-saves every 30s)
sudo process-monitor --memlp

# Explicit checkpoint location (loaded on start, saved on shutdown + autosave)
sudo process-monitor --memlp --memlp-checkpoint /var/lib/talus/memlp.json

Alerts carry the neural verdict in every output channel:

12:00:03 SUSPICIOUS [4132] encrypt.sh opened 50 files in 1s!  [MeMLP R:ransomware 91% L:normal 99% P:suspect 74%]
{"type":"alert","pid":4132,"comm":"encrypt.sh","opens_in_1s":50,
 "memlp":{"ransomware":{"module":"ransomware","class":2,"label":"ransomware","confidence":0.91}, ...}}

Requirements

RequirementNotes
Linux kernel 5.8+eBPF + tracepoint support
root (CAP_BPF / CAP_SYS_ADMIN)Required to load eBPF programs
Rust nightly + rust-srcBuilds eBPF with -Z build-std
bpf-linker, clangeBPF toolchain
BTF (/sys/kernel/btf/vmlinux)Recommended for CO-RE

Quick Start

# Distro-aware installer
./install.sh --system    # System-wide to /usr/local
./install.sh             # User-local to ~/.local

# Or build manually
./build.sh

# Run in EDR mode (detect + auto-respond)
sudo target/release/process-monitor --auto-kill

# Run in monitor-only mode (no auto-kill)
sudo target/release/process-monitor

Usage

# EDR mode — detect and auto-kill
sudo process-monitor --auto-kill

# Lower threshold for stricter detection
sudo process-monitor --auto-kill --alert-threshold 20

# Monitor only (no kill)
sudo process-monitor

# Filter by extension
sudo process-monitor --filter-ext pdf

# JSON output for external pipelines
sudo process-monitor --json | jq .

# Plain text log
sudo process-monitor --plain

# Web dashboard (requires --features web build)
sudo process-monitor --web 0.0.0.0:8080

# MeMLP neural detection engine (online training + JSON checkpoints)
sudo process-monitor --memlp
sudo process-monitor --memlp --memlp-checkpoint /var/lib/talus/memlp.json

# Self-diagnostic
sudo process-monitor --diagnose

CLI Reference

FlagDefaultDescription
-b, --bpf <PATH>autoPath to compiled eBPF object
--alert-threshold <N>50Alert when N+ files opened within 1s
--auto-killoffSend SIGKILL to processes that trigger alerts
--filter-ext <EXT>allFilter by file extension
--top-files <N>8Top files in TUI
--jsonoffNewline-delimited JSON output
--plainoffPlain text log
--memlpoffEnable the MeMLP neural detection engine
--memlp-checkpoint <PATH>~/.local/share/talus/memlp.jsonMeMLP checkpoint (load on start, autosave every 30s)
--diagnoseoff5-second self-diagnostic
--web <ADDR>offStart web server (requires --features web)

Build Variants

# TUI-only (default, 1.7MB)
./build.sh

# Web-featured (2.5MB) — REST API, WebSocket, Prometheus
./build.sh --web

# Both variants
./build.sh --all
VariantSizeDependencies
process-monitor-tui1.7MBaya, frankentui (ftui), chrono, crossterm
process-monitor-web2.5MB+axum, tokio, tower-http, prometheus-client

TUI Controls

KeyAction
q / EscQuit
pPause / resume
cClear all panels
/ / k/jScroll
TabNext panel
1-7Jump to panel
/Search mode
? / hHelp overlay

TUI Panels (7)

#PanelDescription
1EVENTSLive event log with search/filter
2PROCESSESHierarchical process tree with alert counts
3NETWORKReal-time connections (connect/accept/send/recv + IP:port)
4TOP FILESMost-opened files with Shannon entropy
5FILE TYPESExtension frequency with coloured bars
6ALERTSAlert history + response actions
7HEATMAPSyscall frequency visualisation

Web Dashboard

Optional build with --features web:

cargo build --release --features web
sudo process-monitor --web 0.0.0.0:8080
EndpointMethodDescription
/GETDashboard UI
/wsWebSocketLive event stream
/api/v1/statsGETGlobal statistics
/api/v1/processesGETTracked processes
/api/v1/filesGETTop opened files
/api/v1/extensionsGETExtension frequency
/api/v1/thresholdPOSTUpdate threshold at runtime
/metricsGETPrometheus metrics

Operator View (TUI + Web + Desktop)

Talus provides three operator interfaces:

  • TUI — 7-panel terminal interface for local investigation. Cyberpunk aesthetic, process trees, heatmaps, sparklines. Runs anywhere, no browser needed.
  • Web Dashboard — browser-based UI with WebSocket live stream, REST API for integration, and Prometheus metrics for Grafana/monitoring stacks.
  • Desktop App (Tauri + React) — native desktop GUI built with Tauri 2 + React 19 + Recharts. Connects to the talus backend via WebSocket and REST API. See talus-tauri/ for source.

All three consume the same detection engine — the agent is headless-capable and can run as a background daemon with JSON output piped to external SIEM/storage.


Project Structure

talus-process-monitor/
├── process-monitor/          # Userspace: detection engine + TUI + web + FFI
│   └── src/
│       ├── main.rs           # CLI, mode selection, signal handling
│       ├── monitor.rs        # eBPF loading, perf reader, detection, response
│       ├── tui.rs            # 7-panel frankentui (ftui) cyberpunk interface
│       ├── web.rs            # axum web server (--features web)
│       ├── ffi.rs            # C FFI bindings (libtalus)
│       └── storage/          # Kafka / ClickHouse / MemGraph backends
├── process-monitor-ebpf/     # Kernel side (#![no_std], aya-ebpf)
│   └── src/
│       ├── main.rs           # execve/openat → PerfEventArray
│       ├── network.rs        # connect/accept/sendto/recvfrom + sockaddr
│       └── fs.rs             # mkdir/unlink/kill/chmod tracepoints
├── frankentui/               # FrankenTUI — self-hosted terminal UI kernel
│   └── ftui-*/               # ftui-core, ftui-render, ftui-runtime, ... (crates)
├── c-ebpf/                   # Standalone C eBPF programs (ebpf.c, process_monitor.bpf.c)
├── go-agent/                 # Go CLI agent (HTTP/WebSocket client)
├── go-web/                   # Go web frontend (main.go)
├── c-api/                    # C header for libtalus
├── talus-tauri/            # Tauri desktop dashboard (React + Rust)
├── k8s/                      # Kubernetes manifests (DaemonSet, Service)
├── proto/                    # Protobuf schema (gRPC)
├── fuzz/                     # Fuzzing harness
├── demos/                    # Recorded demo tape
├── docs/                     # Landing page, reports (TEST_REPORT, VERIFICATION-EBPF, NEW_FEATURES), licensing docs
├── screenshots/              # TUI screenshots
├── build.sh                  # Build script (--web / --all / --check)
├── install.sh                # Distro-aware installer
├── install-gui.sh            # Graphical (zenity) installer
└── Cargo.toml                # Workspace definition

Tested Live on Linux

Talus has been deployed and tested on real hardware running Linux:

# Verify eBPF tracepoints exist
ls /sys/kernel/tracing/events/syscalls/sys_enter_execve/id

# Load and attach eBPF programs
sudo process-monitor --diagnose

# Watch live events in another terminal
ls -la /tmp
# → Talus shows: 14:09:16 OPEN [29645] bash → /tmp

# Test auto-kill
sudo process-monitor --alert-threshold 3 --auto-kill
# In another terminal: for i in $(seq 1 100); do touch /tmp/f$i; done
# → Talus kills the process after 3 opens in 1s

# Verify with bpftool
bpftool prog list      # shows attached tracepoints
bpftool map dump name events  # shows perf event array

Docker / Kubernetes

# Docker
docker build -t talus .
docker run --privileged -v /sys/kernel/btf:/sys/kernel/btf talus

# Kubernetes (DaemonSet on every node)
kubectl apply -f k8s/

Enterprise Maturity

Talus follows a 20-level enterprise maturity model — from open-source prototype to Fortune 500 ready.

LevelAreaStatus
L0Open Source Prototype
L1Supply Chain Security (cargo-deny, SBOM, gitleaks)
L2Build Provenance (SLSA, cosign, attestation)
L3Security Hardening (seccomp, caps, Landlock, audit)
L4Quality Gates (78 tests, clippy clean)
L5Agent Sandbox (seccomp-BPF, capability drop, Landlock)
L6Signed Audit Log (hash chain, SOC2 compliance)
L7Web Security (TLS, API auth, restricted CORS)
L8–L20Observability → Compliance → Enterprise🔜

📄 Full Enterprise Report (PDF) · Maturity Model


Security & Hardening

Talus is a security agent — it must be secure itself. Enterprise edition includes:

Agent Self-Sandboxing (sandbox.rs)

LayerMechanismWhat it does
Capability droppingprctl(PR_CAPBSET_DROP)Drops from root to 3 caps: CAP_BPF, CAP_PERFMON, CAP_NET_ADMIN
seccomp-BPFWhitelist syscall filterAllows only ~75 syscalls needed for event loop; blocks ptrace, bpf, execve, fork, open_by_handle_at, mount, init_module
Landlock LSMKernel ≥5.13 filesystem restrictionsRead-only access to /sys/kernel/debug, /proc, ~/.config/talus, BPF object path only
[sandbox] dropped 37 capabilities, kept: CAP_BPF, CAP_PERFMON, CAP_NET_ADMIN
[sandbox] seccomp-BPF filter installed (75 allowed syscalls)
[sandbox] Landlock FS restrictions applied
[sandbox] hardening applied ✓

Signed Audit Log (audit.rs)

Every license operation is recorded in a tamper-proof hash chain (SOC2/ISO27001 compliance):

Each entry = SHA-256(HMAC(machine_key, prev_hash + timestamp + event + license_id + detail))
EventWhen
ACTIVATEDLicense key activated
DEACTIVATEDLicense deactivated
EXPIREDLicense expired
MISMATCHMachine fingerprint mismatch
TRANSFERLicense transferred to another machine
talus license audit-log          # Show last 20 entries
talus license verify-audit       # Verify hash chain integrity

License Security (license.rs)

FeatureImplementation
Ed25519 signingLicense keys signed with Ed25519 keypair
Machine fingerprintLicense bound to hardware (CPU, motherboard, MAC)
Encryption at restXOR encryption with machine-derived key
File permissions0600 on license.dat, 0700 on config dir
Rate limitingMax 5 activation attempts per 5 minutes
Binary integrityXOR checksum detects key substitution
Config HMACHMAC on license.dat + .trial.dat detects tampering
Offline grace30-day grace period without internet
Downgrade protectionCannot downgrade from Enterprise
Server-side seat enforcementmax_seats checked in D1 at activation (license-server/)
Signed-key cache bindingLocal cache re-verified against the Ed25519 signature on every load — edited tier/expiry is rejected
Trial integrity tagSHA-256 tag ties the trial marker to binary + machine — copied/edited trial files are voided
Public-key-only serverThe activation worker cannot forge licenses even if fully compromised

Web Dashboard Security (web.rs)

FeatureImplementation
TLS (rustls)Self-signed cert, HTTPS only
API token authAuthorization: Bearer <token> or X-API-Token: <token>
Restricted CORSOnly https://localhost allowed
Auth on all endpointsTALUS_WEB_AUTH=1 env var enables auth on GET/POST

Watchdog (watchdog.rs)

Fail-closed heartbeat monitoring — if the eBPF pipeline crashes:

[watchdog] ⚠ ALARM: no heartbeat for 10s — eBPF pipeline may be unresponsive
[watchdog] ✓ heartbeat restored — pipeline recovered

Webhook alarm via TALUS_ALARM_WEBHOOK env var.


Licensing & Pricing

Talus is available in two editions:

FeatureCommunity (Free)Enterprise
eBPF process monitoring
TUI dashboard (7 panels)
JSON / plain text output
Ransomware detection alerts
Auto-kill (EDR response)
Web dashboard & REST API
WebSocket live stream
Prometheus /metrics
Kafka event streaming
ClickHouse analytics
MemGraph process graphs
C FFI library
Agent sandboxing (seccomp/caps/Landlock)
Signed audit log (hash chain)
TLS + API auth on dashboard
Priority support

Quick Start

# Community (free, no license needed)
sudo talus monitor

# Enterprise (requires license)
talus license activate <YOUR-LICENSE-KEY>
sudo talus monitor --auto-kill

License Management

talus license show              # View license status
talus license activate <KEY>    # Activate online
talus license deactivate        # Deactivate
talus license export-json       # Export as JSON
talus license backup license.json       # Backup
talus license restore license.json      # Restore
talus license transfer          # Transfer to another machine
talus license audit-log          # View audit trail
talus license verify             # Verify validity

30-Day Enterprise Trial

Talus includes a 30-day Enterprise trial on first run. No activation required — all Enterprise features are available during the trial period.

Getting a License

Enterprise licenses are sold directly by the author:

  • 🛒 Purchase via the payment link shared by the author (Gumroad / Lemon Squeezy / bank transfer) — see the pricing structure in docs/pricing-tiers.md (amounts are set per sale, not in the repo)
  • 📧 Contact: @BartoszOsiej — volume & team agreements (10+ seats)
  • 📜 Terms: docs/EULA.txt

How Licensing Works

talus-keygen issue ──► signed key (Ed25519) ──► customer
                                                  │
                                        talus license activate <KEY>
                                                  ▼
              Cloudflare Worker + Turso (primary, free tier) ── signature
              check, expiry, revocation, seat limits ──► activation token
              (automatic failover: talus-license-failover worker —
               same shared storage, transparent for the client)

Buying from a store (Polar / Gumroad / Lemon Squeezy)? You don't need a special Talus key at all — paste the license key you received from the store straight into talus license activate <KEY>. The activation server recognizes store purchases and translates the store key into your Talus license automatically (signing happens offline; store keys are stored only as hashes).

  • Keys are Ed25519-signed; the binary embeds only the public key
  • The activation server (license-server/) holds the public key only — the signing key never leaves the owner's machine
  • Automatic failover: activation, deactivation and store-key redemption try the primary server first, then the failover worker — both serve the same shared storage (Turso), so seats and revocations are identical everywhere. Override with TALUS_LICENSE_SERVER (primary) and TALUS_LICENSE_SERVER_FAILOVER (comma-separated endpoints; set it to an empty string to disable failover)
  • Seats are enforced server-side; moving a machine is deactivateactivate
  • Revoked or expired keys are refused at activation; local cache is re-verified against the signed key on every load

Customer walkthrough: docs/customer-activation-guide.md

Admin Panel (owner only)

The license server ships with a browser admin panel — the worker serves it at /admin. Login is two-factor: auth code (ADMIN_TOKEN) + a 6-digit TOTP code from Google Authenticator. Sessions last 12 h; a used TOTP code can never be replayed. There is also a local-only variant in admin-panel/ (token never leaves your machine). Day-to-day ops:

scripts/issue-license.sh        # issue a signed license key
scripts/revoke-license.sh       # block a key everywhere
scripts/list-activations.sh     # who activated where
scripts/health-check.sh         # is the server up
../scripts/setup-totp.sh        # one-time: enable TOTP login for /admin

Source Code License

MIT (see LICENSE for details)


📺 Demo

talus Demo

Deep Dives

Extended dossiers (architecture, verification, benchmarks, error codex) ship in this repo:

Contributors

Languages

Rust

98.9%