-
Notifications
You must be signed in to change notification settings - Fork 0
feat(agenix): configure SSH key sync from galactica to kyber #412
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b8b7f47
a9b8bb3
9f9908b
65940e8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,23 @@ | ||
| let | ||
| # Galactica's SSH public key | ||
| galactica = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEKze2jlpV7SyTKA2ezqbumpCiDn+5Sj4z5SxrqfzesX shunkakinoki@gmail.com"; | ||
| # Kyber's SSH public key | ||
| kyber = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO0IZtP3KSzY6GVSZ+R+VQYYfu3sEOVaQGDblQxAtwNM ubuntu@kyber"; | ||
| # All machines that can decrypt shared secrets | ||
| allMachines = [ | ||
| galactica | ||
| kyber | ||
| ]; | ||
| in | ||
| { | ||
| # Shared SSH key for GitHub authentication (accessible on all machines) | ||
| "keys/id_ed25519.age" = { | ||
| file = ./keys/id_ed25519.age; | ||
| publicKeys = [ | ||
| "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEKze2jlpV7SyTKA2ezqbumpCiDn+5Sj4z5SxrqfzesX shunkakinoki@gmail.com" | ||
| ]; | ||
| publicKeys = allMachines; | ||
| }; | ||
| # GPG key (galactica only) | ||
| "keys/gpg.age" = { | ||
| file = ./keys/gpg.age; | ||
| publicKeys = [ | ||
| "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEKze2jlpV7SyTKA2ezqbumpCiDn+5Sj4z5SxrqfzesX shunkakinoki@gmail.com" | ||
| ]; | ||
| publicKeys = [ galactica ]; | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,7 +45,22 @@ home-manager.lib.homeManagerConfiguration { | |
|
|
||
| # Agenix configuration | ||
| age.identityPaths = [ "/home/${username}/.ssh/id_ed25519" ]; | ||
| age.secrets = builtins.mapAttrs (name: value: { file = value.file; }) (import ./secrets.nix); | ||
| age.secrets = builtins.mapAttrs ( | ||
| name: value: | ||
| { | ||
| file = value.file; | ||
| # Deploy GitHub SSH key to ~/.ssh/ with correct permissions | ||
| } | ||
| // ( | ||
| if name == "keys/id_ed25519.age" then | ||
| { | ||
| path = "/home/${username}/.ssh/id_ed25519_github"; | ||
| mode = "0600"; | ||
| } | ||
| else | ||
| { } | ||
| ) | ||
| ) (import ./secrets.nix); | ||
|
Comment on lines
+48
to
+63
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This logic for conditionally setting the path and mode for the GitHub SSH key can be simplified using The comment explaining the deployment of the SSH key is also better placed next to the conditional logic. |
||
|
|
||
| programs.home-manager.enable = true; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,38 @@ | ||||||
| #!/usr/bin/env bash | ||||||
| # Remotely rekey galactica secrets to include kyber's public key | ||||||
| # This script should be run from kyber to trigger the rekey on galactica | ||||||
|
|
||||||
| set -e | ||||||
|
||||||
| set -e | |
| set -euo pipefail |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P1: The success path is missing git commit and push operations on galactica. After make rekey-galactica completes successfully, the re-encrypted secrets need to be committed and pushed before git pull on kyber can receive them. Currently, git pull will fetch nothing because galactica never pushed the changes.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At named-hosts/kyber/rekey-galactica.sh, line 16:
<comment>The success path is missing git commit and push operations on galactica. After `make rekey-galactica` completes successfully, the re-encrypted secrets need to be committed and pushed before `git pull` on kyber can receive them. Currently, `git pull` will fetch nothing because galactica never pushed the changes.</comment>
<file context>
@@ -0,0 +1,38 @@
+echo ""
+
+# Try Tailscale SSH first
+if tailscale ssh shunkakinoki@galactica "cd ~/dotfiles && make rekey-galactica" 2>/dev/null; then
+ echo "✅ Rekey completed via Tailscale SSH"
+else
</file context>
Copilot
AI
Dec 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The stderr redirection to /dev/null can hide important error messages. If the Tailscale SSH connection fails, the user won't see the actual error message that could help diagnose the issue. Consider either:
- Capturing and displaying the error message on failure
- Removing the redirection to let errors flow naturally to the user
The fallback error handling already provides instructions, but seeing the actual Tailscale error would be more helpful for debugging.
| if tailscale ssh shunkakinoki@galactica "cd ~/dotfiles && make rekey-galactica" 2>/dev/null; then | |
| if tailscale ssh shunkakinoki@galactica "cd ~/dotfiles && make rekey-galactica"; then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
git ls-files | grep -E "rekey-galactica|Makefile"Repository: shunkakinoki/dotfiles
Length of output: 110
🏁 Script executed:
cat -n named-hosts/kyber/rekey-galactica.shRepository: shunkakinoki/dotfiles
Length of output: 1378
🏁 Script executed:
grep -A 20 "rekey-galactica" MakefileRepository: shunkakinoki/dotfiles
Length of output: 975
🏁 Script executed:
grep -B 5 -A 15 "^rekey:" MakefileRepository: shunkakinoki/dotfiles
Length of output: 743
Script safety and workflow mismatch: banner claims commit/push but remote command only re-encrypts
The banner (line 12) states the script will "Commit and push the changes", but the remote command (line 16) only runs make rekey-galactica, which executes agenix --rekey without committing or pushing. The manual fallback (lines 21–26) explicitly shows git add/commit/push steps, confirming these are not handled automatically. This messaging mismatch creates confusion about whether changes will be persisted to the repository.
Additionally, follow shellcheck-style safety defaults: use set -euo pipefail instead of set -e, remove stderr silencing (2>/dev/null) so failures are debuggable, and add prerequisite checks for tailscale and git.
-#!/usr/bin/env bash
+#!/usr/bin/env bash
# Remotely rekey galactica secrets to include kyber's public key
# This script should be run from kyber to trigger the rekey on galactica
-set -e
+set -euo pipefail
+
+command -v tailscale >/dev/null || { echo "tailscale is required"; exit 1; }
+command -v git >/dev/null || { echo "git is required"; exit 1; }
echo "🔑 Rekeying galactica secrets to include kyber..."
echo ""
echo "This will:"
echo "1. Connect to galactica via Tailscale SSH"
echo "2. Run the rekey command to re-encrypt secrets with both keys"
-echo "3. Commit and push the changes"
+echo "3. (If needed) commit and push the changes from galactica"
echo ""
# Try Tailscale SSH first
-if tailscale ssh shunkakinoki@galactica "cd ~/dotfiles && make rekey-galactica" 2>/dev/null; then
+if tailscale ssh shunkakinoki@galactica "cd ~/dotfiles && make rekey-galactica"; then
echo "✅ Rekey completed via Tailscale SSH"
else
echo "❌ Tailscale SSH failed. Please run this manually on galactica:"🤖 Prompt for AI Agents
In named-hosts/kyber/rekey-galactica.sh around lines 1 to 38, the banner claims
it will "Commit and push the changes" but the remote command only runs make
rekey-galactica (which re-encrypts but does not git add/commit/push), and the
script uses unsafe shell settings and silences stderr; update the script to
either (A) make the banner accurate (remove commit/push claim) or (B) perform
the git add/commit/push on the remote after rekey (e.g., run a remote sequence
that runs make rekey-galactica && git add ... && git commit -m ... && git push),
remove the stderr redirection (do not use 2>/dev/null), replace set -e with set
-euo pipefail, and add prerequisite checks at the top to ensure tailscale and
git are available before attempting the SSH/pull steps.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,21 +2,27 @@ | |
| # To add a new secret: | ||
| # 1. Add the secret definition here | ||
| # 2. Run: make encrypt-key-kyber KEY_FILE=/path/to/secret | ||
| let | ||
| # Galactica's SSH public key | ||
| galactica = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEKze2jlpV7SyTKA2ezqbumpCiDn+5Sj4z5SxrqfzesX shunkakinoki@gmail.com"; | ||
| # Kyber's SSH public key | ||
| kyber = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO0IZtP3KSzY6GVSZ+R+VQYYfu3sEOVaQGDblQxAtwNM ubuntu@kyber"; | ||
| # All machines that can decrypt shared secrets | ||
| allMachines = [ | ||
| galactica | ||
| kyber | ||
| ]; | ||
| in | ||
|
Comment on lines
+5
to
+15
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This For example, you could create a # named-hosts/public-keys.nix
{
galactica = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEKze2jlpV7SyTKA2ezqbumpCiDn+5Sj4z5SxrqfzesX shunkakinoki@gmail.com";
kyber = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO0IZtP3KSzY6GVSZ+R+VQYYfu3sEOVaQGDblQxAtwNM ubuntu@kyber";
}Then, you could import it in both # named-hosts/kyber/secrets.nix
let
keys = import ../public-keys.nix;
allMachines = with keys; [ galactica kyber ];
in {
...
"keys/tailscale-auth.age".publicKeys = [ keys.kyber ];
"keys/id_ed25519.age".publicKeys = allMachines;
} |
||
| { | ||
| # Tailscale auth key - generate from https://login.tailscale.com/admin/settings/keys | ||
| # "keys/tailscale-auth.age" = { | ||
| # file = ./keys/tailscale-auth.age; | ||
| # publicKeys = [ | ||
| # # Kyber's SSH public key (run: ssh ubuntu@kyber "cat ~/.ssh/id_ed25519.pub") | ||
| # "ssh-ed25519 AAAA..." | ||
| # ]; | ||
| # }; | ||
| "keys/tailscale-auth.age" = { | ||
| file = ./keys/tailscale-auth.age; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: This secret references a non-existent file Prompt for AI agents |
||
| publicKeys = [ kyber ]; | ||
| }; | ||
|
|
||
| # SSH key sync (your local key encrypted for kyber) | ||
| # "keys/id_ed25519.age" = { | ||
| # file = ./keys/id_ed25519.age; | ||
| # publicKeys = [ | ||
| # "ssh-ed25519 AAAA..." | ||
| # ]; | ||
| # }; | ||
| # Shared SSH key for GitHub authentication (synced from galactica) | ||
| "keys/id_ed25519.age" = { | ||
| file = ../galactica/keys/id_ed25519.age; | ||
| publicKeys = allMachines; | ||
| }; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This
letblock defining public keys is also present innamed-hosts/kyber/secrets.nix. To improve maintainability and avoid having to update keys in multiple places, consider moving the public key definitions to a shared file (e.g.,named-hosts/public-keys.nix) and importing it where needed.