{
"$type": "site.standard.document",
"canonicalUrl": "https://isabelroses.com/blog/nixos-and-secrets",
"coverImage": {
"$type": "blob",
"ref": {
"$link": "bafkreiglhp2nuf26mv22egueok4ogle3rjcew5uxtuar6pxfu432mpqjke"
},
"mimeType": "image/png",
"size": 11228
},
"description": "My takes and experinces with secrets management on NixOS",
"path": "/blog/nixos-and-secrets",
"publishedAt": "2026-05-08T00:00:00.000Z",
"site": "at://did:plc:qxichs7jsycphrsmbujwqbfb/site.standard.publication/3mn5hmwkcmb22",
"tags": [
"nixos",
"secrets"
],
"textContent": "To start this off I will say that I've been using NixOS for 3 years now and I\nhave used the main 6 (or 7 if we include ragenix) secrets management tools on\nNixOS. This consists of:\n\n- sops-nix\n- agenix or ragenix\n- using your filesystem to its full potential but loosing reproducibility on another machine\n- putting your secrets into private git repo\n- storing them in the main repo with git-crypt\n- writing the secrets directly into your nix configuration\n\nBefore we go any further I want to say DO NOT use the last three if you intend\nto do share your machines or make your configuration public. This is because\nthe nix store is world readable and people who have access to the machine will\nbe able to read the secrets. I find this particularly pertinent at the time of\nwriting with the following vulnerabilities: CVE-2026-31431\n(copyfail) and CVE-2026-43284 and CVE-2026-43500\n(dirtyfrag). For this reason I will not\ncover any of these options. But that is not to say I am guilt free in all of\nthis. I have leaked my secrets on at least two occasions\n1\n2,\nand I'm sure you can find more if you look further.\n\nsops-nix\n\nSo I have a bit of a love hate relationship with sops-nix. It was my first tool\nfor secrets management but it was really hard to get into and working back when\nI originally started using it 3 years ago. Especially for a none technical\nuser like I was at the time I really struggled to get it working. Which also\neventually lead to me removing it since I didn't understand it.\n\nHowever, now I'm looking back it was easier than I realized, the docs have\ngotten miles better, and now sops natively supports using ssh keys to encrypt and\ndecrypt secrets which is a huge improvement. Sadly sops-nix is lagging behind\nin support for this, see both\nsops-nix#779 and sops-nix#922.\n\nThe way you use sops-nix is by creating a yaml file with the rules for\nencrypting and decrypting secrets. An example of this might look like this:\n\nThen you can use the sops command line tool to encrypt and decrypt the\nsecrets. This command may look like sops secrets/shush.yaml. This will then\nopen your chosen editor to allow you to configure a yaml file.\n\nUpon exiting the editor the data will then be encrypted and may look something like:\n\nThis is totally normal, and you can use the same command as you used before to\nkeep editing them.\n\nOnce the file is encrypted you will still need to introduce your config to it. sops-nix\nships a module that does the heavy lifting, so a typical config may look like:\n\nAt activation time sops-nix decrypts the file using the host's SSH key and\ndrops the plaintext at /run/secrets/<name>, which is a tmpfs so the secret\nnever touches disk. Anything that needs the value just reads that path.\n\nAnother feature I lean on heavily is templates. This is particularly useful if\nyour config is shared between users or referenced by others. But there is still\nuse outside of that, for example if a service wants a config file that mixes\nplain text with one or two secret values, you don't have to encrypt the whole\nfile:\n\nAgenix\n\nAgenix takes a different approach from sops-nix making it feel a lot more\nlike nix since you configure all the secrets and who can access them through\nthe secrets.nix file. It is important to note that you can also configure\nwhat keys have access to what secret. This file might look a little like so:\n\nFrom this point you will have to add the secret1.age and secret2.age files.\nThis should be done with the agenix cli, the command may look like agenix -e\nsecret1.age, this same command can be used later in order to edit the files.\n\nWiring agenix into a host looks fairly similar to sops-nix, but the surface area\nis smaller because each secret is its own file:\n\nAt boot the host's SSH key is used to decrypt each .age file into\n/run/agenix/<name>, again on a tmpfs. The bit that catches most people out is\nrekeying. Every time that you add a new host or rotate a key, every secret in\nsecrets.nix whose publicKeys list has changed will need to be re-encrypted.\nThe agenix --rekey command will do this for you, but it needs the _current_\nprivate key for one of the recipients to read the existing ciphertext first. In\npractice this means rekeying happens on the machine you trust most, not on the\nnew host you're trying to bring up.\n\nUsing the filesystem\n\nThe cost of this method being that your config no longer fully describes your\nmachines, which is why I've never attempted to use this method. If you\nreinstall, you have to remember to put every one of those files back in the\nright place with the right ownership. It also makes it a total disaster when\ndoing recovery, which matters more than you'd think when you're rebuilding a\nserver at 2am.\n\nThe thing to avoid is builtins.readFile \"/var/lib/myservice/token\" or\nsimilar. That reads the file at evaluation time and embeds the contents into\nthe nix store, which is world-readable and is exactly the failure mode the\nintro warned about. Always pass the _path_ to the service via options like\nservices.\\.environmentFiles.\n\nFor a single server or laptop this maybe fine. For anything you'd describe as a\nfleet, or anything you want to be able to rebuild from scratch from just your\nconfig, use sops-nix or agenix instead.\n\nThe Battle between the big two\n\nThe main reason to use sops-nix is that you're packing as much data into one\nfile as possible, which has its own respective pros and cons. For me that\nmostly meant that I could put a lot more of my mail server secrets into one\nfile rather than having them split up between 5 or so files like with agenix.\n\nAgenix wins in terms of simplicity. There's no yaml schema to learn, no .sops.yaml\nto keep in sync, and the secrets.nix file is just nix, so the same\nlet ... in bindings you already use for hosts and users work for keys.\nThe mental model is \"one secret, one file, one list of recipients\", and that\nmaps cleanly onto how I think about access control.\n\nThe honest answer is that both tools solve the problem and the difference at\nthis point is mostly ergonomics. If you're starting from scratch and you have\nmore than a couple of services that each want a bundle of related secrets,\nsops-nix will scale better. If you're starting from scratch and you mostly have\na handful of standalone tokens, agenix will get you there with less ceremony.\n\n~~It is also important to note at this current moment of time agenix is\nNOT post quantum\nsafe. However, the same\nissue applies to sops-nix but not because of a limitation of sops like agenix's\nlimitation in the age cli. But rather due to sops-nix not supporting\nPost-Quantum age keys\nsops-nix#885.~~\n\nSince writing I have been corrected in saying this, as age and sops do support\npost-quantum secure encryption keys. Since\nage#578 was closed and\nv1.3.0 was released.\nWhen generating your age key change the command to include -pq so the command\nmight now look like age-keygen -pq -o key.txt.\n\nConclusion\n\nAfter three years of cycling through every option on the list, the picture I've\nlanded on is roughly this:\n\n- sops-nix is what I keep using on hosts as a powerful tool. And what I'd\n pick first for anything mail server shaped where I have more secrets than\n fingers and toes.\n- agenix is what I reach for whenever someone asks me about secrets in a\n NixOS machine. It's the smallest amount of moving parts that still gives you\n proper key-per-host access control.\n- The filesystem is fine for the one or two values per machine that genuinely\n shouldn't live in a repo, as long as you remember that you've made future-you\n responsible for putting them back.\n- Everything else on the original list, private repos, git-crypt, plaintext\n in the nix config. I would NOT recommend ever.\n\nIf you're picking your first secrets tool, pick agenix, get comfortable with\nthe flow, and only graduate to sops-nix once you actually feel the pain of one\nsecret per file.",
"title": "NixOS and Secrets"
}