Configuration drift is any divergence between the intended state of a host and its actual state. On a stateful VPS — one running a database, mail queue, or persistent application data — drift is dangerous because it accumulates silently. A hand-edited my.cnf, an extra package, a modified sysctl, or a stale cron entry can invalidate your provisioning assumptions and make a rebuild behave differently from the host it replaces. Detecting drift early is cheaper than reconciling it during an incident.
Classify what can drift
- Package state — installed versions and held packages (
apt list --installed,dpkg --get-selections). - File content — conventional config paths, service unit overrides, and drop-ins.
- Kernel and runtime parameters — sysctl values, ulimits, sysfs tunables that reset on reboot.
- Stateful data — schema versions, applied migrations, queue depths.
Baseline with a manifest
The cheapest detector is a content-addressed manifest of the files that matter. Hash them on a known-good host and diff on a schedule:
PATHLIST='/etc/mysql /etc/nginx /etc/php /etc/ssh/sshd_config'
find $PATHLIST -type f -print0 | sort -z | \
xargs -0 sha256sum > /var/lib/baseline/files.sha256
# daily comparison
sha256sum -c /var/lib/baseline/files.sha256 2>&1 | grep -v ': OK'
Capture sysctl and ulimits too, since those live in the kernel and are easy to change interactively without touching disk:
sysctl -a 2>/dev/null | sort > /var/lib/baseline/sysctl.txt
ulimit -a > /var/lib/baseline/ulimit.txt
diff -u /var/lib/baseline/sysctl.txt <(sysctl -a 2>/dev/null | sort)
Turn one-off checks into an alert
A manual diff is only useful if someone runs it. Wrap the check in a systemd timer that exits non-zero on drift so monitoring picks it up. The same timer discipline described for scheduling accuracy applies here: use Persistent=true only if a missed run is safe, and always add RandomizedDelaySec.
[Unit]
Description=Config drift check
[Timer]
OnCalendar=*-*-* 04:00:00
RandomizedDelaySec=10min
AccuracySec=5min
[Install]
WantedBy=timers.target
Reconcile, don’t just detect
| Drift class | Detector | Reconcile action |
|---|---|---|
| Package | dpkg selections diff | Reinstall or pin |
| Config files | sha256 manifest | Redeploy from template |
| sysctl/limits | sysctl -a diff | Re-apply drop-in |
| Schema | Migration version table | Run pending migrations |
For stateful hosts, never auto-reconcile data. Gate schema and data changes behind a human step; auto-reconcile only declarative, idempotent config. A rebuild-from-scratch policy is the strongest drift control, which is why immutable images are worth the effort — if you are choosing infrastructure for this pattern, compare VPS hosting providers on snapshot and rebuild support.
A minimal drift inventory
# everything installed outside the base image
comm -13 <(sort /var/lib/baseline/packages.txt) \
<(apt-mark showmanual | sort)
# services enabled but not in the baseline
systemctl list-unit-files --state=enabled --no-pager
Run the checks after every deploy and at least once a day on idle hosts. The goal is not zero drift — small, intentional changes are normal — but zero undetected drift. Combined with verified backups, this keeps a stateful VPS reproducible under pressure.



Leave a Reply
You must be logged in to post a comment.