How to Track Every Config Change with etckeeper and Git (Undo for /etc)

"It worked last week. What changed?" is the question behind most server problems (tutorial 80, step 8). etckeeper answers it precisely: it keeps /etc in a git repository and commits automatically before and after every apt run and once a day, so every configuration change on the server is recorded with a timestamp. git diff shows what an update altered; git checkout puts a file back. Then do the same for your ~/docker folder, by hand, in Gitea.
Quick reference
| Task | Command | |
|---|---|---|
| Install | sudo apt install etckeeper -y | |
| Commit your own change | sudo etckeeper commit "turned off password auth" | |
| What's uncommitted | sudo etckeeper vcs status | |
| History | `sudo etckeeper vcs log --oneline | head` |
| What changed in a commit | sudo etckeeper vcs show HEAD | |
| Diff a file over time | sudo etckeeper vcs diff HEAD~5 -- nginx/nginx.conf | |
| Put a file back | sudo etckeeper vcs checkout HEAD~1 -- ssh/sshd_config |
1. Install
sudo apt install etckeeper -y
On Ubuntu it initialises a git repository in /etc and makes the first commit immediately. Check:
sudo etckeeper vcs log --oneline | head
etckeeper vcs just runs git inside /etc as root; you can cd /etc && sudo git ... directly if you prefer.
2. What it does by itself
- Before and after every apt install/upgrade: a commit, so a package's config changes are isolated from yours.
- Daily: a commit of anything you edited and forgot to commit (a systemd timer).
- Files that shouldn't be tracked (/etc/shadow's permissions are preserved; *.swp, caches) are handled by .gitignore it ships with.
Because the repository lives in /etc, it's owned by root and readable only by root — passwords in config files stay as private as they were.
3. Commit when you change something
After editing a file, record why:
sudo nano /etc/ssh/sshd_config
sudo etckeeper commit "sshd: keys only, no passwords (tutorial 3)"
The daily auto-commit would catch it anyway, but a message you wrote is worth more than "daily autocommit" when you read the log in a year.
4. Use the history
sudo etckeeper vcs log --oneline -- nginx/
sudo etckeeper vcs diff HEAD~3 -- nginx/sites-available/example.com
sudo etckeeper vcs show --stat HEAD
"What did last Tuesday's apt upgrade change?" is one git show. Undo one file:
sudo etckeeper vcs checkout HEAD~1 -- fail2ban/jail.local
sudo etckeeper commit "fail2ban: revert broken edit"
5. A copy off the server
The repository is only as safe as /etc. Push it somewhere — Gitea (tutorial 45) on another box, or even a bare repository on the backup drive:
sudo git -C /etc remote add origin ssh://git@192.168.1.60:2222/john/server-etc.git
sudo git -C /etc push -u origin master
Add sudo git -C /etc push to the nightly backup script. Keep that remote private — /etc contains secrets.
6. The same for ~/docker
Your compose files are configuration too. With .env ignored (tutorial 59):
cd ~/docker
git init
cat > .gitignore <<'EOF'
.env
**/data/
**/db/
**/postgres/
**/config/*.db
EOF
git add -A && git commit -m "initial"
git remote add origin ssh://git@192.168.1.60:2222/john/docker.git
git push -u origin main
From then on: edit a compose file, git commit -am "jellyfin: enable vaapi", git push. The commit log becomes the change history of every service, and a fresh server gets the whole setup with one git clone (plus restored data and .env files).
Troubleshooting
etckeeper says "unclean" during apt. Edits you haven't committed; it commits them for you as "saving uncommitted changes before apt run". Harmless.
Big binary files slowing commits. Add them to /etc/.gitignore — certificates under letsencrypt/archive are the usual culprit; they're backed up elsewhere.
Permissions after git checkout of a file. etckeeper stores and restores metadata (.etckeeper file); run sudo etckeeper init once if a restored file has the wrong mode.
Pushing fails with "permission denied" for root's key. Root runs the push; give root its own deploy key in Gitea, or run the push as your user with sudo -E.
Wrapping up
One package and /etc has an undo button and a diary. Commit with a message when you change something, push nightly, and treat ~/docker the same way in Gitea. The next "what changed?" takes one git log instead of an evening.
