Keeping it maintainable
The introduction made a promise about Arch: the running system is the source of truth, it drifts, and nothing but your own discipline records how it got that way. This chapter is that discipline, written down as a git repository and one command, so that it does not have to live in your head.
Log in as admin. The host repo that setup built the machine from
is already there:
cd ~/arch git log --oneline
3f9c2e1 setup install: myhost (x86_64 PC, UEFI) a14b07d setup host: myhost
| File | Holds | Changed by |
|---|---|---|
host.env |
The install answers | You, rarely |
packages.txt |
Every package you asked for, beyond the base set | You |
units.txt |
Every unit you enabled | You |
etc/ |
Your files under /etc |
You |
bin/admin |
The admin command itself |
Nobody, usually |
authorized_keys |
Public keys admin accepts |
You |
aconfmgr/ |
The same, in aconfmgr’s terms, plus what to ignore | Nobody, usually |
aconfmgr/10-base.sh |
The base packages setup picked for this hardware |
setup install |
admin runs aconfmgr against ~/arch/aconfmgr:
| Command | Direction | What it does |
|---|---|---|
| admin diff | look only | Lists every difference between the machine and the repo |
| admin save | machine → repo | Writes the machine’s drift into the repo, for you to sort and commit |
| admin apply | repo → machine | Makes the machine match the repo, removals included |
| admin upgrade | both | Refuses on drift, pacman -Syu, apply, reports .pacnew files |
admin git ... |
the repo itself | Runs git in the host repo, from wherever you are |
admin git saves remembering where the repo lives: admin git log,
admin git commit -am "...", admin git push, from any directory.
Everything after git is handed to git untouched, and git’s exit
status comes back, so admin git diff --quiet still works as a test.
admin help prints the same list. Every command takes aconfmgr’s own
options after it: --yes answers its questions, --skip-checksums
skips comparing package files with their checksums, which is much
faster but misses edits to files that packages own.
What aconfmgr looks at
aconfmgr knows the whole system, not only what you told it about. It
lists the packages installed explicitly (pacman -Qe; dependencies
come and go with them and are never listed), every file on the
system that no package owns, and every file a package owns that has
changed since it was installed. Anything in that list that the
configuration does not describe, or that the configuration describes
and the machine lacks, is drift.
A fresh install has no drift. That is not an accident of a new
system – a fresh Arch install is full of files no package owns – but
the result of ~/arch/aconfmgr/, which accounts for all of them:
| File | Describes |
|---|---|
00-helpers.sh |
The helpers the others use, including one that works out the links systemctl enable makes |
10-base.sh |
The base packages for this hardware (written by setup install) |
20-host.sh |
What setup wrote from host.env: hostname, locale, keymap, time zone, resolv.conf |
30-repo.sh |
packages.txt, the files under etc/ and bin/, and the units in units.txt |
40-system.sh |
What packages and boot leave behind: units they enable, directories they make, aconfmgr’s links |
90-ignore.sh |
What is not configuration at all |
They are bash, read by aconfmgr in order. 20-host.sh and
30-repo.sh do not copy anything: they read host.env,
packages.txt, units.txt, etc/ and bin/, so those stay the
files you edit and aconfmgr follows them. Adding a package is still a
line in packages.txt.
What is ignored, and why
90-ignore.sh lists what aconfmgr should not report:
- What
setupowns:/boot(the bootloader, kernel and initramfs, rewritten by pacman hooks) and/etc/fstab(UUIDs of this disk). - Accounts:
/etc/passwd,group,shadowand friends.setupmakes the accounts, and password hashes never go into the repo. - Secrets and identity: SSH host keys,
/etc/machine-id, pacman’s keyring. - Generated files: the CA bundle,
ld.so.cache, module and hardware databases, the locale archive, the mirror list. - State:
/var/lib,/var/log,/var/tmp,/swap,/.snapshots, the Nix store (/nix), and aconfmgr’s own checkout.
aconfmgr already ignores /home, /root, /tmp, /var/cache and
the pseudo-filesystems. When something new shows up that is state
rather than configuration – a database a service keeps under /srv,
say – the fix is a line here, with its reason:
# The music server's library database. IgnorePath '/srv/music/*.db'
Quote the pattern, or bash expands it before aconfmgr sees it.
Push it somewhere
The host repo is the only record of this machine that exists off its
own disk – or it will be, once you push it. The next reinstall starts
from it with setup host --from. Make it a private repository: it
holds no secrets, but it describes your machine in detail.
git -C ~/arch remote add origin git@git.example.com:you/arch-myhost.git git -C ~/arch push -u origin main