“What changed in the Nginx config last week?” “Which package update modified sshd_config?” With etckeeper, every change to /etc is recorded in a Git repository, automatically before and after package installs, and once a day for manual edits. It’s a small tool that makes configuration history and rollbacks easy.
Install
sudo apt install etckeeper git # Debian/Ubuntu (initialises automatically)
sudo dnf install etckeeper # RHEL family (EPEL)
sudo etckeeper init && sudo etckeeper commit "Initial commit" # if not done automatically
The repository lives in /etc/.git. It’s only readable by root.
Set a commit identity (so commits aren’t from “root@hostname” with an empty name):
sudo git -C /etc config user.name "Server Admin"
sudo git -C /etc config user.email "[email protected]"
What gets committed automatically
- Before and after every
apt/dnfoperation: commit messages list the packages installed, upgraded or removed. - Daily, via a cron job or systemd timer: any uncommitted manual changes.
- Metadata such as file permissions and ownership (Git alone doesn’t store these), in
/etc/.etckeeper.
Commit your own changes with a message
After editing a config file:
sudo etckeeper commit "nginx: enable HTTP/2 and gzip for json"
Good commit messages turn the history into documentation of your server.
View history and differences
sudo git -C /etc log --oneline | head -20
sudo git -C /etc log -p -- ssh/sshd_config # all changes to one file
sudo git -C /etc diff # uncommitted changes right now
sudo git -C /etc show HEAD~3 -- nginx/ # what an older commit changed in nginx/
sudo etckeeper vcs status
git diff before a restart is a great habit: you see exactly what you’re about to apply.
Roll back a file
sudo git -C /etc checkout HEAD~1 -- nginx/sites-available/example.com
sudo nginx -t && sudo systemctl reload nginx
sudo etckeeper commit "revert example.com config"
Restore single files rather than resetting the whole repository: /etc also contains changes made by package updates that you probably want to keep.
Ignore noisy or sensitive files
etckeeper’s .gitignore already skips many generated files. Add your own:
echo "letsencrypt/archive/" | sudo tee -a /etc/.gitignore
Pushing to a remote (carefully)
/etc contains secrets: /etc/shadow hashes, TLS private keys, database passwords, API keys in config files. If you push the repository anywhere:
- use a private repository on infrastructure you control (for example a self-hosted Gitea), never a public one. See Gitea;
- restrict access tightly, and consider excluding key material via
.gitignore; - treat the remote as sensitive as the server itself.
Pushing gives you an off-server history, which helps after a disaster. But it’s no replacement for backups. See backup strategy.
etckeeper vs configuration management
etckeeper records what happened on one server. Configuration management (Ansible and others) defines what should be there, and applies it to many servers. They work well together: etckeeper catches manual changes that drift from your playbooks. See Linux configuration management.
A good habit
Before any configuration change, run sudo git -C /etc status to confirm there’s nothing uncommitted from earlier work. Make your change, test it (nginx -t, sshd -t), apply it, then commit with a message explaining why. Months later, git log tells the story of the server, which is especially valuable when several people administer it.
Quick reference
| Task | Command |
|---|---|
| Install | apt install etckeeper |
| Commit with message | etckeeper commit "msg" |
| History | git -C /etc log --oneline |
| File history | git -C /etc log -p -- path |
| Uncommitted changes | git -C /etc diff |
| Restore a file | git -C /etc checkout <rev> -- path |
Related: Linux directory structure and dotfiles management.