feat(gitops): migrate domain to riotpiao.com, add CNPG + Forgejo HA on Redis/Postgres, wire ArgoCD apps — enables cluster rebuild after etcd wipe and unblocks the git-source chicken-egg via standalone Helm-source Applications

This commit is contained in:
Story Crater Bot
2026-08-18 15:08:02 -07:00
parent 491e88e493
commit 54bfb5ade6
86 changed files with 889 additions and 446 deletions
@@ -0,0 +1,45 @@
# k8s/bootstrap/cert-manager/letsencrypt-issuer.yaml
# Let's Encrypt ClusterIssuers for *.riotpiao.com, DNS-01 via Cloudflare
# (wildcard certs require DNS-01 — HTTP-01 can't prove ownership of a wildcard name).
#
# Prereq (apply manually, not in git — token is a secret):
# kubectl create secret generic cloudflare-api-token-secret \
# --namespace cert-manager \
# --from-literal=api-token=<CLOUDFLARE_API_TOKEN>
# Token scope: Zone:DNS:Edit for the riotpiao.com zone.
#
# Start with letsencrypt-staging to validate the solver, then point
# Certificate.issuerRef at letsencrypt-prod once staging issues cleanly.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-staging-account-key
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token-secret
key: api-token
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-prod-account-key
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token-secret
key: api-token
+16 -12
View File
@@ -4,7 +4,7 @@
# Why this is needed:
# Grafana v10+ does OIDC auto-discovery by fetching
# /.well-known/openid-configuration from Authentik. When Grafana reaches
# Authentik via the external hostname (authentik.riotpiao.homelab.com), the
# Authentik via the external hostname (authentik.riotpiao.com), the
# HTTP Host header is preserved and Authentik returns external URLs in the
# discovery response. Without this rewrite, the hostname doesn't resolve
# inside the cluster and Grafana falls back to the internal service DNS,
@@ -30,29 +30,33 @@ data:
}
prometheus :9153
# VPN Access: Map api-server.cluster.local to cluster API IP
# Allows secure cluster access via WireGuard tunnel (Shadowrocket/Talos)
rewrite name api-server.cluster.local kubernetes.default.svc.cluster.local
# Forgejo: route through nginx ingress like every other host below. nginx
# terminates TLS (wildcard-tls) on :443 and routes both /v2/ (container
# registry) and web/git to forgejo-gitea-http:3000.
# Do NOT point this at forgejo-gitea-http directly: that service only serves
# port 3000, so containerd image pulls (which use https/:443) get
# `dial tcp <clusterIP>:443: i/o timeout`. SSH stays on its own LB service.
rewrite name forgejo.riotpiao.homelab.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name forgejo.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
# Rewrite homelab hostnames to the nginx ingress controller so in-cluster pods
# hit nginx TLS termination (cert-manager cert) and preserve the Host header.
# Routing through nginx — not directly to the backend service — is critical:
# direct rewrites to the backend bypass nginx TLS and expose each app's own
# self-signed cert, which nothing in the cluster trusts.
rewrite name authentik.riotpiao.homelab.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name grafana.riotpiao.homelab.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name minio.riotpiao.homelab.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name minio-api.riotpiao.homelab.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name argocd.riotpiao.homelab.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name vault.riotpiao.homelab.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name loki.riotpiao.homelab.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name prometheus.riotpiao.homelab.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name portainer.riotpiao.homelab.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name longhorn.riotpiao.homelab.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name authentik.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name grafana.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name minio.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name minio-api.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name argocd.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name vault.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name loki.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name prometheus.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name portainer.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
rewrite name longhorn.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
+15 -15
View File
@@ -1,10 +1,10 @@
# k8s/ingress/ingress.yaml
# Ingress rules for all homelab services.
# TLS is handled centrally: nginx serves the wildcard-tls cert (*.riotpiao.homelab.com)
# TLS is handled centrally: nginx serves the wildcard-tls cert (*.riotpiao.com)
# as its default-ssl-certificate. No per-rule tls: blocks or cert-manager annotations
# are needed — cert-manager manages one cert, nginx uses it for all hosts.
#
# DNS: *.riotpiao.homelab.com must resolve to 10.6.0.1 (WireGuard) or 192.168.1.160 (LAN).
# DNS: *.riotpiao.com must resolve to 10.6.0.1 (WireGuard) or 192.168.1.160 (LAN).
# ── Grafana ───────────────────────────────────────────────────────────────────
apiVersion: networking.k8s.io/v1
@@ -17,7 +17,7 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: grafana.riotpiao.homelab.com
- host: grafana.riotpiao.com
http:
paths:
- path: /
@@ -38,7 +38,7 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: loki.riotpiao.homelab.com
- host: loki.riotpiao.com
http:
paths:
- path: /
@@ -62,7 +62,7 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: authentik.riotpiao.homelab.com
- host: authentik.riotpiao.com
http:
paths:
- path: /
@@ -85,7 +85,7 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: vault.riotpiao.homelab.com
- host: vault.riotpiao.com
http:
paths:
- path: /
@@ -113,7 +113,7 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: minio.riotpiao.homelab.com
- host: minio.riotpiao.com
http:
paths:
- path: /
@@ -138,7 +138,7 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: minio-api.riotpiao.homelab.com
- host: minio-api.riotpiao.com
http:
paths:
- path: /
@@ -159,7 +159,7 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: prometheus.riotpiao.homelab.com
- host: prometheus.riotpiao.com
http:
paths:
- path: /
@@ -183,7 +183,7 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: portainer.riotpiao.homelab.com
- host: portainer.riotpiao.com
http:
paths:
- path: /
@@ -210,7 +210,7 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: forgejo.riotpiao.homelab.com
- host: forgejo.riotpiao.com
http:
paths:
- path: /
@@ -238,7 +238,7 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: argocd.riotpiao.homelab.com
- host: argocd.riotpiao.com
http:
paths:
- path: /
@@ -259,7 +259,7 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: longhorn.riotpiao.homelab.com
- host: longhorn.riotpiao.com
http:
paths:
- path: /
@@ -285,7 +285,7 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: temporal.riotpiao.homelab.com
- host: temporal.riotpiao.com
http:
paths:
- path: /
@@ -307,7 +307,7 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: kmsvc.riotpiao.homelab.com
- host: kmsvc.riotpiao.com
http:
paths:
- path: /
+6 -6
View File
@@ -1,16 +1,16 @@
# k8s/ingress/nginx-values.yaml
# Nginx Ingress Controller — bare-metal homelab config.
# LoadBalancer service with Cilium LB-IPAM assigns fixed IP (192.168.1.160).
# Access services at https://grafana.riotpiao.homelab.com (80/443 via LoadBalancer).
# Access services at https://grafana.riotpiao.com (80/443 via LoadBalancer).
controller:
kind: DaemonSet
# Single wildcard cert served for every *.riotpiao.homelab.com host.
# Applied by the ingress-nginx presync hook (wildcard-cert.yaml) before nginx starts.
# nginx hot-reloads when cert-manager renews homelab-tls — no restart needed.
# Single wildcard cert served for every *.riotpiao.com host (Let's Encrypt,
# see ../ingress/riotpiao-com-cert.yaml + ../cert-manager/letsencrypt-issuer.yaml).
# nginx hot-reloads when cert-manager renews riotpiao-com-tls — no restart needed.
extraArgs:
default-ssl-certificate: "ingress-nginx/homelab-tls"
default-ssl-certificate: "ingress-nginx/riotpiao-com-tls"
hostPort:
enabled: true
@@ -19,7 +19,7 @@ controller:
https: 443
# TCP proxy: forward port 2222 on every node → Forgejo SSH service.
# This lets `git clone [email protected].homelab.com:repo` work via the
# This lets `git clone [email protected]:repo` work via the
# same hostname as HTTPS without a separate LoadBalancer IP for SSH.
tcp:
2222: "cicd/forgejo-gitea-ssh:2222"
@@ -0,0 +1,25 @@
# k8s/bootstrap/ingress/riotpiao-com-cert.yaml
# Public wildcard cert for *.riotpiao.com, signed by Let's Encrypt (DNS-01 via
# Cloudflare, see ../cert-manager/letsencrypt-issuer.yaml). Distinct from
# homelab-tls (self-signed homelab-ca, internal *.riotpiao.com) —
# reference riotpiao-com-tls explicitly on ingresses that expose riotpiao.com
# hosts to the internet; it is not nginx's default-ssl-certificate.
#
# issuerRef starts on letsencrypt-staging. Switch to letsencrypt-prod once the
# staging cert issues cleanly, then delete this Certificate's Secret to force
# a re-issue against prod (staging certs aren't browser-trusted).
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: riotpiao-com-tls
namespace: ingress-nginx
spec:
secretName: riotpiao-com-tls
dnsNames:
- "*.riotpiao.com"
- "riotpiao.com"
issuerRef:
name: letsencrypt-staging
kind: ClusterIssuer
duration: 2160h # 90 days (LE max)
renewBefore: 720h # renew 30 days before expiry
-22
View File
@@ -1,22 +0,0 @@
# k8s/ingress/wildcard-cert.yaml
# Single wildcard TLS certificate for all *.riotpiao.homelab.com services.
# Lives in the ingress-nginx namespace and is set as nginx's default-ssl-certificate,
# so every ingress host gets it automatically — no per-service TLS blocks needed.
#
# Renewal: cert-manager auto-renews 30 days before expiry (renewBefore: 720h).
# nginx detects the secret update via its K8s watch and hot-reloads — no pod restart.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: homelab-tls
namespace: ingress-nginx
spec:
secretName: homelab-tls
dnsNames:
- "*.riotpiao.homelab.com"
- "riotpiao.homelab.com"
issuerRef:
name: homelab-ca
kind: ClusterIssuer
duration: 8760h # 1 year
renewBefore: 720h # renew 30 days before expiry