From 1ea1cfe8f21bbcb25921ba13bcf20af46c34129e Mon Sep 17 00:00:00 2001 From: Ruk Doe Date: Sun, 18 Oct 2026 11:34:56 +0900 Subject: [PATCH] =?UTF-8?q?bootstrap/=20=E3=81=AE=20SOPS=20=E3=83=95?= =?UTF-8?q?=E3=82=A1=E3=82=A4=E3=83=AB=E3=82=92=20*.sops.yaml=20=E3=81=AB?= =?UTF-8?q?=E6=8F=83=E3=81=88=E3=82=8B=E3=80=81talos-boot=20=E3=81=AE=20pa?= =?UTF-8?q?ths=20=E3=82=92=E3=82=A2=E3=83=B3=E3=82=AB=E3=83=BC=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - bootstrap/ の暗号化ファイル 4 つを *.sops.yaml に改名。ArgoCD の `bootstrap` は `*.sops.yaml` で外すので、足すたびに exclude に書き足す約束が要らなくなる。 .sops.yaml の規則もその名前だけに絞った(別の名前では暗号化できない) - talos-boot の pull_request / push の paths を YAML アンカーで 1 つに - docs/talos.md の「bootstrap/ をまるごと inlineManifests」など古い記述を直す render.sh の出力は本番の machine config とバイト単位で同じ(当て直し不要)。 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01JbmWyUB9jcBcYCnNyiGBSV --- .github/workflows/talos-boot.yml | 21 +++++++------------ .sops.yaml | 10 +++++---- README.md | 2 +- apps/matrix/README.md | 2 +- apps/matrix/hookshot.yaml | 2 +- bootstrap/README.md | 9 ++++---- bootstrap/argocd/oidc-secret.yaml | 2 +- bootstrap/argocd/repos.yaml | 6 +++--- ...et-values.yaml => secret-values.sops.yaml} | 0 bootstrap/argocd/values.yaml | 8 +++---- ...ecret.yaml => cloudflare-secret.sops.yaml} | 0 bootstrap/cert-manager/clusterissuer.yaml | 2 +- ...et-values.yaml => secret-values.sops.yaml} | 0 .../{secrets.yaml => secrets.sops.yaml} | 0 bootstrap/infisical/values.yaml | 4 ++-- docs/cloudflare-tokens.md | 4 ++-- docs/talos.md | 7 ++++--- talos/README.md | 2 +- talos/render.sh | 12 +++++------ tools/README.md | 2 +- tools/t.ps1 | 2 +- 21 files changed, 47 insertions(+), 50 deletions(-) rename bootstrap/argocd/{secret-values.yaml => secret-values.sops.yaml} (100%) rename bootstrap/cert-manager/{cloudflare-secret.yaml => cloudflare-secret.sops.yaml} (100%) rename bootstrap/infisical/{secret-values.yaml => secret-values.sops.yaml} (100%) rename bootstrap/infisical/{secrets.yaml => secrets.sops.yaml} (100%) diff --git a/.github/workflows/talos-boot.yml b/.github/workflows/talos-boot.yml index 1037e9de..cd3aaf57 100644 --- a/.github/workflows/talos-boot.yml +++ b/.github/workflows/talos-boot.yml @@ -15,7 +15,8 @@ name: talos boot on: pull_request: - paths: + # push と同じ一覧(YAML のアンカー。GitHub Actions は 2025-09 から読む。マージキー `<<:` は読まない) + paths: &paths - talos/** - bootstrap/cilium/** - bootstrap/cert-manager/** @@ -26,15 +27,7 @@ on: - .github/workflows/talos-boot.yml push: branches: [main] - paths: - - talos/** - - bootstrap/cilium/** - - bootstrap/cert-manager/** - - bootstrap/argocd/** - - bootstrap/infisical/** - - bootstrap/gateway/** - - bootstrap/apiserver/** - - .github/workflows/talos-boot.yml + paths: *paths workflow_dispatch: permissions: @@ -122,8 +115,8 @@ jobs: username: ci-dummy password: ci-dummy PATCH - # **argocd / infisical の値は本物の values.yaml。** 秘密の側(secret-values.yaml)だけダミーに替えて重ねる。 - # 通知の送り先は secret-values.yaml にしか無いので、渡さなければ通知も出ない。 + # **argocd / infisical の値は本物の values.yaml。** 秘密の側(secret-values.sops.yaml)だけダミーに替えて重ねる。 + # 通知の送り先は secret-values.sops.yaml にしか無いので、渡さなければ通知も出ない。 # extraObjects は app-of-apps(`apps`)と GitHub App の repo-creds。CI で本物を同期させない echo 'extraObjects: []' > /tmp/argocd-secret-values.yaml # SMTP は外(smtp.office365.com)に繋ぎに行くので抜く(リストなので丸ごと置き換える) @@ -135,9 +128,9 @@ jobs: | .stringData.ENCRYPTION_KEY = \"$(openssl rand -hex 16)\" | .stringData.AUTH_SECRET = \"$(openssl rand -base64 32)\" | .stringData.TELEMETRY_ENABLED = \"false\"" \ - bootstrap/infisical/secrets.yaml > /tmp/infisical-secret.yaml + bootstrap/infisical/secrets.sops.yaml > /tmp/infisical-secret.yaml yq 'del(.sops) | (.. | select(tag == "!!str" and test("^ENC\\["))) |= "ci-dummy"' \ - bootstrap/cert-manager/cloudflare-secret.yaml > /tmp/cloudflare-secret.yaml + bootstrap/cert-manager/cloudflare-secret.sops.yaml > /tmp/cloudflare-secret.yaml for f in /tmp/infisical-secret.yaml /tmp/cloudflare-secret.yaml; do ! grep -q 'ENC\[' "$f" || { echo "::error::$f に暗号文が残っている"; exit 1; } done diff --git a/.sops.yaml b/.sops.yaml index 61cc49bb..865ed306 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -3,13 +3,15 @@ # tools/t.ps1 sh -c 'mkdir -p ~/.config/sops/age && age -d -o ~/.config/sops/age/keys.txt recovery/sops-age.key.age' # のあと `tools/t.ps1 sops -d`(tools/t.ps1 の中の ~ はリポジトリの .home/)。 creation_rules: - # bootstrap/*/secret-values.yaml(chart の値のうち秘密だけ)は丸ごと暗号化する。 + # bootstrap/*/secret-values.sops.yaml(chart の値のうち秘密だけ)は丸ごと暗号化する。 # 秘密しか入れない約束なので選り分けない。値の残りは同じ場所の平文の values.yaml。 - - path_regex: ^bootstrap/[^/]+/secret-values\.yaml$ + - path_regex: ^bootstrap/[^/]+/secret-values\.sops\.yaml$ age: age1sgnnkn67wpt4wgjsff4c36w3cmjkk557ng504e4aczx2lzls9y6ssy0x9r - # 残りの bootstrap/ は「そのキーだけ」を暗号化する。マニフェストの構造は git で読めたほうが + # 残りの bootstrap/*.sops.yaml は「そのキーだけ」を暗号化する。マニフェストの構造は git で読めたほうが # レビューできるため。 - - path_regex: ^bootstrap/.*\.yaml$ + # **bootstrap/ で暗号化するファイルは `.sops.yaml` で終える。** ArgoCD の `bootstrap` はその名前で外す + # (bootstrap/argocd/repos.yaml)。違う名前で `sops -e` すると、一致する規則が無いと言われて落ちる。 + - path_regex: ^bootstrap/.*\.sops\.yaml$ encrypted_regex: ^(ENCRYPTION_KEY|AUTH_SECRET|CLIENT_ID_GITHUB_LOGIN|CLIENT_SECRET_GITHUB_LOGIN|CF_DNS_API_TOKEN)$ age: age1sgnnkn67wpt4wgjsff4c36w3cmjkk557ng504e4aczx2lzls9y6ssy0x9r # talos/secrets.yaml は丸ごと暗号化する。`talosctl gen secrets` の出力は diff --git a/README.md b/README.md index 4f5bb15f..cedf2aad 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Argo CD が git を読む GitHub App 鍵、cert-manager の Cloudflare トーク ```shell # 鍵はリポジトリの .home/(git に入らない)に置く。コマンドは tools/t.ps1 で動かす(tools/README.md) tools/t.ps1 sh -c 'mkdir -p ~/.config/sops/age && age -d -o ~/.config/sops/age/keys.txt recovery/sops-age.key.age' -tools/t.ps1 sops -d bootstrap/infisical/secrets.yaml # 中を見る(画面に出すと平文になるので注意) +tools/t.ps1 sops -d bootstrap/infisical/secrets.sops.yaml # 中を見る(画面に出すと平文になるので注意) ``` ## ホスト名の付け方 diff --git a/apps/matrix/README.md b/apps/matrix/README.md index 969c1dbc..bccbb3ee 100644 --- a/apps/matrix/README.md +++ b/apps/matrix/README.md @@ -65,7 +65,7 @@ Entra だけ(Tuwunel の `[[global.identity_provider]]`)。パスワードのロ | `server` | k8up の通知 | Infisical `/k8up/k8up-global` の `mattermostWebhook`(名前は据え置き) | | 〃 | Infisical(秘密の変更) | Infisical のプロジェクトの webhook(Project Settings → Webhooks。環境 prod、パス `/`) | | 〃 | Cloudflare(証明書・DDoS・オリジン不達など) | Cloudflare の通知の webhook の送り先([../../pulumi/notifications.ts](../../pulumi/notifications.ts)) | -| `argocd` | Argo CD | `bootstrap/argocd/secret-values.yaml`(SOPS)の `service.webhook.mattermost` | +| `argocd` | Argo CD | `bootstrap/argocd/secret-values.sops.yaml`(SOPS)の `service.webhook.mattermost` | | `ashi` | ashi | Infisical `/ashi/ashi-secrets` の `notify-webhook-url` | | `todoroku` | todoroku | Infisical `/todoroku/todoroku-secrets` の `mattermost-webhook-url` | | `worklog` | worklog | Infisical `/worklog/worklog-secrets` の `mattermost-webhook-url` | diff --git a/apps/matrix/hookshot.yaml b/apps/matrix/hookshot.yaml index d20963c1..48ffc1d8 100644 --- a/apps/matrix/hookshot.yaml +++ b/apps/matrix/hookshot.yaml @@ -88,7 +88,7 @@ data: result = parts.length ? { version: "v2", plain: parts.join("\n\n"), msgtype: "m.notice" } : { version: "v2", empty: true }; - # 部屋 argocd: Argo CD の通知(bootstrap/argocd/values.yaml・secret-values.yaml) + # 部屋 argocd: Argo CD の通知(bootstrap/argocd/values.yaml・secret-values.sops.yaml) - connectionType: uk.half-shot.matrix-hookshot.generic.hook stateKey: ${HOOK_ARGOCD} roomId: "!BeZ3yus1s1E22DPYFauQjZ1AMGT2VkusuLzLk2r1cJk" diff --git a/bootstrap/README.md b/bootstrap/README.md index b88f1cd7..ae9c3b89 100644 --- a/bootstrap/README.md +++ b/bootstrap/README.md @@ -14,8 +14,9 @@ ArgoCD が動くのに要るもの(本体・repo の資格情報・ApplicationSe 最初の何回か落ちて retry で戻る。 **SOPS(age)で暗号化したファイルは ArgoCD が当てない** ── 復号鍵をクラスタにも CI にも渡さないため。 -`bootstrap` の `exclude` に並べてある(**足したら exclude にも足す**)。 -`infisical/secrets.yaml`、`cert-manager/cloudflare-secret.yaml`、`{argocd,infisical}/secret-values.yaml`。 +**名前を `*.sops.yaml` で終える**と `bootstrap` の `exclude` が外す(`.sops.yaml` の規則も +その名前にしか一致しないので、別の名前では暗号化できない)。 +`infisical/secrets.sops.yaml`、`cert-manager/cloudflare-secret.sops.yaml`、`{argocd,infisical}/secret-values.sops.yaml`。 鍵は [`recovery/sops-age.key.age`](../recovery/)。**中を編集するときも `sops edit` を通すこと。** MAC は暗号化して いない値も含めて計算されるので、**平文で 1 行足すだけでも `sops -d` が MAC 不一致で落ちる。** @@ -23,7 +24,7 @@ ArgoCD が動くのに要るもの(本体・repo の資格情報・ApplicationSe どれも `render.sh` が `helm template` して machine config に載せる。どれも同じ形で、 `/version.yaml`(chart・repo・版。Renovate が上げる)と `/values.yaml`(値)。 -argocd と infisical は、値のうち秘密だけを `/secret-values.yaml`(SOPS、丸ごと暗号化)に分けて上に重ねる。 +argocd と infisical は、値のうち秘密だけを `/secret-values.sops.yaml`(SOPS、丸ごと暗号化)に分けて上に重ねる。 argocd・infisical の版は自動マージしない(`renovate.json` の `bootstrap charts`)。 ## git と live がずれていないか @@ -41,7 +42,7 @@ ConfigMap に出ているので、読むだけの権限で比べられる)。** 認証は Kubernetes 方式(TokenReview・長命の資格情報なし)。 - `infisical/` … Infisical 本体(chart + Postgres/Redis)。公開経路は [`apps/infisical/httproute.yaml`](../apps/infisical/httproute.yaml)。 - `secrets.yaml` の `ENCRYPTION_KEY` が DB の暗号鍵で、これを失うと Infisical の中身が全部読めなくなる + `secrets.sops.yaml` の `ENCRYPTION_KEY` が DB の暗号鍵で、これを失うと Infisical の中身が全部読めなくなる (クラスタで一番失ってはいけない値)。Postgres の PVC は既定の `local-path` で、`pg_dump` を k8up が日次で取っている。 - **operator と push-bridge はここには無い。** ArgoCD の Application に移した(`apps/infisical-operator/`、 `apps/infisical-push-bridge/`)。ArgoCD 自身は operator に依存しないので、bootstrap に置く理由がない。 diff --git a/bootstrap/argocd/oidc-secret.yaml b/bootstrap/argocd/oidc-secret.yaml index ecdb4376..7eb94e25 100644 --- a/bootstrap/argocd/oidc-secret.yaml +++ b/bootstrap/argocd/oidc-secret.yaml @@ -2,7 +2,7 @@ # reference from argocd-cm ($argocd-oidc:client-secret in values.yaml). # The label is what lets argocd-server read it. Only the login depends on # this: syncing runs on the GitHub App credential that ships in -# secret-values.yaml, so Infisical being down never blocks its own recovery. +# secret-values.sops.yaml, so Infisical being down never blocks its own recovery. # Applied by hand like the rest of this directory (the apps Application only # syncs repos.yaml). apiVersion: secrets.infisical.com/v1alpha1 diff --git a/bootstrap/argocd/repos.yaml b/bootstrap/argocd/repos.yaml index b175edcc..5345a9f0 100644 --- a/bootstrap/argocd/repos.yaml +++ b/bootstrap/argocd/repos.yaml @@ -111,10 +111,10 @@ spec: # bootstrap/ の平文のマニフェスト(Gateway・auth・ClusterIssuer・InfisicalSecret など)。2026-10-17 まで # GitHub Actions(bootstrap-apply.yml)が当てていた(../../docs/decisions.md「層の分け方」)。 # -# **machine config が持つものは外す。** Helm の値と版(`*values.yaml`・`*version.yaml`)、SOPS のファイル、 +# **machine config が持つものは外す。** Helm の値と版(`*values.yaml`・`*version.yaml`)、SOPS のファイル +# (`*.sops.yaml`。名前で外すので、足しても exclude は触らなくてよい。../../.sops.yaml が他の名前では暗号化させない)、 # machine config が作る Namespace(argocd・cert-manager・infisical)、`apiserver/`、`cilium/`。 # このファイル自身は上の `apps`(argocd/values.yaml の extraObjects)が持つので外す。 -# **SOPS のファイルを足したら exclude にも足すこと**(復号できないまま当たって同期が落ちる)。 # 照合は bootstrap/ からの相対パスで、`*` は `/` もまたぐ(argo-cd の util/glob は区切り文字無しの gobwas/glob)。 apiVersion: argoproj.io/v1alpha1 kind: Application @@ -129,7 +129,7 @@ spec: path: bootstrap directory: recurse: true - exclude: '{*values.yaml,*version.yaml,apiserver/*,cilium/*,argocd/repos.yaml,argocd/namespace.yaml,cert-manager/namespace.yaml,infisical/namespace.yaml,cert-manager/cloudflare-secret.yaml,infisical/secrets.yaml}' + exclude: '{*values.yaml,*version.yaml,*.sops.yaml,apiserver/*,cilium/*,argocd/repos.yaml,argocd/namespace.yaml,cert-manager/namespace.yaml,infisical/namespace.yaml}' destination: server: https://kubernetes.default.svc namespace: argocd diff --git a/bootstrap/argocd/secret-values.yaml b/bootstrap/argocd/secret-values.sops.yaml similarity index 100% rename from bootstrap/argocd/secret-values.yaml rename to bootstrap/argocd/secret-values.sops.yaml diff --git a/bootstrap/argocd/values.yaml b/bootstrap/argocd/values.yaml index c98e4a54..a1606dad 100644 --- a/bootstrap/argocd/values.yaml +++ b/bootstrap/argocd/values.yaml @@ -1,5 +1,5 @@ # argo-cd の chart の値。版は version.yaml、秘密の値(通知の webhook と GitHub App の鍵)は -# secret-values.yaml(SOPS)。描いて machine config に載せるのは talos/render.sh。 +# secret-values.sops.yaml(SOPS)。描いて machine config に載せるのは talos/render.sh。 # # CRD は chart から描かせない。3 つで 1.83 MB あり、描き出しの 95%。 # render.sh が `KubeExternalManifestConfig` で URL を渡す @@ -68,7 +68,7 @@ notifications: # true by default; anything applied out-of-band gets wiped the next time # the chart is re-rendered. # - # notifiers は secret-values.yaml(`service.webhook.mattermost`)。送り先は Matrix の部屋 argocd + # notifiers は secret-values.sops.yaml(`service.webhook.mattermost`)。送り先は Matrix の部屋 argocd # (スペース「通知」)の hookshot の webhook(2026-10-06 に Mattermost → Zulip → Matrix と移した)。 # 名前は mattermost のまま ── テンプレートと subscriptions が参照している。 # 送るのは {"text": …}(Slack 互換)。hookshot の変換のスクリプト(apps/matrix/hookshot.yaml)が読む @@ -127,7 +127,7 @@ extraObjects: # come from Infisical: ArgoCD syncing is how Infisical itself gets # deployed and recovered -- this repo is private. # - # 中身は下の githubAppRepoCreds(鍵だけ secret-values.yaml にあり、helm が map として重ねる)。 + # 中身は下の githubAppRepoCreds(鍵だけ secret-values.sops.yaml にあり、helm が map として重ねる)。 # extraObjects はリストなので、そのままでは値ファイルを重ねると丸ごと置き換わる。 # 文字列の要素は chart が `tpl` に通すので、ここで toYaml して 1 つの要素にする。 - '{{ toYaml .Values.githubAppRepoCreds }}' @@ -175,4 +175,4 @@ githubAppRepoCreds: url: https://github.com/danything githubAppID: "4434943" githubAppInstallationID: "150067651" - # githubAppPrivateKey は secret-values.yaml + # githubAppPrivateKey は secret-values.sops.yaml diff --git a/bootstrap/cert-manager/cloudflare-secret.yaml b/bootstrap/cert-manager/cloudflare-secret.sops.yaml similarity index 100% rename from bootstrap/cert-manager/cloudflare-secret.yaml rename to bootstrap/cert-manager/cloudflare-secret.sops.yaml diff --git a/bootstrap/cert-manager/clusterissuer.yaml b/bootstrap/cert-manager/clusterissuer.yaml index b4ddfbfb..344b7ed9 100644 --- a/bootstrap/cert-manager/clusterissuer.yaml +++ b/bootstrap/cert-manager/clusterissuer.yaml @@ -1,6 +1,6 @@ # Let's Encrypt を Cloudflare の DNS-01 で。ワイルドカード証明書を取るので DNS-01。 # トークンは同じ namespace の Secret にしか置けない(cert-manager は自分の namespace の -# Secret しか読まない)ので、cloudflare-secret.yaml がここに置いている。 +# Secret しか読まない)ので、cloudflare-secret.sops.yaml がここに置いている。 apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: diff --git a/bootstrap/infisical/secret-values.yaml b/bootstrap/infisical/secret-values.sops.yaml similarity index 100% rename from bootstrap/infisical/secret-values.yaml rename to bootstrap/infisical/secret-values.sops.yaml diff --git a/bootstrap/infisical/secrets.yaml b/bootstrap/infisical/secrets.sops.yaml similarity index 100% rename from bootstrap/infisical/secrets.yaml rename to bootstrap/infisical/secrets.sops.yaml diff --git a/bootstrap/infisical/values.yaml b/bootstrap/infisical/values.yaml index 093ce8b6..5d6f170d 100644 --- a/bootstrap/infisical/values.yaml +++ b/bootstrap/infisical/values.yaml @@ -1,5 +1,5 @@ # infisical-standalone の chart の値。版は version.yaml、DB と Redis のパスワードは -# secret-values.yaml(SOPS)。描いて machine config に載せるのは talos/render.sh +# secret-values.sops.yaml(SOPS)。描いて machine config に載せるのは talos/render.sh # (ArgoCD に置けない理由は docs/decisions.md「infisical だけは ArgoCD に移せない」)。 # # https://github.com/Infisical/infisical/tree/main/helm-charts/infisical-standalone-postgres @@ -16,7 +16,7 @@ infisical: repository: mirror.gcr.io/infisical/infisical # The chart's default tag lags releases; pin explicitly. tag: v0.166.8 - # ENCRYPTION_KEY / AUTH_SECRET / SITE_URL live in infisical/secrets.yaml. + # ENCRYPTION_KEY / AUTH_SECRET / SITE_URL live in infisical/secrets.sops.yaml. kubeSecretRef: infisical-secrets extraEnv: # Kubernetes auth makes Infisical call https://kubernetes.default.svc diff --git a/docs/cloudflare-tokens.md b/docs/cloudflare-tokens.md index 6fb04797..0b0e19fa 100644 --- a/docs/cloudflare-tokens.md +++ b/docs/cloudflare-tokens.md @@ -11,7 +11,7 @@ Pulumi で作ると値を Infisical に書く鍵が CI に要る。その鍵は | `external-dns (doany.io DNS write)` | アカウント | `doany.io` の Zone Read + DNS Write | Infisical `/external-dns/external-dns` の `cloudflare-api-token` | apps/external-dns | | `doany-restic` | アカウント | R2 バケット `doany-restic` だけの Object Read & Write | Infisical `/k8up/k8up-global`、`recovery/env.age` | k8up、復元(手元の restic) | | cloudflare-ddns | ユーザー(アカウントの一覧に無い) | 画面で確かめる(DNS Write が要る) | Infisical `/cloudflare-ddns/cloudflare-ddns-secrets` の `CLOUDFLARE_API_TOKEN` | apps/cloudflare-ddns | -| cert-manager | ユーザー(アカウントの一覧に無い) | 画面で確かめる(DNS Write が要る) | SOPS の `bootstrap/cert-manager/cloudflare-secret.yaml` | cert-manager(DNS-01) | +| cert-manager | ユーザー(アカウントの一覧に無い) | 画面で確かめる(DNS Write が要る) | SOPS の `bootstrap/cert-manager/cloudflare-secret.sops.yaml` | cert-manager(DNS-01) | | `todoroku-pulumi (state)` | アカウント | R2 バケット `todoroku-pulumi` だけの Object Read & Write | Forgejo `doa/todoroku` の secrets `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`(ID と値の SHA-256) | todoroku の `infra/`(Pulumi の state) | | `gitops pulumi apply` / `preview` | アカウント | pulumi/README.md「鍵と state」 | GitHub の secrets | gitops の Pulumi | @@ -25,7 +25,7 @@ Pulumi で作ると値を Infisical に書く鍵が CI に要る。その鍵は - **external-dns / cloudflare-ddns:** Infisical の値を差し替える。operator が Secret を書き換え、 push-bridge が同期させる。Deployment の `secrets.infisical.com/auto-reload` 注釈で入れ替わる。 - **todoroku-pulumi (state):** Forgejo の 2 つの secrets を差し替える(S3 の鍵の導き方は下の doany-restic と同じ)。 -- **cert-manager:** `tools/t.ps1 sops bootstrap/cert-manager/cloudflare-secret.yaml` で書き換えてコミットする。 +- **cert-manager:** `tools/t.ps1 sops bootstrap/cert-manager/cloudflare-secret.sops.yaml` で書き換えてコミットする。 - **doany-restic(R2):** S3 の鍵はトークンから導く。アクセスキー ID はトークンの ID、シークレットはトークンの値の SHA-256(16 進)。**2 か所を両方変える**。Infisical が古いとバックアップが落ち(k8up の通知で気づく)、`env.age` が古いと建て直しで Infisical を戻せない(こちらは誰も気づかない)。 1. Infisical `/k8up/k8up-global` の `accessKeyId` / `secretAccessKey` diff --git a/docs/talos.md b/docs/talos.md index 684ae97f..f42043ad 100644 --- a/docs/talos.md +++ b/docs/talos.md @@ -119,7 +119,8 @@ restic dump /work/etcd.snapshot > etcd.snapshot Sidero のドキュメントの「Talos only creates missing resources from inline manifests」は起動時の適用の話で、 **`talosctl apply-config` では更新も削除もされないが、`talosctl upgrade-k8s`(同じ版でも)を通せば SSA とインベントリで更新も削除もされる** -(prune は既定で有効)。プローブ用の `ConfigMap` で確かめた。この実測を根拠に `bootstrap/` をまるごと inlineManifests に載せた。 +(prune は既定で有効)。プローブ用の `ConfigMap` で確かめた。この実測を根拠に `bootstrap/` の起動に要る層(Cilium・cert-manager・ArgoCD・Infisical と SOPS の Secret)を inlineManifests に載せた。 +残りの平文は ArgoCD の Application `bootstrap` が当てる(2026-10-17 から。[bootstrap/README.md](../bootstrap/README.md))。 当て直しの手順は [talos/README.md](../talos/README.md)「上げ方 / 当て直し方」。 ## VM ブートドリル @@ -151,8 +152,8 @@ CNI の交換は構築時にやる ── 稼働中の差し替えは全 Pod 再 | レイヤー | 決めること | 変更手段 | | --- | --- | --- | | イメージ | カーネル引数、system extension(GPU ドライバ等) | Image Factory で schematic を作って `talosctl upgrade` | -| machine config | CNI、kube-proxy、ディスク、ネットワーク、`bootstrap/` の大半 | `render.sh` → `apply-config`(inlineManifests は `upgrade-k8s` まで) | -| Kubernetes | ワークロード | Argo CD(`apps/` と各リポジトリの `deploy/`) | +| machine config | CNI、kube-proxy、ディスク、ネットワーク、`bootstrap/` の chart と SOPS のファイル | `render.sh` → `apply-config`(inlineManifests は `upgrade-k8s` まで) | +| Kubernetes | ワークロード | Argo CD(`apps/`・`bootstrap/` の残りの平文・各リポジトリの `deploy/`) | SSH もシェルもパッケージマネージャも無く gRPC API だけなので、**障害時は「直さず作り直す」**。 デバッグは `talosctl dmesg` / `logs` / `read`、debug コンテナ。 diff --git a/talos/README.md b/talos/README.md index e6097187..d803a4b0 100644 --- a/talos/README.md +++ b/talos/README.md @@ -96,7 +96,7 @@ kubeconfig も talosconfig もファイルでは持たない(t.ps1 がその場 その後ろの Deployment まで当たらないことがある(2026-10-17、argo-cd 10.10.5 を当てたとき 1 回目は ArgoCD が古い版のままだった)。 当て終わったら `kubectl -n argocd get deploy -o wide` でイメージの版を見る - **何も変えていなければ `apply-config --dry-run` の差分は出ない。** 描くたびに変わる値は潰してある - (Hubble の証明書はクラスタの中で作る、infisical の `postgres-password` は secret-values.yaml に固定、`updatedAt` は `render.sh` が落とす)。 + (Hubble の証明書はクラスタの中で作る、infisical の `postgres-password` は secret-values.sops.yaml に固定、`updatedAt` は `render.sh` が落とす)。 差分が出たら、それは本当に変わったもの ### Talos 本体 diff --git a/talos/render.sh b/talos/render.sh index e59cc489..da77852c 100755 --- a/talos/render.sh +++ b/talos/render.sh @@ -112,7 +112,7 @@ inline local-path < talos/manifests/local-path.yaml > "$WORK/inline-local-path.y # 認証の側(OIDC の issuer)は patches/apiserver.yaml の KubeAuthenticationConfig。 inline apiserver-rbac < bootstrap/apiserver/rbac.yaml > "$WORK/inline-apiserver-rbac.yaml" -# 値のうち秘密だけは secret-values.yaml(SOPS)にあり、復号して values.yaml の上に重ねる。 +# 値のうち秘密だけは secret-values.sops.yaml(SOPS)にあり、復号して values.yaml の上に重ねる。 # CI は鍵を持たないので `ARGOCD_SECRET_VALUES` / `INFISICAL_SECRET_VALUES` にダミーを渡す # (SECRETS / REGISTRIES と同じ)。 # @@ -121,7 +121,7 @@ inline apiserver-rbac < bootstrap/apiserver/rbac.yaml > "$WORK/inline-apiserver- # (../docs/decisions.md「infisical だけは ArgoCD に移せない」)。 secret_values() { # $1=name $2=env の上書き if [ -n "$2" ]; then echo "$2"; return 0; fi - sops -d "bootstrap/$1/secret-values.yaml" > "$WORK/$1-secret-values.yaml" + sops -d "bootstrap/$1/secret-values.sops.yaml" > "$WORK/$1-secret-values.yaml" echo "$WORK/$1-secret-values.yaml" } # 先に変数に取る。`chart … -f "$(secret_values …)"` だと復号の失敗を `set -e` が拾わない @@ -150,8 +150,8 @@ done # Gateway の HTTPS リスナーに載せる Secret ができない。 chart cert-manager cert-manager -# SOPS 済みの Secret も入れる。infisical/secrets.yaml は infisical の起動に要る -# (kubeSecretRef)ので、machine config に無いと起動しない。どちらも ArgoCD は復号できない。cloudflare-secret.yaml は +# SOPS 済みの Secret も入れる。infisical/secrets.sops.yaml は infisical の起動に要る +# (kubeSecretRef)ので、machine config に無いと起動しない。どちらも ArgoCD は復号できない。cloudflare-secret.sops.yaml は # DNS-01 の資格情報。machine config はもともと秘密の塊なので信頼水準は変わらない。 # `sops -d … | inline` と繋がないこと。`#!/bin/sh` には `pipefail` が無いので、 # 復号に失敗しても `set -e` が拾わず、中身が空の KubeInlineManifestConfig が @@ -166,8 +166,8 @@ inline_secret() { # $1=inline の名前 $2=SOPS ファイル $3=env の上書 sops -d "$2" > "$WORK/plain-$1.yaml" inline "$1" < "$WORK/plain-$1.yaml" > "$WORK/inline-$1.yaml" } -inline_secret infisical-secrets bootstrap/infisical/secrets.yaml "${INFISICAL_SECRET:-}" -inline_secret cloudflare-secret bootstrap/cert-manager/cloudflare-secret.yaml "${CLOUDFLARE_SECRET:-}" +inline_secret infisical-secrets bootstrap/infisical/secrets.sops.yaml "${INFISICAL_SECRET:-}" +inline_secret cloudflare-secret bootstrap/cert-manager/cloudflare-secret.sops.yaml "${CLOUDFLARE_SECRET:-}" # cert-manager の CRD も URL で渡す(理由は bootstrap/cert-manager/values.yaml の `crds`)。 cat >> "$WORK/external-crds.yaml" <