fix: envoy-gateway migration

This commit is contained in:
auricom
2025-08-19 09:08:41 +02:00
parent 539ec1b7db
commit 6db214c211
81 changed files with 554 additions and 299 deletions

View File

@@ -0,0 +1,27 @@
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: pgadmin
spec:
hostnames:
- pgadmin.${SECRET_EXTERNAL_DOMAIN}
parentRefs:
- group: pgadmin.networking.k8s.io
kind: Gateway
name: internal
namespace: network
sectionName: https
rules:
- backendRefs:
- group: ''
kind: Service
name: pgadmin
namespace: database
port: 5050
weight: 1
matches:
- path:
type: PathPrefix
value: /

View File

@@ -1,32 +0,0 @@
---
# trunk-ignore(checkov/CKV_K8S_21)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: pgadmin
annotations:
gethomepage.dev/enabled: "true"
gethomepage.dev/name: pgAdmin
gethomepage.dev/description: PostgreSQL management tool.
gethomepage.dev/group: Infrrastructure
gethomepage.dev/icon: pgadmin.png
gethomepage.dev/pod-selector: >-
app in (
pgadmin
)
spec:
ingressClassName: internal
tls:
- hosts:
- &host pgadmin.${SECRET_EXTERNAL_DOMAIN}
rules:
- host: *host
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: pgadmin
port:
number: 5050

View File

@@ -4,6 +4,6 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./externalsecret.yaml
- ./ingress.yaml
- ./httproute.yaml
- ./pgadmin.yaml
- ./service.yaml

View File

@@ -93,5 +93,4 @@ spec:
interval: 1m
scrapeTimeout: 10s
serviceAccount:
create: true
name: *app
dragonfly-operator: {}

View File

@@ -4,9 +4,9 @@ apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: &app dragonfly
namespace: flux-system
namespace: &namespace database
spec:
targetNamespace: database
targetNamespace: *namespace
commonMetadata:
labels:
app.kubernetes.io/name: *app
@@ -29,9 +29,9 @@ apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: &app dragonfly-cluster
namespace: flux-system
namespace: &namespace database
spec:
targetNamespace: database
targetNamespace: *namespace
commonMetadata:
labels:
app.kubernetes.io/name: *app

View File

@@ -4,9 +4,9 @@ apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: &app influx
namespace: flux-system
namespace: &namespace database
spec:
targetNamespace: database
targetNamespace: *namespace
commonMetadata:
labels:
app.kubernetes.io/name: *app

View File

@@ -94,8 +94,6 @@ spec:
controller: *app
type: LoadBalancer
externalTrafficPolicy: Local
annotations:
external-dns.alpha.kubernetes.io/hostname: "mqtt.${SECRET_EXTERNAL_DOMAIN}"
ports:
mqtt:
port: 1883

View File

@@ -9,8 +9,6 @@ spec:
commonMetadata:
labels:
app.kubernetes.io/name: *app
components:
- ../../../../components/gatus/guarded
interval: 1h
path: ./kubernetes/apps/database/mosquitto/app
postBuild:

View File

@@ -32,7 +32,7 @@ spec:
PAPERLESS_OAUTH_DIGEST: "{{ .OUTLINE_OAUTH_DIGEST }}"
KOMGA_OAUTH_CLIENT_SECRET: "{{ .OUTLINE_OAUTH_CLIENT_SECRET }}"
KOMGA_OAUTH_DIGEST: "{{ .OUTLINE_OAUTH_DIGEST }}"
SECRET_PUBLIC_DOMAIN: "{{ .SECRET_PUBLIC_DOMAIN }}"
SECRET_EXTERNAL_DOMAIN: "{{ .SECRET_EXTERNAL_DOMAIN }}"
dataFrom:
- extract:
key: authelia

View File

@@ -23,6 +23,7 @@ spec:
postBuild:
substitute:
APP: *app
GATUS_STATUS: "401"
VOLSYNC_CAPACITY: 2Gi
prune: true
retryInterval: 2m

View File

@@ -24,6 +24,7 @@ spec:
postBuild:
substitute:
APP: *app
GATUS_STATUS: "401"
VOLSYNC_CAPACITY: 2Gi
prune: true
retryInterval: 2m

View File

@@ -20,9 +20,6 @@ spec:
values:
controllers:
freshrss:
annotations:
reloader.stakater.com/auto: "true"
secret.reloader.stakater.com/reload: authelia-secret
containers:
app:
image:
@@ -31,20 +28,25 @@ spec:
env:
TZ: ${TIMEZONE}
CRON_MIN: 18,48
DOMAIN: "https://freshrss.${SECRET_EXTERNAL_DOMAIN}/"
envFrom:
- secretRef:
name: freshrss-secret
DOMAIN: "freshrss.${SECRET_EXTERNAL_DOMAIN}"
LISTEN: &port 8080
probes:
liveness:
enabled: true
readiness:
enabled: true
resources:
requests:
cpu: 50m
memory: 256Mi
cpu: 12m
memory: 128M
limits:
memory: 512M
service:
app:
controller: *app
ports:
http:
port: &port 80
port: *port
route:
app:
hostnames: ["{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"]
@@ -58,7 +60,13 @@ spec:
port: *port
persistence:
config:
enabled: true
existingClaim: *app
globalMounts:
advancedMounts:
freshrss:
app:
- path: /var/www/FreshRSS/data
subPath: data
readOnly: false
- path: /var/www/FreshRSS/extensions
subPath: extensions
readOnly: false

View File

@@ -3,5 +3,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./externalsecret.yaml
- ./helmrelease.yaml

View File

@@ -18,7 +18,6 @@ spec:
substitute:
APP: *app
GATUS_PATH: /i/
GATUS_STATUS: "401"
VOLSYNC_CAPACITY: 2Gi
prune: true
retryInterval: 2m

View File

@@ -23,6 +23,7 @@ spec:
postBuild:
substitute:
APP: *app
GATUS_STATUS: "401"
VOLSYNC_CAPACITY: 5Gi
prune: true
retryInterval: 2m

View File

@@ -1,19 +0,0 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: jobs
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: jobs-edit
namespace: default
subjects:
- kind: ServiceAccount
name: jobs
roleRef:
kind: ClusterRole
name: edit
apiGroup: rbac.authorization.k8s.io

View File

@@ -51,5 +51,3 @@ resources:
- ./vikunja/ks.yaml
- ./webhook/ks.yaml
- ./zigbee2mqtt/ks.yaml
# Default resources
- jobs-rbac.yaml

View File

@@ -20,6 +20,7 @@ spec:
postBuild:
substitute:
APP: *app
GATUS_STATUS: "401"
VOLSYNC_CAPACITY: 2Gi
prune: true
retryInterval: 2m

View File

@@ -5,4 +5,3 @@ kind: Kustomization
resources:
- ./externalsecret.yaml
- ./helmrelease.yaml
- ./sync

View File

@@ -39,3 +39,28 @@ spec:
targetNamespace: *namespace
timeout: 5m
wait: false
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: &app lychee-sync
namespace: &namespace default
spec:
commonMetadata:
labels:
app.kubernetes.io/name: *app
interval: 1h
path: ./kubernetes/apps/default/lychee/sync
postBuild:
substitute:
APP: *app
prune: true
retryInterval: 5m
sourceRef:
kind: GitRepository
name: flux-system
namespace: flux-system
targetNamespace: *namespace
timeout: 15m
wait: false

View File

@@ -51,5 +51,19 @@ spec:
controller: *app
enabled: false
serviceAccount:
create: false
name: jobs
lychee-sync: {}
rbac:
roles:
lychee-sync:
type: ClusterRole
rules:
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
bindings:
gatus:
type: ClusterRoleBinding
roleRef:
identifier: lychee-sync
subjects:
- identifier: lychee-sync

View File

@@ -68,7 +68,7 @@ spec:
sectionName: https
rules:
- backendRefs:
- name: *app
- name: qbittorrent-app
port: *port
persistence:
config:

View File

@@ -4,4 +4,3 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./helmrelease.yaml
- ./upgrade-p2pblocklist

View File

@@ -32,3 +32,28 @@ spec:
targetNamespace: *namespace
timeout: 5m
wait: false
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: &app qbittorrent-upgrade-p2pblocklist
namespace: &namespace default
spec:
commonMetadata:
labels:
app.kubernetes.io/name: *app
interval: 1h
path: ./kubernetes/apps/default/qbittorrent/upgrade-p2pblocklist
postBuild:
substitute:
APP: *app
prune: true
retryInterval: 5m
sourceRef:
kind: GitRepository
name: flux-system
namespace: flux-system
targetNamespace: *namespace
timeout: 15m
wait: false

View File

@@ -54,5 +54,22 @@ spec:
controller: *app
enabled: false
serviceAccount:
create: false
name: jobs
qbittorrent-upgrade-p2pblocklist: {}
rbac:
roles:
qbittorrent-upgrade-p2pblocklist:
type: ClusterRole
rules:
- apiGroups: [""]
resources: ["pods", "pods/log", "pods/exec", "pods/ephemeralcontainers"]
verbs: ["get", "list", "create", "update", "patch"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "patch", "update"]
bindings:
gatus:
type: ClusterRoleBinding
roleRef:
identifier: qbittorrent-upgrade-p2pblocklist
subjects:
- identifier: qbittorrent-upgrade-p2pblocklist

View File

@@ -17,6 +17,7 @@ spec:
postBuild:
substitute:
APP: *app
GATUS_STATUS: "401"
prune: true
retryInterval: 2m
sourceRef:

View File

@@ -38,6 +38,14 @@ spec:
memory: 250Mi
limits:
memory: 1Gi
defaultPodOptions:
securityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
fsGroup: 10001
fsGroupChangePolicy: OnRootMismatch
seccompProfile: { type: RuntimeDefault }
service:
app:
controller: *app

View File

@@ -3,18 +3,30 @@ events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
client_body_temp_path /tmp/client_temp;
proxy_temp_path /tmp/proxy_temp_path;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
scgi_temp_path /tmp/scgi_temp;
include mime.types;
server {
listen 8080;
listen 8080 default_server;
listen [::]:8080 default_server;
server_name _;
client_max_body_size 128M;
# serve media files
location /media/ {
alias /media/;
}
# serve static files
location /static/ {
alias /static/;
}
# serve media files
location /media/ {
alias /media//;
}
# pass requests for dynamic content to gunicorn
location / {
proxy_set_header Host $host;
proxy_pass http://localhost:8888;
}
}
}

View File

@@ -46,7 +46,6 @@ spec:
source /opt/recipes/venv/bin/activate
echo "Updating database"
python3 /opt/recipes/manage.py migrate
python3 /opt/recipes/manage.py collectstatic_js_reverse
python3 /opt/recipes/manage.py collectstatic --noinput
containers:
app:
@@ -59,7 +58,7 @@ spec:
ALLOWED_HOSTS: "*"
GUNICORN_MEDIA: "0"
TZ: ${TIMEZONE}
TANDOOR_PORT: &port 8888
TANDOOR_PORT: &tandoorPort 8888
FRACTION_PREF_DEFAULT: "0"
COMMENT_PREF_DEFAULT: "1"
SHOPPING_MIN_AUTOSYNC_INTERVAL: "5"
@@ -74,6 +73,28 @@ spec:
- --log-level
- INFO
- recipes.wsgi
probes:
liveness: &probes
enabled: true
custom: true
spec:
httpGet:
path: /accounts/login/
port: *tandoorPort
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 1
failureThreshold: 3
readiness: *probes
startup:
enabled: true
custom: true
spec:
httpGet:
path: /accounts/login/
port: *tandoorPort
failureThreshold: 30
periodSeconds: 10
resources:
requests:
cpu: 100m
@@ -89,41 +110,21 @@ spec:
controller: *app
ports:
http:
port: *port
port: *tandoorPort
nginx:
port: &port2 8080
ingress:
port: &nginxPort 8080
route:
app:
enabled: true
className: internal
annotations:
gethomepage.dev/enabled: "true"
gethomepage.dev/name: Tandoor
gethomepage.dev/description: Managing recipes, planned meals, shopping lists.
gethomepage.dev/group: Applications
gethomepage.dev/icon: tandoor.png
gethomepage.dev/pod-selector: >-
app in (
tandoor
)
hosts:
- host: &host "{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"
paths:
- path: /
service:
identifier: app
port: http
- path: /media
service:
identifier: app
port: *port2
- path: /static
service:
identifier: app
port: *port2
tls:
- hosts:
- *host
hostnames:
- "{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"
parentRefs:
- name: internal
namespace: network
sectionName: https
rules:
- backendRefs:
- name: *app
port: *nginxPort
persistence:
config:
existingClaim: *app

View File

@@ -40,7 +40,7 @@ spec:
controller: *app
ports:
http:
port: 8265
port: &port 8265
server:
controller: *app
type: LoadBalancer
@@ -50,7 +50,7 @@ spec:
server:
enabled: true
protocol: TCP
port: &port 8266
port: 8266
route:
app:
hostnames: ["{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"]

View File

@@ -24,6 +24,7 @@ spec:
postBuild:
substitute:
APP: *app
GATUS_STATUS: "401"
VOLSYNC_CACHE_CAPACITY: 20Gi
VOLSYNC_CAPACITY: 50Gi
prune: true

View File

@@ -0,0 +1,15 @@
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/backendtlspolicy_v1alpha3.json
apiVersion: gateway.networking.k8s.io/v1alpha3
kind: BackendTLSPolicy
metadata:
name: unifi-backend-tls
spec:
targetRefs:
- group: ''
kind: Service
name: unifi
sectionName: https
validation:
wellKnownCACertificates: System
hostname: unifi.${SECRET_EXTERNAL_DOMAIN}

View File

@@ -0,0 +1,19 @@
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cert-manager.io/certificate_v1.json
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: '${SECRET_EXTERNAL_DOMAIN/./-}-unifi'
spec:
secretName: '${SECRET_EXTERNAL_DOMAIN/./-}-unifi'
issuerRef:
name: letsencrypt-production
kind: ClusterIssuer
commonName: 'unifi.${SECRET_EXTERNAL_DOMAIN}'
dnsNames:
- 'unifi.${SECRET_EXTERNAL_DOMAIN}'
keystores:
jks:
create: true
alias: unifi
password: aircontrolenterprise

View File

@@ -46,7 +46,7 @@ spec:
externalTrafficPolicy: Local
loadBalancerIP: 192.168.169.103
ports:
http:
https:
port: &port 8443
protocol: HTTPS
controller:
@@ -88,9 +88,27 @@ spec:
- backendRefs:
- name: *app
port: *port
timeouts:
request: 0s # websocket, never time out
backendRequest: 0s # websocket, never time out
persistence:
config:
enabled: true
existingClaim: *app
globalMounts:
- path: /unifi
cert:
type: secret
name: '${SECRET_EXTERNAL_DOMAIN/./-}-unifi'
advancedMounts:
unifi:
app:
- path: /unifi/cert/cert.pem
subPath: tls.crt
readOnly: true
- path: /unifi/cert/privkey.pem
subPath: tls.key
readOnly: true
- path: /unifi/data/keystore
subPath: keystore.jks
readOnly: false

View File

@@ -3,4 +3,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./backendtlspolicy.yaml
- ./certificate.yaml
- ./helmrelease.yaml
- ./pushsecret.yaml

View File

@@ -0,0 +1,35 @@
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/pushsecret_v1alpha1.json
apiVersion: external-secrets.io/v1alpha1
kind: PushSecret
metadata:
name: lets-encrypt-unifi
spec:
secretStoreRefs:
- name: onepassword-connect
kind: ClusterSecretStore
selector:
secret:
name: ${SECRET_EXTERNAL_DOMAIN/./-}-unifi
template:
engineVersion: v2
data:
tls.crt: '{{ index . "tls.crt" | b64enc }}'
tls.key: '{{ index . "tls.key" | b64enc }}'
keystore.jks: '{{ index . "keystore.jks" | b64enc }}'
data:
- match:
secretKey: &key tls.crt
remoteRef:
remoteKey: lets-encrypt-unifi
property: *key
- match:
secretKey: &key tls.key
remoteRef:
remoteKey: lets-encrypt-unifi
property: *key
- match:
secretKey: &key keystore.jks
remoteRef:
remoteKey: lets-encrypt-unifi
property: *key

View File

@@ -28,6 +28,7 @@ spec:
substitute:
APP: *app
VOLSYNC_CAPACITY: 2Gi
GATUS_STATUS: "401"
GATUS_SUBDOMAIN: zigbee
prune: true
retryInterval: 2m

View File

@@ -5,6 +5,7 @@ kind: Kustomization
namespace: kube-system
resources:
- ./helmrelease.yaml
- ./prometheusrule.yaml
configMapGenerator:
- name: external-secrets-values
files:

View File

@@ -0,0 +1,26 @@
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/prometheusrule_v1.json
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: external-secret-sync-alert
namespace: external-secrets
spec:
groups:
- name: external-secrets
rules:
- alert: ExternalSecretNotSynced
expr: |
(
max_over_time(
external_secret_status_condition{condition="Ready", status="True"}[15m]
) == 0
) or on(name, namespace) (
external_secret_status_condition{condition="Ready", status="False"} == 1
)
for: 0m
labels:
severity: warning
annotations:
summary: ExternalSecret not synchronized
description: "ExternalSecret {{ $labels.namespace }}/{{ $labels.name }} has not synced for >5 min."

View File

@@ -0,0 +1,21 @@
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: github-webhook
spec:
hostnames: ["flux-webhook.${SECRET_EXTERNAL_DOMAIN}"]
parentRefs:
- name: external
namespace: network
sectionName: https
rules:
- backendRefs:
- name: webhook-receiver
namespace: flux-system
port: 80
matches:
- path:
type: PathPrefix
value: /hook/

View File

@@ -1,21 +0,0 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: webhook-receiver
spec:
ingressClassName: external
rules:
- host: "flux-webhook.${SECRET_EXTERNAL_DOMAIN}"
http:
paths:
- path: /hook/
pathType: Prefix
backend:
service:
name: webhook-receiver
port:
number: 80
tls:
- hosts:
- "flux-webhook.${SECRET_EXTERNAL_DOMAIN}"

View File

@@ -5,7 +5,7 @@ kind: Kustomization
resources:
- ./externalsecret.yaml
- ./helmrelease.yaml
- ./ingress.yaml
- ./httproute.yaml
- ./prometheusrule.yaml
- ./receiver.yaml
configMapGenerator:

View File

@@ -35,32 +35,6 @@ spec:
name: cilium-values
values:
hubble:
enabled: true
metrics:
enabled:
- dns:query
- drop
- tcp
- flow
- port-distribution
- icmp
- http
serviceMonitor:
enabled: true
dashboards:
enabled: true
relay:
enabled: true
rollOutPods: true
prometheus:
serviceMonitor:
enabled: true
ui:
enabled: true
rollOutPods: true
ingress:
enabled: true
className: internal
hosts: ["hubble.${SECRET_EXTERNAL_DOMAIN}"]
enabled: false
operator:
tolerations: []

View File

@@ -3,22 +3,16 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: freshrss
name: cloudflare-dns
spec:
secretStoreRef:
kind: ClusterSecretStore
name: onepassword-connect
target:
name: freshrss-secret
name: cloudflare-dns-secret
template:
engineVersion: v2
data:
OIDC_CLIENT_SECRET: "{{ .FRESHRSS_OAUTH_CLIENT_SECRET }}"
FRESHRSS_OIDC_CLIENT_CRYPTO_KEY: "{{ .FRESHRSS_OIDC_CLIENT_CRYPTO_KEY}}"
CF_API_TOKEN: "{{ .CLOUDFLARE_TOKEN }}"
dataFrom:
- extract:
key: authelia
- extract:
key: cloudnative-pg
- extract:
key: freshrss
key: cloudflare

View File

@@ -0,0 +1,58 @@
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: cloudflare-dns
spec:
interval: 5m
layerSelector:
mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
operation: copy
ref:
tag: 1.18.0
url: oci://ghcr.io/home-operations/charts-mirror/external-dns
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: &app cloudflare-dns
spec:
interval: 1h
chartRef:
kind: OCIRepository
name: cloudflare-dns
install:
remediation:
retries: -1
upgrade:
cleanupOnFail: true
remediation:
retries: 3
values:
fullnameOverride: *app
provider:
name: cloudflare
env:
- name: &name CF_API_TOKEN
valueFrom:
secretKeyRef:
name: &secret cloudflare-dns-secret
key: *name
extraArgs:
- --cloudflare-dns-records-per-page=1000
- --cloudflare-proxied
- --crd-source-apiversion=externaldns.k8s.io/v1alpha1
- --crd-source-kind=DNSEndpoint
- --gateway-name=external
triggerLoopOnEvent: true
policy: sync
sources: ["crd", "gateway-httproute"]
txtOwnerId: default
txtPrefix: k8s.
domainFilters: ["${SECRET_EXTERNAL_DOMAIN}"]
serviceMonitor:
enabled: true
podAnnotations:
secret.reloader.stakater.com/reload: *secret

View File

@@ -0,0 +1,7 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/kustomization.json
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./externalsecret.yaml
- ./helmrelease.yaml

View File

@@ -0,0 +1,32 @@
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: &app cloudflare-dns
namespace: &namespace network
spec:
commonMetadata:
labels:
app.kubernetes.io/name: *app
dependsOn:
- name: external-secrets-stores
namespace: external-secrets
healthChecks:
- apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
name: *app
namespace: *namespace
- apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
name: dnsendpoints.externaldns.k8s.io
interval: 1h
path: ./kubernetes/apps/network/cloudflare-dns/app
prune: true
retryInterval: 2m
sourceRef:
kind: GitRepository
name: flux-system
namespace: flux-system
targetNamespace: *namespace
timeout: 5m

View File

@@ -3,7 +3,7 @@
apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
metadata:
name: cloudflared
name: cloudflare-tunnel
spec:
endpoints:
- dnsName: "external.${SECRET_EXTERNAL_DOMAIN}"

View File

@@ -3,13 +3,13 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: cloudflared-tunnel
name: cloudflare-tunnel
spec:
secretStoreRef:
kind: ClusterSecretStore
name: onepassword-connect
target:
name: cloudflared-tunnel-secret
name: cloudflare-tunnel-secret
template:
engineVersion: v2
data:

View File

@@ -3,7 +3,7 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: cloudflared
name: &app cloudflare-tunnel
spec:
interval: 1h
chartRef:
@@ -17,12 +17,9 @@ spec:
remediation:
strategy: rollback
retries: 3
dependsOn:
- name: nginx-external
namespace: network
values:
controllers:
cloudflared:
cloudflare-tunnel:
replicas: 2
strategy: RollingUpdate
annotations:
@@ -75,13 +72,13 @@ spec:
seccompProfile: { type: RuntimeDefault }
service:
app:
controller: cloudflared
controller: *app
ports:
http:
port: *port
serviceMonitor:
app:
serviceName: cloudflared
serviceName: *app
endpoints:
- port: http
scheme: http
@@ -91,14 +88,14 @@ spec:
persistence:
config:
type: configMap
name: cloudflared-configmap
name: cloudflare-tunnel-configmap
globalMounts:
- path: /etc/cloudflared/config/config.yaml
subPath: config.yaml
readOnly: true
creds:
type: secret
name: cloudflared-tunnel-secret
name: cloudflare-tunnel-secret
globalMounts:
- path: /etc/cloudflared/creds/credentials.json
subPath: credentials.json

View File

@@ -7,7 +7,7 @@ resources:
- ./dnsendpoint.yaml
- ./helmrelease.yaml
configMapGenerator:
- name: cloudflared-configmap
- name: cloudflare-tunnel-configmap
files:
- config.yaml=./resources/config.yaml
generatorOptions:

View File

@@ -4,7 +4,7 @@ originRequest:
ingress:
- hostname: "${SECRET_EXTERNAL_DOMAIN}"
service: https://nginx-external-controller.network.svc.cluster.local:443
service: &svc https://envoy-network-external-b1d9befd.network.svc.cluster.local:443
- hostname: "*.${SECRET_EXTERNAL_DOMAIN}"
service: https://nginx-external-controller.network.svc.cluster.local:443
service: *svc
- service: http_status:404

View File

@@ -3,18 +3,17 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: &app cloudflared
name: &app cloudflare-tunnel
namespace: &namespace network
spec:
commonMetadata:
labels:
app.kubernetes.io/name: *app
dependsOn:
- name: external-dns-cloudflare
- name: external-secrets-stores
namespace: external-secrets
interval: 1h
path: ./kubernetes/apps/network/cloudflared/app
path: ./kubernetes/apps/network/cloudflare-tunnel/app
postBuild:
substitute:
APP: *app

View File

@@ -1,4 +1,5 @@
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cert-manager.io/certificate_v1.json
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:

View File

@@ -18,7 +18,7 @@ spec:
type: Kubernetes
kubernetes:
envoyDeployment:
replicas: 1
replicas: 2
container:
resources:
requests:

View File

@@ -11,7 +11,7 @@ spec:
mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
operation: copy
ref:
tag: 3.2.3
tag: 3.2.6
url: oci://ghcr.io/k8s-gateway/charts/k8s-gateway
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json

View File

@@ -6,8 +6,8 @@ namespace: network
components:
- ../../components/common
resources:
- ./cloudflared/ks.yaml
- ./cloudflare-dns/ks.yaml
- ./cloudflare-tunnel/ks.yaml
- ./envoy-gateway/ks.yaml
- ./external-dns/ks.yaml
- ./gateway-api-crds/ks.yaml
- ./k8s-gateway/ks.yaml

View File

@@ -1,6 +1,10 @@
---
web:
port: 8080
storage:
type: sqlite
path: /config/sqlite.db
caching: true
metrics: true
ui:
title: Status | Gatus
@@ -30,7 +34,7 @@ connectivity:
endpoints:
- name: flux-webhook
group: external
url: https://flux-webhook.${CUSTOM_SECRET_EXTERNAL_DOMAIN}
url: https://flux-webhook.${SECRET_EXTERNAL_DOMAIN}
interval: 1m
client:
dns-resolver: tcp://1.1.1.1:53

View File

@@ -14,8 +14,11 @@ spec:
data:
CUSTOM_PUSHOVER_APP_TOKEN: '{{ .PUSHOVER_API_TOKEN }}'
CUSTOM_PUSHOVER_USER_KEY: '{{ .PUSHOVER_USER_KEY }}'
SECRET_EXTERNAL_DOMAIN: '{{ .SECRET_EXTERNAL_DOMAIN }}'
dataFrom:
- extract:
key: gatus
- extract:
key: generic
- extract:
key: pushover

View File

@@ -48,7 +48,10 @@ spec:
TZ: ${TIMEZONE}
GATUS_CONFIG_PATH: /config
GATUS_DELAY_START_SECONDS: 5
GATUS_WEB_PORT: &port 80
GATUS_WEB_PORT: &port 8080
envFrom:
- secretRef:
name: gatus-secret
probes:
liveness: &probes
enabled: true
@@ -76,20 +79,28 @@ spec:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
seccompProfile: { type: RuntimeDefault }
service:
app:
controller: *app
ports:
http:
port: *port
serviceAccount:
gatus: {}
serviceMonitor:
app:
serviceName: *app
enabled: true
endpoints:
- port: http
route:
app:
hostnames: ["{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"]
hostnames: ["status.${SECRET_EXTERNAL_DOMAIN}"]
parentRefs:
- name: internal
- name: external
namespace: network
sectionName: https
rules:
@@ -108,14 +119,12 @@ spec:
gatus:
type: ClusterRoleBinding
roleRef:
identifier: gatus
identifier: *app
subjects:
- identifier: gatus
serviceAccount:
gatus: {}
persistence:
config:
type: emptyDir
existingClaim: *app
config-file:
type: configMap
name: "{{ .Release.Name }}-configmap"

View File

@@ -5,8 +5,6 @@ kind: Kustomization
resources:
- ./externalsecret.yaml
- ./helmrelease.yaml
- ./pvc.yaml
- ./rbac.yaml
configMapGenerator:
- name: gatus-configmap
files:

View File

@@ -1,11 +0,0 @@
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gatus
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 2Gi
storageClassName: rook-ceph-block

View File

@@ -1,34 +0,0 @@
---
# trunk-ignore(checkov/CKV_K8S_21)
apiVersion: v1
kind: ServiceAccount
metadata:
name: gatus
labels:
app.kubernetes.io/managed-by: Helm
annotations:
meta.helm.sh/release-name: gatus
meta.helm.sh/release-namespace: observability
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: gatus
rules:
# trunk-ignore(trivy/KSV041)
- apiGroups: [""]
resources: [configmaps, secrets]
verbs: [get, watch, list]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: gatus
roleRef:
kind: ClusterRole
name: gatus
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: gatus
namespace: observability

View File

@@ -9,6 +9,8 @@ spec:
commonMetadata:
labels:
app.kubernetes.io/name: *app
components:
- ../../../../components/volsync
dependsOn:
- name: external-secrets-stores
namespace: external-secrets
@@ -17,6 +19,7 @@ spec:
postBuild:
substitute:
APP: *app
VOLSYNC_CAPACITY: 2Gi
prune: true
retryInterval: 2m
sourceRef:

View File

@@ -3,7 +3,7 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: https-redirect
name: pushgateway
spec:
hostnames:
- pushgateway.${SECRET_EXTERNAL_DOMAIN}
@@ -17,8 +17,8 @@ spec:
- backendRefs:
- group: ''
kind: Service
name: pushgateway
namespace: default
name: pushgateway-prometheus-pushgateway
namespace: observability
port: 9091
weight: 1
matches:

View File

@@ -0,0 +1,18 @@
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: rook-ceph-dashboard
spec:
secretStoreRef:
kind: ClusterSecretStore
name: onepassword-connect
target:
name: rook-ceph-dashboard-password # rook-ceph expects this name
template:
data:
password: "{{ .password }}"
dataFrom:
- extract:
key: rook

View File

@@ -46,6 +46,9 @@ spec:
crds:
enabled: true
pspEnable: false
enableDiscoveryDaemon: true
image:
repository: ghcr.io/rook/ceph
monitoring:
enabled: true
resources:

View File

@@ -3,4 +3,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./externalsecret.yaml
- ./helmrelease.yaml

View File

@@ -33,25 +33,6 @@ spec:
monitoring:
enabled: true
createPrometheusRules: true
ingress:
dashboard:
ingressClassName: internal
annotations:
gethomepage.dev/enabled: "true"
gethomepage.dev/name: Rook
gethomepage.dev/description: Cloud-Native Storage for Kubernetes.
gethomepage.dev/group: Infrastructure
gethomepage.dev/icon: rook.png
gethomepage.dev/pod-selector: >-
app in (
rook
)
host:
name: "rook.${SECRET_EXTERNAL_DOMAIN}"
path: /
tls:
- hosts:
- "rook.${SECRET_EXTERNAL_DOMAIN}"
configOverride: |
[global]
bdev_enable_discard = true
@@ -63,6 +44,7 @@ spec:
enabled: true
urlPrefix: /
ssl: false
prometheusEndpoint: http://prometheus-operated.observability.svc.cluster.local:9090
storage:
useAllNodes: false
useAllDevices: false

View File

@@ -0,0 +1,17 @@
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: rook-ceph-dashboard
spec:
hostnames: ["rook.${SECRET_EXTERNAL_DOMAIN}"]
parentRefs:
- name: internal
namespace: network
sectionName: https
rules:
- backendRefs:
- name: rook-ceph-mgr-dashboard
namespace: rook-ceph
port: 7000

View File

@@ -4,3 +4,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./helmrelease.yaml
- ./httproute.yaml

View File

@@ -10,5 +10,5 @@ spec:
mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
operation: copy
ref:
tag: 3.7.3
url: oci://ghcr.io/bjw-s/helm/app-template
tag: 4.2.0
url: oci://ghcr.io/bjw-s-labs/helm/app-template

View File

@@ -10,11 +10,9 @@ stringData:
SECRET_DOMAIN: ENC[AES256_GCM,data:UtdBDs6+azVHO7Y=,iv:ZnWrBW+vW6HiMs1PbgY2LjcwUwuUh1HxYjqvOXvCrDk=,tag:r6uDIJhVoTIcizIfRW+lHw==,type:str]
SECRET_EXTERNAL_DOMAIN: ENC[AES256_GCM,data:Brd9H7gizPxew+4=,iv:YaIxv9TFF0mAks9gJXwXA1N7b8k5mcSJ6hs9lpaUV/M=,tag:8xdRoWun3IUVywagpsrsBw==,type:str]
SECRET_INTERNAL_DOMAIN: ENC[AES256_GCM,data:WLuQAi9JsUsD5Q==,iv:Zc+5/rQONxepZFVC/ia01aBdlVyG99thOeIipeAVS3E=,tag:FwwjDKoUMfZ/taFPRRThOQ==,type:str]
SECRET_CROWDSEC_NGINX_BOUNCER_API_KEY: ENC[AES256_GCM,data:ecukkFOK40WWIxJ48sXrxJUBaHx2BnzqxkIT+cXYZg4=,iv:y6AfslVPufBfrIL3GQqTw0cDAan64mB9J7RY9OzKQqw=,tag:+V4Rgz26wey2UtA32S0PJQ==,type:str]
SECRET_KOMF_MAL_CLIENT_ID: ENC[AES256_GCM,data:HuKHFrICgCj6nbcbix8u7qGeggFmmKht7Elk9dINZtE=,iv:c3mqFdFkIO9dctZ3ooPh4ajOZaY0ZudEeNWbG+lryPI=,tag:jWG2+pgkAf/XUgJyUvdrNg==,type:str]
SECRET_KUBE_PROMETHEUS_STACK_ALERTMANAGER_PUSHOVER_USER_KEY: ENC[AES256_GCM,data:X1J9WLT26soYzlDb8+YtPotGw8p0lJKMuNkn69WX,iv:mW2cJOq5gfzSE+U24IuvPVL+dL2nZcTFpPAkG77Ohus=,tag:kxokidtuE5RAGJlj4Q4P2A==,type:str]
SECRET_KUBE_PROMETHEUS_STACK_ALERTMANAGER_PUSHOVER_USER_KEY: ENC[AES256_GCM,data:6r6jegE5tnW8l9flwQy48jI6biCNXMLonuHt94Zu,iv:iWej1fv28zXlVTHZ+khhF5FuN5RZY5EV/0Slz24no7U=,tag:KH65ZHwl+1Mf7ScuGiAhgw==,type:str]
SECRET_KUBE_PROMETHEUS_STACK_ALERTMANAGER_PUSHOVER_TOKEN: ENC[AES256_GCM,data:Bwvuy/jHIRduy/r1A8dOs0OE8ewdjCgs8g/br1oW,iv:PdnPH9I509MT6UJkUG1zLAGn9aV4AVrROgAVCD4a3Y0=,tag:59kBGx9qx3jeauokyoolQQ==,type:str]
SECRET_KUBE_PROMETHEUS_STACK_GRAFANA_ADMIN_PASSWORD: ENC[AES256_GCM,data:L7LS6+tuwPCyb5HN4zg=,iv:JM2KTtDN/VrKicjp5qwqusWiJKHRZnfTtsZE2hkLq6Q=,tag:XGF3L5P6JxVBrlGuKosdZA==,type:str]
type: Opaque
sops:
age:
@@ -27,7 +25,7 @@ sops:
WG82VkdBMlNnRzBySFQzMk41cEtXSlEKBqOmq9UpO61C85+pj0ibdT31y4pmFsbm
pTi4N0vv81kcf4ilqBU5h1gudNCb42Q2iL0eGNR4e3JzH4iaNsvnEg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-04-15T20:57:26Z"
mac: ENC[AES256_GCM,data:/qQpLkJIhVBnkDVNsls1xfw1Iyy6ijyrmU9LQqhO+Qa6lQ4CKejX6wiLuPJNtQ+rTtmp3KUG4uCF3JvWNnyNOLGtSjM3X7bDS11NY2sfWkBebBQy/s59B7Jb30937lqFP39hP5GhvegN6kP5+iLIltgKKjH0cXXyf+FT/Q+6kOs=,iv:r6HfAGPr09e4xuaDQBE3zXt3n7k88dHZfQXKa2LMiYY=,tag:nxzFsjI9QhhsnTO7Oed8QQ==,type:str]
lastmodified: "2025-08-19T20:12:58Z"
mac: ENC[AES256_GCM,data:uVZFsWvrk0T1q446uNnVdNai7C7mTrZNXkPxwZdmLi1Do6nzCYccmnefz5Fukr9DzWCmofdlqEcDneugHxPbKiOKnqQ1Wbuf7smqRSeHaRycDgmFtYVBTnm2Bc7ePU2a7zcnbR5w6q1HXC+iyxP0aKAMI5Z7NvOJ/CZi3PIPUUY=,iv:ZJLOh9+SxX0WzvIue6/WxG1d2SesdTCBnBr0EaX53ls=,tag:0rL7B/J4b6PNEsKsmdT2NA==,type:str]
encrypted_regex: ^(data|stringData)$
version: 3.10.2

View File

@@ -4,7 +4,7 @@ endpoints:
url: "https://${GATUS_SUBDOMAIN:-${APP}}.${SECRET_EXTERNAL_DOMAIN}${GATUS_PATH:-/}"
interval: 1m
client:
dns-resolver: tcp://192.168.8.1:53
dns-resolver: tcp://1.1.1.1:53
conditions:
- "[STATUS] == ${GATUS_STATUS:-200}"
alerts:

View File

@@ -3,6 +3,8 @@ endpoints:
group: guarded
url: "https://${GATUS_SUBDOMAIN:-${APP}}.${GATUS_DOMAIN:-${SECRET_EXTERNAL_DOMAIN}}${GATUS_PATH:-/}"
interval: 1m
client:
dns-resolver: tcp://192.168.8.1:53
ui:
hide-hostname: true
hide-url: true