“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/dnf operation: 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.

  • Linux
  • Git
  • Administration