diff --git a/apps/3proxy/3proxy-secrets.yaml b/apps/3proxy/3proxy-secrets.yaml index 3e3956e..a0873b0 100644 --- a/apps/3proxy/3proxy-secrets.yaml +++ b/apps/3proxy/3proxy-secrets.yaml @@ -1,15 +1,10 @@ -# Secret 3proxy は Infisical (il.doany.io) のフォルダ /3proxy/3proxy にあり、 -# Infisical 純正 operator (apps/infisical-operator) が Secret にする。 -# 値は Infisical の UI で書き換えるだけ(push-bridge が数秒で同期。auto-reload 注釈のある -# Deployment は自動で入れ替わる)。 +# Secret 3proxy を Infisical (/3proxy/3proxy) から作る。 apiVersion: secrets.infisical.com/v1alpha1 kind: InfisicalSecret metadata: name: 3proxy namespace: 3proxy - # 2 つとも必須。前者は operator が作る Secret を prune させないため、後者は - # CRD がまだ無いクラスタで apps/ の同期が丸ごと落ちるのを防ぐため。 - # bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 + # 2 つとも必須。bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 annotations: argocd.argoproj.io/sync-options: Prune=false,SkipDryRunOnMissingResource=true spec: diff --git a/apps/3proxy/deployment.yaml b/apps/3proxy/deployment.yaml index e7070ca..3f31185 100644 --- a/apps/3proxy/deployment.yaml +++ b/apps/3proxy/deployment.yaml @@ -31,9 +31,6 @@ spec: ports: # Gateway は使わない。443 では TLS 終端(HTTPS リスナー)と passthrough が共存できず # ProtocolConflict になるため(docs/decisions.md)、このサイドカーがホストのポートで直接受ける。 - # - # 3proxy 自身の平文が 3128(プロキシの慣用ポート)なので、その TLS 版として隣の 3129。 - # コンテナ側の待ち受けと同じ番号なので読み替えも要らない。 - name: proxy-tls containerPort: 3129 hostPort: 3129 diff --git a/apps/adguardhome/certificate.yaml b/apps/adguardhome/certificate.yaml index be0f07b..1c4cf85 100644 --- a/apps/adguardhome/certificate.yaml +++ b/apps/adguardhome/certificate.yaml @@ -11,5 +11,4 @@ spec: kind: ClusterIssuer dnsNames: # 命名規則(../../README.md「ホスト名の付け方」)どおり、AdGuard Home の 2 語で `ah`。 - # 以前は `d.doany.io` で、2026-09-07 に端末の設定を移してから外した。 - ah.doany.io diff --git a/apps/adguardhome/deployment.yaml b/apps/adguardhome/deployment.yaml index a24d7f1..c867d56 100644 --- a/apps/adguardhome/deployment.yaml +++ b/apps/adguardhome/deployment.yaml @@ -4,16 +4,10 @@ metadata: name: adguardhome namespace: adguardhome annotations: - # AdGuard 自身の認証は切ってある(`users: []`、2026-09-07)。守っているのは前段の - # oauth2-proxy(bootstrap/auth/adguard-proxy.yaml)で、通るのは Entra のアプリロール - # `admin` を持つ人だけ。AdGuard には SSO も利用者管理も無く、上流の認証プロキシ対応も - # 2020 年から open のままなので、認証を 1 か所(Entra)に寄せた。 + # AdGuard 自身の認証は切ってある(`users: []`)。守っているのは前段の oauth2-proxy + # (bootstrap/auth/adguard-proxy.yaml、Entra のアプリロール `admin`)。 # Web の口はクラスタ内からは無認証になる。外からは Gateway 経由だけで、その手前に SSO がある。 - # - # AdGuard の設定の正本は initContainer の `CONFIG`(下)。UI で変えた設定は Pod が作り直されると戻る (2026-10-07 から)。 - # - # クエリログの保持は 90d だと querylog.json だけで 2 GB に育ち、毎日のバックアップに乗るので - # 7d に縮めた (2026-09-06。`CONFIG` の querylog.interval)。 + # クエリログの保持(querylog.interval)は 90d だと querylog.json が 2 GB に育ちバックアップに乗るので 7d。 spec: replicas: 1 # hostPort を持つので同じポートを 2 つの Pod が同時に掴めない。RollingUpdate だと @@ -30,8 +24,7 @@ spec: spec: # 設定の正本は下の `CONFIG`。起動のたびに PVC の AdGuardHome.yaml に書き戻してから AdGuard を起動する # (AdGuard は設定ファイルを書き換えるので、読み取り専用の ConfigMap を直接マウントしない)。 - # **Pod の定義の中に置くのは、設定を変えれば Pod が作り直されるようにするため**(ConfigMap だと変えても - # Pod は古い設定のまま動き続け、2026-10-18 まではハッシュの注釈と CI で見張っていた)。 + # **Pod の定義の中に置くのは、設定を変えれば Pod が作り直されるようにするため**(ConfigMap だと Pod は古い設定のまま)。 initContainers: - name: config image: busybox:1.38 @@ -244,11 +237,10 @@ spec: schema_version: 34 containers: - name: adguardhome - # 版を固定する (2026-10-07 まで latest)。上げると起動時に設定を移行する (schema_version) ので、 - # Renovate の PR の中で renovate-post-upgrade.sh が config.yaml も移行しておく。その PR は自動マージする + # 版を上げる Renovate の PR では renovate-post-upgrade.sh が `CONFIG` も移行する(上の注記)。その PR は自動マージする image: adguard/adguardhome:v0.107.79 # LoadBalancer は使わず、ノードの全アドレスで受けるために hostPort を持つ(docs/decisions.md「LoadBalancer をどう置き換えるか」)。 - # hostPort は送信元 IP を保つので、AdGuard のクライアント別統計も従来どおり。 + # hostPort は送信元 IP を保つので、AdGuard のクライアント別統計が取れる。 ports: - name: dns-udp containerPort: 53 @@ -295,7 +287,6 @@ spec: name: doh-proxy # DoT(853)用の証明書。cert-manager が ah.doany.io で発行した Secret を、 # AdGuard の設定が見ているファイル名(server.crt / server.key)に読み替えて渡す。 - # 以前は Traefik の acme.json を監視する acme-watcher が PVC に書き出していた。 - name: adguardhome-ssl secret: secretName: adguard-dot-tls diff --git a/apps/adguardhome/doh-proxy-config.yaml b/apps/adguardhome/doh-proxy-config.yaml index 1f24a04..05d0150 100644 --- a/apps/adguardhome/doh-proxy-config.yaml +++ b/apps/adguardhome/doh-proxy-config.yaml @@ -2,7 +2,7 @@ # # なぜ要るのか。AdGuard は DoH を HTTPS の口(443)でしか出さない。平文の 80 では 404 になる。 # Gateway が backend へ平文で繋ぐ構成だと DoH が死に、これを「セキュア DNS」に入れている -# ブラウザや端末は名前解決が全部できなくなる(2026-09-07 に実際に起きた)。 +# ブラウザや端末は名前解決が全部できなくなる。 # # なぜ BackendTLSPolicy ではないのか。Cilium 1.20.1 は BackendTLSPolicy を Accepted にするが # 実際には Envoy の cluster に transport_socket を付けない。backend に平文で繋いだままなので diff --git a/apps/adguardhome/httproute.yaml b/apps/adguardhome/httproute.yaml index eb28033..57c165c 100644 --- a/apps/adguardhome/httproute.yaml +++ b/apps/adguardhome/httproute.yaml @@ -28,11 +28,9 @@ spec: type: PathPrefix value: / backendRefs: - # 管理画面は SSO の後ろ。AdGuard 自身には SSO が無いので oauth2-proxy を - # 前段に置く(bootstrap/auth/adguard-proxy.yaml)。名前空間をまたぐので - # auth 側に ReferenceGrant がある。 + # 管理画面は oauth2-proxy(bootstrap/auth/adguard-proxy.yaml)の後ろ。auth 側に ReferenceGrant がある。 # `/dns-query` は上のルールで先に拾われる。ここを通すと DoH に認証がかかって - # 名前解決が止まる(2026-09-07 朝の障害)。 + # 名前解決が止まる。 - name: auth-adguard namespace: auth port: 4180 diff --git a/apps/adguardhome/pvc.yaml b/apps/adguardhome/pvc.yaml index f2a74a0..bee88a8 100644 --- a/apps/adguardhome/pvc.yaml +++ b/apps/adguardhome/pvc.yaml @@ -1,7 +1,5 @@ -# 2 本ともファイルとして k8up に取らせる(`k8up.io/backup: "true"`)。 -# 設定・フィルタ・クエリログで、書き換わっても部分的に古いだけで壊れない類い。 -# operator は `BACKUP_SKIP_WITHOUT_ANNOTATION=true` なので、注釈が無い PVC は素通りする -#。つまりこの 2 行が「取る」という宣言そのもの(apps/k8up/README.md)。 +# 2 本とも k8up に取らせる(書き換わっても部分的に古いだけで壊れない類い)。注釈が無い PVC は +# 取られないので、`k8up.io/backup: "true"` が「取る」という宣言そのもの(apps/k8up/README.md)。 apiVersion: v1 kind: PersistentVolumeClaim metadata: diff --git a/apps/adguardhome/service-dns.yaml b/apps/adguardhome/service-dns.yaml index 6819dbe..b10dafa 100644 --- a/apps/adguardhome/service-dns.yaml +++ b/apps/adguardhome/service-dns.yaml @@ -6,9 +6,7 @@ metadata: spec: # ClusterIP でよい理由は docs/decisions.md「ルーティングの選定」の hostPort の表 type: ClusterIP - # Dual-stack: without this the Service is IPv4-only, yet the CNI still - # installs hostPort DNAT rules for v6 :53 -- so IPv6 queries reach the - # svclb pod and are dropped there (klipper-lb only gets SRC_RANGES for v4). + # 無いと IPv4 だけの Service になり、IPv6 で来た DNS(:53)を受けられない。 ipFamilyPolicy: RequireDualStack ipFamilies: - IPv4 diff --git a/apps/cloudflare-ddns/cloudflare-ddns-secrets.yaml b/apps/cloudflare-ddns/cloudflare-ddns-secrets.yaml index 39eb5cc..45ed7de 100644 --- a/apps/cloudflare-ddns/cloudflare-ddns-secrets.yaml +++ b/apps/cloudflare-ddns/cloudflare-ddns-secrets.yaml @@ -1,15 +1,10 @@ -# Secret cloudflare-ddns-secrets は Infisical (il.doany.io) のフォルダ /cloudflare-ddns/cloudflare-ddns-secrets にあり、 -# Infisical 純正 operator (apps/infisical-operator) が Secret にする。 -# 値は Infisical の UI で書き換えるだけ(push-bridge が数秒で同期。auto-reload 注釈のある -# Deployment は自動で入れ替わる)。 +# Secret cloudflare-ddns-secrets を Infisical (/cloudflare-ddns/cloudflare-ddns-secrets) から作る。 apiVersion: secrets.infisical.com/v1alpha1 kind: InfisicalSecret metadata: name: cloudflare-ddns-secrets namespace: cloudflare-ddns - # 2 つとも必須。前者は operator が作る Secret を prune させないため、後者は - # CRD がまだ無いクラスタで apps/ の同期が丸ごと落ちるのを防ぐため。 - # bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 + # 2 つとも必須。bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 annotations: argocd.argoproj.io/sync-options: Prune=false,SkipDryRunOnMissingResource=true spec: diff --git a/apps/external-dns/application.yaml b/apps/external-dns/application.yaml index 8301377..2168dec 100644 --- a/apps/external-dns/application.yaml +++ b/apps/external-dns/application.yaml @@ -1,6 +1,6 @@ -# ExternalDNS。**Cloudflare を通すアプリの DNS レコードを、アプリの HTTPRoute から作る**(2026-10-06)。 +# ExternalDNS。**Cloudflare を通すアプリの DNS レコードを、アプリの HTTPRoute から作る**。 # -# 方針(本人): +# 方針: # - 社内用や通信量が多いアプリは**直接つなぐ**。何もしない ── `*.doany.io` のワイルドカード # (proxied ではない CNAME)で引ける # - SaaS のように外へ出すアプリは **Cloudflare のプロキシを通す**。アプリのリポジトリの HTTPRoute に diff --git a/apps/external-dns/external-dns-secrets.yaml b/apps/external-dns/external-dns-secrets.yaml index a15ffef..a7d0c0f 100644 --- a/apps/external-dns/external-dns-secrets.yaml +++ b/apps/external-dns/external-dns-secrets.yaml @@ -1,8 +1,7 @@ -# Secret external-dns は Infisical (il.doany.io) のフォルダ /external-dns/external-dns にあり、 -# Infisical 純正 operator (apps/infisical-operator) が Secret にする。 +# Secret external-dns を Infisical (/external-dns/external-dns) から作る。 # # cloudflare-api-token Cloudflare の Account API token「external-dns (doany.io DNS write)」。 -# 権限は doany.io のゾーンだけの Zone Read + DNS Write(2026-10-06 に作った) +# 権限は doany.io のゾーンだけの Zone Read + DNS Write apiVersion: secrets.infisical.com/v1alpha1 kind: InfisicalSecret metadata: diff --git a/apps/forgejo/forgejo-secrets.yaml b/apps/forgejo/forgejo-secrets.yaml index 6bb5119..3996702 100644 --- a/apps/forgejo/forgejo-secrets.yaml +++ b/apps/forgejo/forgejo-secrets.yaml @@ -16,9 +16,7 @@ kind: InfisicalSecret metadata: name: forgejo-db namespace: forgejo - # 2 つとも必須。前者は operator が作る Secret を prune させないため、後者は - # CRD がまだ無いクラスタで apps/ の同期が丸ごと落ちるのを防ぐため。 - # bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 + # 2 つとも必須。bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 annotations: argocd.argoproj.io/sync-options: Prune=false,SkipDryRunOnMissingResource=true spec: diff --git a/apps/forgejo/forgejo.yaml b/apps/forgejo/forgejo.yaml index 64aed1d..e887d68 100644 --- a/apps/forgejo/forgejo.yaml +++ b/apps/forgejo/forgejo.yaml @@ -2,14 +2,12 @@ # # **chart(forgejo-helm)は使わない。** chart は app.ini の元と init のスクリプトを Secret で作るが、 # このクラスタの ArgoCD は Secret を丸ごと管理対象から外している(bootstrap/argocd/values.yaml の -# resource.exclusions)ので、それらが作られず Pod が起動しない(2026-09-15 に踏んだ)。 +# resource.exclusions)ので、それらが作られず Pod が起動しない。 # 設定は環境変数(FORGEJO__
__)で渡し、イメージの docker-setup.sh が app.ini に書く。 # -# 版は最新を追う(LTS に留めない。2026-09-15 に 15.0.8 → 16.0.4)。Renovate が PR を出す。 -# メジャーを上げるときはリリースノートの破壊的変更を読んでから。 +# 版は最新を追う(LTS に留めない)。メジャーを上げるときはリリースノートの破壊的変更を読んでから。 # -# 名前が forgejo-web / forgejo-repos なのは、chart 時代の Application が消えるときに -# 同名のリソース(forgejo / forgejo-http / forgejo-data)を消すので、それに巻き込まれないように。 +# 名前が forgejo-web / forgejo-repos なのは chart 時代のリソース(forgejo / forgejo-http / forgejo-data)と被らないようにした名残。 apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -85,7 +83,7 @@ data: --group-claim-name tid \ --group-team-map '{"22ac977d-b140-4dc8-8150-90d645d3475b": {"doa": ["members"]}}' # 一覧はタブ区切り(ID Name Type Enabled)。--vertical-bars の出力は空白の入り方が一定でなく、 - # grep で拾えずに 2 回目の起動で add-oauth が「already exists」で落ちた(2026-09-15) + # 拾い損ねると 2 回目の起動で add-oauth が「already exists」で落ちる id=$(gitea admin auth list | awk '$2 == "entra" {print $1}') if [ -z "$id" ]; then gitea admin auth add-oauth "$@" @@ -260,7 +258,7 @@ data: FORGEJO__actions__DEFAULT_ACTIONS_URL: https://github.com FORGEJO__repository__DEFAULT_BRANCH: main FORGEJO__repository__DEFAULT_PRIVATE: private - # マージはスカッシュだけにする方針(GitHub の頃と同じ)。組織単位で縛る設定は Forgejo に無いので、 + # マージはスカッシュだけにする方針。組織単位で縛る設定は Forgejo に無いので、 # 既定のマージ方法だけここで決め、許すマージ方法はリポジトリごとに API で絞る(README「マージはスカッシュ」) FORGEJO__repository_0X2E_pull_0X2D_request__DEFAULT_MERGE_STYLE: squash FORGEJO__session__COOKIE_SECURE: "true" diff --git a/apps/forgejo/runner.yaml b/apps/forgejo/runner.yaml index cc01616..0a53637 100644 --- a/apps/forgejo/runner.yaml +++ b/apps/forgejo/runner.yaml @@ -16,29 +16,21 @@ # # ネットワークは**ジョブごとに別**(container.network: "")。Runner がジョブごとに dind の中に bridge の # ネットワーク(WORKFLOW-…)を作り、ジョブ(と services)のコンテナをそこに置き、終わったら消す。 -# 前は host(全ジョブが Pod のネットワークを分け合う)だった。それだと、どれかのジョブが dind でコンテナを -# 起こすたびに、全ジョブから見えるところに veth(IPv6 のリンクローカル付き)が出入りし、Chromium が -# ERR_NETWORK_CHANGED で読み込みを切って e2e が落ちた(doa/todoroku#366)。同じ番号のポート(4173 など)も取り合っていた。 +# host(全ジョブが Pod のネットワークを分け合う)にしないこと。ほかのジョブの veth が出入りするたびに Chromium が +# ERR_NETWORK_CHANGED で読み込みを切って e2e が落ち(doa/todoroku#366)、同じ番号のポートも取り合う。 # -# ジョブの中から docker を使う(イメージを作る・docker run)ときは、forgejo の docs の「docker-access」の DIND の形: +# ジョブの中から docker を使うときは、forgejo の docs の「docker-access」の DIND の形: # - ジョブには `--add-host=dind.docker.internal:host-gateway` を足す。host-gateway は dind の docker0 の -# 住所(172.17.0.1。dind 自身 = Pod のネットワーク名前空間の住所)で、dockerd は 0.0.0.0:2376 で待っている。 -# ジョブのネットワークからでも、宛先が dind 自身なので届く(別のネットワークのコンテナへの転送とは違い、遮られない) +# 住所(172.17.0.1 = dind 自身)で、dockerd は 0.0.0.0:2376 で待っているので、ジョブのネットワークからも届く # - ジョブの DOCKER_HOST は tcp://dind.docker.internal:2376。TLS はそのまま(証明書は valid_volumes で渡す)。 # dind のサーバー証明書の SAN にこの名前を足す(DOCKER_TLS_SAN) -# 渡しているのは今までと同じ「dind を丸ごと操れる鍵」なので、できることは host のときと変わらない -# (capacity が 2 以上なので、ジョブは docker の CLI で同時に走っているほかのジョブのコンテナも見える。前から同じ)。 -# Runner 自身は今までどおり localhost:2376(Pod の中)で dind に話す。 -# キャッシュ(ACTIONS_CACHE_URL)は Runner が自分の Pod の IP で出す。ジョブのネットワークから見ても dind の -# 自分の IP なので届く。 +# 渡しているのは「dind を丸ごと操れる鍵」なので、ジョブは同時に走っているほかのジョブのコンテナも見える。 +# Runner 自身は localhost:2376 で dind に話す。キャッシュ(ACTIONS_CACHE_URL)は Pod の IP で出すので、ジョブからも届く。 # # **ジョブのネットワークにも IPv6 を付ける(enable_ipv6)。** 無いと fj.doany.io に届かない。 -# fj.doany.io は AAAA(ノード)と A(家の外向きの IPv4)を返し、Pod からは IPv4 の方はヘアピンで届かない -# (curl -4 は時間切れ)。host の頃は Pod の IPv6 で届いていた。checkout・API・upload-artifact・OIDC は -# ジョブの中から fj.doany.io に行くので、IPv4 だけのネットワークでは全部止まる。 -# enable_ipv6 にすると dind がネットワークごとに ULA の /64 を割り当て、外へは NAT66(Pod の IPv6)で出るので、 -# 外向きは host の頃と同じ形になる(2026-10-07 に本番の dind で確かめた)。 -# docker login / push は dind(Pod のネットワーク)が自分で名前を引くので、これまでどおり。 +# fj.doany.io は AAAA(ノード)と A(家の外向きの IPv4)を返し、Pod からは IPv4 の方はヘアピンで届かない。 +# checkout・API・upload-artifact・OIDC はジョブの中から fj.doany.io に行くので、IPv4 だけでは全部止まる。 +# enable_ipv6 にすると dind がネットワークごとに ULA の /64 を割り当て、外へは NAT66(Pod の IPv6)で出る。 # Cilium は vxlan なので Pod の MTU は 1500 より小さい。dind の既定 1500 のままだと大きいパケットが落ちる。 # --mtu は既定の bridge(docker0)にしか効かないので、ジョブのネットワークの分は --default-network-opt で揃える。 apiVersion: v1 @@ -71,10 +63,7 @@ data: log: level: info runner: - # 同時に受けるジョブの数。ワークフローが 2 本(test と claude-review)ある PR を - # 3 リポジトリぶん積むと 2 では順番待ちが長い。ノードは 44 コア / 46 GiB で - # 使用率は CPU 8% / メモリ 16%、CPU は余っているので詰まるのは下の dind のメモリ。 - # 8 本のうち重いのは e2e(ブラウザ)くらいで、それが同時に何本も来ることは稀 + # 同時に受けるジョブの数。CPU は余っているので、上限は dind のメモリ(下の limits)で決まる capacity: 8 timeout: 3h labels: diff --git a/apps/headlamp/application.yaml b/apps/headlamp/application.yaml index 8c20bc9..0c635fb 100644 --- a/apps/headlamp/application.yaml +++ b/apps/headlamp/application.yaml @@ -1,4 +1,4 @@ -# Kubernetes の Web UI。Portainer の置き換え(2026-09-09 に入れ替えた)。h.doany.io。 +# Kubernetes の Web UI。h.doany.io。 # # Resource Map が Gateway / HTTPRoute / GRPCRoute を最初から知っていて、 # parentRefs と backendRefs の線も定義済みなので、公開経路が 1 枚で出る。 @@ -10,7 +10,7 @@ # # コールバックは Headlamp が要求のホストから組み立てる(Envoy が x-forwarded-proto を # 付ける)ので指定しない。Entra 側の redirect URI は登録済み -# (https://h.doany.io/oidc-callback、2026-09-09)。 +# (https://h.doany.io/oidc-callback)。 apiVersion: argoproj.io/v1alpha1 kind: Application metadata: diff --git a/apps/headlamp/headlamp-secrets.yaml b/apps/headlamp/headlamp-secrets.yaml index ea10b23..f3703f8 100644 --- a/apps/headlamp/headlamp-secrets.yaml +++ b/apps/headlamp/headlamp-secrets.yaml @@ -16,9 +16,7 @@ kind: InfisicalSecret metadata: name: headlamp-oidc namespace: headlamp - # 2 つとも必須。前者は operator が作る Secret を prune させないため、後者は - # CRD がまだ無いクラスタで apps/ の同期が丸ごと落ちるのを防ぐため。 - # bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 + # 2 つとも必須。bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 annotations: argocd.argoproj.io/sync-options: Prune=false,SkipDryRunOnMissingResource=true spec: diff --git a/apps/infisical-operator/application.yaml b/apps/infisical-operator/application.yaml index d716f40..6a9f08d 100644 --- a/apps/infisical-operator/application.yaml +++ b/apps/infisical-operator/application.yaml @@ -3,9 +3,6 @@ # Secret 更新時に自動でローリング再起動される。 # https://infisical.com/docs/integrations/platforms/kubernetes/overview # -# もとは HelmChart CR で入れていた(2026-09-07 に Application へ。docs/decisions.md)。 -# ArgoCD 自身は operator に依存しないので、bootstrap ではなくここで面倒を見られる。 -# # リリース名は変えられない。chart は名前を 15 文字で切って # `infisical-secre-controller-manager` を作るので、変えると別物として作り直しになる。 apiVersion: argoproj.io/v1alpha1 diff --git a/apps/k8up/denpa-encoded-forget.yaml b/apps/k8up/denpa-encoded-forget.yaml index 5f4876b..0dac255 100644 --- a/apps/k8up/denpa-encoded-forget.yaml +++ b/apps/k8up/denpa-encoded-forget.yaml @@ -1,10 +1,9 @@ # エンコード済みの録画(PVC denpa-encoded、Pod の中では /media/encoded)だけ世代を持たない。 -# 中身が入れ替わるので、古い世代が消えたファイルを抱え続ける(1 世代でよい、は本人の判断。2026-10-05)。 +# 中身が入れ替わるので、古い世代が消えたファイルを抱え続ける。 # 翌日までに誤削除に気づかないと戻せない。余裕が欲しくなったら --keep-last 2(約 2 GiB)。 # # k8up の保持は Schedule(= namespace)単位でしか書けない。restic の forget は既定で (host, paths) ごとに # 保持を効かせる(k8up は --group-by を渡さない)ので、PVC ごとに別の保持を当てるには path を絞った forget を回す。 -# 以前のホストのスナップショット(host=main)が同じ blob を掴んでいて効いていなかったが、2026-10-17 に消した。 apiVersion: batch/v1 kind: CronJob metadata: diff --git a/apps/k8up/etcd-snapshot.yaml b/apps/k8up/etcd-snapshot.yaml index 687a375..58bf59f 100644 --- a/apps/k8up/etcd-snapshot.yaml +++ b/apps/k8up/etcd-snapshot.yaml @@ -1,7 +1,7 @@ # etcd のスナップショットを日次で restic(R2)へ。 # # **戻すときの主経路ではない。** 主経路は「git から Argo CD で建て直して PV を k8up で戻す」 -# (recovery/README.md。2026-10-17 に実機で通した)。こちらは git に無い状態 +# (recovery/README.md)。こちらは git に無い状態 # (Argo CD が作った Application の同期状態、cert-manager の発行済み証明書など)まで含めて**一瞬で戻したいとき**の近道。 # 戻し方は docs/talos.md「etcd スナップショットからの復旧」の `bootstrap --recover-from`。 # @@ -39,8 +39,7 @@ spec: spec: restartPolicy: Never # 2 つのコンテナを同じユーザーで動かす。talosctl のイメージは root で走り、スナップショットを - # 0600 で書くので、k8up のイメージ(65532)の restic が `permission denied` で読めなかった - # (最初の 1 回、2026-10-17)。 + # 0600 で書くので、k8up のイメージ(65532)の restic が `permission denied` で読めない。 securityContext: runAsUser: 65532 runAsGroup: 65532 @@ -69,7 +68,7 @@ spec: - -ec - | export RESTIC_REPOSITORY="s3:${ENDPOINT}/${BUCKET}" - # 空のファイルを「取れた」にしない(k8up の空スナップショットで懲りている。apps/k8up/README.md) + # 空のファイルを「取れた」にしない(apps/k8up/README.md「空のスナップショット」) [ -s etcd.snapshot ] || { echo "etcd.snapshot が空" >&2; exit 1; } # --host は k8up の namespace と被らない名前に。k8up の prune は # --host= で絞るのでこちらには届かない ── 保持は自分で回す。 diff --git a/apps/k8up/k8up-secrets.yaml b/apps/k8up/k8up-secrets.yaml index a7274fa..c3ca00f 100644 --- a/apps/k8up/k8up-secrets.yaml +++ b/apps/k8up/k8up-secrets.yaml @@ -13,9 +13,7 @@ kind: InfisicalSecret metadata: name: k8up-global namespace: k8up - # 2 つとも必須。前者は operator が作る Secret を prune させないため、後者は - # CRD がまだ無いクラスタで apps/ の同期が丸ごと落ちるのを防ぐため。 - # bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 + # 2 つとも必須。bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 annotations: argocd.argoproj.io/sync-options: Prune=false,SkipDryRunOnMissingResource=true spec: diff --git a/apps/k8up/notify.yaml b/apps/k8up/notify.yaml index 300a890..c3fd3fc 100644 --- a/apps/k8up/notify.yaml +++ b/apps/k8up/notify.yaml @@ -6,7 +6,7 @@ metadata: name: k8up-notify namespace: k8up --- -# 読むだけ。k8up.io の 4 種類だけに絞る。 +# 読むだけ。 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: @@ -19,8 +19,7 @@ rules: - apiGroups: [""] resources: [persistentvolumeclaims, pods] verbs: [list] - # k8up の namespace の CronJob(etcd-snapshot・restore-check など)が最後まで走ったか。 - # status しか読まない + # k8up の namespace の CronJob(etcd-snapshot・restore-check など)が最後まで走ったか。status しか読まない - apiGroups: [batch] resources: [cronjobs] verbs: [list] @@ -137,7 +136,6 @@ data: const now = Date.now(); const hours = (t) => (now - Date.parse(t)) / 3600e3; - // (host, path) ごとに最新を拾う。 const latest = new Map(); for (const s of snapshots) { for (const path of s.paths ?? []) { @@ -169,7 +167,6 @@ data: return (await r.json()).items ?? []; }; const get = (kind) => fetchAll(`https://kubernetes.default.svc/apis/k8up.io/v1/${kind}`, kind); - // コアの API は `/api/v1`(`/apis` ではない)。 const getCore = (kind) => fetchAll(`https://kubernetes.default.svc/api/v1/${kind}`, kind); // 止めてあるアプリ(Running / Pending の Pod が無い namespace)の stale / 空 / 無音は見送る。 diff --git a/apps/k8up/restore-check.yaml b/apps/k8up/restore-check.yaml index af630c5..589b23b 100644 --- a/apps/k8up/restore-check.yaml +++ b/apps/k8up/restore-check.yaml @@ -3,7 +3,7 @@ # notify.yaml は「新しいスナップショットができたか」「中身が 0 バイトでないか」までしか # 見ない。**取れていることと戻せることは別** ── 壊れた SQLite や途中で切れたダンプでも # スナップショットは新しく、0 バイトでもない。それを捕まえるには実際に取り出して開くしかない。 -# 四半期ごとの手動のリハーサル(ROADMAP)の代わり。建て直しそのものの手順は recovery/README.md。 +# 建て直しそのものの手順は recovery/README.md。 # # 見るもの((host, path) ごとの最新。過去 8 日に出てこない経路は notify の担当): # - SQLite(.db): `PRAGMA integrity_check` が ok、表が 1 つ以上 @@ -23,8 +23,7 @@ metadata: name: k8up-restore-check namespace: k8up spec: - # 毎月 1 日 06:00 UTC。バックアップ(13:00〜18:30 UTC)と日曜の prune・check(〜23:45 UTC)の外。 - # 全部で 2 分ほど(27 件。2026-10-17 実測)。 + # 毎月 1 日 06:00 UTC。バックアップ(13:00〜18:30 UTC)と日曜の prune・check(〜23:45 UTC)の外。全部で 2 分ほど。 schedule: "0 6 1 * *" concurrencyPolicy: Forbid successfulJobsHistoryLimit: 1 @@ -47,7 +46,7 @@ spec: # 道具を集める。restic は k8up のイメージから(notify・etcd-snapshot と同じ版)、 # bun は notify と同じイメージから。どちらも 1 ファイルで、postgres のイメージの上で動く。 # **CA の束も持ってくる。** postgres のイメージには入っていない。無いと restic は - # x509 のエラーを黙って retry し続け、何も言わずに止まって見える(2026-10-17 に踏んだ)。 + # x509 のエラーを黙って retry し続け、何も言わずに止まって見える。 # メモリの上限は bun(約 90 MB)の書き込みがページキャッシュに乗るぶん。64Mi では OOMKilled だった - name: restic image: ghcr.io/k8up-io/k8up:v2.16.0 @@ -119,8 +118,6 @@ data: // 最新のスナップショットを取り出して開いてみる。結果を 1 通にまとめて投げる。 import { Database } from "bun:sqlite"; import { mkdirSync, rmSync, readdirSync, statSync, existsSync, readFileSync } from "fs"; - // ここで投稿まで届かずに落ちたとき(OOMKilled・期限切れなど)は、日次の notify が - // CronJob の lastSuccessfulTime を見て拾う(notify.yaml) const LEARN_H = 24 * 8; const W = "/work"; @@ -295,5 +292,4 @@ data: console.error(`投稿に失敗: ${r.status} ${await r.text()}`); process.exit(1); } - // FAILED でも exit 0(notify.yaml と同じ理由。Job が落ちると CronJob が Degraded になり - // ArgoCD の同期が retry に入る)。非ゼロは投稿そのものに失敗したときだけ + // FAILED でも exit 0(理由は notify.yaml の末尾)。非ゼロは投稿そのものに失敗したときだけ diff --git a/apps/k8up/schedules.yaml b/apps/k8up/schedules.yaml index 3bba9fa..1c62b3f 100644 --- a/apps/k8up/schedules.yaml +++ b/apps/k8up/schedules.yaml @@ -8,7 +8,6 @@ # 寄せてある。ジョブの履歴の数もあちら # - `runAsUser: 0` は全部に要る。既定の nonroot では 0600 のファイルが読めず、restic は 0 バイトの # スナップショットを作り、k8up はそれを Succeeded にする(README「空のスナップショット」) -# - 保持は全部 keepDaily 7 / keepWeekly 4 / keepMonthly 6 # # 時刻は固定で、重ねない。k8up 同士(backup・prune・check)は operator が順に待たせる(`operator/locker/locker.go`)が、 # k8up の外の CronJob は待たない。etcd-snapshot(13:00 UTC)と denpa-encoded-forget(18:30 UTC)の forget と diff --git a/apps/matrix/hookshot.yaml b/apps/matrix/hookshot.yaml index 48ffc1d..6d22452 100644 --- a/apps/matrix/hookshot.yaml +++ b/apps/matrix/hookshot.yaml @@ -55,9 +55,9 @@ data: services: - service: "*" level: admin - # 通知のルームごとの webhook。URL は https://m.doany.io/webhook/。 + # 通知のルームごとの webhook。 # stateKey は推測されない乱数で、Infisical /matrix/matrix の hook-<部屋>(公開のリポジトリなので git に置かない)。 - # 下の render が HOOK_ で始まる変数(stateKey)を差し替える。送り手は @_webhooks_:doany.io + # 下の render が HOOK_ で始まる変数(stateKey)を差し替える。 # # 投稿は全部 m.notice(bot の発言)。スマホに通知するかと音は、Element の「bot のメッセージ」の設定と # 部屋ごとの通知の設定で決める(人の会話は音あり、bot は音無しで通知、要らない部屋はメンションのみ) @@ -95,21 +95,18 @@ data: state: name: argocd transformationFunction: *slack - # 部屋 ashi: ashi - connectionType: uk.half-shot.matrix-hookshot.generic.hook stateKey: ${HOOK_ASHI} roomId: "!Ffdb9KuBulsduDwuX3ig_Mm_L58QUBd78rcfGOTWoNs" state: name: ashi transformationFunction: *slack - # 部屋 todoroku: todoroku - connectionType: uk.half-shot.matrix-hookshot.generic.hook stateKey: ${HOOK_TODOROKU} roomId: "!6cY5BJsmPL_0_-t2q2E-veifDIO73fz2ABcZErJXkhQ" state: name: todoroku transformationFunction: *slack - # 部屋 worklog: worklog - connectionType: uk.half-shot.matrix-hookshot.generic.hook stateKey: ${HOOK_WORKLOG} roomId: "!aAFRLm9zquKQuIO3X7L-PkvvWcPg7_dqu5WIgYQNhe0" diff --git a/apps/matrix/matrix-secrets.yaml b/apps/matrix/matrix-secrets.yaml index eb56827..dff3bdb 100644 --- a/apps/matrix/matrix-secrets.yaml +++ b/apps/matrix/matrix-secrets.yaml @@ -1,5 +1,4 @@ -# Secret matrix は Infisical (il.doany.io) のフォルダ /matrix/matrix にあり、 -# Infisical 純正 operator (apps/infisical-operator) が Secret にする。 +# Secret matrix を Infisical (/matrix/matrix) から作る。 # # oidc-client-secret Entra の共用のアプリ登録のクライアントシークレット(auth などと同じ値) # hookshot-as-token Tuwunel と hookshot の合言葉(アプリサービスの登録。長いランダム文字列) diff --git a/apps/matrix/tuwunel.yaml b/apps/matrix/tuwunel.yaml index 107fd8b..4cf00c0 100644 --- a/apps/matrix/tuwunel.yaml +++ b/apps/matrix/tuwunel.yaml @@ -1,8 +1,8 @@ -# Tuwunel(Matrix のサーバー。https://github.com/matrix-construct/tuwunel)。Zulip からの移行先(2026-10-06)。 +# Tuwunel(Matrix のサーバー。https://github.com/matrix-construct/tuwunel)。 # # 最小構成。サーバーはこれ 1 つで、DB(RocksDB)も中にある。Postgres も MAS も要らない: # - ログインは Tuwunel 自身の OAuth/OIDC サーバー(MSC3861/2965)が受け、Entra に回す。 -# スマホの Element X は「OAuth か パスワード」しか受け付けないので、これが要る(Synapse だと MAS が要る) +# スマホの Element X は「OAuth か パスワード」しか受け付けないので、これが要る # - ID は @<メールの @ の前>:doany.io。初回のログインで自動で作られ、最初の人が管理者になる # - フェデレーションは無し(家の中だけ)。パスワードのログインも無し # @@ -136,7 +136,7 @@ spec: k8up.io/file-extension: .tar spec: # Service の自動の環境変数(TUWUNEL_PORT=tcp://… など)を入れない。Service の名前が tuwunel なので、 - # Tuwunel が自分の設定(TUWUNEL_*)として読んで起動に失敗する(2026-10-06 に踏んだ) + # Tuwunel が自分の設定(TUWUNEL_*)として読んで起動に失敗する enableServiceLinks: false # バックアップのサイドカーが Tuwunel のプロセスにシグナルを送るため shareProcessNamespace: true @@ -194,9 +194,8 @@ spec: - name: secrets mountPath: /run/secrets/matrix readOnly: true - # k8up のバックアップのときにだけ働く(上の backupcommand)。Tuwunel に SIGUSR2 を送って - # 整合の取れたバックアップ(backups/)を作らせ、できたら backups/ と media/ を tar で渡す。 - # ふだんは寝ているだけ。Tuwunel のイメージにはシェルが無いので別に置く + # k8up のバックアップのときにだけ働く(上の backupcommand)。ふだんは寝ているだけ。 + # Tuwunel のイメージにはシェルが無いので別に置く - name: backup image: busybox:1.38 command: [sh, -c, "trap 'exit 0' TERM; sleep infinity & wait"] diff --git a/apps/metrics-server/application.yaml b/apps/metrics-server/application.yaml index b09f280..d0e6e8a 100644 --- a/apps/metrics-server/application.yaml +++ b/apps/metrics-server/application.yaml @@ -1,7 +1,7 @@ # metrics-server。Talos には無い。入れないと `kubectl top` が使えず、ArgoCD・Headlamp・ # Hubble の各 UI から使用量の表示が消える。HPA は今のところ 1 つも無いので停止には至らない。 # -# 2026-10-17 まで machine config の inlineManifest だった。起動に要るものではないので ArgoCD に移した +# 起動に要るものではないので machine config の inlineManifest ではなく ArgoCD で入れる # (版を上げても render.sh → apply-config → upgrade-k8s を流さなくて済む)。 apiVersion: argoproj.io/v1alpha1 kind: Application diff --git a/apps/netbird/deployment.yaml b/apps/netbird/deployment.yaml index 02626f7..5710fc4 100644 --- a/apps/netbird/deployment.yaml +++ b/apps/netbird/deployment.yaml @@ -1,21 +1,15 @@ -# NetBird の combined サーバ + ダッシュボード。VPN はこれ 1 本(wg-easy は 2026-09-07 に撤去)。 -# 選定の理由と比較は docs/decisions.md「VPN を wg-easy から NetBird にした」。 +# NetBird の combined サーバ + ダッシュボード。選定の理由は docs/decisions.md「VPN を wg-easy から NetBird にした」。 apiVersion: v1 kind: PersistentVolumeClaim metadata: name: netbird-data namespace: netbird annotations: - # ファイルとしては取らない。下の backup サイドカーが store.db / idp.db / - # events.db を整合したコピーで取っている。ここに同居している GeoLite2-City(65 MB)と - # geonames(7 MB)は起動時に落とし直せるので、取る意味が無い。 + # ファイルとしては取らない。下の backup サイドカーが DB だけを整合したコピーで取る。 k8up.io/backup: "false" spec: accessModes: - ReadWriteOnce - # 既定の local-path(reclaim は Delete) - # ---「git で消したものはちゃんと消える」に寄せた(docs/decisions.md)。 - # 後ろ盾は日次の restic。 resources: requests: storage: 2Gi @@ -40,8 +34,6 @@ spec: labels: app: netbird-server annotations: - # バックアップは下の backup コンテナで取る。netbird-server のイメージには - # sqlite3 が無く(あるのは perl だけ)、上流のイメージなのでこちらでは足せない。 k8up.io/backupcommand-container: backup # store.db(ピアと設定)・idp.db(内蔵 IdP のユーザ)・events.db を、それぞれ # SQLite の pager 越しに読んで tar 1 本にまとめる。同じ PVC に居る @@ -122,10 +114,8 @@ spec: mountPath: /var/lib/netbird - name: config mountPath: /etc/netbird - # バックアップのためだけのサイドカー。上の k8up.io/backupcommand は - # ここで走る。bun には bun:sqlite が入っているので、sqlite3 を持つイメージを - # 自前で焼かずに済む(アプリ側の 5 つと同じ手)。 - # 読み取り専用でマウントする。このコンテナが DB を書き換えることは無い。 + # バックアップのためだけのサイドカー(上の k8up.io/backupcommand はここで走る)。 + # netbird-server のイメージには sqlite3 が無いので、bun:sqlite を使う。DB は読み取り専用でマウントする。 - name: backup image: oven/bun:1.4.3-slim command: ["sleep", "infinity"] @@ -171,7 +161,6 @@ spec: # WebSocket(`/relay`)が HTTP/2 上では拡張 CONNECT を要求されて壊れる # (Envoy が `upstream connect error ... reset reason: protocol error` で 502)。 # Service を分ければクラスタが分かれ、h2c になるのは gRPC 側だけになる。 -# 公式の Traefik 例が netbird-server と netbird-server-h2c の 2 つを定義しているのと同じ理由。 apiVersion: v1 kind: Service metadata: diff --git a/apps/netbird/namespace.yaml b/apps/netbird/namespace.yaml index 97b74fa..2220661 100644 --- a/apps/netbird/namespace.yaml +++ b/apps/netbird/namespace.yaml @@ -1,10 +1,5 @@ -# PSA は privileged。STUN(UDP 3478)を hostPort でノードの IP に直接出すため。 -# Pod Security Standards の baseline は `hostPort` を許さない(許容値は未定義か 0 だけ)ので、 -# baseline のままだと Pod が作れない(docs/talos.md「PSA のラベル」)。 -# -# STUN をゲートウェイ経由にできないのは NetBird 側の制約: -# 「HTTP reverse proxies only handle TCP traffic; STUN requires direct UDP access」 -# (https://docs.netbird.io/selfhosted/external-reverse-proxy)。 +# PSA は privileged。理由: STUN(UDP 3478)の hostPort が baseline に通らない(STUN は Gateway を通せない。 +# https://docs.netbird.io/selfhosted/external-reverse-proxy)。一覧と背景は docs/talos.md「PSA のラベル」。 apiVersion: v1 kind: Namespace metadata: diff --git a/apps/netbird/netbird-secrets.yaml b/apps/netbird/netbird-secrets.yaml index 6dafc70..d9c20d0 100644 --- a/apps/netbird/netbird-secrets.yaml +++ b/apps/netbird/netbird-secrets.yaml @@ -1,5 +1,4 @@ -# Secret netbird-secrets は Infisical (il.doany.io) のフォルダ /netbird/netbird-secrets にあり、 -# Infisical 純正 operator (apps/infisical-operator) が Secret にする。 +# Secret netbird-secrets を Infisical (/netbird/netbird-secrets) から作る。 # # 中身は 3 つとも `openssl rand -base64 32` で作った乱数で、人が読む値ではない: # auth-secret ローカル relay の共有秘密 (server.authSecret) @@ -14,9 +13,7 @@ kind: InfisicalSecret metadata: name: netbird-secrets namespace: netbird - # 2 つとも必須。前者は operator が作る Secret を prune させないため、後者は - # CRD がまだ無いクラスタで apps/ の同期が丸ごと落ちるのを防ぐため。 - # bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 + # 2 つとも必須。bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 annotations: argocd.argoproj.io/sync-options: Prune=false,SkipDryRunOnMissingResource=true spec: diff --git a/apps/netbird/routing-peer.yaml b/apps/netbird/routing-peer.yaml index 8993f07..346cd41 100644 --- a/apps/netbird/routing-peer.yaml +++ b/apps/netbird/routing-peer.yaml @@ -1,29 +1,20 @@ # NetBird の routing peer(サブネットルータ)。自宅 LAN 10.0.0.0/24 への入口で、 # iLO(10.0.0.3)や AdGuard(10.0.0.2:53)にここ経由で届く。 -# -# Headscale を落として NetBird にした理由がここ。headscale は FAQ で -# 「headscale 自身を動かすマシンをサブネットルータにするな」と明記していて、 -# ノード 1 台のこの構成では回避できなかった。NetBird は routing peer が独立した -# 概念で、コンテナで動かす前提のドキュメントがある(docs/decisions.md)。 -# -# 上流の kubernetes-operator にも NetworkRouter があるが、あれは -# Kubernetes の Service を公開するためのもので、物理 LAN のサブネットルータではない。 -# ここが必要としているのは後者なので、素の Deployment で組む(hostNetwork は -# 2026-09-08 に外した。理由は下の spec のコメント)。 +# Headscale ではなく NetBird にした理由はこれ(docs/decisions.md)。上流の kubernetes-operator の NetworkRouter は +# Service を公開するためのもので、物理 LAN のサブネットルータではないので、素の Deployment で組む。 apiVersion: v1 kind: PersistentVolumeClaim metadata: name: netbird-routing-peer-data namespace: netbird annotations: - # ピアの identity(秘密鍵)。消えると再登録が要るので取る。 + # ピアの identity(秘密鍵)と設定だけ。消えると再登録が要るので取る。 k8up.io/backup: "true" spec: accessModes: - ReadWriteOnce resources: requests: - # ピアの identity(秘密鍵)と設定だけ。消えると再登録が要る storage: 128Mi --- # 鍵は Infisical の /netbird/netbird-routing-peer に `setup-key` で置く。 @@ -74,26 +65,9 @@ spec: labels: app: netbird-routing-peer spec: - # hostNetwork にしない(2026-09-08 に外した)。 - # - # 元は「LAN へ素で出るため」に hostNetwork にしていたが、Pod のネットワークからでも - # LAN には届く(Cilium が masquerade する)。実測: - # - # Pod から 10.10.0.2:3389 / 10.10.0.1:80 / 10.10.0.4:853 / 10.0.0.1:80 … 全部 OK - # - # 逆に hostNetwork だと管理サーバに繋げなくなった。Gateway を hostNetwork に - # した(#91)結果、ホスト自身からノードの 443 に繋ぐと応答が返らない - # (bootstrap/cilium/values.yaml の `nodePort`)。このピアは `nb.doany.io:443` に - # 繋ぎに行くので、そこに巻き込まれて `Management: Disconnected` で止まっていた。 - # - # ホストから nb.doany.io:443 … connection refused / timeout - # Pod から nb.doany.io:443 … 200 - # - # 2026-10-18 に nodePort の手当てを外してからは、ホストからもノード自身の 443 に届く。ただし公開 DNS の A - # (WAN 側)にはホストから届かない(talos/patches/cluster.yaml の fj.doany.io の StaticHostConfig)ので、 - # hostNetwork に戻す理由は無い。 - # - # ダッシュボードに出る名前がノード名(`main`)から Pod 名に変わる。 + # hostNetwork にしない。Pod のネットワークからでも LAN には届く(Cilium が masquerade する)。 + # ホストからは公開 DNS の A(WAN 側)に届かない(talos/patches/cluster.yaml の StaticHostConfig)ので、 + # hostNetwork だと nb.doany.io:443 に繋げず `Management: Disconnected` で止まる。 containers: - name: netbird image: netbirdio/netbird:0.81.2 @@ -107,14 +81,14 @@ spec: value: https://nb.doany.io - name: NB_LOG_LEVEL value: info - # WireGuard の口。下の hostPort と揃える。2026-10-18 までは wg-easy と併走していた頃の名残で 51822 だった。 + # WireGuard の口。下の hostPort と揃える。 # ルーターは DMZ で全部をノードに向けているので、番号を変えてもルーターは触らない(docs/router.md)。 # **効くのは最初の起動だけ。** NetBird は PVC の /var/lib/netbird/default.json に `"WgPort"` を保存し、以降はそちらを使う。 - # 番号を変えるときは default.json も直してから作り直す(2026-10-18 に変えたとき、env だけ直して hostPort とずれた)。 + # 番号を変えるときは default.json も直してから作り直す(env だけ直すと hostPort とずれる)。 - name: NB_WIREGUARD_PORT value: "51820" ports: - # hostNetwork をやめたので、WireGuard の口は hostPort で出す。 + # WireGuard の口は hostPort で出す。 # 無くても relay 経由で通信は成立するが、直接 P2P にならない。 - name: wireguard containerPort: 51820 diff --git a/apps/netbird/server-config.yaml b/apps/netbird/server-config.yaml index 1201ffa..ad64046 100644 --- a/apps/netbird/server-config.yaml +++ b/apps/netbird/server-config.yaml @@ -1,7 +1,6 @@ # NetBird combined サーバ(netbirdio/netbird-server)の設定。 # v0.65.0 以降の「combined」構成で、management / signal / relay / STUN と内蔵 IdP(Dex)が -# 1 コンテナに入っている。旧来の management+signal+relay+dashboard の 4 コンテナ構成ではない -# (公式 Helm chart netbirdio/helms は 2026-04 で更新が止まっていて旧構成のままなので使っていない)。 +# 1 コンテナに入っている(公式 Helm chart は旧来の 4 コンテナ構成のままなので使わない)。 # # 素の値は https://github.com/netbirdio/netbird/blob/main/combined/config.yaml.example と、 # 公式インストーラ getting-started.sh の render_combined_yaml() に合わせてある。 @@ -32,10 +31,9 @@ data: dataDir: "/var/lib/netbird" auth: - # 内蔵 IdP(Dex)。外部 IdP は要らない(0.62 以降)。Entra を足すのは後から - # ダッシュボードの UI でできるので、まずはローカルユーザーだけで動かす。 + # 内蔵 IdP(Dex)。Entra はダッシュボードの UI で外部 IdP として足してある。 issuer: "https://nb.doany.io/oauth2" - # ローカルのメール+パスワードを閉じる(2026-09-07)。入口は Entra だけ。 + # ローカルのメール+パスワードを閉じる。入口は Entra だけ。 # 内蔵 IdP(Dex)自体は動いたままで、外部 IdP のコネクタを提供する役に徹する。 # # 締め出したときの戻し方: ここを false にして ArgoCD に流し、 diff --git a/apps/pt3/rebind.yaml b/apps/pt3/rebind.yaml index cb2044f..1b185ff 100644 --- a/apps/pt3/rebind.yaml +++ b/apps/pt3/rebind.yaml @@ -2,7 +2,7 @@ # # Talos は kernel.modules を書いた順ではなく名前の順に読むので、earth-pt3 がチューナー # (qm1d1c0042 / mxl301rf)より先に入り、`Failed to create FE0` で /dev/dvb/*/frontend0 ができない。 -# チューナーが揃ってから unbind / bind すれば通る(移行当日 2026-10-17 に手で確かめた)。 +# チューナーが揃ってから unbind / bind すれば通る。 # 起動のたびに 1 回だけやって、あとは寝ている。tuner-agent は /dev/dvb ができるまでマウントを再試行する。 # 付け直しても frontend0 が無ければ落ちて、kubelet の再起動でやり直す(黙って寝ない)。 # namespace は denpa(PSA privileged。denpa のリポジトリの chart が作る)。PT3 は main にしか無い。 diff --git a/apps/renovate/renovate-secrets.yaml b/apps/renovate/renovate-secrets.yaml index 94bbe89..3556112 100644 --- a/apps/renovate/renovate-secrets.yaml +++ b/apps/renovate/renovate-secrets.yaml @@ -1,14 +1,11 @@ -# Secret renovate-secrets は Infisical (il.doany.io) のフォルダ /renovate/renovate-secrets にあり、 -# Infisical 純正 operator (apps/infisical-operator) が Secret にする。キーは README.md の表。 +# Secret renovate-secrets を Infisical (/renovate/renovate-secrets) から作る。キーは README.md の表。 # CronJob は Secret を毎回読み直すので、値を Infisical で書き換えれば次の実行から効く(auto-reload は要らない)。 apiVersion: secrets.infisical.com/v1alpha1 kind: InfisicalSecret metadata: name: renovate-secrets namespace: renovate - # 2 つとも必須。前者は operator が作る Secret を prune させないため、後者は - # CRD がまだ無いクラスタで apps/ の同期が丸ごと落ちるのを防ぐため。 - # bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 + # 2 つとも必須。bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 annotations: argocd.argoproj.io/sync-options: Prune=false,SkipDryRunOnMissingResource=true spec: diff --git a/apps/renovate/renovate.yaml b/apps/renovate/renovate.yaml index 2723288..e1f2683 100644 --- a/apps/renovate/renovate.yaml +++ b/apps/renovate/renovate.yaml @@ -1,9 +1,7 @@ # Renovate を自前で回す。danything と 5ym の GitHub の全リポジトリと、Forgejo(fj.doany.io)の doa の全リポジトリ。 # -# それまでは GitHub Actions(5ym/repo-config の renovate.yml)と Forgejo Actions(doa/renovate)で毎時回していたが、 -# GitHub の schedule は 15〜40 分遅れるうえに丸ごと飛ばされることがあった(2026-10-12 に数えた)。 -# CronJob なら時刻どおりに走る。**クラスタが落ちている間は止まる**が、予備は置かない(もとの 2 つの workflow は消した)。 -# クラスタが止まっているときはそれを直すのが先で、ほかの依存を上げる PR を出しても仕方がない(Forgejo はそもそもクラスタの上)。 +# GitHub Actions の schedule は遅れたり丸ごと飛ばされたりするので CronJob で回す。**クラスタが落ちている間は止まる**が、 +# 予備は置かない(クラスタを直すのが先。Forgejo はそもそもクラスタの上)。 # # 1 つの Pod が 1 つの owner を受け持つ(GitHub App のトークンがインストールごとに分かれるため)。 # Renovate には複数の owner を並行に回す機能が無いので、Indexed Job の 3 つの Pod で並べる。 @@ -11,7 +9,7 @@ # # **Pod はいつも成功で終える。** Renovate が非ゼロで終わっても、トークンが作れなくても exit 0。 # Job が失敗すると CronJob が Degraded になり、ArgoCD が gitops の同期を retry に入れて -# apps/ の更新が止まる(2026-09-12 に k8up-notify で実際に起きた。apps/k8up/notify.yaml の末尾)。 +# apps/ の更新が止まる(apps/k8up/notify.yaml の末尾)。 # 失敗はログに残す: `kubectl -n renovate logs job/<名前> --all-pods`。Job はいつも成功なので、ログを見られるよう成功の Job を 3 回分残す。 apiVersion: v1 kind: ConfigMap @@ -33,7 +31,7 @@ data: export OWNER RENOVATE_AUTODISCOVER_FILTER="$OWNER/*" echo "受け持ち: $OWNER" if [ "$OWNER" = doa ]; then - # Forgejo(fj.doany.io)。もとの doa/renovate(2026-10-17 に消した)の Forgejo Actions の env と同じ。 + # Forgejo(fj.doany.io)。 # Pod から fj.doany.io へは IPv6 でしか届かない(IPv4 はヘアピンで落ちる。apps/forgejo/runner.yaml の冒頭) export RENOVATE_PLATFORM=forgejo RENOVATE_ENDPOINT=https://fj.doany.io/api/v1 export RENOVATE_GIT_AUTHOR='Renovate Bot ' @@ -44,8 +42,7 @@ data: fi RENOVATE_TOKEN=$FORGEJO_TOKEN else - # GitHub。中身は Actions の頃の renovate.yml の env と同じ。 - # GitHub App doa-renovate(danything の org が持ち主。5ym にもインストールしてある)。client ID は秘密ではない + # GitHub。GitHub App doa-renovate(danything の org が持ち主。5ym にもインストールしてある)。client ID は秘密ではない export RENOVATE_PLATFORM=github APP_CLIENT_ID=Iv23liZjExRcK6lxJueN # App のトークンからは自分のユーザーを引けないので明示する。id は # `gh api users/doa-renovate%5Bbot%5D --jq .id` @@ -79,8 +76,7 @@ data: [ "$rc" -eq 0 ] || echo "renovate が $rc で終わった(Job は成功にしておく。renovate.yaml の冒頭)" >&2 exit 0 github-app-token.mjs: | - // GitHub App doa-renovate のインストールトークンを作って標準出力に出す - // (Actions の頃の actions/create-github-app-token の代わり)。 + // GitHub App doa-renovate のインストールトークンを作って標準出力に出す。 // App の JWT(RS256、iss は client ID)で OWNER のインストールを探し、トークンと交換する。 // トークンは 1 時間で切れる。Job の activeDeadlineSeconds はそれより短くしてある。 import { sign } from "node:crypto"; @@ -129,7 +125,6 @@ spec: completions: 3 parallelism: 3 # 番号ごとに数える。1 つが落ちても(OOMKilled など。exit 0 にできない終わり方)残りの番号は最後まで回す - # (そのときの Job は Failed になる。3 本の CronJob だった頃にその 1 本が Failed になったのと同じ) backoffLimitPerIndex: 0 # トークンは 1 時間で切れる。それより前に止める activeDeadlineSeconds: 2700 diff --git a/apps/rybbit/clickhouse.yaml b/apps/rybbit/clickhouse.yaml index 95ab366..9aa4f2e 100644 --- a/apps/rybbit/clickhouse.yaml +++ b/apps/rybbit/clickhouse.yaml @@ -1,7 +1,7 @@ # Rybbit のイベントを溜める ClickHouse。上流の docker-compose.yml の設定(network / logging / resource_limits / # user_settings)をそのまま ConfigMap にし、メモリの上限だけこの箱に合わせて下げた。 # -# 版は上流の compose に合わせる(26.3 系)。Renovate が PR を出す。 +# 版は上流の compose に合わせる。 apiVersion: v1 kind: Service metadata: diff --git a/apps/rybbit/rybbit-secrets.yaml b/apps/rybbit/rybbit-secrets.yaml index a895c83..1975eb1 100644 --- a/apps/rybbit/rybbit-secrets.yaml +++ b/apps/rybbit/rybbit-secrets.yaml @@ -1,5 +1,4 @@ -# Secret rybbit は Infisical (il.doany.io) のフォルダ /rybbit/rybbit にあり、 -# Infisical 純正 operator (apps/infisical-operator) が Secret にする。 +# Secret rybbit を Infisical (/rybbit/rybbit) から作る。 # # | キー | 何に使うか | # | --- | --- | @@ -10,16 +9,12 @@ # # 4 つとも英数字だけのランダム(32 文字くらい)。**同期する前に**入れる。無いと Pod が # CreateContainerConfigError で待つ(入れれば operator が Secret を作って自然に上がる)。 -# 値は Infisical の UI で書き換えるだけ(push-bridge が数秒で同期。auto-reload 注釈のある -# Deployment は自動で入れ替わる)。 apiVersion: secrets.infisical.com/v1alpha1 kind: InfisicalSecret metadata: name: rybbit namespace: rybbit - # 2 つとも必須。前者は operator が作る Secret を prune させないため、後者は - # CRD がまだ無いクラスタで apps/ の同期が丸ごと落ちるのを防ぐため。 - # bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 + # 2 つとも必須。bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 annotations: argocd.argoproj.io/sync-options: Prune=false,SkipDryRunOnMissingResource=true spec: diff --git a/apps/rybbit/rybbit.yaml b/apps/rybbit/rybbit.yaml index 82f6ad7..8d15a41 100644 --- a/apps/rybbit/rybbit.yaml +++ b/apps/rybbit/rybbit.yaml @@ -2,7 +2,7 @@ # 版は GitHub のリリースに合わせて 2 つ同じタグで上げる(タグは v 付き。latest は追わない)。 # # 環境変数は上流の docker-compose.yml の backend / client と同じ。DISABLE_SIGNUP は -# 最初のアカウントを作ったら true にする(README「使い始め」)。テレメトリは切る。 +# 最初のアカウント(管理者)を作ったら true にする(README「使い始め」)。 apiVersion: v1 kind: Service metadata: @@ -35,7 +35,6 @@ metadata: name: backend namespace: rybbit annotations: - # 参照している Secret を Infisical operator が同期したら、自動でローリング再起動する secrets.infisical.com/auto-reload: "true" spec: replicas: 1 @@ -110,7 +109,6 @@ spec: secretKeyRef: name: rybbit key: better-auth-secret - # 最初のアカウント(管理者)は 2026-09-19 に作った。以後は誰も登録できない - name: DISABLE_SIGNUP value: "true" - name: DISABLE_TELEMETRY