agenix/README.md

179 lines
4.4 KiB
Markdown
Raw Normal View History

2020-09-03 22:03:01 +03:00
# agenix
[age](https://github.com/FiloSottile/age)-encrypted secrets for NixOS.
2020-09-03 23:16:44 +03:00
It consists of a NixOS module `age`, and a CLI tool called `agenix`
used for editing and rekeying the secret files.
## Features
2020-09-03 22:03:01 +03:00
* Secrets are encrypted with SSH keys
2020-09-03 23:18:21 +03:00
* system public keys via `ssh-keyscan`
* can use public keys available on GitHub for users (for example, https://github.com/ryantm.keys)
2020-09-03 22:03:01 +03:00
* No GPG
* Very little code, so it should be easy for you to audit
2020-09-03 23:16:44 +03:00
## Installation
2020-09-03 22:03:01 +03:00
Choose one of the following methods:
2020-09-03 23:16:44 +03:00
### [niv](https://github.com/nmattia/niv) (Current recommendation)
2020-09-03 22:03:01 +03:00
First add it to niv:
```console
$ niv add ryantm/agenix
```
2020-09-03 23:16:44 +03:00
#### Module
Then add the following to your configuration.nix in the `imports` list:
2020-09-03 22:03:01 +03:00
```nix
{
imports = [ "${(import ./nix/sources.nix).agenix}/modules/age" ];
}
```
2020-09-03 23:16:44 +03:00
### nix-channel
2020-09-03 22:03:01 +03:00
As root run:
```console
$ nix-channel --add https://github.com/ryantm/agenix/archive/master.tar.gz agenix
$ nix-channel --update
```
Than add the following to your configuration.nix in the `imports` list:
```nix
{
imports = [ <agenix/modules/age> ];
}
```
2020-09-03 23:16:44 +03:00
### fetchTarball
2020-09-03 22:03:01 +03:00
Add the following to your configuration.nix:
2020-09-03 23:16:44 +03:00
```nix
2020-09-03 22:03:01 +03:00
{
imports = [ "${builtins.fetchTarball "https://github.com/ryantm/agenix/archive/master.tar.gz"}/modules/age" ];
}
```
or with pinning:
```nix
{
imports = let
# replace this with an actual commit id or tag
commit = "298b235f664f925b433614dc33380f0662adfc3f";
in [
"${builtins.fetchTarball {
url = "https://github.com/ryantm/agenix/archive/${commit}.tar.gz";
# replace this with an actual hash
sha256 = "0000000000000000000000000000000000000000000000000000";
}}/modules/age"
];
}
```
2020-09-03 23:16:44 +03:00
### Flakes
#### Module
2020-09-03 22:03:01 +03:00
2020-09-03 23:16:44 +03:00
```nix
2020-09-03 22:03:01 +03:00
{
inputs.agenix.url = "github:ryantm/agenix";
# optional, not necessary for the module
#inputs.agenix.inputs.nixpkgs.follows = "nixpkgs";
outputs = { self, nixpkgs, agenix }: {
# change `yourhostname` to your actual hostname
nixosConfigurations.yourhostname = nixpkgs.lib.nixosSystem {
# change to your system:
system = "x86_64-linux";
modules = [
./configuration.nix
agenix.nixosModules.age
];
};
};
}
```
2020-09-03 23:16:44 +03:00
#### CLI
You don't need to install it:
```console
nix run github:ryantm/agenix -- --help
```
## Tutorial
2020-09-04 01:18:20 +03:00
1. Make a directory to store secrets and `secrets.nix` file for listing secrets and their public keys:
2020-09-03 23:16:44 +03:00
```console
$ mkdir secrets
$ cd secerts
2020-09-04 01:18:20 +03:00
$ touch secrets.nix
2020-09-03 23:16:44 +03:00
```
2020-09-04 01:18:20 +03:00
2. Add public keys to `secrets.nix` file (hint: use `ssh-keyscan` or GitHub (for example, https://github.com/ryantm.keys)):
```nix
let
user1 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL0idNvgGiucWgup/mP78zyC23uFjYq0evcWdjGQUaBH";
system1 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPJDyIr/FSz1cJdcoW69R+NrWzwGK/+3gJpqD1t8L2zE";
in
{
2020-09-04 01:19:30 +03:00
"secret1.age".public_keys = [ user1 system1 ];
2020-09-04 01:18:20 +03:00
"secret2.age".public_keys = [ user1 ];
}
2020-09-03 23:16:44 +03:00
```
3. Edit secret files (assuming your SSH private key is in ~/.ssh/):
```console
$ agenix -e secret1.age
```
4. Add secret to NixOS module config:
```nix
age.secrets.secret1 = ../secrets/secret1.age;
```
5. NixOS rebuild or use your deployment too like usual.
## Rekeying
2020-09-04 01:18:20 +03:00
If you change the public keys in `secrets.nix`, you should rekey your
2020-09-03 23:16:44 +03:00
secrets:
```console
$ agenix --rekey
```
To rekey a secret, you have to be able to decrypt it. Because of
randomness in `age`'s encryption algorithms, the files always change
when rekeyed, even if the identities do not. This eventually could be
improved upon by reading the identities from the age file.
## Threat model/Warnings
2020-09-03 23:35:15 +03:00
This project has not be audited by a security professional.
2020-09-03 23:16:44 +03:00
People unfamiliar with `age` might be surprised that secrets are not
authenticated. This means that every attacker that has write access to
the repository can modify secrets because public keys are exposed.
This seems like not a problem on the first glance because changing the
configuration itself could expose secrets easily. However it is easier
to review configuration changes rather than random secrets (for
example 4096-bit rsa keys). This would be solved by having a message
authentication code (MAC) like other implementations like GPG or
[sops](https://github.com/Mic92/sops-nix) have, however this was left
out for simplicity in `age`.
## Acknowledgements
2020-09-03 22:03:01 +03:00
2020-09-03 23:16:44 +03:00
This project is based off of
[sops-nix](https://github.com/Mic92/sops-nix) created Mic92. Thank you
to Mic92 for inspiration and help with making this.