Compare commits

...
Author SHA1 Message Date
renovate[bot] d81ee1b65b chore(kube): bump chart Helm release stalwart to v0.7.18 2026-09-19 04:01:11 +00:00
vhaudiquet f2d7fe7bcc openclaw: pin image to 2026.9.3 and chown PVC mount root (operator#607)
- Pin gateway image to immutable tag 2026.9.3: the stale node-cached
  'latest' (old build, state schema v1) crash-looped against the PVC's
  DB already migrated to schema v15/16.
- Add fix-data-owner init container: the operator mounts the PVC root
  at /home/openclaw/.openclaw with fsGroup only, leaving the mount root
  owned by root; OpenClaw >= 2026.9 fchmods its config dir on write and
  fails with EPERM (paperclipinc/openclaw-operator#607).
- Ran one-time 'openclaw doctor --fix --non-interactive' against the
  PVC to complete the 2.0 workspace-state migration.
2026-09-10 00:59:25 +02:00
vhaudiquet 807d764bdf cilium(kube): scale replicas down to 1 2026-09-10 00:16:34 +02:00
vhaudiquet c613811c8e gitea: bump memory limit for valkey 2026-09-09 23:39:29 +02:00
vhaudiquet 5608fa2f0d kyverno(kube): strip limits.cpu too 2026-09-09 23:21:51 +02:00
vhaudiquet 3d258f147d kyverno(kube): foreach patchStrategicMerge must be inline mapping, not block scalar 2026-09-09 23:07:13 +02:00
vhaudiquet 764a029c39 kyverno(kube): update policy to v1 2026-09-09 22:57:58 +02:00
vhaudiquet 21d54fba97 kyverno(kube): bump version 2026-09-09 22:52:51 +02:00
vhaudiquet 26dd59845f kyverno(kube): fix deployment 2026-09-09 22:20:59 +02:00
vhaudiquet a07ce44e6d kyverno(kube): add kyverno
add a policy to remove cpu requests, to relieve cluster
2026-09-09 21:43:13 +02:00
vhaudiquet 99880ab291 gitea,longhorn: update CPU limits, tolerations, replicas 2026-09-09 18:47:12 +02:00
vhaudiquet f813170b86 gitea/valkey(kube): bump memory limit to 512 Mi
bump requested memory to 256 Mi
2026-09-07 23:43:39 +02:00
renovate[bot]andvhaudiquet c0b73e29be chore(kube): bump chart postgres Docker tag to v0.20.4 2026-09-01 01:05:41 +02:00
renovate[bot]andvhaudiquet 69c59daf5e chore(kube): bump caddy Docker tag to v2.11.4 2026-09-01 01:05:29 +02:00
renovate[bot]andvhaudiquet a2a97180c9 chore(kube): bump chart Helm release cert-manager-webhook-ovh to v0.9.16 2026-09-01 01:05:19 +02:00
renovate[bot]andvhaudiquet 6d9e6c76c8 chore(kube): bump coredns/coredns Docker tag to v1.14.7 2026-09-01 01:04:56 +02:00
renovate[bot]andvhaudiquet 9a9894fc8c chore(kube): bump chart redis Docker tag to v0.34.26 2026-09-01 01:04:41 +02:00
renovate[bot]andvhaudiquet 2c4b3127b4 chore(kube): bump stalwartlabs/stalwart Docker tag to v0.16.20 2026-09-01 01:04:00 +02:00
renovate[bot]andvhaudiquet 372dbff681 chore(kube): bump chart Helm release stalwart to v0.7.16 2026-09-01 01:03:46 +02:00
renovate[bot]andvhaudiquet 072470c17d chore(kube): bump chart Helm release longhorn to v1.12.1 2026-09-01 01:03:20 +02:00
vhaudiquet 38a6fdba74 renovate: remove pr footer, remove hourly limit, fix patterns 2026-09-01 00:39:25 +02:00
vhaudiquet 54ae16dda9 renovate: remove schedule 2026-08-31 22:58:06 +02:00
vhaudiquet 15b8ef7687 renovate: set ram limits up to 2G 2026-08-30 10:04:19 +02:00
vhaudiquet 2a44c4932b renovate: update renovate.json config 2026-08-26 21:55:09 +02:00
vhaudiquet 13cca1852e renovate: update to new oci repository 2026-08-26 21:39:34 +02:00
vhaudiquet a80b45618c renovate: deploy renovate on kube 2026-08-26 21:35:02 +02:00
kosmos-ai-botandvhaudiquet 45f8f84cbc chore(renovate): drop self-hosted runner from this PR (merge config only)
Per review feedback: remove the self-hosted Renovate deployment
(kubernetes/code/renovate/* + root kustomization wiring) from this PR and
defer it to a follow-up. Keep the renovate.json config to merge now.

Also drop the postUpgradeTasks SOPS re-encrypt block: it depended on the
runner's boot.sh decrypt flow, and the hosted Mend app cannot run 'sops'
(allowedPostUpgradeCommands). SOPS handling returns with the deployment.
2026-08-26 19:58:55 +02:00
kosmosandvhaudiquet 1623b2ea7d fix(renovate): decrypt values BEFORE renovate edits them (retract broken post-bump round-trip)
The prior postUpgradeTasks command 'sops -d ... && sops -e' was wrong:
Renovate has no preUpgradeTasks hook, and postUpgradeTasks runs AFTER
Renovate rewrites the file. These values.yaml are SOPS documents whose
sops.mac authenticates the whole file, so editing a plaintext image.tag
invalidates the MAC and 'sops -d' then fails (data-integrity error). The
claimed decrypt-after-bump therefore could never work.

boot.sh now decrypts every values.yaml in the checkout BEFORE Renovate
extracts/edits them, committing the decrypted tree locally (never pushed,
so no plaintext secrets enter remote git). postUpgradeTasks is reduced to
'sops -e -i' only (the file is already plaintext when Renovate edits it).

Validated: kustomize build passes for the whole kubernetes/ tree.
2026-08-26 19:58:55 +02:00
kosmosandvhaudiquet 5bf07a2fff chore(renovate): add SOPS round-trip postUpgradeTasks + self-hosted runner
Address review feedback on SOPS handling for encrypted values.yaml.

- renovate.json: Renovate has NO preUpgradeTasks option (verified against
  the renovate-schema). Decrypt must therefore happen inside postUpgradeTasks
  (which run after the tag bump, before the commit): decrypt the values.yaml,
  then re-encrypt. Encrypting an already-encrypted file would double-encrypt
  the existing ENC secret values. Only **/values.yaml is re-encrypted; the
  docker-compose and Chart.yaml files are not SOPS-encrypted here.
- kubernetes/code/renovate: self-hosted Renovate runner as a Flux CronJob
  running the renovatebot/renovate image, with sops allowed as a
  postUpgradeTask command and the SOPS PGP key loaded to re-encrypt
  values.yaml. Secrets come from SOPS-encrypted dotenv/env file sources.
- Wire code/renovate into the root kubernetes kustomization.
2026-08-26 19:58:55 +02:00
kosmosandvhaudiquet e71d4be59f chore(renovate): use chore(docker)/chore(kube) commit message scopes 2026-08-26 19:58:55 +02:00
kosmosandvhaudiquet 74f404b6c9 chore: simplify renovate config to rely on auto-discovery
Drop the generate-renovate.sh generator and explicit fileMatch lists.
Renovate auto-discovers docker-compose, values.yaml and Chart.yaml via
the docker-compose, helm-values and helmv3 managers. Use helmv3 (not
helm-requirements) for Chart.yaml dependencies (Helm v3).
2026-08-26 19:58:55 +02:00
kosmosandvhaudiquet 3774c8ef7e chore: migrate from Dependabot to Renovate 2026-08-26 19:58:55 +02:00
dependabot[bot]andkosmos cf2e464d4a docker(deps): bump esphome/esphome in /docker/home/esphome
Bumps [esphome/esphome](https://github.com/esphome/esphome) from 2026.7.4 to 2026.8.0.
- [Release notes](https://github.com/esphome/esphome/releases)
- [Commits](https://github.com/esphome/esphome/compare/2026.7.4...2026.8.0)

---
updated-dependencies:
- dependency-name: esphome/esphome
  dependency-version: 2026.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-25 14:08:35 +00:00
kosmosandvhaudiquet 6da9484fa3 openclaw: add egress NetworkPolicy for Radicale CalDAV
Allow the openclaw pod to reach the Radicale CalDAV/CardDAV server
(namespace: radicale, port 5232) so Kosmos can read/write Valentin's
calendar via the in-cluster service. Mirrors networkpolicy-mail-egress.yaml.

Workaround for spec.networkPolicy.additionalEgress not being in the CRD
bundled with operator chart 0.39.0 yet (silently pruned).
2026-08-25 00:08:03 +02:00
vhaudiquet 989a16b878 openclaw: allow runtimeDeps python 2026-08-24 23:19:41 +02:00
vhaudiquet 53fd78081d openclaw: add chromium sidecar 2026-08-24 23:15:04 +02:00
vhaudiquet b351545c92 radicale: deploy on kube 2026-08-24 21:16:53 +02:00
vhaudiquet ced1042fc1 openclaw: update secrets
<beep boop, I'm a bot>
2026-08-24 14:01:23 +02:00
vhaudiquet 400d5910be openclaw: allow ingress networkpolicy 2026-08-23 21:36:32 +02:00
vhaudiquet 79faafe40a openclaw: allow traefik namespace 2026-08-23 18:21:54 +02:00
vhaudiquet 539622817d openclaw: enable http access 2026-08-23 11:03:05 +02:00
vhaudiquet 34660b1231 openclaw: deploy openclaw on kube 2026-08-23 10:43:07 +02:00
vhaudiquet 9c2f4de590 dependabot: update commit messages 2026-08-22 21:19:11 +02:00
vhaudiquet b393049241 gitea: make namespace privileged for actions runners 2026-08-22 12:31:03 +02:00
vhaudiquet 8abd2add2e gitea: deploy in-cluster action runner 2026-08-22 12:15:30 +02:00
vhaudiquet 19fb650b8d infra: remove stale old kube files, infra/kube is new truth 2026-08-21 20:36:53 +02:00
vhaudiquet 8f97feb3e9 infra/kube: added kube cluster infrastructure 2026-08-21 20:35:32 +02:00
vhaudiquet 7ff65257a7 linkwarden: remove linkwarden, bye! 2026-08-21 20:18:41 +02:00
vhaudiquet 16f83820e7 dns(local): remove/update stale entries 2026-08-21 19:25:02 +02:00
vhaudiquet 972d4d1510 blocky: update coredns service ip 2026-08-21 18:53:47 +02:00
vhaudiquet 38fa3ae058 dns(local): update truenas, p330 2026-08-21 00:30:27 +02:00
vhaudiquet 0ef10e278e trafik: pin loadbalancerip 2026-08-20 23:32:22 +02:00
vhaudiquet ac3a6a1b60 network: fix previous ips 2026-08-20 23:26:03 +02:00
vhaudiquet 207aa84670 network: allocate new ips on final segment 2026-08-20 22:31:57 +02:00
vhaudiquet 950ced8477 flux: re-order longhorn jobs for right dependencies 2026-08-19 17:14:26 +02:00
vhaudiquet bc6f92e145 flux: re-order certificates for right dependencies 2026-08-19 16:56:23 +02:00
vhaudiquet f420718943 dns(local): update p330 2026-08-17 21:32:25 +02:00
vhaudiquet fd309e4f94 network: release old IPs, allocate new IPs, swap DNS
Migrating houses is never easy...
2026-08-17 20:27:08 +02:00
vhaudiquet 4b1d2c3102 obsidian-livesync: remove from docker 2026-08-17 00:12:49 +02:00
vhaudiquet d8970a5f4b obsidian-livesync: set couchdb shards to 1 2026-08-16 23:50:13 +02:00
vhaudiquet 7b6d8f3dc4 obsidian-livesync: update ingress 2026-08-16 22:29:08 +02:00
vhaudiquet 7d32e91b9c obsidian-livesync: add couchdb uuid 2026-08-16 22:25:52 +02:00
vhaudiquet 8c83e6c7ab obsidian-livesync: deploy to kube 2026-08-16 22:16:47 +02:00
vhaudiquet f553e19af4 p330: remove dedicated=failover taint 2026-08-16 20:40:15 +02:00
vhaudiquet 5e9bebc4f0 paperless: remove from docker 2026-08-16 12:10:27 +02:00
vhaudiquet 5a3984c0b2 dns(local): remove old paperless dns entry 2026-08-16 11:46:25 +02:00
vhaudiquet 48608bc59e paperless: deploy on kube 2026-08-16 11:07:01 +02:00
semerysandvhaudiquet 8bca7ca466 semery-fr: remove from docker 2026-08-15 16:46:33 +02:00
semerysandvhaudiquet dcdc0bf138 caddy: move semeryfr to kube 2026-08-15 16:46:33 +02:00
semerysandvhaudiquet 07ea93a90a semery-fr: deploy on kube 2026-08-15 16:46:33 +02:00
vhaudiquet 2d05743c6d dns(local): update p330 ip 2026-08-15 14:49:50 +02:00
vhaudiquet fe98f670cf infra/rpi4: set CNI to none for cilium 2026-08-14 20:31:46 +02:00
vhaudiquet 2a024821d2 infra/p330: set CNI to none for cilium 2026-08-14 18:36:28 +02:00
vhaudiquet 00859be72a notesnook: tryfix, remove know_proxies 2026-08-13 19:31:25 +02:00
vhaudiquet c1f4a57570 notesnook: add minio ingress path 2026-08-13 19:21:15 +02:00
vhaudiquet eaa47c9b6d notesnook: updated chart, added inbox API 2026-08-13 18:55:06 +02:00
vhaudiquet f2cd5f2d98 buildpath: update memory limits 2026-08-13 12:55:04 +02:00
vhaudiquet be88bbcd93 buildpath: remove from docker, bye! 2026-08-13 01:16:17 +02:00
vhaudiquet a8f7ff538c caddy: move buildpath from docker to kube 2026-08-13 00:52:49 +02:00
vhaudiquet b5a48584f0 gitea: go back to rootless 2026-08-13 00:43:19 +02:00
vhaudiquet c89ee33798 gitea: tryfix running non-rootless image 2026-08-12 23:24:09 +02:00
vhaudiquet 1e9a9080e9 gitea: add env override for HOME 2026-08-12 22:59:54 +02:00
vhaudiquet 50b68bf569 buildpath: specify kube chart version 2026-08-12 18:31:38 +02:00
vhaudiquet 2a95f8129b buildpath: update repository for kube 2026-08-12 18:28:05 +02:00
vhaudiquet 2a988f1a7c gitea: bump to latest 2026-08-12 18:22:39 +02:00
vhaudiquet 8604e270e1 buildpath: update kustomizeconfig 2026-08-12 18:17:10 +02:00
vhaudiquet 99639b1052 buildpath: fix kube chart repository 2026-08-12 18:14:26 +02:00
vhaudiquet 51d234157d buildpath: fix kube chart kind 2026-08-12 18:12:26 +02:00
vhaudiquet b8104d982b buildpath: fix kube chart 2026-08-12 18:11:08 +02:00
vhaudiquet 0fcfc016a6 buildpath: deploy on kube 2026-08-12 18:02:38 +02:00
vhaudiquet 315a7d79ea build(deps): bump buildpath 2026-08-12 00:53:11 +02:00
vhaudiquet 314b51313e photoprism: bump storage to 10G 2026-08-11 11:25:09 +02:00
vhaudiquet 8f8fa75099 photoprism: bump memory to 8G and limit to 1 worker 2026-08-11 00:49:57 +02:00
vhaudiquet 68ba23768e photoprism: moved to photos.vhaudiquet.fr 2026-08-10 23:40:33 +02:00
vhaudiquet 98cb3b8a52 infra/r740/proxmox: remove floating memory on kube VM 2026-08-10 23:12:47 +02:00
vhaudiquet 91adc68fd1 sshportal: remove sshportal, bye! 2026-08-10 23:07:22 +02:00
vhaudiquet 9411e860f9 matter-server: remove matter-server, bye! 2026-08-10 23:05:44 +02:00
vhaudiquet c183f17606 fix(observability,photoprism): add resource limits to prevent OOM kills and sidecar crash-loops
- photoprism: add requests (200m/1Gi) and limits (2/4Gi) for RAW indexing
- grafana: add requests (100m/256Mi) and limits (500m/512Mi) to prevent OOMKill
- kube-state-metrics: add requests (50m/128Mi) and limits (200m/256Mi)
- node-exporter: add requests (50m/50Mi) and limits (200m/128Mi)
- vm-operator: add requests (50m/64Mi) and limits (200m/256Mi)
- loki sidecar (rules): add REQ_TIMEOUT=120, retry env vars, and small resources
- grafana sidecars (dashboards+datasources): add REQ_TIMEOUT=120 and retry env vars
2026-08-10 22:52:47 +02:00
dependabot[bot]andvhaudiquet 086b35fde4 build(deps): bump esphome/esphome in /docker/home/esphome
Bumps [esphome/esphome](https://github.com/esphome/esphome) from 2026.6.4 to 2026.7.4.
- [Release notes](https://github.com/esphome/esphome/releases)
- [Commits](https://github.com/esphome/esphome/compare/2026.6.4...2026.7.4)

---
updated-dependencies:
- dependency-name: esphome/esphome
  dependency-version: 2026.7.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 18:10:34 +02:00
dependabot[bot]andvhaudiquet 22c1573277 build(deps): bump victoriametrics/vmagent
Bumps victoriametrics/vmagent from v1.131.0 to v1.149.0.

---
updated-dependencies:
- dependency-name: victoriametrics/vmagent
  dependency-version: v1.149.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 18:10:18 +02:00
dependabot[bot]andvhaudiquet 8c16390634 build(deps): bump hotio/jackett
Bumps [hotio/jackett](https://github.com/hotio/jackett) from release-v0.24.2184 to release-v0.24.2335.
- [Commits](https://github.com/hotio/jackett/commits)

---
updated-dependencies:
- dependency-name: hotio/jackett
  dependency-version: release-v0.24.2335
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 18:10:06 +02:00
dependabot[bot]andvhaudiquet 1bcd2d2843 build(deps): bump jellyfin/jellyfin
Bumps jellyfin/jellyfin from 2026070606 to 2026080308.

---
updated-dependencies:
- dependency-name: jellyfin/jellyfin
  dependency-version: '2026080308'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 18:09:58 +02:00
dependabot[bot]andvhaudiquet 7627129f37 build(deps): bump hotio/radarr
Bumps [hotio/radarr](https://github.com/hotio/radarr) from release-6.2.1.10461 to release-6.3.0.10514.
- [Commits](https://github.com/hotio/radarr/commits)

---
updated-dependencies:
- dependency-name: hotio/radarr
  dependency-version: release-6.3.0.10514
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 18:09:48 +02:00
dependabot[bot]andvhaudiquet 9b856de5ce build(deps): bump deluan/navidrome
Bumps deluan/navidrome from 0.62.0 to 0.63.2.

---
updated-dependencies:
- dependency-name: deluan/navidrome
  dependency-version: 0.63.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 18:09:40 +02:00
dependabot[bot]andvhaudiquet 62797cb853 build(deps): bump tomsquest/docker-radicale in /docker/personal/radicale
Bumps tomsquest/docker-radicale from 3.7.5.0 to 3.7.6.0.

---
updated-dependencies:
- dependency-name: tomsquest/docker-radicale
  dependency-version: 3.7.6.0
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 18:09:33 +02:00
dependabot[bot]andvhaudiquet 783cf7f115 build(deps): bump cadvisor/cadvisor
Bumps cadvisor/cadvisor from v0.49.1 to v0.55.1.

---
updated-dependencies:
- dependency-name: cadvisor/cadvisor
  dependency-version: v0.55.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 18:09:26 +02:00
dependabot[bot]andvhaudiquet 80486948b0 build(deps): bump prom/node-exporter
Bumps prom/node-exporter from v1.9.1 to v1.12.1.

---
updated-dependencies:
- dependency-name: prom/node-exporter
  dependency-version: v1.12.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 18:09:17 +02:00
dependabot[bot]andvhaudiquet b0deddfb04 build(deps): bump shaneisrael/fireshare in /docker/personal/fireshare
Bumps shaneisrael/fireshare from 1.7.3-lite to 1.7.4-lite.

---
updated-dependencies:
- dependency-name: shaneisrael/fireshare
  dependency-version: 1.7.4-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 18:09:09 +02:00
dependabot[bot]andvhaudiquet 2a060150be build(deps): bump gramps-project/grampsweb in /docker/personal/gramps
Bumps [gramps-project/grampsweb](https://github.com/gramps-project/gramps-web) from 26.6.2 to 26.7.1.
- [Release notes](https://github.com/gramps-project/gramps-web/releases)
- [Commits](https://github.com/gramps-project/gramps-web/compare/v26.6.2...v26.7.1)

---
updated-dependencies:
- dependency-name: gramps-project/grampsweb
  dependency-version: 26.7.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 18:09:02 +02:00
dependabot[bot]andvhaudiquet 1422b1c641 build(deps): bump library/redis in /docker/personal/gramps
Bumps library/redis from 8.8.0-alpine to 8.10.0-alpine.

---
updated-dependencies:
- dependency-name: library/redis
  dependency-version: 8.10.0-alpine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 18:08:56 +02:00
vhaudiquet be6053f5a3 openwebui: deploy openwebui 2026-08-09 21:23:15 +02:00
vhaudiquet 88146579c0 refactor: consolidate kubernetes categories 2026-08-09 19:58:18 +02:00
vhaudiquet 434c1aa51e build(deps): bump buildpath 2026-08-08 22:51:26 +02:00
vhaudiquet 16240e0589 readme: add p330, rpi4, typos 2026-08-04 22:24:16 +02:00
235 changed files with 3659 additions and 2988 deletions
-66
View File
@@ -1,66 +0,0 @@
version: 2
updates:
- package-ecosystem: "docker-compose"
open-pull-requests-limit: 15
schedule:
interval: weekly
directories:
- "/docker/home/esphome"
- "/docker/home/matter-server"
- "/docker/home/mosquitto-mqtt"
- "/docker/home/n8n"
- "/docker/home/node-red"
- "/docker/home/zigbee2mqtt"
- "/docker/infrastructure/mail/roundcube"
- "/docker/infrastructure/network/traefik"
- "/docker/infrastructure/observability"
- "/docker/infrastructure/squid"
- "/docker/infrastructure/sshportal"
- "/docker/personal/fireshare"
- "/docker/personal/gramps"
- "/docker/personal/media/films-series/jackett"
- "/docker/personal/media/films-series/jellyfin"
- "/docker/personal/media/films-series/jellyseerr"
- "/docker/personal/media/films-series/radarr"
- "/docker/personal/media/films-series/sonarr"
- "/docker/personal/media/films-series/transmission"
- "/docker/personal/media/films-series/wizarr"
- "/docker/personal/media/music/navidrome"
- "/docker/personal/media/youtube/tubearchivist"
- "/docker/personal/paperless"
- "/docker/personal/radicale"
- "/docker/personal/syncthing"
- "/docker/personal/tandoor"
- "/docker/production/alexscript"
- "/docker/production/buildpath"
- "/docker/production/semeryfr"
- "/docker/tools/excalidraw"
- "/docker/tools/obsidian-livesync"
- "/docker/tools/stirling-pdf"
- package-ecosystem: "helm"
open-pull-requests-limit: 15
schedule:
interval: weekly
directories:
- "/kubernetes/code/gitea"
- "/kubernetes/code/harbor"
- "/kubernetes/home/home-assistant"
- "/kubernetes/home/zigbee2mqtt"
- "/kubernetes/infrastructure/authentik"
- "/kubernetes/infrastructure/mail/stalwart"
- "/kubernetes/personal/linkwarden"
- "/kubernetes/personal/notesnook"
- "/kubernetes/personal/photoprism"
- "/kubernetes/production/umami"
- "/kubernetes/production/vhaudiquet-fr"
- "/kubernetes/system/blocky"
- "/kubernetes/system/caddy"
- "/kubernetes/system/cert-manager"
- "/kubernetes/system/cert-manager-webhook-ovh"
- "/kubernetes/system/coredns"
- "/kubernetes/system/csi-driver-nfs"
- "/kubernetes/system/external-dns"
- "/kubernetes/system/longhorn"
- "/kubernetes/system/traefik"
- "/kubernetes/tools/dashy"
- "/kubernetes/tools/glance"
-5
View File
@@ -6,11 +6,6 @@ repos:
entry: .pre-commit-sops.sh
language: script
pass_filenames: true
- id: generate-dependabot
name: generate dependabot
entry: generate-dependabot.sh
language: script
pass_filenames: false
- id: generate-docker-swarmcd
name: generate docker swarmcd
entry: generate-docker-swarmcd.sh
+7
View File
@@ -1,6 +1,13 @@
#!/bin/bash
for filename in "$@"; do
if [[ "${filename}" =~ values.ya?ml$ ]] || [[ "${filename}" =~ secrets?.ya?ml$ ]] || [[ "${filename}" =~ .env$ ]]; then
# Skip files that are already SOPS-encrypted: sops -e -i refuses files
# containing a top-level 'sops' metadata block (YAML) or '#sops'
# comments (dotenv), and double-encrypting would corrupt them anyway.
# Makes the hook idempotent for encrypted-at-rest working trees.
if grep -qE '^(sops:|#sops)' "${filename}" 2>/dev/null; then
continue
fi
sops -e -i "${filename}"
git add "${filename}"
fi
+3 -2
View File
@@ -1,9 +1,10 @@
creation_rules:
- path_regex: .*values.yaml$
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*\.ya?ml)$
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*PASS|.*SOCIALACCOUNT_PROVIDERS|.*\.ya?ml)$
mac_only_encrypted: true
pgp: DC6910268E657FF70BA7EC289974494E76938DDC
- path_regex: .*.yaml
encrypted_regex: ^(data|stringData|.*.key|.*.crt)$
encrypted_regex: ^(data|stringData|.*key|.*crt)$
pgp: DC6910268E657FF70BA7EC289974494E76938DDC
- path_regex: .*.env$
input_type: dotenv
-36
View File
@@ -3,11 +3,6 @@ esphome:
branch: main
compose_file: docker/home/esphome/docker-compose.yml
matter-server:
repo: homeprod
branch: main
compose_file: docker/home/matter-server/docker-compose.yml
mosquitto-mqtt:
repo: homeprod
branch: main
@@ -48,11 +43,6 @@ squid:
branch: main
compose_file: docker/infrastructure/squid/docker-compose.yml
sshportal:
repo: homeprod
branch: main
compose_file: docker/infrastructure/sshportal/docker-compose.yml
fireshare:
repo: homeprod
branch: main
@@ -112,13 +102,6 @@ tubearchivist:
sops_files:
- docker/personal/media/youtube/tubearchivist/.env
paperless:
repo: homeprod
branch: main
compose_file: docker/personal/paperless/docker-compose.yml
sops_files:
- docker/personal/paperless/.env
radicale:
repo: homeprod
branch: main
@@ -141,30 +124,11 @@ alexscript:
branch: main
compose_file: docker/production/alexscript/docker-compose.yml
buildpath:
repo: homeprod
branch: main
compose_file: docker/production/buildpath/docker-compose.yml
sops_files:
- docker/production/buildpath/.env
semeryfr:
repo: homeprod
branch: main
compose_file: docker/production/semeryfr/docker-compose.yml
excalidraw:
repo: homeprod
branch: main
compose_file: docker/tools/excalidraw/docker-compose.yml
obsidian-livesync:
repo: homeprod
branch: main
compose_file: docker/tools/obsidian-livesync/docker-compose.yml
sops_files:
- docker/tools/obsidian-livesync/.env
stirling-pdf:
repo: homeprod
branch: main
+10 -2
View File
@@ -20,7 +20,15 @@ SAS9300-8E external SAS card
NVIDIA RTX 3060 12G graphics card
```
Running as single-node Proxmox
Running as single-node Proxmox, with multiple VMs and LXC containers.
#### Lenovo P330
Running as a Talos/Kubernetes cluster node, for failover deployment.
#### Raspberry Pi 4
Running as a Talos/Kubernetes cluster node, for quorum only.
### Software stack(s)
@@ -50,7 +58,7 @@ Debian and docker / docker swarm are deployed by Terraform, which also deploys [
| <img width=32 src="https://avatars.githubusercontent.com/u/12724356"><img width=32 src="https://avatars.githubusercontent.com/u/40275816"> | Repository applications | Gitea, Harbor to store code and images |
| <img width=30 src="https://buildpath.win/_ipx/w_60&f_webp/buildpath-high-resolution-logo-transparent.png"> <img width=32 src="https://avatars.githubusercontent.com/u/13844975"> | Production applications | Personal applications running on the cluster |
Talos Linux, Cilium and flux are deployed using Terraform ; then flux takes over and deploys the whole `kubernetes` folder of this repository.
Talos Linux, Cilium and Flux are deployed using Terraform; then Flux takes over and deploys the whole `kubernetes` folder of this repository.
### Production/personal applications
+2 -2
View File
@@ -6,7 +6,7 @@
proxied: false
ttl: 300
type: A
value: 83.113.30.49
value: 82.64.154.58
- type: TXT
value: google-site-verification=BvFkK7orKeezgxGcdPiGa67PUm9RPI6ZjyyykhSJ24A
_acme-challenge:
@@ -25,4 +25,4 @@ www:
proxied: false
ttl: 300
type: A
value: 83.113.30.49
value: 82.64.154.58
+16 -52
View File
@@ -5,7 +5,7 @@
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
value: 82.64.154.58
- octodns:
cloudflare:
auto-ttl: true
@@ -257,27 +257,20 @@ _submissions._tcp:
priority: 0
target: vhaudiquet.fr.
weight: 1
alexscript:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
auth-nook:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
value: 82.64.154.58
authentik:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
value: 82.64.154.58
autoconfig:
octodns:
cloudflare:
@@ -292,13 +285,6 @@ autodiscover:
ttl: 300
type: CNAME
value: mail.vhaudiquet.fr.
canada:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 192.99.6.159
clips:
octodns:
cloudflare:
@@ -319,29 +305,21 @@ flux-webhook:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
value: 82.64.154.58
git:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
jupyter:
value: 82.64.154.58
inbox-nook:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
kasm:
octodns:
cloudflare:
auto-ttl: true
proxied: true
ttl: 300
type: A
value: 83.113.30.49
value: 82.64.154.58
ligory:
- octodns:
cloudflare:
@@ -357,33 +335,19 @@ ligory:
value:
exchange: ligory.vhaudiquet.fr.
preference: 20
lol:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
mail:
- octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
value: 82.64.154.58
- octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TXT
value: v=spf1 a ra=postmaster -all
md:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
mta-sts:
octodns:
cloudflare:
@@ -397,46 +361,46 @@ n:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
value: 82.64.154.58
nook:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
value: 82.64.154.58
notesnook:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
overleaf:
value: 82.64.154.58
photos:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
value: 82.64.154.58
sse-nook:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
value: 82.64.154.58
umami:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
value: 82.64.154.58
www:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
value: 82.64.154.58
+1 -1
View File
@@ -1,6 +1,6 @@
services:
esphome:
image: ghcr.io/esphome/esphome:2026.6.4
image: ghcr.io/esphome/esphome:2026.8.0
ports:
- "6052"
networks:
@@ -1,16 +0,0 @@
services:
matter-server:
image: ghcr.io/matter-js/python-matter-server:8.1.2
container_name: matter-server
restart: unless-stopped
network_mode: host
volumes:
- data:/data/
volumes:
data:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/matter-server/data'
@@ -9,7 +9,7 @@
services:
node-exporter:
image: prom/node-exporter:v1.9.1
image: prom/node-exporter:v1.12.1
container_name: obs-node-exporter
network_mode: host
pid: host
@@ -22,7 +22,7 @@ services:
- "traefik.enable=false"
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.49.1
image: gcr.io/cadvisor/cadvisor:v0.55.1
container_name: obs-cadvisor
ports:
- "8080"
@@ -37,7 +37,7 @@ services:
- "traefik.enable=false"
vmagent:
image: victoriametrics/vmagent:v1.131.0
image: victoriametrics/vmagent:v1.149.0
container_name: obs-vmagent
# vmagent listens on 8429 (its own metrics), scrapes node-exporter:9100
# and cadvisor:8080, remote_writes to vm-internal.lan
@@ -1,11 +0,0 @@
services:
sshportal:
image: moul/sshportal
container_name: sshportal
ports:
- "2222:2222"
volumes:
- "data:/root/"
volumes:
data:
+1 -1
View File
@@ -1,7 +1,7 @@
services:
fireshare:
container_name: fireshare
image: shaneisrael/fireshare:1.7.3-lite
image: shaneisrael/fireshare:1.7.4-lite
ports:
- "80"
volumes:
+3 -3
View File
@@ -1,7 +1,7 @@
services:
grampsweb:
container_name: grampsweb
image: ghcr.io/gramps-project/grampsweb:26.6.2
image: ghcr.io/gramps-project/grampsweb:26.7.1
restart: always
networks:
- default
@@ -31,7 +31,7 @@ services:
grampsweb_celery:
container_name: grampsweb_celery
image: ghcr.io/gramps-project/grampsweb:26.6.2
image: ghcr.io/gramps-project/grampsweb:26.7.1
restart: always
environment:
- GRAMPSWEB_TREE="Gramps Web" # will create a new tree if not exists
@@ -52,7 +52,7 @@ services:
command: celery -A gramps_webapi.celery worker --loglevel=INFO --concurrency=2
grampsweb_redis:
image: docker.io/library/redis:8.8.0-alpine
image: docker.io/library/redis:8.10.0-alpine
container_name: grampsweb_redis
restart: always
@@ -1,7 +1,7 @@
services:
jackett:
container_name: jackett
image: ghcr.io/hotio/jackett:release-v0.24.2184
image: ghcr.io/hotio/jackett:release-v0.24.2335
ports:
- "9117"
networks:
@@ -1,6 +1,6 @@
services:
jellyfin:
image: jellyfin/jellyfin:2026070606
image: jellyfin/jellyfin:2026080308
container_name: jellyfin
networks:
- default
@@ -1,7 +1,7 @@
services:
radarr:
container_name: radarr
image: ghcr.io/hotio/radarr:release-6.2.1.10461
image: ghcr.io/hotio/radarr:release-6.3.0.10514
ports:
- "7878"
networks:
@@ -1,6 +1,6 @@
services:
navidrome:
image: deluan/navidrome:0.62.0
image: deluan/navidrome:0.63.2
user: 1000:1000 # should be owner of volumes
ports:
- "4533"
-16
View File
@@ -1,16 +0,0 @@
PAPERLESS_URL=ENC[AES256_GCM,data:5Vt6SqefNzOKGzUaRukM7wKu7Nw=,iv:/x12Sv55XY1znKr2UFQB1Scp+T1cZBs5XlqxTNtBQck=,tag:xahglGfuW2wCkDMgX1nZGA==,type:str]
PAPERLESS_SECRET_KEY=ENC[AES256_GCM,data:CoWplCZsHbgFPkkBDnzaPnXcq9Fv4OpXuJHs0YTLDi+MmJjK4Lpd+Q==,iv:vX3uYJ0S6lSyHW3comqum5ncXUHFj7LCdNSbRRgY3/M=,tag:gwSwk1lVmoQdgqQ38sFN0A==,type:str]
PAPERLESS_TIME_ZONE=ENC[AES256_GCM,data:sDtE4GwXr9CScxyq,iv:7oGDO/5Dvj8/E4qzzIhncbboTRfJbTfT/FwUhF4tCNg=,tag:mEcg/i2TaCls+FgCTl6AlA==,type:str]
PAPERLESS_OCR_LANGUAGE=ENC[AES256_GCM,data:ihFV,iv:+xRvsrymSIB4z5K03bU6N+pugafhvHph3epj1HTDPag=,tag:RhBA2b1q3jIhE9bmcwtYxQ==,type:str]
PAPERLESS_OCR_LANGUAGES=ENC[AES256_GCM,data:0pbc/9WMlw==,iv:HRnX25U1CasIvdU0h0G0SYvRjzzpmyPpDrcN6sAk+Ck=,tag:Ym08zaK+LqSDEafnUVvGnQ==,type:str]
PAPERLESS_OCR_USER_ARGS=ENC[AES256_GCM,data:DdpIIK0k5wsJWhcVNtq6w1mK2nsBlXKs/bB3kCxUe9tj7tyff2yH,iv:htcBkWENiugF1T2N0JfJOGfn2F15Ti6icf6JnzmLNjQ=,tag:EACbCMn4aZ7zCWxd1voawA==,type:str]
PAPERLESS_SOCIALACCOUNT_PROVIDERS=ENC[AES256_GCM,data:vLWinFKXotVzhHqmwpJ6R93Ep44JL7D1P91DbbLcGawfl8Hx+cTtYX2zuBAzeqrlDd+pHVX9I/F/eq3sAFUJrHhwSiscPaw4lc0KWVj3yAbR6guu3ZGKLMZiltGi8adOt+ELvL4aJYNfsdcECaj71JXaqF08+DkLuG6k3BOp/5j+BRFTuAfyS8SXgSo9UTpfNqJWLA2YyNiEy1ht9sbNJYT5FbN9++ZFlJPVmJDyo/8kU2CdkowmLuFhij2hcCt/wvhQ5kjYIzr+LCuPGtF68CVChVguXxTj7w5Mqo9bkdIIUtjzubhbP7LiERE5vQdLve75ZE4mQFt/5H01qwqZkXw7DFn4sJXKQCpCyA+IanA1NO2ypd1plYiR8F+15LNtbfPuZo5hzpYdf3y1xgPrSHUMV0AvAbvJYXyDg2UprpGzxSwLmskZc+4Dqm8ZfTp8IdC9RvETets6fA6t1ucnYFbEB4t0RfF1wzI93m5acE0XvDe7PvnW9X10XDwAhKV6EY9V7OktiL1/swO7MxI5qV6NtxXMMg46V6l/63k5GDmM0FS4Sn9BeIQ=,iv:JwSeogftyoa4k0kQAf63nnoqbIiHWH0Iwa83Nhqlx9Y=,tag:9KrbSxSmN1CzqnVxcsvPgw==,type:str]
POSTGRES_USER=ENC[AES256_GCM,data:2IkvrQgFYj0v,iv:YxKokHIOsRhgRx2XZsCYsjtJwW0yOx+S5HKKiFQBKlY=,tag:HI4aSRYp7GotOXeF8VBHQw==,type:str]
POSTGRES_PASSWORD=ENC[AES256_GCM,data:8IiqLOi+Xoln,iv:9zLPLvSe+7FjjunVQvcn5YiejZj0wN1mQu++B2JPy9o=,tag:HRIHXlmYTPCSaZ5BzPA/aQ==,type:str]
sops_lastmodified=2025-10-08T19:39:41Z
sops_mac=ENC[AES256_GCM,data:bjQBttibD3m6mjiDtQ/RqfSc0rt3eV/ip+UUzwF45k/+akQCM+kAvSVFiICpRYLQd90hGDSJJytGze0YQBIYS58u/PXovqT+BmbJ5S9jEVwDUnAnFwoVmuGI6dkorCGgLZFxbj/Vwde5v2R3K7nMTyPC/5EJPd4R9gZLgT8/+Bw=,iv:tyyjQXpBEDb+KOEFRNPxUIcEcxYAM+qw2pCyvOltuFE=,tag:xPfaZTAi1Sd0RW5PN0iKog==,type:str]
sops_pgp__list_0__map_created_at=2025-10-08T19:39:41Z
sops_pgp__list_0__map_enc=-----BEGIN PGP MESSAGE-----\n\nhQIMA7uy4qQr71wiAQ//WBbj9C5n7tOL8HBWRiiwRHS8nE3XWg7rAROnvEaD5QuE\nEubGw+PnsX3nSiv07Th23dN24IqpgLqz9grq1s6WDgRgQAFqu2f2FTYmIvcU/mko\n9I69i1E8iSYIvfRmReOn3L2GlhQrADYbCYC+mMEAXJtTuJ44KP0JtGTFPP0+m4vb\nspuuebFeES8cVsk2RPuRUQJC6uSk0E78ZaxMWgZm6P/6bnRwDbn4OE3NrQbkvhvn\nKupR01MQ7HAZh5jVi73aVnY0wfxe4fDToef1bjiiZUJEwJ57oKhOmj5EYlTurX0m\nzraNkpDIWQNJnVlMgUEOclmrnL0uz3wkaqu8BoUkyaWAJS2f545amJNUBO23Mogp\ng9VgFeOyivM0xx5JZAN2LRkK5CrpKNpjXYtFzGkxKZxAAs4iyrUGDecJtfZJM48M\ntvgzbL4jqJu6rrOH27e3F74HyEmX+f1sIJMSnvanEiyYxIpdbvMc8+ULtGzpsdUd\n4hQ/yYKqEkecyKwjPEN4OlAI2LdokTxeYOszjJ7iBO1jE2D7e3hgzpjsGZmj1i+J\nzTUGUSAEgfd2w+/xfYzWttMysthrGa0MMwEeKYttuoZjIJ04IDB6JBQWNWxbfGpp\nXlNd5G2+xrGl2oaYzc4fAJRZoQZRWgX1Dy78cvRm8OIUGJucz0cZeBPiI3/Ny5/S\nXgFC/aC1TJBNvFC/60oOrerjzf5LVrx6O3zevs7LCrVVq0iL/xSSU+DnTxdczKPt\nKh9x1LMKUQK5cnMOdoWt78uUNmLkKiSkht43ozLcqvb3cxgRyoSlMP2lvk9YWx4=\n=gnXz\n-----END PGP MESSAGE-----
sops_pgp__list_0__map_fp=DC6910268E657FF70BA7EC289974494E76938DDC
sops_unencrypted_suffix=_unencrypted
sops_version=3.10.2
@@ -1,86 +0,0 @@
services:
pplessbroker:
image: docker.io/library/redis:8
restart: unless-stopped
volumes:
- redisdata:/data
pplessdb:
image: docker.io/library/postgres:16
restart: unless-stopped
volumes:
- pgdata:/var/lib/postgresql/data
env_file:
- .env
environment:
POSTGRES_DB: paperless
paperless-webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:2.20.15
restart: unless-stopped
networks:
- default
- proxy
depends_on:
- pplessdb
- pplessbroker
ports:
- "8000"
volumes:
- data:/usr/src/paperless/data
- media:/usr/src/paperless/media
- export:/usr/src/paperless/export
- consume:/usr/src/paperless/consume
labels:
- "traefik.enable=true"
- "traefik.http.routers.paperless-webserver.rule=Host(`paperless.lan`)"
env_file: .env
environment:
PAPERLESS_REDIS: redis://pplessbroker:6379
PAPERLESS_DBHOST: pplessdb
PAPERLESS_APPS: allauth.socialaccount.providers.openid_connect
PAPERLESS_ACCOUNT_DEFAULT_HTTP_PROTOCOL: http
volumes:
data:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/paperless/data'
media:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/paperless/media'
pgdata:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/paperless/db'
redisdata:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/paperless/redis'
export:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/paperless/export'
consume:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/paperless/consume'
networks:
proxy:
external: true
name: proxy
+1 -1
View File
@@ -1,6 +1,6 @@
services:
radicale:
image: tomsquest/docker-radicale:3.7.5.0
image: tomsquest/docker-radicale:3.7.6.0
container_name: radicale
ports:
- 5232
-18
View File
@@ -1,18 +0,0 @@
ME_CONFIG_MONGODB_ADMINUSERNAME=ENC[AES256_GCM,data:AHXIMA==,iv:trofFagJGNq5OyWDaN57vPpKwwG3SouiV5xLl5sJIBA=,tag:c1NUlmBouEb0Milri85QNw==,type:str]
ME_CONFIG_MONGODB_ADMINPASSWORD=ENC[AES256_GCM,data:8X6+SphUNus=,iv:zwofVw03pToXHR6weckniT/fymFYeHZw6lVmrGUsnLc=,tag:lEWtnnqpwamNsCnkStsRfQ==,type:str]
ME_CONFIG_MONGODB_URL=ENC[AES256_GCM,data:3xLFWhRYU/EfhRw+rOs9pOb+nzsbV9IvQydB4VGZGw/WLkQd,iv:T9T6ewB+05qzFDL7z2WESs6fIc9lTFdjVxy/71YzhXo=,tag:S3YsOokO4jzhJVWep/QTsQ==,type:str]
ME_CONFIG_BASICAUTH=ENC[AES256_GCM,data:FnUichsnpQ==,iv:Ayw1Vqg5rj6P79vtERX2hRCttnol/4aNUG5Y0OhFVTo=,tag:JkTxro0kyYJLr9gdkY8A1Q==,type:str]
MONGO_USER=ENC[AES256_GCM,data:2KFDcg==,iv:wdDxrQd07+hC5GEq1DS0DLVASiL9L4ds1V3TG1NA9EQ=,tag:gieiOLmOfLtUQjfjwZg6qQ==,type:str]
MONGO_PASS=ENC[AES256_GCM,data:W80YLzp8G50=,iv:eFts3fhrB9PGEfC69d8btt4ko3gcOGrFZUy95hx2rCE=,tag:+1JFEiclNnjei8+2I42j6w==,type:str]
MONGO_HOST=ENC[AES256_GCM,data:0RknYUM=,iv:8QyL4KHrSr9pv1kX+FD09N2ltVSZkEKqtFCS30ik1v0=,tag:bTXBMHqp5JU9VTD3soXEyQ==,type:str]
MONGO_INITDB_ROOT_USERNAME=ENC[AES256_GCM,data:G6wekw==,iv:AH5qqxXOeEBVI2mXXPPrC1X8X/Vq5MHZBWdfNRNeK1c=,tag:nMkWql/aVHi2FGnJ5NGFBQ==,type:str]
MONGO_INITDB_ROOT_PASSWORD=ENC[AES256_GCM,data:jzVSUjGSjOY=,iv:S/Ar0oYN2vSE7pK+/tfp9RyCThtDbk0gOUYDyzNYjVE=,tag:whWyBFHuXBcmF+WixjafOw==,type:str]
RIOT_API_KEY=ENC[AES256_GCM,data:EzqWk1Y73htAXaUJhzByV6Aru/hxUNjHGK90ac1NGaz92Cwk9YEdmrb9,iv:KorIppEflVX2aDC8K3ndRzK1q6scNjdQfl38p/8fLGM=,tag:Ei2zLoiGOlOX8ocrO2wNMw==,type:str]
CDRAGON_CACHE_DIR=ENC[AES256_GCM,data:uMogP1/K/pc=,iv:/0A8fs9HEuksSiKV1SZDoslHHGlJe+vFw0BQ5zQ9BBA=,tag:grwWPwMQarpmSAUIgKDZ5Q==,type:str]
sops_lastmodified=2026-04-30T18:20:37Z
sops_mac=ENC[AES256_GCM,data:7teYIGLLHBH8TJ/gr3lcbtfo4CVl0Gj2RWPSLgx4AyTvM+pZaSvUDaVUhWuprSCVqZcDWI2tNHUOHE4aYlJzyt9JfQrooKLPkKUq3WX3bucg3Rv5GpiP1tNHiPDE7UZCBp5bkHhYvwn+dPjhObEUdMUuwMBDA9JSpPlr3YQCg/E=,iv:6knBO6QNe33E2bJw5WZMzcDzeTW9mwgjQtftv0FZq8s=,tag:xuIKZl7szrUyX8/D9xxAmA==,type:str]
sops_pgp__list_0__map_created_at=2026-04-30T18:20:33Z
sops_pgp__list_0__map_enc=-----BEGIN PGP MESSAGE-----\n\nhQIMA7uy4qQr71wiARAAufkTVdCq2ARwMFuec9+0N1BzTo7WgGQhzKIJehe+uQ5I\nuPS5bafo5vrvxlCuxVmhup45CS3gm3X46hgHh/d3htaYzDnbyh/awbVGIhU9sa9T\n74i4jZAabzWjWAU8lAvxS6dJ6hf5U3MHOc1zYoCUfCJjgw+QRzR5PxZKFhpVklQU\nQJycdfRAl5oAqF7N6B7oCNTs7w1hbx2CJXBVGM8YoJySkThpXEY3dECxZ5nTSPmp\nXo3hmidO09uYsjWzcqynJHnh9RkMd1VAe6ULzhVIOv5KLXQLQV/paNAPdsxA5UmY\nE1imIFrqS25BVU9xbsGaPj6AHX6+Ux8bpO8TOVbpULe56Aq2c5GOjIZXb3p20K7N\nEk5rJ/K+8FxvytK3jDkhJI49wiDs9UDim02DSZmsWirIy/c02Ojy2d/Cxors1Lw/\nBCc4S6/ESH9u/LGlWs8WDqcDQqhHgeCvGOLAvOXs9eOCXNW2ROtNdfW808APbu1A\nzgYJwPtdfBhUv4KhZcEVMldWgX1OiYhcWMWYgJUXcfOwaRbzntZ/MczPNJ/a+57T\nPvH9GuTiwCXn0fOgcETTp9RPvXflL+4LPgh9drCOo4zwMvlqZs2+0Os2m8GDdDcL\nD45VMTsnNUXWuO7YUdtYX47bON2W6Z7NwzvkSr5odogzq1xw38SgRN7g3Jbl6+fS\nXAH/Rw8jWjpYztZ5HgDXisTxLEXqn5UNYKZBjzsLV5tE9GQp8ppck21igBiDCqoT\nsziZwFyRy/nKq076lZlRgSFr0pm4168u7Vn5x1TLQBHl+i0eKficgUQpwCFx\n=XUsx\n-----END PGP MESSAGE-----
sops_pgp__list_0__map_fp=DC6910268E657FF70BA7EC289974494E76938DDC
sops_unencrypted_suffix=_unencrypted
sops_version=3.10.2
@@ -1,57 +0,0 @@
services:
mongo:
hostname: mongo
image: mongo:8.2.11
restart: always
user: root:root
command: mongod --wiredTigerCacheSizeGB 2
deploy:
resources:
limits:
memory: 6G
reservations:
memory: 3G
volumes:
- bpmongo_data:/data/db:Z
- bpmongo_config:/data/configdb:Z
env_file: .env
match_collector:
image: git.vhaudiquet.fr/vhaudiquet/lolstats-match_collector:d878af6d1a5cb633175515259e27a12c76c4609b
build: ./match_collector
volumes:
- bpcdragon_cache:/cdragon
restart: "no"
deploy:
restart_policy:
condition: any
delay: '0'
window: 20s
env_file: .env
frontend:
image: git.vhaudiquet.fr/vhaudiquet/lolstats-frontend:d878af6d1a5cb633175515259e27a12c76c4609b
build: ./frontend
restart: always
volumes:
- bpcdragon_cache:/cdragon
networks:
- default
- proxy
ports:
- "3000"
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host(`buildpath.win`)"
- "traefik.http.services.frontend.loadbalancer.server.port=3000"
env_file: .env
volumes:
bpmongo_data:
bpmongo_config:
bpcdragon_cache:
networks:
proxy:
external: true
name: proxy
@@ -1,20 +0,0 @@
services:
semeryfr:
container_name: semeryfr
image: git.vhaudiquet.fr/semerys/semery.fr:latest
networks:
- default
- proxy
ports:
- 80
labels:
- "traefik.enable=true"
- "traefik.http.routers.semeryfr.rule=Host(`semery.fr`)"
environment:
- NGINX_HOST=semery.fr
- NGINX_PORT=80
networks:
proxy:
external: true
name: proxy
-9
View File
@@ -1,9 +0,0 @@
COUCHDB_USER=ENC[AES256_GCM,data:wMQJhlZFW30=,iv:OG3S+hZppJdP/PjDINGEEQZD8Qf4520mfzsyw+/QAx4=,tag:i1og4xc0N4Hf4UE0GKPtbg==,type:str]
COUCHDB_PASSWORD=ENC[AES256_GCM,data:eud7WTnlZEzzBGciiwM=,iv:g8RCLIcO1ZxUn/SROHV/stl+whdzICMSX0jVLKXbTns=,tag:6gReHLd+97dqUoAlYL780Q==,type:str]
sops_lastmodified=2025-11-21T23:00:14Z
sops_mac=ENC[AES256_GCM,data:O+jtG9ojK8Md6NSaqfyykVdVG84Kafz3zoKb5hbj2alzvJgaLuzVu3ihM75ZU3/meu/nPl9wCc+J4RKepE7VTp5Il3HK09MVHYRHQKVlbyiZ5cTbU74JJuSL3PF1GiU7p/U5Ht9+Z9c8sDrqSN2IPSIfDr8zCdTwKZF71nYOqew=,iv:n33XCpiwVOGnrJyH3Q967u5uMknRfAwx9esJuOLl+9g=,tag:aKMwsOKXPRUaa+9/ZmnpfQ==,type:str]
sops_pgp__list_0__map_created_at=2025-11-21T23:00:14Z
sops_pgp__list_0__map_enc=-----BEGIN PGP MESSAGE-----\n\nhQIMA7uy4qQr71wiAQ/+Mt0/uXHnndDK7FLEM8rhWmX0NpJWtgBY3BBXMX7I2Ilg\n6hNZJxISOqcoJCPqb8gZ9pUulcGC5F8owoo/wUILyI/mK3kAzGCP+lfp6Dk03k+P\nwB6BcQTC8NJsApoygdm50h/jtnlK2KUCICFKXUxf527KLWdo8g0wnMIOBe8mBvVC\n8bI/1BOcJZeB4IhmFVrgED+Ct1dTTiuyLscJirCqHD0VTD4eavd6DVpN89m/mtY/\nhTRVT3omuV8JITLeWPdVVWyQznrq3/x8OGAs8L2c24gad5AsTLCr2WS20CvXP1uL\nUoLH9EH0IDvo36DbiMO+p3LdyEvlRe1PW+0dvOpO64CLNoH4szYDJ/dG+UUa3xWo\nRpOIT1F0puXRz3UHZv/IkAFah4Zzi8TxdZDD7Riz5pzMWqzWwdQHQUS1ZWibm1ve\nfC7strrMNybh+QUfMTXhTaW4OoRkY+rGo3d2x3eUjZpaqlKOBWaScZ0c1I7DY/CP\no4QoCoga1RNePXp/WWvWAbQf0w+hAxrsb6U3/ECKtcd4gYGE3shvH0MS6T4oAaIx\nB9ldqRbKIcEUYU7MWq3Wqt8c1k/MtJZh1q3YuZwy8C3U8cHiS5iqDWzAnjIkUwbC\nJpYVaIOvI0qOjE7v6Fc06ZnTBoh/DoTX4XfdIY39GMo3ZageBV0r7Fi0HUzbFxvS\nXAHnsiZZXFB/TJAVEZKDO0Yic3DhlYLL/glOJF0kNgUOoYGvTFaSuNhwhv4tqOrw\nSv7FLH+79LSrM/bPug3Zq9Ec7p/TSnsJ4amu6p7VSmSHRBGV0uZDxt5wkYnG\n=yY4C\n-----END PGP MESSAGE-----
sops_pgp__list_0__map_fp=DC6910268E657FF70BA7EC289974494E76938DDC
sops_unencrypted_suffix=_unencrypted
sops_version=3.10.2
@@ -1,44 +0,0 @@
services:
couchdb:
image: couchdb:3.5.2
container_name: couchdb
env_file: .env
volumes:
- couchdb-data:/opt/couchdb/data
- couchdb-etc:/opt/couchdb/etc/local.d
networks:
- default
- proxy
ports:
- 5984
labels:
- "traefik.enable=true"
- "traefik.http.routers.couchdb.rule=Host(`obsidian-livesync.lan`)"
- "traefik.http.services.couchdb.loadbalancer.server.port=5984"
- "traefik.http.routers.obsidian-livesync.middlewares=obsidiancors"
- "traefik.http.middlewares.obsidiancors.headers.accesscontrolallowmethods=GET,PUT,POST,HEAD,DELETE"
- "traefik.http.middlewares.obsidiancors.headers.accesscontrolallowheaders=accept,authorization,content-type,origin,referer"
- "traefik.http.middlewares.obsidiancors.headers.accesscontrolalloworiginlist=app://obsidian.md,capacitor://localhost,http://localhost"
- "traefik.http.middlewares.obsidiancors.headers.accesscontrolmaxage=3600"
- "traefik.http.middlewares.obsidiancors.headers.addvaryheader=true"
- "traefik.http.middlewares.obsidiancors.headers.accessControlAllowCredentials=true"
restart: unless-stopped
networks:
proxy:
external: true
name: proxy
volumes:
couchdb-data:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/obsidian-livesync/data'
couchdb-etc:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/obsidian-livesync/etc'
-58
View File
@@ -1,58 +0,0 @@
#!/bin/bash
# Create .github directory if needed
if [ ! -d .github ]; then
mkdir -p .github
fi
tmpfile=$(mktemp)
# Make sure to cleanup our temp file on any kind of exit
trap 'rm -f "$tmpfile"' EXIT
# dependabot.yml docker header
cat > "$tmpfile" <<'YAML'
version: 2
updates:
- package-ecosystem: "docker-compose"
open-pull-requests-limit: 15
schedule:
interval: weekly
directories:
YAML
# Find and sort all docker-compose.yml directories
find docker -name 'docker-compose.yml' -print0 \
| xargs -0 -n1 dirname \
| sed 's|^\./||' \
| sort \
| while read -r dir; do
echo " - \"/$dir\"" >> "$tmpfile"
done
# dependabot.yml helm header
cat >> "$tmpfile" <<'YAML'
- package-ecosystem: "helm"
open-pull-requests-limit: 15
schedule:
interval: weekly
directories:
YAML
# Find and sort all release.yaml directories
find kubernetes -name 'release.yaml' -print0 \
| xargs -0 -n1 dirname \
| sed 's|^\./||' \
| sort \
| while read -r dir; do
echo " - \"/$dir\"" >> "$tmpfile"
done
# Overwrite file on change
if ! [ -f .github/dependabot.yml ] || ! cmp -s "$tmpfile" .github/dependabot.yml; then
mv "$tmpfile" .github/dependabot.yml
echo "Updated .github/dependabot.yml!"
git add ".github/dependabot.yml"
else
echo "No changes to .github/dependabot.yml."
fi
+3
View File
@@ -0,0 +1,3 @@
clusterconfig/
manifests/cilium.yaml
talconfig.json
+73
View File
@@ -0,0 +1,73 @@
ipam:
mode: kubernetes
kubeProxyReplacement: true
securityContext:
capabilities:
ciliumAgent:
- CHOWN
- KILL
- NET_ADMIN
- NET_RAW
- IPC_LOCK
- SYS_ADMIN
- SYS_RESOURCE
- DAC_OVERRIDE
- FOWNER
- SETGID
- SETUID
cleanCiliumState:
- NET_ADMIN
- SYS_ADMIN
- SYS_RESOURCE
cgroup:
autoMount:
enabled: false
hostRoot: /sys/fs/cgroup
k8sServiceHost: localhost
k8sServicePort: 7445
etcd:
clusterDomain: cluster.local
l2announcements:
enabled: true
externalIPs:
enabled: true
# Single-node cluster: the operator defaults to 2 replicas, but both
# bind the same host ports, so the second replica can never schedule ("node(s)
# didn't have free ports for the requested pod ports") and sits Pending forever.
operator:
replicas: 1
ingressController:
enabled: false
loadbalancerMode: shared
default: false
service:
externalTrafficPolicy: Cluster
envoy:
xffNumTrustedHopsL7PolicyIngress: 1
sops:
lastmodified: "2026-08-26T19:28:03Z"
mac: ENC[AES256_GCM,data:2aioHoSXw5UOFKj5z5PJmtPC4rGl9DYY0gWgevHIxXbKdjLrTfyyoRfBPCl3+NPWAZllieMr4VKsGy53YUqq5xFgRg0BaqG+gqMFX/YjHPqhF0/WT0YI3GdTWhl/YY0wma+CEN0kE5SsljpKh7vBgY8l2WlFhpMdlbAKEeyONRs=,iv:EY7Vdlj/VpqY34KmrVUSQutLiD8DEAB0OqIXnN40ERA=,tag:XOZNdUoeWAV4cD111ciBzw==,type:str]
pgp:
- created_at: "2026-08-26T19:28:02Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiARAAp9OoebtSeHrGp/3bQz93JMbp78C9xnHuumz7exhd9Ky6
zrJUm+bL8tNMWTL72Q+GUTCo7lEVltYciXZZVYSvD3Uee8stAeOdhCrY6jsH2IxZ
yCVZktlnsAbsPDwmEt+/HRoiqwy4hkbIx99J5W18cJD4eSw8MlJYjDVfSh2UWGIi
rd+7ameKbHR8PCduWu1T5SY0EFWaVr3WJDW//lD/FUT1KXJDrB0ExVtsuL0l8GgW
ue+noYGAn5l9PRgjgqTLSbHoQQDaMO9KalR+Gz6jmYpUdkJEuCT1amQiH+dE8i85
Rs0KXHWLnW59xY4pqdNzJzOysKEsM/oPes36JFvuIOIpB0KDSK/hcFKkYogk96Rw
VZ131NNOYMbKunORjmKfei7SWE975zzB/OFCWRDkAwGceqm+hdWaKhKV+rZlBSHR
ClbWTZt9+EEI3Er1f/J8qsfhvxJswWTDIOs7+I7YgbFgPAHMh/kcNU+xJJmWtDOq
Fq3uBi/oowR6mwTvUwswFFkuaDePcjHrvWaQLTzOw/wv5JU59nUTstSr+zMQzm4Y
ZTjKoz62hz5gntyjRFG58w7tyLR8D48CFPA6BFGLBkBpsykhyc42F4woCUqEg6YJ
5QBuCFsBXxjSeRHTLRyaWdI5BmppmLZ5axzdMVt0X+rXy/7LhGPY40bGuWBbsgPS
XgEL/HGgfFafvsfgJU5x71E4n+Ak7EPLCxin1uTW/CM0cJszT1/zdwIdQ+T5JDiY
JlZZTK9C49sF3OngtmRTtf1JesnOYdfhdOVCpDO9EgcUiF769X0JPhdFNemkOeY=
=8NLP
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*PASS|.*SOCIALACCOUNT_PROVIDERS|.*\.ya?ml)$
mac_only_encrypted: true
version: 3.10.2
@@ -1,4 +1,18 @@
instance:
apiVersion: fluxcd.controlplane.io/v1
kind: FluxInstance
metadata:
name: flux
namespace: flux-system
spec:
distribution:
version: "2.x"
registry: ghcr.io/fluxcd
sync:
name: homeprod
kind: GitRepository
url: https://github.com/vhaudiquet/homeprod
path: kubernetes/
ref: refs/heads/main
components:
- source-controller
- kustomize-controller
@@ -31,4 +45,4 @@ instance:
secretRef:
name: flux-sops
target:
kind: Kustomization
kind: Kustomization
+55
View File
@@ -0,0 +1,55 @@
#!/bin/sh
# Reconcile Talos cluster infrastructure
# Environment needed:
# - SOPS_KEY: sops private key
set -euo pipefail
if [ -z "${SOPS_KEY:-}" ]; then
echo "Error: SOPS_KEY environment variable is not set" >&2
exit 1
fi
# Render the Cilium chart for manifest deployment
helm repo add cilium https://helm.cilium.io/
helm repo update
helm template cilium cilium/cilium \
--version 1.20.1 \
--namespace kube-system \
-f manifests/cilium/values.yaml \
> manifests/cilium.yaml
# Escape shell variables that must be resolved at container runtime, not by talhelper.
# talhelper expands ${VAR} statically; prefixing with $$ (i.e. $${VAR}) tells it to
# preserve the literal ${VAR} in the output so bash can expand it inside the container.
sed -i 's/\${BIN_PATH}/$${BIN_PATH}/g' manifests/cilium.yaml
# Generate Talos machine config
talhelper genconfig
# Apply generated machine config to the nodes, without reboot.
# If it fails, it is safer for reconcile to be done manually:
# the reboot is needed and that might disrupt the node
talhelper gencommand apply --extra-flags="-m no-reboot" | bash
# Obtain kubeconfig and export it for kubectl
talosctl --talosconfig ./clusterconfig/talosconfig kubeconfig -f ./clusterconfig/kubeconfig
export KUBECONFIG=./clusterconfig/kubeconfig
# Show nodes
kubectl get nodes
# Create Flux namespace if it does not already exists
kubectl get ns "flux-system" || kubectl create ns "flux-system"
# Create SOPS secret in the cluster
kubectl create secret generic flux-sops \
--namespace "flux-system" \
--from-literal=sops.asc="$SOPS_KEY" \
--dry-run=client -o yaml | kubectl apply -f -
# Install the Flux operator if not installed already
kubectl get deployment -n flux-system flux-operator || helm install flux-operator oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator \
--namespace "flux-system" \
--wait
kubectl apply -f manifests/flux-system/flux-instance.yaml
+46
View File
@@ -0,0 +1,46 @@
---
clusterName: kube
talosVersion: v1.13.8
kubernetesVersion: v1.36.0
endpoint: https://10.2.2.138:6443
domain: cluster.local
allowSchedulingOnMasters: true
clusterPodNets:
- 10.244.0.0/16
clusterSvcNets:
- 10.96.0.0/12
cniConfig:
name: none
nodes:
- hostname: p330
ipAddress: 10.2.2.138
filenameTmpl: "{{.ClusterName}}-{{.Hostname}}.yaml"
extensionServices: []
controlPlane: true
machineSpec:
mode: metal
arch: amd64
secureboot: false
useUKI: false
bootMethod: iso
installDisk: /dev/nvme0n1
schematic:
customization:
systemExtensions:
officialExtensions:
- siderolabs/intel-ucode
- siderolabs/iscsi-tools
kernelModules:
- name: iscsi_tcp
- name: libiscsi
- name: scsi_transport_iscsi
- name: ext4
- name: ixgbe
parameters:
- allow_unsupported_sfp=1
networkInterfaces:
- interface: eno1
dhcp: true
inlineManifests:
- name: cilium
contents: "@./manifests/cilium.yaml"
File diff suppressed because one or more lines are too long
-195
View File
@@ -1,195 +0,0 @@
# Talos node for the P330 — joins the r740 "kube" cluster.
terraform {
required_providers {
talos = {
source = "siderolabs/talos"
version = "0.9.0"
}
null = {
source = "hashicorp/null"
version = "3.2.3"
}
}
}
# Read the r740 kube module state to reuse the cluster secrets & endpoint.
# The r740 module exposes: client_configuration, machine_secrets, cluster_name,
# cluster_endpoint, kube_host.
data "terraform_remote_state" "r740_kube" {
backend = var.r740_backend
config = var.r740_backend == "local" ? {
path = "${var.r740_state_path}/terraform.tfstate"
} : var.r740_backend_config
}
locals {
cluster_name = data.terraform_remote_state.r740_kube.outputs.cluster_name
cluster_endpoint = data.terraform_remote_state.r740_kube.outputs.cluster_endpoint
machine_secrets = data.terraform_remote_state.r740_kube.outputs.machine_secrets
client_config = data.terraform_remote_state.r740_kube.outputs.client_configuration
# kubeconfig produced by the r740 kube module — used to wait for the node and
# apply labels/taints. There is no in-tree kubernetes provider here on
# purpose: managing a `kubernetes_node` resource conflicts with the node
# object that kubelet itself creates, so we use a null_resource with kubectl
# to wait + label + taint idempotently.
kubeconfig_path = "${var.r740_state_path}/kubeconfig"
# Network config: static if node_subnet is provided, otherwise Talos DHCPs.
static_network = var.node_subnet == null ? {} : {
interfaces = [{
interface = var.network_interface
addresses = [var.node_subnet]
routes = var.node_gateway == null ? [] : [{ gateway = var.node_gateway }]
}]
}
network_patch = {
nameservers = var.nameservers
}
network_patch_merged = merge(local.network_patch, local.static_network)
machine_patch = {
install = {
image = var.installer_image
disk = var.install_disk
}
network = merge(local.network_patch_merged, {
# Pin the Kubernetes node name. Talos otherwise auto-generates a hostname
# (e.g. "talos-8ec-vd1"), so the node registers with that random name
# instead of var.p330_node_name — and our label/taint null_resource waits
# for the wrong node. Setting machine.network.hostname fixes the node name.
hostname = var.p330_node_name
})
# Kernel modules required by Longhorn (iSCSI + ext4) — must match the
# control-plane nodes so Longhorn can schedule replicas on the failover node.
kernel = {
modules = [
{ name = "iscsi_tcp" },
{ name = "libiscsi" },
{ name = "scsi_transport_iscsi" },
{ name = "ext4" },
]
}
sysctls = {
"fs.inotify.max_user_instances" = "1024"
"fs.inotify.max_user_watches" = "1048576"
}
kubelet = {
# Keep the failover node from accumulating non-essential DaemonSet pods
# via the regular scheduler; the taint does the heavy lifting, this is
# belt-and-braces.
extraArgs = {
"register-with-taints" = "${var.failover_taint_key}=${var.failover_taint_value}:${var.failover_taint_effect}"
}
}
}
}
# Control-plane machine configuration. machine_type = "controlplane" makes
# Talos generate a join config that runs the apiserver/controller-manager/
# scheduler AND joins the existing etcd cluster as a new member (the cluster
# was already bootstrapped by the r740 module's talos_machine_bootstrap).
data "talos_machine_configuration" "p330" {
cluster_name = local.cluster_name
machine_type = "controlplane"
cluster_endpoint = local.cluster_endpoint
machine_secrets = local.machine_secrets
config_patches = [
yamlencode({
machine = local.machine_patch
})
]
}
# Rendered config is written to disk so it can also be applied manually with
# `talosctl apply-config --nodes <p330_host> --file p330.yaml` if needed.
resource "local_file" "p330_machine_config" {
filename = "${path.module}/p330.yaml"
content = data.talos_machine_configuration.p330.machine_configuration
}
# Apply the machine config to the running (maintenance-mode) node over the
# Talos API. Because the config patch contains a `machine.install` block, when
# Talos receives this config on a node booted from the USB (maintenance) image
# it installs itself to install.disk and reboots into the installed system.
# For a controlplane node it then joins the existing etcd cluster as a new
# member and runs the control-plane components; for a worker it just registers
# via kubelet.
resource "talos_machine_configuration_apply" "p330" {
client_configuration = local.client_config
machine_configuration_input = data.talos_machine_configuration.p330.machine_configuration
node = var.p330_host
depends_on = [local_file.p330_machine_config]
}
# Emit a talosconfig scoped to this node for ad-hoc `talosctl` use.
data "talos_client_configuration" "p330" {
cluster_name = local.cluster_name
client_configuration = local.client_config
nodes = [var.p330_host]
}
resource "local_file" "talosconfig" {
content = data.talos_client_configuration.p330.talos_config
filename = "${path.module}/talosconfig"
depends_on = [data.talos_client_configuration.p330]
}
# Wait for the node to register with Kubernetes (kubelet creates the Node
# object after Talos installs and reboots), then label it and (re)apply the
# failover taint. This is idempotent: kubectl exits 0 if the label/taint already
# exists. The taint is also set via kubelet `register-with-taints`, so this
# null_resource is a safety net for manual edits / drift.
resource "null_resource" "p330_node_label_and_taint" {
triggers = {
node = var.p330_node_name
key = var.failover_taint_key
value = var.failover_taint_value
effect = var.failover_taint_effect
kubeconfig = local.kubeconfig_path
}
provisioner "local-exec" {
# Wait for the node to show up, then label + taint. The wait loop is bounded
# by kubectl --timeout; tune it via TF_LOG / re-run if the node is slow to
# join (a controlplane node must first complete the etcd join handshake).
command = <<-EOT
set -euo pipefail
KUBECONFIG="${local.kubeconfig_path}"
export KUBECONFIG
NODE="${var.p330_node_name}"
echo "Waiting for node $NODE to be registered (kubelet creates the Node object once Talos has installed, rebooted and joined etcd)..."
# kubectl wait --for=condition=Ready fails instantly with NotFound if the
# node object doesn't exist yet, so poll for existence first.
# /bin/sh (dash) has no $SECONDS, so count iterations with a bounded loop.
tries=240 # 240 * 5s = 20 minutes max
until kubectl get node "$NODE" >/dev/null 2>&1; do
tries=$((tries - 1))
if [ "$tries" -le 0 ]; then
echo "Timed out waiting for node $NODE to register." >&2
exit 1
fi
sleep 5
done
echo "Node $NODE registered. Waiting for it to become Ready..."
# Now wait for Ready (a controlplane node needs etcd joined + apiserver up).
kubectl wait --for=condition=Ready "node/$NODE" --timeout=20m || \
kubectl wait --for=jsonpath='{.status.conditions[?(@.reason=="KubeletReady")].status}'=True "node/$NODE" --timeout=20m
# Failover marker + taint (applied to both controlplane and worker nodes).
kubectl label --overwrite node "$NODE" homeprod.io/failover=true
# Apply the taint idempotently (kubectl taint --overwrite is a no-op if it exists).
kubectl taint --overwrite node "$NODE" \
"${var.failover_taint_key}=${var.failover_taint_value}:${var.failover_taint_effect}"
echo "Node $NODE ready, labeled and tainted for failover-only scheduling."
EOT
}
depends_on = [talos_machine_configuration_apply.p330]
}
-118
View File
@@ -1,118 +0,0 @@
# Variables for the P330 Talos worker node that joins the r740 cluster.
variable "p330_host" {
description = "Reachable IP/hostname of the P330 Talos node (for Talos API access)."
type = string
}
variable "p330_node_name" {
description = "Kubernetes/Talos node name for the P330 (e.g. p330)."
type = string
default = "p330"
}
variable "r740_state_path" {
description = <<EOT
Path to the Terraform state of the r740 kube module, used by terraform_remote_state
to read the cluster secrets and endpoint so this node can join the existing cluster.
Path is resolved by terraform_remote_state relative to the working directory where
terraform runs (this module dir). The default points two levels up to the repo
root and back down to the r740 kube module.
EOT
type = string
default = "../../r740/kube"
}
variable "r740_backend" {
description = <<EOT
Terraform backend type used by the r740 kube module.
Set to "local" (default) when r740 uses a local tfstate file in its own directory,
or the matching remote backend name ("s3", "remote", ...) if the r740 module uses
a configured backend.
EOT
type = string
default = "local"
}
variable "r740_backend_config" {
description = <<EOT
Backend configuration map passed to terraform_remote_state when r740_backend is
not "local". For a local backend this is ignored.
EOT
type = map(string)
default = {}
}
variable "installer_image" {
description = <<EOT
Talos installer image to use on the P330 (bare metal).
Must be a **metal** Image Factory build that includes ixgbe.allow_unsupported_sfp=1
in the kernel command line (sd-boot/UKI ignores machine.install.extraKernelArgs, so
the param must be baked into the image). The default is a custom factory build
(a18165114...).
EOT
type = string
default = "factory.talos.dev/installer/a18165114f80c28601d05bc4ff1f6ea6d6b214882c5b9af7928aaf4d09741beb:v1.13.6"
}
variable "install_disk" {
description = "Block device path to install Talos on (e.g. /dev/sda, /dev/nvme0n1)."
type = string
default = "/dev/nvme0n1"
}
variable "node_subnet" {
description = <<EOT
Static IPv4 address in CIDR notation for the P330 node (e.g. 10.1.2.132/24).
Set to null to use DHCP. A static address is recommended for a failover node so
DNS/affinity rules stay stable.
EOT
type = string
default = "10.1.2.132/24"
}
variable "node_gateway" {
description = "IPv4 gateway for the P330 node. Ignored when node_subnet is null."
type = string
default = "10.1.2.1"
}
variable "network_interface" {
description = <<EOT
Primary network interface name on the P330. Defaults to enp3s0f1 (the 10G Intel
X520 NIC), which must be on the same L2/subnet as the r740 control plane so etcd
peer traffic (TLS-verified against the r740's etcd cert SANs) doesn't cross a
router. eno1 (1G) is left unconfigured.
EOT
type = string
default = "enp3s0f1"
}
variable "nameservers" {
description = "DNS nameservers configured on the node (must work independently of kube)."
type = list(string)
default = ["10.1.2.148", "1.1.1.1"]
}
variable "failover_taint_key" {
description = "Taint key applied to the node to reserve it for failover workloads."
type = string
default = "dedicated"
}
variable "failover_taint_value" {
description = "Taint value applied to the node."
type = string
default = "failover"
}
variable "failover_taint_effect" {
description = "Taint effect applied to the node (NoSchedule / NoExecute)."
type = string
default = "NoSchedule"
validation {
condition = contains(["NoSchedule", "PreferNoSchedule", "NoExecute"], var.failover_taint_effect)
error_message = "failover_taint_effect must be NoSchedule, PreferNoSchedule or NoExecute."
}
}
-365
View File
@@ -1,365 +0,0 @@
terraform {
required_providers {
talos = {
source = "siderolabs/talos"
version = "0.9.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "2.36.0"
}
helm = {
source = "hashicorp/helm"
version = "2.17.0"
}
}
}
# Talos configuration
provider "talos" {}
# Kubernetes configuration
provider "kubernetes" {
config_path = "${path.module}/kubeconfig"
}
# Helm configuration
provider "helm" {
kubernetes {
config_path = "${path.module}/kubeconfig"
}
}
resource "talos_machine_secrets" "kube" {}
data "talos_machine_configuration" "kube" {
cluster_name = "kube-${var.physical_hostname}"
machine_type = "controlplane"
cluster_endpoint = "https://${var.kube_host}:6443"
machine_secrets = talos_machine_secrets.kube.machine_secrets
config_patches = [
yamlencode({
machine = {
install = {
# Image Factory image with iSCSI extension for Longhorn.
# Generated at https://factory.talos.dev — siderolabs/iscsi-tools + qemu-guest-agent
image = "factory.talos.dev/installer/dc7b152cb3ea99b821fcb7340ce7168313ce393d663740b791c36f6e95fc8586:v1.13.6"
}
network = {
nameservers = [
# We need a set of nameservers that can work independently of kube
# to bootstrap.
"10.1.2.148",
"1.1.1.1"
]
}
certSANs = [
"${var.kube_host}", "${var.kube_hostname}"
]
# Kernel modules required by Longhorn (iSCSI + ext4)
kernel = {
modules = [
{
name = "iscsi_tcp"
},
{
name = "libiscsi"
},
{
name = "scsi_transport_iscsi"
},
{
name = "ext4"
},
]
}
# Sysctls for Longhorn
sysctls = {
"fs.inotify.max_user_instances" = "1024"
"fs.inotify.max_user_watches" = "1048576"
}
}
cluster = {
clusterName = "kube-${var.physical_hostname}"
allowSchedulingOnControlPlanes = true
apiServer = {
certSANs = [
"${var.kube_host}", "${var.kube_hostname}"
]
}
network = {
dnsDomain = "cluster.local"
cni = {
name: "none"
}
}
proxy = {
disabled = true
}
}
})
]
}
data "talos_client_configuration" "kube" {
cluster_name = "kube-${var.physical_hostname}"
client_configuration = talos_machine_secrets.kube.client_configuration
nodes = ["${var.kube_host}"]
}
resource "talos_machine_configuration_apply" "kube" {
client_configuration = talos_machine_secrets.kube.client_configuration
machine_configuration_input = data.talos_machine_configuration.kube.machine_configuration
node = var.kube_host
depends_on = [ talos_machine_secrets.kube ]
}
resource "talos_machine_bootstrap" "kube" {
node = var.kube_host
client_configuration = talos_machine_secrets.kube.client_configuration
depends_on = [ talos_machine_configuration_apply.kube, talos_machine_secrets.kube ]
}
resource "talos_cluster_kubeconfig" "kube" {
node = var.kube_host
depends_on = [ talos_machine_bootstrap.kube ]
client_configuration = talos_machine_secrets.kube.client_configuration
}
output "kubeconfig" {
sensitive = true
value = talos_cluster_kubeconfig.kube.kubeconfig_raw
}
output "client_configuration" {
description = "Talos client configuration (sensitive) used to manage nodes."
sensitive = true
value = talos_machine_secrets.kube.client_configuration
}
output "machine_secrets" {
description = "Talos machine secrets (sensitive) used to generate node configs."
sensitive = true
value = talos_machine_secrets.kube.machine_secrets
}
output "cluster_name" {
description = "Name of the Talos cluster the worker joins."
value = "kube-${var.physical_hostname}"
}
output "cluster_endpoint" {
description = "Endpoint (host:port) of the Talos/Kubernetes API on the cluster."
value = "https://${var.kube_host}:6443"
}
output "kube_host" {
description = "Reachable IP/hostname of the control-plane node."
value = var.kube_host
}
resource "local_file" "kubeconfig" {
content = "${talos_cluster_kubeconfig.kube.kubeconfig_raw}"
filename = "${path.module}/kubeconfig"
depends_on = [ talos_cluster_kubeconfig.kube ]
}
data "talos_client_configuration" "talosconfig" {
cluster_name = "kube-${var.physical_hostname}"
client_configuration = talos_machine_secrets.kube.client_configuration
nodes = [var.kube_host]
}
resource "local_file" "talosconfig" {
content = "${data.talos_client_configuration.talosconfig.talos_config}"
filename = "${path.module}/talosconfig"
depends_on = [ data.talos_client_configuration.talosconfig ]
}
# TODO : Wait for talos_cluster_kubeconfig...
resource "helm_release" "cilium" {
name = "cilium"
namespace = "kube-system"
repository = "https://helm.cilium.io/"
chart = "cilium"
wait = false
depends_on = [ local_file.kubeconfig, talos_cluster_kubeconfig.kube ]
set {
name = "ipam.mode"
value = "kubernetes"
}
set {
name = "kubeProxyReplacement"
value = true
}
set {
name = "securityContext.capabilities.ciliumAgent"
value = "{CHOWN,KILL,NET_ADMIN,NET_RAW,IPC_LOCK,SYS_ADMIN,SYS_RESOURCE,DAC_OVERRIDE,FOWNER,SETGID,SETUID}"
}
set {
name = "securityContext.capabilities.cleanCiliumState"
value = "{NET_ADMIN,SYS_ADMIN,SYS_RESOURCE}"
}
set {
name = "cgroup.autoMount.enabled"
value = false
}
set {
name = "cgroup.hostRoot"
value = "/sys/fs/cgroup"
}
set {
name = "k8sServiceHost"
value = "localhost"
}
set {
name = "k8sServicePort"
value = 7445
}
set {
name = "etcd.clusterDomain"
value = "cluster.local"
}
set {
name = "hubble.relay.enabled"
value = true
}
# Enable hubble ui
set {
name = "hubble.ui.enabled"
value = true
}
# Gateway API support
set {
name = "gatewayAPI.enabled"
value = true
}
set {
name = "gatewayAPI.enableAlpn"
value = true
}
set {
name = "gatewayAPI.enableAppProtocol"
value = true
}
# Gateway API trusted hops : for reverse proxy
set {
name = "gatewayAPI.xffNumTrustedHops"
value = 1
}
# Single-node cluster, so 1 operator only
set {
name = "operator.replicas"
value = 1
}
# L2 announcements
set {
name = "l2announcements.enabled"
value = true
}
set {
name = "externalIPs.enabled"
value = true
}
# Disable ingress controller (traefik will be used for now)
set {
name = "ingressController.enabled"
value = false
}
set {
name = "ingressController.loadbalancerMode"
value = "shared"
}
# Ingress controller for external : behind reverse proxy, trust 1 hop
set {
name = "envoy.xffNumTrustedHopsL7PolicyIngress"
value = 1
}
# Set cilium as default ingress controller
set {
name = "ingressController.default"
value = true
}
set {
name = "ingressController.service.externalTrafficPolicy"
value = "Local"
}
}
resource "kubernetes_namespace" "flux-system" {
metadata {
name = "flux-system"
}
lifecycle {
ignore_changes = [ metadata[0].annotations, metadata[0].labels ]
}
depends_on = [ talos_cluster_kubeconfig.kube, local_file.kubeconfig, helm_release.cilium ]
}
resource "kubernetes_secret" "flux-sops" {
metadata {
name = "flux-sops"
namespace = "flux-system"
}
type = "generic"
data = {
"sops.asc"=var.sops_private_key
}
depends_on = [ kubernetes_namespace.flux-system ]
}
resource "helm_release" "flux-operator" {
name = "flux-operator"
namespace = "flux-system"
repository = "oci://ghcr.io/controlplaneio-fluxcd/charts"
chart = "flux-operator"
wait = true
depends_on = [ kubernetes_secret.flux-sops ]
}
resource "helm_release" "flux-instance" {
name = "flux"
namespace = "flux-system"
repository = "oci://ghcr.io/controlplaneio-fluxcd/charts"
chart = "flux-instance"
values = [
file("values/components.yaml")
]
set {
name = "instance.distribution.version"
value = "2.x"
}
set {
name = "instance.distribution.registry"
value = "ghcr.io/fluxcd"
}
set {
name = "instance.sync.name"
value = "homeprod"
}
set {
name = "instance.sync.kind"
value = "GitRepository"
}
set {
name = "instance.sync.url"
value = "https://github.com/vhaudiquet/homeprod"
}
set {
name = "instance.sync.path"
value = "kubernetes/"
}
set {
name = "instance.sync.ref"
value = "refs/heads/main"
}
depends_on = [ helm_release.flux-operator ]
}
-16
View File
@@ -1,16 +0,0 @@
variable "sops_private_key" {
description = "Private SOPS GPG key for flux/kubernetes to decrypt secrets"
type = string
}
variable "kube_hostname" {
description = "Kubernetes cluster hostname"
type = string
}
variable "kube_host" {
description = "Kubernetes cluster host"
type = string
}
variable "physical_hostname" {
description = "Host name of the physical host for the kubernetes VM"
type = string
}
-1
View File
@@ -29,7 +29,6 @@ resource "proxmox_virtual_environment_vm" "kube" {
memory {
dedicated = 32768
floating = 22222
}
boot_order = ["scsi0", "ide0"]
-214
View File
@@ -1,214 +0,0 @@
# Talos control-plane node for the Raspberry Pi 4 — joins the r740 "kube" cluster
# as a third etcd member to restore quorum (2-of-3 majority). Unlike the p330
# failover node, this node is tainted "quorum" so no user workloads are ever
# scheduled on it; only essential DaemonSets (Cilium, etc.) that tolerate the
# taint land here for cluster networking.
#
# Secret handling: the cluster machine secrets are provided via
# var.machine_secrets_file (a local, gitignored JSON file in the provider's
# machine_secrets format). They are consumed by EPHEMERAL resources and
# WRITE-ONLY attributes so they never land in Terraform state. See
# variables.tf and scripts/extract-talos-secrets.sh for how to produce the
# file from the live r740 node.
terraform {
required_providers {
talos = {
source = "siderolabs/talos"
version = "0.11.0"
}
null = {
source = "hashicorp/null"
version = "3.2.3"
}
}
}
locals {
# Load the machine secrets from the gitignored JSON file. This local is only
# ever referenced by ephemeral resources / write-only attributes, so the
# values are never persisted to state.
machine_secrets = jsondecode(file(var.machine_secrets_file))
# Network config: static if node_subnet is provided, otherwise Talos DHCPs.
# The rpi4 uses DHCP (node_subnet = null), so only nameservers are patched in.
static_network = var.node_subnet == null ? {} : {
interfaces = [{
interface = var.network_interface
addresses = [var.node_subnet]
routes = var.node_gateway == null ? [] : [{ gateway = var.node_gateway }]
}]
}
network_patch = {
nameservers = var.nameservers
}
network_patch_merged = merge(local.network_patch, local.static_network)
machine_patch = {
install = {
image = var.installer_image
disk = var.install_disk
}
network = local.network_patch_merged
# NOTE: no Longhorn iSCSI/ext4 kernel modules here. This is a quorum-only
# node: the quorum taint keeps user workloads (and Longhorn replicas) off
# it, so the storage stack is not needed. Essential DaemonSets such as
# Cilium still run here for cluster networking and tolerate the taint.
sysctls = {
"fs.inotify.max_user_instances" = "1024"
"fs.inotify.max_user_watches" = "1048576"
}
kubelet = {
# Register the node already tainted so the scheduler never admits user
# workloads even before the null_resource below runs. NoSchedule is
# sufficient: essential DaemonSets (Cilium, etc.) tolerate it, but no
# user pods are admitted.
extraArgs = {
"register-with-taints" = "${var.quorum_taint_key}=${var.quorum_taint_value}:${var.quorum_taint_effect}"
}
}
}
}
# --- Ephemeral resources: secrets never stored in state ---------------------
#
# talos_machine_configuration generates the control-plane join config from the
# provided machine_secrets. The output (machine_configuration) is an ephemeral
# value — it can only flow into write-only attributes or provisioners, never
# into a persisted resource attribute.
ephemeral "talos_machine_configuration" "rpi4" {
cluster_name = var.cluster_name
machine_type = "controlplane"
cluster_endpoint = var.cluster_endpoint
machine_secrets = local.machine_secrets
config_patches = [
yamlencode({
machine = local.machine_patch
}),
# Pin the Kubernetes node name via a HostnameConfig document (Talos v1.13+).
# The old machine.network.hostname field conflicts with the default
# HostnameConfig document ("static hostname is already set"), so we use the
# document-based config with auto: off + an explicit hostname instead.
yamlencode({
apiVersion = "v1alpha1"
kind = "HostnameConfig"
hostname = var.rpi4_node_name
auto = "off"
})
]
}
# talos_client_configuration generates a Talos client config (talosconfig) from
# the machine_secrets, scoped to the rpi4 node. Also ephemeral — used only to
# drive the write-only client_configuration_wo on the apply resource.
ephemeral "talos_client_configuration" "rpi4" {
cluster_name = var.cluster_name
machine_secrets = local.machine_secrets
nodes = [var.rpi4_host]
}
# --- Apply the config to the node (write-only attrs → no secrets in state) --
#
# machine_configuration_input_wo and client_configuration_wo are write-only:
# Terraform uses them during apply but does NOT persist them to state. Only a
# hash of the machine config (machine_configuration_hash) is stored, for drift
# detection. Because the config patch contains a `machine.install` block, when
# Talos receives this config on a node booted from the SD card (maintenance)
# image it installs itself to install.disk and reboots into the installed
# system. As a controlplane node it then joins the existing etcd cluster as a
# new member and runs the control-plane components. With r740 + p330 + rpi4 the
# etcd cluster reaches 3 members → 2-of-3 quorum.
resource "talos_machine_configuration_apply" "rpi4" {
node = var.rpi4_host
client_configuration_wo = ephemeral.talos_client_configuration.rpi4.client_configuration
machine_configuration_input_wo = ephemeral.talos_machine_configuration.rpi4.machine_configuration
}
# --- Write the rendered config to disk for manual use ----------------------
#
# local_file.content cannot accept an ephemeral value (it would persist to
# state), so we use a null_resource local-exec provisioner instead —
# provisioners do not persist their arguments to state. This writes rpi4.yaml
# so the config can also be applied manually with
# `talosctl apply-config --nodes <rpi4_host> --file rpi4.yaml` if needed.
resource "null_resource" "rpi4_machine_config_file" {
triggers = {
# Re-run only when the (non-secret) inputs that shape the config change.
node = var.rpi4_node_name
install_disk = var.install_disk
installer_image = var.installer_image
taint = "${var.quorum_taint_key}=${var.quorum_taint_value}:${var.quorum_taint_effect}"
}
provisioner "local-exec" {
command = <<-EOT
set -euo pipefail
cat > "${path.module}/rpi4.yaml" <<'YAMLEOF'
${ephemeral.talos_machine_configuration.rpi4.machine_configuration}
YAMLEOF
echo "Wrote ${path.module}/rpi4.yaml"
EOT
}
depends_on = [talos_machine_configuration_apply.rpi4]
}
# --- Wait for the node, then label + taint ---------------------------------
#
# Wait for the node to register with Kubernetes (kubelet creates the Node
# object after Talos installs and reboots), then label it and (re)apply the
# quorum taint. This is idempotent: kubectl exits 0 if the label/taint already
# exists. The taint is also set via kubelet `register-with-taints`, so this
# null_resource is a safety net for manual edits / drift. The kubeconfig path
# is only used inside the provisioner (not persisted to state).
resource "null_resource" "rpi4_node_label_and_taint" {
triggers = {
node = var.rpi4_node_name
key = var.quorum_taint_key
value = var.quorum_taint_value
effect = var.quorum_taint_effect
kubeconfig = var.kubeconfig_path
}
provisioner "local-exec" {
# Wait for the node to show up, then label + taint. The wait loop is bounded
# by kubectl --timeout; tune it via TF_LOG / re-run if the node is slow to
# join (a controlplane node must first complete the etcd join handshake).
command = <<-EOT
set -euo pipefail
KUBECONFIG="${var.kubeconfig_path}"
export KUBECONFIG
NODE="${var.rpi4_node_name}"
echo "Waiting for node $NODE to be registered (kubelet creates the Node object once Talos has installed, rebooted and joined etcd)..."
# kubectl wait --for=condition=Ready fails instantly with NotFound if the
# node object doesn't exist yet, so poll for existence first.
# /bin/sh (dash) has no $SECONDS, so count iterations with a bounded loop.
tries=240 # 240 * 5s = 20 minutes max
until kubectl get node "$NODE" >/dev/null 2>&1; do
tries=$((tries - 1))
if [ "$tries" -le 0 ]; then
echo "Timed out waiting for node $NODE to register." >&2
exit 1
fi
sleep 5
done
echo "Node $NODE registered. Waiting for it to become Ready..."
# Now wait for Ready (a controlplane node needs etcd joined + apiserver up).
kubectl wait --for=condition=Ready "node/$NODE" --timeout=20m || \
kubectl wait --for=jsonpath='{.status.conditions[?(@.reason=="KubeletReady")].status}'=True "node/$NODE" --timeout=20m
# Quorum marker + taint (applied to the controlplane node).
kubectl label --overwrite node "$NODE" homeprod.io/quorum=true
# Apply the taint idempotently (kubectl taint --overwrite is a no-op if it exists).
kubectl taint --overwrite node "$NODE" \
"${var.quorum_taint_key}=${var.quorum_taint_value}:${var.quorum_taint_effect}"
echo "Node $NODE ready, labeled and tainted for quorum-only scheduling."
EOT
}
depends_on = [talos_machine_configuration_apply.rpi4]
}
-146
View File
@@ -1,146 +0,0 @@
# Variables for the Raspberry Pi 4 Talos control-plane node that joins the r740
# "kube" cluster as a third etcd member to restore quorum (2-of-3 majority).
#
# Secret handling: the cluster machine secrets (cluster id/secret, etcd/k8s
# certs, bootstrap token) are NOT read from terraform state (the r740 state is
# stale) and are NOT generated here (that would create a new, incompatible
# cluster). Instead they are provided via `machine_secrets_file` — a local,
# gitignored JSON file in the Talos provider's machine_secrets format. The
# file is produced once from the live r740 node (see
# scripts/extract-talos-secrets.sh) and stored in a real secret manager
# (Bitwarden); you paste it back to disk when running this module. Ephemeral
# resources + write-only attributes ensure the secrets never land in Terraform
# state.
variable "rpi4_host" {
description = "Reachable IP/hostname of the rpi4 Talos node (for Talos API access). With DHCP this is the leased IP (e.g. 10.1.2.135)."
type = string
}
variable "rpi4_node_name" {
description = "Kubernetes/Talos node name for the rpi4 (e.g. rpi4). Pinned via machine.network.hostname so the node registers with this name regardless of DHCP."
type = string
default = "rpi4"
}
# --- Cluster identity (no terraform_remote_state — state is stale) ----------
variable "cluster_name" {
description = "Name of the existing Talos cluster the rpi4 joins. Must match the cluster the r740 bootstrapped (kube-r740)."
type = string
default = "kube-r740"
}
variable "cluster_endpoint" {
description = "Endpoint (host:port) of the Talos/Kubernetes API on the cluster. Must match the r740 bootstrap endpoint."
type = string
default = "https://kube-r740.lan:6443"
}
# --- Secrets (provided manually, never in state) ---------------------------
variable "machine_secrets_file" {
description = <<EOT
Path to a local, gitignored JSON file containing the cluster machine secrets in
the Talos provider's machine_secrets format (cluster.id, cluster.secret, certs,
secrets.bootstrap_token, secrets.secretbox_encryption_secret, trustdinfo.token).
Generate it once from the live r740 node with
scripts/extract-talos-secrets.sh, store the contents in Bitwarden, and paste it
back to this file when running this module. The file MUST be gitignored — it
contains the cluster root of trust.
EOT
type = string
default = "secrets.json"
}
# --- Install / network -----------------------------------------------------
variable "installer_image" {
description = <<EOT
Talos installer image to use on the rpi4 (bare metal, ARM64).
Must be an ARM64 Image Factory build (schematic generated at
https://factory.talos.dev) for the Raspberry Pi 4 platform. Unlike the x86
control-plane nodes, this quorum node does NOT need the iSCSI/Longhorn
extensions because no user workloads or Longhorn replicas are scheduled on it
(the quorum taint keeps it empty); only essential DaemonSets (Cilium, etc.)
land here.
EOT
type = string
default = "factory.talos.dev/installer/ee21ef4a5ef808a9b7484cc0dda0f25075021691c8c09a276591eedb638ea1f9:v1.13.6"
}
variable "install_disk" {
description = "Block device path to install Talos on. For the rpi4 booting from the SD card this is /dev/mmcblk0."
type = string
default = "/dev/mmcblk0"
}
variable "node_subnet" {
description = <<EOT
Static IPv4 address in CIDR notation for the rpi4 node (e.g. 10.1.2.135/24).
Set to null (default) to use DHCP. The rpi4 uses DHCP, so a static address is
not required; the node registers with Kubernetes under rpi4_node_name regardless
of the leased IP.
EOT
type = string
default = null
}
variable "node_gateway" {
description = "IPv4 gateway for the rpi4 node. Ignored when node_subnet is null (DHCP)."
type = string
default = null
}
variable "network_interface" {
description = <<EOT
Primary network interface name on the rpi4. The built-in Ethernet port is eth0.
EOT
type = string
default = "eth0"
}
variable "nameservers" {
description = "DNS nameservers configured on the node (must work independently of kube)."
type = list(string)
default = ["10.1.2.148", "1.1.1.1"]
}
# --- Quorum taint ----------------------------------------------------------
variable "quorum_taint_key" {
description = "Taint key applied to the node to reserve it as a quorum-only member (no user workloads)."
type = string
default = "dedicated"
}
variable "quorum_taint_value" {
description = "Taint value applied to the node."
type = string
default = "quorum"
}
variable "quorum_taint_effect" {
description = "Taint effect applied to the node. NoSchedule is sufficient: essential DaemonSets (Cilium, etc.) tolerate it for networking, but no user workloads are admitted."
type = string
default = "NoSchedule"
validation {
condition = contains(["NoSchedule", "PreferNoSchedule", "NoExecute"], var.quorum_taint_effect)
error_message = "quorum_taint_effect must be NoSchedule, PreferNoSchedule or NoExecute."
}
}
# --- Kubeconfig for the label/taint null_resource --------------------------
variable "kubeconfig_path" {
description = <<EOT
Path to a kubeconfig for the cluster, used by the null_resource that waits for
the node and applies the quorum label/taint. This is NOT stored in state — it is
only referenced inside a local-exec provisioner. Point it at the r740 kube
module's kubeconfig (../../r740/kube/kubeconfig) or any valid kubeconfig for the
cluster.
EOT
type = string
default = "../../r740/kube/kubeconfig"
}
-196
View File
@@ -1,196 +0,0 @@
image:
tag: 1.26.2
ingress:
enabled: true
hosts:
- host: git.vhaudiquet.fr
paths:
- path: /
pathType: Prefix
# Disable HA, we are on a 1-node cluster
redis-cluster:
enabled: false
# Valkey cluster is the new default in chart 12.x - must be explicitly disabled
valkey-cluster:
enabled: false
# Use standalone Valkey (replaces 'redis' in chart 12.x)
valkey:
enabled: true
master:
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
tolerations:
- key: ENC[AES256_GCM,data:o/sXxge7tAi4,iv:4at3gD2SjyjA1r1eVYE3bi0xEzFkwxKgJRJGagfzDjA=,tag:OxOcClpHU/Z3sSiMHikOsA==,type:str]
operator: Equal
value: ENC[AES256_GCM,data:5FY3Hmqh8Uw=,iv:8LGdTpFovI9lsfAaf65dHdJnNsm17ahm2/x+97LiTgA=,tag:b07oTtzzfU4FFjm9W+iz9A==,type:str]
effect: NoSchedule
- key: ENC[AES256_GCM,data:FPkNzrFpfqQI7h1D346c72Og0B2y5w+z5m25trSt4kIEjxJ4RA==,iv:Xjl+xrXs5m28siBqNXTTmtLKEiTxnLZAzvFXEXH8ZcM=,tag:VQoot4mURGhCmy+MSjr4BA==,type:str]
operator: Exists
effect: NoSchedule
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: ENC[AES256_GCM,data:O4Wtr+1YuNGmYknT35XPONTeqUk=,iv:VqTkPwG4bxvRgXDGrmpwVeT2zLQzOLrwKlhqYCv/GiA=,tag:2pntJGKlUF8cBKgKpyySHQ==,type:str]
operator: NotIn
values:
- "true"
postgresql:
enabled: true
global:
postgresql:
auth:
postgressPassword: ENC[AES256_GCM,data:/vgY7Q154znmpg==,iv:GqwNyccbeCSm/b+7PufHcoSrsrrIR3FVgRAI0WxrHow=,tag:o/kkueEMtJUVLeARdy5zpQ==,type:str]
password: ENC[AES256_GCM,data:gc4Ev4kn9KaSqw==,iv:Bd/qGIaobKewB/rtJf426pzS4qPe/WAMi2AB7T7HtCE=,tag:XlDtRF1tWv+9YmTo1H/Lvw==,type:str]
database: gitea
username: ENC[AES256_GCM,data:6mlFP+E=,iv:+QEgLA6reecmpvvtmdOnwkpqOa7fOV06ZS8VTDQo7MY=,tag:dREH7uvHk8ZS6HcA7Vo0zw==,type:str]
volumePermissions:
enabled: true
primary:
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 1000m
memory: 1Gi
tolerations:
- key: ENC[AES256_GCM,data:xd4ugBSV+lcC,iv:3dUqomveQf0/rMwOrlNnTk1mJoF5sW2RQ+UrPLlczkI=,tag:16IzYY0mqB8LlwRGXxUy8w==,type:str]
operator: Equal
value: ENC[AES256_GCM,data:rK9ACxsGlEk=,iv:afDm0KWC0HAHw4AJnlpPw5oGcfEe3oG+RgiRCTpjb7g=,tag:sDOIWCiqxi04YYxalZ6DbQ==,type:str]
effect: NoSchedule
- key: ENC[AES256_GCM,data:83c8V9jJ+d5zpFFFhbo//O/opfgAKNpoqcsRw8W9oGbTu9pBMg==,iv:uw+6IhfkixBxBo7Gs2VSvW+q+JpW35rE9REkb6SQDTc=,tag:donRKnK6NbgBKhDgEOR0Eg==,type:str]
operator: Exists
effect: NoSchedule
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: ENC[AES256_GCM,data:UKDLBJ1yfJ2gcyu/Ms3jVnBTfDE=,iv:fK73/46Jh3nfPMnWmMHr+SK3k3l16IsT9Ah45+yCz0w=,tag:A+PvsR9YpWwHrVpHOYXMGQ==,type:str]
operator: NotIn
values:
- "true"
livenessProbe:
enabled: true
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 10
successThreshold: 1
failureThreshold: 10
readinessProbe:
enabled: true
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 10
successThreshold: 1
failureThreshold: 6
postgresql-ha:
enabled: false
persistence:
enabled: true
subPath: data
extraVolumes:
- name: git
nfs:
server: truenas.lan
path: /mnt/fast_app_data/git
extraContainerVolumeMounts:
- name: git
mountPath: /git
clusterDomain: cluster.local
gitea:
oauth:
- name: Authentik
provider: openidConnect
key: ENC[AES256_GCM,data:ctukTzFfQAZSAIaXonIu6nVsTHnTNAlqObVhGkKt/aLa9o3KxDHdBw==,iv:QoudL4RRdwpPfz6h6MWoaBOztALRa8PEi5fRFkjFzQ8=,tag:+TgP8KrYQNCBmTaqscOn8Q==,type:str]
secret: ENC[AES256_GCM,data:mxNRVXfX0X777xh5bB7PwMEeaxRPszmvmpoQt2lMtvkTSIQMJOllzY27PAShJ/y6JBPRslg6us9TpKd3zt5KcVY4Jne3hkpkQCKqE8HN3XnjHDHDzAm4ugYib5J97BeLw9pvdurLxw5iXAp3XFxMytzU4xCrYPsS61FWJRTLFRg=,iv:NCGMyWJT575CGnnFM4mcLDxsoMkggsxiNkXNp/aU0es=,tag:5uudyC1IIxorgepR7HnPMA==,type:str]
autoDiscoverUrl: https://authentik.vhaudiquet.fr/application/o/gitea/.well-known/openid-configuration
config:
APP_NAME: Gitea
server:
ROOT_URL: https://git.vhaudiquet.fr
lfs:
STORAGE_TYPE: local
PATH: /git/lfs
repository:
ROOT: /git/repo
database:
DB_TYPE: postgres
service:
ALLOW_ONLY_EXTERNAL_REGISTRATION: true
actions:
ENABLED: true
oauth2_client:
ENABLE_AUTO_REGISTRATION: true
ACCOUNT_LINKING: login
openid:
ENABLE_OPENID_SIGNIN: false
ENABLE_OPENID_SIGNUP: false
indexer:
ISSUE_INDEXER_TYPE: bleve
REPO_INDEXER_ENABLED: true
# Resource limits for Gitea container
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
# Increase replica count is not useful for 1-node cluster
replicaCount: 1
# Failover tolerations + affinity — allow scheduling on p330 during r740 outage
tolerations:
- key: ENC[AES256_GCM,data:RBMIdZLIV79D,iv:TTa1CovTGm91r/lYCKOKjnhM+i9hoLVsmDi2kmki9c4=,tag:zuhnRKxy3dtkYJr3TuLilw==,type:str]
operator: Equal
value: ENC[AES256_GCM,data:LLOg34s1mrw=,iv:rjOyHPWBGrpNl1YGi2cYN6JRm7m28HiRibQoK0JZ3CE=,tag:oSyz0nISr3plqdXQ5UJxzw==,type:str]
effect: NoSchedule
- key: ENC[AES256_GCM,data:jVh0MTlCs7rVPSYvulsw8bIGwYPw5soaOzMlzVzVbFy13qqKLA==,iv:JfZ+JWxHBiTD/rG8xHYKogkyryNQIUIXyf9chxpwlEo=,tag:hwlZ+k1L0uPe+UGBOeMlYg==,type:str]
operator: Exists
effect: NoSchedule
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: ENC[AES256_GCM,data:Sn7FuYqGMbTjx/EpqRIDx5GofR8=,iv:Wkyz+RmyTGswohAZmyeQ1lWT8hTaYw7qAVmXTnSIT7c=,tag:WAiU90Wo8Av0TsdMtyPF9w==,type:str]
operator: NotIn
values:
- "true"
# (postgresql and valkey tolerations are set in their respective blocks above)
sops:
lastmodified: "2026-07-25T12:44:33Z"
mac: ENC[AES256_GCM,data:V9ZOpVvIi9PzScyasqQJb0yZDrqQ0RSXGyAY1+WaHCIa4/YRKn9d9V4wy+CwWaeEiIO7+fkp2ROInl7eVmETm5JppQ899G33GTmHCZLcBvVR2M4xEkx8eXy3saKCbC2DN4bHRuSCvvqw2XR+QIdemLL7ETuRo2cepUMhz/93peY=,iv:3wm/iCVfAYUUa7VfBXsx200LypYYWgJYCEm5X5Wwsnk=,tag:OzGw1PQUuVRVtQ5slH3E0Q==,type:str]
pgp:
- created_at: "2026-07-25T12:44:32Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ//RIr73tcloQQg2OqSLn7W1DI6T1dYCh+ntTP3Y8KeB1WC
hZy2JOdTwHLkd9MiDimgjH0E1036+Pta9xhmoi9lnY3cvwOH/1oHxjd6ixhPxYzV
Xt38fQ3BkFvf3fHbhcbzpMIFL8tfvuVDAxRV1fHHOdCGgXqeC5GP0KtDGmnddHui
w+ms/1bS/EiwS4C7IW0yYSD3nGIF3GyLwMPOnbmJSz+ealEWjuBi8R0S1gX40QFU
EV0MBrVrtFtnA2R8UZGCjU/xpgoQFE1U8dArNt0DPqNsOeL17WQZrZ58DurmnmiE
DNjndlR8Est1y0gSO9ujPtGXbbuhAOIXuEsYMfnBgQ5Y+dShs2G1EHC0OexYB83W
FSHxM69hjQkvRLL0/lX+5NH5h+IJqZEUsLd0/J4h2Iz/EsDRxO6pKt0HzZbJd/y8
qY0Y2K5cGUzG0y0TWuUznJyxmTSCgrZAE8sgBhU607+UnXU678cqbkRgSuHTNdMe
yNxQas/PA0ltezOe3dBG34Cwf0oQZ/NCt2TfSFciFEgf6ze+fu+T+gCFfftWPiy6
pQ/3Fl6yAaVguu6UCR27wRMhXETZ+YZ8rw32XPbLE6BOvQ1LcGg9E7wJlw5eeir8
0aWvKyUu/ClK6+/s7Ytxv1RoL72gn6WuOgK5q6Sf3mqmltuvJxtDVAnqCHNRfHXS
XgFH8gPqy47Gqg9qggCHjDIUbQeAu1IAznJAQ368WXkTqqnq887sSSgcs6JVduJf
2YV5NQFOcoI6OF66FXXmY+sTpJaHcgVfKt3EHAqXxHCFZUSBHMwDJm9ulRBuYsc=
=raBM
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*\.ya?ml)$
version: 3.10.2
-37
View File
@@ -1,37 +0,0 @@
externalURL: http://harbor.lan
expose:
type: ingress
ingress:
hosts:
core: harbor.lan
core:
extraEnvVars:
- name: ENC[AES256_GCM,data:Y1D+lAT57F4HpiwnKJuhN3cqr/17,iv:ZARBNcGuiD5U7TnlBuQJLaWCMkQIELpj195aeKaBGZU=,tag:exBNWO/o2CXyNMLr2Y6bTw==,type:str]
value: ENC[AES256_GCM,data:EDMjB9DVCG3FiXdWrQmE4LhXTtTPLebKkBaQZ05tooakENXWQ2jm4YNRgBKWibHSM2gAL/z9POEi5BkiD0zK+NQV8DJKFLa8sxg9HR2OfeCqk3gMbq1uwurqrl6+OVX75E0Vqd9xN2CUtvfNVvPktMYn8UBU1nKuiRaHm3Tbt4QpcSQ6Oh1q2t7uqLDxt6DcAVb71gjpUXCZ96gg8/XsWlZXyzwJsfOEi33KlkBQhXYPFPEqq4wkXGqE1G+rT9MNOWc+WUdyY8FbP5zko+4F0Fcprj6iKlw8UB8PCtF7yAwFnxO7Bb0QGXxDGdKx93SbmGwxsYKe9muQZFfdp9rNW4R4L7K/O/ymiV+KEmwuwWoIBKZTHEwgOpD/B94MfEsPOlrmD438Ae3aifBQEOo3Ln6qu7I9md8tv2co4rmY4Wt3bBI8xXIPC1dzKI2YyQ540QtN5L22UZpabLLez0wNiVuDtCG2vg0ncI0flouQ1KjQp8DJ0Wz5i2WABwNg5X4sLU66nquD5hlf2YoNPw8EuY+E5lM0T0xBiv9AJHtQK5rN4AUopQWsi1FTSdFtCOlykBxnoYsLDyEa/73LA8e7m5Hi82IUl/5xR6LOEblEm+6jgcxY5UGaB7hsgh4K2qizmC+TWg0ua8YD4SIJZxqsNk4yz1l9DQAhZBnt/j2/I8K8PObD/7+6ObOfLM8A9UiwyIGUeQ/SCaN5DNMAHwFyELuXgTzdbdTgguJcJDgypCLUgvuVfx8dAOoj6cvHm7c=,iv:PEenzkk4lUyFBPx6e8Ah9LW7M5N7o93aueSE+pQozuU=,tag:rUeeXqEtHUQ3RYn1Pt4rBA==,type:str]
sops:
lastmodified: "2025-08-27T10:07:49Z"
mac: ENC[AES256_GCM,data:tp6aHDIfLuBDRBYPmNDn1ZWEq0ZT/WH7GYCJNp52tO1tNldi+kK2avluY0QBbC6/5V8LfxpokN3Je6uBveRVzleituxlK7dvsZ4piITTmR0T79PtUqxa4Jh+7PYp0uTofjme1M2L2MU1sOWrCdRdiKWEpDVIJCCCsZ2oDCCoMTs=,iv:O65a/alrwX4cNJH1tYh4kQPaprmulyAitg9jFhOJqnE=,tag:ewAqx7h1e12bMYGrFC9PTQ==,type:str]
pgp:
- created_at: "2025-08-27T10:07:49Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ//VDjjaWIsqY0nUFINvzxnt+dullI/+lHYQTfWvZ7LqH4d
TN2p2VZRGRkupYUYxt4iucYl6qViGey4iaQopsYrV19kJ+eEJuI+depXYsKBAccs
24rNJuTLHYi7r353u48qUVoQcE6uK0mYB8/4+w5J6uANvwmjXUtDMEHUoiBCh56+
F7olPPSPUjXv7BpTNq5EC8YjGRjUjQNf1NOyHHz1eTsyDbPszIs6eT1q98AMo3GZ
boh7T6Z2yLI7Bj5guEn5OfwyFtB9DzcpaHajDgF309CsUsxfvhoVH85rx58vce3h
QW2zy7KPvNEr84ZsTBQwLqi318JiSD1egx4m+CPvbFvV1s7DFDgQQifLRzlqR9/d
PZc3DAZ81QzXhZV9Wh4nxG26SQtsbVxAjdfLrpvpDLV3l0wIU8bzP/UsskjGa8zR
VBriJ6qGeeDeXVVuxcLMlAhd8R8ipEvLrId3TzvAPRClk4+fU7wzTfqR8Cl9hu29
csLtPW4Fu6iZshf3UJJ8KEhjYo6060TlfEZX9hzypJFf+kwJopSrS7KCPFheNBkN
P2cuyBgpG8OANQ0vYx68mgkDqqWVWNXAjUHxcp98IjZxwcSfMR+HwZi6xbK97GKS
ltqUSxYixLQUelHJX9YHkheXDwfH+q+CaG76IznvMrFi+bB4laU+DmmVnfPZT1LU
aAEJAhDJ8KQkP2yRHCV2qycNpY0qBHN6pk6FXQq7O7dl3Z1oQXkS88KopCwan36k
Hf4vvXRGLR4fm0uFYhN9aApnDFQuWm4NjEGiNyg6p6WN0XMBNARWfmTyDNc8xceA
Q5I2AHdBk7Nu
=+11i
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*\.ya?ml)$
version: 3.10.2
@@ -0,0 +1,35 @@
# Registration token for the Gitea Actions runner.
apiVersion: v1
kind: Secret
metadata:
name: gitea-actions-runner-token
namespace: gitea
type: Opaque
stringData:
token: ENC[AES256_GCM,data:IOVPnopbQKY7HBT9tlnfuwvakgegLuK+PdTTwg+eRWdMz+dAoIxhug==,iv:QhfgyXNuZnYTXV1X16bdR+Axhfbe7buoRjXV8IdSbZU=,tag:r5By6+E45B04vgZrBoPSsw==,type:str]
sops:
lastmodified: "2026-08-26T19:28:03Z"
mac: ENC[AES256_GCM,data:o3gyJNXJIBE1zSV4vWKFQWfmwZvz5Ek8ie/SjU6cF6kOqaLae2y9WBqYCQphCpasgN32qP0RM/bzzV3AZlIYqGEzI6lf0ha7aDPdVJKMy3ieie0F/UW6fJcTfidEFZYFKereRQwCWTzOESIZmsc+fqisyVxW3wL2yyYuh1a1HPs=,iv:RsG3AoqpMqR19DPQdqzfjbKNV5FZPxEsTbIZzzJtXq8=,tag:XzsmRc58Q+cNmBZXtygV3Q==,type:str]
pgp:
- created_at: "2026-08-26T19:28:03Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiARAAwpBrBeb3ywJTc54HNC7s/3+tqCvlozNym8E13jqHREOY
e6bfDO2hN2/JvbdGfMaWspLa8mU9ten6yFfUtoPADfccmbWwRAgS2mJuLyh5tksV
p+9m5vjyRQBH35pfTJ4F6Ksf7/2V8M4b2PxzBzTVQseqhOC2notYdvQeWED0gH1S
6cQvPClv/X214I9FfaHNig8SB7DV8uJ6ttj+IG9RL+NZ8lkT5GObSrphR6QH25Ne
65VMJmjcQLIWfZxR+zYVAxTsSeeDMFUY28WBUfjRei+WZ3ggmFRVERZzG6oSXfoA
nlqSQU16TyqadubPV2LcapqR/IwoSKdWO1/RmxH1NAFNvMg9nYLHzffAwPGL5wzT
GQZci20IlRQ5CLsaREyI1SNqYfjZ6esjUw8iKr5/bsr9XuI3FnWgqnKoAMs8O7d0
ZSGAohsUNrRki+ohhXtZFTelzufM1Hrt3Yz1TYQWtvoD7j87hq45BEZOU1ifiwre
Re0IhzcOdiBbCd3Lm9WSNmZzKHZoy9PJR/zaaitzZasIzsCH/7KjLBO0h1Bz+Osf
9Yxl5BMrUDFLlCIT0ORKZFtugwvS7Ez0IISMuRnSGjcutVsZGP1a6fN5K7oaSeAv
J9+9u5BuqRUs6ZYkC6TVqX7S8tAJkCOFIOFqxzb/oI2SBdRQmPP6Ix3FmN8NFu7S
XgGr3gKAnEDyuXwdZY7guYdVIteiLKUpvqk6F0yQD7b/rDGQoBD/g1twbx21ZDcI
UJ9aijLLe4JDcP02LNb64y8LaDb8VdFqlAIzV+MsYTwHAY3dB7LQtMGSmVlSZNI=
=lc7+
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(data|stringData|.*key|.*crt)$
version: 3.10.2
+20
View File
@@ -0,0 +1,20 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: gitea
resources:
- namespace.yaml
- repository.yaml
- release.yaml
# Gitea Actions runners (gitea/helm-actions "actions" chart, same HelmRepository)
- priorityclass-actions.yaml
- actions-token-secret.yaml
- release-actions.yaml
secretGenerator:
- name: gitea-values
files:
- values.yaml=values.yaml
- name: gitea-actions-values
files:
- values.yaml=values-actions.yaml
configurations:
- kustomizeconfig.yaml
+11
View File
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Namespace
metadata:
name: gitea
labels:
# The Gitea Actions runner uses a privileged Docker-in-Docker sidecar,
# which PodSecurity "baseline" forbids
pod-security.kubernetes.io/enforce: privileged
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: privileged
pod-security.kubernetes.io/warn: privileged
@@ -0,0 +1,17 @@
# Low priority class for Gitea Actions runners.
#
# Negative value + Never preemption policy means runner pods never displace
# other workloads, and are always the first candidates for kubelet eviction
# and the kernel OOM killer when a node runs out of resources. Combined with
# the hard resource limits on the runner pod, an intensive CI job can only
# ever fail itself — it cannot take the node down with it.
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: gitea-actions-runner-low
value: -1000
preemptionPolicy: Never
globalDefault: false
description: >-
Low priority for Gitea Actions runner pods. Under node pressure these pods
are evicted (and OOM-killed) first, protecting system and app workloads.
+34
View File
@@ -0,0 +1,34 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: gitea-actions-runner
namespace: gitea
spec:
interval: 1m
dependsOn:
- name: gitea
chart:
spec:
sourceRef:
kind: HelmRepository
name: gitea
namespace: gitea
chart: actions
version: '0.1.2'
interval: 1m
valuesFrom:
- kind: Secret
name: gitea-actions-values
# The chart has no priorityClassName support: inject a low-priority class so
# runner pods are the first to be evicted/OOM-killed under node pressure,
# instead of starving system or application workloads.
postRenderers:
- kustomize:
patches:
- target:
kind: StatefulSet
name: gitea-actions-runner-runner
patch: |
- op: add
path: /spec/template/spec/priorityClassName
value: gitea-actions-runner-low
@@ -12,7 +12,7 @@ spec:
name: gitea
namespace: gitea
chart: gitea
version: '12.6.0'
version: '12.7.0'
interval: 1m
valuesFrom:
- kind: Secret
+99
View File
@@ -0,0 +1,99 @@
# Values for the gitea-actions (Actions runner) chart.
#
# Hard resource caps: CI jobs can be very intensive, so every layer is capped
# so that a runaway job gets OOM-killed/throttled inside the runner pod instead
# of exhausting the node and taking it (and everything running on it) down.
#
# Layers of protection:
# 1. dind container limits -> hard cap for the Docker daemon and ALL job
# containers it spawns (they run inside the dind cgroup).
# 2. Per-job docker options -> each job container additionally capped below
# the dind limit, keeping headroom for the daemon + image cache.
# 3. Low PriorityClass (injected via postRenderers in release-actions.yaml)
# -> under node pressure the runner is evicted/OOM-killed first.
enabled: true
# Register against the in-cluster Gitea service (chart "gitea" release).
giteaRootURL: http://gitea-http.gitea.svc.cluster.local:3000
existingSecret: gitea-actions-runner-token
existingSecretKey: token
statefulset:
# Single-node cluster, no point in more replicas
replicas: 1
timezone: Europe/Paris
runner:
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
config: |
log:
level: info
cache:
enabled: false
runner:
# One job at a time keeps resource usage predictable
capacity: 1
# Raise if jobs need longer than 3h (Gitea server-side job
# timeout applies as well)
#timeout: 3h
container:
require_docker: true
docker_timeout: 300s
# Hard per-job caps (docker create args). Slightly below the
# dind limits so the daemon and image cache keep headroom.
options: --memory=7g --cpus=1
dind:
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 1500m
memory: 8Gi
tolerations:
- key: ENC[AES256_GCM,data:wLfr0r+e9KYm,iv:BGZnWKQUlOje9RhAs7tBDzNcDt5LcfTnqRSqrdFc/A4=,tag:bb1f7NwEwmEzrf5k9ivFPg==,type:str]
operator: Equal
value: failover
effect: NoSchedule
- key: ENC[AES256_GCM,data:1kBsMuUlpluDmpVddyZCI/ylRbluHmQ62F88Q9LEoiZkgdpm5g==,iv:IlggVbY7s/xaSM2ljMkiTDwvIjf12g3SQzfL2fWWf78=,tag:2aNlCFumidKSbnoUV1IBzw==,type:str]
operator: Exists
effect: NoSchedule
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: ENC[AES256_GCM,data:JuejrbDWeF+d/+d2Hq+q4V9vihk=,iv:VPgkBuv2hqJbTNFXpv3SzRGtFA6iVq1kFR8hfANg0cQ=,tag:D/wrkytnO8oZ3/+4yicq7Q==,type:str]
operator: NotIn
values:
- "true"
sops:
lastmodified: "2026-08-26T19:28:03Z"
mac: ENC[AES256_GCM,data:srIJjIgWx1OGgGwz71wQgT8c1gg64iV2VHrrb11SYXpaYg0VMp9d0maJHCaKt5rDVtWw/+Ft4WbR0z2FJBLEmr64/cFX8/SgrOR7pAc/vAgPKfxiSHg6iJoVCGHssGHm4NzvSUC2fkMqc8WUiZDR5hztUKSlp9oNPO2bKZmw7Zo=,iv:tgSmO28JZiGK9xO4uIH35zlRzJcW8lKxaggtqXlFq/w=,tag:+mIagmS+Z5RSFdSo/yDhjg==,type:str]
pgp:
- created_at: "2026-08-26T19:28:03Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ//X9NxtKUDFkdKDmWQh3wRSriiq25U7gkL0Q7SE45Tz5V6
03i6QmzCyBpI81TQQBRRzfdkuuqocBgplTRRRvFsNQNcwc5KCq1zHIDVYE+XlcmI
/bwA0GpBZwDN6Mv+G8+6UwhSp+YgsiGFTVAIctfz90cRYPpABX4wRcDYInTlifHk
weBq30iS6Nl9TajpgyyAUct6EBQ8u1YmxsII9RYWjdoTS/SAuAxNM2px7fwOPAoL
fq6/AxXj1n+uKjxl1calL95768RmLUerdxDmac53/73Pj271hmbwrWqe+JzkSriu
YMHYNOVLglf7nS3AQSqAa9PljBv7xHw9jOUqkJH14W7/NpSRvc4PICyIWA3Yfpfq
ymMI/OOYosyl3ZYhfLGUIAIYLkA1StgGVfpmeOmUCPEn2FIInBmguzDRMrdnUkoz
KYh/06Ug6YsgCTsy8Ffhzy724ITRADzqYlTU060tTwFN7cgFVHiIfZdYIFxDxNSL
NELw8Nl7+9jkWjlnmPvtxfrN90L7nBm4s3mZrYeyZ1/ElcxDkJKb4r+PJuc6rCpM
tuD9BXxjl5qa/trl/1+fVToDMMm5vws0MLl4DBkbNUNkD7wWko0I4rDSZ+X4SihM
/V7XgzeQ41KMnDdZYwTKdIVhCpZOIBwZlLuZSYCn8uhqO0YMkkpB1x1EOb2fy3zS
XgFdP2zpsUHWsy/iENHCgnMkQ+l2XwZZ2bgZGqwpRbLO0fDNX0kRZ45NzKl2+t79
npggZ12JFTPPbQG+o0hY0p7LjnjbfBsp7m9ykvymizZXlzP9efoOq6kjD/CRBu0=
=WgiB
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(data|stringData|.*key|.*crt)$
version: 3.10.2
+141
View File
@@ -0,0 +1,141 @@
image:
tag: 1.27.1
rootless: true
ingress:
enabled: true
hosts:
- host: git.vhaudiquet.fr
paths:
- path: /
pathType: Prefix
# Disable HA, we are on a 1-node cluster
redis-cluster:
enabled: false
# Valkey cluster is the new default in chart 12.x - must be explicitly disabled
valkey-cluster:
enabled: false
# Use standalone Valkey (replaces 'redis' in chart 12.x)
valkey:
enabled: true
master:
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 1Gi
postgresql:
enabled: true
global:
postgresql:
auth:
postgressPassword: ENC[AES256_GCM,data:PtWMsukqbrWiVg==,iv:iQtDckrih/3ZKopzD9eEViOMZrvSulmCI5tHCsJph1A=,tag:7S54w4ADG7+8QNiLDw2Q0A==,type:str]
password: ENC[AES256_GCM,data:jLC1oEl+ZAnpbw==,iv:PliGMmxHKn3eEt8uvsv9wL4syk91EC5OpA7AL5J0+4o=,tag:Oan4ek7m0Cxnl5bzOCGHXw==,type:str]
database: gitea
username: ENC[AES256_GCM,data:ricveNc=,iv:rPrHKhIzsNEQzoaX2cPDvVWjR7NIxsN1tBlzLB80IQ0=,tag:n64SpL6qM/IT9D7t85/Lvg==,type:str]
volumePermissions:
enabled: true
primary:
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 1Gi
livenessProbe:
enabled: true
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 10
successThreshold: 1
failureThreshold: 10
readinessProbe:
enabled: true
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 10
successThreshold: 1
failureThreshold: 6
postgresql-ha:
enabled: false
persistence:
enabled: true
subPath: data
extraVolumes:
- name: git
nfs:
server: truenas.lan
path: /mnt/fast_app_data/git
extraContainerVolumeMounts:
- name: git
mountPath: /git
clusterDomain: cluster.local
gitea:
oauth:
- name: Authentik
provider: openidConnect
key: ENC[AES256_GCM,data:9UuG23PYFiWrQKJX5xGxMgyWKLPFCxKjDUYJd59rMWcdAw619/v/Bw==,iv:AfHV1MzbYi5Z5Bb63/51Hmy9rM247b4quwKCzo7MpYw=,tag:pfpz7hhZyIUjIGGcxZVx/w==,type:str]
secret: ENC[AES256_GCM,data:PKFx/LhjwWJluC6/RHc1eMgw4TZXkXymNCrc7TQU6Bp5rGKHMvACC+G+MjXGylIMZVt65LHWq5YEHJNjO8HMsa4ejGukXDuU9sCgKaOOniCs3EQivfVsCCHtF/G48eULPkege7JRzTbmJSYJDnscsSikwvUDChy+zGlC2ZmBZjk=,iv:qsIaaeXepJ9ECilo+05+A0i2joxV0svBOjgL37DkimE=,tag:/3Xer7Yb6QyUtmPIOvSLQQ==,type:str]
autoDiscoverUrl: https://authentik.vhaudiquet.fr/application/o/gitea/.well-known/openid-configuration
config:
APP_NAME: Gitea
server:
ROOT_URL: https://git.vhaudiquet.fr
lfs:
STORAGE_TYPE: local
PATH: /git/lfs
repository:
ROOT: /git/repo
database:
DB_TYPE: postgres
service:
ALLOW_ONLY_EXTERNAL_REGISTRATION: true
actions:
ENABLED: true
oauth2_client:
ENABLE_AUTO_REGISTRATION: true
ACCOUNT_LINKING: login
openid:
ENABLE_OPENID_SIGNIN: false
ENABLE_OPENID_SIGNUP: false
indexer:
ISSUE_INDEXER_TYPE: bleve
REPO_INDEXER_ENABLED: true
# Resource limits for Gitea container
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
cpu: 500m
memory: 1Gi
replicaCount: 1
sops:
lastmodified: "2026-09-09T21:39:30Z"
mac: ENC[AES256_GCM,data:ACBKJLGUfWw9T3fOhQMT251gcLzG3bUXjUqBxG1DuPl8c8bblaIpLOu0QsrfQziQY3jM0DFJ2W/I2vjkrhCuCaZhZCtRg2nzUk+7HelqjEdKLphSuIdlHIkz7Icu+khShrwTgmQiE00Gg1WUsLRkKBgNsOm3TMK4wB874iBvSYY=,iv:Idp0+UBXaRFkpOFKFoRrLKuN1mOmfM7pukC22KkNiCU=,tag:fL9DzAo8FSx4PblVlTHtaQ==,type:str]
pgp:
- created_at: "2026-09-09T21:39:30Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ/+PK0/kUHlc+exa8slolUeTGjHzd/R1Dtux/+HJdC9Vpow
ImAQvIdkEjwL0FmoA7Z4val/Wzx/YzFJ5r6sADNaQ9EG7QO+I8WY3VrKj5aRi0Qz
+FgHAgng+wdRCCBoxv9Z+MTPSl4TwrKsbrulHAg7EayDKxwGzkyMrnxvukRqD8GB
iMQCUadudR458fzB04dkhljAbl/FqX5ppflzEoGVCiRSBcWNkaHgyYqopYGzMASy
KTzoV01adnOZY+xeZa5GasgCEbCU3BDesD9vBb+sFsRugVuRHzdyqp3nVBwudpeh
OcE9MOMyBN1SAdx9RCsB8aHWYndF1dim84ZWgQThkLlA+7CWJt/NyFYwmMdqqzSv
C7slojC6B8bb3863c5w3qe9TPPBwyTOcuNTMunr6wXidlPZWtsImhu/RX9fqzFjZ
9X1+wAjAfs7AASeNJLFYqiPrknSAA3JumQZtrFC5dejpTj9H2ns6DkiHSZy8FA8O
RuZ8hv/L8L8oilbubKnKFZLhR8lh8A1jXHUxzaEC/L4o4cd7/3TlEms/51yM9qYx
WJOz4H8lbphDYO4tFgsGAhL/yHbLHvww/X1hNldwI7mqYrFLSjIwxW2Oxo8c+QB6
yZ3VxTXuS9jEVpGTVhIOfepwS8rJQbTUeewqok3riw9GpSEFpOMWsBxlT6+HI8zS
XgHPVohxe93kk51O7WjBgq8PAwG7DtWrygqWYORz+pTYN8wTtC4pfotiJZ7hv7Gv
NICEZlirrTUdIol8jyM+yRv1gWuYwQJpjnrQVY2AoAQX6ta5/3st24cyuGwGHO0=
=Q6Pu
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*PASS|.*SOCIALACCOUNT_PROVIDERS|.*\.ya?ml)$
mac_only_encrypted: true
version: 3.10.2
+37
View File
@@ -0,0 +1,37 @@
externalURL: http://harbor.lan
expose:
type: ingress
ingress:
hosts:
core: harbor.lan
core:
extraEnvVars:
- name: ENC[AES256_GCM,data:lr90LLYoAKXh8PqT0QEmELOWBxKm,iv:y9mIMG3ND6l4rBnhW6f5FoU5BX5m4vi4WW87bv1XOB8=,tag:gtoyqreaGqG50Of69Pfqlg==,type:str]
value: ENC[AES256_GCM,data:qSCBq39+RSf1KGLyZ9TUKgVXtrXhvOhtR791n1hWKSUWho3YxM2LfTRJwcmAcLyIu8numioNlKEWQKDvOEefURzFy05RXkUYWa+ZebRp9c2y0d5ZrSiRDHM2cuxHRjeg/g4QKoX6IVhIcAEIqfHIs1NGxoqeaopAZcB6lGqspZZhzduUYJUWZGULylYdTpyF41F3RKv3xMnNBAQX2FCP3wOeb0DM8s4JMcgJ2eZwRDYecjotTC0pWL7LAZiZaLJR97O8/4cjofc9cGKEcyy0Yf05kSMxeZDWqrEplXNu2y30szafzC0SqkRwDPlifRUanNU2FaT/TIz4Ixklws7iaY0Db9yW+a+SvaWpNTY3pecbo01+4RG0eIDW4sRJFBp3/70vZ2FjCDDzaw6OEJYxrDf1fJ/UGGur2/rzDwLMhQgiRzIKoqq4n87hg1zwZ9ki63tKc+2Mp9oZ8GlvaCuNLMoG8QjXrxCkz/rcEL5Gkb11XwVAnsFdCCZVNfLstqQKpdnO8d4vvLHyRlw7lkf3ggX/b2l7Va/EkpHYONrwIdigd9ambMlHDRRhox3onZsgVaNqDdf5E8oeZJABqKV/1BT7oQn5Jx06kQhN7KvI07y21bQM2Gtvbv8LyhJHPdU3gZwtKEglp9+bU1UvFbQv9lEFm+1crQKBcgySCD8iLS+D2Tp4Y45qWjwD9Nsa2U9eGiHA1o3JZ5s3ltc2ZZVUvTpswRAfok66YqmL+XdbUkk6OtkSLS8FZVARHYbZ4bU=,iv:uxPwCWlMTEgtfGB93ywnMZLEBdNan+K7Bm0xuprYsPk=,tag:oLVwtUcrbERt9GExKo3tLg==,type:str]
sops:
lastmodified: "2026-08-26T19:28:03Z"
mac: ENC[AES256_GCM,data:UVtitK0Ct6M7scvv1qsP+QeQL7S89+856IozBcQgnLZJzeZ5cquzKvrYZ+q7DeL1rk6EWvsxxFAFnSUDLfqCItEAMs4QQhORqplv6ot6BeW0LYUf5i1646Kl7x7Mg0RkJJ4OLsfqCwNPDT0opBQBhbYwTl3HCta8McCjSg96xNs=,iv:ebt36qndBjaThOJfAVJ7ACN06NrRSJnFlFmXIH2l4gM=,tag:TArRCiiM0xdMvOcZDqBrCQ==,type:str]
pgp:
- created_at: "2026-08-26T19:28:03Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ/+JkaqlVRJtypgMHl1jg9Dv1XqgeEW/5tv52YgxvNYk5kS
MJBeuku6/tVGb7i3eArj19My4hQLTXPWv/SK2cBiq3dKnjEs77Nfc1ffRJF/J03W
Ur/zy3o9lhVaWOTYVPTH1QIOehJS749ApadN7zB30g4RiOwJfTWiivEx67TzalDv
nvRMaotbAWxyD0PNpWV27i93FK8SIUy9HufpZucoN0BQ0moAj9BhbneumB+dUwRe
gh+C6LzbRuehFvegIh8DlWIKeMH1L0xW100cwuXyf6FOK/FM/pSsWX1IdlXD5Hfv
OSt4QHJESepTmEukfEgyywBMxk1iKdhW9/xa5lkEGxfGv6LnomzFWuKKOqiOF8GG
ZTt3NIj3Hr0S0USehbyQwQNOB/EvWTSWcoeaEVUmdphil8rZySZ6B2kkHWaj60YQ
cxb+vv9wgrjJitAhwds/xI5HYk0VSXdwtxZPTB4wqzNak5jHFKEY6/s0meQHk3Y4
UF9JIZsxLgPGGpAxzYka+Rlibv1FlPpyWQJZet6NGD/VbinhosIVv9vSZA3PqbyB
1x31PxGbKac/b7yeo2AfncpKPm0A33VENv1btRbbBGc2LRkYyLnlTDGmHbBrFE0s
HNnh4Gfc5EU6+GQo9UO7WIex5AQLvje91js895StVeh52ziyCBdjUwy6hhlSERPS
XAHgjHq0JXu8+cZrgjWyPlLcDYbMelW8RWsiGvvyZqUJn5YfVLBkMpSYVRanC0ib
3jBdLOaHKZvi9na0Tuf6QcWHep8J4hj1u80yUmIIzk0Xyv5WFYcypJ+g7KqC
=MmP5
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*PASS|.*SOCIALACCOUNT_PROVIDERS|.*\.ya?ml)$
mac_only_encrypted: true
version: 3.10.2
@@ -0,0 +1,14 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: renovate
resources:
- namespace.yaml
- repository.yaml
- release.yaml
- token-secret.yaml
secretGenerator:
- name: renovate-values
files:
- values.yaml=values.yaml
configurations:
- kustomizeconfig.yaml
@@ -0,0 +1,6 @@
nameReference:
- kind: Secret
version: v1
fieldSpecs:
- path: spec/valuesFrom/name
kind: HelmRelease
@@ -1,4 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: gitea
name: renovate
@@ -1,19 +1,19 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: linkwarden
namespace: linkwarden
name: renovate
namespace: renovate
spec:
interval: 1m
chart:
spec:
sourceRef:
kind: HelmRepository
name: linkwarden
namespace: linkwarden
chart: linkwarden
version: '1.0.1'
name: renovate
namespace: renovate
chart: renovate
version: "46.260.4"
interval: 1m
valuesFrom:
- kind: Secret
name: linkwarden-values
name: renovate-values
+11
View File
@@ -0,0 +1,11 @@
# Upstream publishes the chart to OCI only; the legacy HTTP repo
# (docs.renovatebot.com/helm-charts) is stale and lags behind releases.
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: renovate
namespace: renovate
spec:
interval: 1h
type: oci
url: oci://ghcr.io/renovatebot/charts
+43
View File
@@ -0,0 +1,43 @@
# GitHub Personal Access Token used by the Renovate CronJob.
# The chart injects this Secret's keys as container env vars (envFrom), and
# Renovate picks up RENOVATE_TOKEN automatically.
#
# Required scopes (fine-grained PAT, restricted to vhaudiquet/homeprod):
# - Contents: Read & write (push update branches)
# - Pull requests: Read & write
# - Workflows: Read & write (repo has .github/, lets Renovate manage
# action-related files if configured later)
apiVersion: v1
kind: Secret
metadata:
name: renovate-token
namespace: renovate
type: Opaque
stringData:
RENOVATE_TOKEN: ENC[AES256_GCM,data:XgCD6ppqguo6MMv0OScXUkqhn07Mo31F8o4yf9Hd51wHjpmh/DHBSREqBzYpETrB4vDjec9AVyylOTz5qEITFdme+K8qg4L6Ti/JPIm5WOPNsXD84k3ZFIr6PWvQ,iv:ovQhFt2XlyHYzadYlQnQQ/X/NFV+9CeacZ40B1WYjqw=,tag:NTWOBN0ceJ7evKGq+y+cFg==,type:str]
sops:
lastmodified: "2026-08-26T19:31:53Z"
mac: ENC[AES256_GCM,data:1EsEQ1JmB0pTgoA062k48hKAa4IUNKm55E/9bbmHPRcI5CUC7IBC2npT2yn0+6eQ7gTSqdrbqZw+xu0LAF5IrEjIIscKE7yZizkFAIy5VuCdZdAOBlvLtc1GXg7PE6ACXn8wHDcWBcAoq12HEAtpdXS1dNhdZBFxkB27RD7UvYw=,iv:hPeTFZlrqXyVNuy3D00VeLqecKDEKKGe/AhuFwSxPYs=,tag:O6+OYfJU3QeL58f5/tUQkg==,type:str]
pgp:
- created_at: "2026-08-26T19:31:53Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiARAAvkrhQ3QLbfF4xTCjmLnY4BzudBMrx4j1+zjG7S8MZ/oL
Vx4ji8gAxRIvv6DZ/eSwybeTijtY4ROUQRAm+2Ut5r2yKVGZiokTUE3js/SgQ4Nx
uSMcEdn5GOilgM/c30GXsWzCo3yiGWWCNISwxOLvdRC2FEw0OYxTRSEvtBnck22q
FExVE6fvH/ks7nak3ry9Bo4OEVZZrLmr8MR/RL/l6Z8AyOLCp7yss+a0OvTb+NRq
PVQXmoLlRYqEdbkW8lbyt32oJ451ukMH3l6yscC0ZxHIC6XvKUwUa9uhcUPLZq97
o73fmYqCSKmfLc8CMTDX97d9yuApOepZZtVaJGxLhxd/pNIZNwbojoo6pCKh8bdY
2CdSf/FA+EqjG1B6CtzHCE35FgiYuDxFsOM7WbPROvT8n7QYVnZGI/QoFawWAFsw
heFi9sDGBcqM+bZDo7NTV0Nd25Q/+GfCHpK1BAug4n3K61OuJhJfHw1kadbH81y0
vWN9AAQTYfu5FjqMjSbyASbTYNX28a776ojYrR6HGgD2A5PyC1vBAR+VZwSernfm
N+wJ8YAK/2hPKVReEhYFcJiSm/MuNW9QD49/gbj7Y/NFs5NEJlV33cAEo6hyduR+
Z+Aw2M9xOsz+qFop86oRGSXNCZh/TG/G5/7rjS2zNG0vQAsgQ+xVXmDJPsmZnPnS
XgFuPLMkIN+DFl3PaX9LwkqgROXA3KGG4jZsZ4qzQ0+fZOCAvoU7FNXKnyQ/i2qv
NPSRW2WLDAAbqwjj3jNxdd3JFRbDq6XQ+V175fYN8sTFuOYLq59d8YD7Z8e9+aU=
=xVRA
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(data|stringData|.*key|.*crt)$
version: 3.10.2
+70
View File
@@ -0,0 +1,70 @@
# Official Renovate chart (https://github.com/renovatebot/helm-charts).
# Runs Renovate as a CronJob against github.com/vhaudiquet/homeprod.
#
# The GitHub token is NOT stored here: it lives in token-secret.yaml and is
# injected as env (top-level existingSecret -> envFrom), picked up by Renovate
# as RENOVATE_TOKEN.
cronjob:
# Aligns with the "every weekend" schedule in the repo's renovate.json:
# one run every Saturday morning is enough to open the weekly PRs.
schedule: 0 6 * * 6
timeZone: Europe/Paris
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 2
# Top-level chart key: wires the `renovate-token` Secret's keys as container
# env vars via envFrom.
existingSecret: ENC[AES256_GCM,data:tt9OJ41wHayCWgQYd+Y=,iv:jBqe+K1hL36ViFntV4cU3qh9jdnG6W8e4LiE99rIFIA=,tag:Kj8/qKd689iIatQgUc+9iA==,type:str]
renovate:
# Self-hosted config (https://docs.renovatebot.com/self-hosted-configuration).
# Repo-level update policy lives in renovate.json at the repo root; this only
# tells the bot WHERE to run and WHO to authenticate as.
config: |
{
"platform": "github",
"repositories": ["vhaudiquet/homeprod"],
"gitAuthor": "renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>",
"onboarding": false,
"persistRepoData": true
}
persistence:
cache:
# Persist the repo cache + SQLite between runs: much faster clones and
# fewer GitHub API calls on a weekly schedule.
enabled: true
storageClass: longhorn
storageSize: 1Gi
resources:
requests:
cpu: 50m
memory: 512Mi
limits:
cpu: "1"
memory: 2Gi
sops:
lastmodified: "2026-08-26T19:31:53Z"
mac: ENC[AES256_GCM,data:fA2nukiGOWK5UVQRbBagOLdqSBjYYG2VysxXfQ3TuRtFYhN8bd16j5xIfy2aDrlLEVw19uhInggQMu2vJg7xT6V6Z9w5YsHwcSQWSGCMjTk764/ChT3QGA0nhVG2ktgsZgaiU/MrCAPN/XQP3dG6Y25vkcptFcXnn7Ig5D+V2eQ=,iv:3fKfVaDJ7RjjAI0n4I+6na9pKLB07yGgjvRXjh7I3Iw=,tag:cyclZ/i2rfKeAof15J4ufA==,type:str]
pgp:
- created_at: "2026-08-26T19:31:53Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiARAAi9efDDL8A1RFxx50RBFjLi3G2OG8XQfo/UF3O7gd65vH
tu+3b9KtiRvWurOVqapAxUwapiiwx4Gsem5F1Q9FoX+5HfQ3APQ91kxfGjQTjx00
2lt+pl4JyeKj0+ilGMP5xaUyOvZGNB33v4ls14Uljzg3tqQQPGUvYMJ6f5svXXOo
ugagStCSx9jh0j++Y9gCFZXYSn3C1IblGeUxkh7fUJQjveqp8R5Ofntdg7sbV5Au
Xeah95zdQxdJ/zb6GW7t0dWY5KEYi4Tg1gNybvMIKDdWZ8NND7kaFOSx5Bg8aGJa
+6nh21MHs7oNmzpxLXNa9rTk1ncE2HcLcTIXl+NHf10dPcR6R32w8Bc5e1UtBKI9
mUeHgH2zphG4Xihcchbeeb6RAxBvl2EWLglxB/HKKw8ouC3EmlOj63QS7o8ES8CZ
z+/uq4uOP65Q9k0xa9YHl4nGVXlOYqxFkiB71UYIqwUxyw/Th0IEZhBrd2GFf2wl
CUj9DDDejWBvGyIwp1MIRLhQkMrL4KczHLAdMEC/OcvylZHxESOpMEIq+CUXi0wr
GyjnwLS3F1ZPB0+Xbpy8OfTKAT1jI6Z65G6138p6c8xJsh+lBwBd4QFTJ0VfR+fd
/edCwMKalySDK0Li9OIphj1or90l/ZURdlZpIrgnYrYeBg7HibuN2E0u0cMur/DS
XgExhwYtGznQThvIySwqAa2YMLm5tz5PJ1mUGkJ2AUaJuQX9SfhFYJSCGjpv8Fbf
04FCKZ7B8eG9j9ae0Wfn07SeN9xSZEMuCtE0KLjAR0v5ACAF5Lb6Ee5tc+5K2sk=
=zZdk
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*PASS|.*SOCIALACCOUNT_PROVIDERS|.*\.ya?ml)$
mac_only_encrypted: true
version: 3.10.2
+23 -22
View File
@@ -16,11 +16,11 @@ configurations:
- 127.0.0.0/8
# Failover tolerations + affinity — allow scheduling on p330 during r740 outage
tolerations:
- key: ENC[AES256_GCM,data:SMOTaAtzpNtv,iv:rsMiAMaugnRKQjtp67nU0pW+MWXgolluiE5qoIWJkRA=,tag:RLUTotQG3XUQfDiA7CE7vA==,type:str]
- key: ENC[AES256_GCM,data:5+QTI95qM5mc,iv:FS4FVgDoOOpaDSArV8o/RkpkpJxx+VHJhuExKZn1Vgo=,tag:f/7b4p2Yzc2fQpZrJNB0EA==,type:str]
operator: Equal
value: ENC[AES256_GCM,data:DhbXHMsUJ7E=,iv:lQQTpWpDGi7JEQV24jdICHMnC8yV0EsNQ/nauBsqk/8=,tag:RKripNRdBwqnt1sCY72eYA==,type:str]
value: ENC[AES256_GCM,data:p9l+vJ81qoA=,iv:x44SAzdRxMGCGdnS1EQxU5rG/7BQ0gWJAqZHohii8W4=,tag:wzVAvTzbcJFD0Rl+8uS4Sw==,type:str]
effect: NoSchedule
- key: ENC[AES256_GCM,data:YApCSh00O5YoRqzHUNSoPbYWOsNVwFKOlln0C2+mYpDfKqLU5g==,iv:eOv/Yri400RHpm6Bnxqw4IYp2IiYAKXTd06sduW3Ku0=,tag:9GR1Q8lWHG7Uplevd1hbYg==,type:str]
- key: ENC[AES256_GCM,data:2RIXb5x6dsNEV241NTXFGYL030lRupkjWcPUHsueK4a6bn8DBg==,iv:2RVpm3L1RXXc6nN3L4UqkBxuNe/pfeNBzprwLDp6ank=,tag:jgyvyNdcurQVuih3YvaBiQ==,type:str]
operator: Exists
effect: NoSchedule
affinity:
@@ -29,33 +29,34 @@ affinity:
- weight: 100
preference:
matchExpressions:
- key: ENC[AES256_GCM,data:0rESi0B+l5uEwmPQPuFzMylc6JE=,iv:dGx39YEojvQ/J2y6SlP54I5L7Zr+yecwJwNQQ53RV9k=,tag:icAw2r/q4+UcHzYClfOBSg==,type:str]
- key: ENC[AES256_GCM,data:I6Z6SR2x8z6grjUUv3PBHLDc58E=,iv:smfPq81TGWdkPyao+pJCoZidgUFhPTdFdXBRMPeJ+p0=,tag:035Zf3xHRZL0wmbt9e7pUw==,type:str]
operator: NotIn
values:
- "true"
sops:
lastmodified: "2026-07-25T12:44:32Z"
mac: ENC[AES256_GCM,data:cNqULRYPz0Es3az9v9HWlEf1pvPFWfZ67OofRWaDgFx3KVKVj6VUY6HQgN589xbbCoBKLSKXUoag2zOku1P3yBkb39WrdUtfSJw2t7BvZIo0l9VG0bRAYZgJYgnQA1NrjxixzgZZ7AHst1ljB+ZC6qq5DgEJcuCiue9zkfySTMY=,iv:rNDmiWS1U01xgRHty/sp/RJ5iz78sOdBGP0mdjUX7TA=,tag:BVKsb/HQchTaLo+2Tlrn+A==,type:str]
lastmodified: "2026-08-26T19:28:03Z"
mac: ENC[AES256_GCM,data:qQWuHn260xF3a0+H06TZD5fdVkj7/yff2W+klPjFFPTq9x+roBXQsHaulnSVO966djEvprPJQHIHUN5pgx2Re1rgyQ6MSI8J8H+iO010Gw+k7w6Ya/gMN157qxusY9gwyKG56eciE/4FTocfAsjxcOkTuk+nX+N/MkSjbv1mAIM=,iv:ddhMEsQIHNqWJB2gMOMd6N5WZneeeFNOAnFoPfVUE/s=,tag:QziO35kTfqj7JOFPqC431A==,type:str]
pgp:
- created_at: "2026-07-25T12:44:32Z"
- created_at: "2026-08-26T19:28:03Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiARAAgxstgt71NySIfZBgF0Nb78qkkFV7xOEfv+VWO3EaSp7Q
8jhARPxkAVMwl1MQIdCxB6UuUeQi8fOrLwjYzTN1tWG/VV1P3KV3klm6jNcZ4Zxv
OdYt6kRLNfI4J7KWFhZg8A7/FfXSOtZEWLjD60hb4ie02ALEC9o2rUcdxWH2ZdHU
69GhP3VU9uiChOxEk6eLyQr22IF9IfQ7BVUckVzU13neZ2PEYXCV3QaHMBrvutMz
IFUGpi+drrXxXq9KmJQ4Yr4L0+mHwXYrFVi5rHK/ibgRDNT7T9nK56WCsgRd0MiK
7+1vK/q73p5ZdozmalYB2lKuehRapf/xdXbn1SrWGXbsHubdrE2AQgRxBHVy3k8I
spN2ZTPzl29mUsVIWKE/CdF1GsUGYrKwKL7S6aHZBtRXncbKBEFLbrloAjs+j83+
aU5ybyQWnZxh7f4+nQyDerSJXZJ17eEJRjqMDhJ6VmA8iOBWxgudM57d4Umt53cf
s4vOikRSO0cd+/OMvQQBW1IPMkwRSi4/jD8BZTXisWVUQ3/98NQPXQE5EYk2w7aM
5T1orWWWMz5EdQNptqz5GL6qPoH4UpVSGCNuCf/oyLR6MCt24JDR9KobOgXKUrfM
Qig6/+4WbvxBJ9zevi14FL+K00MeWd3pQT2Bsg8l3fWPIRe+p9lSB6yrsf6xHu/S
XgFWycRMj+U+y7B1kyXT5W6WshFHHTOlyAVgk9lnB+kKEVno4pAQBNuNlW4gwOvr
iuc9EaiuHat+CW+WdxLdH3i/jcNmvXfXRXdE3449aXv+haNBjxz93nRo1vbAFuw=
=O+AO
hQIMA7uy4qQr71wiARAAmUXgE37uXgmjh0BbCsX+hqX0yLGtzWm0LfAF72lhU74X
899VsY3OsCGAOndSH0T4vH27/ayoNE5wTZMahfxa02IdWZXMo3nD6F4k6nai6Dkn
7m52RRBqNM66NhF4TAaTKg/j60XJKw0aoVSlgkUq/JVvs4JSyZPpwCp2TVz4/TwD
Dn8jC6Wfs9YQKWa7FWKW8d4vz9SNOpPSsiT5hIF93XVs9GdcsCtCsPB4Cr71whZj
q0RYWi21dnFzf5qCEH/5Mmz235JudMYESwJ79yrIM9r1Cj3QPPc1oEy2qjbBpN78
ulobKXMdclkCpNNgqaNr86v6weT0HpjqR/lleUO1EMzyTOKaIZ1uGS5xPYHlqF4M
8u6Gj8S6kGCLDsAQlnUbt+cycg1NOPNPJq5E/htio+sdoUeEmO+Y3+y54ccqR622
eyIZhp4RJukNLnq1y+6LiIUmimTSRlApwLbBouY24D/JPaO1oWL+Q2dcvm2qpZ9w
/o2bdXyr0vNUnpq4Yc1uU8rBSeElOIRHcTZVdtsUZuJp72tXo7/oJqJmsnrAih4i
/7+rsOpRRQDQPIyEveBXcwEp/baSVsYdeINufmXiM57ie+B135+5tsYYucF3pXzc
elJLdKSif1Kt8w6Ch+O2M3NqsCp+yp6IihUOt9vyZ7pYLZvWLo/e5JUmvy9S5snS
XAFFVhnrgNL+dBuzZXa6vfglwvBNl9iEogYWtcX4/Sr7X30Dv2RfkcNYi55sq7ji
A9Y8/cyL7d0m/ksgpcFcmRQvPCOpM/KPKZ2KbLLdeuXOhP/WXG+2auhJtwzF
=BS4A
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*\.ya?ml)$
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*PASS|.*SOCIALACCOUNT_PROVIDERS|.*\.ya?ml)$
mac_only_encrypted: true
version: 3.10.2
+21 -20
View File
@@ -35,8 +35,8 @@ zigbee2mqtt:
external_converters: []
mqtt:
server: mqtt://mqtt.lan:1883
user: ENC[AES256_GCM,data:8chGUA==,iv:SOAuBYShpWbza3idtyqFoVIFstZFM34OPDN4uhAer0Y=,tag:WPoH80VcUGLy5Uq/z8EtaQ==,type:str]
password: ENC[AES256_GCM,data:XVcTzQ3pDvPKbw==,iv:TK5qHq2yMTWgzcOPvj0GO7tOOD4PHvKMWfd3p4T8LuM=,tag:GJpKQWpVhwrewX4+9NITfQ==,type:str]
user: ENC[AES256_GCM,data:Sl/k+A==,iv:d1LIy5ny5jS5yEWtWfVntN4R8uQCoRwSiYkUb1JG/yo=,tag:dkNv+GqyD8geimnuJHgAFg==,type:str]
password: ENC[AES256_GCM,data:vwap+JwtgOpLAA==,iv:PC2f6Lg0EpmaJKd9M2yeQGejvXTNmhRPjAkFw1M4zwc=,tag:zp0sgA2uzLmOBNNH6yY95Q==,type:str]
base_topic: z2m
serial:
port: tcp://10.1.1.159:6638
@@ -44,28 +44,29 @@ zigbee2mqtt:
rtscts: false
adapter: ember
sops:
lastmodified: "2026-05-02T10:26:20Z"
mac: ENC[AES256_GCM,data:32zZ0bYrgn+zTz8DEOU1N8MgDrihzWyMsV9q2m5RhFHRvXFuq3Z2GTORlUTeuK5qZIUrZt22VskigGAQiKC2CdzsJTcO3cGPshu5E6gWGBRNob02bXXsMu3TfCKxic/Ek7jE2p9R++a5AKczFZY8SxL7Sv1BZDxozkginDdYR4Q=,iv:VcDKwoPgYxZc8KXYv9oEH2GBqDRAJJxphj6MFLLI8ok=,tag:vPWqcEHoBVvfCoKoN5UiLA==,type:str]
lastmodified: "2026-08-26T19:28:03Z"
mac: ENC[AES256_GCM,data:RUcA16mUHxIwToAQBR5UCbi/cEcDXms5r1cXYS7drYfvcPI1r84oX9/PHsXrRHcMsqIwyQbiK72CDLhQFXDW/YIugpy9OEFPAP88oqkfXrZFA5NfoU/9U0bfI5U8GmJEHx56DJtsqfSy1VMotC8sd0wj21YBcnmRhYIMoXLl/G8=,iv:tcjXHh0DvXheMlQIifVVY2TJryFmgZchbVfLKFpnLf8=,tag:KjpEK92QTFtzl6ml/Yw/VA==,type:str]
pgp:
- created_at: "2026-05-02T10:26:20Z"
- created_at: "2026-08-26T19:28:03Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ//fl1m3T6TnQvQ+yG0plOZaRXIGRI/YHiyP9KsK6I6l4c9
Y7lUjVcgADbjZYAMv08LFOEyN0/dtTFx2kV1vC5sF4CjxXKfddazKrQFjZQygc56
Yn3wiYX2ZMTsc3AnOoUF/evXyDHYMu0l8FwZEupi0cjmgKjVZZsLYScMjLi6h9oO
agDUxqZX8d3ikj3LPF1dk/XGP75fHBg7Jfim1RMMrOcpAbRi0H3XU82cr2s9fTS8
UtylTk1x3F253YTC0JdvU0UskvzCvVl0Sf8TlkVb2tTJgwf/XnXMTmMeCvbhIj5u
bgqIs0y6F0xm8NjhPGV2CtsQuQtLMLb5SxVFj7P4ad/Ekf9TizAJlcPt2u1/25zu
x9v/kFnI5XMDIr3eWBJlFUwtImQJ+bO3GTauqwpULIHSa+y3Ux2XMNarKfN1jH3Y
RG86rLQSioSA+HdZuZdEvo2ACc5DotC835cnMGMeIuO1Ad/RjvUaptN/p5hvTFMf
5t6SoE8gLXH7FZF7IomY0Xs/feztPOvPK76zpKV1Tqqgb7i0GaTFcKKBUxMPklZw
XwqOQl36HWz1BSvtYtYYX6/HyuknH4T6tk//J6MrNttnTQ/ZqjrBvl4FEVxTgf1h
pFc8fTzNak+VB4MSdALg6Eo5xR57eGHhKgdUMgDAv1JMEP9ikk4/p8/1WHKhpTvS
XAG3QSahHWoc9L5A73xFmD66TRUhm8CVKRCAQebB7rXjsxaqgEOl70taQpucrckD
624SYxJwG9Uuk4odCQJ6g7T2KCKxsS/NKy6jOqgprkerR6pCfuXg8LDxBkHP
=cZ3t
hQIMA7uy4qQr71wiARAAptsMCNyzKNo3EtUeF1rdkRPPPg3yfjd4UjZD6ZkIFExw
IhqPSUqQl9tdjqNQaY3Amyo5rwvk62Reep6Zqz3+ig2DulwQN1lyJj+CPdNNAZ7O
81n1E1NcIoQWjVkDoh5MN9UEZkCfsr+2zE7fTiR2Zt5WOQm/p6eGB/WxFytirN6N
cgOt7ZNDZi2UW4ffyqt9ayU1s5C8o9epQecfhtGWxchM1GeBz/vyT/FHJsh6Jq3I
K2a/wz5vQAq1GMMAybzB2xNnM882YuclyfTLOJaAAYBovY9bzEV5SXOxpyUq5gXk
hJVN1xtzjBJOHySY2Nk8blX4md49W0CTmQptsKsIBQZ2+RtZg6MK5R4UeCrO8u1X
UkBYS4tbfBQtijoUMAlqUpSdvYGWEHg72dX1u7LQRW5adKCB+JHtIXYHQ4f5DSjA
HBHwZmMjf4yEMOmbV/E8cvGCCDHX3pOPx3F2I5RYcp+mES5SvkX/6SQUMVmypeyf
wp2zcx1JMh44HDd63vIEntQ4FALNHB7INqSytZjiV2DBphUimPMAOKSz6GLQ8Ye8
NLTkZOFVmyCLNRj/Z8iy1m74LHL4a58arZ+D5OrXlhRlE6SyK95QzRs0xyvPS58A
PudcPKf0BrXCKWJfd87Kqurf7r64F22UYge7nyM2U/jhRLWtcBmG+tIy5U+U65vS
UQFbkLECKQZUbk9FJW9nR6dXbFuK0dhZFsR2c0lsEGSsl9N5exosNbuH/43jjzXo
LEn+CGVci15x7+2yBtA59ZMzohu78K8riLGbtlDUaeouSQ==
=Zbi6
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*\.ya?ml)$
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*PASS|.*SOCIALACCOUNT_PROVIDERS|.*\.ya?ml)$
mac_only_encrypted: true
version: 3.10.2
+32 -31
View File
@@ -1,14 +1,14 @@
authentik:
secret_key: ENC[AES256_GCM,data:P5e7cSOa0Uw0NEmWuDzIv1QxIkbvLE9vjzULmS8yS8b62fS5jHuFWUF/8VkW+pXiJo51mZ9b3QWDBdD732hpSrR7hUpK19WdZvFfXMKsqVc=,iv:AuuvJtXdlQ2SzeiFdxv96cEVyeMTNW/fG8bPS4ItFtY=,tag:AJC/T+eXGwOdQ/U7rebIdQ==,type:str]
secret_key: ENC[AES256_GCM,data:QjhY+442U44K3EJuXqSb42eyWt2znf1KAG0DeQ7JQw2qGA4tMaZKVaBKP9jHkF0yR2G8gZpYIofxBJFfl82kYsqvrixcxgH11H+ctZxVI6Q=,iv:HjPjBzFkmBYahpKjSXA8qUS1a6c4/solENAB7noaIxE=,tag:qpW50kV2bVoduM92UNKVxA==,type:str]
postgresql:
password: ENC[AES256_GCM,data:wmidNe0ODeH8FQ==,iv:zh38F/lIKdFBBIQufjLORtfusPWwDnsDIh61b6ltbQE=,tag:SSMCicRKoPBXwPLFoh+uoQ==,type:str]
password: ENC[AES256_GCM,data:Prv+e2pcLAyVyA==,iv:y36fhvpI2qm4nRnJzPXvLi1Sopn1g4YhdFVs+5fVeaI=,tag:z+HhXLN57qryvLdqtByO9g==,type:str]
email:
from: webbot@vhaudiquet.fr
host: mail.vhaudiquet.fr
port: 587
username: ENC[AES256_GCM,data:VV9x5UWZ2F/p/l4pOVdDB3ZeK98=,iv:H7YXijpo2oJEO96LJOERL4lyQtV7QJq86H33wDpKObU=,tag:q+KiivjpV3kXY0AYGKhzFQ==,type:str]
username: ENC[AES256_GCM,data:iZeZ2IgJH0iJWLYWCh22ogOuEzE=,iv:Un1P3ra/ziVZdPJFVnHBGs6zZwTA1elODRuKHaMEHYA=,tag:KdFfmfF553e9BeG4Ypt0tA==,type:str]
use_tls: true
password: ENC[AES256_GCM,data:pco+hLWairs2UFNFTSY=,iv:OMrxrzKDo91UIMgEhPdN4dTpRxl5A1LKHYk5h4eFD/A=,tag:ecjAP9lv6FPxPppyurJ5cA==,type:str]
password: ENC[AES256_GCM,data:Vvs0ibOmTCo5f5P8JQ8=,iv:uiT2+qK+KxS0TQqw4Tda+CA2h9mlhcf62WjKH61LP4U=,tag:6tRDtEWmHpiSjZz1xchHxQ==,type:str]
postgresql:
enabled: true
volumePermissions:
@@ -17,18 +17,18 @@ postgresql:
repository: bitnamilegacy/os-shell
tag: 12-debian-12-r51
auth:
password: ENC[AES256_GCM,data:cRaZ23HWjZ41ig==,iv:HABmXhmHvMhjUJ989xJOFPWW+EnLTCot1is80vMTBUE=,tag:r+/iRkQIlXvALv/JQbGFRg==,type:str]
password: ENC[AES256_GCM,data:eQj7A0VNaObUag==,iv:19JuGpdcwc+aJRiINaIu8015gODcDZO4pMO/uc3n+Yk=,tag:WUJAw2X6NLLDmqlIydyuoA==,type:str]
image:
repository: bitnamilegacy/postgresql
tag: 15.9.0
primary:
args: []
tolerations:
- key: ENC[AES256_GCM,data:M14eAjMj2w2+,iv:5vIosyFtwVgqs07CT2UcL1KL2hqg+rvKS5PWRvWRlPQ=,tag:OJ4RwlLAhGDN4JGPX8gypw==,type:str]
- key: ENC[AES256_GCM,data:NZUuKYSOkot6,iv:wwDpZ18Q2OAj6Va5nWWKyrYK6/DqxjMKnvTRNMDkLCA=,tag:I8Na3EpJfAgCzUVSxFn8JQ==,type:str]
operator: Equal
value: ENC[AES256_GCM,data:KKZ1Kd5yRa8=,iv:adSUcfmjnDAc9QZ14NDfFz4oATpcBhtn8iHTF2xXpcw=,tag:G//QEbSKXiGP7nD5oAfNSA==,type:str]
value: ENC[AES256_GCM,data:XJw93s+tOis=,iv:svIxr795xD/Hz3yaHc4aiZ14hExVgmEDGfCOJoAK7Do=,tag:jdb0UgIOyXVmegHq3TvOJA==,type:str]
effect: NoSchedule
- key: ENC[AES256_GCM,data:KtJS0g+/3y6VZb9VNKv1IWMwIi8FBURPGT6W6qvBAV1CHW4UMg==,iv:1I8o3SNljujN4FqByFC9uHpImJhHjj4Us0QEpHpDHZ4=,tag:FIpRW9I4OSVFVx4ejmau5w==,type:str]
- key: ENC[AES256_GCM,data:kzg1pA8p8cBUgcKw6VfQuVPPmUmXR8uMAgxklAcJB/hVjGuxHQ==,iv:sFvOylmUNsfC9+XwwGPsFiua+/OMEDXlb/ICSQ6KNVk=,tag:ybJIKFMS3wtk/ESidcbEeA==,type:str]
operator: Exists
effect: NoSchedule
affinity:
@@ -37,7 +37,7 @@ postgresql:
- weight: 100
preference:
matchExpressions:
- key: ENC[AES256_GCM,data:IkWdKkS/XlGw0u7I+Q2wYhXL+CU=,iv:2k9d0Jo4Vw5gA4tGeIq1Dw0IiZKQykfV8YAt2lYk7GE=,tag:Xnz58VP61Ew/J8hvIClOVg==,type:str]
- key: ENC[AES256_GCM,data:A7lJZoDqSfcwF+W3aweIxGmiVIE=,iv:ZFC9gAM0wVhGpFsfzHfBI3fUPNwGo2/stpZk9FTlu4k=,tag:8HzGLiqZ/Fp8AvGjDLeBVQ==,type:str]
operator: NotIn
values:
- "true"
@@ -67,45 +67,46 @@ server:
# and global.affinity.nodeAffinity (preset system with type + matchExpressions).
global:
tolerations:
- key: ENC[AES256_GCM,data:yy3LVikckQ4y,iv:PlWRKZVoR6g/RtQdGBoIKbnwjX887xZY7ZhciTa0nps=,tag:yRMuJW3yjBV2C3LDWVdEHg==,type:str]
- key: ENC[AES256_GCM,data:FR3QHEd6FFk9,iv:fmWDfiL122FdaZT9SpwqCCiJDXtFRLR31+SjbI7+HbI=,tag:++WE+3RwdDbXTyV2xu2UIA==,type:str]
operator: Equal
value: ENC[AES256_GCM,data:IqKHhgroaK0=,iv:bvg7kLaVQEsH31xHH1rCW29dWlWDlDsAMAmR1cX2nS4=,tag:B77eeEjVnRwk/feuPyi2Kw==,type:str]
value: ENC[AES256_GCM,data:/BSFTcoWqMk=,iv:gNvCYESHtDwF/2ZeUwFj2h3LjpHbCaO97YK/HvYl9t0=,tag:HAZPhDedb5E0D5SlHEoZwg==,type:str]
effect: NoSchedule
- key: ENC[AES256_GCM,data:QYGmJBgxhqC2L3UvGYyJKKWDfzSFq91w1ifwNn9rofPnBqL0Ug==,iv:+tI3xw51LqinZnEOi7Lgao9liOD8KT8rOGNtn10qkFg=,tag:fJhk0PifHEyFlX4j75Sklg==,type:str]
- key: ENC[AES256_GCM,data:/Qrec35ekNu97Vt5uezNfI+siytofle4uTm/YXt5KihmcTerPQ==,iv:/+hLpM20CFSVjG4KEpjv7vvem4XlAYt5RM2mAykaG1g=,tag:GfXvuHlBsWGAlpvSjaHMWQ==,type:str]
operator: Exists
effect: NoSchedule
affinity:
nodeAffinity:
type: soft
matchExpressions:
- key: ENC[AES256_GCM,data:qRInCqtomABFKcUFHzDQe2qmzJY=,iv:9cMrKqqpIMtNCUqkIWaCr5YGNoK6zsID3xAKp34q1kM=,tag:Zf1ZjGwCgnaOqTq8Hr++Fg==,type:str]
- key: ENC[AES256_GCM,data:8IL59mlYJP3mmE7F9MoKdztW/Vo=,iv:e6rBLp5lXnktdY9wHN7sMTteDQcUZoPuKW2rx7fuSlM=,tag:u7McVTzQIfW6oXILHuhFvw==,type:str]
operator: NotIn
values:
- "true"
# (postgresql tolerations are set in the postgresql block above)
sops:
lastmodified: "2026-07-25T12:48:03Z"
mac: ENC[AES256_GCM,data:noPba/BIxyoUo3sFfwXuMaZwwSMNADgWcwGaIoQchdzu3KodtWRHk5xJ9wy4VGelOuy3gS79j9ErDnsn8I1v05Bqqlrig99Sch5Jlu1UQpeUQtUjq9S7d5BQ0f3QdeU4iP2v28JovI3gBNHEIlZiueV6xYUrpeoKzS9ukrBtJsM=,iv:XRmbI5hX0OCh4I+7MmnI9LyBLJhf2CsfHgvsNaEUWgc=,tag:Ym5JeVRqTWHWl8qSQAFh0w==,type:str]
lastmodified: "2026-08-26T19:28:03Z"
mac: ENC[AES256_GCM,data:XucjlNYeRTBXcSqA8Tmnl/Oy7MtdVM6ZrYnv50S5nytSx2wjKxdoJtGzvVIrRTNPdt86J+jNhIJKRAlBoEamDWy2+qh38suXx0JSzpoePuqd6mGxvXLXtVje7OynAq742q7rrHiJqffpD8ck+U3xN8Y1rNrAwnEoucFTlreCN/c=,iv:DBY6fMt6cSfvoOrOmFoYWN5DUUMV+I+3zCltZPcGF44=,tag:iz9TMhxLLBsTmwgDYfnIvA==,type:str]
pgp:
- created_at: "2026-07-25T12:48:03Z"
- created_at: "2026-08-26T19:28:03Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ//Sa5nJk6vXXFdf4C5XwsCeRmkSYKSdxJZ2auRzRi+2znv
IqicZh0YENwEX++2NQNtt/jaPFCqWUMEVfncvYceutHzZxDZihkbIL/jKs0h/Hjr
gL/JNRPQbVD4HXLTQ5dOuAfixJXcN9DfYQGyBg1vOtvpKxR4cD4JirA3KyYjtSWf
cYw5fMSalPJ0D3B5pObFZoVJhu8emO3FegSu/tqnZseJuT4mqZqdhpuej17FtkQB
il0tNwBdy9pDFXMxiZoGFtVb5Bii7ZU19MPleBBTFO9nNLXE8rCZ/1tJBtR+XUXE
acglYoZHt3aHAqe1+8iLWAOmE1KkElUMU6/G5yZCpLNNwwgx1jXqGsvITMQQVptJ
RMMKfdNGZSC4mcVXT+Ux/uwvw09DO9Mrbf0tjiTTjLProNxUmY4pPMShwCmGsfTa
si/bZbCui/Jryy02dYWuzA4bpReY+ySMwUGZ9C/0Gn/SBEAdeGQKDhJwgmE6BM1n
hMZOh9YPcGSc0n4a9q/CzFqcQ7T8m1uHgqciFG/zW8A+l8bC1H5uxsUwcYPALLxY
adAZ6XMPZAZ1L/zp3NO/SpdHp7hQVqx+TZOWvmlZ4XiDrICp4AVK8oZAXKw/nrAu
k4ZYVsrBKrkLBIMNmM1mxuhi248ELB7V+kN9zDxQZh87J+F2WXk8D4dMwBfRfYzS
XAGiurXdFcCH3i8O5mmE8QY+ZgdKzyAj7hVw8BvXlOIne8pPe3YuZsp68zwdz8MQ
Gr5oDPaZWhEwFEg+4H+ub5xSIZewY7Ib7FM8bzzfd23vODtZ+0sBoRH+Tq4R
=m933
hQIMA7uy4qQr71wiAQ/9GZ0NMlA2Vyh4RtFbvJvZBZkSHg0L5w7K9txYAcyKr017
uZm/UCgp9ohQK5DKg472EzevniIdGmA907ypV5BAtsXJt6KIkmA7RLTdIw8FwTeL
kJaN0jvijShaV5c1Wt5HlRHl/zVjil7Hokq6Q8fp4iz+MJ7H3U+5c6ElT2xE7YWf
H2FYKsQlgHAjd3KlQvECsn4fOO7wKhIs9qNhvA5c503gyOtRq2cR5IiFQiwzKJLq
5tzN4SROfWUrO7FfqXlkqsFNSn51SAOtkzqc2osbXmZH6s84ZJzgAow3SVZ7/ZQb
NqK1CfLauhL/RBb3sgKZBOX8zhC0gdRb0NKlothMx4sjo0Ao1fMlzgc/FpDlnf8U
CSVbE2u3K2Q4tUKEKCmIOdLzT+uthnQSvumXbt5d7Hj73wBM56P2sZGs244+SF11
SStk9yiYkQSwoCDS/0MHS9cP7p2Jx0dtcqrM1g94ACGJFLbplOuqQh/UYDofi7XA
8UOePz6KRevU7tJZ0bV44j3BMPiSHLwJA8Xlld38pTVxx4hbWeffW3DcjZpLXJqW
Dyz3EtGv9mHB0MoGzj1Djlhb01wNj1g/VHqDonugp0h8DDx4uwZHXiiF8c5qOdTy
z/q7lljNT3FxiwYEmAs3yo+RmxbVSLMzSUu/p37VtCOJigB0+1WPbg1wFWwd67HS
XAF1CpLZiCr1ZaCRbNBT6CXuyUwjYeSd+OXq3MTOGZD81xvYKxbs4mRdzSlpxCQ9
tObUsjTWMf/0q3zPU0mN74hNLrz7Z5ywol/j1IMKpy1B4Q8CuQmfL0zjyMY6
=3su6
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*\.ya?ml)$
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*PASS|.*SOCIALACCOUNT_PROVIDERS|.*\.ya?ml)$
mac_only_encrypted: true
version: 3.10.2
@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- certificates.yaml
@@ -30,11 +30,14 @@ data:
@nook-mg host n.vhaudiquet.fr
@nook host nook.vhaudiquet.fr
@sse-nook host sse-nook.vhaudiquet.fr
@inbox-nook host inbox-nook.vhaudiquet.fr
@gitea host git.vhaudiquet.fr
@flux-wh host flux-webhook.vhaudiquet.fr
@photos host photos.vhaudiquet.fr
@umami host umami.vhaudiquet.fr
handle @authentik {
@@ -52,12 +55,18 @@ data:
handle @sse-nook {
reverse_proxy traefik.traefik.svc.cluster.local.:80
}
handle @inbox-nook {
reverse_proxy traefik.traefik.svc.cluster.local.:80
}
handle @gitea {
reverse_proxy traefik.traefik.svc.cluster.local.:80
}
handle @flux-wh {
reverse_proxy traefik.traefik.svc.cluster.local.:80
}
handle @photos {
reverse_proxy traefik.traefik.svc.cluster.local.:80
}
handle @umami {
reverse_proxy traefik.traefik.svc.cluster.local.:80
}
@@ -86,10 +95,10 @@ data:
semery.fr {
tls /etc/caddy/certs/semery-fr/tls.crt /etc/caddy/certs/semery-fr/tls.key
reverse_proxy 10.1.2.212:80
reverse_proxy traefik.traefik.svc.cluster.local.:80
}
buildpath.win {
tls /etc/caddy/certs/buildpath-win/tls.crt /etc/caddy/certs/buildpath-win/tls.key
reverse_proxy 10.1.2.212:80
reverse_proxy traefik.traefik.svc.cluster.local.:80
}
@@ -5,7 +5,6 @@ resources:
- namespace.yaml
- repository.yaml
- release.yaml
- certificates.yaml
- caddyfile.yaml
secretGenerator:
- name: caddy-values
@@ -27,4 +27,4 @@ spec:
patch: |
- op: add
path: /spec/loadBalancerIP
value: "10.1.2.152"
value: "10.2.2.4"
+149
View File
@@ -0,0 +1,149 @@
# Caddy Edge Proxy
replicaCount: 2
# Listen on standard HTTP port
listenPort: 80
# Enable HTTPS
https:
enabled: true
port: 443
image:
repository: caddy
pullPolicy: IfNotPresent
tagSuffix: ""
tag: 2.11.4
service:
type: LoadBalancer
# Cluster (not Local) so any node can forward to pods on any other node.
externalTrafficPolicy: Cluster
# Disable ingress - Caddy IS the edge proxy
ingress:
enabled: false
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
# Caddy needs root to bind to ports 80/443 and write runtime data
# Using restrictive security context causes "operation not permitted"
podSecurityContext: {}
securityContext: {}
health:
path: /
port: 9999
# Extra volumes: TLS certificates from cert-manager + external routes ConfigMap
volumes:
- name: vhaudiquet-fr-tls
secret:
secretName: ENC[AES256_GCM,data:HYQb37rKxMqxFTsCz5kw6qY=,iv:dI9uqUVLLqPv3a5vwz1vowTvO9WduQaXqj7XZREd7oA=,tag:mz257AC3pvubgzOMxbHfrg==,type:str]
optional: ENC[AES256_GCM,data:k9FVxw==,iv:XMAGop2PvSGD1R1cy6qqE39bsIAOFIqGzTnwDmYRhHM=,tag:7zZAwSzRWWiT9Y2iMWkI6w==,type:bool]
- name: wildcard-vhaudiquet-fr-tls
secret:
secretName: ENC[AES256_GCM,data:2OUkq/AMuv2wQyIlLPS3bSRrnV1mvDR6vd0=,iv:1e9HC8FFC4vo7GjCnJyNjF05R+Js41ONy2in5a+/doI=,tag:icKdtLhvQ40YI+KCE+6fXg==,type:str]
optional: ENC[AES256_GCM,data:b+zvMw==,iv:QyU+T1BGZenO/nO8wq6R+KkrT/I6ZXIIhAnf5npFhvw=,tag:4UPyop81BQu4zxhZmK2n+Q==,type:bool]
# semery.fr certs from cert-manager (OVH DNS-01)
- name: semery-fr-tls
secret:
secretName: ENC[AES256_GCM,data:cLzhXgUhrwgIMACU1Q==,iv:DJ+6mjtjYmWxNcHl1gzeoifpcFCJsXiOXeyxEWnRU3g=,tag:7yc2bt6fBWwBuefPY48xyA==,type:str]
optional: ENC[AES256_GCM,data:DTfxaQ==,iv:K7TJjSI/vF3x34SWmwmivYo+mSsUAg9nB94Ui85nHCI=,tag:1/JRBMlb07+aHKEulIYpQQ==,type:bool]
- name: wildcard-semery-fr-tls
secret:
secretName: ENC[AES256_GCM,data:Qq+ybi1kSVdVn9RP/kTkTcw0lkao3Q==,iv:vFmV3YvSNhLizgJVBnq1ZERqDP70onuZDvy/I3joPtI=,tag:AiEW+yh51Dexz3Vha4MPgg==,type:str]
optional: ENC[AES256_GCM,data:0o4ODw==,iv:VwnCs2C1MVUJEfBvNJT1rkDV7m60sNZPdtERo9wWPJk=,tag:oo+liLatrjqEtlrKQyjhyg==,type:bool]
- name: buildpath-win-tls
secret:
secretName: ENC[AES256_GCM,data:SejgJvZY/B7DDgf3YJcxcFA=,iv:bDZWhie17exL+9r9A7Ea/a8Rgpex7nuabVtW60LotJQ=,tag:WxqFbzulxxPgsynqfo5hzQ==,type:str]
optional: ENC[AES256_GCM,data:nBNRkw==,iv:JEvsFzMli7AzUj6GXJlHXOnANm45gnFE/kXrSbBotPQ=,tag:Puss6mCkoC7SGCb86guI2w==,type:bool]
- name: routes
configMap:
name: caddy-routes
# Extra volume mounts - each secret mounted as a directory with tls.crt/tls.key
volumeMounts:
- name: vhaudiquet-fr-tls
mountPath: /etc/caddy/certs/vhaudiquet-fr
readOnly: true
- name: wildcard-vhaudiquet-fr-tls
mountPath: /etc/caddy/certs/wildcard-vhaudiquet-fr
readOnly: true
- name: semery-fr-tls
mountPath: /etc/caddy/certs/semery-fr
readOnly: true
- name: wildcard-semery-fr-tls
mountPath: /etc/caddy/certs/wildcard-semery-fr
readOnly: true
- name: buildpath-win-tls
mountPath: /etc/caddy/certs/buildpath-win
readOnly: true
- name: routes
mountPath: /etc/caddy/routes
readOnly: true
# Caddy configuration
config:
debug: false
# Global options (goes inside the global {} block)
global: |
auto_https off
# The main Caddyfile content - imports routes from external ConfigMap
# This keeps routes in a separate, easily editable file
caddyFile: |
:80 {
redir https://{host}{uri} permanent
}
import /etc/caddy/routes/Caddyfile
affinity:
# Prefer non-failover nodes in normal operation
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: ENC[AES256_GCM,data:oCV218wXg+k2L/edhWv6qpiyiaY=,iv:Y+O2of2NCOvcjSwr0EenGns0BtpT+P6pjCzEZUIMpm0=,tag:kY/WyHJ4Jr5ZLMe6ZcT/Tw==,type:str]
operator: NotIn
values:
- "true"
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app.kubernetes.io/name: caddy
topologyKey: kubernetes.io/hostname
tolerations:
# Tolerate the failover taint so caddy CAN schedule on p330 (small-node-1).
- key: ENC[AES256_GCM,data:K6vJkO2dpKRi,iv:b7NIPKTMYOxNao6KcSJUhsxKNRJ2J3ksEtmXkI8b0So=,tag:pMRmz17upWMTEZjwBRNyZQ==,type:str]
operator: Equal
value: ENC[AES256_GCM,data:4ULPtEoUhgs=,iv:ikqWRqRR9ki35QQ6VnMEzOgT0/e+5DggGP8w60BhW/Q=,tag:MW9lX8miIWb9nnbc0woZTg==,type:str]
effect: NoSchedule
- key: ENC[AES256_GCM,data:l7abu6ywKFevJdJod2Af2bj7XSfBJATL7UnfiUHrRJoCjBsl9A==,iv:xnUvzVX8z4doC+mQs1r0rNCSqaZ8KlXxr5Ee9FOFPjI=,tag:mnqCx9NSMSyeYwz57QFQIQ==,type:str]
operator: Exists
effect: NoSchedule
sops:
lastmodified: "2026-08-26T19:28:03Z"
mac: ENC[AES256_GCM,data:gn90e5Gjq5/CraT7Cl43DVMIQukD798faKGbVO5IJlbpAuTwDrhvqnnojFq4R7LEEETtedpR3MRyqcnbfSWVruHoysebycL7EZJkiy7H36JmzQAOWKusshMF9kOyZIV6+AFfz8As/Mu4pF1p5+3jmgy6oOJn7Ewm0C930Gpa3gs=,iv:cf1UC/2NGBHtQgx6h8vRpMjeJRaAvG7ZznhErn2b+cE=,tag:3Ule+pq7pZHWA7NqhlgfPg==,type:str]
pgp:
- created_at: "2026-08-26T19:28:03Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ/9FKZhqwE2RZcfsIeMOtAkOTf/4aEbrSzsHbEO8DP8V3Ct
rQBu/v8y1Hcu3fVU/OjVk/7QbEBjPNu1AJST55DBIWktnYUgSo4fIujvG54/hqwM
9u0iuA1EcqVzGDa+vLSqgmi4Oxbujs0Ytn7uQrefqkdAOjltKqvknebI9EBdSRUi
GjVFwysR6jHmIVf9S64vu4VsjfC7ju9MBYZniaKsJ1GOBhIjUZ6ogkYs5S2E5PJ/
zE8cn79x61YLX74H+BAqnFcxbprtsCwMJPgyerfgijV6d+JpwT/6mp1VUrLe9Zz7
WEd/lVMlIcwnYCtIDAvuURvMP2OebWplr95d5V1Vb5Yywnl3M0pwkqL4dRiJISvk
N2rBQYvDfXBtJA7yTAkJ3PymrECKoFs6nspEBie/kDJmdRGv8s2aajzTTQ1qLAkP
FeJe0TcowjCCWMxk4W5DEoCh+PUA1HVo+/KmHjnIVgzdgxaeqT90VXwN8H7MPPeu
LKE01+Guue821h7GykkIhe9sf3nMGbI5rOiCcsVtgu5bODkRk8jXpXh1qdRAliuq
uddjy1mWEfdUHNBj8YxvZ8WOU7h9FyZjsYZB96n9du1vqcuuP5eTJDVuvjjtDuTK
fbXYQbxwA5j4akyI4AKJYLA0Y/lcSXc84r6q8IA52nZz6uQZExbkoc7PPX7Q/ufS
XgE0CWRS+0tk2oVANMVU31UrCvitttezjR6sUSAINh122a5kcmOfJzLlB2OqVKc5
wMAyvOYccrQMrPDX1WJE7agDOaqGUQcwuFnvqpHhe8q9Yg1uOUU4sK1R8A1Qs0Q=
=wlYf
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*PASS|.*SOCIALACCOUNT_PROVIDERS|.*\.ya?ml)$
mac_only_encrypted: true
version: 3.10.2
@@ -0,0 +1,50 @@
# OVH API Credentials for DNS-01 Challenges
#
# OVH API credentials with the following permissions:
# - GET, POST, PUT, DELETE on /domain/zone/*
#
# The secret MUST live in the cert-manager-webhook-ovh namespace (cert-manager),
# because for a ClusterIssuer cert-manager sets the webhook's ResourceNamespace
# to the webhook's own namespace, and the webhook looks up credential secrets
# there (see ch.ResourceNamespace in the webhook's ovhClient() function).
#
# SOPS will encrypt the stringData fields on pre-commit.
apiVersion: v1
kind: Secret
metadata:
name: ovh-credentials
namespace: cert-manager
labels:
app.kubernetes.io/name: cert-manager-webhook-ovh
app.kubernetes.io/component: ovh-credentials
type: Opaque
stringData:
applicationKey: ENC[AES256_GCM,data:qOGxuFHguxe7e7pVfd1eiw==,iv:CC5CMc+VTL8aW4injRN2GxQvWf4nobGuQYhuUytHDfQ=,tag:3l8srdCgAtnz/fWqn+VrdA==,type:str]
applicationSecret: ENC[AES256_GCM,data:tvj/Km80zHBLA+gLqjCA0wKh9y/+g20O+kE2zZzEDVM=,iv:SKfeoThkwFbNGjNdQQByqAk/+dbyCLyzft1eXVh3a3o=,tag:qHoR2ZqEkfulKzdE/GvZrw==,type:str]
consumerKey: ENC[AES256_GCM,data:gGTsvDEy0DZvTiHP2mdghBrDbwE5hmkNDJtDf4CJEPc=,iv:EgvG8TmZuY4hWs3YD4y9zpJv/Ndu5tnGLs+hIMWvZU4=,tag:R4tSbVvJjkyXe/N93CRSSw==,type:str]
sops:
lastmodified: "2026-08-26T19:28:03Z"
mac: ENC[AES256_GCM,data:xNUZ8stxMx7Y2ggmjBaF5FX0NtC18JJcaDgU52V4b+pnG72t8+P83DkYY3Xr6gWJfmS9wFNs3vZ8TJ+nvVP0C62zoN9cmC0BolJrTOyQ2rpoUu/0Xj+Tbfiwnmbm76yZ+SdQJLYg3n7fNG/g6fh88/BUERi0NAVil228ExFFliE=,iv:2Nu2LaqVYqM5WchoPqoHkCJcXypGHskDjLHFYRC4eTk=,tag:2H9FSAQ3UNGSxSx3WhUD1Q==,type:str]
pgp:
- created_at: "2026-08-26T19:28:03Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ//XxGw3gzr7UtuMakZqWGp6uZ5mZ42KscvHpQCZchh0wZb
01Dq6HLl6EMwu+fpnfkOU05SxozkaKvLw+xzTX4TExbfE3GBTjpJ5R4e/aj5B24M
iw32oy+y2jCIzMS0PKxIkhIJrClv5hRSZt5dVDzln5sOapXapE5iLpM/glerIwXk
i4EfntjzNhOUFCbwnH2F/s1ZKmwZWw88GNff26aAIDOhNiEyB7kz0s6Gr575cKvw
CdZrHDtfl7ZoP4JiozNXzXF65+YnIiG5kli1A0GVF/9XUeqgXTUHYJKvdGcHFAqs
NysLbdsoppDJUUpqWvU1gS0X6PifZWkd3Sv0LDaoV7TIa8UWHZMbyV9W/1NiGSjt
VVBO+ezQgpSFbEVixz1WEDyD9MPBAvWq+PS2QQcUc0aep8xRqoWAe1pojjs2k0DJ
2vcFkWmdj0RVngNvw3rBAxrYY8DtqrNOjc0B9s+2ZqIN9TT+9IWaS65Xh0wRMZoy
Ntxr7oyG3wicA8YFRH3WxLJiTqOOeYYgc+Qltds7fb79hJScdXNxbC8mFjo9zOUV
bnHSQrjj/Se6tzSpZt7yF/+3aBTAUsOfOXHO1md/ydjCBpO6eUYU+T6m+buIJ6F8
M7kov+/x5on8k9dcNjkwdVuOztIuIXGUaJ41idrGKOSvtAjW0CGO3VU67e76NwnS
XgGVAwNds2Bfs8mQfmKdhvCrJnPxqtN29z5fguTMGTPqMncsx62mhdwI6tgAgEdD
qEX+tRkjpgoa8yO3gkvu7J3+oQ2HQ5mOZaSyl/Xz4ALP4+MOEHEiMNWcDmotq/Q=
=BT71
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(data|stringData|.*key|.*crt)$
version: 3.10.2
@@ -12,7 +12,7 @@ spec:
name: cert-manager-webhook-ovh
namespace: cert-manager
chart: cert-manager-webhook-ovh
version: "v0.9.13"
version: "0.9.16"
interval: 1m
valuesFrom:
- kind: Secret
@@ -0,0 +1,46 @@
# cert-manager-webhook-ovh Values
# groupName must match the ClusterIssuer webhook stanza
groupName: acme.aureq.com
# cert-manager deployment configuration for RBAC
# The webhook creates ClusterRole/RoleBinding so cert-manager's
# service account can create the "ovh" ChallengePayload resources
certManager:
namespace: cert-manager
serviceAccountName: cert-manager
# Pod configuration
pod:
replicas: 1
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 100m
memory: 128Mi
sops:
lastmodified: "2026-08-26T19:28:03Z"
mac: ENC[AES256_GCM,data:jzaxMCQB6eTssTai71HIAzLwCktDSllQagk6dnz6KI509kZeM1mUyL/Mti25R1XpsTZv2aGWzG968CivR2q35wiP7CoRptHx2xPku63ljLihojp2Z2aklcM5uwcZRJIkSsZeVk2m2rWHE1hz6SiLIGbtmY8HMz7fBeLryni8SgI=,iv:yglyVdWx6Zy+GiD/guAWexolRwQXTAkKslI6zn0RUcA=,tag:6XvZb4RJCY+UtZGvOPxzNw==,type:str]
pgp:
- created_at: "2026-08-26T19:28:03Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiARAAl7HETp1m0KX0RwxpIW1kBIjhWCpDp2ynTTC1+Q/95A8t
JHYNTaeymQQLubEl1lB3EzgAnrvFIOlOW6aX9Vbrv9UPhnoEabVH0W6VWF7JFFcf
ZvKnkYJrPtlAu5dyN606ifXlZw5ZE1wP7hASgano96H8Irfxi+8JE5k0gwTNFlUu
cLDhjhwcnlxCIxf/akQpw4ic+aHvj2bp2ilaxBuo8YtVZUX21My55rjZpWxf4ekn
oq7kh7UD/dt3lZ8qWi9Lk7aGXrzjdErqIt3ESefKUQtqQEGVrOeZ4mnkU4KONa6R
FcLGTjuXl5Mily4U6cQJwkkyxJZyZLAVp2Phw86LeytZtFgtj/YsEk5NiTSl2a+3
qzbMySigD8q6lVAu/WO6r+KXitZaMNodekJh54xgxer2ZUBekOpzafHawbAXO47e
ZVKnNW/aYs51Vt8NeDGqF0KiUIGPqLN2ffT1t0SfNqZF9MYPc5rKX18/cfom0Lo2
80Qwb1l47DiZbht6AQ0oMzFdK3SJp1jnXPMd6ZNOSMj3TfRq9WZydNlEeBPiFG+i
0ASkPHuERyiogaZlsGgi8gKA4iM55wULCBXIsPdVc4cIbU7MpNpP0icsQN5WRV8L
vOUKjAntXik2ZHY4bhHd3Ty7/FVVIgi2M0Wi5/6mTn4ftb2DMyoqVKBYHwm5iqfS
XgEt7iRIfcYwAy9WKnHayTfk3Is/dnBTaMp/PKSCUwEELqnAgmpbLcZ/8lNm6wEi
Azo8CgLer0P7YHU+GbbONeQV29VrkjqHkA0imPFCHaAWxfSNE+55IctMgk+oclk=
=Ko1N
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*PASS|.*SOCIALACCOUNT_PROVIDERS|.*\.ya?ml)$
mac_only_encrypted: true
version: 3.10.2
@@ -0,0 +1,47 @@
# Cloudflare API Token for DNS-01 Challenges
#
# A Cloudflare API token with the following permissions:
# - Zone > DNS > Edit
# - Zone > Zone > Read
#
# Base64-encoded:
# echo -n "api-token" | base64
#
# This file will be SOPS-encrypted on pre-commit
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-token
namespace: cert-manager
labels:
app.kubernetes.io/name: cert-manager
app.kubernetes.io/component: cloudflare-api-token
type: Opaque
data:
api-token: ENC[AES256_GCM,data:YdjAxeCqpOuRapujdleSZ4mcqWtnIDOiT4ttohorOX4/pzI1DdytmXSYpISiTpnh73i/+CEr5OpWXeHr5yOZ5lJMf0gN9usR,iv:pNZNxVnWvvMfcOxo0fXyefiI6vW6nIjdFsP/0+el0p0=,tag:V4Zc6zW0PGP5YX8Edd407g==,type:str]
sops:
lastmodified: "2026-08-26T19:28:03Z"
mac: ENC[AES256_GCM,data:ovnp+gcpIuMHG3MC4Y9SWpZtj4ilWM3XvJOyuyoecm4DIytQgSAW+lUrqREeOh6MleKF1dT2u3cO8pnqjqn4YaMeHD8dXAV57iBM1d070ySDP8EG+O/eLEjzd/NINglf3PEaBSK9yzemhPkTUlUqVdBn+kHNLX1y+WC+GU0tcaI=,iv:RQUcZ7RU75itmhuZW1NmpH17MHhtd0HI8isSRIKqzCA=,tag:qEm0euMGQOvRjtBS9Sra1A==,type:str]
pgp:
- created_at: "2026-08-26T19:28:03Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiARAAi83x7L6cxjIV0HETlf3e9oXOQErINQ+VQPJ8Q3VrdoLR
Q5t2CVMRRKz6dF+D2NvV4+dxCi4NNNf8qRteSmUeQpfhsonSlOW4ArpgzgFjc5M+
HO1jD61C++8ISSTssd6HaifLUeCmvIBJyAtr8BWuXDFuVyRCB2EEQ2wcs9X+HGLz
5ertIJQe/rvn3HQVojNwpjVmHR68hiFrF4b4yxNHz7kTY9JRKBzeqflQ4OCz5mdD
uXOxR2RukPoxTwjWLcxm791J3iTo9TQxMjI3JaJcmNXiPCy161a3ZDUGVBA1bY+w
apa7K8wKobjhVYjZ9ScxA6qS4dQ2Iktchxw/BUZLI8Vv2LT8UrJcUqQS2MoRZCa6
XpN7gKAnSDE0RoPJxHlX/2kV3bsVABLlaTS0Fx399iYvHJt3MyNLBIQfr2nMUzLJ
0pP/3nBqEo1iUMGfKJhOWIQK8lG0dieVkxInXrM8K75dNqm/gBsPGLwJIdT4GVaX
+vkzud5uZNExq1ajXHi1JMG4oCRdXDINoUVLsU2RWHzm41M1vU1UQDUGxPuc4lkb
OUl/4yCJ9UQ0wqLdw0O/q2ooay48sH08nNRMsfVIKL+us+ymrBC55VoHIDBwluUd
ztVPDJ6He1oNTcKnF2cxaCTrbWPODVTYnAy58DprjXxSRF+3bcb2Ky8loG3ESzDS
XAGUpWuWTvFtdvfTe1fmM5jeCtjZNpw6B79akcQuCbnQkKsqg9JRGwIfV048pYTR
BWN6UY+oFVUp4arpHbVdi283VsNtFIKr8ibs9t089Q0Yd/K4F9GPU5vTI6q4
=emCy
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(data|stringData|.*key|.*crt)$
version: 3.10.2
@@ -0,0 +1,92 @@
# Cert-Manager Values
# Install CRDs as part of the Helm release
crds:
enabled: true
keep: true
# Enable DNS01 challenge providers
extraArgs:
- ENC[AES256_GCM,data:WklAooZiEmMv0a4HuSkzUryQQcZxBMw+EQ5CohnkZVcLOs0e0yTSDA1ZWMzzcFN8+lJv,iv:dCML/TDEhl5iUfF4wHlpsdBiAxUETyvDAsQl3G+45Gc=,tag:tARyDDKB5sNuLOYcWfxEkQ==,type:str]
# Resource settings
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 100m
memory: 128Mi
# Tolerate failover nodes
tolerations:
- key: ENC[AES256_GCM,data:SCjKoTipNgof,iv:nvp9VrxZsJWbunDoIzExh40P9e/FIQqBsbPbH8LkooI=,tag:/zF3Vf42U5Pdg4d3akd0xg==,type:str]
operator: Equal
value: ENC[AES256_GCM,data:hkez1UBYhjA=,iv:KIko5RclWRZHxRG3Er3u7IflHX5ybrcOgBpOTCEGw2M=,tag:Ms7+y3q7Pjawo6L3N3PvlA==,type:str]
effect: NoSchedule
- key: ENC[AES256_GCM,data:jwng5gCK5pG/bVnybci4V6pWxhegwclLt6jFv5hAP5AonwYeTQ==,iv:E55c6dKHf3ixsBjJhRaz2lqpFRuI3CqjYKSJ0baMIDs=,tag:kE+hKUtHG9T3rgeU/aCbcQ==,type:str]
operator: Exists
effect: NoSchedule
webhook:
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 100m
memory: 128Mi
tolerations:
- key: ENC[AES256_GCM,data:T6EcMGNo6uJB,iv:slnPrxrfTn2NDZ4nd3bpKl+G3aQEmPIq0/FtcHsy6iE=,tag:8GkbKn2ZA0zKOiDvo/X7FQ==,type:str]
operator: Equal
value: ENC[AES256_GCM,data:ARfB33JtZvw=,iv:BLlUEDenivmTr/dFddReGwCDZp9yyVRMln68F+AqGyo=,tag:Q7aJUz9TIzntGJhN6KG32g==,type:str]
effect: NoSchedule
- key: ENC[AES256_GCM,data:pXbWnDdllf4mhbc9E1FpG9SmI2iXjszjTdOm56K4QMkpHlZbcw==,iv:UNVYfOnIu0LeDKq9etRTwn3nCa8u9GdZ40etEYMICMc=,tag:mFRkt3YtmMwF1bRo0SWuLQ==,type:str]
operator: Exists
effect: NoSchedule
cainjector:
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 100m
memory: 128Mi
tolerations:
- key: ENC[AES256_GCM,data:nENalnOT52oI,iv:Q//78lGQhi74smaqzPLD5rQoIo3/1UaoSHhaenym4do=,tag:keej4Md40ilDQw/ogZ8VXA==,type:str]
operator: Equal
value: ENC[AES256_GCM,data:P87X+3Q4pIs=,iv:HvJ0o/rvCeEzEunH7cYKSQwrVhE4g6mk3JVifZff6Hs=,tag:UzbzzoK1LIx6Thuw65zLlw==,type:str]
effect: NoSchedule
- key: ENC[AES256_GCM,data:2QkmTBIHIoKZ9E2paPOE9xjm84QkEhj7at+yV3muPALoiKDVWg==,iv:T1YgyxogBbf2k3GBsQ8Zax3kUtqnmk1aqIjoWz2yC74=,tag:aVri3xZ8PZeFBaG7+YQCXw==,type:str]
operator: Exists
effect: NoSchedule
startupapicheck:
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 100m
memory: 128Mi
sops:
lastmodified: "2026-08-26T19:28:03Z"
mac: ENC[AES256_GCM,data:+wrZiehApZjOfmDBophPBkMy6BXaOspsLeWbGDJ4cde20QrLrM1CkPfNM+1E4Wg0+gRw2M8nPOP5HVzAPEkdDSn+RLZQwshCPMjQJweEQz4c/8bIy2KCsKAKbwDKRYaHkgGY344QVASsY9mKgeoYssKmKQ+BxE+vSeHhTqAIOjo=,iv:vsQhlx+g6B9lkDfPiCWNdZb3/zN2vh9C5tICdmMSpq4=,tag:f8Q8tReFgmqlKR8FlOZTcQ==,type:str]
pgp:
- created_at: "2026-08-26T19:28:03Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ//cnoE4ALPvnSzdhSweCbII9A/D8HeP+AM0Pd6AbXxTCOZ
ZOwpBmFUDmA5+RaUheJYbYYEiy31JTjUTlIi3/r5A/42DtmN9EZlUh0B41nMVtwV
w9xX937BdPSBEPqpYkA24kBuk4N2p2zHfylCS50z0LH08w5+M9lFAce5GIlHzitn
QoBwCvTCV/D9X2hbQ1aqPmGKl739TOSO1QYfwEhWjfZj/fOr0FCwvrSPssL0v2l6
1M6KssKp0CaV4JOOPVCeeNYRDroo2KqmGaHbsKTUNWtMoN8fx1w+GiEwPd90UBMM
uk/etwdDbUw0QMXuPaRucyTVOjXuGmIDFZsCPkwL2xDEppZUVuY+hnbIw6Mfih11
gI+IlQiSByWAICSdJa2usSTtx10Ck01hoOKblE84rq9xzyf/JgnakpPNsS2iJtFr
8AJLsLyCLdov6th8O3bCvTYvpYGBBREEz5xlFdohhpWMNd9YXjZ/PglyAyUBhsUi
eMvPFguwH7UQc2sZLmXbgrN6vyvnYdqPVhNXZvJqpXbsw/v2evlvZX06J3Tv4xjp
XA8+MRrHKnznSgtgZM37fM8KfJRA7u8AWD7rbBeow/hXBF8CaplLhbiTSy0vSnYq
bXoxw7x1LfzE3WPm5CcBeENFbVi8f2Hjxd1Vz26E2yaFqD0afFpB9bDjisXzK6vS
XgG+x5v87myoWx/uC9hXfEAsmB2Oe7EI+04qCpZIDo7ZGfDO+dj23oU/c6K7P3aU
JjkNYSpVlHVvzSqbkFVgYV/+8XhVvDVCC16cFA3VoGYk3EvZqMXT52dP77EyW/U=
=io2w
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*PASS|.*SOCIALACCOUNT_PROVIDERS|.*\.ya?ml)$
mac_only_encrypted: true
version: 3.10.2
@@ -4,7 +4,6 @@ namespace: stalwart
resources:
- namespace.yaml
- repository.yaml
- certificate.yaml
- recovery-admin-secret.yaml
- release.yaml
secretGenerator:
@@ -17,31 +17,31 @@ metadata:
app.kubernetes.io/component: recovery-admin
type: Opaque
stringData:
username: ENC[AES256_GCM,data:CYm0+Kw=,iv:UdgReqdb8GdoOfv1ZEW/7BAvY3vV88httj3W976eV0Y=,tag:PPrDQY/mo0RcJiz/cmxFSA==,type:str]
password: ENC[AES256_GCM,data:r0mPJ4qKIhAWDw==,iv:L5+OKTznQgDUgqttHwdW0X66vz+JPTqWdwYPGklCuj0=,tag:WNOj7ZjC6Lx76UlPsgSDhg==,type:str]
username: ENC[AES256_GCM,data:AB2zGZo=,iv:DShjxCtBagfnqm3oXLj3EVkV/bNEqnYXGJVSN4Jwd+M=,tag:++ig5p1ec7WZU3G6SvOnsg==,type:str]
password: ENC[AES256_GCM,data:v0HBWQEiGkpslw==,iv:OUEKmtKJVnXuJwMTyST8ycz6cZ6qvipWPfmxDyCQ+cw=,tag:whNSOquceAh0LxzH77cQdw==,type:str]
sops:
lastmodified: "2026-07-02T20:57:39Z"
mac: ENC[AES256_GCM,data:lIVOaMsFV9F1/yLvykA3LH5ukn9PIba6N8cE9RGdcFepM56tBYlY6fbkcKTtojyAkoYov6OCjgTsOkMtUzRdGES4Zti6zHB3cTPal8bJCf5cAfYnGFRcQaASIkVjNZkQSJ2pDRP4rZqioCHuj2/a6uJZ4hhtSpxrECYbpzD2Gk8=,iv:31fXHsWH1ZP00Od5DSxgYPuw87NqQNfWl4vFtoouIHk=,tag:u5cJn231VT2ZTmlcdpBz0g==,type:str]
lastmodified: "2026-08-26T19:28:03Z"
mac: ENC[AES256_GCM,data:4ts11OGRul28LVfQT6g6tnLmpSaMchaO06j3iYecak7yRqXnzsYyWu/LYweybCgQ20zeyZOnFU7rM/VUpkafueu+KmVrw+HsE1WOzjI4g911BGNEz6DOK8MliFtaYitFwRzJfZE4Fh/M8Wos+aGEs59IR1FsiB0DHbdd57pUYT0=,iv:XkiIh3vRCkKzQ3LNYsTa6HkBYOhblK6hWqiw0O9ufVc=,tag:QMS69yIJDfvM/BnMFvUk4g==,type:str]
pgp:
- created_at: "2026-07-02T20:57:39Z"
- created_at: "2026-08-26T19:28:03Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ//fYBIypexVfQJn5BxVCRgZKRBcYw78XSoPjFYWFyk5F7I
UFRQKtdZOVVhgNHtFJOVyBvl1sAmmzAt3xq3L+Z5bvtrUfZ33tTp7ty+MmSmuutS
wquSh4NOHUYENGvo5pWsgVwQDj5bI2qUq4L92aedpB2XJycb7/Df7BWFKNMNgWdt
l+Hj9HEJWxmFjrz1MQJEL2r5WOx9/hK7uatbDTXVFPqyyW1aCM5XOkKErTuc3Avn
8tNNlvP1aqhI/2dHfOSZ1l0/PHhdi3RBmGa3BfAZUXEseBEesIK/EaJZXMjQYhF2
5tAPQ1irqg8LLv9mhrUD2mWaUigcuZ1EeyfZFvNtY/noF8fyZny1jra0sDe4CmQP
7uyP6CNRWPCikutUw45oxtw+/Us5Ld8xzJxhDEm0e+8FFiAK/SFSOx57JbjNzoCj
dqHU3UIzyp9VVZohqW7xdHOW64fgDI41BDKBsEiKraLnZUoXL2Lx0lnjxayJqVsD
2pX9D5YXzmtwFvUU5ZpcCzUWFu9MVxSfp6HdKvocGdtpSz7J23PQvHtkv20GxJYd
J45RYGgekuJ2EXc9kPaCuSex/0BKtYybOk5ANRv2yGeUZlc6EoW8/GZ4sHXPY6um
tt1DdIsMNMjAU68EgRkhmQnFAkZixJVdDR3u4MNXFUr0WdVIqzjFBavyrkcK6HjS
XAGhFNWdk5DNZ1ChGrMKEnYCZEB6XNkofa7S2xAomEoxyuCq7X2vbfBfqDQ/Rtcf
kSx0TpIOSHxefSFMduPz90rDqdZgUW0D3GND0PD5XRFFiJxxdrRYPux9MDMd
=Ef8e
hQIMA7uy4qQr71wiAQ//VOfCE4MQxdlmnzN8BYlmlouOePL7E51T4ERhLpTrCpZF
5rLhni/YdGDyKtPOm/9nIeF6zr5FCateZdArJx9QVT7xXIs0Tvl2xZpRvDRxHwyt
o+zFTUUaUUj8b0V6ZR0jnjPJmhK/iwpTbG4aCBe1rWl+bUwHt25KWtgAfyMtdJ0j
SUcuOyjcc/hEUuZeoDNEwxbbWsInA54/hfUjCJU9iLUzC3zc7k+5PpsZfKh4ABIA
qSj/+p98a3VrcZLc5VG89z9T0SunBfCX0AmIf2O/xUhUT08IBfGti9XyE2TC7vMQ
WxX+sYB4cK+tIDcWAMWipq46iRVhWNS2qjdRS8tUpwoVsVLZSrQiUdIxBtzlJqrm
toN36T1b8Vl3XS+LD53oWDJ54YnnSV9oxmBjwNaZ5dGVkz+FoBNqLab8FZ8GZQS4
bFJLjbuq4hxvgD6U74PG/feLnxWXjJ6w7t66VqJndo+yqTMSzedM31iNqqp1norm
LGjT5QhFkR5NwHdAN1S9AlmMm9tGxIE2GAHKHzPyrvus47PfgaidtA7KyiNtC88X
SnSIF9uT0VYR0MjD9nGlW+VAP08KU+9+vqpVDoqE0CbI8hCl7lMOg5Eyzh44Zp42
YyRLDqib/IeUKxob3/L4Ia+TWXOp/dEFbfOoKw+CreYUrP8ltrVk5qozlMy9TZfS
XgEJztLQbB1pqJEoBL7bA0HOU4VXEyOddAj9BW7hZcV/xk2DwUJjDhcozAjVY0dQ
W68Oc/Fm8/c/UHwpBRSfmxofR2kDIygYS3AQavyXfogLWfdulEbDpulqsmu0VLM=
=oe+v
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(data|stringData|.*.key|.*.crt)$
encrypted_regex: ^(data|stringData|.*key|.*crt)$
version: 3.10.2
@@ -14,7 +14,7 @@ spec:
name: stalwart-helm
namespace: stalwart
chart: stalwart
version: "0.7.5"
version: "0.7.18"
interval: 1m
valuesFrom:
- kind: Secret
@@ -7,7 +7,7 @@
# Container image
image:
repository: stalwartlabs/stalwart
tag: v0.16.11
tag: v0.16.20
pullPolicy: IfNotPresent
# Single-node RocksDB deployment.
replicaCount: 1
@@ -19,9 +19,9 @@ pushShard: ""
# with these credentials on every cert-manager renewal.
recoveryAdmin:
enabled: true
username: ENC[AES256_GCM,data:kpf88Vc=,iv:k2kGcGlH0jQkLmb35V4+IIrBpDM93PaG6atcO/SLDB4=,tag:qZIR2LZlv1g0XBkEh0y8qA==,type:str]
username: ENC[AES256_GCM,data:/BGEPaI=,iv:QTV3fDckhrdxI0k43vUY/6Hr15pCcEQostuxcAHEF+g=,tag:nSGTlZJuclizN2AKtfGG0A==,type:str]
password: ""
existingSecret: ENC[AES256_GCM,data:DnjFoj8VNeqHmwM/KVebjOOHvYHPgZQ=,iv:JWBs6OeZzsa+8uJt/FjptI6t+tf+CRQDKA7149rBg1o=,tag:M4CXA2k8M65mbSUF0mnGvQ==,type:str]
existingSecret: ENC[AES256_GCM,data:P/5gC7128OrelglEo5iTGTva45BOI3E=,iv:W0QngumMdOo/LFXdUrMN236CIHaOh8N9cj1wMEtfr3Q=,tag:5QLyu1Yd31YCZfRRYyK+2g==,type:str]
usernameKey: username
passwordKey: password
# Recovery mode suspends mail services and exposes only the management listener.
@@ -40,7 +40,7 @@ bootstrap:
# certificate.yaml (letsencrypt-production, Cloudflare DNS-01).
mailTls:
enabled: true
existingSecret: ENC[AES256_GCM,data:e8rzv2mvlpoZR/vMfd5sgNuYLDvptQ==,iv:qIQfpHxAOameSdDzOHh89n+RIOd9CcJcl0oRumSHAQQ=,tag:xwbQR5Jabvz+lEju5zuW2g==,type:str]
existingSecret: ENC[AES256_GCM,data:Mi40TeV+sRmZaEBMsOI0qgXWkMyNmQ==,iv:ExlgVMe+CONDWLmZY4uze+jhVvXN92zb2ptcLCor3Dw=,tag:4VQ38SxY28yR7kp1u69auw==,type:str]
certKey: tls.crt
privateKeyKey: tls.key
mountPath: /etc/stalwart/tls/ingress
@@ -77,7 +77,7 @@ mailService:
enabled: true
name: stalwart-mail
type: LoadBalancer
loadBalancerIP: 10.1.2.143
loadBalancerIP: 10.2.2.5
annotations: {}
# WebUI ingress. TLS is terminated by Caddy at the edge (wildcard cert), so the
# path is: public -> Caddy (TLS) -> Traefik (HTTP) -> this Ingress -> mgmt:8080.
@@ -120,28 +120,29 @@ podSecurityContext:
type: RuntimeDefault
containerSecurityContext: {}
sops:
lastmodified: "2026-07-18T14:22:17Z"
mac: ENC[AES256_GCM,data:JjN4ziOnd65U8AzI9ZnMiPUBiYFGqjGjM3HJ7XoSJuJ+fgYjOH+WX/U2IAfSeqEIMkzvP435BxKGoylrwEVM1k5v07slul5zEclPZglphDjiX+md403lVDtYEXdCSo0+3nqv1DFEQDkKItEEEz882sZBbhMotBHhgcd41RSA1aY=,iv:MaSmisJoj3aobpMw1HGgEOktegX2LtOaXLh3601xgvc=,tag:acWtTiu4ub7GDNp8nM/yVA==,type:str]
lastmodified: "2026-08-26T19:28:03Z"
mac: ENC[AES256_GCM,data:Fh5vxhnPiSRaC/xMV06GwoNAqfiZYJHFj3xKrWzMwau2aC62JTDkEpmm/UN7w4ILQk05xjUkcoSJF5IcKT6+gjkLRVt8qwiarJDZ3SbwM11x7rm4m0wBTJIMeytq1h68l5mQ9i5yW5bxnBNDpUqaAAmq/Ev0/+6lspXw/kfJTUw=,iv:Tg5ZYPd2bpTN/gu99oJEcl0aKiNtX5xca0MUfzCXILo=,tag:2IKyAEuTjp8QhhUaNb1+5A==,type:str]
pgp:
- created_at: "2026-07-18T14:22:17Z"
- created_at: "2026-08-26T19:28:03Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ/9G7UtHO7Ux0YNAPlnkVmU5BI+crzwbWPhdaUZFf5dmCkg
r67EAi/DjqFHR9Ew1Dhpn0InTA/Ld+mGZAAbWeP7xhIEQ+AqACmm/Oxgf3IkHKzE
P7dvco6lQO50W/m3fiU0Pv4A7w3Oq+AdFHcPr3UBi8YGYLgkCbzLs2r9JNviCJsl
uuvz438g92aXfa5JcyUjzxtxKFjzHrZ8seDx38X4fveS/mROpRqiw+G8aQ0BlXDM
9wfiQtiM9CcuahPUWopv4RCOjuqrSc14sxv9xRGsYt1YZFxZ/4Q7rqM+HXBsFp4u
8r4MgE+EflrhKp1aWPGnSn2kalDy3o+yFuk7IhWsrSKsNIU4j1J5xCfhliey+kNJ
387cVf7Bjw+iqoy+qiV7Q7XGip6NgF8WwSudZhznv/pS6LL5H5yHaKxjz5rny/TQ
0upK///2YGuiE66sBb8h2sqzIgr6hZecvb2VdY7BQX4FCo2uAmxTEh+h1fHlervc
i/03B9kNSjP5fSufhE9lsLl0oZgaFIKSpkzLlPdy6z0X5vDEXJGSL+qFudo9RKtf
aaEwaQ+I+snmhWyBeeywxpdyRE5g3xhRwuwaxp7zzVt5ykCnyrZIPvzaSxu/QjaF
jCUmvPp0ZLzAB2xY9AMwOHIrym9lPmcBEEqCiHywCauOQzsGJE3vLF8x3/nzZnvS
XgEE9z1NxK8o0ntL+JZO3+GYvm28Hyw0eXgDJbjJ+tlBYeWH8lfBUOsk2V485OJZ
4SDNvxzxpyF/4RJY4P4KR7HgwDC8gOCsDgqcyn1s4KzECXyQlqmrXxOrL8cFRhY=
=aeJw
hQIMA7uy4qQr71wiAQ/9FX7SR8uKEyIvQYbNb8JdhsMCjbioQc/JMvx9EWjqhIwE
WTsntkuZ0874eXO4c/WicYNHtxNmeqHfyt6ByVq7F8qIsHb19u33qkc67tjGG7rh
svebMITMYgfqdHOmblLMCAHVoB0tI21nyPbf4POUHUtsP0IogUogY70x2a1wefdS
RpH28+VIcKQjK2l7JKIkQ81+CHy4RV50/CzVUOojSOeNPDGtsT+5I3sf7dHuj2jF
Ab5MhqXICRDlTj5AXLNfGuymILVjKWytRe5dR02EpuvlLUkHH1hztZQN9TaV92sj
kcEz6Qfft/PudcG4iZj6yqbjAoZjoSGEOwH/gRONa5dAamG/QGXFpaf7z6pPKHal
TQPidrFADuI7upnb+1xK0rF87FQON+p4py57/H5E+0FueSqXs0MiHgc4mL06IdqR
uoOODfpp4G66uxAqBxs6YvEPYxT9yib/keUQli7gFPwRjsZixm2hiwCnDPNR11gZ
HjgH3XN9Ba+uELuNIRtU96uWc6HZACrq0PmCvLKgvamDd0LbK7yD1cX7OiD4XCP4
G7dllNeAgEUY2ha3xE93cMBDirSlN0LbV+NYFm2MR2IluI1DkaVDqLa3ajoP/7Qp
2zop6Mp3QEKWjZrS27eEjHHIcjGqbfvaOI1qXCHGw3elM0XkbKtaMmqV4rwjwjLS
XgG9T3aqe9VCK1wyHAdsHsSgjVz+44YgoOXT2HnC4nSNej5xRZBEIfF8YNnCBiY8
sLfjNlnSVe6+x1H8VZn4NrXGOz/kwiWpMEMEQuCIbqPJt45GM+GtC1f/gj8eMyo=
=IbSO
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*\.ya?ml)$
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*PASS|.*SOCIALACCOUNT_PROVIDERS|.*\.ya?ml)$
mac_only_encrypted: true
version: 3.10.2

Some files were not shown because too many files have changed in this diff Show More