sops-nix: declarative secret provisioning for NixOS, and where it stops
Atomic secret provisioning for NixOS based on sops
At a glance
- What is it?
- sops-nix decrypts sops files at activation time and writes one file per secret under declarative ownership. It fits hosts rebuilt from a repository, and it fits poorly when your secrets already live in a cloud vault.
- Who is it for?
- Adopt sops-nix if your machines are rebuilt from a repository and you want secrets to travel with the configuration under declarative ownership. Do not adopt it if your secrets already live in a cloud KMS that you rotate centrally, or if you need per-application secret fetching at runtime rather than files on disk.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Nix, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What sops-nix solves for NixOS hosts
A NixOS configuration is a single artifact built from a repository. Secrets break that property. The usual workaround is a provisioning step that copies key material onto the machine after the build, which means the machine cannot be reproduced from the repository alone and the copy step has to be maintained separately for every deployment framework.
sops-nix keeps the encrypted files in the repository and decrypts them on the target host during activation. The README describes the result as "atomic, declarative, and reproducible secret provisioning for NixOS based on sops". The audience is narrow and specific: people running NixOS who already use sops for encrypted files, and who want the decryption step to be part of the system activation rather than a script that runs before or after it.
Two consequences follow from that design. Because the files are encrypted, they can be committed to version control, and the README notes that diffs remain readable and can be shown in cleartext. Because decryption happens at activation time, no extra upload step is needed for NixOps, krops or morph, which is the "fast time-to-deploy" claim in the feature list.
Activation-time decryption and the atomic directory swap
The mechanism is a directory that gets replaced, not files that get overwritten. New secrets are written to a new directory, and that directory replaces the old one atomically. A reader of a secret path either sees the old generation or the new one, never a half-written file.
Ownership is part of the configuration, not something applied afterwards. Each secret is one file, with its user, group and permissions declared alongside it. The README states that sops files are checked against the configuration at evaluation time, so a mismatch between what the configuration expects and what the encrypted file contains surfaces when you build, not when the machine boots.
The repository is not only Nix. The top-level layout includes go.mod, go.sum and a pkgs directory, and the module path is github.com/Mic92/sops-nix. The Go dependencies include github.com/getsops/sops/v3, github.com/Mic92/ssh-to-age, gopkg.in/ini.v1 and github.com/joho/godotenv, which lines up with the claim that secrets can be stored in YAML, dotenv, INI, JSON or binary. The Nix modules in modules/ drive activation; the Go code is what parses and decrypts those formats on the host.
Installing sops-nix with flakes and writing a first secret
The README calls flakes the current recommendation. You add the input and pull the NixOS module into your system configuration. Replace yourhostname with the actual hostname and adjust system to match the machine.
{
inputs.sops-nix.url = "github:Mic92/sops-nix";
inputs.sops-nix.inputs.nixpkgs.follows = "nixpkgs";
outputs = { self, nixpkgs, sops-nix }: {
nixosConfigurations.yourhostname = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./configuration.nix
sops-nix.nixosModules.sops
];
};
};
}If you do not use flakes, the README documents niv as the recommended path, added with niv add Mic92/sops-nix and imported as "${(import ./nix/sources.nix).sops-nix}/modules/sops". A fetchTarball import is also shown, pinned by commit and sha256.
Next you need a key to edit secrets with. For age, the README gives age-keygen writing to ~/.config/sops/age/keys.txt, or converting an existing SSH Ed25519 key with ssh-to-age. For GPG it gives gpg --full-generate-key on versions 2.1.17 and newer. The ssh-to-pgp route derives a GPG key from an SSH key, and the README notes explicitly that ssh-to-pgp only supports RSA keys; Ed25519 keys belong on the age path.
mkdir -p ~/.config/sops/age
age-keygen -o ~/.config/sops/age/keys.txtOn the host side, secrets are declared in the NixOS configuration under sops.secrets, with the encrypted file referenced by sops.defaultSopsFile or per-secret. Because the README's usage example is split into collapsible sections and the excerpt here is truncated at the key-generation step, check the deployment example in the repository before copying a full configuration: that is where the working configuration.nix lives.
Where sops-nix is the wrong tool
Decrypted secrets land on disk. That is the whole point, and it is also the boundary. If your threat model says plaintext key material must never be written to the filesystem, sops-nix does not meet it, because activation writes files and the services read them from paths.
Cloud KMS support is the second soft spot. sops itself supports AWS KMS, GCP KMS, Azure Key Vault and Hashicorp Vault, but the README says these are "not officially supported by sops-nix yet" and that they can be controlled through environment variables passed to sops. That is a materially different promise from the GPG and age paths, which the project does support. If your secrets live in Vault and you expect sops-nix to be a first-class Vault client, you are on your own for the wiring.
The third case is secrets that change without a rebuild. sops-nix decrypts at activation. A credential that rotates hourly and must be picked up live by a running service is not what this is for; that belongs in the application or a sidecar that talks to the issuer directly.
There is also a key-availability trap that is easy to hit. The host needs the private key that is listed in the sops file. If you generate an age key on your workstation and encrypt for it, but the target machine's host key was never added as a recipient, the build succeeds and activation fails. The README's ssh-to-age and ssh-to-pgp tools exist to make that mapping easier, not to check it for you.
sops-nix compared with agenix
The comparison people reach for is agenix, and the difference is in the encryption model rather than the Nix integration. sops-nix uses sops, which encrypts each secret once with a master key and then wraps that master key for each recipient. The README points at this directly when it says the cryptography is designed to be scalable because secrets are encrypted once rather than per machine or per developer key. Adding a new recipient means re-wrapping the master key, not re-encrypting every value.
The practical differences follow. sops-nix handles several storage formats (YAML, dotenv, INI, JSON, binary) because sops does, and it gives you cleartext diffs of encrypted files in git. It also ships a home-manager module and nix-darwin module, and it has nix-shell hooks so several people can import their GPG keys quickly. agenix is a smaller tool built around age with a different file layout and editing flow. If your team already edits secrets with the sops CLI and wants those files to be the same ones the host consumes, sops-nix removes a translation step. If you want the smallest possible surface and age only, the sops dependency chain in go.mod is a real cost to weigh: it pulls in the cloud SDKs for AWS, Azure and GCP even when you only use age.
Maintenance, rollback and the MIT licence
The repository is not archived, and the last push was on 2026-09-20, days before this writing. The only release entry is an assets-only tag from 2021-08-29, so version numbers are not the way this project communicates change; commit history and the flake lock are. That matters for upgrades: pinning sops-nix by commit or by flake input and updating deliberately is more meaningful here than watching a release feed.
Rollback is conditional, and the README is explicit about the condition. If sops files are added to the Nix store, old secrets can be rolled back, and the README marks this as optional. Putting them in the store is what makes the previous generation recoverable, so the choice is a trade-off you make knowingly rather than a default you inherit.
The licence is MIT. That is permissive and imposes no copyleft obligation on your configuration. It says nothing about the licences of the tools you will actually run: sops, age, GnuPG, ssh-to-age and ssh-to-pgp are separate projects with their own terms, and your distribution of a built system may raise questions this repository cannot answer. Treat licence review as work you still owe, not as something the MIT header settles.
Editorial conclusion
Adopt sops-nix if your machines are rebuilt from a repository and you want secrets to travel with the configuration under declarative ownership. Do not adopt it if your secrets already live in a cloud KMS that you rotate centrally, or if you need per-application secret fetching at runtime rather than files on disk. Before committing, verify three things: that the age or GPG key the target host will use is actually listed in the sops file, that the paths you set under sops.secrets do not collide with files another module writes, and whether you want sops files in the Nix store, because that choice is what makes rollback possible.
Frequently asked questions
What is sops-nix?
It is a set of NixOS, nix-darwin and home-manager modules that decrypt sops-encrypted files during activation and write each secret to a file with declarative ownership and permissions. The README describes it as atomic, declarative and reproducible secret provisioning for NixOS based on sops.
How do I use sops-nix?
Add the flake input and the sops-nix.nixosModules.sops module to your system configuration, generate an age or GPG key to edit secrets with, then declare each secret under sops.secrets with its file, owner and permissions. Decryption happens at activation time on the target host.
Should I choose sops-nix or agenix?
sops-nix builds on sops, so secrets are encrypted once with a master key and that key is wrapped per recipient, and it supports YAML, dotenv, INI, JSON and binary formats. agenix is a smaller age-based tool with a different file layout and editing flow. The choice usually comes down to whether your team already edits secrets with the sops CLI.
What are the alternatives to sops-nix?
agenix is the alternative the search data points at, and it differs mainly in using age directly instead of sops. Separately, sops itself supports cloud key management APIs such as AWS KMS, GCP KMS, Azure Key Vault and Hashicorp Vault, but the README states these are not officially supported by sops-nix yet and can only be controlled through environment variables passed to sops.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mic92-sops-nix)