diff --git a/doc/secrets.md b/doc/secrets.md index de77c5b8..6afe2f6a 100644 --- a/doc/secrets.md +++ b/doc/secrets.md @@ -1,18 +1,110 @@ # Secrets -Secrets are managed using [git-crypt][git-crypt] so you can keep your flake in -a public repository like GitHub without exposing your password or other -sensitive data. +Secrets are managed using [git-crypt][git-crypt] and [agenix][agenix] +so you can keep your flake in a public repository like GitHub without +exposing your password or other sensitive data. By default, everything in the secrets folder is automatically encrypted. Just be sure to run `git-crypt init` before putting anything in here. +## Agenix +Currently, there is [no mechanism][secrets-issue] in nix itself to deploy secrets +within the nix store because it is world-readable. + +Most NixOS modules have the ability to set options to files in the system, outside +the nix store, that contain sensitive information. You can use [agenix][agenix] +to easily setup those secret files declaratively. + +[agenix][agenix] encrypts secrets and stores them as .age files in your repository. +Age files are encrypted with multiple ssh public keys, so any host or user with a +matching ssh private key can read the data. The [age module][age module] will add those +encrypted files to the nix store and decrypt them on activation to `/run/secrets`. + +### Setup +All hosts must have openssh enabled, this is done by default in the core profile. + +You need to populate your `secrets/secrets.nix` with the proper ssh public keys. +Be extra careful to make sure you only add public keys, you should never share a +private key!! + +secrets/secrets.nix: +```nix +let + system = ""; + user = ""; + allKeys = [ system user ]; +in +``` + +On most systems, you can get your systems ssh public key from `/etc/ssh/ssh_host_ed25519_key.pub`. If +this file doesn't exist you likely need to enable openssh and rebuild your system. + +Your users ssh public key is probably stored in `~/.ssh/id_ed25519.pub` or +`~/.ssh/id_rsa.pub`. If you haven't generated a ssh key yet, be sure do so: +```sh +ssh-keygen -t ed25519 +``` + > ##### _Note:_ -> Currently, there is [no mechanism][secrets-issue] in nix to deploy secrets -> within the nix/store so, if they end up in the nix/store after deployment, they -> will be world readable on that machine. -> -> The author of devos intends to implement a workaround for this situation in -> the near future, but for the time being, simple be aware of this. +> The underlying tool used by agenix, rage, doesn't work well with password protected +> ssh keys. So if you have lots of secrets you might have to type in your password many +> times. + + +### Secrets +You will need the `agenix` command to create secrets. DevOS conveniently provides that +in the devShell, so just run `nix develop` whenever you want to edit secrets. Make sure +to always run `agenix` while in the `secrets/` folder, so it can pick up your `secrets.nix`. + +To create secrets, simply add lines to your `secrets/secrets.nix`: +``` +let + ... + allKeys = [ system user ]; +in +{ + "secret.age".publicKeys = allKeys; +} +``` +That would tell agenix to create a `secret.age` file that is encrypted with the `system` +and `user` ssh public key. + +Then go into the `secrets` folder and run: +```sh +agenix -e secret.age +``` +This will create the `secret.age`, if it doesn't already exist, and allow you to edit it. + +If you ever change the `publicKeys` entry of any secret make sure to rekey the secrets: +```sh +agenix --rekey +``` + +### Usage +Once you have your secret file encrypted and ready to use, you can utilize the [age module][age module] +to ensure that your secrets end up in `/run/secrets`. + +In any profile that uses a NixOS module that requires a secret you can enable a particular secret like so: + +```nix +{ self, ... }: +{ + age.secrets.mysecret.file = "${self}/secrets/mysecret.age"; +} +``` + + +Then you can just pass the path `/run/secrets/mysecret` to the module. + +You can make use of the many options provided by the age module to customize where and how +secrets get decrypted. You can learn about them by looking at the +[age module][age module]. + + +> ##### _Note:_ +> You can take a look at the [agenix repository][agenix] for more information +> about the tool. [git-crypt]: https://github.com/AGWA/git-crypt +[agenix]: https://github.com/ryantm/agenix +[age module]: https://github.com/ryantm/agenix/blob/master/modules/age.nix [secrets-issue]: https://github.com/NixOS/nix/issues/8 diff --git a/flake.lock b/flake.lock index 5dd25600..cb213802 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,25 @@ { "nodes": { + "agenix": { + "inputs": { + "nixpkgs": [ + "latest" + ] + }, + "locked": { + "lastModified": 1620877075, + "narHash": "sha256-XvgTqtmQZHegu9UMDSR50gK5cHEM2gbnRH0qecmdN54=", + "owner": "ryantm", + "repo": "agenix", + "rev": "e543aa7d68f222e1e771165da9e9a64b5bf7b3e3", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, "ci-agent": { "inputs": { "flake-compat": "flake-compat", @@ -352,6 +372,7 @@ }, "root": { "inputs": { + "agenix": "agenix", "ci-agent": "ci-agent", "darwin": "darwin", "digga": "digga", diff --git a/flake.nix b/flake.nix index 535c7174..8e62d61f 100644 --- a/flake.nix +++ b/flake.nix @@ -17,13 +17,26 @@ home.inputs.nixpkgs.follows = "nixos"; naersk.url = "github:nmattia/naersk"; naersk.inputs.nixpkgs.follows = "latest"; + agenix.url = "github:ryantm/agenix"; + agenix.inputs.nixpkgs.follows = "latest"; nixos-hardware.url = "github:nixos/nixos-hardware"; pkgs.url = "path:./pkgs"; pkgs.inputs.nixpkgs.follows = "nixos"; }; - outputs = inputs@{ self, pkgs, digga, nixos, ci-agent, home, nixos-hardware, nur, ... }: + outputs = + { self + , pkgs + , digga + , nixos + , ci-agent + , home + , nixos-hardware + , nur + , agenix + , ... + } @ inputs: digga.lib.mkFlake { inherit self inputs; @@ -36,6 +49,7 @@ ./pkgs/default.nix pkgs.overlay # for `srcs` nur.overlay + agenix.overlay ]; }; latest = { }; @@ -60,6 +74,7 @@ { _module.args.ourLib = self.lib; } ci-agent.nixosModules.agent-profile home.nixosModules.home-manager + agenix.nixosModules.age ./modules/customBuilds.nix ]; }; diff --git a/overlays/overrides.nix b/overlays/overrides.nix index 59516b3d..629f44b1 100644 --- a/overlays/overrides.nix +++ b/overlays/overrides.nix @@ -8,6 +8,7 @@ channels: final: prev: { discord element-desktop manix + rage nixpkgs-fmt qutebrowser signal-desktop diff --git a/profiles/core/default.nix b/profiles/core/default.nix index 41b5136e..9e98ba6b 100644 --- a/profiles/core/default.nix +++ b/profiles/core/default.nix @@ -143,6 +143,12 @@ in ''; }; + # For rage encryption, all hosts need a ssh key pair + services.openssh = { + enable = true; + openFirewall = lib.mkDefault false; + }; + services.earlyoom.enable = true; } diff --git a/secrets/.gitattributes b/secrets/.gitattributes index ff69eb2a..901863e3 100644 --- a/secrets/.gitattributes +++ b/secrets/.gitattributes @@ -1,3 +1,4 @@ * filter=git-crypt diff=git-crypt .gitattributes !filter !diff +secrets.nix !filter !diff README.md !filter !diff diff --git a/secrets/secrets.nix b/secrets/secrets.nix new file mode 100644 index 00000000..bac30e03 --- /dev/null +++ b/secrets/secrets.nix @@ -0,0 +1,9 @@ +let + # set ssh public keys here for your system and user + system = ""; + user = ""; + allKeys = [ system user ]; +in +{ + "secret.age".publicKeys = allKeys; +}