diff --git a/home/core/git.nix b/home/core/git.nix index 8420e383..638e40f7 100644 --- a/home/core/git.nix +++ b/home/core/git.nix @@ -46,6 +46,11 @@ in push.default = "current"; rerere.enabled = true; github.user = "ncaq"; + credential."https://forgejo.ncaq.net" = { + helper = "!${pkgs.pass-git-helper}/bin/pass-git-helper $@"; + useHttpPath = false; + username = "ncaq"; + }; }; ignores = [ "**/.claude/scheduled_tasks.lock" diff --git a/home/core/pass.nix b/home/core/pass.nix index bcc31977..d99025e6 100644 --- a/home/core/pass.nix +++ b/home/core/pass.nix @@ -1,4 +1,5 @@ { + pkgs, lib, config, ... @@ -6,6 +7,7 @@ let inherit (config.services.pass-secret-service) storePath; storeRel = lib.removePrefix "${config.home.homeDirectory}/" storePath; + inherit (config.programs.password-store.settings) PASSWORD_STORE_KEY; in { # GPGによる暗号化を行うpassを使用します。 @@ -26,9 +28,45 @@ in }; services.pass-secret-service.enable = true; - # `pass init`の代わりに宣言的に`.gpg-id`を配置してストアを初期化します。 - # `pass-secret-service`が内部で使うプログラムは`PASSWORD_STORE_KEY`を読まず、 - # 起動時に`.gpg-id`の存在を必須とするため実ファイルの配置が避けられません。 - home.file."${storeRel}/.gpg-id".text = - "${config.programs.password-store.settings.PASSWORD_STORE_KEY}\n"; + # gitのcredential helperとしてpass-git-helperを使用します。 + # Forgejoの`https`エンドポイントへのアクセス時に、 + # passに格納されたトークンを返します。 + # 実際のhelperの紐付けは`programs.git.settings.credential`で行います。 + xdg.configFile."pass-git-helper/git-pass-mapping.ini".text = '' + [forgejo.ncaq.net*] + target=forgejo.ncaq.net/ncaq + username=ncaq + ''; + + # sopsで管理されているForgejoのトークンを長期管理します。 + sops.secrets."forgejo/token/normal" = { + sopsFile = ../../secrets/forgejo.yaml; + key = "token/normal"; + mode = "0400"; + }; + + home = { + # `pass init`の代わりに宣言的に`.gpg-id`を配置してストアを初期化します。 + # `pass-secret-service`が内部で使うプログラムは`PASSWORD_STORE_KEY`を読まず、 + # 起動時に`.gpg-id`の存在を必須とするため実ファイルの配置が避けられません。 + file."${storeRel}/.gpg-id".text = "${PASSWORD_STORE_KEY}\n"; + + # sopsで復号化したトークンをpassのエントリとして再暗号化して配置します。 + # 内容が変化した時のみ書き換えて`home-manager switch`の度に差分が出るのを避けます。 + activation.forgejoTokenToPass = lib.hm.dag.entryAfter [ "sops-nix" ] '' + src="${config.sops.secrets."forgejo/token/normal".path}" + dst="${storePath}/forgejo.ncaq.net/ncaq.gpg" + $DRY_RUN_CMD mkdir -p "$(dirname "$dst")" + if [ ! -e "$dst" ] \ + || ! ${pkgs.gnupg}/bin/gpg --batch --quiet --decrypt "$dst" 2>/dev/null \ + | ${pkgs.diffutils}/bin/cmp -s - "$src"; then + $DRY_RUN_CMD ${pkgs.gnupg}/bin/gpg \ + --batch --yes --trust-model always \ + --encrypt --recipient ${PASSWORD_STORE_KEY} \ + --output "$dst" "$src" + fi + ''; + + packages = [ pkgs.pass-git-helper ]; + }; } diff --git a/secrets/forgejo.yaml b/secrets/forgejo.yaml new file mode 100644 index 00000000..0e3fabac --- /dev/null +++ b/secrets/forgejo.yaml @@ -0,0 +1,19 @@ +token: + normal: ENC[AES256_GCM,data:fEeLXCPCyHw8PjaBT9SSeHc7mjk0YPHiiqOZHv51qcaStlwy2naGMw==,iv:3SmZ3dy+Ts1l/DBHS5WNVRlHoKwFLVptZnlqM43QfGY=,tag:smixRYYhgl5jTcCIPW1GxQ==,type:str] +sops: + lastmodified: "2026-06-27T09:36:39Z" + mac: ENC[AES256_GCM,data:U2yL4rz2R8x1zGxin9HcRmpTPml9/6mYgku/eM7WN8yHb+sPmJoV5kZyfgBqXLN/Xm+lZvGCKr3rWKcu1TwJeiyWFL6ZZ+apTVQAfpxfIfhvW3Kempnv3+RY9ZeKfO0bOFl14digH0Dy7mpXWgBIJ8oai6sSLJcls22nbV/IkXM=,iv:qEojYfsjBBIbel6tZNfZbGSoXtHhggORgi4eVrlq5cw=,tag:k0hUeZc9QpL4M0C8704fvw==,type:str] + pgp: + - created_at: "2026-06-27T09:36:39Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4Dxlt1nl1bPpUSAQdAIqJ57h/GeJy+H2efDxNPZ4b/XOfTuLWkPgmJlismGXAw + LbptdFOqiB3XwVkQk6/HCQ8v8qlUOe2v5GAqeq0g05pnQVEmyywPoyfGPjcagEdf + 0lwBwwzvA4oFRIrmwUSt0c9pp/usISVEkC0YjS9U4PHe6D2y+M8+4xXpBNyhaN21 + eX8Wn5LWdoPICZ5vDbz0UiATcygS6b0D5rlUcfmqnL6dtxyVOvPoDllEE/972Q== + =Czd6 + -----END PGP MESSAGE----- + fp: 7DDE3BC405DC58D94BF661D342248C7D0FB73D57 + unencrypted_suffix: _unencrypted + version: 3.13.1