From 725e9f6d8791699bb35ef72f3e896c5b057db065 Mon Sep 17 00:00:00 2001 From: Poby <87608318+smg1024@users.noreply.github.com> Date: Wed, 13 May 2026 22:18:40 +0900 Subject: [PATCH] feat: add secret-backed kmeat ssh config --- Justfile | 49 +++++----- flake.lock | 18 ++-- modules/aspects/_secrets/sops.nix | 1 + modules/aspects/_ssh/ssh.nix | 7 ++ modules/aspects/_terminal/wezterm.lua | 5 ++ secrets/README.md | 125 ++++++++++++++++++++++++++ secrets/poby.yaml | 11 +-- 7 files changed, 180 insertions(+), 36 deletions(-) create mode 100644 secrets/README.md diff --git a/Justfile b/Justfile index bb030f3..c0b5670 100644 --- a/Justfile +++ b/Justfile @@ -2,7 +2,7 @@ # List all the just commands default: - @just --list + @just --list ############################################################################ # @@ -11,18 +11,24 @@ default: ############################################################################ [group('desktop')] -darwin hostname: - nix build .#darwinConfigurations.{{hostname}}.system \ - --extra-experimental-features 'nix-command flakes' +dry-run hostname: + nix build .#darwinConfigurations.{{ hostname }}.system \ + --dry-run \ + --extra-experimental-features 'nix-command flakes' - sudo -E ./result/sw/bin/darwin-rebuild switch --flake .#{{hostname}} +[group('desktop')] +darwin hostname: + nix build .#darwinConfigurations.{{ hostname }}.system \ + --extra-experimental-features 'nix-command flakes' + + sudo -E ./result/sw/bin/darwin-rebuild switch --flake .#{{ hostname }} [group('desktop')] darwin-debug hostname: - nix build .#darwinConfigurations.{{hostname}}.system --show-trace --verbose \ - --extra-experimental-features 'nix-command flakes' + nix build .#darwinConfigurations.{{ hostname }}.system --show-trace --verbose \ + --extra-experimental-features 'nix-command flakes' - sudo -E ./result/sw/bin/darwin-rebuild switch --flake .#{{hostname}} --show-trace --verbose + sudo -E ./result/sw/bin/darwin-rebuild switch --flake .#{{ hostname }} --show-trace --verbose ############################################################################ # @@ -33,46 +39,45 @@ darwin-debug hostname: # Update all the flake inputs [group('nix')] up: - nix flake update + nix flake update # Update specific input # Usage: just upp nixpkgs [group('nix')] upp input: - nix flake update {{input}} + nix flake update {{ input }} # List all generations of the system profile [group('nix')] history: - nix profile history --profile /nix/var/nix/profiles/system + nix profile history --profile /nix/var/nix/profiles/system # Open a nix shell with the flake [group('nix')] repl: - nix repl -f flake:nixpkgs + nix repl -f flake:nixpkgs # remove all generations older than 7 days # on darwin, you may need to switch to root user to run this command [group('nix')] clean: - sudo nix profile wipe-history --profile /nix/var/nix/profiles/system --older-than 7d + sudo nix profile wipe-history --profile /nix/var/nix/profiles/system --older-than 7d # Garbage collect all unused nix store entries [group('nix')] gc: - # garbage collect all unused nix store entries(system-wide) - sudo nix-collect-garbage --delete-older-than 7d - # garbage collect all unused nix store entries(for the user - home-manager) - # https://github.com/NixOS/nix/issues/8508 - nix-collect-garbage --delete-older-than 7d + # garbage collect all unused nix store entries(system-wide) + sudo nix-collect-garbage --delete-older-than 7d + # garbage collect all unused nix store entries(for the user - home-manager) + # https://github.com/NixOS/nix/issues/8508 + nix-collect-garbage --delete-older-than 7d [group('nix')] fmt range: - # format the nix files in this repo - nix fmt {{range}} + # format the nix files in this repo + nix fmt {{ range }} # Show all the auto gc roots in the nix store [group('nix')] gcroot: - ls -al /nix/var/nix/gcroots/auto/ - + ls -al /nix/var/nix/gcroots/auto/ diff --git a/flake.lock b/flake.lock index 6304df3..5e6865c 100644 --- a/flake.lock +++ b/flake.lock @@ -99,11 +99,11 @@ ] }, "locked": { - "lastModified": 1778444552, - "narHash": "sha256-f18pIiR9q/p1vHY93gmAum7aHhQOG49oGvAB9+lptRo=", + "lastModified": 1778628724, + "narHash": "sha256-VNG6hJ146VEenXcDrB3t6MVnrMx+gtyCWTCDkzOp9Qs=", "owner": "nix-community", "repo": "home-manager", - "rev": "dcebe66f958673729896eec2de4abfd86ef22d21", + "rev": "6a0bbd6b4720da1c9ce7ebf35ff5c41a82db367a", "type": "github" }, "original": { @@ -184,11 +184,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1778458615, - "narHash": "sha256-cY07EsdhBJ8tFXPzDYevgqxRev9ZLxFonuq9wmq5kwg=", + "lastModified": 1778580735, + "narHash": "sha256-t+8AVV8ExvOmslz2sLIgw/hJBKlyl65rJvxjvvjHgpE=", "owner": "nixos", "repo": "nixpkgs", - "rev": "c6e5ca3c836a5f4dd9af9f2c1fc1c38f0fac988a", + "rev": "48d91f2c0ce7b9e589f967d4f685153dd765dcdd", "type": "github" }, "original": { @@ -225,11 +225,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1778408907, - "narHash": "sha256-QXjdRz5fssxAWDrtfBYxvjMtTqJzQAbnAmX3u22xCck=", + "lastModified": 1778618635, + "narHash": "sha256-eiZkwksjBS4yr5uPt9rzoEQrnuwTgmFVFb6glGrNGF4=", "owner": "notashelf", "repo": "nvf", - "rev": "e86a92e4b29b499e5f1285b737b7612115103da9", + "rev": "0f7a1ff6ecff4a1f4fa2bbdd0f42151706a26831", "type": "github" }, "original": { diff --git a/modules/aspects/_secrets/sops.nix b/modules/aspects/_secrets/sops.nix index 62bf4d7..ae6057f 100644 --- a/modules/aspects/_secrets/sops.nix +++ b/modules/aspects/_secrets/sops.nix @@ -7,6 +7,7 @@ secrets = { "github_ssh_key" = {}; "github_cli_token" = {}; + "kmeat_mac_mini_ssh_key" = {}; }; }; } diff --git a/modules/aspects/_ssh/ssh.nix b/modules/aspects/_ssh/ssh.nix index ac2c186..251cf74 100644 --- a/modules/aspects/_ssh/ssh.nix +++ b/modules/aspects/_ssh/ssh.nix @@ -17,6 +17,13 @@ identitiesOnly = true; identityFile = [config.sops.secrets."github_ssh_key".path]; }; + "kmeat-mac-mini" = { + hostname = "ai.kmeat.com"; + user = "kmeat"; + port = 10222; + identitiesOnly = true; + identityFile = [config.sops.secrets."kmeat_mac_mini_ssh_key".path]; + }; }; }; } diff --git a/modules/aspects/_terminal/wezterm.lua b/modules/aspects/_terminal/wezterm.lua index b7469c7..8577a3d 100644 --- a/modules/aspects/_terminal/wezterm.lua +++ b/modules/aspects/_terminal/wezterm.lua @@ -37,6 +37,11 @@ config = { mods = "SUPER", action = wezterm.action.ActivateCommandPalette, }, + { + key = "Enter", + mods = "ALT", + action = wezterm.action.DisableDefaultAssignment, + }, }, } diff --git a/secrets/README.md b/secrets/README.md new file mode 100644 index 0000000..d19fcc7 --- /dev/null +++ b/secrets/README.md @@ -0,0 +1,125 @@ +# Secrets + +This directory stores SOPS-encrypted secrets used by the `secrets` Home Manager +aspect. Do not commit plaintext secrets. + +## Current Setup + +- Secret file: `secrets/poby.yaml` +- SOPS rules: `.sops.yaml` +- Age key file: `~/.config/sops/age/keys.txt` +- Secret declarations: `modules/aspects/_secrets/sops.nix` +- SSH host wiring: `modules/aspects/_ssh/ssh.nix` + +## Add An SSH Private Key + +From the repository root, open a shell with `sops` and `age`: + +```bash +nix-shell -p sops age +``` + +Open the encrypted secret file with the age key: + +```bash +SOPS_AGE_KEY_FILE="$HOME/.config/sops/age/keys.txt" sops secrets/poby.yaml +``` + +Add a top-level key name and paste the private key as a YAML block scalar: + +```yaml +workstation_ssh_key: | + -----BEGIN OPENSSH PRIVATE KEY----- + ... + -----END OPENSSH PRIVATE KEY----- +``` + +Save and quit the editor. SOPS will re-encrypt the file automatically. + +Do not edit the `sops:` metadata block manually. + +## Generate A New SSH Key First + +If the key does not exist yet, generate it before opening SOPS: + +```bash +ssh-keygen -t ed25519 -f ~/.ssh/workstation_ssh_key -C "workstation" +``` + +Register the public key wherever the remote service expects it: + +```bash +cat ~/.ssh/workstation_ssh_key.pub +``` + +Then copy the private key contents into `secrets/poby.yaml` with SOPS. + +After the private key is stored in SOPS and deployed through `sops-nix`, remove +any temporary plaintext private key if it is no longer needed outside this repo. + +## Declare The Secret In Nix + +Add the secret name to `modules/aspects/_secrets/sops.nix`: + +```nix +secrets = { + "github_ssh_key" = {}; + "github_cli_token" = {}; + "workstation_ssh_key" = {}; +}; +``` + +## Use The Secret For SSH + +Reference the SOPS-managed secret path from the matching SSH host block in +`modules/aspects/_ssh/ssh.nix`: + +```nix +"workstation-host" = { + hostname = "example.com"; + user = "example"; + identitiesOnly = true; + identityFile = [config.sops.secrets."workstation_ssh_key".path]; +}; +``` + +## Verify + +Confirm the encrypted file contains the expected top-level secret names without +printing secret values: + +```bash +SOPS_AGE_KEY_FILE="$HOME/.config/sops/age/keys.txt" \ + sops -d secrets/poby.yaml \ + | awk -F: '/^[A-Za-z0-9_]+:/ { print $1 }' +``` + +Confirm no plaintext private key was written into the encrypted file: + +```bash +rg -n "BEGIN OPENSSH PRIVATE KEY|END OPENSSH PRIVATE KEY" secrets/poby.yaml +``` + +Expected result: no output. + +Evaluate the Darwin configuration: + +```bash +nix build .#darwinConfigurations.fenrir.system \ + --dry-run \ + --extra-experimental-features 'nix-command flakes' +``` + +Build and switch: + +```bash +just darwin fenrir +``` + +Test the SSH alias: + +```bash +ssh -o BatchMode=yes workstation-host true +``` + +No output means the SSH command succeeded. diff --git a/secrets/poby.yaml b/secrets/poby.yaml index d1277db..63aae5f 100644 --- a/secrets/poby.yaml +++ b/secrets/poby.yaml @@ -1,9 +1,9 @@ github_ssh_key: ENC[AES256_GCM,data:3EPsAfo11u5p48B2myGkHmKcbj0jpFXbc1LxSzpRSFa4yBuRwBIne2hCcgpbqF3pMJml9FuhWtamVPsuhJoRHHonTdgPb5Y48uqegl4HAJefUBWPJEZ0q3F990wqpcF3P8PK5NjjwkZdzJlzXSucjISxEI65q43+/KAlxylu0DMwClZY1lF3DEwg2V9cycmgDWN4XWYQLp89aAXY2A6mC1nHQNI3UbI3VogEVooALSiWgNGZVAWbLNgpPN8qc2zqfPqVdC0Qna+ucRA5MEkvyhyWnjvzoKgFv8n0IHLd+Y676R9SaP56zxFdZUgyQ7nUNSWW8fWaHuL9EvvK4uTaJAGv2Je5AyehRKZ6Sw9/3O2hugCG8d1DhMcc7A1p2wiEScy/m3MDtMUv9ndk0rmk6/+7bH1Ha71tOsAjR08zOPBs5hrDOEXuA0yURqEV9HdNWSt1zQ0NrWsxOJTHeKw6jWG0shWpvLftqoLbhTYGIeNkxhSft7Vm9Cp23hCvG2J38BtRV108UITKvDg9U8utVVR/oCFIBuZkJ2j7,iv:t82G7RM7QybvOW008lZh6XNcmvP0XkBUbgjKMlq3Ov0=,tag:7Y1H0QPsA3k6NOiy3ock+Q==,type:str] github_cli_token: ENC[AES256_GCM,data:8+IqQnxA/Qm7dsFVNYAVWfYVTNTbmW1bevGnF8e635wU2fBjPpnsZg==,iv:v0sV8Te6eIqKcu6lArU4OfHAP5ucfmPHLnqtFW8dZxk=,tag:VjVdJqIbYrNlcGyKSa3Fmg==,type:str] +kmeat_mac_mini_ssh_key: ENC[AES256_GCM,data:rDopWoLKy0lXIDxKKKGoY8NFINIfJBIu/6fgcki0lr6zL/GAl1OmMY5T/GJkNOAhZjGSww4U9zOAzH5KPAe6QznstAqZz3T9qor1VOte7hd7r2iKrurc4ezZ0CLeP5y1rrKuruQ1xh47t5z0y6s2tP+QtDTShTYlCyCC1BS+k/1US+gpk7+qe/3U0qM5HLcu6m11Hp7sExEESffjTU+YeqaGAGBStY4uAhHeLZHvTZNHKcb9HrLREp91SwmvRLa9n5NAKyXZJQysyHyNHRTYOYEOpNt9hmKoRNSNg4qcLvZjmEtlLA2I11RPvgmiNhKQKpewj6CVKNWGUsaxIG7eWNvwPziaZBViNNP65WrULeo7d1csf/VdGegRK09b1iBAr+/JlsNryiBSYmVTDJWBFrte7LEanXyZJ8LLPebqHXJmmyznfUriz3maTBTkJNfyqqfuSLT2l6j1NHM0GBqnNOV+5gkjU9CuOn/75fiMMW2b8OtJjyJ1gj4GCf7DLZIg2Jod,iv:RnRaShSyw8OS/R0tkESezqgCyQk/fQNrS19gnfzhudY=,tag:ak46MeblmraeHI3V2fZy2Q==,type:str] sops: age: - - recipient: age1qeyrh6e40nek3da4mnj298cy2l3aswe7432us30d2p93akcvp9zqext63j - enc: | + - enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQaUt1Y1hFS1N0djNEU3NQ QjFIMk9GZkxoeks2WUx0WlBNblR6dEpSZ2tBCkl3Wk1xaDlXWEFnYkIzZ2J3bUxw @@ -11,7 +11,8 @@ sops: QXQ3YUkxWnk2U0hacjBMZDQ5WlNFQTAKzzzcoCZg7iNg5QoajxSpP1ka5qIIfaNE 5VMXcX4qL0OszsO3j3ShYIT02m3XqkSeaOMSz+uty2BWtPCDZoLHrg== -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-04-16T13:40:02Z" - mac: ENC[AES256_GCM,data:u6uqpTdLRE8gB4WphelVhMRKouTZDlNqpa1R6ACXu1ek/9sVaZLxyAhY/xrKhYhGu7MHN0RDG0sHousRtdqCTGE/mDiCEj4hVufctpefpwS9amDRH2XW1kOcheEHvNjPTimKPsJJXutcofxm1LtBZkbkhflrsRQLyOvkc/674eI=,iv:bHtn8yrudQnwH2rPzfUEU25Mar4uwPZK3beU0uLgxY4=,tag:6Fwl6ZeM83w6eTfxBNiqtw==,type:str] + recipient: age1qeyrh6e40nek3da4mnj298cy2l3aswe7432us30d2p93akcvp9zqext63j + lastmodified: "2026-05-13T12:58:01Z" + mac: ENC[AES256_GCM,data:RJM9WeCDqWPYMs8xROuZ8TrBfIU3T6t2jy/VW6qZJ6YAwRjkGQ8Bkr+YlZaqpWxr4dRnuUNA1NonZZJxW5xfGti+umsRHiGEa1fGTz+0sq5TIK9XpYIOZPy0AksKSGMvvfG8VZbdBYE+DT97yWSANqWeuY6vnaGThkJXyLDfnAs=,iv:qpQq7H2kIgETS43FCLW2WorU91yC6drSqVQhvhniCRs=,tag:hPW7FvOiMjcHH7WZ09+psw==,type:str] unencrypted_suffix: _unencrypted - version: 3.12.1 + version: 3.13.0