Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot] b602510256 build(deps): bump bitnamilegacy/postgresql
Bumps bitnamilegacy/postgresql from 15.9.0 to 17.5.0.

---
updated-dependencies:
- dependency-name: bitnamilegacy/postgresql
  dependency-version: 17.5.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-08 00:20:26 +00:00
180 changed files with 954 additions and 4798 deletions
+5 -15
View File
@@ -5,6 +5,7 @@ updates:
schedule:
interval: weekly
directories:
- "/docker/gitea-actions"
- "/docker/home/esphome"
- "/docker/home/matter-server"
- "/docker/home/mosquitto-mqtt"
@@ -12,11 +13,10 @@ updates:
- "/docker/home/node-red"
- "/docker/home/zigbee2mqtt"
- "/docker/infrastructure/mail/roundcube"
- "/docker/infrastructure/mail/stalwart"
- "/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"
@@ -34,7 +34,9 @@ updates:
- "/docker/production/alexscript"
- "/docker/production/buildpath"
- "/docker/production/semeryfr"
- "/docker/production/vhaudiquetfr"
- "/docker/tools/excalidraw"
- "/docker/tools/notesnook"
- "/docker/tools/obsidian-livesync"
- "/docker/tools/stirling-pdf"
- package-ecosystem: "helm"
@@ -44,23 +46,11 @@ updates:
directories:
- "/kubernetes/code/gitea"
- "/kubernetes/code/harbor"
- "/kubernetes/home/home-assistant"
- "/kubernetes/home/zigbee2mqtt"
- "/kubernetes/home/home-assisant"
- "/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"
-21
View File
@@ -1,21 +0,0 @@
name: DNS
on:
push:
branches: [main]
defaults:
run:
working-directory: ./dns
jobs:
update-records:
name: octodns
runs-on: ubuntu-latest
container: octodns/cloudflare:latest
steps:
- uses: actions/checkout@v4
- name: octodns-sync - production
run: octodns-sync --config-file ./config/production.yaml --doit
env:
CLOUDFLARE_TOKEN: ${{ secrets.CLOUDFLARE_TOKEN }}
-3
View File
@@ -9,6 +9,3 @@ terraform.tfstate.backup
kubeconfig
talosconfig
# Ignore rendered Talos machine configs (may contain cluster secrets)
p330.yaml
-5
View File
@@ -16,8 +16,3 @@ repos:
entry: generate-docker-swarmcd.sh
language: script
pass_filenames: false
- id: validate-kustomize
name: validate kustomize build
entry: bash -c 'kubectl kustomize kubernetes/ > /dev/null'
language: system
pass_filenames: false
+1 -1
View File
@@ -3,7 +3,7 @@ creation_rules:
encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*\.ya?ml)$
pgp: DC6910268E657FF70BA7EC289974494E76938DDC
- path_regex: .*.yaml
encrypted_regex: ^(data|stringData|.*.key|.*.crt)$
encrypted_regex: ^(data|stringData)$
pgp: DC6910268E657FF70BA7EC289974494E76938DDC
- path_regex: .*.env$
input_type: dotenv
+24 -12
View File
@@ -1,3 +1,10 @@
gitea-actions:
repo: homeprod
branch: main
compose_file: docker/gitea-actions/docker-compose.yml
sops_files:
- docker/gitea-actions/.env
esphome:
repo: homeprod
branch: main
@@ -33,16 +40,16 @@ roundcube:
branch: main
compose_file: docker/infrastructure/mail/roundcube/docker-compose.yml
stalwart:
repo: homeprod
branch: main
compose_file: docker/infrastructure/mail/stalwart/docker-compose.yml
traefik:
repo: homeprod
branch: main
compose_file: docker/infrastructure/network/traefik/docker-compose.yml
observability:
repo: homeprod
branch: main
compose_file: docker/infrastructure/observability/docker-compose.yml
squid:
repo: homeprod
branch: main
@@ -53,13 +60,6 @@ sshportal:
branch: main
compose_file: docker/infrastructure/sshportal/docker-compose.yml
fireshare:
repo: homeprod
branch: main
compose_file: docker/personal/fireshare/docker-compose.yml
sops_files:
- docker/personal/fireshare/.env
gramps:
repo: homeprod
branch: main
@@ -153,11 +153,23 @@ semeryfr:
branch: main
compose_file: docker/production/semeryfr/docker-compose.yml
vhaudiquetfr:
repo: homeprod
branch: main
compose_file: docker/production/vhaudiquetfr/docker-compose.yml
excalidraw:
repo: homeprod
branch: main
compose_file: docker/tools/excalidraw/docker-compose.yml
notesnook:
repo: homeprod
branch: main
compose_file: docker/tools/notesnook/docker-compose.yml
sops_files:
- docker/tools/notesnook/.env
obsidian-livesync:
repo: homeprod
branch: main
+8 -18
View File
@@ -7,17 +7,17 @@ Personal home production environment mono-repo
### Hardware and operating systems
#### Dell R740
<img align="left" width="100" src="https://vhaudiquet.fr/public/github_assets/homeprod/p330_sff.png"/>
#### Lenovo ThinkStation P330 SFF
Specifications :
```
2* Intel Xeon Gold 6138 @ 2GHz (20 cores, 40 threads)
144 GiB DDR4 ECC RAM
2* 2 TiB SAS SSD (mirror)
10Gbps 4* RJ45 network card
H730P, 16* SFF 2.5 drive bays
SAS9300-8E external SAS card
NVIDIA RTX 3060 12G graphics card
Intel Xeon E-2134 @ 3.50GHz (4 cores, 8 threads)
64 GiB DDR4 ECC RAM
1 TiB nVME SSD
Intel X520-DA2 SFP+ 10Gbps network card
nVIDIA Quadro P620 graphics card
```
Running as single-node Proxmox
@@ -80,13 +80,3 @@ This setup allows running multiple applications, either self-hosted applications
| <img width=32 src="https://avatars.githubusercontent.com/u/26692192"> | Navidrome | Personal music streaming service |
| <img width=32 src="https://avatars.githubusercontent.com/u/102734415"> | TubeArchivist | YouTube archiver |
| <img width=24 src="https://radicale.org/assets/logo.svg"> | Radicale | Calendar and contacts server |
## Docs (internal, using this repository)
This repository uses pre-commit hooks to automate tasks like file encryption and configuration generation.
After cloning, install the pre-commit hooks:
```bash
pre-commit install
```
-16
View File
@@ -1,16 +0,0 @@
providers:
config:
class: octodns.provider.yaml.YamlProvider
directory: ./production
default_ttl: 3600
enforce_order: True
cloudflare:
class: octodns_cloudflare.CloudflareProvider
token: env/CLOUDFLARE_TOKEN
zones:
'*':
sources:
- config
targets:
- cloudflare
-28
View File
@@ -1,28 +0,0 @@
---
? ''
: - octodns:
cloudflare:
auto-ttl: true
proxied: false
ttl: 300
type: A
value: 83.113.30.49
- type: TXT
value: google-site-verification=BvFkK7orKeezgxGcdPiGa67PUm9RPI6ZjyyykhSJ24A
_acme-challenge:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TXT
values:
- 15ks77ymwx2rPrwai5lV0KbySgDrN6AwDqt8e3LNc3Y
- ypJ7zk6-P0TPrdp4Ag2BTJ0NIaY9XNdndqlGOLaFACc
www:
octodns:
cloudflare:
auto-ttl: true
proxied: false
ttl: 300
type: A
value: 83.113.30.49
-442
View File
@@ -1,442 +0,0 @@
---
? ''
: - octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
- octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: MX
values:
- exchange: mail.vhaudiquet.fr.
preference: 10
- exchange: vhaudiquet.fr.
preference: 10
- octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TXT
values:
- v=spf1 a ra=postmaster -all
- v=spf1 mx ra=postmaster -all
202412e._domainkey:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TXT
values:
- v=DKIM1\; k=ed25519\; h=sha256\; p=jln+6mPae83WbgR5FHA1yw0exmcGVmkEwNx1ZpISv7k=
- v=DKIM1\; k=ed25519\; h=sha256\; p=zue5tDdPhC91KvjPj28r1F3RoQNiQamYahX371tPmd8=
202412r._domainkey:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TXT
values:
- v=DKIM1\; k=rsa\; h=sha256\; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3Pzzsp4MALfuXDoYsmXotp5mCidcKsDeWycjCMyhGvBDjfaX8l0ZCPemPOjD+uMPhbZV7e1RkzIt6A0qmutDixT1Dup3uhYhnyblp4Gkx1e85vaIncE1V2paJ85EOsDH/4rcGtdcPQfANbPw9LlqcdU3S+X9KpYaMf2DqPPfYa7emhJxBklUMymY06lssqb7+3ltLujGH8J+qNIYJmPa0s1tf2Pu1/opBKkk1qeUyF/wLmW0UTwNB3UyRCSMwR4DzburfHfE9cSNcm/STzrWcPmDnro2E3S69pTmzECU0g2xRqBBq3eYfQO8KxtGGQy63KUqAAhN5D8n9BZ4+TbD5QIDAQAB
- v=DKIM1\; k=rsa\; h=sha256\; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs7vM7V1LhJJ6NRazIFyZ5bGseKOABnwBwzNspD+hdeVa7bbE38L+xfbhKKopXwQCCV8lJ+BgDpLJQvTYgRR+6UjuYm7/b/BX8qewPZUGphamkNRExBalsMAxAf9zeMqPUfpjDEKggten90RdrklQCnn5ebyUcTFk+uKfImqn3S2L34vSHfuCtsaZExu8mCych2Q3ZBdx3gsAtmMsmqrAJqBOlF/d/1xVloNMMWBIUNY9NYdC+ZspTvoakIrTOIzHCfoiG3lzpWLM8Du7GWd2umpXOsM4RpJL1vTRDOWjnd25N63L3GlCnAfr8Yu2K77A2PvloOIwZXYrLFOB5S7jxwIDAQAB
202508e._domainkey:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TXT
value: v=DKIM1\; k=ed25519\; h=sha256\; p=B25PCl1mN4ajiGlVW/CZnWlZzfUxKaB8EhIal4bAHEo=
202508r._domainkey:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TXT
value: v=DKIM1\; k=rsa\; h=sha256\; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1PMbJghh91KpUfghVLVuDiwyo3ChtYiphsR6Z/YJcCGcoNIInH4SJCfL43M5WDboWLzOw8ddGCZLERgY6AOt7LjpzXJpH8ReeZjBNvo57ZJLV9PYdr7Ejrj+ZB/9GAHk4WChWBWIPtbOvFrKyRUNABI2c5fVNPp2c57im+G10rgpCOrp1Y34PaNYpqKu2YyLpkWyAZc4kMUsuxKd9iSIDUCBPKibmQaKt1xJk8Wo1fqsXgVqRJ1iAvTFRyEjGkcA1g1m11mO7aXNuJmr7J41i6MqSwG2vQEPpadqJdqA9TkK2HcMeVV9Tn+4XLxpAHN31e96kXET+9CZlUW1lrSyfQIDAQAB
202510e._domainkey:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TXT
value: v=DKIM1\; k=ed25519\; h=sha256\; p=ieEhnbQlDTWNsK8s38f392ef/Fvfrj511kHz9OoN06c=
202510r._domainkey:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TXT
value: v=DKIM1\; k=rsa\; h=sha256\; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvlO5KyPBJAYmGnIoaerGzNlWiiWCOiKaluIauTmRKArSDfDafDiy+k30mwtGRn4i4Q8EAWgplG4Xd3fRYCZsjsEna7QV0GDHsX5fY3eFPOnzdU0M5bbXne9UIztej+qUuPTq5BIZhCCNboAIKCKXbRdAJ+hVGnPkPUq+JjfD1EB2E4aoZ/ukoA+QYfq8A86X2TU1WQKNARRsQvGob1No1xyjtztu+1mt8FC15q/YGYfrNt9GxgPnWlsp2PuHgLblX8COiJMejWJ8DgRTmLc0ncEI3qVVpNICDzl0I8+cvkEgJxF6QA4EKB/SjzlfRooHbf7zwfxmcc5ndTsxix9NawIDAQAB
_25._tcp:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TLSA
values:
- certificate_association_data: CC6230E3A88A173D11C7F614ACFB4FE7B57A01F649ED1ADEE5F953213D4C6607
certificate_usage: 3
matching_type: 1
selector: 1
- certificate_association_data: 731B7CD6FA08C4A56060172BF8E30563919139F16265A38EC35B2A1F41CE2B6B
certificate_usage: 3
matching_type: 1
selector: 0
_caldavs._tcp:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: SRV
value:
port: 443
priority: 0
target: vhaudiquet.fr.
weight: 1
_carddavs._tcp:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: SRV
value:
port: 443
priority: 0
target: vhaudiquet.fr.
weight: 1
_dmarc:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TXT
value: v=DMARC1\; p=reject\; rua=mailto:postmaster@vhaudiquet.fr\; ruf=mailto:postmaster@vhaudiquet.fr
_dmarc.ligory:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TXT
value: v=DMARC1\; p=reject\; rua=mailto:postmaster@ligory.vhaudiquet.fr\; ruf=mailto:postmaster@ligory.vhaudiquet.fr
_imap._tcp:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: SRV
values:
- port: 143
priority: 0
target: mail.vhaudiquet.fr.
weight: 1
- port: 143
priority: 0
target: vhaudiquet.fr.
weight: 1
_imaps._tcp:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: SRV
values:
- port: 993
priority: 0
target: mail.vhaudiquet.fr.
weight: 1
- port: 993
priority: 0
target: vhaudiquet.fr.
weight: 1
_jmap._tcp:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: SRV
values:
- port: 443
priority: 0
target: mail.vhaudiquet.fr.
weight: 1
- port: 443
priority: 0
target: vhaudiquet.fr.
weight: 1
_mta-sts:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TXT
values:
- v=STSv1\; id=12286879188751086068
- v=STSv1\; id=15827089775314309854
_pop3._tcp:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: SRV
values:
- port: 110
priority: 0
target: mail.vhaudiquet.fr.
weight: 1
- port: 110
priority: 0
target: vhaudiquet.fr.
weight: 1
_pop3s._tcp:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: SRV
values:
- port: 995
priority: 0
target: mail.vhaudiquet.fr.
weight: 1
- port: 995
priority: 0
target: vhaudiquet.fr.
weight: 1
_smtp._tls:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TXT
value: v=TLSRPTv1\; rua=mailto:postmaster@vhaudiquet.fr
_smtp._tls.ligory:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: TXT
value: v=TLSRPTv1\; rua=mailto:postmaster@ligory.vhaudiquet.fr
_submission._tcp:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: SRV
values:
- port: 587
priority: 0
target: ligory.vhaudiquet.fr.
weight: 1
- port: 587
priority: 0
target: mail.vhaudiquet.fr.
weight: 1
- port: 587
priority: 0
target: vhaudiquet.fr.
weight: 1
_submissions._tcp:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: SRV
values:
- port: 465
priority: 0
target: ligory.vhaudiquet.fr.
weight: 1
- port: 465
priority: 0
target: mail.vhaudiquet.fr.
weight: 1
- port: 465
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
authentik:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
autoconfig:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: CNAME
value: mail.vhaudiquet.fr.
autodiscover:
octodns:
cloudflare:
auto-ttl: true
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:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
flix:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
flux-webhook:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
git:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
jupyter:
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
ligory:
- octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 82.64.154.58
- octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: MX
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
- 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:
auto-ttl: true
ttl: 300
type: CNAME
value: ligory.vhaudiquet.fr.
n:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
nook:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
notesnook:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
overleaf:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
sse-nook:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
umami:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
www:
octodns:
cloudflare:
auto-ttl: true
ttl: 300
type: A
value: 83.113.30.49
+11
View File
@@ -0,0 +1,11 @@
GITEA_INSTANCE_URL=ENC[AES256_GCM,data:PYjmpgDEvPEC1S7MrN6d91IUBnGbFA9Xag==,iv:m7YQOMnuEoT5wDyy47aaTqjJG+dhqTJKf5i3hQs6GwY=,tag:2ldKTNRqdJEXTxr3uAyLLQ==,type:str]
GITEA_RUNNER_REGISTRATION_TOKEN=ENC[AES256_GCM,data:RDnENtxQw80C7SwmMZV2DTlEx4+uvzVMy95leGb/1RR6egc6S4xWnQ==,iv:wThZ2+qukJqC+ApvXC9GBdneXJ00jkkTyq+2VXSDG+w=,tag:KygPnxauOpaI1goZ4+uf3g==,type:str]
GITEA_RUNNER_NAME=ENC[AES256_GCM,data:HvNmmQyKxk16WQV8dRfPOfCO39w=,iv:z1YuNWvglBYaXQwZXjMzXD4ZN2d7c3eD9GdSaG1maNY=,tag:FtX6wG47uTGjTQ8UNvGfcg==,type:str]
GITEA_RUNNER_LABELS=
sops_lastmodified=2025-09-16T19:22:00Z
sops_mac=ENC[AES256_GCM,data:JIp7wyaIsy2Jg9p3ybHAljkDn8vpDRHtf7Zm2/M4exe6CbWCRn1jGMle+SnKBv2DKVciquQ9B9cKtKnVCpEAQOceZ1WakwS/mCmjYTIHqcvm8/vst1BYiL1Ovbw2dDstzWo8g+UTKAmVC7E0TJ01vAbsOab+fVacKLHF97pBqW8=,iv:5tcuJntPXrWCeNTGQbXzLaGZnCc8rr+gKG+UTRBNUaY=,tag:g7EYMAaOmwjKFYfz1ID5xQ==,type:str]
sops_pgp__list_0__map_created_at=2025-09-16T19:22:00Z
sops_pgp__list_0__map_enc=-----BEGIN PGP MESSAGE-----\n\nhQIMA7uy4qQr71wiAQ//c0J+b0XwnMbLlQku3tAEutXuEkQPMMrdOpPYwrua9nNu\nSVPBSiamnTeoaP2kM5lcaQ7HUaRLiS1qjXNVPsnAdkGPPID3SxUJzUo7Ca/JOq7e\n39ihqetWAcn9dNDofTxVKyvKXhXKGaDFy2LhaKugj4tkx6qdMA/XAldvRD6ik1jK\nAZjl2xGYTvZ+XgTGtFs6u3Z9ugD6Q3yPjKRSfeIO8NPT5OFFzY70wqlZflxcpupD\npnsvXQkAK1Rnz6F9+dh6jJYYijTdEe9Q0i+0Uy3q+wMsf8KRWs4ARD05DpgIOnUA\nG0s2kdOOlvqoJ/m2fSV7vkIcCvCwhEirn5kfrdUGi3ENazh0g3vpppAfE0ynZdSo\nDiXI7dzCwMxYi8edieOhK3RrOn8bx7B8F1WE+mHL6StQmD2G+xfvgtKlsEJGY2Ed\n1CpMZSQ0TwFx58fYiK+HsZrwAw/3YVzPWryaYvJ6P8QnY3oJOJihSYGRMmyH5WRo\nle1Rxd+Lrt1UnWyZQ7rpqMsYiIzihsNgNix/2wS1R9R1wRFXPdNDfzjrv1BGm/aJ\nOOqUFo6Hd3jEwYcSsG7mbe+hCAAXoJjZSU43dVzeZ0k5ls/lpOjqjQrZZLgz33uF\nNVNRAKTYD2y+/mQ4vpDUsHhu5rtjxh8u1CJf0++q1W/w+Z4ooq5hcNm3ud3DHYjS\nXgF1JA9ThTS+Hs1fV5SFzGMyFMFGeiTVJeww26R+1Vws7fFwbyAYugOqAgkiNkIf\nS2dsxlH1TRjBq1XD4GYk6P3VDUU5UyxG/5XiOexGEVSxBL/wg6TwpyL1hjvgc9k=\n=fmOe\n-----END PGP MESSAGE-----
sops_pgp__list_0__map_fp=DC6910268E657FF70BA7EC289974494E76938DDC
sops_unencrypted_suffix=_unencrypted
sops_version=3.10.2
+6
View File
@@ -0,0 +1,6 @@
services:
runner:
image: docker.io/gitea/act_runner:nightly
env_file: .env
volumes:
- /var/run/docker.sock:/var/run/docker.sock
+1 -1
View File
@@ -1,6 +1,6 @@
services:
esphome:
image: ghcr.io/esphome/esphome:2026.6.4
image: ghcr.io/esphome/esphome:2025.11.3
ports:
- "6052"
networks:
+1 -1
View File
@@ -1,6 +1,6 @@
services:
matter-server:
image: ghcr.io/matter-js/python-matter-server:8.1.2
image: ghcr.io/home-assistant-libs/python-matter-server:8.1.0
container_name: matter-server
restart: unless-stopped
network_mode: host
@@ -1,6 +1,6 @@
services:
mosquitto:
image: eclipse-mosquitto:2.0.22
image: eclipse-mosquitto
container_name: mosquitto
restart: unless-stopped
ports:
+1 -2
View File
@@ -1,10 +1,9 @@
services:
n8n:
image: docker.n8n.io/n8nio/n8n:2.26.4
image: docker.n8n.io/n8nio/n8n:1.122.5
environment:
- TZ=Europe/Paris
- N8N_SECURE_COOKIE=false
- NODES_EXCLUDE="[]"
ports:
- "5678"
networks:
+1 -1
View File
@@ -2,7 +2,7 @@ services:
zigbee2mqtt:
container_name: zigbee2mqtt
restart: unless-stopped
image: koenkk/zigbee2mqtt:2.12.1
image: koenkk/zigbee2mqtt:2.7.0
networks:
- default
- proxy
@@ -1,6 +1,6 @@
services:
roundcube:
image: roundcube/roundcubemail:1.7.2-apache
image: roundcube/roundcubemail:1.6.11-apache
container_name: roundcube
networks:
- default
@@ -0,0 +1,40 @@
services:
stalwart:
image: stalwartlabs/stalwart:v0.14.1
container_name: stalwart
networks:
- default
- proxy
volumes:
- stalwart_data:/opt/stalwart
ports:
- target: 25
published: 25
mode: host
- target: 465
published: 465
mode: host
- target: 993
published: 993
mode: host
- target: 587
published: 587
mode: host
- "8080"
labels:
- "traefik.enable=true"
- "traefik.http.routers.stalwart.rule=Host(`mail.vhaudiquet.fr`)"
- "traefik.http.services.stalwart.loadbalancer.server.port=8080"
volumes:
stalwart_data:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/stalwart/data'
networks:
proxy:
name: proxy
external: true
@@ -1,6 +1,6 @@
services:
traefik:
image: traefik:v3.7
image: traefik:3.6
command:
- "--configFile=/etc/traefik/traefik.yml"
ports:
@@ -8,8 +8,6 @@ entryPoints:
trustedIPs:
- "127.0.0.1/32"
- "10.1.2.11/32" # nginxproxymanager
- "10.1.2.152/32" # caddy
- "10.0.0.0/8" # caddy pods
providers:
docker:
@@ -1,71 +0,0 @@
// Grafana Alloy config for the docker host (replaces Promtail, EOL since
// 2026-03-02). Tails Docker container logs via docker_sd discovery, attaches
// container_name/compose_service/stream labels, and pushes them to the
// in-cluster Loki at loki-internal.lan (LAN-only Traefik Ingress on port 80).
// River config produced by `alloy convert -f promtail` from an equivalent
// Promtail YAML (so component names and argument shapes are guaranteed
// correct for Alloy v1.18).
discovery.docker "docker" {
host = "unix:///var/run/docker.sock"
refresh_interval = "5s"
}
loki.process "docker" {
forward_to = [loki.write.default.receiver]
// Parse docker json-file log lines
// ({"log":"...","stream":"stdout","time":"..."}).
stage.json {
expressions = {
log = "log",
stream = "stream",
}
}
stage.labels {
values = {
stream = null,
}
}
}
discovery.relabel "docker" {
targets = []
// Strip leading / from container name.
rule {
source_labels = ["__meta_docker_container_name"]
regex = "/(.*)"
target_label = "container_name"
}
// Compose service name (if label is set).
rule {
source_labels = ["__meta_docker_container_label_com_docker_compose_service"]
target_label = "compose_service"
}
// Log stream (stdout/stderr).
rule {
source_labels = ["__meta_docker_container_log_stream"]
target_label = "stream"
}
// Mark the source so dashboards/alerts can distinguish the docker host.
rule {
target_label = "source"
replacement = "docker-host"
}
}
loki.source.docker "docker" {
host = "unix:///var/run/docker.sock"
targets = discovery.docker.docker.targets
forward_to = [loki.process.docker.receiver]
relabel_rules = discovery.relabel.docker.rules
refresh_interval = "5s"
}
loki.write "default" {
endpoint {
url = "http://loki-internal.lan/loki/api/v1/push"
}
external_labels = {}
}
@@ -1,81 +0,0 @@
# Docker-host collectors for the central observability stack on Kubernetes.
# Managed by swarm-cd (see .swarmcd/stacks.yaml).
#
# node-exporter + cAdvisor run locally (scraped by vmagent below).
# vmagent remote_writes metrics to vm-internal.lan (LAN-only Traefik Ingress) ->
# vmsingle-vm-victoria-metrics-k8s-stack.observability.svc.cluster.local:8428
# alloy tails /var/lib/docker/containers + /var/log and pushes logs to
# loki-internal.lan -> loki.observability.svc.cluster.local:3100
services:
node-exporter:
image: prom/node-exporter:v1.9.1
container_name: obs-node-exporter
network_mode: host
pid: host
command:
- "--path.rootfs=/host"
volumes:
- /:/host:ro,rslave
restart: unless-stopped
labels:
- "traefik.enable=false"
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.49.1
container_name: obs-cadvisor
ports:
- "8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /dev/disk/:/dev/disk:ro
- /var/lib/docker/:/var/lib/docker:ro
restart: unless-stopped
labels:
- "traefik.enable=false"
vmagent:
image: victoriametrics/vmagent:v1.131.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
command:
- "-promscrape.config=/etc/vmagent/vmagent.yml"
- "-remoteWrite.url=http://vm-internal.lan/api/v1/write"
volumes:
- type: bind
source: /root/homeprod/docker/infrastructure/observability/vmagent.yml
target: /etc/vmagent/vmagent.yml
read_only: true
depends_on:
- node-exporter
- cadvisor
restart: unless-stopped
labels:
- "traefik.enable=false"
alloy:
image: grafana/alloy:v1.18.0
container_name: obs-alloy
command:
- "run"
- "/etc/alloy/config.river"
- "--server.http.listen-addr=0.0.0.0:12345"
volumes:
- type: bind
source: /root/homeprod/docker/infrastructure/observability/alloy.river
target: /etc/alloy/config.river
read_only: true
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/log:/var/log:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
labels:
- "traefik.enable=false"
networks:
default:
name: proxy
external: true
@@ -1,22 +0,0 @@
# vmagent scrape config for the docker host.
# Scrapes the two local collectors, forwards everything to the central
# VictoriaMetrics via the LAN-only Caddy route vm-internal.lan (Caddy proxies
# it to vmsingle-vm-victoria-metrics-k8s-stack.observability.svc.cluster.local:8428).
scrape_configs:
- job_name: docker-host-node
static_configs:
- targets:
- localhost:9100
labels:
# Distinguishes the docker host from K8s nodes in dashboards/alerts.
instance_source: docker-host
host: docker-r740
- job_name: docker-host-cadvisor
static_configs:
- targets:
- localhost:8080
labels:
instance_source: docker-host
host: docker-r740
-11
View File
@@ -1,11 +0,0 @@
ADMIN_USERNAME=ENC[AES256_GCM,data:8ngfC8VHpaaGCQ==,iv:Ze7ThfWmAWj0ZvV3A7Pd+aqAW/pahkTZhdFC/TnAwZ0=,tag:KCFdGV1dEw3e+q6FBgy2cw==,type:str]
ADMIN_PASSWORD=ENC[AES256_GCM,data:UhxEMnqYDyfgffqUf3Q=,iv:VvNX867P+w20Y7laG0R0c4BUw1uICeyF5SU3+waosRE=,tag:JL4GC+UZY3TqSmCq14CTpg==,type:str]
SECRET_KEY=ENC[AES256_GCM,data:uahYXYr4DvavNMTTdcDA0hdp5wj3OLret3fPF1DEc2lis+E7/fe45DWFuhUu8RAK76tuheA=,iv:Lofc+PP7Rtg99l36yOx6bt0i8hg1DJXzwSKQNJCRYPw=,tag:AiUGZOiLyjKItf++Gya+eA==,type:str]
DOMAIN=ENC[AES256_GCM,data:LyJ7RAgrioTltNQ/BKoPbEN8XQ==,iv:IHrT5TkaXuIhkfN/nHcapz4CNBG0t9lbzrHDjp04JLw=,tag:gjSa/tSVEqk6pXrfhjs7gQ==,type:str]
sops_lastmodified=2026-05-06T17:05:48Z
sops_mac=ENC[AES256_GCM,data:wRtDnVQkNsc1MtxSpbuVDuACkCwunYeyYSaQX2Tglm2kwOnx9iCyhuWY6RMYu5nfyJ1CT1kfqeGrGxhJ5uMDee29eLUv844X3hIXwpMT50jHFXEtfKLfRMfqpv9r9mbp2EP9VNDUtPyIwDk5vSjGeaYqEWtHW/q5y9qIrzqqy5g=,iv:UG4XGi3Qo8/nAddY+rzJm1AKIAmJjtR+2bDqSeaVxG4=,tag:SL2rvrxFmMfgyUyMqFIZEQ==,type:str]
sops_pgp__list_0__map_created_at=2026-05-06T17:05:48Z
sops_pgp__list_0__map_enc=-----BEGIN PGP MESSAGE-----\n\nhQIMA7uy4qQr71wiAQ//b6zlRVKrqzzszBJmnOUlfeZd5m2ekYv/zIBr4oxHyn5L\neLLff+N7hjBVSajg9Qg7GBQv7s3DX70vHTpdUP38UEO1aM0l3eU1JCwA4Hdh7Ds5\nnq330vUKhIAd+K8Vv4Ei9YHpj+kgMnt+R780qZUg18D39TAnx36q9b5SKzZCUsks\n3YM+G8pHLRipZhxp6zwhOPHVSnImOFjty4d6JV6Zes9zfslaETgva7p5DIKP0ttf\nI2JRacvL75MMp1USyqGKt7Bpl6Yz4VxY49aea+FxDlbzCVLuBBgZMoEjhPQifQfh\nB6OObmu1cVhECidrMHmqDBNqgKsNLble+g3Le+gJdn/zKxVc+q+cPPuk/JdT8tfv\nZTei6jg66IREZOrZCP3Gt4OB5LbkLdS0NET2CMVAYkGQvGrSC+diwUnFkI+WEh+p\noZhvgp/ytBgaw6ZyNPmvkGkFeFg1/ISpOHkVQ+P6Pnot8h4HvuI/KcBwJRCrtdbg\n+XMpqeQdmCnM04v5Uq1NVqRWHD0yvd7GHDOZCqJPMFHP0M6R+SwHq+8+pgbO3jxt\n+426MvhNKw8xWMtnUIO8sSSkzgOfT6vFXmzQvIawbXvitjGjiElkpmT5Hz3hn1Bm\nnu8CivqLwL4Gs1Uc2m6qHGkvGqxWwcHABWqftAk3VfhmjcFDwAyWROlCuD+A15PS\nXgE1wn9jLesXaiCwzAp4AOstkk0fR2yio4fa9dCeenzuedULNLuCyJfYtSm4QlSU\nvffH4iL8X/R24s6SdPsCIuNnAeKc0P4E55AlOaeZN4HcZzfspVikAZx+bK14JS8=\n=KGp6\n-----END PGP MESSAGE-----
sops_pgp__list_0__map_fp=DC6910268E657FF70BA7EC289974494E76938DDC
sops_unencrypted_suffix=_unencrypted
sops_version=3.10.2
@@ -1,58 +0,0 @@
services:
fireshare:
container_name: fireshare
image: shaneisrael/fireshare:1.7.3-lite
ports:
- "80"
volumes:
- data:/data
- processed:/processed
- video:/videos
- images:/images
env_file:
- .env
environment:
# PUID/PGID: the user/group ID the container runs as. Files written to your
# volumes (data, processed, videos, images) will be owned by this user. Set these to
# match the owner of your host directories to avoid permission errors.
# Run `id` on your host to find your UID and GID.
- PUID=1000
- PGID=1000
networks:
- default
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.fireshare.rule=Host(`clips.vhaudiquet.fr`)"
- "traefik.http.services.fireshare.loadbalancer.server.port=80"
volumes:
data:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/fireshare/data'
processed:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/fireshare/processed'
video:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/fireshare/video'
images:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/fireshare/images'
networks:
proxy:
external: true
name: proxy
+7 -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:25.11.2
restart: always
networks:
- default
@@ -28,10 +28,14 @@ services:
labels:
- "traefik.enable=true"
- "traefik.http.routers.grampsweb.rule=Host(`gramps.lan`)"
healthcheck:
test: curl -f http://127.0.0.1:5000 || exit 1
interval: 30s
retries: 6
grampsweb_celery:
container_name: grampsweb_celery
image: ghcr.io/gramps-project/grampsweb:26.6.2
image: ghcr.io/gramps-project/grampsweb:25.11.2
restart: always
environment:
- GRAMPSWEB_TREE="Gramps Web" # will create a new tree if not exists
@@ -52,7 +56,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.4.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-0.24.402
ports:
- "9117"
networks:
@@ -1,6 +1,6 @@
services:
jellyfin:
image: jellyfin/jellyfin:2026070606
image: jellyfin/jellyfin:2025120105
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.0.4.10291
ports:
- "7878"
networks:
@@ -1,7 +1,7 @@
services:
sonarr:
container_name: sonarr
image: ghcr.io/hotio/sonarr:release-4.0.19.2979
image: ghcr.io/hotio/sonarr:release-4.0.16.2944
ports:
- "8989"
networks:
@@ -1,7 +1,7 @@
services:
wizarr:
container_name: wizarr
image: ghcr.io/wizarrrr/wizarr:v2026.7.1
image: ghcr.io/wizarrrr/wizarr:v2025.11.3
networks:
- default
- proxy
@@ -1,6 +1,6 @@
services:
navidrome:
image: deluan/navidrome:0.62.0
image: deluan/navidrome:0.58.5
user: 1000:1000 # should be owner of volumes
ports:
- "4533"
@@ -14,7 +14,7 @@ services:
ND_SESSIONTIMEOUT: 24h
ND_BASEURL: "http://navidrome.lan"
ND_PORT: 4533
ND_REVERSEPROXYWHITELIST: "172.20.0.0/16,10.1.2.11/32,10.1.2.152/32"
ND_REVERSEPROXYWHITELIST: "172.20.0.0/16,10.1.2.11/32"
volumes:
- data:/data
- "music:/music:ro"
@@ -2,7 +2,7 @@ services:
tubearchivist:
container_name: tubearchivist
restart: unless-stopped
image: bbilly1/tubearchivist:v0.5.10
image: bbilly1/tubearchivist:v0.5.8
ports:
- "8000"
networks:
@@ -31,7 +31,7 @@ services:
- archivist-redis
labels:
- "traefik.enable=true"
- "traefik.http.routers.tubearchivist.rule=Host(`tubearchivist.lan`)"
- "traefik.http.routers.tubearchivist.rule=Host(`tubearchivist.local`)"
- "traefik.http.routers.tubearchivist.middlewares=tubearchivist-headers"
- "traefik.http.middlewares.tubearchivist-headers.headers.accesscontrolalloworiginlist=*"
- "traefik.http.middlewares.tubearchivist-headers.headers.accesscontrolallowmethods=GET,OPTIONS,PUT"
@@ -49,7 +49,7 @@ services:
- archivist-es
archivist-es:
image: bbilly1/tubearchivist-es:8.19.0 # only for amd64, or use official es 8.16.0
image: bbilly1/tubearchivist-es:8.18.2 # only for amd64, or use official es 8.16.0
container_name: archivist-es
restart: unless-stopped
env_file:
+1 -1
View File
@@ -16,7 +16,7 @@ services:
POSTGRES_DB: paperless
paperless-webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:2.20.15
image: ghcr.io/paperless-ngx/paperless-ngx:2.20.1
restart: unless-stopped
networks:
- default
+1 -1
View File
@@ -1,6 +1,6 @@
services:
radicale:
image: tomsquest/docker-radicale:3.7.5.0
image: tomsquest/docker-radicale:3.5.8.2
container_name: radicale
ports:
- 5232
+1 -1
View File
@@ -1,6 +1,6 @@
services:
syncthing-valentin:
image: syncthing/syncthing:2.1
image: syncthing/syncthing:2.0
container_name: syncthing-valentin
hostname: syncthing-valentin
environment:
+1 -1
View File
@@ -9,7 +9,7 @@ services:
web_recipes:
restart: always
image: vabene1111/recipes:2.6.13
image: vabene1111/recipes:2.3.6
networks:
- default
- proxy
+12 -15
View File
@@ -1,18 +1,15 @@
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-----
ME_CONFIG_MONGODB_ADMINUSERNAME=ENC[AES256_GCM,data:GjWjDw==,iv:kBzyj+UsDd/el38BJFmn8CiDH0ojagZo91qyOAF7M8k=,tag:M7oaKZltblyTUp0ekD927w==,type:str]
ME_CONFIG_MONGODB_ADMINPASSWORD=ENC[AES256_GCM,data:diSSmsCxW5A=,iv:6kEac9UIlp/ksuqbLrB75eoJA3ReGoJNs/Pnr3C26yA=,tag:xY+J92/KtEsoN2ziqGNZ6Q==,type:str]
ME_CONFIG_MONGODB_URL=ENC[AES256_GCM,data:bUO+B5Bm7m/DUtCFpguFHQSyA7vkRbXcuPhYSNlpfnATVcgf,iv:WDSHNQyM5cnh1dxKAl0QXfXBmNfeoDjtZvKOeunvJAI=,tag:E0zwMGNECKYWvL/hFdanVg==,type:str]
ME_CONFIG_BASICAUTH=ENC[AES256_GCM,data:nj4ofzIdqw==,iv:PkWzZ7mRaftatgX7Whk43S5W2r/M/QGgmLoJ2MIC3Dc=,tag:/J6R5bRgsUFiOectNaKnIw==,type:str]
MONGO_USER=ENC[AES256_GCM,data:XopGfw==,iv:r2uoRr5k/nWSGiSOnseVze8UxeMxTnA174E2mWcxcO4=,tag:VWp076qsVpugr96cAwgiHQ==,type:str]
MONGO_PASS=ENC[AES256_GCM,data:QY4VoeaySJU=,iv:STKUpM03rSmfSzkK1mmOP6IDmC4gOnyBUpYzTYylguo=,tag:AFx59JJavyf/qW4eEdn5Ug==,type:str]
MONGO_HOST=ENC[AES256_GCM,data:iIPq+z4=,iv:Xrs9Z01H1/SnTGBTBHuFTCjU0CuCmHs0GABB6AL191E=,tag:LvgyigEAvac1tP6hF0O3+Q==,type:str]
RIOT_API_KEY=ENC[AES256_GCM,data:Zi8LX8LuFcAtvX0gLUOOH2KjqOLWUeFWy//MQ1PBdUy/YXqbUJEOsszQ,iv:am8ZA80GQ/pxavda0AR5S3ps6WUXfnpVHb36hZvxroo=,tag:LFvcViq8GZhWD+f4d0904Q==,type:str]
sops_lastmodified=2025-11-24T00:00:31Z
sops_mac=ENC[AES256_GCM,data:z/Va9k5vTCwmoVntX693PcV95D+fKrlmfe75ldyfkowCrgG/vl7s8uglKjn+wUixMdjz+bDYqR/RXovq9KmXhJO4TYOJd0JZdTXWqn+Ekk8OxooPLOgUdPvrL6rc3Iz53AhplSvAcoLzstZf8Z2WRGNIGve3jONJLFdFI+rL1HQ=,iv:SKTJDTBB6OGqBSfKLjj+xHG7c3ierdCo7mmQ9/+Z/gg=,tag:J92wwQtIyofqqnbm/sYtpA==,type:str]
sops_pgp__list_0__map_created_at=2025-11-24T00:00:31Z
sops_pgp__list_0__map_enc=-----BEGIN PGP MESSAGE-----\n\nhQIMA7uy4qQr71wiAQ/+Ny6UKLVYWP+9bmkZcKBvQXuCti45eWD2NsEKWMtO2LoF\nw5qqzLS1DLWLMBFQz+sn35a6N/RBHfN2LeZehM0c3MKXeTQvkozoxY0Qsj/B4pds\n5XTYpF73wjBCqm48A3Bh3Y9JNl7IiEbbQmGfeunloAr2WWrKsX2ugb3Emay8UrQL\nNvaK8yLV8WfvOWopgeJfGTjV7IPEgW6CBKif8meSq1+D6YLNRbmqpup5eMnZPOWn\ngrH821Q3O8XrKKuALM9N7b+pyBWCqA/R2ohxkLsxHCHNVdDKMQiwGha7y+pu4Fz6\nfEymEw+BPFvwPhcpxMCeT3h1kEX1dbyrvuayrqilCuiSuWNybRNUr/Awpigc9swR\nslW4Tf8ojvnWurBrVbIHxT7uP6xpO9ByzrYCtHauPLuyerlt50GC4Rc6bcJ40Mml\ne0vhrCvoJfUNX+Hfy280rP8NP+K7tPXIhwAK8JRTIwebF1Z1V4qSbvblZlgjglPt\nq/kSy2QTkPfhAohCNEGQK2xkaCAgWhMHPZoYV2We4GCaPT81g6DH/JH/wwGg3uTD\nY15vhHitcgoe9Z9B4V+rW3LQcx59vfvsMkjdPpkzfjCPcOLicR+ZzmmACuZal6aa\n09N4nqd6ESLUc11u4ojcExfbRNbS8IrVRnJxUKe8neI8ANTBAQn/oIidi1OjixvS\nXgHF3afYw7it86b51pEhgwTQ3TxMC5rIix2UUk9EUHOMUxG86Dtf4Cs4S6x/a5q+\nfJ9q+931YCyRQDN3C9H+MSIYWa8d+xAf76ShVS0hW3+//X0Hel2HMb/VNX53jOY=\n=OcbU\n-----END PGP MESSAGE-----
sops_pgp__list_0__map_fp=DC6910268E657FF70BA7EC289974494E76938DDC
sops_unencrypted_suffix=_unencrypted
sops_version=3.10.2
+24 -20
View File
@@ -1,26 +1,29 @@
services:
mongo:
hostname: mongo
image: mongo:8.2.11
image: mongo:8.0.1
restart: always
user: root:root
command: mongod --wiredTigerCacheSizeGB 2
deploy:
resources:
limits:
memory: 6G
reservations:
memory: 3G
user: 2000:2000
volumes:
- bpmongo_data:/data/db:Z
- bpmongo_config:/data/configdb:Z
- mongo_data:/data/db:Z
- mongo_data:/data/configdb:Z
env_file: .env
patch_detector:
image: git.vhaudiquet.fr/vhaudiquet/lolstats-patch_detector:5ecd5f8a954031909425346d40c18ec89d97406c
build: ./patch_detector
restart: "no"
deploy:
restart_policy:
condition: any
delay: '0'
window: 10s
env_file: .env
match_collector:
image: git.vhaudiquet.fr/vhaudiquet/lolstats-match_collector:d878af6d1a5cb633175515259e27a12c76c4609b
image: git.vhaudiquet.fr/vhaudiquet/lolstats-match_collector:5ecd5f8a954031909425346d40c18ec89d97406c
build: ./match_collector
volumes:
- bpcdragon_cache:/cdragon
restart: "no"
deploy:
restart_policy:
@@ -30,11 +33,9 @@ services:
env_file: .env
frontend:
image: git.vhaudiquet.fr/vhaudiquet/lolstats-frontend:d878af6d1a5cb633175515259e27a12c76c4609b
image: git.vhaudiquet.fr/vhaudiquet/lolstats-frontend:5ecd5f8a954031909425346d40c18ec89d97406c
build: ./frontend
restart: always
volumes:
- bpcdragon_cache:/cdragon
networks:
- default
- proxy
@@ -47,9 +48,12 @@ services:
env_file: .env
volumes:
bpmongo_data:
bpmongo_config:
bpcdragon_cache:
mongo_data:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/buildpath/data/_data'
networks:
proxy:
@@ -0,0 +1,36 @@
services:
vhaudiquetfr:
container_name: vhaudiquetfr
image: git.vhaudiquet.fr/vhaudiquet/vhaudiquet.fr:bd5a8ff9fae266a2905e8421689caef2197e00cf
networks:
- default
- proxy
ports:
- 80
labels:
- "traefik.enable=true"
- "traefik.http.routers.vhaudiquetfr.rule=Host(`vhaudiquet.fr`)"
environment:
- NGINX_HOST=vhaudiquet.fr
- NGINX_PORT=80
volumes:
- files:/usr/share/nginx/html/files
- public:/usr/share/nginx/html/public
networks:
proxy:
external: true
name: proxy
volumes:
files:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/vhaudiquetfr/files'
public:
driver_opts:
type: 'nfs'
o: 'addr=truenas.lan'
device: ':/mnt/main_storage/public'
+22
View File
@@ -0,0 +1,22 @@
WEBRISK_API_URI=
INSTANCE_NAME=ENC[AES256_GCM,data:qEEZGdAX83nTP2isYB1sVSUlfLiv6Xw=,iv:vdLcvAbaCd2bEpHfQVv2CQEHO3cFdvLfgEGIMS/lA2w=,tag:uPUhfd/nuuxegH2RXkADSA==,type:str]
NOTESNOOK_API_SECRET=ENC[AES256_GCM,data:o9/2+nDeoBAXFE8R,iv:8Lzz6Flltia+pr6CmdaGaba8x/+KnIjhKdwJOkgX3ys=,tag:hHI3VZj/uOrmSMmhh+T4yA==,type:str]
DISABLE_SIGNUPS=ENC[AES256_GCM,data:w1MjyQ==,iv:NKjhnLyPeOakGSMwVmOft7WtK6ggDYx0OucmUZId4Dc=,tag:wk5GpTs5xOMQ2S6w1MLjQA==,type:str]
SMTP_USERNAME=ENC[AES256_GCM,data:N6/huGyOvYbkb580YyZ+5u3chhA=,iv:pyglhbFMwyRxI1k9bmMS0sr/x+5RXn/I+fKavdNUSCc=,tag:/XgQDqYugazoFb0NQJGjSg==,type:str]
SMTP_PASSWORD=ENC[AES256_GCM,data:L2FG6mz9BlhuFfLNDa0=,iv:1P6ABsBleUYAn+Yz6qC3MbD2bR85HTrxM0aH8eRLVNY=,tag:IAggPwIHY5hobYobIGm8Qw==,type:str]
SMTP_HOST=ENC[AES256_GCM,data:3NSiYgn8jooDDZLTuTgj8Jah,iv:k0sz5H35fv9xzgfyV/NyE9CUVJySFvgbIoKuq7s+VF4=,tag:W7Ce8BUIz5bULaPOwIcv/Q==,type:str]
SMTP_PORT=ENC[AES256_GCM,data:AxM/,iv:tsQ8RA8f6YhxACcgUaHE3RgADcXB0hAd3dIkEtch0Bc=,tag:fxInjB435fi9XzLqdoOJwg==,type:str]
NOTESNOOK_APP_PUBLIC_URL=ENC[AES256_GCM,data:DCTjjJBUapunw5wZpQEWZscUtOZiAoWJFw==,iv:e192t2+LDSh6YokJso2I2hD3Z2yRJ4g0QwUyRSnACBo=,tag:ULInUTM5qbGJlCrVpkDxIg==,type:str]
AUTH_SERVER_PUBLIC_URL=ENC[AES256_GCM,data:9Nt/sTzOZwQZoaErm7epTw+buoWXQXQ8jZtlVZzLoiGDh7mjx9x9jQ==,iv:d0MvX6CWvEyx7YwIgGo3SIXV3hmZA3KqU5255gRhVAo=,tag:doKLa1njr4bK0lTy2i53DA==,type:str]
NOTESNOOK_APP_PUBLIC_URL=ENC[AES256_GCM,data:tzfOXeT0jBubJnvcx+EHmHQJhXXyJjkgMw==,iv:HM5ykxZ9E5BwLOU1+6pY9777Tz7CmPS+JyrBLbIj7BA=,tag:/1NhvVLkq4w+yWWWs338bA==,type:str]
MONOGRAPH_PUBLIC_URL=ENC[AES256_GCM,data:nTvb9xckE3Dwb8e3ngQimwbbEqu37kUgEQVJ9dKDAIAPkU7HumXMn3Y=,iv:QDjvaxuLWR80VL05C/lL17EVUpMsb8TF/9WRLw6fAPk=,tag:rdrAZlpJ5kY1O9QgmErBDQ==,type:str]
ATTACHMENTS_SERVER_PUBLIC_URL=ENC[AES256_GCM,data:SxJr4/nJRij39l6EACQz83dg8IPiSe9PjD7i6l9xAkpyvA==,iv:rrj951k7KQ8+FbU8cenkBv3ESBB7B6dpcX8aLeVjtNk=,tag:nVQyawlBhd69f+3MIk/Ftg==,type:str]
NOTESNOOK_CORS_ORIGINS=ENC[AES256_GCM,data:DOUsLeX882mGUKz1NcMhBRPydhoBYlxoyoSTSe6NEIiF9YM1TZwOBaJqw9zbdjy45zxzuvXxZmAFt+CL91/8oVHUMX2kBi1cT88W2nZU5g==,iv:sPUEYWPfTTR5o8Dm4rtFyD1rjkTkV9GgGlbZJPMPZGM=,tag:qNxvouzH/lgRZXWQtAGxsA==,type:str]
NOTESNOOK_CORS=ENC[AES256_GCM,data:H4pMn0DbumkeWxLjbKqvd//hTKav7Yucz9QT/Nnvu0sLLOiDMg3exKQy33VEWFuGs3F4CuqzcT2tKmi3viXbGQ9CnNsZp6EhBv1eWBQ21g==,iv:RI8hq0B/HJ98HTKg5y9TAZGzTulokqeqghXej/J6UHA=,tag:cvm+i+oNND7/340fV/VdsQ==,type:str]
sops_lastmodified=2025-10-15T14:21:43Z
sops_mac=ENC[AES256_GCM,data:+1PYCITFsGvfXDUAFAaDW6gBqfi/cE8Hrp9yw/wuS6E2Q1iw1GGEiFzeK/IL57MUvAZSdQkmv2bNrnboeDBYhHhADdqJdqht1SNui50aEYdLaHHUFADx54b157Op6HLYSccG1J6Hm7riBeurCDUxpC0hJ1whLva2V/T73LnzAf0=,iv:fsmU91jFjSDNjDfaki1c00cS2cya4jcVwd3pbSl/VBs=,tag:SOitwcXraXgrJVmfuLkDKg==,type:str]
sops_pgp__list_0__map_created_at=2025-10-15T14:21:43Z
sops_pgp__list_0__map_enc=-----BEGIN PGP MESSAGE-----\n\nhQIMA7uy4qQr71wiAQ//Rp9OH/H6e414f5jzczN4JgAUcJ7iWvP7CfvPN6gMZiFf\nAHlzejEGhfSxyx8/HNrdWK2BQn1wEqKCTAfB4LtHFNXEvUlMUdxjbzVaqGk8YUQF\nrRduMHpHNamsalk+4Kz7oHWpjw994qxpypHvsFxczAH2NLzYD+brEovaRDi+XTUy\n+e64wNnLhDJS1Xtm2urF1dvs/XQmCYxIpANqGvMezS+vHT8fDQze9Ka1KJh+E/rp\nCFCu3rSbs74E4QjttDoHF1FgMqB1HnbyRStBnq62BjsUMGuV560m/9R76Q++QUBa\nG78pg87ixBtJib24eApeLRMqiIGCdSNxIPn2+b069k5Chp+KCuFl9OAxFUYWIuLs\nmzrizfMKY2iWxBbkn14p24dgHDTkIEnwTOIHSzXHy02AZFcY/Z15R/Yj/nsvnMzO\nUwY931MMoWjME5R/lWrLzBz9FniYxxPwosDzYPdJH9+tJIs4C9EQmmDbKR48inLF\nkNP/ZzNmmhosOHzAEVNlmOo955YTSeGwGLxTsqtpJzNesGnA5q+ENq5Li2v26RTm\nijZJG+U2MyM55jWdETm3bkPwZooUOxpKmJy1gaXNl8/b1Pp0t3fQRWKGGwhsFWsI\nZ8j2++lW+1Gu5EcpjvFH6jdEfDh1R4UMlRO/pyBpWDdBrCwxrPlOv/j2/ogCdEfS\nXgFQwcLcFtZleLH537SZLgf8IJhrKQr6MM8jQf1tv1sLZC0LF3Ojhw9zs8YrX821\nwg3kw0Vd0gsKxxcQHaoLHqwTV/dY0kSHjkbCzG53XT2+p97PFNjhAEKBvNovov8=\n=qFED\n-----END PGP MESSAGE-----
sops_pgp__list_0__map_fp=DC6910268E657FF70BA7EC289974494E76938DDC
sops_unencrypted_suffix=_unencrypted
sops_version=3.10.2
+224
View File
@@ -0,0 +1,224 @@
services:
notesnook-db:
image: mongo:8.0.15
hostname: notesnookdb
user: mongodb:mongodb
volumes:
- dbdata:/data/db
- dbdata:/data/configdb
networks:
- notesnook
command: --replSet rs0 --bind_ip_all
healthcheck:
test: echo 'db.runCommand("ping").ok' | mongosh mongodb://localhost:27017 --quiet
interval: 40s
timeout: 30s
retries: 3
start_period: 60s
notesnook-s3:
image: minio/minio:RELEASE.2024-07-29T22-14-52Z
# ports:
# - 9000:9000
networks:
- notesnook
- proxy
volumes:
- s3data:/data/s3
environment:
MINIO_BROWSER: "on"
env_file: .env
command: server /data/s3 --console-address :9090
healthcheck:
test: timeout 5s bash -c ':> /dev/tcp/127.0.0.1/9000' || exit 1
interval: 40s
timeout: 30s
retries: 3
start_period: 60s
labels:
- "traefik.enable=true"
- "traefik.http.routers.notesnook-s3.rule=Host(`notesnook.vhaudiquet.fr`) && PathPrefix(`/s3`)"
- "traefik.http.routers.notesnook-s3.middlewares=notesnook-s3"
- "traefik.http.middlewares.notesnook-s3.stripprefix.prefixes=/s3"
- "traefik.docker.network=proxy"
- "traefik.http.routers.notesnook-s3.entrypoints=http"
identity-server:
image: streetwriters/identity:v1.0-beta.5
ports:
- 8264
networks:
- notesnook
- proxy
env_file: .env
depends_on:
- notesnook-db
healthcheck:
test: wget --tries=1 -nv -q http://localhost:8264/health -O- || exit 1
interval: 40s
timeout: 30s
retries: 3
start_period: 60s
environment:
NOTESNOOK_SERVER_PORT: 5264
NOTESNOOK_SERVER_HOST: notesnook-server
IDENTITY_SERVER_PORT: 8264
IDENTITY_SERVER_HOST: identity-server
SSE_SERVER_PORT: 7264
SSE_SERVER_HOST: sse-server
SELF_HOSTED: 1
IDENTITY_SERVER_URL: https://notesnook.vhaudiquet.fr/identity
NOTESNOOK_APP_HOST: https://app.notesnook.com
MONGODB_CONNECTION_STRING: mongodb://notesnookdb:27017/identity?replSet=rs0
MONGODB_DATABASE_NAME: identity
labels:
- "traefik.enable=true"
- "traefik.http.routers.identity-server.rule=Host(`notesnook.vhaudiquet.fr`) && PathPrefix(`/identity`)"
- "traefik.http.routers.identity-server.middlewares=identity-server,notesnook-server-cors"
- "traefik.http.middlewares.identity-server.stripprefix.prefixes=/identity"
- "traefik.docker.network=proxy"
- "traefik.http.routers.identity-server.entrypoints=http"
- "traefik.http.services.identity-server.loadbalancer.server.port=8264"
notesnook-server:
image: streetwriters/notesnook-sync:v1.0-beta.5
ports:
- 5264
networks:
- notesnook
- proxy
env_file: .env
depends_on:
- notesnook-s3
- identity-server
healthcheck:
test: wget --tries=1 -nv -q http://localhost:5264/health -O- || exit 1
interval: 40s
timeout: 30s
retries: 3
start_period: 60s
environment:
NOTESNOOK_SERVER_PORT: 5264
NOTESNOOK_SERVER_HOST: notesnook-server
IDENTITY_SERVER_PORT: 8264
IDENTITY_SERVER_HOST: identity-server
SSE_SERVER_PORT: 7264
SSE_SERVER_HOST: sse-server
SELF_HOSTED: 1
IDENTITY_SERVER_URL: https://notesnook.vhaudiquet.fr/identity
NOTESNOOK_APP_HOST: https://app.notesnook.com
MONGODB_CONNECTION_STRING: mongodb://notesnookdb:27017/?replSet=rs0
MONGODB_DATABASE_NAME: notesnook
S3_INTERNAL_SERVICE_URL: "http://notesnook-s3:9000"
S3_INTERNAL_BUCKET_NAME: "attachments"
S3_ACCESS_KEY_ID: "${MINIO_ROOT_USER:-minioadmin}"
S3_ACCESS_KEY: "${MINIO_ROOT_PASSWORD:-minioadmin}"
S3_SERVICE_URL: "${ATTACHMENTS_SERVER_PUBLIC_URL}"
S3_REGION: "us-east-1"
S3_BUCKET_NAME: "attachments"
labels:
- "traefik.enable=true"
- "traefik.http.routers.notesnook-server.rule=Host(`notesnook.vhaudiquet.fr`)"
- "traefik.http.services.notesnook-server.loadbalancer.server.port=5264"
- "traefik.docker.network=proxy"
- "traefik.http.routers.notesnook-server.entrypoints=http"
- "traefik.http.routers.notesnook-server.middlewares=notesnook-server-cors"
- "traefik.http.middlewares.notesnook-server-cors.headers.accesscontrolalloworiginlist=*"
- "traefik.http.middlewares.notesnook-server-cors.headers.accesscontrolallowmethods=*"
- "traefik.http.middlewares.notesnook-server-cors.headers.accesscontrolallowheaders=*"
- "traefik.http.middlewares.notesnook-server-cors.headers.accesscontrolallowcredentials=true"
sse-server:
image: streetwriters/sse:v1.0-beta.5
ports:
- 7264
env_file: .env
depends_on:
- identity-server
- notesnook-server
networks:
- notesnook
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.sse-server.rule=Host(`notesnook.vhaudiquet.fr`) && PathPrefix(`/sse`)"
- "traefik.http.services.sse-server.loadbalancer.server.port=7264"
- "traefik.http.routers.sse-server.middlewares=sse-server,notesnook-server-cors"
- "traefik.http.middlewares.sse-server.stripprefix.prefixes=/sse"
- "traefik.docker.network=proxy"
- "traefik.http.routers.sse-server.entrypoints=http"
healthcheck:
test: wget --tries=1 -nv -q http://localhost:7264/health -O- || exit 1
interval: 40s
timeout: 30s
retries: 3
start_period: 60s
environment:
NOTESNOOK_SERVER_PORT: 5264
NOTESNOOK_SERVER_HOST: notesnook-server
IDENTITY_SERVER_PORT: 8264
IDENTITY_SERVER_HOST: identity-server
SSE_SERVER_PORT: 7264
SSE_SERVER_HOST: sse-server
SELF_HOSTED: 1
IDENTITY_SERVER_URL: https://notesnook.vhaudiquet.fr/identity
NOTESNOOK_APP_HOST: https://app.notesnook.com
monograph-server:
image: streetwriters/monograph:1.2.4
# ports:
# - 6264:3000
env_file: .env
depends_on:
- notesnook-server
networks:
- notesnook
- proxy
healthcheck:
test: wget --tries=1 -nv -q http://localhost:3000/api/health -O- || exit 1
interval: 40s
timeout: 30s
retries: 3
start_period: 60s
environment:
NOTESNOOK_SERVER_PORT: 5264
NOTESNOOK_SERVER_HOST: notesnook-server
IDENTITY_SERVER_PORT: 8264
IDENTITY_SERVER_HOST: identity-server
SSE_SERVER_PORT: 7264
SSE_SERVER_HOST: sse-server
SELF_HOSTED: 1
IDENTITY_SERVER_URL: https://notesnook.vhaudiquet.fr/identity
NOTESNOOK_APP_HOST: https://app.notesnook.com
API_HOST: http://notesnook-server:5264
MONOGRAPH_PUBLIC_URL: https://notesnook.vhaudiquet.fr/monograph
PUBLIC_URL: https://notesnook.vhaudiquet.fr/monograph
labels:
- "traefik.enable=true"
- "traefik.http.routers.monograph-server.rule=Host(`notesnook.vhaudiquet.fr`) && PathPrefix(`/monograph`)"
- "traefik.http.routers.monograph-server.middlewares=monograph-server,notesnook-server-cors"
- "traefik.http.middlewares.monograph-server.stripprefix.prefixes=/monograph"
- "traefik.docker.network=proxy"
- "traefik.http.routers.monograph-server.entrypoints=http"
- "traefik.http.services.monograph-server.loadbalancer.server.port=3000"
networks:
notesnook:
proxy:
name: proxy
external: true
volumes:
dbdata:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/notesnook/dbdata/_data'
s3data:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/app/notesnook/s3data/_data'
@@ -1,6 +1,6 @@
services:
couchdb:
image: couchdb:3.5.2
image: couchdb:3.5.1
container_name: couchdb
env_file: .env
volumes:
-1
View File
@@ -52,7 +52,6 @@ find kubernetes -name 'release.yaml' -print0 \
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
-1
View File
@@ -33,7 +33,6 @@ find docker -name 'docker-compose.yml' -print0 \
if ! [ -f .swarmcd/stacks.yaml ] || ! cmp -s "$tmpfile" .swarmcd/stacks.yaml; then
mv "$tmpfile" .swarmcd/stacks.yaml
echo "Updated .swarmcd/stacks.yaml!"
git add ".swarmcd/stacks.yaml"
else
echo "No changes to .swarmcd/stacks.yaml."
fi
-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."
}
}
+137
View File
@@ -0,0 +1,137 @@
/*
* Docker machine terraform file
*/
resource "proxmox_virtual_environment_download_file" "debian-latest-cloudimg" {
content_type = "iso"
datastore_id = "local"
file_name = "debian-12-generic-amd64.qcow2.img"
node_name = "pve"
url = "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2"
}
resource "proxmox_virtual_environment_file" "docker-machine-cloud-config" {
content_type = "snippets"
datastore_id = "local"
node_name = "pve"
source_raw {
data = <<-EOF
#cloud-config
package_update: true
packages:
- git
- ca-certificates
- wget
- curl
- gnupg2
- qemu-guest-agent
- nfs-common
runcmd:
- systemctl enable --now qemu-guest-agent
- install -m 0755 -d /etc/apt/keyrings
- curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
- chmod a+r /etc/apt/keyrings/docker.asc
- echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
- apt-get update
- apt-get -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
- docker swarm init
- git clone https://github.com/vhaudiquet/homeprod /root/homeprod
- mkdir /app
- echo "truenas.lan:/mnt/fast_app_data/docker-homeprod /app nfs defaults,_netdev 0 0" >>/etc/fstab
- mount -t nfs truenas.lan:/mnt/fast_app_data/docker-homeprod /app
- echo "${var.sops_private_key}" | gpg --import
EOF
file_name = "docker-machine-cloud-config.yaml"
}
}
resource "proxmox_virtual_environment_vm" "docker-machine" {
name = "docker-machine"
node_name = "pve"
on_boot = true
agent {
enabled = true
}
tags = ["debian", "debian-latest", "docker", "terraform"]
cpu {
type = "host"
cores = 4
sockets = 1
flags = []
}
memory {
dedicated = 16192
}
network_device {
bridge = "vmbr0"
model = "virtio"
vlan_id = 2
}
lifecycle {
ignore_changes = [
network_interface_names,
mac_addresses,
ipv4_addresses,
ipv6_addresses,
id,
disk,
initialization,
vga
]
}
boot_order = ["scsi0"]
scsi_hardware = "virtio-scsi-single"
vga {
type = "serial0"
}
disk {
interface = "scsi0"
iothread = true
datastore_id = "local-lvm"
size = 128
discard = "ignore"
file_id = proxmox_virtual_environment_download_file.debian-latest-cloudimg.id
}
vm_id = 701
initialization {
datastore_id = "local-lvm"
interface = "ide2"
ip_config {
ipv4 {
address = "10.1.2.175/24"
gateway = "10.1.2.1"
}
}
user_account {
keys = [trimspace(var.ssh_public_key)]
password = var.machine_root_password
username = "root"
}
vendor_data_file_id = proxmox_virtual_environment_file.docker-machine-cloud-config.id
}
operating_system {
type = "l26"
}
tpm_state {
version = "v2.0"
}
serial_device {}
}
@@ -9,14 +9,11 @@ terraform {
# Docker configuration
provider "docker" {
host = "ssh://root@${var.docker_host}"
host = "ssh://root@docker-machine.lan"
}
resource "docker_image" "swarm-cd" {
name = "swarm-cd:latest"
# For now, custom-built image based on custom development branch
# Once this reaches upstream, back to upstream tag, like:
# ghcr.io/m-adawi/swarm-cd:1.9.0
name = "ghcr.io/m-adawi/swarm-cd:latest"
}
resource "docker_container" "swarm-cd" {
@@ -37,13 +34,6 @@ resource "docker_container" "swarm-cd" {
container_path = "/app/stacks.yaml"
read_only = true
}
volumes {
host_path = "/app/swarm-cd/data"
container_path = "/data"
}
env = [
"SOPS_GPG_PRIVATE_KEY=${var.sops_private_key}"
]
depends_on = [ docker_image.swarm-cd ]
}
+116 -100
View File
@@ -1,93 +1,130 @@
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"
}
}
/*
* Kubernetes cluster terraform file
*/
resource "proxmox_virtual_environment_download_file" "talos-cloudimg" {
content_type = "iso"
datastore_id = "local"
file_name = "talos-v1.11.1-nocloud-amd64.iso"
node_name = "pve"
url = "https://factory.talos.dev/image/ce4c980550dd2ab1b17bbf2b08801c7eb59418eafe8f279833297925d67c7515/v1.11.1/nocloud-amd64.iso"
}
# Talos configuration
provider "talos" {}
resource "proxmox_virtual_environment_vm" "kube" {
name = "kube-talos"
description = "Kubernetes Talos Linux"
tags = ["kubernetes", "talos", "terraform"]
# Kubernetes configuration
provider "kubernetes" {
config_path = "${path.module}/kubeconfig"
}
# Helm configuration
provider "helm" {
kubernetes {
config_path = "${path.module}/kubeconfig"
node_name = "pve"
vm_id = 703
machine = "q35"
keyboard_layout = "fr"
agent {
enabled = true
}
stop_on_destroy = true
cpu {
cores = 4
type = "x86-64-v3"
}
memory {
dedicated = 16192
floating = 16192
}
boot_order = ["scsi0", "ide0"]
scsi_hardware = "virtio-scsi-single"
cdrom {
file_id = proxmox_virtual_environment_download_file.talos-cloudimg.id
interface = "ide0"
}
disk {
interface = "scsi0"
iothread = true
datastore_id = "local-lvm"
size = 128
discard = "ignore"
file_format = "raw"
}
vga {
type = "serial0"
}
initialization {
datastore_id = "local-lvm"
interface = "ide2"
ip_config {
ipv4 {
address = "10.1.2.187/24"
gateway = "10.1.2.1"
}
}
user_account {
keys = [trimspace(var.ssh_public_key)]
password = var.machine_root_password
username = "root"
}
}
lifecycle {
ignore_changes = [
ipv4_addresses, ipv6_addresses, network_interface_names
]
}
network_device {
bridge = "vmbr0"
model = "virtio"
vlan_id = 2
}
operating_system {
type = "l26"
}
tpm_state {
version = "v2.0"
}
serial_device {}
}
resource "talos_machine_secrets" "kube" {}
data "talos_machine_configuration" "kube" {
cluster_name = "kube-${var.physical_hostname}"
cluster_name = "kube"
machine_type = "controlplane"
cluster_endpoint = "https://${var.kube_host}:6443"
cluster_endpoint = "https://kube-talos.lan: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"
image = "factory.talos.dev/installer/ce4c980550dd2ab1b17bbf2b08801c7eb59418eafe8f279833297925d67c7515:v1.11.1"
}
network = {
nameservers = [
# We need a set of nameservers that can work independently of kube
# to bootstrap.
"10.1.2.148",
"1.1.1.1"
"10.1.2.3"
]
}
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}"
"kube-talos.lan"
]
}
network = {
dnsDomain = "cluster.local"
dnsDomain = "kube-talos.lan"
cni = {
name: "none"
}
@@ -101,26 +138,32 @@ data "talos_machine_configuration" "kube" {
}
data "talos_client_configuration" "kube" {
cluster_name = "kube-${var.physical_hostname}"
cluster_name = "kube"
client_configuration = talos_machine_secrets.kube.client_configuration
nodes = ["${var.kube_host}"]
nodes = ["kube-talos"]
}
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 ]
node = "10.1.2.187" #proxmox_virtual_environment_vm.kube.ipv4_addresses[7][0] # lo + 6 talos-created interfaces before eth0
depends_on = [ proxmox_virtual_environment_vm.kube ]
lifecycle {
replace_triggered_by = [ proxmox_virtual_environment_vm.kube ]
}
}
resource "talos_machine_bootstrap" "kube" {
node = var.kube_host
node = "10.1.2.187" #proxmox_virtual_environment_vm.kube.ipv4_addresses[7][0] # lo + 6 talos-created interfaces before eth0
client_configuration = talos_machine_secrets.kube.client_configuration
depends_on = [ talos_machine_configuration_apply.kube, talos_machine_secrets.kube ]
depends_on = [ talos_machine_configuration_apply.kube ]
lifecycle {
replace_triggered_by = [ proxmox_virtual_environment_vm.kube ]
}
}
resource "talos_cluster_kubeconfig" "kube" {
node = var.kube_host
node = proxmox_virtual_environment_vm.kube.ipv4_addresses[7][0] # lo + 6 talos-created interfaces before eth0
depends_on = [ talos_machine_bootstrap.kube ]
client_configuration = talos_machine_secrets.kube.client_configuration
}
@@ -130,33 +173,6 @@ output "kubeconfig" {
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"
@@ -164,9 +180,9 @@ resource "local_file" "kubeconfig" {
}
data "talos_client_configuration" "talosconfig" {
cluster_name = "kube-${var.physical_hostname}"
cluster_name = "homeprod"
client_configuration = talos_machine_secrets.kube.client_configuration
nodes = [var.kube_host]
nodes = [proxmox_virtual_environment_vm.kube.ipv4_addresses[7][0]]
}
resource "local_file" "talosconfig" {
@@ -182,7 +198,7 @@ resource "helm_release" "cilium" {
repository = "https://helm.cilium.io/"
chart = "cilium"
wait = false
depends_on = [ local_file.kubeconfig, talos_cluster_kubeconfig.kube ]
depends_on = [ local_file.kubeconfig ]
set {
name = "ipam.mode"
@@ -218,7 +234,7 @@ resource "helm_release" "cilium" {
}
set {
name = "etcd.clusterDomain"
value = "cluster.local"
value = "kube-talos.lan"
}
set {
name = "hubble.relay.enabled"
+46
View File
@@ -0,0 +1,46 @@
# Terraform providers configuration
terraform {
required_providers {
proxmox = {
source = "bpg/proxmox"
version = "0.83.2"
}
talos = {
source = "siderolabs/talos"
version = "0.9.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "2.38.0"
}
helm = {
source = "hashicorp/helm"
version = "2.17.0"
}
}
}
# Proxmox configuration
provider "proxmox" {
endpoint = "https://pve.lan:8006/"
api_token = var.api_token
insecure = true
ssh {
agent = true
username = "root"
}
}
# Talos configuration
provider "talos" {}
# Kubernetes configuration
provider "kubernetes" {
config_path = "${path.module}/kubeconfig"
}
# Helm configuration
provider "helm" {
kubernetes {
config_path = "${path.module}/kubeconfig"
}
}
@@ -10,7 +10,7 @@ instance:
type: kubernetes
multitenant: false
networkPolicy: true
domain: "cluster.local"
domain: "kube-talos.lan"
kustomize:
patches:
- target:
+19
View File
@@ -0,0 +1,19 @@
variable "api_token" {
description = "Token to connect Proxmox API"
type = string
}
variable "machine_root_password" {
description = "Root password for VMs and containers"
type = string
}
variable "ssh_public_key" {
description = "Public SSH key authorized access for VMs and containers"
type = string
}
variable "sops_private_key" {
description = "Private SOPS GPG key for flux/kubernetes to decrypt secrets"
type = string
}
-8
View File
@@ -1,8 +0,0 @@
variable "sops_private_key" {
description = "Private SOPS GPG key for SwarmCD to decrypt secrets"
type = string
}
variable "docker_host" {
description = "Docker machine hostname"
type = string
}
-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 -3
View File
@@ -47,9 +47,7 @@ resource "proxmox_virtual_environment_file" "ai-cloud-config" {
resource "proxmox_virtual_environment_vm" "ai" {
name = "ai-${var.proxmox_node_name}"
node_name = var.proxmox_node_name
on_boot = false
started = false
on_boot = true
agent {
enabled = true
+1 -2
View File
@@ -24,7 +24,6 @@ resource "proxmox_virtual_environment_file" "docker-machine-cloud-config" {
- qemu-guest-agent
- nfs-common
runcmd:
- systemctl mask tmp.mount
- systemctl enable --now qemu-guest-agent
- install -m 0755 -d /etc/apt/keyrings
- curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
@@ -61,7 +60,7 @@ resource "proxmox_virtual_environment_vm" "docker-machine" {
}
memory {
floating = 32000
floating = 16192
dedicated = 38768
}
+3 -21
View File
@@ -1,9 +1,9 @@
resource "proxmox_virtual_environment_download_file" "talos-cloudimg" {
content_type = "iso"
datastore_id = "local"
file_name = "talos-v1.13.6-nocloud-amd64.iso"
file_name = "talos-v1.11.1-nocloud-amd64.iso"
node_name = var.proxmox_node_name
url = "https://factory.talos.dev/image/5a697fd6e91537a2c9c45929d004d82af180bb5d4e989dd8494e25fedca005bd/v1.13.6/nocloud-amd64.iso"
url = "https://factory.talos.dev/image/ce4c980550dd2ab1b17bbf2b08801c7eb59418eafe8f279833297925d67c7515/v1.11.5/nocloud-amd64.iso"
}
resource "proxmox_virtual_environment_vm" "kube" {
@@ -29,7 +29,7 @@ resource "proxmox_virtual_environment_vm" "kube" {
memory {
dedicated = 32768
floating = 22222
floating = 16192
}
boot_order = ["scsi0", "ide0"]
@@ -83,24 +83,6 @@ resource "proxmox_virtual_environment_vm" "kube" {
vlan_id = 2
}
network_device {
bridge = "vmbr0"
model = "virtio"
vlan_id = 2
}
network_device {
bridge = "vmbr0"
model = "virtio"
vlan_id = 2
}
network_device {
bridge = "vmbr0"
model = "virtio"
vlan_id = 2
}
operating_system {
type = "l26"
}
-1
View File
@@ -12,7 +12,6 @@ spec:
name: gitea
namespace: gitea
chart: gitea
version: '12.6.0'
interval: 1m
valuesFrom:
- kind: Secret
+25 -125
View File
@@ -1,5 +1,5 @@
image:
tag: 1.26.2
tag: 1.24.3
ingress:
enabled: true
hosts:
@@ -10,89 +10,19 @@ ingress:
# 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:
redis:
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]
postgressPassword: ENC[AES256_GCM,data:Lqe5Sx1rYyHK6g==,iv:nORpoyPzjAMghIeufPNrUnG7pi0YszOYwaWUdl2IyEc=,tag:cOzImE2HlZhItR7OGoJmgQ==,type:str]
password: ENC[AES256_GCM,data:AkUd6d32sjBZig==,iv:IaMaIvyCKQy2lq82HxsEeiLf7j+6+p3rV8jCMRysgTo=,tag:tLK1tim6i1EeK4bJyFptfg==,type:str]
database: gitea
username: ENC[AES256_GCM,data:6mlFP+E=,iv:+QEgLA6reecmpvvtmdOnwkpqOa7fOV06ZS8VTDQo7MY=,tag:dREH7uvHk8ZS6HcA7Vo0zw==,type:str]
username: ENC[AES256_GCM,data:jVMd2yM=,iv:bKIg47uWcsHZIB9o3LFrppWY/HvNAGRra1gHtt9zOf8=,tag:6872w7HOGAoVy6RhayqwbQ==,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:
@@ -102,7 +32,7 @@ extraVolumes:
- name: git
nfs:
server: truenas.lan
path: /mnt/fast_app_data/git
path: /mnt/main_storage/git
extraContainerVolumeMounts:
- name: git
mountPath: /git
@@ -111,8 +41,8 @@ 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]
key: ENC[AES256_GCM,data:taMkaU5kqwgKbSjPOT345KIE5SICdnjQRzVs6YKGcMGomkUKJRq7Cw==,iv:9UhNZ4jj1Hl4gS5xcBLTTGtlELqvNfGjxB08nRk9Gig=,tag:fRMTXQRyEgs2euN4bj7H+w==,type:str]
secret: ENC[AES256_GCM,data:D/14Oe3iE02HgiQ/dC5pfXHEC8HFoFm8Xp7LAC4kMlj0F2hx/ep516IJrC9J8s2KuutqT9WLRO4Fh6eaLh4M4zOr3rlxiLEq/fnIc5hvDsTxZAyWK7QUHv7d5/zCa8XCib0xxeX180lIR/DUNTv4OrtQBYg/uSUO/8x/Kze83Z0=,iv:X+XWtvYn8w+LUsXk4j1mFdEoRdpEIVMzw6TNGFY5YzQ=,tag:WcQ6MT3mdsxQOsTqA5PZbQ==,type:str]
autoDiscoverUrl: https://authentik.vhaudiquet.fr/application/o/gitea/.well-known/openid-configuration
config:
APP_NAME: Gitea
@@ -138,58 +68,28 @@ gitea:
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]
lastmodified: "2025-12-05T19:41:30Z"
mac: ENC[AES256_GCM,data:vnq6D9k/4JOdkMr4YOJRRZhWjJBakzmtuk50vmTzO5cpkK97sjCZRm4CtCnolmUZxvUgLtENjUKxt3Mr8IWbd+xWQDx+sa/ZEoncK2zxOOJnMsdRtbVY0zeuK2wWgncEFxbudGo2tewBd4qLiwBeIaMgMrhIHluB+iahKgoTqw0=,iv:ENoRWvGBtvfaBbLytmd1gAyeg7L6iyewfTkUYmee8Cg=,tag:IF7Df8OOxH2HAhJeOhW3zA==,type:str]
pgp:
- created_at: "2026-07-25T12:44:32Z"
- created_at: "2025-12-05T19:41:30Z"
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
hQIMA7uy4qQr71wiAQ//S/uYUC8ZESfaeLPGbat+vWkqyqimnfA5XEeJN/6KPtC6
sAyQAkzdecJCKqVHo/4MC31ICpzQG1KEUAxnfuPWHaGNY8DDaFAo1H5Ici+Wji6S
KP9Ti7NqRhiJ+IeImAPObeqBxi+vnAepCuzac/SWoulyIYT/l90bdYmT71x362pw
QrDGbeiwulHAWAHA7O9/Baob01vlKH6+oGHl2gT5biabMxUVXYZ4s1KZt6W3znq6
2I1L8nKGZCR2R64diOG06i8Yom57c41cdlOio7m4hoZ13Phuwna7mQrqrGyLtGwj
2N5NvaijoxNtetCOLkZ9eh2IwvO4f4CvN55RWZVg+Kc5kyhtUlr9dCx+wj/DY4rn
SYBfAWJUhFC7RfTLhv3qUn5OQmPxt0xrrW7ijJTBX+bb5FZyiH/SztA9o0OJDnwV
icMlKEiPD4Ip5UxSR8ZRj0lvJkbTf/KJ52dzhklIpiweb1nLG8YUAP2MEu73USS7
jgaC4PpBTwNsEclQ8E8/Y7sS2uDeyfwntpYsKSQsvLS6HWjpn3ymWX6sVr7N303q
CrWH5NfTe9aETbOdGU/DT3g8Ie51YpIId6fYXPp9SNXW1omAFVS1jrxSWCwyrz+w
frQ6ZYWEU26C+9eY9uqLTNveJ6YSTnbDvL8pS5qf4o04014WSgYJfr+0MkXO/SbS
XgGZk59IZXXZ8gzqD93ZFrDAD40DYUqb6nRN8Dupn4zdYAlMxk/V98vKyJ3W9y9r
28qlvoWagN/To2EP40jc6qTYdKVVS73asEadcG6IZV2A9J7htqiGRvTvQN51oQs=
=CQiX
-----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)$
+42
View File
@@ -0,0 +1,42 @@
persistence:
enabled: true
ingress:
enabled: true
external: false
hosts:
- host: homeassistant.lan
paths:
- path: /
pathType: Prefix
configurations:
trusted_proxies:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
- 127.0.0.0/8
sops:
lastmodified: "2025-12-04T18:23:43Z"
mac: ENC[AES256_GCM,data:JSaTCBXqpiP0R3rIEa/EZaDPbBInY2a6UMhFD9Gcw/mJVq/wF72KsFRfJl2hZ3d1FtsQ6Z0l3GrbiV41348jxzWM4XnE0e0hywdc2Ryqw0B3GS0EoNk1IoPR8ieZtxWNtFvglR2gVWWUnN7caYf/acE04NnzIDxl0tPEFckS+Nc=,iv:C784uqYb7KGhn2wGWZnCA7rhGocJWP6mfBhjNLWbimE=,tag:A7JLOmSVJ+ZrNA36DJfRCw==,type:str]
pgp:
- created_at: "2025-12-04T18:23:43Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ/+J1e3KfHaAkFS+lYz9jKzPAffkiDVCeecEf31Lk9DJxFd
7agtTWvcXtIsiJwF4sv4NzxY3pQrNRKwiq8pd3iXWHSqflIaQ2M9+dUGHykkjA5W
R+y/wgM+K0MBaFMxQU/xC0lM7YFwypV1JBp4jmpNn3McGba2yZAoKo1uAQ9LMP4L
Fd5wqNUrLNfwbh5Ts1rBVAGwStVlkRUvdUVCXjngdWVmE5xB3IBypdrFX2oclkl8
0zSNJwknC4bi4FeKBxWC90HT0n8zSMybdZOltcl8J3YVCL6l0F9hw6Ub5j1ej7qN
Igyll2/T4FEOExdo9oRXbEjC6GSZZBD6NMlrgJqVVUWoqDm4WQlKc7JRYAjtRgbS
Us8qCD8CMb57E6AZHD+GRZDK48OeevM21YxRvpSQlQfyeGbMrxF05zzw5InHSMhw
VslHQRmUMQqEzTsSeFbNxTeqy1YGGDYlnBpEjl8TPIZXE+mjwHm9QJbKwQFUK4Rh
YuEZDlUONdaKQpNX9OS6kwiV493sSruC2yWNwYIlgERrkcjBggKYPiV7lDiFnl1W
RVcsqOGnsrrwFHT7m6/MTIzH0k4fDt6Vv/FCToaoadvLPYNZb7xoKMahzT1z3SP9
FMuGus2r8h6ShEZVyLAt6o+BuuYyzOrVo10k1yTKDqEDD662rbRvTrBZlOk1vUPS
XgEtw6w6fFkESJKetHiN6TxG2+WyJw5PILm2sjak5AcR3qWiux/ENPb8kE0BIB0S
1Z/YTHYNP2mtEegDsp1DoT9tOSTWfrllL+p3kccvizEB5hq9+oMEzPGBstjWRjg=
=5PDx
-----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
@@ -1,61 +0,0 @@
persistence:
enabled: true
ingress:
enabled: true
external: false
hosts:
- host: homeassistant.lan
paths:
- path: /
pathType: Prefix
configurations:
trusted_proxies:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
- 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]
operator: Equal
value: ENC[AES256_GCM,data:DhbXHMsUJ7E=,iv:lQQTpWpDGi7JEQV24jdICHMnC8yV0EsNQ/nauBsqk/8=,tag:RKripNRdBwqnt1sCY72eYA==,type:str]
effect: NoSchedule
- key: ENC[AES256_GCM,data:YApCSh00O5YoRqzHUNSoPbYWOsNVwFKOlln0C2+mYpDfKqLU5g==,iv:eOv/Yri400RHpm6Bnxqw4IYp2IiYAKXTd06sduW3Ku0=,tag:9GR1Q8lWHG7Uplevd1hbYg==,type:str]
operator: Exists
effect: NoSchedule
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: ENC[AES256_GCM,data:0rESi0B+l5uEwmPQPuFzMylc6JE=,iv:dGx39YEojvQ/J2y6SlP54I5L7Zr+yecwJwNQQ53RV9k=,tag:icAw2r/q4+UcHzYClfOBSg==,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]
pgp:
- created_at: "2026-07-25T12:44:32Z"
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
-----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
@@ -1,13 +0,0 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: zigbee2mqtt
resources:
- namespace.yaml
- repository.yaml
- release.yaml
secretGenerator:
- name: zigbee2mqtt-values
files:
- values.yaml=values.yaml
configurations:
- kustomizeconfig.yaml
@@ -1,6 +0,0 @@
nameReference:
- kind: Secret
version: v1
fieldSpecs:
- path: spec/valuesFrom/name
kind: HelmRelease
@@ -1,4 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
name: zigbee2mqtt
-18
View File
@@ -1,18 +0,0 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: zigbee2mqtt
namespace: zigbee2mqtt
spec:
interval: 1m
chart:
spec:
sourceRef:
kind: HelmRepository
name: zigbee2mqtt
namespace: zigbee2mqtt
chart: zigbee2mqtt
interval: 1m
valuesFrom:
- kind: Secret
name: zigbee2mqtt-values
@@ -1,8 +0,0 @@
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: zigbee2mqtt
namespace: zigbee2mqtt
spec:
interval: 1m
url: https://charts.zigbee2mqtt.io/
-71
View File
@@ -1,71 +0,0 @@
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: z2m.lan
paths:
- path: /
pathType: Prefix
service:
type: ClusterIP
statefulset:
securityContext:
privileged: false
capabilities:
add: []
zigbee2mqtt:
homeassistant:
enabled: true
discovery_topic: homeassistant
status_topic: hass/status
legacy_entity_attributes: true
legacy_triggers: false
permit_join: false
blocklist: []
availability:
active:
# -- Time after which an active device will be marked as offline in
# minutes (default = 10 minutes)
timeout: 10
passive:
# -- Time after which a passive device will be marked as offline in
# minutes (default = 1500 minutes aka 25 hours)
timeout: 1500
timezone: Europe/Paris
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]
base_topic: z2m
serial:
port: tcp://10.1.1.159:6638
baudrate: 115200
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]
pgp:
- created_at: "2026-05-02T10:26:20Z"
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
-----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
+24 -77
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:nS0n+g3riD47shHDhs8JzfHT+a8oOKvFJDvO72mUU3bVslFYRBueJK+rWCGYjXwwyZzUjAcb638sqA66THxaxebPLtZ/UCmT79qzOw7Rf3A=,iv:o9WztN8vb8Pag8WMKIEWDMgFVWiTB3dIjCx7nU/0hrc=,tag:6tx684P4cJSZrrmut7KVcA==,type:str]
postgresql:
password: ENC[AES256_GCM,data:wmidNe0ODeH8FQ==,iv:zh38F/lIKdFBBIQufjLORtfusPWwDnsDIh61b6ltbQE=,tag:SSMCicRKoPBXwPLFoh+uoQ==,type:str]
password: ENC[AES256_GCM,data:ES3BL3tEiv+NSg==,iv:oOKiH38wi5zqKkgvezIgj5Qg8+1bcFZXpoEewMucygM=,tag:YigQ3X8pRXVqhkoycGNjbA==,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:EmE524Yp3Ihv+FnO3GfTilzLwGo=,iv:XzJW6v4owBETgLHfqvvELhkDLQJSH962eEByQF0zeSQ=,tag:rkvVWCX3JwNO+j9MIB/+LQ==,type:str]
use_tls: true
password: ENC[AES256_GCM,data:pco+hLWairs2UFNFTSY=,iv:OMrxrzKDo91UIMgEhPdN4dTpRxl5A1LKHYk5h4eFD/A=,tag:ecjAP9lv6FPxPppyurJ5cA==,type:str]
password: ENC[AES256_GCM,data:b6joibJRT46C+XeH2eI=,iv:Lo+28oE5mv3uxI8CUAQ1OgNhN+3iv1JfdxvkZWZC05c=,tag:VAIrnXSg9w82N00oT+d8JA==,type:str]
postgresql:
enabled: true
volumePermissions:
@@ -17,44 +17,12 @@ 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:NWk6kvOp1RRs4A==,iv:q0GoRFQ15LBXDxDnOiKWHX6/K8DwX+k2Myxk7iaBo2U=,tag:6qfY+5TF2oy4cRfeJKr7IA==,type:str]
image:
repository: bitnamilegacy/postgresql
tag: 15.9.0
tag: 17.5.0
primary:
args: []
tolerations:
- key: ENC[AES256_GCM,data:M14eAjMj2w2+,iv:5vIosyFtwVgqs07CT2UcL1KL2hqg+rvKS5PWRvWRlPQ=,tag:OJ4RwlLAhGDN4JGPX8gypw==,type:str]
operator: Equal
value: ENC[AES256_GCM,data:KKZ1Kd5yRa8=,iv:adSUcfmjnDAc9QZ14NDfFz4oATpcBhtn8iHTF2xXpcw=,tag:G//QEbSKXiGP7nD5oAfNSA==,type:str]
effect: NoSchedule
- key: ENC[AES256_GCM,data:KtJS0g+/3y6VZb9VNKv1IWMwIi8FBURPGT6W6qvBAV1CHW4UMg==,iv:1I8o3SNljujN4FqByFC9uHpImJhHjj4Us0QEpHpDHZ4=,tag:FIpRW9I4OSVFVx4ejmau5w==,type:str]
operator: Exists
effect: NoSchedule
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: ENC[AES256_GCM,data:IkWdKkS/XlGw0u7I+Q2wYhXL+CU=,iv:2k9d0Jo4Vw5gA4tGeIq1Dw0IiZKQykfV8YAt2lYk7GE=,tag:Xnz58VP61Ew/J8hvIClOVg==,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
redis:
enabled: true
server:
@@ -62,50 +30,29 @@ server:
enabled: true
hosts:
- authentik.vhaudiquet.fr
# Failover tolerations + affinity — allow scheduling on p330 during r740 outage.
# The authentik chart reads global.tolerations (applied to server + worker)
# and global.affinity.nodeAffinity (preset system with type + matchExpressions).
global:
tolerations:
- key: ENC[AES256_GCM,data:yy3LVikckQ4y,iv:PlWRKZVoR6g/RtQdGBoIKbnwjX887xZY7ZhciTa0nps=,tag:yRMuJW3yjBV2C3LDWVdEHg==,type:str]
operator: Equal
value: ENC[AES256_GCM,data:IqKHhgroaK0=,iv:bvg7kLaVQEsH31xHH1rCW29dWlWDlDsAMAmR1cX2nS4=,tag:B77eeEjVnRwk/feuPyi2Kw==,type:str]
effect: NoSchedule
- key: ENC[AES256_GCM,data:QYGmJBgxhqC2L3UvGYyJKKWDfzSFq91w1ifwNn9rofPnBqL0Ug==,iv:+tI3xw51LqinZnEOi7Lgao9liOD8KT8rOGNtn10qkFg=,tag:fJhk0PifHEyFlX4j75Sklg==,type:str]
operator: Exists
effect: NoSchedule
affinity:
nodeAffinity:
type: soft
matchExpressions:
- key: ENC[AES256_GCM,data:qRInCqtomABFKcUFHzDQe2qmzJY=,iv:9cMrKqqpIMtNCUqkIWaCr5YGNoK6zsID3xAKp34q1kM=,tag:Zf1ZjGwCgnaOqTq8Hr++Fg==,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: "2025-12-05T21:18:24Z"
mac: ENC[AES256_GCM,data:DpKXYMtn+01IVQ98t/oVG4bqRVBBSQojqKGmt1A0vco8EJKNtHxyykVuuouO4mhmx+UWKjxEg+KvgvV2Ptk4uGs64x2sCSnMuqnpwfd8xpxLukqVxVd60ICKFeeVt4MgwRrlOBO2WKMDoZE5pi7pxVoGDb86P2J4XHzWqVkGGX8=,iv:W1OZznwbmlZJzICIuEVszGwFGFOgPLiThX4uxVpaOiw=,tag:s1HhjGwGt/mkWMhsqmXjZw==,type:str]
pgp:
- created_at: "2026-07-25T12:48:03Z"
- created_at: "2025-12-05T21:18:24Z"
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//ZrmaLqypfT4HvrAO8tV/I8tl3PDZgLot0pQyv3Idu3s3
0e+Pn7zGBUvZXNYfgd20ilCatPVzt4x2KvFgaAkEMkqHnE2btLSrN66QiwHZDxF5
1G+TNWs6ZOUSpUn7P1UdfroSm/Gy5sdUc8cTuolOkLqq0r88Wh3+RkxoR9Nv4f4p
XDDNRo4al8t0QT+WHKlGwaD/58Vgu0CRzBsjZodZWrG+4VgzxHK+3rqPGY7s0Mpy
/epq73LBFRzgVagMqjH8LBJ60jjScWHVlGjRg4TtXDyhHYizEvlWt63sbWeYBLwC
Uz0QHR3jWZoErbb71JpEhHa5P+QuUaZTeEq/groWsD1I7cceDC9EorhbcyWm7SNa
swTx23zjfdM/Hqi5Wz9UeTN8CkdSpb1mbG9YTvhB510wcpdVPTJNM1hVF+9OJycu
RP6YH6dXuWNK7aSx62ppaz+UJb27tF+KXafO4yDIu5hY1vaeFSgCUgJTpYae4tS1
pWBLR51FikImgkkEFjzDwAWGBwfYzvqWqGOjO6E2yaVRTSYYdZQbTj8Owq49zizT
A4eZpPEeq+Z1FmQ7kjV7+tAV/GTDrSyvtytQ+fgebhVf+0KrcNUzQDEsQfV1htNl
mnR590NnBp83jlHVAFYUwaCEzcrfRrfGzrlacUVuOO2c4orSeRI2FOro+2AOjvzS
XgGkpLEkrINUIuI27G838z9/9cFUqMqL6MTThuJjUmKphgLAZ1iqhyfEm/2kwXZz
oJnnbBWIxN2/vltsuu/WprLHzbL5dBusLiBUeuSbPPron4r9Do2cNcFIT2hyAfA=
=1NR0
-----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
version: 3.10.2
@@ -1,24 +0,0 @@
# TLS certificate for the Stalwart mail listeners (SMTP/IMAP/POP3 STARTTLS + implicit TLS)
# and the management WebUI hostname.
#
# Issued by cert-manager via the letsencrypt-production ClusterIssuer (Cloudflare DNS-01).
# The resulting Secret (mail-vhaudiquet-fr-tls) is consumed in two places:
# 1. The Stalwart HelmRelease mailTls block -> mounted into the pod + pushed to
# Stalwart by the tls-sync sidecar (JMAP) so SMTP/IMAP/POP3 present this cert.
# 2. The chart ingress (TLS termination is handled by Caddy in this cluster, so the
# ingress is TLS-less and only routes HTTP to the mgmt port).
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: mail-vhaudiquet-fr
namespace: stalwart
spec:
secretName: mail-vhaudiquet-fr-tls
issuerRef:
name: letsencrypt-production
kind: ClusterIssuer
commonName: mail.vhaudiquet.fr
dnsNames:
- mail.vhaudiquet.fr
duration: 2160h # 90 days
renewBefore: 360h # 15 days before expiry
@@ -1,15 +0,0 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: stalwart
resources:
- namespace.yaml
- repository.yaml
- certificate.yaml
- recovery-admin-secret.yaml
- release.yaml
secretGenerator:
- name: stalwart-values
files:
- values.yaml=values.yaml
configurations:
- kustomizeconfig.yaml
@@ -1,6 +0,0 @@
nameReference:
- kind: Secret
version: v1
fieldSpecs:
- path: spec/valuesFrom/name
kind: HelmRelease
@@ -1,4 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
name: stalwart
@@ -1,47 +0,0 @@
# Recovery / bootstrap administrator credential for Stalwart.
#
# This Secret is referenced by:
# - recoveryAdmin.existingSecret in the HelmRelease, which injects it into the
# Stalwart pod (and the tls-sync sidecar) so the cert-manager certificate can
# be pushed to Stalwart via JMAP. Keep it present for the lifetime of the
# deployment; the tls-sync sidecar needs it on every cert renewal.
#
# The username/password here are ONLY the recovery account.
apiVersion: v1
kind: Secret
metadata:
name: stalwart-recovery-admin
namespace: stalwart
labels:
app.kubernetes.io/name: stalwart
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]
sops:
lastmodified: "2026-07-02T20:57:39Z"
mac: ENC[AES256_GCM,data:lIVOaMsFV9F1/yLvykA3LH5ukn9PIba6N8cE9RGdcFepM56tBYlY6fbkcKTtojyAkoYov6OCjgTsOkMtUzRdGES4Zti6zHB3cTPal8bJCf5cAfYnGFRcQaASIkVjNZkQSJ2pDRP4rZqioCHuj2/a6uJZ4hhtSpxrECYbpzD2Gk8=,iv:31fXHsWH1ZP00Od5DSxgYPuw87NqQNfWl4vFtoouIHk=,tag:u5cJn231VT2ZTmlcdpBz0g==,type:str]
pgp:
- created_at: "2026-07-02T20:57:39Z"
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
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(data|stringData|.*.key|.*.crt)$
version: 3.10.2
@@ -1,21 +0,0 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: stalwart
namespace: stalwart
annotations:
homeprod.io/essential: "true"
spec:
interval: 1m
chart:
spec:
sourceRef:
kind: HelmRepository
name: stalwart-helm
namespace: stalwart
chart: stalwart
version: "0.7.5"
interval: 1m
valuesFrom:
- kind: Secret
name: stalwart-values
@@ -1,8 +0,0 @@
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: stalwart-helm
namespace: stalwart
spec:
interval: 1m
url: https://kgrubb.github.io/stalwart-helm-chart
@@ -1,147 +0,0 @@
# Stalwart Mail Server - Helm values
#
# TLS for the mail listeners is sourced from cert-manager: the
# mail-vhaudiquet-fr-tls Secret (see certificate.yaml) is mounted into the pod
# and pushed to Stalwart by the chart's tls-sync sidecar over JMAP, which also
# calls ReloadTlsCertificates on every cert-manager renewal.
# Container image
image:
repository: stalwartlabs/stalwart
tag: v0.16.11
pullPolicy: IfNotPresent
# Single-node RocksDB deployment.
replicaCount: 1
role: ""
pushShard: ""
# Recovery / bootstrap administrator.
# The Secret (stalwart-recovery-admin) is required for the lifetime of the
# deployment because the tls-sync sidecar authenticates to Stalwart's JMAP API
# 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]
password: ""
existingSecret: ENC[AES256_GCM,data:DnjFoj8VNeqHmwM/KVebjOOHvYHPgZQ=,iv:JWBs6OeZzsa+8uJt/FjptI6t+tf+CRQDKA7149rBg1o=,tag:M4CXA2k8M65mbSUF0mnGvQ==,type:str]
usernameKey: username
passwordKey: password
# Recovery mode suspends mail services and exposes only the management listener.
# Ship production values with this OFF.
recoveryMode:
enabled: false
port: 8080
logLevel: info
extraEnv: {}
extraSecretEnv: {}
# The bootstrap hook Job provisions a *fresh* domain/accounts/OIDC directory.
bootstrap:
enabled: false
# cert-manager TLS integration for the mail (SMTP/IMAP/POP3 STARTTLS + implicit
# TLS) listeners. The Secret below is produced by the Certificate in
# 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]
certKey: tls.crt
privateKeyKey: tls.key
mountPath: /etc/stalwart/tls/ingress
hostname: mail.vhaudiquet.fr
domain: vhaudiquet.fr
# How often the sidecar re-checks the mounted cert for changes.
reloadIntervalSeconds: 300
# config.json contents - ONLY the DataStore object. All other settings
# (listeners, storage backends, domains, accounts, certs) live in the database
# and are managed via JMAP/WebUI.
config:
'@type': RocksDb
path: /var/lib/stalwart
# Main Service: ClusterIP. Used by the Ingress for the management WebUI (mgmt)
# and for in-cluster access. Mail L4 ports are exposed separately via mailService.
service:
type: ClusterIP
ports:
smtp: 25
smtps: 465
submission: 587
imap: 143
imaps: 993
pop3: 110
pop3s: 995
sieve: 4190
http: 80
https: 443
mgmt: 8080
# Dedicated LoadBalancer for SMTP/IMAP/POP3/Sieve (L4). HTTP/HTTPS/mgmt are NOT
# exposed here - the WebUI is reached via the Ingress (Traefik) below.
# The WAN router NAT for 25/465/587/993/995/4190 must be repointed to this IP.
mailService:
enabled: true
name: stalwart-mail
type: LoadBalancer
loadBalancerIP: 10.1.2.143
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.
# No TLS block here.
ingress:
enabled: true
annotations: {}
hosts:
- host: mail.vhaudiquet.fr
paths:
- path: /
pathType: Prefix
portName: mgmt
tls: []
# Persistent volume for the RocksDB data directory.
persistence:
enabled: true
accessMode: ReadWriteOnce
storageClass: longhorn
size: 50Gi
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: "1"
memory: 1Gi
# Override chart defaults to add fsGroupChangePolicy: OnRootMismatch.
# Without this, kubelet recursively chowns every file in the NFS-backed PVC
# on every pod start (15k+ RocksDB files), causing multi-minute delays.
# OnRootMismatch skips the recursive chown if the volume root already
# has the correct owner (UID 2000).
podSecurityContext:
fsGroup: 2000
fsGroupChangePolicy: OnRootMismatch
runAsUser: 2000
runAsGroup: 2000
runAsNonRoot: true
seccompProfile:
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]
pgp:
- created_at: "2026-07-18T14:22:17Z"
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
-----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
@@ -1,68 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: alloy-config
namespace: observability
labels:
app.kubernetes.io/name: alloy
app.kubernetes.io/component: log-collector
data:
config.river: |
// -----------------------------------------------------------------------------
// Grafana Alloy — log collection only (metrics cluster+host collection is
// handled by vmagent/node-exporter/cAdvisor elsewhere).
// Forwards pod logs to the in-cluster Loki single-binary.
// River config produced by `alloy convert -f promtail` from an equivalent
// Promtail YAML (so component names and argument shapes are guaranteed
// correct for Alloy v1.18).
// -----------------------------------------------------------------------------
discovery.kubernetes "kubernetes_pods" {
role = "pod"
selectors {
role = "pod"
field = "spec.nodeName=" + coalesce(sys.env("HOSTNAME"), constants.hostname)
}
}
loki.process "kubernetes_pods" {
forward_to = [loki.write.default.receiver]
// CRI-style log lines on the host: {"log":"...","stream":"stdout","time":"..."}
stage.cri { }
}
discovery.relabel "kubernetes_pods" {
targets = discovery.kubernetes.kubernetes_pods.targets
rule {
source_labels = ["__meta_kubernetes_namespace"]
target_label = "namespace"
}
rule {
source_labels = ["__meta_kubernetes_pod_name"]
target_label = "pod"
}
rule {
source_labels = ["__meta_kubernetes_pod_container_name"]
target_label = "container"
}
}
loki.source.file "kubernetes_pods" {
targets = discovery.relabel.kubernetes_pods.output
forward_to = [loki.process.kubernetes_pods.receiver]
file_match {
enabled = true
}
legacy_positions_file = "/tmp/positions.yaml"
}
loki.write "default" {
endpoint {
url = "http://loki.observability.svc.cluster.local:3100/loki/api/v1/push"
}
external_labels = {}
}
@@ -1,19 +0,0 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: alloy
namespace: observability
spec:
interval: 1m
chart:
spec:
sourceRef:
kind: HelmRepository
name: grafana
namespace: observability
chart: alloy
version: "1.11.0"
interval: 1m
valuesFrom:
- kind: Secret
name: alloy-values
@@ -1,57 +0,0 @@
# Grafana Alloy
# Runs as a DaemonSet on every node (tolerates the failover taint).
# Tails pod logs from /var/log/pods, attaches K8s labels (pod, namespace,
# service, container, image), and pushes them to Loki at
# http://loki.observability.svc.cluster.local:3100 (in-cluster, no auth).
# Use the externally provisioned ConfigMap (alloy-config) carrying config.river.
alloy:
configMap:
create: false
name: alloy-config
key: ENC[AES256_GCM,data:aevkZsfe4c4H34BJ,iv:4vrNZWwYWaxJUKGbNlnZfk0NM182nBQZuwvqUPslKNA=,tag:lh1iILM3uQAt0An6kN6EHg==,type:str]
# Mount host log paths so the DaemonSet can tail pod/container logs.
mounts:
varlog: true
dockercontainers: false
stabilityLevel: generally-available
tolerations:
- key: ENC[AES256_GCM,data:zOMWiA9dG+8o,iv:yHp9aBczV8nVRGlJmsBaKs9WdmE3+ii8gWOaj5Xok6M=,tag:8c5ZqBT+vvC0WCW8mi0c9g==,type:str]
value: ENC[AES256_GCM,data:2Q04VR9xLbQ=,iv:6+tQXx3IGUIcrse+poG4X/4pS5dN2dKvhb79sCy+nfA=,tag:jb/TZmGpvdsWnKoC5NdCow==,type:str]
operator: Equal
effect: NoSchedule
- key: ENC[AES256_GCM,data:aVq8GU1ZDg5m9XDEI3PoVbbykU36SnKpEgrohvZ0IBmH47qDKg==,iv:eMcHRO5mGp9hhY4KnuBmdPTjd/9lqtesjA/RRSu4QMw=,tag:2jaGuogkLcIuye2meJQMDQ==,type:str]
operator: Exists
effect: NoSchedule
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 256Mi
sops:
lastmodified: "2026-07-28T13:46:53Z"
mac: ENC[AES256_GCM,data:u6J/EIP5aFtOi8ZtT8BPn978wJAEL1E3r0WcmG5WIsWKJBZMMQHUYRmHgkS6n0/UMtczWoCdXlxObS73ZQMSSkdtagQHE/HPh69dDdGkjxyM4mlP+YMwcnIQkxpJBAQTERXA+SVoWCZb7ztKbiJS+zPjOCfA95ixQINmBCdUgEc=,iv:WOXngWu3uNWYp18/xWghGJyONBrq3SSnPDwbjHBDozU=,tag:1fasTfuLBGXBCo9JPytsJw==,type:str]
pgp:
- created_at: "2026-07-28T13:46:53Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ/8DSD0jEn3YE7XHTm4DWdfLHPs1IVg9hyiWSHe5/xH0siD
zWonfjcuytw8EHDzv6pQMNYmIpyAmJ92Al4ROJmBV8gZ59+U9goHmw5HgaQAupBJ
/gy8iFBteGOHJT+XJPoVb/bu449f7Vle4L3DrOAl6mwxE0WT/7ERoQBeSxL+2OTZ
iDPdq24Zy+crDHpoM0GcSnFRLX5UpmL2QXGB8PHyctwSQoDW+sbAY2ME6buOw8HI
AremKTRtFm6Pu1Ksdh6ZicaHpLSvLyByPPt2zYhlBQsG3s/SjJDlnakUZHhm7T4o
oHzSpKqV7NQbE09ZMyGJrEkl+rfCPeu6jHplW2EX3xjqLWNUF8GHcsDWljogZxXF
irBPkyKASEDdkHZgiZobU6BmvQlxILj104xNtUYTTChcKu3s0d5BrkIOGe+Y7rJd
fNvMfkmO8/URBgtsXy2xPKo0Jzu/0pZsPEp2lxNeyElwxQqo1CFwhKZPkeQ2eLpu
4X7/CMN8KJr6jLX8HhX9AivlCj+2CoT8SB5GAPw4p00eD0GIMWSNyOXjyW/qQZi3
82EyX9KIpHjALoOI4/3YgFpUO12AEsjirYKWkUM+IoDp5l+YX59QdM7zUVVyzsTG
2EXEdQqYVA7DIcMJb0tHqxDGMGxNayaUsikV7e/kcRVUyDSH+xOfaSUrDTqqv+XS
XAFro6848HF5uMIP4pfM+dxzkc9rFF4il0CuGWlscbz5q+Aw9LImGbpNzrWk3Lpi
beuwWKFTZ8zab5TH9UF/xqsQeg/nyzQnb3fFPk+owvY7fH6XiYbN5WjKjXGW
=kBpp
-----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
@@ -1,8 +0,0 @@
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: grafana
namespace: observability
spec:
interval: 1m
url: https://grafana.github.io/helm-charts
@@ -1,26 +0,0 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: observability
resources:
- namespace.yaml
- vmstack-repository.yaml
- grafana-repository.yaml
- loki-repository.yaml
- vmstack-release.yaml
- loki-release.yaml
- alloy-release.yaml
- alloy-config.yaml
- vm-internal-ingress.yaml
- loki-internal-ingress.yaml
secretGenerator:
- name: vmstack-values
files:
- values.yaml=vmstack-values.yaml
- name: loki-values
files:
- values.yaml=loki-values.yaml
- name: alloy-values
files:
- values.yaml=alloy-values.yaml
configurations:
- kustomizeconfig.yaml
@@ -1,6 +0,0 @@
nameReference:
- kind: Secret
version: v1
fieldSpecs:
- path: spec/valuesFrom/name
kind: HelmRelease
@@ -1,23 +0,0 @@
# Ingress exposing the Loki push API (loki:3100) through Traefik as
# loki-internal.lan — used by the docker-host promtail to push container logs
# into the central Loki.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: loki-internal
namespace: observability
annotations:
external-dns.alpha.kubernetes.io/enabled: "true"
spec:
ingressClassName: traefik
rules:
- host: loki-internal.lan
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: loki
port:
number: 3100
@@ -1,19 +0,0 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: loki
namespace: observability
spec:
interval: 1m
chart:
spec:
sourceRef:
kind: HelmRepository
name: grafana-community
namespace: observability
chart: loki
version: "18.5.4"
interval: 1m
valuesFrom:
- kind: Secret
name: loki-values
@@ -1,9 +0,0 @@
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: grafana-community
namespace: observability
spec:
interval: 1m
type: oci
url: oci://ghcr.io/grafana-community/helm-charts
@@ -1,86 +0,0 @@
# Loki Helm values
# Uses Monolithic deployment mode with filesystem storage on a Longhorn PVC.
loki:
deploymentMode: Monolithic
# Filesystem storage — chunks + rules on the PVC.
storage:
type: filesystem
filesystem:
chunks_directory: /var/loki/chunks
rules_directory: /var/loki/rules
# Required schema config. tsdb store + filesystem object store, schema v13.
# See https://grafana.com/docs/loki/latest/operations/storage/schema/.
schemaConfig:
configs:
- from: "2024-04-01"
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
# For monolithic mode, point tsdb_shipper at the local store (no index gateway).
storage_config:
tsdb_shipper:
active_index_directory: /var/loki/index
cache_location: /var/loki/index-cache
filesystem:
chunks_directory: /var/loki/chunks
rules_directory: /var/loki/rules
monolithic:
persistence:
storageClassName: longhorn
accessModes:
- ReadWriteOnce
size: 10Gi
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: "1"
memory: 1Gi
# 7d log retention (user can tune later).
limitsConfig:
retention_period: 7d
# Disable distributed components + gateway + minio (monolithic only).
test:
enabled: false
backend:
replicas: 0
read:
replicas: 0
write:
replicas: 0
singleBinary:
replicas: 0
gateway:
enabled: false
minio:
enabled: false
sops:
lastmodified: "2026-07-31T09:43:02Z"
mac: ENC[AES256_GCM,data:UpLILMOvXsgAcT4HkpYBYyYrLKPQeypQlJlGHzXU+7IE+Y1cWR17NPEwJZack17HMC/2c0IrlRBJtwreHULHqADrx34aQoTHN8cxRpr+XYfszx3o0CSm+Lwo2HupFmE1b6SA8KnV6C9Qqn/Wqvde7bFVaHYenvXxoLvnLOBIYQg=,iv:KBySVRbz5JpzO+8RN+YCR2UkpJ68bWhbRIL74kmMDNQ=,tag:hFW618Zc6oHVIcnkc/yqCw==,type:str]
pgp:
- created_at: "2026-07-31T09:43:02Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ//cVvg8AJiO7KGD1IyPVccefmfj4KHj7x0mc2W1BW1ZaLj
NSOef8ajJsRHrzY+DldPzqAOy0MyRYfCJzTEkcKe2OwZTIwCp52erFR5PQy8VLpX
85nNnKiWto9k1TdSNPidIPLNLwq24Rc4nkT5j2XcezjVNr9dV0+aWJMXd8MmZBmT
kyDct+W2rbiMSQMmM5R+apVbDNwGAqxNBS58G1pNcj/F2cC4sRQfLzdN6zdQaQa0
50S76I8HbR1ZM6JWX6OkM0saH8BKigfcuYF6xZbfqSrwGzGXDpWRW/2lBwUKFFVo
6abp205VFAzFvIIx2h7jaFOeuJMy1+mcJS9Uz/8gIbP507z7RxgGZEw2dIMII/Uu
OQyIIQArJAa6a/cv4kQ4bypYLlTl3mJDT54VJePsmLG9ZYrtLoyI8Q9weAPiWnvZ
yjp8XfImYyhJoTBPrvs5dY8q9l9lbGE1/jkbqWIaV+p3rrYl3SU5YypTt+Lvwdcl
7hB0UQISF4BlDgC+3jvptJLoAPgjFkPkW9DmY3XBMJvwRogIApOnJBmxL+RciuuK
nrTPZ1kYmXiZQqxCZJ3VBt77P2bgQneEaJf98khfDAJ/su3kvLoK6DPsLxT1p4oc
O8Eqaz4t0dZFBP753YnoKEv4hDf3ySCcuBF1vsPn63ITbi1cgUKvKb44/D3dk3bS
XgE1/X9jh7smSRPeo+kuvWBSDHg/aQEwobhuK1wOUx2UGDYT00S/3jYNRsoam6CS
LbG9x5v6bGOysfJNpZ1LfCWIz6sP/n6SVEYFCUYkoQsNutNYd9Yz/1MblO7hW84=
=jcSy
-----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
@@ -1,6 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
name: observability
labels:
pod-security.kubernetes.io/enforce: privileged
@@ -1,26 +0,0 @@
# Ingress exposing the VictoriaMetrics vminsert endpoint (vmsingle:8428)
# through Traefik as vm-internal.lan — used by the docker-host vmagent to
# remote_write metrics into the central VictoriaMetrics.
# external-dns auto-creates the vm-internal.lan A record pointing at the
# Traefik LoadBalancer (see kubernetes/system/external-dns).
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: vm-internal
namespace: observability
annotations:
external-dns.alpha.kubernetes.io/enabled: "true"
# No chart ingress is available for vmsingle, so declare it here.
spec:
ingressClassName: traefik
rules:
- host: vm-internal.lan
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: vmsingle-vm-victoria-metrics-k8s-stack
port:
number: 8428
@@ -1,19 +0,0 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: vm-victoria-metrics-k8s-stack
namespace: observability
spec:
interval: 1m
chart:
spec:
sourceRef:
kind: HelmRepository
name: vm
namespace: observability
chart: victoria-metrics-k8s-stack
version: "0.87.0"
interval: 1m
valuesFrom:
- kind: Secret
name: vmstack-values
@@ -1,8 +0,0 @@
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: vm
namespace: observability
spec:
interval: 1m
url: https://victoriametrics.github.io/helm-charts/
@@ -1,199 +0,0 @@
# victoria-metrics-k8s-stack Helm values
# The chart installs the VictoriaMetrics operator + CRDs and creates VMSingle,
# VMAgent, VMAlert, VMAlertmanager CRs.
# ---------------------------------------------------------------------------
# VictoriaMetrics single-binary (the metrics database)
# ---------------------------------------------------------------------------
vmsingle:
enabled: true
spec:
retentionPeriod: 7d
storage:
storageClassName: longhorn
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: "1"
memory: 1Gi
# ---------------------------------------------------------------------------
# vmagent — scrapes node-exporter, kube-state-metrics, kubelet, etc.
# The docker host runs its own vmagent that remote_writes through
# vm-internal.lan (the Traefik Ingress → this vmsingle).
# ---------------------------------------------------------------------------
vmagent:
enabled: true
spec:
selectAllByDefault: true
scrapeInterval: 20s
tolerations:
- key: ENC[AES256_GCM,data:SyutB0y9QtqQ,iv:EKRXNGtUovQYsESHFQTGygP09O2UWtLuBEQQcYZm3Oc=,tag:zh7CYOZleSgbbQhYZvcT+w==,type:str]
value: ENC[AES256_GCM,data:So+8xmHYSxs=,iv:7sfUBAaMZd7imjVx14lusVn58cJQ4HpTkaPy5Eal2dY=,tag:hRBjT6wuEfG3Z+ZiPJhwQQ==,type:str]
operator: Equal
effect: NoSchedule
- key: ENC[AES256_GCM,data:lj9OurynU8pRt4/MhgyevjmV0b7Zq+WG/9+zRRvPeA+RYZsV+A==,iv:LjuhErDT0bDlLcpo/AlNykz8Xu89B+nx1ja+HkPNXwo=,tag:5xM6XHrCdEejE7ituQ8W4Q==,type:str]
operator: Exists
effect: NoSchedule
# ---------------------------------------------------------------------------
# kube-state-metrics + node-exporter (metrics sources)
# ---------------------------------------------------------------------------
kube-state-metrics:
enabled: true
prometheus-node-exporter:
enabled: true
# ---------------------------------------------------------------------------
# Grafana (UI) — served behind ingress at grafana.lan.
# ---------------------------------------------------------------------------
grafana:
enabled: true
persistence:
enabled: true
storageClassName: longhorn
accessModes:
- ReadWriteOnce
size: 5Gi
adminUser: admin
# SOPS encrypts this when the file is processed.
adminPassword: ENC[AES256_GCM,data:vpPvJA/PktMnsg/IovYfsD4lDBndUw==,iv:b4eLMEcUMJj4BwyeYw1kw2sZuieyr2xL9et+R7ss0BU=,tag:u0RcTp6mkQNAGkblG4/xww==,type:str]
# Provision a Loki datasource alongside the chart's default VictoriaMetrics
# datasource so metric/log correlation works in one UI.
datasources:
datasources.yaml:
apiVersion: ENC[AES256_GCM,data:Uw==,iv:KYTMBV53yMbojMaqNinYpm/Uj5ylV86jcdJTdxuy+G0=,tag:IbIpiSBQFw7YSTQg0WRGqg==,type:int]
datasources:
- name: ENC[AES256_GCM,data:BPfR8Q==,iv:MkMhH3IJfBZzbIcqQw7y6bfJB/4Ew4feZNugjovk5O0=,tag:jaa43tzIXkE8kWZp2R/kcg==,type:str]
type: ENC[AES256_GCM,data:WWncww==,iv:hPqJE0KCidSBnf11wxFH+Je+YKztWmeToBqi39Qf4ZQ=,tag:c9enJ2VgQqDJVbasvgG+Dw==,type:str]
url: ENC[AES256_GCM,data:YkS66tpWXpW62Dtful0KNCwoZ3rG3nQtDBUsNQUwdQ+eqtG38JTrAudQqnsRD51q,iv:Mu3Sc6T2xypdot9dA1DHc8nD7UI8372nqlveLITR82E=,tag:1VmmIg+xR9qjWcvPKVYsJQ==,type:str]
access: ENC[AES256_GCM,data:af3GpjE=,iv:MAYKfklF+wCC/XN+4snebjPAnW4KpYzaMMGYds7rG18=,tag:X+oFiDAiCb1f7cfREqFT7A==,type:str]
isDefault: ENC[AES256_GCM,data:Zgu4Hn8=,iv:nnVB/in75nPAQos0Dfl6abBrHwT8tCt5X7lcCYBZbLc=,tag:u1UvkSj6SjcMm06NzKMGDA==,type:bool]
jsonData:
maxLines: ENC[AES256_GCM,data:88JJqA==,iv:lKsZa024I6223UEu0SHuZ3N9LZrzw0WBTfC+L2/3ljI=,tag:YvqieXK36xMmC/sSJ11NIg==,type:int]
ingress:
enabled: true
ingressClassName: traefik
annotations:
external-dns.alpha.kubernetes.io/enabled: "true"
hosts:
- grafana.lan
path: /
pathType: Prefix
tls: []
# ---------------------------------------------------------------------------
# vmalert — evaluates VMRule CRs against VictoriaMetrics, forwards firing
# alerts to Alertmanager. selectAllByDefault picks up all VMRules in the
# namespace (including our vmalert-rules.yaml VMRule CR).
# ---------------------------------------------------------------------------
vmalert:
enabled: true
spec:
selectAllByDefault: true
evaluationInterval: 20s
notifiers:
- url: http://vm-victoria-metrics-k8s-stack-alertmanager.observability.svc.cluster.local:9093
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
# ---------------------------------------------------------------------------
# Alertmanager — 1 replica; inline config with a single n8n webhook receiver.
# n8n runs on the docker host and fans out to email/Telegram/whatever.
# ---------------------------------------------------------------------------
alertmanager:
enabled: true
spec:
replicaCount: 1
port: "9093"
selectAllByDefault: true
storage:
volumeClaimTemplate:
spec:
storageClassName: longhorn
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
config:
route:
receiver: n8n-webhook
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receivers:
- name: n8n-webhook
webhook_configs:
- url: http://n8n.lan/webhook/observability-alert
send_resolved: true
extraRules:
node-alerts:
groups:
- name: node
rules:
- alert: HighNodeCPU
expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 10m
labels:
severity: warning
annotations:
summary: High CPU on {{ $labels.instance }}
description: CPU usage above 80% for 10 minutes.
- alert: HighNodeRAM
expr: 100 - ((node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100) > 85
for: 10m
labels:
severity: warning
annotations:
summary: High RAM on {{ $labels.instance }}
description: RAM usage above 85% for 10 minutes.
- alert: LowDiskSpace
expr: |
100 - ((node_filesystem_avail_bytes{mountpoint!~"/run.*|/var/lib/docker.*"} /
node_filesystem_size_bytes{mountpoint!~"/run.*|/var/lib/docker.*"}) * 100) > 85
for: 10m
labels:
severity: warning
annotations:
summary: Low disk space on {{ $labels.instance }} {{ $labels.mountpoint }}
description: Disk usage above 85% for 10 minutes.
sops:
lastmodified: "2026-07-28T16:39:09Z"
mac: ENC[AES256_GCM,data:Ymxmmkui0Nuv35Yq6v4BXM4xGhvjAufexW7fIm9fUIdTTXZ3e10PitNCZXKiaDwwCJfdEkNZri7jPAYzhTzKMIdcTKnOMImsMjdiJZwRwwbKcYVay0A6KSLJ8eFjDRRYhlCXbsAIRlQHpFh4UkssKdu40mIiudU0qIVm04ppbno=,iv:R8kpITPYSbQ1yZw5IK0fArssxUtIjNmvzknOrLJQcuk=,tag:/CRcr1VZAIKIPbcag05uTw==,type:str]
pgp:
- created_at: "2026-07-28T16:39:08Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiARAAmOxyx5eH5Jykp/GDL79REgf61iGujtPiUVy8CT3o7O5k
tTGma6rRXK5wZV/iGN3wOQehF19Oy2iYwMfxilRwpB69RFwyKPKdHDDWMWNXv5Th
wJnNjVjWZ0xiRautWPn/TjDOJZ6j6p7lQ3IcQ3vzuap1RVRIXv081DxJGR9JbeYl
khmrl1+zecwxS87JK+fLko9NIBb5JgFEtEf1RvLyFak8nZu5cNCu+PCykALvUaO7
V5NAaF1aV9cdz8G9TZWmHZsIlDDE9/oro2aLR7cr8uxnKQhWerttqvyDYNwYzNKW
qgsUplTxTmyuc9DdnLDfJ55Ncuv9qS5/4/p5GpsHrteD6oiPNjXaxR8cBVFLvGwp
kQb/VZgOGAnkYlMCUG8APiwRhbpAlyy51hKBqVh+a9iRlzZEWHKlxcvIrcFAQaHt
sDXyg36F0GCoHiMAqHKG0kRcbTV7Sq0JZVoLU/qxvaDfqvyCZO7X/U/YsSWNbWL0
emyBfeSvBX9h62NJx2aw8xKyiL+aeVfzSKAaXHMd/r4gKxBw/kVHAljKwRzbL85j
UHeLUvqVkXs1mtIqGgUnpCcAVuV83omgcOwF44FitG/f9GCx+UWTvScwaw5ywuG3
J/4fOaA3K0Z4e/mOejARd4jLSPktSRpA01k9kjYY8UBn7TzQ0LrMLj5dxh8BpWrS
XgECZapi+q6IjIses7+JqkWiP25hcglhqK3LAiUapA0c5UmAa5Vf7jfnkFm8eUdZ
bA7ZnhX8nxK9n7JdSxrZhrbPWMO8hF/XKi7KTZMvgXFlb4/qP96y7oeqzKYcnvE=
=pmSq
-----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 @@
# Root Kustomization for Flux
# Explicitly lists all components to exclude:
# - cert-manager: managed by separate Flux Kustomization (CRD dependency)
# - cert-manager-issuer: managed by separate Flux Kustomization (depends on cert-manager)
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
# System components
- system/cilium # cilium IP pool is managed here
- system/blocky
- system/caddy
- system/coredns
- system/csi-driver-nfs
- system/longhorn
- system/external-dns
- system/flux
- system/traefik
# Code
- code/gitea
- code/harbor
# Home
- home/home-assistant
- home/zigbee2mqtt
# Infrastructure
- infrastructure/authentik
- infrastructure/mail/stalwart
- infrastructure/observability
# Personal
- personal/linkwarden
- personal/notesnook
- personal/photoprism
# Production
- production/umami
- production/vhaudiquet-fr
# Tools
- tools/dashy
- tools/glance
+23 -23
View File
@@ -18,46 +18,46 @@ configuration:
disableNewSSOUsers: false
PublicCredentialsEnabled: false
authURL: http://linkwarden.lan/api/v1/auth
authSecret: ENC[AES256_GCM,data:Qaxb9o3xtrDo9rsxHFpm6tkRd7OWPDyjiIyoPvc1SiIQIthOwXyHQ0b7YAW8rGg1vKBg2fDCIUK4Kgoyr26qUw==,iv:KFt4KqTUwB830flAmxfw7tQrLktacTtWmYDjBAiugk4=,tag:IAi0x3AlCdCTXz7MBryg8A==,type:str]
authSecret: ENC[AES256_GCM,data:UUZagqAY6+9AM4gMv9WFsWFSzjLxAALUz2iGg3dBIrpP+JCdJWVbXIRpZ8bZPJxvwnTcZSPOsLHlqzeqJRHubA==,iv:xgPnCNp2dpy8UG/fjEHPUxdXYXEQzFn3K/EX9lfjpWo=,tag:1uFZDdgGUvMvyKHj93z4yw==,type:str]
sso:
enabled: true
authentik:
enabled: true
clientId: ENC[AES256_GCM,data:1u8Xe9ZMosAJWwPGZCloAFEQE6n0eTtBzaw149zsuL/yrVoiU8s7Pg==,iv:uxfiXfpocKbiFIu0dPq0So6Kdfr3iMFUM4hRJm3eQPQ=,tag:BxgV/Wl2ZE80+08uaDnsDw==,type:str]
clientSecret: ENC[AES256_GCM,data:LBIh0Jc2MtS5pvOhmFbWSrQaOMiM05e2i5aeMbDJJGNArQ7PGK+okbltWnZHonIwGU/sriFm/x4BMz+snrd+NgTUR2aPPXnomK6f9dEmSXNjLxgnVFUmgcT2P7zqlKUBjMT+SKjZLELfYGzysKTRkXHOCrOoGX8ZobEgOXGflpQ=,iv:iADfUCL30NrwPPof7r/ppO3Rt7ap4RoOkKpBuzyoO8A=,tag:lrt50iqFsZcEdBx25BY0PA==,type:str]
clientId: ENC[AES256_GCM,data:6XqAMjwywGgZK23ywm1GKWpIhIrXNa28Z52+0J1yhocBxLXoJAiocw==,iv:DiIpcD0H6wnIkXCMPmhLEHTzE6qKQrotGZ7q7Lv2iME=,tag:Kx80RoPf7BFMWEO1lZ4wCQ==,type:str]
clientSecret: ENC[AES256_GCM,data:OO8vjjWVxzUNuY/Jhk348RykWnVRQ/xthunOyI4XVzCmT0WXAH/uWSupljfWQW8aj4WzUUHMpJOvFpd3iYTExFn6QqyBisOgVzS9jy4sP4qdhnSpu9jXzEUNmKyjQncl3QTQCcPZMjlGGf0oJzZgHivVWl6rFbnYQOJHDlu3r48=,iv:H2OvOpH2yxUivH8RTvSnM9k86i9jUJKcUmNPpSSos6g=,tag:XXTyOC+Hj7BvgZJ7qxEZyA==,type:str]
customName: Authentik
issuer: https://authentik.vhaudiquet.fr/application/o/linkwarden
persistence:
enabled: true
storageClass: longhorn
storageClass: nfs-csi
postgres:
enabled: true
host: linkwarden-postgresql.linkwarden.svc.kube-talos.lan
username: ENC[AES256_GCM,data:eUTE15OnJZ4dBQ==,iv:bN7y9EwD9rzzH3pm6JJvFkSHmdXkCunui2tyerb3z98=,tag:apU0hdiJbp5fgKjesLfdrw==,type:str]
password: ENC[AES256_GCM,data:qA/FQZdMQG3vdQ==,iv:S0fBAfNiNUi1t7coaKFLloaXolv7l//tUVnSui0Tmo0=,tag:SbW/QBMoNqUSENkSCR83AQ==,type:str]
username: ENC[AES256_GCM,data:N+ozpU6TgAZSLA==,iv:XJT1fUe2XqSxpuuPfmzbyrJUUInUEhLyNddOX0jogZQ=,tag:z9rCjOKISMT+wpfwUzFd1Q==,type:str]
password: ENC[AES256_GCM,data:G7dF3Oo+1wzL9g==,iv:yAjh22rwaBhKtHgYAmQEjFSMFspOpG2hThwwjAo2KJk=,tag:DdXlyNk+TfR0IuSpQG3+Zg==,type:str]
database: linkwarden
sops:
lastmodified: "2026-07-18T14:22:17Z"
mac: ENC[AES256_GCM,data:DoHEvtWEetZGb/lCzQalLAMUlAZ7OVG66bDSaGY7s0i8mhDzRxrkvPq7FL07rnDQoLSW+SFSq6h7LB1PV1HodW35b4rmDzpCCHQ/S7Gj8WW/sX0t6dFpF1GlYeseqAMtNMPeMf095Q9LIHmQlILmjPAKbAuOg6shQ9oIesBzSDw=,iv:3D+wZjBHp0gZRDOvmVHaTIyZlC9IzMupvXfbvYYZVm4=,tag:ui9jt5/F/9NJ08P7MD+7AQ==,type:str]
lastmodified: "2025-09-15T21:48:06Z"
mac: ENC[AES256_GCM,data:i9Mg17Z72cBJOSvmOlHkl0x0/FqhpCqS8iTGTYKlXacXi9E0nYYZr/y74qVjhubEaI1y6cRYXgaePI47lkyfvTzB3VGEpEs/y5fiL+PfiuV8Z18J9244+TyoasYR/a2sdRuJcY5jm6PSTKoGiwGnyZEthVwt1T38yr5msW3D79A=,iv:yj7uCySaoZcnO+7XsgB1EMfZOMwHSA0mtJXUq66MUgQ=,tag:YRvUG0/hj8Bjp+pMdJvePQ==,type:str]
pgp:
- created_at: "2026-07-18T14:22:16Z"
- created_at: "2025-09-15T21:48:06Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ/+LxkvBdTDic8D31VBAtMiKJJ4nHAIpxja6gHsyVCmS+LP
VOqnEvvEBxf3ifXqwlYh/rY7ywjMyuQAW03zIlNq+9Ufv5QV9Py+UTiQV1mfmRoa
73kINswzbUGvH+HXVkcRGjusS/StPMWKC6jwyrov09gtTF1rJUfcfenqy2waHZOk
JhwcxhrPUnHGOsv4f1+91CCjKHux3/FVagpxJcEvxckMJweuZWm59z77dbwF1lQ3
ws4VMLKzt2wiYSULCDr5KM2YlYWkvzheqhwnOVKXk11ewM+6n8RHIvsE03nvkfRf
tJduJYmXnz249SM4hq3GvyMq+j3qShIMvvKRMv6+aYMZ3SFzAIxtV0dA3lCoA9oy
mGWvImrA7JX4GsG44tEzu0ECvoFV8lEb39QKBXBf8fN6UExasF4pSm276ZGG4Eom
IpfpuaB9oYL4TOEH0/56IEc2BRlvAm62ibra5jNCVLnLB0pzE3KdN7ZYMQyXooZi
dOa56z4KidI4N5oDTc63Hkg0tApdV0x+Rtm7qgdhEp/1i4zqciQqb8//yN6CAb7I
DkyPilrvNkZw95iGqpKVLrAp57BaFHLYNr0O7+WS9urCIUQl3Q37Nz2HyNLJt0Ej
i3VgiJUIoy5NcAIBIFvuAJDsXB+FQxzg+7XUZL44xxsSvA248Shz1CYH9CgwbszS
XgHdJTIcrq3ReybtFVDPtqMkLyItA1fbJzpCr4Fwk922hmEpqBeMHx1Upy81MZJj
T+4v8xBo7KR/6sx3U9kO/TjV7AhdTJPRlgG0WfnfLMncCkrvg4cQWxEIkySShFo=
=XPzS
hQIMA7uy4qQr71wiAQ//dICUFaREdeVKhKkK7iPji73IRFZEnwoZwEnR0vtCBL3d
HXFfdXUMOVcXOvkkuF9zG52flUZBpVgilQz2W8Y7xI3tU8xX6wxmuz8LjegidCHk
R2xKAJ5iCEWZTIouFwg4fM399Mm9xhiIPuM4+25DAZnSJJAc7fQ2NaNaA8vjbJQ7
YUnqkmE+QPGbyeykudlTFfl/zZzrgKbQqWuUmD/vq1XckUaPxM5cdeFDsg87AZCs
o51lQ39b+CpWmdbDbJDF5nMWUrCzIz9okptoNfHM/5E0Jg53JBsXBvsqwWTOI5vo
djilDfsyu5nQj7UDstaax839T7P5gm5ass2/YtIjgrJUczyRt6vS97zuXLsbEGpH
6hXHan7OormqbmISnFrL68Q4w6JUZev43bdzqtX0EnYHNZVLXH3qAxD5EnuL/i20
oY/oMEteFh86Smw/LXwtWjVfPKYzNQ6GTkTCzM3hVcfMOzdFVPgYDM+5EXF+/oAB
+BGqZvWW4G3G9sbPTRSJ1k+toWuC/erY41r+g3+KHbW73YdqIVwBsTDAFhPPNbe5
hnr1JFLQ75GHdDRnKRl3nZSPc2j9JMUtMhX+rKwLb/0DoVjNz0lFut/Tj+6xiG/1
SqHTpROU1tkip+rP0shzdu218+hjrzj+cDKkawoqmpD9gOm83P7YEqrIwcBj+TPS
XgE3UHtwHdJM38kfPm1fkTuCejlAQ3Hsz6W4PSbXJfY8w1gO241dEzy+b0At9Rv2
6IklhRBAs4ioH/hD653yz0mkCYRpOLYDJU2iMWZdv61YLXb4rsnAwr6xLbDHDXM=
=69Pc
-----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)$

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