From c8bf9423e5c2b096a3849438bbbc6587edea9a89 Mon Sep 17 00:00:00 2001 From: Ruk Doe Date: Sat, 31 Oct 2026 00:45:53 +0900 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20=E5=8F=A4=E3=81=8F=E3=81=AA?= =?UTF-8?q?=E3=81=A3=E3=81=9F=E8=A8=98=E8=BF=B0=E3=82=92=E7=9B=B4=E3=81=97?= =?UTF-8?q?=E3=80=81=E9=87=8D=E8=A4=87=E3=82=92=E3=81=BE=E3=81=A8=E3=82=81?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 消えたもの・古いものへの言及を直す(apps/cluster の PT3 の DaemonSet、main.yaml、 bootstrap apply、bootstrap/ の Secret の数、Argo CD が bootstrap/ の平文を当てる話、 Talos のモジュールの読み方、NetBird の DNS の例外、README の見出し) - bootstrap/README の Hubble の証明書の節は cronJob 方式と食い違うので書き直す - 同じ説明の重複をまとめる(cilium-drift、SOPS の決まり、API サーバの入口、 upgrade-k8s の --endpoint、ROADMAP の済んだ項目) - コメントの相対パスを直す(cilium-values・argocd-values・routing-peer) machine config の描き出しはバイト単位で同じ。apps/ はコメントだけ。 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01T9PbUfqG4pPxus99UeLiJs --- README.md | 22 ++++++++-------- ROADMAP.md | 10 +++----- apps/external-dns/README.md | 2 +- apps/netbird/routing-peer.yaml | 2 +- bootstrap/README.md | 42 ++++++++++++------------------- bootstrap/argocd-values.sops.yaml | 2 +- bootstrap/cilium-values.yaml | 2 +- bootstrap/talos.md | 29 +++++++++------------ docs/cloudflare-tokens.md | 2 +- docs/decisions.md | 2 +- docs/talos.md | 10 ++++---- docs/z440-migration.md | 2 +- pulumi/README.md | 2 +- pulumi/netbird.ts | 2 +- recovery/README.md | 6 ++--- tools/README.md | 4 +-- tools/creds.sh | 2 +- 17 files changed, 62 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index 30d4c362..4db1f16b 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ | | | | --- | --- | | `apps/` | Argo CD が再帰的に同期するアプリのマニフェスト。**`_` で始まるディレクトリは同期しない** (動かしていないものの置き場。下の「動かしていないもの」) | -| [`bootstrap/`](bootstrap/) | クラスタそのものを組む層。**ここにあるものは全部 machine config に載る**([render.sh](bootstrap/render.sh) が `helm template` して inlineManifest にする)。ノードの Talos の設定(**v1.14 以降の形**。手で書くのは [talos.sops.yaml](bootstrap/talos.sops.yaml) の 1 本。PR ごとに [talos-boot](.github/workflows/talos-boot.yml) が生成物を検証して VM で起動する)、Helm で入れるもの(Cilium・Argo CD 本体・Infisical・cert-manager。部品ごとに `-values.yaml` 1 本。秘密を含むものは `-values.sops.yaml` で、秘密の値だけ SOPS)、RBAC、SOPS 済みのもの | +| [`bootstrap/`](bootstrap/) | クラスタそのものを組む層。**ここにあるものは全部 machine config に載る**([render.sh](bootstrap/render.sh) が描く)。Talos の設定([talos.sops.yaml](bootstrap/talos.sops.yaml))、Helm で入れるもの(Cilium・Argo CD 本体・Infisical・cert-manager)、RBAC。PR ごとに [talos-boot](.github/workflows/talos-boot.yml) が VM で起動して確かめる | | [`pulumi/`](pulumi/) | Cloudflare(R2・DNS・ゾーンの設定・通知)・Entra(リダイレクト URI・CI の信頼の設定)・NetBird の設定を Pulumi で持つ。**PR で差分がコメントされ、main に入ると当たる** | | [`mado/`](mado/) | **`main` が落ちたときの入口**。JCOM 側の PC(10.10.0.2)で [mado](https://github.com/danything/mado)(OIDC でログインしてブラウザから RDP する exe)を動かす(`md.doany.io`。クラスタの外) | | [`recovery/`](recovery/) | **まっさらから建て直す入口**(手順・PV を戻す道具・暗号化した鍵)。git と restic だけで戻す | @@ -26,7 +26,7 @@ | [`docs/`](docs/) | [決定の記録](docs/decisions.md)、[Talos の作法と検証](docs/talos.md)、[Entra ID の認可](docs/entra.md)、[家のルーター](docs/router.md)、[Z440 への移行](docs/z440-migration.md)、[Cloudflare の API トークン](docs/cloudflare-tokens.md) | | [`ROADMAP.md`](ROADMAP.md) | やることと進捗(なぜそうしたかは `docs/decisions.md`) | | `deploy/argocd.yaml` | このリポジトリ自身の Application 定義(他のリポジトリと同じ場所) | -| [`.sops.yaml`](.sops.yaml) | 平文の秘密を SOPS(age)で暗号化する規則(`bootstrap/` の `*.sops.yaml` の 6 つ) | +| [`.sops.yaml`](.sops.yaml) | `bootstrap/*.sops.yaml` を SOPS(age)で暗号化する規則 | ## 秘密の扱い @@ -35,10 +35,10 @@ そのまま Secret のキーになる。値を変えるのは Infisical の UI だけでよく、`secrets.infisical.com/auto-reload: "true"` の注釈がある Deployment は Pod ごと入れ替わる。詳しくは [`bootstrap/README.md`](bootstrap/README.md)。 -**Infisical より下の層だけは Infisical から取れない**ので、`bootstrap/` の 4 ファイル(Infisical 自身の鍵、 -Argo CD が git を読む GitHub App 鍵、cert-manager の Cloudflare トークン)は **SOPS + age** で該当キーだけ暗号化してある。 +**Infisical より下の層だけは Infisical から取れない**ので、`bootstrap/*.sops.yaml`(クラスタの CA、Infisical 自身の鍵、 +Argo CD が git を読む GitHub App 鍵、cert-manager の Cloudflare トークン、fj.doany.io の資格情報など)は **SOPS + age** で暗号化してある。 鍵は [`recovery/sops-age.key.age`](recovery/)(バックアップの `env.age` と同じパスフレーズ)。 -当てるのは machine config(`bootstrap/render.sh` が復号して載せる)。 +当てるのは machine config(`bootstrap/render.sh` が復号して載せる)。書き方は [`bootstrap/README.md`](bootstrap/README.md)。 ```shell # 鍵はリポジトリの .home/(git に入らない)に置く。コマンドは tools/t.ps1 で動かす(tools/README.md) @@ -83,17 +83,15 @@ headlamp が 1 文字なのは、規則どおりだと head + lamp でも hubble | [`3proxy/`](apps/3proxy/) | 3proxy (国内IP経由の HTTPS フォワードプロキシ) | | [`k8up/`](apps/k8up/) | バックアップ(restic → Cloudflare R2)。PVC・DB のダンプ・etcd のスナップショット | | [`infisical/`](apps/infisical/) | 秘密の配布。本体は `bootstrap/` にあり、ここには公開経路と operator と即時反映のブリッジと SMTP のパスワード | -| [`cluster/`](apps/cluster/) | ノードまわりの小物。metrics-server(Talos に無い。`kubectl top` と各 UI の使用量表示)と、PT3 をドライバに付け直す DaemonSet | +| [`cluster/`](apps/cluster/) | metrics-server(Talos に無い。`kubectl top` と各 UI の使用量表示) | | [`smtp-relay/`](apps/smtp-relay/) | メールの中継。アプリの SMTP を受けて Microsoft 365 へ Graph で送る(Exchange Online の SMTP AUTH の Basic 認証の廃止に備えて)。**送る側の設定は [apps/smtp-relay/README.md](apps/smtp-relay/README.md)** | | [`renovate/`](apps/renovate/) | Renovate(GitHub の danything・5ym と Forgejo の doa の全リポジトリの依存を上げる PR)。CronJob で 15 分おき。**秘密の入れ方は [apps/renovate/README.md](apps/renovate/README.md)** | | [`headlamp/`](apps/headlamp/) | Kubernetes の Web UI(`h.doany.io`)。認証は Entra、権限は `bootstrap/apiserver-rbac.yaml` | | [`rybbit/`](apps/rybbit/) | Rybbit(`rt.doany.io`、アクセス解析。クッキー無し)+ ClickHouse + PostgreSQL + Redis。トドロクの離脱をファネル・ジャーニー・セッションリプレイで見る。**使い始めは [apps/rybbit/README.md](apps/rybbit/README.md)** | -**動かしていないもの**は `apps/_/` に置いてある。`_` で始まるディレクトリは Argo CD が同期しない -([bootstrap/argocd-repos.yaml](bootstrap/argocd-repos.yaml) の `directory.exclude`。全リポジトリ共通の決まり)ので、 -クラスタには何も作らない。動かすときは `git mv apps/_ apps/`。いまは無い。 +**動かしていないもの**は `apps/_/` に置く。`_` で始まるディレクトリは Argo CD が同期しない +([bootstrap/argocd-repos.yaml](bootstrap/argocd-repos.yaml) の `directory.exclude`。全リポジトリ共通の決まり)。 +動かすときは `git mv apps/_ apps/`。いまは無い。 -**アプリの多くはこのリポジトリに無い。** 各アプリのリポジトリの `deploy/` に置いてあり、 -`bootstrap/argocd-repos.yaml` の ApplicationSet が拾う(上の「仕組み」)。 -`kubectl -n argocd get applications` が実際の一覧。 +**アプリの多くはこのリポジトリに無い**(各リポジトリの `deploy/`。上の「仕組み」)。実際の一覧は `kubectl -n argocd get applications`。 diff --git a/ROADMAP.md b/ROADMAP.md index 0fd40295..791ecc02 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -27,14 +27,12 @@ bond0 の MAC は設定で固定してあるのでルーターは触らない。 ## Phase 3 — Talos 定常運用 - [ ] **Talos 1.15.0 の正式版が出たら乗り換える**(Renovate の PR) -- [x] **上流がカーネルにモジュールを必要な時に読ませる仕組み(modprobe の helper)を入れたら**、pt3-rebind を外し、 - `bootstrap/talos.sops.yaml` の `kernel.modules` を `earth-pt3` だけにする。並び順を守る PR([siderolabs/talos#14652](https://github.com/siderolabs/talos/pull/14652))は - 2026-10-23 に「並び順ではなく、カーネルが必要な時に読み込む形にすべき。こちらで別に実装する」(smira)として閉じられ、 - その実装 [siderolabs/talos#14724](https://github.com/siderolabs/talos/pull/14724) が 2026-10-24 にマージされて v1.15.0-alpha.2 に入った。 - 2026-10-24 に v1.15.0-alpha.1 + この PR を自前で組んだ installer で実機を起こし、`earth-pt3` だけでチューナー 4 つが付くことは確かめてあった。 - alpha.2 に上げる PR(#607)で pt3-rebind を消し、`kernel.modules` を `earth-pt3` だけにした。2026-10-29 に公式の alpha.2 へ upgrade し、earth_pt3 から tc90522・qm1d1c0042・mxl301rf が自動で読まれてチューナー 4 つ(adapter0〜3 と frontend0)が付くのを確かめた。Kubernetes も 1.37.2 になった ## 済んだこと(記録) - **Talos へ移した(2026-10-17)。** git から建て直し、PV を restic から戻した([recovery/README.md](recovery/README.md)) - **バックアップと復元の確認を自動に。** restic + k8up で日次、etcd も日次、月次の取り出し確認、machine config は PR ごとに QEMU で起動([apps/k8up/README.md](apps/k8up/README.md)) +- **PT3 の付け直し(pt3-rebind)を外した(2026-10-29)。** 並び順を守る PR([siderolabs/talos#14652](https://github.com/siderolabs/talos/pull/14652))は + 「カーネルが必要な時に読み込む形にすべき」(smira)として閉じられ、その実装 [siderolabs/talos#14724](https://github.com/siderolabs/talos/pull/14724) が + v1.15.0-alpha.2 に入った。#607 で `kernel.modules` を `earth-pt3` だけにし、alpha.2(Kubernetes 1.37.2)に上げて、 + tc90522・qm1d1c0042・mxl301rf が自動で読まれてチューナー 4 つ(adapter0〜3 と frontend0)が付くのを確かめた diff --git a/apps/external-dns/README.md b/apps/external-dns/README.md index ea6d9815..79eab541 100644 --- a/apps/external-dns/README.md +++ b/apps/external-dns/README.md @@ -43,7 +43,7 @@ metadata: - アプリから見える接続元は Cloudflare の IP。本当の接続元は `CF-Connecting-IP`(Rybbit は自分で読む) - 応答が 100 秒を超えると 524、リクエストの本文は 100MB まで(無料プラン) - SSL は Full (strict)(`pulumi/dns.ts` の zone 設定)。Gateway の Let's Encrypt の証明書で足りる -- NetBird につないでいる端末は、NetBird の DNS(`pulumi/netbird.ts`)で `*.doany.io` を 10.0.0.2 に引くので Cloudflare を通らない +- NetBird につないでいる端末は、NetBird の DNS(`pulumi/netbird.ts`)で `*.doany.io` を 10.0.0.2 に引くので Cloudflare を通らない(`nb`・`md`・`autodiscover` を除く) ## 触るもの・触らないもの diff --git a/apps/netbird/routing-peer.yaml b/apps/netbird/routing-peer.yaml index ff7aae73..3579dadc 100644 --- a/apps/netbird/routing-peer.yaml +++ b/apps/netbird/routing-peer.yaml @@ -106,7 +106,7 @@ spec: - name: data mountPath: /var/lib/netbird # カーネルの wireguard が使えないときのユーザ空間フォールバック用。 - # Talos でもカーネル組み込みは確認済み(bootstrap/talos.md)なので通常は使わない + # Talos でもカーネル組み込みは確認済みなので通常は使わない - name: tun mountPath: /dev/net/tun volumes: diff --git a/bootstrap/README.md b/bootstrap/README.md index 059d4b28..f6f0e243 100644 --- a/bootstrap/README.md +++ b/bootstrap/README.md @@ -74,8 +74,7 @@ Namespace は chart が描かないので、`render.sh` が kube-system 以外 ## git と live がずれていないか -**cilium は [cilium-drift.yml](../.github/workflows/cilium-drift.yml) が週次で見ている**(値が `cilium-config` という -ConfigMap に出ているので、読むだけの権限で比べられる)。**残りは見ていない。** 当て忘れは `upgrade-k8s` の差分に出るので、 +**cilium だけは [cilium-drift.yml](../.github/workflows/cilium-drift.yml) が見ている**(下の「cilium」)。**残りは見ていない。** 直したら流す(流し忘れたことは誰も教えてくれない)。描くたびに変わる値は潰してあるので、 `apply-config --dry-run` に出る差分は全部本物([talos.md](talos.md)「inlineManifests を直したとき」)。 @@ -89,18 +88,13 @@ ConfigMap に出ているので、読むだけの権限で比べられる)。** `render.sh` がここから描く派生物(二度書かない。decisions.md「machine config と Cilium の chart をどう連動させるか」)。 **どの設定が何のために要るかは [cilium-values.yaml](cilium-values.yaml) のコメントにある**(ここには写さない)。 -### 描き直すたびに Hubble の証明書が入れ替わる - -チャートの `hubble/tls-helm/*` は毎回 `genCA` / `genSignedCert` で作り直す -(`cilium.io/helm-template-non-idempotent: "true"`)。**値を 1 行も変えなくても、`hubble-ca-secret` / -`hubble-server-certs` / `hubble-relay-client-certs` の 3 つは `upgrade-k8s` の差分に出る。** -実害は無い(エージェントも Relay もファイルの入れ替わりに追従する。Pod の再起動は要らない)。 -`cilium-dbg status` の `Hubble: Ok` と `hubble-relay` の Ready で確かめる。 +**Hubble の証明書はクラスタの中の CronJob が作る**(`hubble.tls.auto.method: cronJob`)。chart の既定(`helm`)は描くたびに +作り直して machine config に秘密鍵が載り、値を変えなくても `upgrade-k8s` の差分に出ていた。 ### ズレは CI が見ている **当て忘れとクラスタ側の直接編集は [cilium-drift.yml](../.github/workflows/cilium-drift.yml) が見つける。** -`cilium-values.yaml` から ConfigMap を描いて live と突き合わせるだけで、**読むだけ**(権限は `cilium-config` の `get` 1 つ)。 +`cilium-values.yaml` から `cilium-config` の ConfigMap を描いて live と突き合わせるだけで、**読むだけ**(権限は `cilium-config` の `get` 1 つ)。 `cilium-values.yaml` を触ったときと毎週月曜に走る。当てるのは自動化しない(Talos API の os:admin を CI に置かない)。 ### 当てたあとに確認すること @@ -115,18 +109,15 @@ kubectl -n kube-system get gateway doany ## Secret 平文の Secret はアプリのリポジトリにはコミットしない。値は **Infisical**(https://il.doany.io、このクラスタでセルフホスト)が持ち、 -**Infisical 純正 operator**(`apps/infisical/operator.yaml`)が各リポジトリの `InfisicalSecret` を見て Infisical から値を取り、普通の `Secret` を作る。 -認証は Kubernetes 方式(TokenReview・長命の資格情報なし)。 - -- `infisical-*` … Infisical 本体(chart + Postgres/Redis)。公開経路は [`apps/infisical/httproute.yaml`](../apps/infisical/httproute.yaml)。 - `infisical-values.sops.yaml` の 2 つめのドキュメントの `ENCRYPTION_KEY` が DB の暗号鍵で、これを失うと Infisical の中身が全部読めなくなる - (クラスタで一番失ってはいけない値)。Postgres の PVC は既定の `local-path` で、`pg_dump` を k8up が日次で取っている。 -- **operator と push-bridge はここには無い**(`apps/infisical/operator.yaml`、`apps/infisical/push-bridge.yaml`)。 - ArgoCD 自身は operator に依存しないので、bootstrap に置く理由がない。 - 認証は Infisical の Kubernetes auth: operator が SA `infisical-auth` のトークンで Infisical にログインし、 - Infisical がそのトークンで TokenReview を呼んで本物か確かめる(なので SA に `system:auth-delegator` を - 付けてある)。SA と RBAC は `apps/infisical/operator-rbac.yaml`。 - operator 側に長期の資格情報は無い(`identityId` は秘密ではない)。 +**Infisical 純正 operator** が各リポジトリの `InfisicalSecret` を見て Infisical から値を取り、普通の `Secret` を作る。 + +- **本体**(chart + Postgres/Redis)だけがここ(machine config)。`infisical-values.sops.yaml` の 2 つめのドキュメントの + `ENCRYPTION_KEY` が DB の暗号鍵で、これを失うと Infisical の中身が全部読めなくなる(クラスタで一番失ってはいけない値)。 + Postgres の PVC は `local-path` で、`pg_dump` を k8up が日次で取っている。 +- **公開経路・operator・push-bridge は [`apps/infisical/`](../apps/infisical/)**(ArgoCD 自身は operator に依存しないので、ここに置く理由がない)。 +- 認証は Infisical の Kubernetes auth: operator が SA `infisical-auth` のトークンで Infisical にログインし、 + Infisical がそのトークンで TokenReview を呼んで本物か確かめる(なので SA に `system:auth-delegator` を付けてある。 + `apps/infisical/operator-rbac.yaml`)。長命の資格情報はどこにも無い(`identityId` は秘密ではない)。 ### API サーバの入口(GitHub Actions と人) @@ -140,10 +131,9 @@ kubeconfig も age 鍵も GitHub に置いていない。 Headlamp が利用者本人の id_token を API サーバへ転送する。アプリロール `admin` を持つ人は `entra:admin` で cluster-admin、それ以外は `entra:viewer` で読み取り専用(組み込みの `view` + CRD とノードぶんの `readonly-extra`)。**振り分けは CEL で、割り当ては Entra 側で完結する。** -ここに置いたのは、ArgoCD も CI も要らずに効く層だから ── 締め出されたときに直せる。 -認証設定([talos.sops.yaml](talos.sops.yaml))も [apiserver-rbac.yaml](apiserver-rbac.yaml) も -machine config に載っているので、変えたら `render.sh` → `apply-config`(RBAC は inlineManifest なので `upgrade-k8s` まで)。 -**ArgoCD には当てさせない**(締め出されたときに直せる層に置く)。 +認証設定([talos.sops.yaml](talos.sops.yaml))も [apiserver-rbac.yaml](apiserver-rbac.yaml) も machine config に載せ、 +**ArgoCD には当てさせない**(ArgoCD も CI も要らずに効く層なので、締め出されたときに直せる)。 +変えたら `render.sh` → `apply-config`(RBAC は inlineManifest なので `upgrade-k8s` まで)。 ### Infisical の中の構成 diff --git a/bootstrap/argocd-values.sops.yaml b/bootstrap/argocd-values.sops.yaml index e832562e..b7dfcbfa 100644 --- a/bootstrap/argocd-values.sops.yaml +++ b/bootstrap/argocd-values.sops.yaml @@ -13,7 +13,7 @@ redis: image: repository: mirror.gcr.io/library/redis tag: 8.10.3-alpine -# Dex を使わず Entra ID に直接 OIDC(auth/deployment.yaml と同じアプリ登録) +# Dex を使わず Entra ID に直接 OIDC(../apps/auth/deployment.yaml と同じアプリ登録) dex: enabled: false configs: diff --git a/bootstrap/cilium-values.yaml b/bootstrap/cilium-values.yaml index 5a9453a9..6686bd63 100644 --- a/bootstrap/cilium-values.yaml +++ b/bootstrap/cilium-values.yaml @@ -48,7 +48,7 @@ gatewayAPI: # 全リスナーが HTTP/2 になるが、WebSocket はブラウザが HTTP/1.1 に落ちるので動く。 enableAlpn: true -# UI 自身は認証を持たない。前段の oauth2-proxy(../auth/hubble-proxy.yaml)で守る。UI の Service を直接 HTTPRoute に繋がない。 +# UI 自身は認証を持たない。前段の oauth2-proxy(../apps/auth/hubble-proxy.yaml)で守る。UI の Service を直接 HTTPRoute に繋がない。 hubble: relay: enabled: true diff --git a/bootstrap/talos.md b/bootstrap/talos.md index ff733cbe..bfb204a1 100644 --- a/bootstrap/talos.md +++ b/bootstrap/talos.md @@ -1,12 +1,11 @@ # talos ノード `main`(HP ProLiant DL360 Gen9)の machine config。**v1.14 以降の型付きドキュメントの形で書いてある** -(版は [talos.sops.yaml](talos.sops.yaml) の先頭のコメント。1.13 以前とは別物。作法は [../docs/talos.md](../docs/talos.md))。 +(1.13 以前とは別物。作法は [../docs/talos.md](../docs/talos.md))。 **入れ方(まっさらから建てる手順)は [../recovery/README.md](../recovery/README.md)。** ここは組み立てと当て直し。 **版と schematic の出どころは [talos.sops.yaml](talos.sops.yaml) の先頭のコメント(`# version:` と `# schematic:`)。** Renovate がそこを見て、 -新しい Talos が出たら PR を作る。**適用は自動化しない**(下の「適用は CI にやらせない」)。 -コマンドに埋めてある版と schematic も、変えるときはそこと揃えること。talhelper は使わない。 +新しい Talos が出たら PR を作る。**適用は自動化しない**(下の「適用は CI にやらせない」)。talhelper は使わない。 **組み立ては [render.sh](render.sh) が全部やる。** 手で書く部分は [talos.sops.yaml](talos.sops.yaml) の 1 本だけで、 他から描いてくる部分(Cilium・cert-manager・argocd・infisical は `-values(.sops).yaml` から、 @@ -18,17 +17,13 @@ CI([talos-boot](../.github/workflows/talos-boot.yml))も同じ `render.sh` を ./bootstrap/render.sh bootstrap/clusterconfig # 出力先は丸ごと消して作り直す(.gitignore 済み) ``` -**描いた machine config(`clusterconfig/controlplane.yaml`)を丸ごとコミットしないのは**、生成物の 9 割が chart を描いたもの(約 300 KB の 1 行文字列)で、 -読めず、chart や Kubernetes の版を上げるたびに描き直しのコミットが要るから。 +描いた machine config はコミットしない(理由は [../docs/decisions.md](../docs/decisions.md)「machine config と Cilium の chart をどう連動させるか」)。 **inlineManifest をファイルで指す仕組みは Talos に無い**(machine config はノードが読むので手元のパスは書けない。 外を指せるのは URL の `KubeExternalManifestConfig` だけで、CRD はそれで渡している)。ファイルを包むのは render.sh の `inline`。 -**秘密は 2 か所、どちらも SOPS でコミット済み**(規則は [`../.sops.yaml`](../.sops.yaml)。**平文は git に入れない**)。 - -- [talos-secrets.sops.yaml](talos-secrets.sops.yaml): クラスタの CA 一式(`talosctl gen secrets` の形)。丸ごと暗号化 -- [talos.sops.yaml](talos.sops.yaml): `password` の値(下の fj.doany.io の資格情報)**だけ**をその場で暗号化。 - ほかは平文のまま読めて、`sops` を通さず直接直せる(`mac_only_encrypted`)。パスワードを変えるときだけ `sops edit bootstrap/talos.sops.yaml`。 - SOPS は**ドキュメントごとに `sops:` のメタデータを付け、インデントを 4 にする**(触らない)。render.sh は `sops -d` してから渡す +**Talos の秘密は 2 か所、どちらも SOPS でコミット済み**(暗号化の決まりは [README.md](README.md) の「ファイル」の下)。 +[talos-secrets.sops.yaml](talos-secrets.sops.yaml) はクラスタの CA 一式(`talosctl gen secrets` の形)で丸ごと、 +[talos.sops.yaml](talos.sops.yaml) は `password` の値(下の fj.doany.io の資格情報)**だけ**。 **`talos-secrets.sops.yaml` を作り直すと別のクラスタになる**(`apiserver-ca.crt` と Infisical の Kubernetes auth の CA も 替えることになる)ので触らない。まっさらから組むときだけ: @@ -67,8 +62,8 @@ needle は `render.sh` の末尾の 1 か所だけに置く。 | 変えたもの | やること | 停止 | | --- | --- | --- | | `talos.sops.yaml` の先頭の Talos の `# version:`(または `# schematic:`) | `talosctl upgrade --image factory.talos.dev/installer/:<版> --k8s-endpoint https://10.10.0.4:6443` | **再起動** | -| `talos.sops.yaml` の先頭の Kubernetes の `# version:` | `render.sh` → `apply-config` → `talosctl upgrade-k8s --to <版>` | 無し | -| `talos.sops.yaml` の本文と、`bootstrap/` の残りの全部(`*-values.yaml`・`*-values.sops.yaml`(2 つめのドキュメントの Secret も)・`apiserver-rbac.yaml`・`local-path.yaml`) | `render.sh` → `apply-config` → `talosctl upgrade-k8s` | 場合による | +| `talos.sops.yaml` の先頭の Kubernetes の `# version:` | `render.sh` → `apply-config` → `talosctl upgrade-k8s --to <新しい版>` | 無し | +| `talos.sops.yaml` の本文と、`bootstrap/` の残りの全部(`*-values(.sops).yaml`(2 つめのドキュメントの Secret も)・`apiserver-rbac.yaml`・`local-path.yaml`) | `render.sh` → `apply-config` → `talosctl upgrade-k8s --to <今の版>`(下の「inlineManifests を直したとき」) | 場合による | ### inlineManifests を直したとき @@ -87,6 +82,8 @@ talosctl upgrade-k8s --to --end - **`upgrade-k8s` には必ず `--to` を付ける。** 省くと talosctl の既定の版に上がる(Talos の alpha の talosctl なら Kubernetes も alpha)。 版を変えないなら `talos.sops.yaml` の先頭の今の版を渡す +- **`--endpoint https://10.10.0.4:6443` も付ける。** `upgrade-k8s` は Kubernetes の API に直接繋ぎに行き、既定ではクラスタの + endpoint(10.0.0.2)へ行くので作業用 PC からは届かない - **`apply-config` の直後に流さない。** machine config から `manifests` の資源が作り直されるまで少しかかり、その前に流すと**古いマニフェストで 「変更なし」のまま終わる**(2026-10-23 に Cilium 1.20.4 で踏んだ)。`talosctl get manifests` に新しい版が出てから流す @@ -119,7 +116,5 @@ talosctl upgrade --image factory.talos.dev/installer/:<版> --k8s-end ### 当てても効かないもの -- **ディスクの割り方**(talos.sops.yaml の `VolumeConfig` / `UserVolumeConfig`)。ボリュームは**まだ確保されていないときにしか - 効かない**ので、あとから `apply-config` しても黙って無視される。変えるには入れ直し -- **`talosctl upgrade-k8s` は Kubernetes の API に直接繋ぎに行く。** 既定ではクラスタの endpoint(10.0.0.2)へ行き、 - 作業用 PC からは届かないので `--endpoint https://10.10.0.4:6443` を渡す +**ディスクの割り方**(talos.sops.yaml の `VolumeConfig` / `UserVolumeConfig`)。ボリュームは**まだ確保されていないときにしか +効かない**ので、あとから `apply-config` しても黙って無視される。変えるには入れ直し。 diff --git a/docs/cloudflare-tokens.md b/docs/cloudflare-tokens.md index 3b094985..e02ae77e 100644 --- a/docs/cloudflare-tokens.md +++ b/docs/cloudflare-tokens.md @@ -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-values.sops.yaml` で書き換えてコミットする。 +- **cert-manager:** `tools/t.ps1 sops edit bootstrap/cert-manager-values.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/decisions.md b/docs/decisions.md index fc665331..68ac10ff 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -50,7 +50,7 @@ Object Read & Write をこのバケットだけに絞った Account API token。 | R2 の鍵 + restic のパスフレーズ | `recovery/env.age`(公開 repo) | **パスフレーズで直接**(`age -d`) | | SOPS の age 秘密鍵 | `recovery/sops-age.key.age`(公開 repo) | **パスフレーズで直接**(`age -d`) | | Talos の `secrets.yaml` | `bootstrap/talos-secrets.sops.yaml`(公開 repo・SOPS 済み) | 上の age 鍵で(`sops -d`) | -| `bootstrap/` の Secret 4 つ | 公開 repo・SOPS 済み | 同上 | +| `bootstrap/` の残りの `*.sops.yaml`(chart の値の秘密、fj.doany.io の資格情報) | 公開 repo・SOPS 済み | 同上 | **`recovery/` の 2 つだけ `age -p` なのは、それが「まだ何も無い状態で最初に開けるもの」だから。** それ以外は age 鍵さえ手に入れば開くので、`bootstrap/` と同じ SOPS に揃えてある。 diff --git a/docs/talos.md b/docs/talos.md index e03bbeb5..d02952a0 100644 --- a/docs/talos.md +++ b/docs/talos.md @@ -34,8 +34,8 @@ curl -X POST --data-binary @schematic.yaml https://factory.talos.dev/schematics | 用途 | URL | | --- | --- | -| ISO(Secure Boot オフ) | `https://factory.talos.dev/image/96371c8f…/v1.15.0-alpha.2/metal-amd64.iso`(Secure Boot 用の `metal-amd64-secureboot.iso` は UEFI に鍵登録が要るので使わない) | -| `--install-image` と `talosctl upgrade --image` | `factory.talos.dev/installer/96371c8f…:v1.15.0-alpha.2` | +| ISO(Secure Boot オフ) | `https://factory.talos.dev/image//<版>/metal-amd64.iso`(Secure Boot 用の `metal-amd64-secureboot.iso` は UEFI に鍵登録が要るので使わない) | +| `--install-image` と `talosctl upgrade --image` | `factory.talos.dev/installer/:<版>` | プレリリース(alpha / beta)も同じ形の URL で取れる。extension を足したくなったら schematic を作り直して ID を差し替え、 `talosctl upgrade` で当てる(ISO を焼き直す必要はない)。 @@ -55,7 +55,7 @@ curl -X POST --data-binary @schematic.yaml https://factory.talos.dev/schematics | PV の置き場 | `UserVolumeConfig`。マウント先(`/var/mnt/`)は kubelet に自動で通るので `extraMounts` は要らない([talos.sops.yaml](../bootstrap/talos.sops.yaml))。ディスク上のラベルは `u-` | | control-plane への scheduling 許可 | v1alpha1 の `allowSchedulingOnControlPlanes` は弾かれる。**`KubeNodeConfig` を `$patch: delete` して `labels` だけ書き戻す**([talos.sops.yaml](../bootstrap/talos.sops.yaml)) | | CNI を止める | `KubeFlannelCNIConfig` を `$patch: delete`、`KubeProxyConfig` を `enabled: false`([talos.sops.yaml](../bootstrap/talos.sops.yaml))。**v1alpha1 の `cni.name: none` はもう書けない** | -| カーネルモジュール | `machine.kernel.modules`。**並べた順ではなく名前の順に読まれる**。Talos 1.14 以降は usermode の modprobe helper が無い(`/proc/sys/kernel/modprobe` が空)ので、`request_module` で依存を引くドライバは順番が狂うと失敗する(PT3 で踏んだ。[talos.sops.yaml](../bootstrap/talos.sops.yaml)。上流は並び順ではなく、カーネルが必要な時に読み込む形で直す方針。ROADMAP) | +| カーネルモジュール | `machine.kernel.modules`。**並べた順ではなく名前の順に読まれる**。v1.15.0-alpha.2 からはカーネルの要求(`request_module`)でも読むので、書くのは自分からは読まれないものだけでよい(PT3 は `earth-pt3` だけ。[talos.sops.yaml](../bootstrap/talos.sops.yaml)、[decisions.md](decisions.md)「PT3 チューナー」) | ### PSA のラベル(Pod Security Admission が既定で `baseline`) @@ -124,7 +124,7 @@ Sidero のドキュメントの「Talos only creates missing resources from inli [.github/workflows/talos-boot.yml](../.github/workflows/talos-boot.yml) が PR ごとに描いた machine config を QEMU で起動して見る。 見つけた穴は直した場所(`bootstrap/talos.sops.yaml`・`bootstrap/render.sh`)に理由を書いてある。 -VM では確かめられないもの: PT3 のモジュールの読み順、bond のフェイルオーバーの復旧方向(落とす方向は 8 秒以内で `talosctl` は途切れない)。 +VM では確かめられないもの: PT3(実機のカードが要る)、bond のフェイルオーバーの復旧方向(落とす方向は 8 秒以内で `talosctl` は途切れない)。 - **v1.14 以降の `talosctl` は `--nodes` / `--endpoints` がグローバルフラグではない。** `talosctl get links --insecure -n … -e …` の順で書く。 `talosctl apply-config -m reboot` は無い(`auto` / `no-reboot` / `staged` / `try`) @@ -147,7 +147,7 @@ LoadBalancer とクライアント IP も decisions.md「ルーティングの | --- | --- | --- | | イメージ | カーネル引数、system extension(GPU ドライバ等) | Image Factory で schematic を作って `talosctl upgrade` | | machine config | CNI、kube-proxy、ディスク、ネットワーク、`bootstrap/` の chart と SOPS のファイル | `render.sh` → `apply-config`(inlineManifests は `upgrade-k8s` まで) | -| Kubernetes | ワークロード | Argo CD(`apps/`・`bootstrap/` の残りの平文・各リポジトリの `deploy/`) | +| Kubernetes | ワークロード | Argo CD(`apps/`・各リポジトリの `deploy/`) | SSH もシェルもパッケージマネージャも無く gRPC API だけなので、**障害時は「直さず作り直す」**。 デバッグは `talosctl dmesg` / `logs` / `read`、debug コンテナ。 diff --git a/docs/z440-migration.md b/docs/z440-migration.md index d5a39a47..4d2b3076 100644 --- a/docs/z440-migration.md +++ b/docs/z440-migration.md @@ -93,7 +93,7 @@ AMT の SOL は、OS からは PCI のシリアルポート(「Intel … KT Cont 2. Image Factory の schematic の `customization.extraKernelArgs` に `console=tty0` と `console=ttyS<番号>,115200n8` を足し、 新しい schematic ID で `talosctl upgrade --image factory.talos.dev/installer/:<版>`(再起動する)。 カーネル引数は machine config に書けない(`bootstrap/talos.sops.yaml` の注、[talos.md](talos.md))。 - schematic ID は `bootstrap/talos.sops.yaml` の先頭の `# schematic:` と `main.yaml` の注も揃える。**Arc の extension を足すのも同じ手順**なので一緒にやる + schematic ID は `bootstrap/talos.sops.yaml` の先頭の `# schematic:` に書く(Renovate と render.sh はそこを読む)。**Arc の extension を足すのも同じ手順**なので一緒にやる (`siderolabs/i915` で足りるか要確認。Arc B シリーズなどは `siderolabs/xe`。**両方は入れない** ── 同じ GPU を取り合う) ### つなぎ方 diff --git a/pulumi/README.md b/pulumi/README.md index 4a760cf5..7debc989 100644 --- a/pulumi/README.md +++ b/pulumi/README.md @@ -116,7 +116,7 @@ apply 用は「自分が所有者のアプリ登録」しか書けない。所 し、作り直した bun.lock を同じ枝にコミットさせる。手元・CI と同じ `pulumi install` で作るので、CI の lock の確認とずれない。 実行の許可は [apps/renovate/renovate.yaml](../apps/renovate/renovate.yaml) の `RENOVATE_ALLOWED_COMMANDS` - `*.doany.io` を家の 10.0.0.2 に向けているのは、exit ノード越しに家の外向きの IPv4 を引くと折り返しで届かないため。 - `nb.doany.io` だけは外向きのアドレスで例外にしている。アドレスは書かず、2 段の名前 `nb.origin.doany.io` (ゾーンのワイルドカードに当たらず Cloudflare で引かれ、cloudflare-ddns が追従させる) に CNAME で向ける + 家の Gateway に無い名前は例外にしている。`nb.doany.io` はアドレスを書かず、2 段の名前 `nb.origin.doany.io` (ゾーンのワイルドカードに当たらず Cloudflare で引かれ、cloudflare-ddns が追従させる) に CNAME で向ける。`md.doany.io` (mado) と `autodiscover` は外向きと同じ先を書く | 鍵 | どこ | NetBird のサービスユーザー | | --- | --- | --- | diff --git a/pulumi/netbird.ts b/pulumi/netbird.ts index 1cfd6155..8beb0980 100644 --- a/pulumi/netbird.ts +++ b/pulumi/netbird.ts @@ -34,7 +34,7 @@ new netbird.NameserverGroup( new netbird.DnsSettings("settings", { disabledManagementGroups: [] }, { provider }); // *.doany.io を家の Gateway に向ける (外向きの IPv4 は家のルーターで折り返せず届かない)。 -// nb.doany.io だけは外向きのまま (内部に向けると、トンネルが切れたときに戻ってこられない) +// nb.doany.io は外向きのまま (内部に向けると、トンネルが切れたときに戻ってこられない)。ほかの例外は下の md・autodiscover const zone = new netbird.DnsZone( "doany-io", { name: "doany.io", domain: "doany.io", enabled: true, enableSearchDomain: false, distributionGroups: [ALL] }, diff --git a/recovery/README.md b/recovery/README.md index 11acd87e..51c44b9f 100644 --- a/recovery/README.md +++ b/recovery/README.md @@ -11,7 +11,7 @@ | [pv.sh](pv.sh) | PV のデータを k8up の `Restore` で戻す道具(下の 8) | | [infisical.sh](infisical.sh) / [infisical-ca.mjs](infisical-ca.mjs) | Infisical を restic から直接戻す道具(下の 6・7) | -**2 つの道具は、2026-10-17 に使ったものから決め打ちを外した形で、この形ではまだ流していない。** 次の建て直しで最初に確かめる(`pv.sh - plan-all` は 2026-10-20 に本番の restic と突き合わせて、全 namespace の判定が上の表どおりになるのを確かめた)。 +**2 つの道具は、2026-10-17 に使ったものから決め打ちを外した形で、この形ではまだ流していない。** 次の建て直しで最初に確かめる(`pv.sh - plan-all` は 2026-10-20 に本番の restic と突き合わせて、全 namespace の判定が 8 の表どおりになるのを確かめた)。 **手動のリハーサルは回さない。** 中身は月次の [restore-check](../apps/k8up/restore-check.yaml)、machine config は [talos-boot](../.github/workflows/talos-boot.yml) が確かめる。残るのはこの手順書の通し(道具そのもの)だけ。 @@ -78,7 +78,7 @@ curl -LO https://factory.talos.dev/image/96371c8f956f7f5f9d09925bb49fe096c0cad05 - **Secure Boot が Disabled**(RBSU は POST 中に F9 → Server Security → Secure Boot Settings)。Boot Mode は UEFI のまま - POST 中に **F11** で USB を選ぶ(iLO の Virtual Media なら Image File CD-ROM/DVD に ISO の URL を貼り、Reset して F11) - コンソールに maintenance mode の IP が出る。インタフェースが `eno1` / `eno2` / `eno4`、インストール先が `/dev/sda`(447 GB)であること - (違ったら `bootstrap/talos.sops.yaml` / `main.yaml` を直して 1 に戻る。**`diskSelector` の先は書いたら消える**): + (違ったら `bootstrap/talos.sops.yaml` を直して 1 に戻る。**`diskSelector` の先は書いたら消える**): ```shell IP=<コンソールに出た IP> @@ -238,6 +238,6 @@ rm -f ~/.config/restic.env ~/infisical-load.log | Pod が Pending | **PSA のラベル**([../docs/talos.md](../docs/talos.md)「PSA のラベル」)か、control-plane の taint | | PVC が Bound しない | local-path の ConfigMap に `setup` / `teardown` があるか | | 非公開イメージが引けない | `bootstrap/talos.sops.yaml` の fj.doany.io の `password` が machine config に入っているか、Forgejo が戻っているか(8) | -| bootstrap apply が TLS で落ちる | `talos-secrets.sops.yaml` を作り直した。`bootstrap/apiserver-ca.crt` を新しい `talos-secrets.sops.yaml` の Kubernetes の CA(`certs.k8s.crt` を base64 で戻したもの)にする | +| cilium-drift が TLS で落ちる | `talos-secrets.sops.yaml` を作り直した。`bootstrap/apiserver-ca.crt` を新しい `talos-secrets.sops.yaml` の Kubernetes の CA(`certs.k8s.crt` を base64 で戻したもの)にする | | Application が `OutOfSync / Missing` のまま | `retry`(約 33 分)で自力で戻る。30 分以上動かなければ `kubectl -n argocd patch application <名前> --type=merge -p '{"operation":{"sync":{"revision":"HEAD"},"initiatedBy":{"username":"me"}}}'`。**chart のものは `HEAD` ではなく `spec.source.targetRevision` の値** | | inlineManifest を直したのに効かない | `render.sh` → `apply-config` → **`upgrade-k8s`**([../bootstrap/talos.md](../bootstrap/talos.md)「上げ方 / 当て直し方」) | diff --git a/tools/README.md b/tools/README.md index 86998605..94236479 100644 --- a/tools/README.md +++ b/tools/README.md @@ -33,7 +33,7 @@ tools/t.ps1 # 引数なしならシェルに入る クラスタの資格情報はここにも置かない(下の「クラスタの資格情報」)。 `.home/` は本人だけが読める ACL にする - **`git clean -fdx` で消える**(無視しているファイルも消すため)。age 鍵は `recovery/sops-age.key.age` から戻せる - (README「Infisical より下の層」)、ほかはログインし直せば戻る + (README「秘密の扱い」)、ほかはログインし直せば戻る - Dockerfile を変えると、次の `tools/t.ps1` でイメージを作り直す(変わっていなければキャッシュで一瞬) - パイプやリダイレクトのときは TTY を付けない(`tools/t.ps1` が見分ける) - PowerShell でパイプしたもの(`tools/t.ps1 sops -d … | tools/t.ps1 --admin kubectl apply -f -`)は、`t.ps1` がコンテナの標準入力に流し直す。 @@ -80,7 +80,7 @@ tools/t.ps1 # 引数なしならシェルに入る 1 秒ほど以上かかるコマンドの出力が落ちて `ERROR_INVALID_HANDLE` で終わるので、`t.ps1` はそのときだけ空のパイプを渡す。 NUL かどうかは標準入力の種類(`GetFileType`)で見分けるので、ファイルや外のパイプからの入力は今までどおり届く - NetBird の exit ノード越しだと `*.doany.io` を外向きの IPv4 で引いたときに届かないので、NetBird の DNS ゾーンで - 内部の 10.0.0.2 に向けている(`nb.doany.io` だけは例外) + 内部の 10.0.0.2 に向けている(`nb`・`md`・`autodiscover` は例外。[../pulumi/netbird.ts](../pulumi/netbird.ts)) ## 入れるものの確かめ方 diff --git a/tools/creds.sh b/tools/creds.sh index a749602e..f1c4dd57 100755 --- a/tools/creds.sh +++ b/tools/creds.sh @@ -39,7 +39,7 @@ esac if [ "${GITOPS_ADMIN:-}" = 1 ]; then role=admin; else role=readonly; fi mkdir -p -m 700 "$shm" cd /repo -nokey() { [ -s ~/.config/sops/age/keys.txt ] || die "age の鍵が無い(README「Infisical より下の層」の 1 行目で .home に置く)"; } +nokey() { [ -s ~/.config/sops/age/keys.txt ] || die "age の鍵が無い(README「秘密の扱い」の 1 行目で .home に置く)"; } # CA($1 = os か k8s)で件名 $2・鍵 $4(ed25519 / EC)の証明書を作り $3.crt / $3.key / $3.ca に置く。 # ノードの時計の遅れを見て 5 分前から有効にする。CA の鍵が出る $w はすぐ消す。 From a7b3b0bb2c8c051f79990f619fdd60c2abafb00e Mon Sep 17 00:00:00 2001 From: Ruk Doe Date: Sat, 31 Oct 2026 00:47:25 +0900 Subject: [PATCH 2/2] =?UTF-8?q?docs(k8up):=20SQLite=20=E3=81=AE=E8=A1=8C?= =?UTF-8?q?=E3=81=AE=20namespace=20=E3=81=AF=20blog=20=E3=81=A7=E3=81=AF?= =?UTF-8?q?=E3=81=AA=E3=81=8F=20yosegaki?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01T9PbUfqG4pPxus99UeLiJs --- apps/k8up/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/k8up/README.md b/apps/k8up/README.md index f61417c5..b43a6a66 100644 --- a/apps/k8up/README.md +++ b/apps/k8up/README.md @@ -15,7 +15,7 @@ | forgejo | postgres の `pg_dump` + リポジトリの PVC(ファイル) | [../forgejo/postgres.yaml](../forgejo/postgres.yaml) | | rybbit | postgres の `pg_dump` + ClickHouse の PVC(ファイル。パートは追記だけなので動いたまま取る) | [../rybbit/postgres.yaml](../rybbit/postgres.yaml) / [../rybbit/clickhouse.yaml](../rybbit/clickhouse.yaml) | | infisical | postgres の `pg_dump` | `bootstrap/infisical-values.sops.yaml` の `postgresql.primary.podAnnotations` | -| lgtm / xool / worklog / denpa / blog / todoroku | SQLite を `serialize()` した 1 ファイル | 各アプリのリポジトリの `deploy/`(denpa と yosegaki は chart) | +| lgtm / xool / worklog / denpa / yosegaki / todoroku | SQLite を `serialize()` した 1 ファイル | 各アプリのリポジトリの `deploy/`(denpa と yosegaki は chart) | | netbird | `store.db` / `idp.db` / `events.db` を tar 1 本に(bun のサイドカー) | [../netbird/deployment.yaml](../netbird/deployment.yaml) | | matrix | Tuwunel 自身のバックアップと `media/` を tar 1 本に(DB は動いたまま写さない) | [../matrix/tuwunel.yaml](../matrix/tuwunel.yaml) | | adguardhome / yuzuriha / ashi | ファイルだけ(下の表) | ─ |