Secrets
Secrets — login passwords, WiFi keys, disk passphrases — are kept as encrypted files in version control with sops-nix. Each is decrypted where it is needed: some by every machine at boot, some only by the people who administer the machines. This chapter covers the trust model and how the pieces fit together; the Baseline chapters on Login passwords, WiFi and Disk encryption cover managing each kind.
The trust model
Section titled “The trust model”Every secret is a YAML file under secrets/, encrypted with sops and
committed to the repository. Only the values are encrypted; the keys, the
file names, and .sops.yaml itself stay in clear text.
Who may decrypt a file is declared in .sops.yaml, as a list of age
keys — one per reader. A machine becomes a reader through its SSH host key
(converted to an age key with ssh-to-age); a person becomes one through
their own SSH key. Every host is set up to decrypt its secrets at boot with
its own SSH host key, /etc/ssh/ssh_host_ed25519_key, by
secrets.nix.
Who can decrypt what
Section titled “Who can decrypt what”| Secret | Readers | Decrypted by |
|---|---|---|
passwords.yaml | every machine + admins | each host, at boot |
wifi.yaml | every machine + admins | each host, at boot |
disks/<user>.yaml | that user + lead admin | a person, at install |
Passwords and WiFi credentials are decrypted by the machines themselves, so
both files have the same readers — every machine, plus the admins (one rule
in .sops.yaml can therefore cover them together).
A disk passphrase is what protects a machine when it is stolen; handing it
to the host would defeat the encryption, so hosts are deliberately kept out
of the readers of disks/*.yaml. Each person’s passphrase sits in its own
file that only they can decrypt, yet we can flexibly add other readers — an
admin or the install automation — when a machine needs setting up.
keys: users: - &alice ssh-ed25519 AAAA… - &bob ssh-ed25519 AAAA… hosts: - &laptop age1…
stores: yaml: indent: 2
creation_rules:- path_regex: secrets/(passwords|wifi)\.yaml$ key_groups: - age: - *laptop - *alice - *bob- path_regex: secrets/disks/alice\.yaml$ key_groups: - age: - *aliceEditing secrets
Section titled “Editing secrets”Open a secret with, e.g., sops secrets/passwords.yaml to edit its contents;
it decrypts the file into your editor and re-encrypts it on save. Who may
decrypt a file is declared separately, in .sops.yaml. To change that set,
edit .sops.yaml first, then re-encrypt the file to match:
sops updatekeys secrets/passwords.yamlHow it works
Section titled “How it works”On a running host, once it can decrypt them, each kind of secret feeds a different part of the system.
Login passwords. Every name passwords.yaml lists is applied as that user’s
users.users.<name>.hashedPasswordFile; names that are not users on the host
are ignored.
WiFi. Every entry in the wifi list becomes a NetworkManager connection
named after its SSID. A wifi-provision service reconciles the connections at
boot, deleting the ones it previously created that the list no longer names.
Disk encryption. The automatic layout (see Disks) puts
everything on a LUKS2 volume. Each of a host’s owners — its normal users, listed
by disk.owners — has a keyslot on that
volume, unlocked by the passphrase kept in secrets/disks/<user>.yaml. Version
control is the source of truth for who may unlock a disk.