Rule sets become their own project
A DSL, a tuning pass, an exception file, and a second exception file. Every new host is another chance for the policy to mean something different.
driftkeep watches the files, daemons, ports, packages, local accounts, and runtime security posture that matter on a Linux host. It compares them to the baseline you explicitly accepted — and shows you only what changed.
Rules multiply. Upgrades look like attacks. Per-host scripts drift apart. The result is a queue nobody trusts — and the one change that matters gets lost in it.
A DSL, a tuning pass, an exception file, and a second exception file. Every new host is another chance for the policy to mean something different.
A binary hash changes on every normal upgrade. Without package context, the tool either pages you constantly or you turn the alert off.
Per-host scripts, ad-hoc baselines, and no shared view. You cannot tell whether a host is different because it should be, or because nobody looked.
Everything in driftkeep is a diff against a baseline the operator explicitly accepted. Events add timing and attribution; a full reconcile scan is the source of truth.
Observe the real host. Auto-accept only what is demonstrably boring: package-owned processes, loopback listeners, ordinary config, stable across cycles.
Risky items stay in the queue. Nothing in /tmp, nothing unowned, nothing critical, nothing high-severity gets accepted silently.
The baseline records the exact state, who accepted it, and how. Every item has provenance, not just a timestamp.
Every cycle compares the full host to the baseline. Restarts, missed inotify events, and overloaded queues cannot hide a change.
rev 12 · 128 hosts current
Pick a surface. Every view is designed to answer one question: is this different from what we approved, and why does it matter?
Security-relevant paths, content hashes, ownership, and package provenance. Exclude the noise at the policy level, not with a pile of host-local exceptions.
› driftkeep diff hub policy RHEL baseline rev 4 · baseline rev 412 · 5 changes HIGH 1 change · 1 area FILE /etc/ssh/sshd_config sha256 336857dd → 5c99f9fb · +2 lines reason: content changed outside package manager MED 2 changes · 2 areas PROC /tmp/.x/payload added PORT tcp:0.0.0.0:4444 added LOW 2 changes · 2 areas PKG openssl.x86_64 3.0.7-2 → 3.0.7-3
driftkeep scores process identity, not just path. A known binary running from a new cgroup, a deleted executable, an unowned process, or a reverse-shell shape can all be different.
Package inventory catches additions, removals, and downgrades. Scheduled integrity checks ask rpm -V or dpkg --verify whether the files still match the package.
Read cached repository metadata for available security updates. Optionally query OSV, the Debian tracker, or Ubuntu OVAL for known vulnerabilities with fix and no-fix status.
5.14.0-427.el9 → 5.14.0-427.28.1.el9_4
RHSA-2026:1234 · CVE-2026-11113.0.7-2 → 3.0.7-3
ALSA-2026:5678 · CVE-2026-2222component not in use
accepted risk · reason recorded · audit entryAssign policies by tag. Roll out revisions. See which hosts applied them, which are stale, and which have an error. The dashboard talks to the hub API; it never needs the admin token.
Every alert carries the item, the signal, the score, the policy, the first-seen time, and the reason. Accept, ignore, or investigate from one place — then keep the audit trail.
Hash changed outside a package transaction. 2 lines added. The package owner still matches.
Deleted inode, spawned from the web service cgroup, listening on a public port.
One binary, one state directory, one SQLite hub. No kernel module, no runtime dependency, no Java, no agent framework.
Everything is a diff against the state you approved. Events add timing; the reconcile scan is authoritative.
Auto-accepts only demonstrably boring items. Never drop-zone executables, fileless processes, or critical paths.
/etc, SSH keys, cron, systemd units, setuid sweeps, and drop-zone executables — hashed where it matters.
Instance identity, cgroups, package owner, reverse-shell shapes, and loopback-to-public changes.
Inventory, version changes, critical-package removal, and scheduled rpm/dpkg verification.
Native security updates and optional vulnerability lookups with fix/no-fix context and accepted risks.
Policies, selectors, revisions, rollout status, TLS bundles, host commands, and audit.
Settle windows, suppression, batching, and delivery retries. No alert for a process that was already gone.
JSON output, stable exit codes, a documented REST API, and an OpenAPI contract.
Install the static binary, run the learning window, and review what driftkeep found. The agent is a single file; the hub is optional.
# RHEL / Rocky / Alma sudo dnf install ./driftkeep-*.rpm # Debian / Ubuntu sudo apt install ./driftkeep_*.deb # write a documented config and start learning sudo driftkeep init sudo driftkeep agent --learning 24h sudo systemctl enable --now driftkeep
driftkeep is pre-1.0. The model and the core are ready; the rough edges are being filed down in public.
No. driftkeep is a visibility tool. It does not block execution and cannot defend against a kernel rootkit. The threat model is explicit about that.
No. It is one static binary with no runtime dependencies. Events are optional; the reconcile scan is the source of truth.
Security-relevant files and config, local users, processes and listening ports, systemd units, installed packages, package file integrity, native security updates, and optional vulnerability feeds.
Only if you enable the optional exposure lookup. The default providers are local on Debian and RPM-family hosts. The hub is self-hosted.
Rules describe what you think the host is. A baseline records what you approved. New hosts start from a real observation, and changes are reviewed against that record instead of a growing pile of exceptions.
AGPL-3.0. The source, docs, and threat model are public.
Approve once. Reconcile everywhere. Know exactly what changed, and why it matters.