git-like server state tracker โ snapshot, diff, and blame your entire server state
Project description
drift ๐
git for your server state. Snapshot, diff, and blame every change to packages, services, ports, users, cron jobs, and kernel parameters โ automatically.
The problem
Something broke on prod at 2am. What changed?
Right now your answer is: grep bash history, check deploy logs, ask in Slack, look at git commits, pray someone ran Ansible. Four different places, all incomplete, all manual.
drift answers it in one command.
$ drift diff HEAD~1
[PACKAGE]
+ postgresql 14.8 โ 15.2
- libssl1.1 1.1.1 (removed)
[SERVICE]
+ postgresql inactive โ active โ
+ postgresql-15 added โ
[PORT]
+ 5432/tcp postgres โ
[USER]
+ deploy uid=1001 shell=/bin/bash โ
What it tracks
| Category | What's captured |
|---|---|
| Packages | apt/dpkg, yum/rpm, pip, snap, npm (global), gem |
| Services | Every systemd unit โ state (active/inactive/failed) + enabled status |
| Open ports | All listening TCP/UDP ports + process name |
| Users | /etc/passwd โ uid, shell, home, group memberships |
| Groups | /etc/group โ gid, members |
| Cron jobs | /etc/crontab, /etc/cron.d/*, all user crontabs |
| Sysctl | All kernel parameters (security-relevant ones flagged critical) |
| Mounts | /proc/mounts (virtual filesystems excluded) |
| Environment | /etc/environment, /etc/profile.d/*.sh |
| Kernel modules | /proc/modules |
Install
pip install drift-tool
# Or from source:
git clone https://github.com/matthewvaishnav/drift
pip install ./drift
Install as systemd daemon (recommended)
sudo drift install
This installs:
- A systemd service that takes a snapshot every hour
- A PAM hook that takes a snapshot on every SSH login/logout
Commands
# Take a snapshot right now
drift snapshot
# Show the commit log (newest first)
drift log
drift log 50
# Show what changed since the last snapshot
drift diff
# Show changes between specific commits
drift diff HEAD~1 # last two snapshots
drift diff abc123 # specific commit vs HEAD
drift diff abc123 def456 # between two commits
# Show verbose diff (full before/after values)
drift diff -v
# Who caused these changes? (correlates with SSH logs)
drift blame # HEAD
drift blame abc123 # specific commit
# Full details of a snapshot
drift show abc123
drift show abc123 --json # raw JSON output
# Search across all snapshots
drift search nginx
drift search "port 4444"
# Current server state summary
drift status
# Storage stats
drift stats
# Manage the background daemon
drift daemon start
drift daemon stop
drift daemon status
# PAM hook setup instructions
drift init-pam
# Install systemd service + PAM hook (requires root)
sudo drift install
How it works
โโโโโโโโโโโโโโโโโโโโโโโ
SSH login โโโโบโ โ
SSH logoutโโโบโ drift daemon โโโโบ take snapshot
Scheduledโโโโโบโ (hourly) โ
drift snapโโโโบโ โ
โโโโโโโโโโโโฌโโโโโโโโโโโ
โ
โโโโโโโโโโโโผโโโโโโโโโโโ
โ Collectors โ
โ packages ยท servicesโ
โ ports ยท users โ
โ cron ยท sysctl โ
โ mounts ยท env โ
โโโโโโโโโโโโฌโโโโโโโโโโโ
โ
โโโโโโโโโโโโผโโโโโโโโโโโ
โ Content-Addressableโ
โ Object Store โโโโบ ~/.drift/objects/ab/cdef1234...
โ (SHA-256, gzip) โ
โโโโโโโโโโโโฌโโโโโโโโโโโ
โ
โโโโโโโโโโโโผโโโโโโโโโโโ
โ Append-Only Log โโโโบ ~/.drift/log (JSONL)
โ (like git commits) โ
โโโโโโโโโโโโโโโโโโโโโโโ
Storage is designed like git:
- Each snapshot is stored once, addressed by its SHA-256 hash
- The log is append-only โ the audit trail cannot be silently altered
- Snapshots are gzip-compressed โ a typical server state is 50โ200 KB
drift blame โ who changed what
$ drift blame abc123
drift blame abc123
Window: 2026-03-19 14:00 โ 2026-03-19 15:32 on app01.prod.example.com
SSH sessions during this window:
โโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโ
โ User โ From โ Action โ Time โ
โโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโค
โ alice โ 10.0.0.42 โ login โ 2026-03-19 14:23 โ
โโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโ
7 changes in this commit:
+ [package] postgresql 15.2
+ [service] postgresql โ
+ [port] 5432/tcp โ
+ [user] deploy โ
...
Configuration
| Environment variable | Default | Description |
|---|---|---|
DRIFT_DIR |
~/.drift |
Storage directory |
DRIFT_INTERVAL |
3600 |
Snapshot interval in seconds |
DRIFT_EXCLUDE_COLLECTORS |
`` | Comma-separated collectors to skip |
DRIFT_SLACK_WEBHOOK |
`` | Slack webhook for critical change alerts |
DRIFT_LOG_FILE |
`` | Log file for the daemon |
DRIFT_DEBUG |
`` | Set to 1 for traceback on errors |
Why not X?
| Tool | Why it's not drift |
|---|---|
| Tripwire / AIDE | File integrity only. No packages, services, users, or ports. No history. |
| driftctl | Terraform-managed cloud resources only. Zero OS awareness. |
| osquery | Shows current state. No history, no diff, no blame. |
| Ansible facts | Point-in-time snapshot. No daemon, no history, no diff. |
drift is the only tool that does git-style history for full server state.
Run tests
pip install pytest
python -m pytest tests/ -v
60 tests. All green.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file drift_tracker-0.1.1.tar.gz.
File metadata
- Download URL: drift_tracker-0.1.1.tar.gz
- Upload date:
- Size: 51.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a56aa9d428e09988f5cf8f02759a58bce4c9714d46d46119e569e5d3b49269f
|
|
| MD5 |
ec772f0c6712bf28cc5ebde6edc70f5e
|
|
| BLAKE2b-256 |
d5172f8f75b049324f71e1b9d994027b82aa1d9f77860849d839370046be6d5d
|
File details
Details for the file drift_tracker-0.1.1-py3-none-any.whl.
File metadata
- Download URL: drift_tracker-0.1.1-py3-none-any.whl
- Upload date:
- Size: 54.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
731a8812ef7c7d658f1bdd4c7ef0d295d6337cc6da89262eca9b3956e47dd95f
|
|
| MD5 |
a2d3ec51c9d4cf5c6b74952cd0c1b2e5
|
|
| BLAKE2b-256 |
61f1180cccb0711413012d8f23bc4d849bac73635649daca161add28b1b0219a
|