Skip to content

feat(agenix): configure SSH key sync from galactica to kyber - #412

Merged
shunkakinoki merged 4 commits into
mainfrom
feat/kyber-ssh-sync
Dec 13, 2025
Merged

feat(agenix): configure SSH key sync from galactica to kyber#412
shunkakinoki merged 4 commits into
mainfrom
feat/kyber-ssh-sync

Conversation

@shunkakinoki

@shunkakinoki shunkakinoki commented Dec 13, 2025

Copy link
Copy Markdown
Owner

Summary

  • Configure agenix to sync GitHub SSH key from galactica to kyber
  • Enable post-quantum SSH algorithms (sntrup761x25519-sha512@openssh.com)
  • Add kyber's public key to galactica secrets for shared key access

Changes

  • Galactica secrets: Added kyber's public key to allow decryption on both machines
  • Kyber configuration: Configured to decrypt and deploy GitHub SSH key to ~/.ssh/id_ed25519_github
  • SSH config: Updated to use synced GitHub key for github.com with post-quantum key exchange
  • Documentation: Added helper script and instructions in kyber README

Next Steps

After merging, run on galactica:

cd ~/dotfiles
git pull
make rekey-galactica
git add named-hosts/galactica/keys/
git commit -m "chore(agenix): rekey secrets for kyber access"
git push

Then on kyber:

cd ~/dotfiles
git pull
make switch
ssh -T git@github.com  # Test GitHub access

🤖 Generated with Claude Code


Summary by cubic

Set up agenix to sync the GitHub SSH key from galactica to kyber and use it for github.com. Also enables post‑quantum key exchange and adds a helper script to automate rekeying.

  • New Features

    • Share keys/id_ed25519.age between galactica and kyber by adding kyber’s public key.
    • Deploy the GitHub key on kyber to ~/.ssh/id_ed25519_github with 0600.
    • Update SSH config for github.com to use the synced key.
    • Enable modern algorithms, including sntrup761x25519-sha512@openssh.com.
    • Add rekey-galactica.sh and README instructions for one‑command rekeying.
  • Migration

Written for commit 65940e8. Summary will update automatically on new commits.

shunkakinoki and others added 2 commits December 13, 2025 03:55
- Add kyber's public key to galactica secrets for shared key access
- Configure kyber to decrypt and deploy GitHub SSH key to ~/.ssh/id_ed25519_github
- Update SSH config to use synced GitHub key for github.com
- Enable post-quantum SSH algorithms (sntrup761x25519-sha512@openssh.com)
- Modernize host key and public key algorithm preferences

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add rekey-galactica.sh script to automate remote rekeying
- Document SSH key sync process in kyber README
- Provide clear instructions for both galactica and kyber sides

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings December 13, 2025 04:06
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Dec 13, 2025

Copy link
Copy Markdown

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Adds post‑quantum KEX to system SSH config, introduces shared public‑key variables and moves GitHub key deployment into host secrets, and adds a rekeying automation script plus documentation to sync Galactica ↔ Kyber secrets.

Changes

Cohort / File(s) Change Summary
SSH configuration
home-manager/programs/ssh/default.nix
Adds sntrup761x25519-sha512@openssh.com to KexAlgorithms; reasserts HostKeyAlgorithms and PubkeyAcceptedAlgorithms; adds host-specific IdentityFile for ~/.ssh/id_ed25519_github
Galactica secrets
named-hosts/galactica/secrets.nix
Introduces let-bound galactica, kyber, and allMachines public-key bindings; replaces hardcoded publicKeys with these variables for keys/id_ed25519.age and keys/gpg.age
Kyber secrets & deployment
named-hosts/kyber/secrets.nix, named-hosts/kyber/default.nix
Adds top-level galactica/kyber bindings and uses allMachines; age.secrets mapping now conditionally sets path = "/home/${username}/.ssh/id_ed25519_github" and mode = "0600" for keys/id_ed25519.age
Kyber automation & docs
named-hosts/kyber/rekey-galactica.sh, named-hosts/kyber/README.md
Adds rekey-galactica.sh to attempt remote rekey via Tailscale SSH with fallback manual instructions; documents the sync workflow and where the GitHub key is deployed

Sequence Diagram

sequenceDiagram
    participant User
    participant Kyber
    participant Galactica
    participant Git
    User->>Kyber: run rekey-galactica.sh
    Kyber->>Galactica: ssh (Tailscale) -> cd ~/dotfiles && make rekey-galactica
    alt remote rekey succeeds
        Galactica->>Git: commit & push re-encrypted secrets
        Kyber->>Git: git pull -> fetch updated secrets
        Git-->>Kyber: updated secrets
        Kyber->>User: prompt to run make switch
    else remote rekey fails
        Kyber-->>User: show manual rekey instructions
        User->>Galactica: run commands locally (cd ~/dotfiles && make rekey-galactica)
        Galactica->>Git: commit & push
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify conditional mapAttrs in named-hosts/kyber/default.nix correctly sets path and mode.
  • Confirm named-hosts/galactica/secrets.nix and named-hosts/kyber/secrets.nix use consistent public-key variables.
  • Inspect rekey-galactica.sh for robust error handling and safe git/ssh behavior.
  • Validate SSH algorithm additions in home-manager/programs/ssh/default.nix for compatibility with other hosts.

Possibly related PRs

  • fix switch #404 — touches the same host-specific key deployment, agenix secrets, and Kyber/Galactica sync workflows.

Poem

🐰 I hopped from Galactica to Kyber's door,
I carried keys in paw and asked for more,
Git pushed a secret, Tailscale sang along,
Ed25519 hums, PQ KEX grows strong —
Hop, rekey, deploy, and then restore.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately describes the primary change: configuring SSH key synchronization from galactica to kyber using agenix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The pull request description clearly outlines the changes made: configuring agenix for SSH key synchronization, enabling post-quantum algorithms, and adding kyber's public key to galactica secrets. The description is directly related to the changeset across all modified files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/kyber-ssh-sync

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @shunkakinoki, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request establishes a secure and automated mechanism for synchronizing a GitHub SSH key between 'galactica' and 'kyber' using agenix for secret management. It significantly boosts the security posture by integrating post-quantum SSH algorithms and streamlines the key deployment process on 'kyber'. The changes aim to provide seamless and secure GitHub access from 'kyber' while maintaining a centralized, encrypted key store on 'galactica'.

Highlights

  • SSH Key Synchronization: Configured agenix to securely sync the GitHub SSH key from the 'galactica' machine to 'kyber', ensuring 'kyber' can decrypt and utilize the shared key for GitHub authentication.
  • Post-Quantum SSH Algorithms: Enabled the 'sntrup761x25519-sha512@openssh.com' post-quantum key exchange algorithm, along with other modern host key and public key algorithms, in the SSH configuration for enhanced future-proof security.
  • Shared Secret Access: Updated 'galactica's secrets definition to include 'kyber's public key, allowing both machines to decrypt the shared GitHub SSH key. The GPG key remains exclusive to 'galactica'.
  • Automated Rekeying Script: Introduced a new helper script, 'rekey-galactica.sh', on 'kyber' to automate the process of remotely rekeying 'galactica's secrets via Tailscale SSH, simplifying the secret management workflow.
  • Documentation and Configuration: Added detailed instructions to 'kyber's README for syncing SSH keys and updated 'kyber's agenix configuration to deploy the GitHub SSH key to '~/.ssh/id_ed25519_github' with correct permissions.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@mesa-dot-dev

mesa-dot-dev Bot commented Dec 13, 2025

Copy link
Copy Markdown

You do not have enough credits to review this pull request. Please purchase more credits to continue.

@mesa-dot-dev

mesa-dot-dev Bot commented Dec 13, 2025

Copy link
Copy Markdown

Mesa Description

TL;DR

Configure agenix to sync GitHub SSH key from galactica to kyber, enable post-quantum SSH algorithms, and add kyber's public key to galactica secrets for shared key access.

What changed?

  • home-manager/programs/ssh/default.nix: Updated SSH configuration to include post-quantum key exchange algorithms and prioritize modern host/public key algorithms, with a specific identity file for GitHub.
  • named-hosts/galactica/secrets.nix: Added Kyber's SSH public key to allMachines list, allowing both Galactica and Kyber to decrypt keys/id_ed25519.age.
  • named-hosts/kyber/README.md: Updated with instructions for syncing SSH keys from Galactica and verifying GitHub access.
  • named-hosts/kyber/default.nix: Configured deployment of keys/id_ed25519.age (GitHub SSH key) to ~/.ssh/id_ed25519_github with 0600 permissions on Kyber.
  • named-hosts/kyber/rekey-galactica.sh: New script to automate rekeying secrets on Galactica to include Kyber's public key, with manual fallback and post-rekey instructions.
  • named-hosts/kyber/secrets.nix: Refactored to use let bindings for SSH public keys and allMachines array. Activated tailscale-auth.age for Kyber and updated id_ed25519.age to be decryptable by both Galactica and Kyber.

Description generated by Mesa. Update settings

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request configures agenix to sync an SSH key between two hosts, galactica and kyber, and enables post-quantum cryptography for SSH. The changes are well-structured and the documentation updates are clear. My review includes a few suggestions to improve the maintainability of the Nix code by reducing duplication and using more idiomatic expressions. Specifically, I've recommended centralizing the public key definitions and simplifying conditional attribute sets in the agenix configuration.

Comment on lines +1 to +8
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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This let block defining public keys is also present in named-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.

Comment on lines +48 to +61
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);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This logic for conditionally setting the path and mode for the GitHub SSH key can be simplified using lib.optionalAttrs from nixpkgs.lib. This makes the code more concise and idiomatic.

The comment explaining the deployment of the SSH key is also better placed next to the conditional logic.

      age.secrets = builtins.mapAttrs (
        name: value: { file = value.file; } //
          # Deploy GitHub SSH key to ~/.ssh/ with correct permissions
          (lib.optionalAttrs (name == "keys/id_ed25519.age") {
            path = "/home/${username}/.ssh/id_ed25519_github";
            mode = "0600";
          })
      ) (import ./secrets.nix);

Comment on lines +5 to +12
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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This let block defining public keys is duplicated in named-hosts/galactica/secrets.nix. To improve maintainability and avoid having to update keys in multiple places, consider moving the public key definitions to a shared file.

For example, you could create a named-hosts/public-keys.nix file:

# 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 secrets.nix files:

# 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;
}

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 6 files

Prompt for AI agents (all 2 issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="named-hosts/kyber/secrets.nix">

<violation number="1" location="named-hosts/kyber/secrets.nix:16">
P1: This secret references a non-existent file `./keys/tailscale-auth.age`. The `keys/` directory doesn&#39;t exist under `named-hosts/kyber/`, which will cause Nix evaluation to fail. Either create the directory and encrypted file first, or keep this configuration commented out until the file exists.</violation>
</file>

<file name="named-hosts/kyber/rekey-galactica.sh">

<violation number="1" location="named-hosts/kyber/rekey-galactica.sh:16">
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.</violation>
</file>

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

# ];
# };
"keys/tailscale-auth.age" = {
file = ./keys/tailscale-auth.age;

@cubic-dev-ai cubic-dev-ai Bot Dec 13, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: This secret references a non-existent file ./keys/tailscale-auth.age. The keys/ directory doesn't exist under named-hosts/kyber/, which will cause Nix evaluation to fail. Either create the directory and encrypted file first, or keep this configuration commented out until the file exists.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At named-hosts/kyber/secrets.nix, line 16:

<comment>This secret references a non-existent file `./keys/tailscale-auth.age`. The `keys/` directory doesn&#39;t exist under `named-hosts/kyber/`, which will cause Nix evaluation to fail. Either create the directory and encrypted file first, or keep this configuration commented out until the file exists.</comment>

<file context>
@@ -2,21 +2,24 @@
-  #   ];
-  # };
+  &quot;keys/tailscale-auth.age&quot; = {
+    file = ./keys/tailscale-auth.age;
+    publicKeys = [ kyber ];
+  };
</file context>
Fix with Cubic

echo ""

# Try Tailscale SSH first
if tailscale ssh shunkakinoki@galactica "cd ~/dotfiles && make rekey-galactica" 2>/dev/null; then

@cubic-dev-ai cubic-dev-ai Bot Dec 13, 2025

Copy link
Copy Markdown
Contributor

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 &quot;&quot;
+
+# Try Tailscale SSH first
+if tailscale ssh shunkakinoki@galactica &quot;cd ~/dotfiles &amp;&amp; make rekey-galactica&quot; 2&gt;/dev/null; then
+  echo &quot;✅ Rekey completed via Tailscale SSH&quot;
+else
</file context>
Fix with Cubic

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
home-manager/programs/ssh/default.nix (2)

23-30: Avoid globally overriding SSH algorithm lists; prefer appending to defaults
Hard-setting KexAlgorithms / HostKeyAlgorithms / PubkeyAcceptedAlgorithms under "*" can unexpectedly break connectivity (and may not be supported on older OpenSSH builds). I’d append the PQ KEX and leave the rest as defaults unless you have a compatibility matrix for all hosts.

 extraOptions = {
   IgnoreUnknown = "UseKeychain";
   UseKeyChain = "yes";
-  # Enable post-quantum key exchange algorithms
-  # sntrup761x25519 is a hybrid post-quantum algorithm combining
-  # Streamlined NTRU Prime (sntrup761) with X25519
-  KexAlgorithms = "sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256";
-  # Prefer modern host key algorithms
-  HostKeyAlgorithms = "ssh-ed25519-cert-v01@openssh.com,ssh-ed25519,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-256";
-  # Prefer modern public key algorithms
-  PubkeyAcceptedAlgorithms = "ssh-ed25519-cert-v01@openssh.com,ssh-ed25519,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-256";
+  # Enable post-quantum key exchange (append to OpenSSH defaults)
+  KexAlgorithms = "+sntrup761x25519-sha512@openssh.com";
 };

39-46: Pin GitHub to the intended key (avoid offering other identities)
Consider setting identitiesOnly = true for github.com so SSH doesn’t try other keys and trigger “too many authentication failures”.

 "github.com" = {
   serverAliveInterval = 0;
   identityFile = "~/.ssh/id_ed25519_github";
+  identitiesOnly = true;
   extraOptions = {
     ControlMaster = "auto";
     ControlPath = "~/.ssh/github.sock";
     ControlPersist = "3m";
   };
 };
named-hosts/kyber/README.md (1)

52-78: Docs: consider referencing the helper script to reduce manual steps
Since named-hosts/kyber/rekey-galactica.sh was added, it may be worth adding an “Option A: run the script” path (and keep current manual steps as fallback) so the README stays in sync with the intended workflow. Based on learnings, document major changes in Nix configurations and workflows.

named-hosts/kyber/secrets.nix (1)

5-24: Reduce duplicated SSH public-key literals (and avoid ultra-long Nix lines)
Both named-hosts/kyber/secrets.nix and named-hosts/galactica/secrets.nix embed the same public keys. Consider sourcing them from checked-in *.pub files via builtins.readFile (or centralizing in a shared Nix module) to avoid drift and keep the Nix formatting/line-length rules practical. Based on coding guidelines, keep Nix files formatted and documented.

named-hosts/galactica/secrets.nix (1)

1-19: Nice: centralizing allMachines improves clarity; consider de-duplicating pubkey literals
The allMachines refactor is clean and makes intent obvious. Only suggestion: source the public keys from *.pub files (or a shared module) to avoid duplication with named-hosts/kyber/secrets.nix and reduce giant string lines. Based on learnings, documenting major Nix changes is good here.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4889969 and a9b8bb3.

📒 Files selected for processing (6)
  • home-manager/programs/ssh/default.nix (2 hunks)
  • named-hosts/galactica/secrets.nix (1 hunks)
  • named-hosts/kyber/README.md (1 hunks)
  • named-hosts/kyber/default.nix (1 hunks)
  • named-hosts/kyber/rekey-galactica.sh (1 hunks)
  • named-hosts/kyber/secrets.nix (1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{js,jsx,ts,tsx,json,jsonc,md}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Use Biome for code formatting as configured in biome.json

Files:

  • named-hosts/kyber/README.md
**/*.{sh,bash}

📄 CodeRabbit inference engine (CLAUDE.md)

Use shfmt with 2-space indentation for shell scripts

**/*.{sh,bash}: Use 2 spaces for indentation in shell scripts
Add proper shebang lines to shell scripts
Follow shellcheck recommendations in shell scripts
Document complex commands in shell scripts
Use consistent variable naming in shell scripts

Files:

  • named-hosts/kyber/rekey-galactica.sh
**/*.nix

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.nix: Use nixfmt for formatting all Nix files
Document complex configurations with comments in Nix files

**/*.nix: Use 2 spaces for indentation in Nix files
Keep line length under 100 characters in Nix files
Sort attribute sets alphabetically in Nix files
Use consistent spacing around operators in Nix files
Format lists and sets consistently in Nix files

Use treefmt.toml for formatting Nix files

**/*.nix: Use mkOption for configurable options in Nix modules
Implement proper typing for all options in Nix modules
Follow the Nix expression language style guide

Files:

  • home-manager/programs/ssh/default.nix
  • named-hosts/kyber/default.nix
  • named-hosts/kyber/secrets.nix
  • named-hosts/galactica/secrets.nix
**/default.nix

📄 CodeRabbit inference engine (CLAUDE.md)

Use default.nix files for module exports

Files:

  • home-manager/programs/ssh/default.nix
  • named-hosts/kyber/default.nix
home-manager/programs/*/default.nix

📄 CodeRabbit inference engine (.cursor/rules/home-manager.mdc)

Program configurations should be located in home-manager/programs/<name>/ and use home-manager's built-in modules when available

Files:

  • home-manager/programs/ssh/default.nix
home-manager/programs/**/default.nix

📄 CodeRabbit inference engine (.cursor/rules/home-manager.mdc)

Program configurations must include all necessary dependencies in their configuration

Files:

  • home-manager/programs/ssh/default.nix
home-manager/**/*.nix

📄 CodeRabbit inference engine (.cursor/rules/home-manager.mdc)

home-manager/**/*.nix: Use typed options whenever possible in Nix configurations
Document all configuration options in Nix modules and programs
Follow home-manager's module structure and keep configurations modular
Use proper indentation and formatting in Nix configuration files

Files:

  • home-manager/programs/ssh/default.nix
home-manager/programs/**/*.nix

📄 CodeRabbit inference engine (.cursor/rules/home-manager.mdc)

Follow program-specific best practices in program configuration files

Program configurations in home-manager/programs/ should be organized by program name, include all necessary dependencies, use home.packages for package installations, and use programs.<name> when available in home-manager

Files:

  • home-manager/programs/ssh/default.nix
🧠 Learnings (12)
📚 Learning: 2025-11-25T09:34:40.062Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/general.mdc:0-0
Timestamp: 2025-11-25T09:34:40.062Z
Learning: Document all major changes in Nix configurations

Applied to files:

  • home-manager/programs/ssh/default.nix
  • named-hosts/kyber/default.nix
  • named-hosts/kyber/secrets.nix
📚 Learning: 2025-11-25T09:34:55.014Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/home-manager.mdc:0-0
Timestamp: 2025-11-25T09:34:55.014Z
Learning: Applies to home-manager/**/*.nix : Document all configuration options in Nix modules and programs

Applied to files:

  • home-manager/programs/ssh/default.nix
  • named-hosts/kyber/default.nix
📚 Learning: 2025-11-25T09:34:55.014Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/home-manager.mdc:0-0
Timestamp: 2025-11-25T09:34:55.014Z
Learning: Applies to home-manager/programs/**/*.nix : Follow program-specific best practices in program configuration files

Applied to files:

  • home-manager/programs/ssh/default.nix
  • named-hosts/kyber/default.nix
📚 Learning: 2025-11-25T09:35:01.066Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/nix.mdc:0-0
Timestamp: 2025-11-25T09:35:01.066Z
Learning: Applies to home-manager/modules/**/*.nix : Document all custom modules and options

Applied to files:

  • home-manager/programs/ssh/default.nix
  • named-hosts/kyber/default.nix
📚 Learning: 2025-11-25T09:34:40.062Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/general.mdc:0-0
Timestamp: 2025-11-25T09:34:40.062Z
Learning: Keep configurations modular across home-manager, hosts, and nix-darwin directories

Applied to files:

  • home-manager/programs/ssh/default.nix
  • named-hosts/kyber/default.nix
📚 Learning: 2025-11-25T09:34:55.014Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/home-manager.mdc:0-0
Timestamp: 2025-11-25T09:34:55.014Z
Learning: Applies to home-manager/**/*.nix : Use proper indentation and formatting in Nix configuration files

Applied to files:

  • home-manager/programs/ssh/default.nix
  • named-hosts/kyber/default.nix
📚 Learning: 2025-11-25T09:34:55.014Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/home-manager.mdc:0-0
Timestamp: 2025-11-25T09:34:55.014Z
Learning: Applies to home-manager/**/*.nix : Follow home-manager's module structure and keep configurations modular

Applied to files:

  • home-manager/programs/ssh/default.nix
  • named-hosts/kyber/default.nix
📚 Learning: 2025-11-25T09:34:55.014Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/home-manager.mdc:0-0
Timestamp: 2025-11-25T09:34:55.014Z
Learning: Applies to home-manager/services/**/default.nix : Service configurations must include proper service definitions, handle dependencies correctly, and document service parameters

Applied to files:

  • home-manager/programs/ssh/default.nix
📚 Learning: 2025-11-25T09:35:01.066Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/nix.mdc:0-0
Timestamp: 2025-11-25T09:35:01.066Z
Learning: Applies to home-manager/programs/**/*.nix : Program configurations in `home-manager/programs/` should be organized by program name, include all necessary dependencies, use `home.packages` for package installations, and use `programs.<name>` when available in home-manager

Applied to files:

  • named-hosts/kyber/default.nix
📚 Learning: 2025-11-25T09:34:55.014Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/home-manager.mdc:0-0
Timestamp: 2025-11-25T09:34:55.014Z
Learning: Applies to home-manager/programs/*/default.nix : Program configurations should be located in `home-manager/programs/<name>/` and use home-manager's built-in modules when available

Applied to files:

  • named-hosts/kyber/default.nix
📚 Learning: 2025-11-25T09:35:01.066Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/nix.mdc:0-0
Timestamp: 2025-11-25T09:35:01.066Z
Learning: Test configurations before committing using `nix flake check` and `home-manager build --show-trace`

Applied to files:

  • named-hosts/kyber/default.nix
📚 Learning: 2025-11-25T09:34:55.014Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/home-manager.mdc:0-0
Timestamp: 2025-11-25T09:34:55.014Z
Learning: Applies to home-manager/programs/**/default.nix : Program configurations must include all necessary dependencies in their configuration

Applied to files:

  • named-hosts/kyber/default.nix
🪛 LanguageTool
named-hosts/kyber/README.md

[uncategorized] ~78-~78: The official name of this software platform is spelled with a capital “H”.
Context: ...automatically decrypted and deployed to ~/.ssh/id_ed25519_github.

(GITHUB)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (15)
  • GitHub Check: Agent
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: e2e-run (Ubuntu, ubuntu-latest)
  • GitHub Check: e2e-run (NixOS, ubuntu-latest)
  • GitHub Check: e2e-run (MacOS, macos-latest)
  • GitHub Check: lua-hammerspoon
  • GitHub Check: lua-neovim
  • GitHub Check: lua-neovim-test
  • GitHub Check: docker-build-push (linux/amd64, amd64, ubuntu-latest)
  • GitHub Check: docker-build-push (linux/arm64, arm64, ubuntu-24.04-arm)
  • GitHub Check: nix-darwin
  • GitHub Check: nix-nixos
  • GitHub Check: nix-linux
  • GitHub Check: shellcheck
  • GitHub Check: shellspec
🔇 Additional comments (1)
named-hosts/kyber/default.nix (1)

48-61: Per-secret path/mode override looks right; please verify final ownership + perms
The conditional override for keys/id_ed25519.age is a good fit. I’d just verify after make switch that ~/.ssh/id_ed25519_github is owned by ${username} and is 0600 (and that other secrets didn’t change modes unexpectedly). As per learnings, testing configs before committing is recommended.

Comment on lines +1 to +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

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 ""

# 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
echo "❌ Tailscale SSH failed. Please run this manually on galactica:"
echo ""
echo " cd ~/dotfiles"
echo " git pull"
echo " make rekey-galactica"
echo " git add named-hosts/galactica/keys/"
echo " git commit -m 'chore(agenix): rekey secrets for kyber access'"
echo " git push"
echo ""
exit 1
fi

# Pull the changes
echo ""
echo "📥 Pulling re-encrypted secrets..."
cd ~/dotfiles
git pull

echo ""
echo "✅ Done! Now run: make switch"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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.sh

Repository: shunkakinoki/dotfiles

Length of output: 1378


🏁 Script executed:

grep -A 20 "rekey-galactica" Makefile

Repository: shunkakinoki/dotfiles

Length of output: 975


🏁 Script executed:

grep -B 5 -A 15 "^rekey:" Makefile

Repository: 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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR configures agenix to enable SSH key synchronization from galactica (macOS) to kyber (Ubuntu server), allowing both machines to authenticate with GitHub using the same SSH key. Additionally, it enhances SSH security by enabling post-quantum key exchange algorithms across all SSH connections.

Key Changes:

  • Shared secret configuration enabling kyber to decrypt galactica's GitHub SSH key
  • Automated deployment of the GitHub SSH key to ~/.ssh/id_ed25519_github on kyber
  • Post-quantum SSH algorithms (sntrup761x25519-sha512) enabled globally for enhanced security

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
named-hosts/galactica/secrets.nix Refactored to share SSH key with kyber by adding kyber's public key to the allMachines list for the id_ed25519 secret
named-hosts/kyber/secrets.nix Added references to galactica's SSH key with cross-host file path and configured secret sharing between machines
named-hosts/kyber/default.nix Enhanced agenix configuration to automatically deploy GitHub SSH key to ~/.ssh/id_ed25519_github with correct permissions
named-hosts/kyber/rekey-galactica.sh Added helper script to remotely rekey galactica secrets from kyber via Tailscale SSH
named-hosts/kyber/README.md Documented SSH key sync process with step-by-step instructions for both machines
home-manager/programs/ssh/default.nix Enabled post-quantum key exchange algorithms globally and configured github.com to use the synced SSH key

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

# 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

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script uses 'set -e' but should use 'set -euo pipefail' for more robust error handling. This ensures that:

  • 'u' treats unset variables as errors
  • 'o pipefail' ensures failures in pipes are caught

The reference script at scripts/update-gitalias.sh uses 'set -euo pipefail', which should be the standard for bash scripts in this codebase.

Suggested change
set -e
set -euo pipefail

Copilot uses AI. Check for mistakes.
echo ""

# Try Tailscale SSH first
if tailscale ssh shunkakinoki@galactica "cd ~/dotfiles && make rekey-galactica" 2>/dev/null; then

Copilot AI Dec 13, 2025

Copy link

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:

  1. Capturing and displaying the error message on failure
  2. 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.

Suggested change
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

Copilot uses AI. Check for mistakes.
Comment on lines +51 to +54
# Deploy GitHub SSH key to ~/.ssh/ with correct permissions
} // (
if name == "keys/id_ed25519.age" then
{

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment 'Deploy GitHub SSH key to ~/.ssh/ with correct permissions' is misleadingly placed. It appears to apply to all secrets, but only affects the 'keys/id_ed25519.age' secret based on the conditional logic below. Consider either:

  1. Moving the comment inside the 'if' block where it specifically applies
  2. Rewording it to clarify that it only applies to the GitHub SSH key

This will improve code clarity and prevent confusion about which secrets are deployed where.

Suggested change
# Deploy GitHub SSH key to ~/.ssh/ with correct permissions
} // (
if name == "keys/id_ed25519.age" then
{
} // (
if name == "keys/id_ed25519.age" then
{
# Deploy GitHub SSH key to ~/.ssh/ with correct permissions

Copilot uses AI. Check for mistakes.
@shunkakinoki
shunkakinoki enabled auto-merge (squash) December 13, 2025 05:13
@shunkakinoki
shunkakinoki merged commit 3f0eef7 into main Dec 13, 2025
29 checks passed
@shunkakinoki
shunkakinoki deleted the feat/kyber-ssh-sync branch December 13, 2025 05:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants