mirror of
https://github.com/ryan4yin/nix-config.git
synced 2026-07-14 00:22:39 +02:00
docs: secrets
This commit is contained in:
+38
-18
@@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
All my secrets are safely encrypted via agenix, and stored in a separate private GitHub repository and referenced as a flake input in this flake.
|
All my secrets are safely encrypted via agenix, and stored in a separate private GitHub repository and referenced as a flake input in this flake.
|
||||||
|
|
||||||
|
The encryption is done by using all my host's public keys(`/etc/ssh/ssh_host_ed25519_key`), so that they can only be decrypted on any of my configured hosts.
|
||||||
|
The host keys are generated locally on each host by openssh without passphrase, and are only readable by `root`, and will never leave the host.
|
||||||
|
|
||||||
In this way, all secrets is still encrypted when transmitted over the network and written to `/nix/store`,
|
In this way, all secrets is still encrypted when transmitted over the network and written to `/nix/store`,
|
||||||
they are decrypted only when they are finally used.
|
they are decrypted only when they are finally used.
|
||||||
|
|
||||||
@@ -34,18 +37,24 @@ Suppose you want to add a new secret file `xxx.age`. Follow these steps:
|
|||||||
# and users can decrypt the secrets by any of the corresponding private keys.
|
# and users can decrypt the secrets by any of the corresponding private keys.
|
||||||
|
|
||||||
let
|
let
|
||||||
# get user's ssh public key by command:
|
# Get system's ssh public key by command:
|
||||||
# cat ~/.ssh/id_ed25519.pub
|
|
||||||
# if you do not have one, you can generate it by command:
|
|
||||||
# ssh-keygen -t ed25519
|
|
||||||
ryan = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJx3Sk20pLL1b2PPKZey2oTyioODrErq83xG78YpFBoj";
|
|
||||||
users = [ ryan ];
|
|
||||||
|
|
||||||
# get system's ssh public key by command:
|
|
||||||
# cat /etc/ssh/ssh_host_ed25519_key.pub
|
# cat /etc/ssh/ssh_host_ed25519_key.pub
|
||||||
ai = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICGeXNCazqiqxn8TmbCRjA+pLWrxwenn+CFhizBMP6en root@ai";
|
# If you do not have this file, you can generate all the host keys by command:
|
||||||
systems = [ ai ];
|
# sudo ssh-keygen -A
|
||||||
in
|
idol_ai = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINHZtzeaQyXwuRMLzoOAuTu8P9bu5yc5MBwo5LI3iWBV root@ai";
|
||||||
|
harmonica = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINT7Pgy/Yl+t6UkHp5+8zfeyJqeJ8EndyR1Vjf/XBe5f root@harmonica";
|
||||||
|
fern = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMokXUYcUy7tysH4tRR6pevFjyOP4cXMjpBSgBZggm9X root@fern";
|
||||||
|
|
||||||
|
# A key for recovery purpose, generated by `ssh-keygen -t ed25519 -a 256 -C "ryan@agenix-recovery"` with a strong passphrase
|
||||||
|
# and keeped it offline in a safe place.
|
||||||
|
recovery_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHnIGH+653Oe+GQaA8zjjj7HWMWp7bWXed4q5KqY4nqG ryan@agenix-recovery";
|
||||||
|
systems = [
|
||||||
|
idol_ai
|
||||||
|
harmonica
|
||||||
|
fern
|
||||||
|
|
||||||
|
recovery_key
|
||||||
|
];
|
||||||
{
|
{
|
||||||
"./xxx.age".publicKeys = users ++ systems;
|
"./xxx.age".publicKeys = users ++ systems;
|
||||||
}
|
}
|
||||||
@@ -63,7 +72,7 @@ Alternatively, you can encrypt an existing file to `xxx.age` using the following
|
|||||||
cat /path/to/xxx | agenix -e ./xxx.age
|
cat /path/to/xxx | agenix -e ./xxx.age
|
||||||
```
|
```
|
||||||
|
|
||||||
`agenix` will encrypt the file with all the public keys we defined in `secrets.nix`,
|
`agenix` will encrypt the file with all the public keys we defined in `secrets.nix`,
|
||||||
so all the users and systems defined in `secrets.nix` can decrypt it with their private keys.
|
so all the users and systems defined in `secrets.nix` can decrypt it with their private keys.
|
||||||
|
|
||||||
## Deploying Secrets
|
## Deploying Secrets
|
||||||
@@ -83,7 +92,7 @@ First, add your own private `nix-secrets` repository and `agenix` as a flake inp
|
|||||||
# my private secrets, it's a private repository, you need to replace it with your own.
|
# my private secrets, it's a private repository, you need to replace it with your own.
|
||||||
mysecrets = { url = "github:ryan4yin/nix-secrets"; flake = false; };
|
mysecrets = { url = "github:ryan4yin/nix-secrets"; flake = false; };
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs@{ self, nixpkgs, ... }: {
|
outputs = inputs@{ self, nixpkgs, ... }: {
|
||||||
nixosConfigurations = {
|
nixosConfigurations = {
|
||||||
nixos-test = nixpkgs.lib.nixosSystem {
|
nixos-test = nixpkgs.lib.nixosSystem {
|
||||||
@@ -116,8 +125,10 @@ Then, create `./secrets/default.nix` with the following content:
|
|||||||
];
|
];
|
||||||
|
|
||||||
# if you changed this key, you need to regenerate all encrypt files from the decrypt contents!
|
# if you changed this key, you need to regenerate all encrypt files from the decrypt contents!
|
||||||
age.identityPaths = [
|
age.identityPaths = [
|
||||||
"/home/ryan/.ssh/juliet-age"
|
# using the host key for decryption
|
||||||
|
# the host key is generated on every host locally by openssh, and will never leave the host.
|
||||||
|
"/etc/ssh/ssh_host_ed25519_key"
|
||||||
];
|
];
|
||||||
|
|
||||||
age.secrets."xxx" = {
|
age.secrets."xxx" = {
|
||||||
@@ -134,16 +145,25 @@ Then, create `./secrets/default.nix` with the following content:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
From now on, every time you run `nixos-rebuild switch`, it will decrypt the secrets using the private keys defined in `age.identityPaths`.
|
From now on, every time you run `nixos-rebuild switch`, it will decrypt the secrets using the private keys defined in `age.identityPaths`.
|
||||||
It will then symlink the secrets to the path defined by the `age.secrets.<name>.path` argument, which defaults to `/etc/secrets`.
|
It will then symlink the secrets to the path defined by the `age.secrets.<name>.path` argument, which defaults to `/etc/secrets`.
|
||||||
|
|
||||||
NOTE: By default, `age.identityPaths` is set to `~/.ssh/id_ed25519` and `~/.ssh/id_rsa`,
|
NOTE: By default, `age.identityPaths` is set to `~/.ssh/id_ed25519` and `~/.ssh/id_rsa`,
|
||||||
so make sure to place your decryption keys there.
|
so make sure to place your decryption keys there.
|
||||||
If you're deploying to the same machine from which you encrypted the secrets, it should work out of the box.
|
If you're deploying to the same machine from which you encrypted the secrets, it should work out of the box.
|
||||||
|
|
||||||
|
## Adding a new host
|
||||||
|
|
||||||
|
1. `cat` the public key of the new host, send it to an old host.
|
||||||
|
2. On the old host:
|
||||||
|
1. Add the public key to `secrets.nix`, and rekey all the secrets via `sudo agenix -r -i /etc/ssh/ssh_host_ed25519_key`.
|
||||||
|
2. Commit and push the changes to `nix-secrets`.
|
||||||
|
3. On the new host:
|
||||||
|
1. Clone this repo and run `nixos-rebuild switch` to deploy it, all the secrets will be decrypted automatically via the host private key.
|
||||||
|
|
||||||
|
|
||||||
## Other Replacements
|
## Other Replacements
|
||||||
|
|
||||||
- [ragenix](https://github.com/yaxitech/ragenix): A Rust reimplementation of agenix.
|
- [ragenix](https://github.com/yaxitech/ragenix): A Rust reimplementation of agenix.
|
||||||
- agenix is mainly written in bash, and it's error message is quite obscure, a little typo may cause some errors no one can understand.
|
- agenix is mainly written in bash, and it's error message is quite obscure, a little typo may cause some errors no one can understand.
|
||||||
- with a type-safe language like Rust, we can get a better error message and less bugs.
|
- with a type-safe language like Rust, we can get a better error message and less bugs.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user