Skip to main content

infradrift

CI PyPI version License: MIT

Detect infrastructure drift between a known-good baseline and the current state of any Linux server — packages, listening ports, user accounts, privileged groups, cron jobs and systemd services.

Take a snapshot when the server is in a good state. Run check any time — after a deploy, from cron, or during an incident — to see exactly what changed. No agent, no daemon, no dependencies on the server beyond Python.

infradrift demo: drift report with new port, new user and suspicious cron job


📄 Example

  ╔═══════════════════════════════╗
  ║  infradrift  ·  drift report  ║
  ╚═══════════════════════════════╝

  Baseline   2026-05-10T09:00:00+02:00  (prod-01)  as root
  Current    2026-05-12T14:22:18+02:00  (prod-01)  as root


  ── Ports ─────────────────────────────────
  ⛔ +  4444/tcp on all interfaces  (nc) — new listening port
  ⛔ ~  6379/tcp on all interfaces  (redis-server) — now listening on a new address

  ── Users ─────────────────────────────────
  ⛔ ~  backup — account changed  shell /usr/sbin/nologin → /bin/bash
  ⛔ +  deploy — new user  uid=1005 shell=/bin/bash

  ── Privileged Groups ─────────────────────
  ⛔ +  deploy added to privileged group sudo

  ── Cron Jobs ─────────────────────────────
  ⚠  +  New cron job: @reboot  /tmp/.cache/update.sh  crontab:www-data

  ── Services ──────────────────────────────
  ⚠  ~  nginx  active → failed

  ── Packages ──────────────────────────────
  · ~  [apt] openssl upgraded  3.0.13-0ubuntu3 → 3.0.13-0ubuntu3.1

  ──────────────────────────────────────────
  8 changes detected  (5 critical, 2 warnings, 1 info)

✨ What it detects

Category What's tracked
Packages dpkg (Debian/Ubuntu), rpm (RHEL/Fedora/SUSE), pacman (Arch), pip — installed, removed, upgraded, downgraded
Ports Listening TCP and bound UDP sockets with their bind address — a service moving from 127.0.0.1 to 0.0.0.0 is flagged
Users /etc/passwd accounts — added, removed, uid/gid/shell/home changes
Privileged groups Membership of sudo, wheel, admin, docker, lxd, libvirt, adm, disk, shadow, root
Cron jobs User crontabs, /etc/crontab, /etc/cron.d/, /etc/cron.{hourly,daily,weekly,monthly}/, including @reboot entries
Services systemd unit state (active / inactive / failed) and boot enablement (enabled / disabled / masked)

Severity levels

Severity Examples
⛔ CRITICAL New listening port, port exposed on a new address, new user, uid/shell change, user added to a privileged group
⚠️ WARNING Service state or enablement change, new enabled service, cron job added/removed, package removed or downgraded
ℹ️ INFO Package installed or upgraded, new high UDP port (ephemeral range — usually a client socket)

📥 Installation

pip install infradrift

Run it as root for complete results: other users' crontabs and the process names of every socket are only visible to root. infradrift warns you when it runs unprivileged.


🛠 Usage

1 — Take a baseline snapshot

sudo infradrift snapshot

Saved to /var/lib/infradrift/baseline.json when run as root, or ~/.config/infradrift/baseline.json otherwise. The file is created with 0600 permissions: it lists users, ports and cron commands.

sudo infradrift snapshot --output /opt/baselines/prod-$(date +%F).json

2 — Check for drift

sudo infradrift check                                   # terminal report
sudo infradrift check --format json | jq .summary       # JSON on stdout, progress on stderr
sudo infradrift check -f markdown -o drift-report.md    # Markdown file
sudo infradrift check --baseline /opt/baselines/prod-2026-05-12.json --fail-on critical

3 — Diff any two snapshots

infradrift diff before-deploy.json after-deploy.json
infradrift diff web-01.json web-02.json --format markdown   # compare two servers

🔁 Use in cron / CI

Exit code Meaning
0 No drift at or above --fail-on
1 Drift detected
2 Error (missing or unreadable baseline)
# Every hour: keep a Markdown report only when something critical changed
0 * * * * root infradrift check --fail-on critical -o /var/log/infradrift/last.md || cp /var/log/infradrift/last.md /var/log/infradrift/alert-$(date +\%F-\%H).md

📋 Options

infradrift snapshot

Option Description
-o, --output FILE Where to save the baseline

infradrift check / infradrift diff BASELINE CURRENT

Option Description
-b, --baseline FILE (check) Baseline to compare against
-f, --format terminal (default), json or markdown
-o, --output FILE Write the report to a file (JSON or Markdown)
--fail-on LEVEL info (default: any change), warning, critical or never

🧪 Development

pip install -e ".[dev]"
ruff check .
pytest

See CHANGELOG.md for release notes.


📝 License

MIT — see LICENSE.

🌐 Connect

GitHub

Metadata

Release files for infradrift 1.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for infradrift 1.1.1
File Size Uploaded
infradrift-1.1.1.tar.gz 23.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for infradrift 1.1.1
File Interpreter ABI Platform
infradrift-1.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 42.1 kB

Release files / infradrift-1.1.1.tar.gz

Download URL infradrift-1.1.1.tar.gz
Size 23.0 kB
Tags Source
SHA-256 checksum
How to use checksums
282170c402ecb38a342bc95febaa6309a46464d2c206fc0e07c429f0773c06fe
BLAKE2b-256 checksum
How to use checksums
cad6beb3d944c1e5b04dcce52307588381610a579ede1f09ad278d3854fd37e6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / infradrift-1.1.1-py3-none-any.whl

Download URL infradrift-1.1.1-py3-none-any.whl
Size 19.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a089389e26ed82e121e92831cc94d266e3bcbed08cc6a0739a66a33d6d8ecad7
BLAKE2b-256 checksum
How to use checksums
a196318640e1f5e6536cd061ca06f9affccb97158a83bfa91b4d7bbf198e652f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

1.1.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page