chore(secrets): refresh mysecrets and follow agenix-rules rename

Update the mysecrets lock to 7f93490, which renames secrets.nix to agenix-rules.nix, drops the deprecated ./ key prefixes for agenix 0.18, and re-encrypts the access-token secret. Update the docs and agenix skill to the new filename and path convention.
This commit is contained in:
Ryan Yin committed 2026-10-29 21:28:08 +08:00
1 parent 38d1d85e85
commit 01d2e76410
4 files changed
+39 -36

No files matched your search

+17 -15
View File
@@ -19,7 +19,7 @@ Read [secrets/README.md](../../../secrets/README.md) for the concepts and the re
Two age flows live in `~/codes/nix-secrets`, and a file belongs to exactly one.
- **agenix** (`secrets.nix`): static and one-way, repository → host, decrypted at activation.
- **agenix** (`agenix-rules.nix`): static and one-way, repository → host, decrypted at activation.
Consumed as `/run/agenix/<name>` or an `environment.etc` copy; needs a `flake.lock` bump.
- **dotfiles sync** (`dotfiles/`): changes on the host; `save`/`restore` are manual, outside Nix.
Consumed as a real file under `$HOME`, edited by hand or by its tool; **no** lock bump.
@@ -30,8 +30,8 @@ is a config file its tool keeps rewriting that happens to carry a few secrets in
decides it, not the encryption: `flake.lock` fixes the agenix revision, so every edit costs a
rebuild and switch on every desktop.
Nothing in this flake evaluates the sync flow: no `secrets.nix` entry, no `agenix -r`, no lock bump,
so the three-step order in §2 does not apply to it. Its manifest and file list live in
Nothing in this flake evaluates the sync flow: no `agenix-rules.nix` entry, no `agenix -r`, no lock
bump, so the three-step order in §2 does not apply to it. Its manifest and file list live in
`~/codes/nix-secrets/dotfiles/`; this repository carries the pointer, never the inventory. Do not
list synced paths here or copy one into a Nix module. The flow covers the desktops only; do not set
it up on a server or a cluster node.
@@ -72,14 +72,14 @@ must not get one back.
- Decryption key: `age.identityPaths` — the host's SSH host key; `/persistent/etc/ssh/...` on a
preservation host
- Secret-bearing dotfiles edited in place: `~/codes/nix-secrets/dotfiles/` — private, not a flake
input, no entry in `secrets.nix`
input, no entry in `agenix-rules.nix`
The private repository keeps its `.age` files in `desktop/` (only desktops decrypt them), `server/`
(any server), and `certs/`; `public/` holds publishable plaintext, not `.age`.
## 2. Add or change a secret
Do the mechanical work yourself: edit `secrets.nix` in `~/codes/nix-secrets`, run the
Do the mechanical work yourself: edit `agenix-rules.nix` in `~/codes/nix-secrets`, run the
non-interactive steps, bump the lock, and add the declaration and consumer. For a new secret, or a
full replacement, pipe the plaintext into the `replace` recipe: it removes the target first, so
agenix only encrypts and needs no `sudo`. Hand back only what needs a human: the partial `edit` and
@@ -88,8 +88,8 @@ value, so they handle key material, `$EDITOR`, and `sudo`) and anything else und
and pushes follow the global git rules.
1. In `~/codes/nix-secrets`, add the file under `desktop/` or `server/` with a matching
`secrets.nix` entry, keyed by that exact path (e.g. `"./desktop/xxx.age"`), and the recipient set
from core rule 3. Then encrypt it with the `replace` recipe (§3); ask the user only when the
`agenix-rules.nix` entry, keyed by that exact path (e.g. `"desktop/xxx.age"`), and the recipient
set from core rule 3. Then encrypt it with the `replace` recipe (§3); ask the user only when the
plaintext has to come from an interactive session.
2. Here: `just upp mysecrets` (commits the lock) or `nix flake update mysecrets` (leaves it for you
to commit). `git diff flake.lock` should show only `mysecrets` moving.
@@ -106,18 +106,18 @@ Changing only a secret's value is steps 1, 2, and the deploy: use `replace` for
The agenix operations run against `~/codes/nix-secrets`. Their single source is
[`secrets/Justfile`](../../../secrets/Justfile), which pins the identity, option order, and
`$EDITOR`; run them from this repository's root and keep each path identical to its key in
`secrets.nix`:
`agenix-rules.nix`:
```bash
just -f secrets/Justfile replace ./desktop/xxx.age < plaintext # add or fully replace (no sudo)
just -f secrets/Justfile edit ./desktop/xxx.age # partial edit (sudo, $EDITOR)
just -f secrets/Justfile replace desktop/xxx.age < plaintext # add or fully replace (no sudo)
just -f secrets/Justfile edit desktop/xxx.age # partial edit (sudo, $EDITOR)
just -f secrets/Justfile rekey # re-encrypt after a recipient change
```
`edit` and `rekey` decrypt the current value with the host key, so they need `sudo`; `replace` only
encrypts to the recipients in `secrets.nix`, so it needs no `sudo`. `edit` passes `EDITOR=hx` to the
root `agenix` process, because `sudo` resets the environment and the invoking user's `EDITOR` would
not reach it; do not add `sudo -E` or set `EDITOR` yourself.
encrypts to the recipients in `agenix-rules.nix`, so it needs no `sudo`. `edit` passes `EDITOR=hx`
to the root `agenix` process, because `sudo` resets the environment and the invoking user's `EDITOR`
would not reach it; do not add `sudo -E` or set `EDITOR` yourself.
## 4. Modes and ownership
@@ -152,7 +152,8 @@ you set, an old copy gone) instead of assuming activation did it.
- Delete the `age.secrets` entry, its `environment.etc` placement, and every consumer in one change;
a declaration whose file no longer exists breaks activation. On darwin also drop the path from the
`chown`/`chmod` list in `system.activationScripts.postActivation`.
- Remove it from `secrets.nix` and delete the file in the private repository, then bump the lock.
- Remove it from `agenix-rules.nix` and delete the file in the private repository, then bump the
lock.
- A rename changes the attribute name and every consumer. The `.age` filename is separate.
- Moving a secret **out** of agenix into the sync flow is that deletion plus what agenix used to
guarantee: the consumer points at a `$HOME` path, and on a preservation host the directory joins
@@ -164,7 +165,8 @@ you set, an old copy gone) instead of assuming activation did it.
## 7. Failure modes
- **Decryption fails on one host:** its host key is not a recipient. Add its
`/etc/ssh/ssh_host_ed25519_key.pub` to `secrets.nix`, rekey (§3), push, bump the lock, redeploy.
`/etc/ssh/ssh_host_ed25519_key.pub` to `agenix-rules.nix`, rekey (§3), push, bump the lock,
redeploy.
- **Eval or activation cannot find the file:** the lock still points at a `mysecrets` revision
without it (core rule 2).
- **`permission denied` in a user service:** it reads a root-only secret. Fix that secret's owner;
Generated
+3 -3
View File
@@ -695,10 +695,10 @@
"mysecrets": {
"flake": false,
"locked": {
"lastModified": 1790919428,
"narHash": "sha256-04+A6Hmjj2lXGanEWfqoQkkAGiQgVT0CMY5BTOlfcBo=",
"lastModified": 1793275857,
"narHash": "sha256-Ut8ohwrRRiIsQdWEzVNtysY7g34uzYS/+sWnQK7c3O0=",
"ref": "refs/heads/main",
"rev": "7b78dbb128be0ca52ac2815d5d8a73c5f883dada",
"rev": "7f93490f165543532f34f388f346af91db5715ac",
"shallow": true,
"type": "git",
"url": "ssh://git@github.com/ryan4yin/nix-secrets.git"
+1 -1
View File
@@ -218,7 +218,7 @@ reinstall or a key rotation:
1. `ssh aquamarine cat /etc/ssh/ssh_host_ed25519_key.pub`.
2. Put that key in `vars/networking.nix` under `knownHosts` (the entry was removed with the old key)
and, if this host should read agenix secrets, in `~/codes/nix-secrets/secrets.nix` under
and, if this host should read agenix secrets, in `~/codes/nix-secrets/agenix-rules.nix` under
`application_server_keys`.
3. Rekey and bump the pin: `just -f secrets/Justfile rekey`, push `nix-secrets`, then
`just upp mysecrets` here.
+18 -17
View File
@@ -29,9 +29,10 @@ costs a lock bump plus a rebuild and switch on every host that reads it.
Anything else is a synced dotfile: Nix does not read it, it changes often, or it is a config file
its tool keeps rewriting that happens to carry a few secrets inside. The private repository syncs
those as age ciphertext under `dotfiles/`, by hand and outside Nix, so there is no `secrets.nix`
entry and no lock bump. `nushell-secrets.nu` moved that way and is `~/.secrets/nushell-secrets.nu`
now; do not re-add it to `age.secrets`. The file list stays in the private repository.
those as age ciphertext under `dotfiles/`, by hand and outside Nix, so there is no
`agenix-rules.nix` entry and no lock bump. `nushell-secrets.nu` moved that way and is
`~/.secrets/nushell-secrets.nu` now; do not re-add it to `age.secrets`. The file list stays in the
private repository.
## Which Keys Go on a Secret
@@ -70,13 +71,13 @@ a blanket chown over `/etc/agenix/*` would make the root-only secrets readable b
## Adding or Updating Secrets
> The encrypted `.age` files and `secrets.nix` live in my private `nix-secrets` repository. The
> The encrypted `.age` files and `agenix-rules.nix` live in my private `nix-secrets` repository. The
> `Justfile` referenced below lives in this repository and runs its recipes with `working-directory`
> set to a local `~/codes/nix-secrets` checkout, so invoke it from this repository's root.
This task is accomplished using the [agenix](https://github.com/ryantm/agenix) CLI tool with the
`./secrets.nix` file in the private `nix-secrets` repository, so you need to have it installed
first:
`agenix-rules.nix` file in the private `nix-secrets` repository, so you need to have it installed
first. Rule keys are paths relative to that file and must not start with `./` (agenix 0.18+).
To use agenix temporarily, run:
@@ -93,8 +94,8 @@ nix shell github:ryan4yin/ragenix#ragenix
Suppose you want to add a new secret file `xxx.age`. Follow these steps:
1. Navigate to your private `nix-secrets` repository.
2. Edit `secrets.nix` and add a new entry for `xxx.age`, defining the encryption keys and the secret
file path, for example:
2. Edit `agenix-rules.nix` and add a new entry for `xxx.age`, defining the encryption keys and the
secret file path, for example:
```nix
# This file is not imported into your NixOS configuration. It is only used for the agenix CLI.
@@ -121,7 +122,7 @@ let
hosts = [ ];
in
{
"./xxx.age".publicKeys = desktop_keys ++ hosts;
"xxx.age".publicKeys = desktop_keys ++ hosts;
}
```
@@ -129,20 +130,20 @@ in
`replace` recipe, piping the plaintext on stdin:
```shell
just -f secrets/Justfile replace ./xxx.age < plaintext
just -f secrets/Justfile replace xxx.age < plaintext
```
`replace` deletes the target first, so agenix only encrypts to the public keys in `secrets.nix` and
never decrypts the old value — it needs no `sudo`. Use `edit` instead for a partial change to an
`replace` deletes the target first, so agenix only encrypts to the public keys in `agenix-rules.nix`
and never decrypts the old value — it needs no `sudo`. Use `edit` instead for a partial change to an
existing secret: it decrypts the current value first with the host key
(`/etc/ssh/ssh_host_ed25519_key`), so it needs `sudo`.
```shell
just -f secrets/Justfile edit ./xxx.age
just -f secrets/Justfile edit xxx.age
```
`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.
`agenix` will encrypt the file with all the public keys we defined in `agenix-rules.nix`, so all the
users and systems defined in `agenix-rules.nix` can decrypt it with their private keys.
After pushing, run `just upp mysecrets` in this repository: `flake.lock` pins `mysecrets`, so a new
or changed file is invisible here until the lock moves. The repo-side steps are in
@@ -219,7 +220,7 @@ Then, create `./secrets/nixos.nix` (or `./secrets/darwin.nix` on macOS) with the
# target path for decrypted file
path = "/etc/xxx";
# encrypted file path
file = "${mysecrets}/xxx.age"; # refer to ./xxx.age located in `mysecrets` repo
file = "${mysecrets}/xxx.age"; # refer to xxx.age located in `mysecrets` repo
mode = "0400";
owner = "root";
group = "root";
@@ -236,7 +237,7 @@ the `age.secrets.<name>.path` argument, which defaults to `/run/agenix/<name>`.
1. `cat` the system-level public key(`/etc/ssh/ssh_host_ed25519_key.pub`) of the new host, and send
it to an old host which has already been configured.
2. On the old host:
1. Add the public key to `secrets.nix`, then rekey all the secrets:
1. Add the public key to `agenix-rules.nix`, then rekey all the secrets:
`just -f secrets/Justfile rekey`.
2. Commit and push the changes to `nix-secrets`.
3. On the new host: