Adopt Traefik ingress resources into Argo CD

This commit is contained in:
2026-10-19 11:20:42 +02:00
parent c40cf551c8
commit b484412416
62 changed files with 1853 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
# Cilium recovery
Argo CD is the normal owner of Cilium. Use this only if Argo CD cannot restore
the CNI and the cluster needs a break-glass repair. Work from a fresh checkout
of this repository and verify `kubectl config current-context` is
`kubernetes-admin@kubernetes` before any cluster changes.
The chart version is canonically recorded as `spec.sources[0].targetRevision`
in `bootstrap/cilium.yaml`; the cluster configuration is in `apps/cilium/values.yaml`.
Restore the Hubble CA resources from `apps/cilium/resources/hubble-pki.yaml` if
needed. Then use the Cilium CLI's `upgrade` command with the chart version from
the Application and those values. Do not uninstall Cilium, delete its CRDs, or
remove the retained Helm release record during recovery. Once Argo is healthy,
return all routine changes to GitOps and let it reconcile.
This is a recovery procedure, not a second deployment path. Keep credentials
and secret values out of this public repository.
+12
View File
@@ -0,0 +1,12 @@
# Traefik
The Argo CD Application adopts the existing `traefik` Helm release in
`default`. `bootstrap/traefik.yaml` is the single chart-version source; the
values here preserve the cluster's current controller settings and live
file-provider routes. Those routes include the staubsauger vacuum, Victron
NanoPi and WebSocket endpoint, Growatt, and OpenDTU. Do not restore the
commented/retired routers from the former local configuration.
Traefik CRDs and Gateway API CRDs are cluster-wide prerequisites. Keep the
existing CRDs during adoption and upgrades; they are not safe cleanup targets.
Application-specific ingress resources remain with their owning application.
@@ -0,0 +1,25 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "192-168-0-2",
"namespace": "default"
},
"spec": {
"entryPoints": [
"web"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`192.168.0.2`)",
"services": [
{
"name": "brunner-ninja",
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,27 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "code-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`code.brunner.ninja`)",
"services": [
{
"kind": "Service",
"name": "legacy-gitea-service",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,27 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "code-test-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`code-test.brunner.ninja`)",
"services": [
{
"kind": "Service",
"name": "legacy-forgejo-service",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,51 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "helm-charts-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`brunner.ninja`) && (Path(`/charts`) || Path(`/charts/`))",
"middlewares": [
{
"name": "helm-charts-index-rewrite"
}
],
"priority": 301,
"services": [
{
"kind": "Service",
"name": "legacy-gitea-service",
"passHostHeader": true,
"port": "http"
}
]
},
{
"kind": "Rule",
"match": "Host(`brunner.ninja`) && PathPrefix(`/charts/`)",
"middlewares": [
{
"name": "helm-charts-path-rewrite"
}
],
"priority": 300,
"services": [
{
"kind": "Service",
"name": "legacy-gitea-service",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,28 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "immich-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`immich.brunner.ninja`)",
"services": [
{
"kind": "Service",
"name": "legacy-immich-service",
"passHostHeader": true,
"port": "http",
"serversTransport": "immich-transport"
}
]
}
]
}
}
@@ -0,0 +1,26 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "komposthaufen",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`brunner.ninja`) && PathPrefix(`/komposthaufen`)",
"services": [
{
"kind": "Service",
"name": "legacy-apache-service",
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,32 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "lidarr-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`lidarr.brunner.ninja`)",
"middlewares": [
{
"name": "authentik"
}
],
"services": [
{
"kind": "Service",
"name": "legacy-lidarr-service",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,31 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "mcmap",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`brunner.ninja`) && PathPrefix(`/mcmap`)",
"middlewares": [
{
"name": "mcmap-strip"
}
],
"services": [
{
"kind": "Service",
"name": "legacy-mcmap-service",
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,27 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "photos-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`photos.brunner.ninja`)",
"services": [
{
"kind": "Service",
"name": "legacy-immich-service",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,32 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "prowlarr-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`prowlarr.brunner.ninja`)",
"middlewares": [
{
"name": "authentik"
}
],
"services": [
{
"kind": "Service",
"name": "legacy-prowlarr-service",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,32 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "qbittorrent-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`qbittorrent.brunner.ninja`)",
"middlewares": [
{
"name": "authentik"
}
],
"services": [
{
"kind": "Service",
"name": "legacy-qbittorrent-service",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,32 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "radarr-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`radarr.brunner.ninja`)",
"middlewares": [
{
"name": "authentik"
}
],
"services": [
{
"kind": "Service",
"name": "legacy-radarr-service",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,32 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "readarr-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`readarr.brunner.ninja`)",
"middlewares": [
{
"name": "authentik"
}
],
"services": [
{
"kind": "Service",
"name": "legacy-readarr-service",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,32 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "sonarr-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`sonarr.brunner.ninja`)",
"middlewares": [
{
"name": "authentik"
}
],
"services": [
{
"kind": "Service",
"name": "legacy-sonarr-service",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,32 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "syncthing-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`syncthing.brunner.ninja`)",
"middlewares": [
{
"name": "authentik"
}
],
"services": [
{
"kind": "Service",
"name": "legacy-syncthing-service",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,27 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "vault-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`vault.brunner.ninja`)",
"services": [
{
"kind": "Service",
"name": "legacy-vault-service",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,32 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "whisparr-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`whisparr.brunner.ninja`)",
"middlewares": [
{
"name": "authentik"
}
],
"services": [
{
"kind": "Service",
"name": "legacy-whisparr-service",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,27 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "youtube-brunner-ninja",
"namespace": "default"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`youtube.brunner.ninja`)",
"services": [
{
"kind": "Service",
"name": "legacy-apache-service",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,13 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "helm-charts-index-rewrite",
"namespace": "default"
},
"spec": {
"replacePath": {
"path": "/api/packages/feedc0de/helm/index.yaml"
}
}
}
@@ -0,0 +1,14 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "helm-charts-path-rewrite",
"namespace": "default"
},
"spec": {
"replacePathRegex": {
"regex": "^/charts/(.*)$",
"replacement": "/api/packages/feedc0de/helm/${1}"
}
}
}
@@ -0,0 +1,15 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "mcmap-strip",
"namespace": "default"
},
"spec": {
"stripPrefix": {
"prefixes": [
"/mcmap"
]
}
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-apache-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.105.55.200",
"clusterIPs": [
"10.105.55.200"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 81,
"protocol": "TCP",
"targetPort": 81
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-forgejo-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.102.202.224",
"clusterIPs": [
"10.102.202.224"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 3005,
"protocol": "TCP",
"targetPort": 3005
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-gitea-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.103.230.204",
"clusterIPs": [
"10.103.230.204"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 3004,
"protocol": "TCP",
"targetPort": 3004
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-immich-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.104.46.119",
"clusterIPs": [
"10.104.46.119"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 2283,
"protocol": "TCP",
"targetPort": 2283
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-lidarr-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.103.43.185",
"clusterIPs": [
"10.103.43.185"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 8686,
"protocol": "TCP",
"targetPort": 8686
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-mastodon-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.111.83.15",
"clusterIPs": [
"10.111.83.15"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 3000,
"protocol": "TCP",
"targetPort": 3000
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-matrix-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.98.20.196",
"clusterIPs": [
"10.98.20.196"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 8008,
"protocol": "TCP",
"targetPort": 8008
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-mcmap-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.97.249.106",
"clusterIPs": [
"10.97.249.106"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 8124,
"protocol": "TCP",
"targetPort": 8124
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-prowlarr-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.97.85.22",
"clusterIPs": [
"10.97.85.22"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 9696,
"protocol": "TCP",
"targetPort": 9696
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-qbittorrent-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.97.73.158",
"clusterIPs": [
"10.97.73.158"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 8081,
"protocol": "TCP",
"targetPort": 8081
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-radarr-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.105.65.227",
"clusterIPs": [
"10.105.65.227"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 7878,
"protocol": "TCP",
"targetPort": 7878
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-readarr-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.103.216.34",
"clusterIPs": [
"10.103.216.34"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 8787,
"protocol": "TCP",
"targetPort": 8787
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-sonarr-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.97.124.201",
"clusterIPs": [
"10.97.124.201"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 8989,
"protocol": "TCP",
"targetPort": 8989
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-syncthing-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.101.5.124",
"clusterIPs": [
"10.101.5.124"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 8384,
"protocol": "TCP",
"targetPort": 8384
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-vault-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.101.2.74",
"clusterIPs": [
"10.101.2.74"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 8000,
"protocol": "TCP",
"targetPort": 8000
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "legacy-whisparr-service",
"namespace": "default"
},
"spec": {
"clusterIP": "10.99.146.118",
"clusterIPs": [
"10.99.146.118"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 6969,
"protocol": "TCP",
"targetPort": 6969
}
],
"sessionAffinity": "None",
"type": "ClusterIP"
}
}
@@ -0,0 +1,30 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "garrysmod-loading-screen",
"namespace": "garrysmod",
"labels": {
"app.kubernetes.io/name": "garrysmod"
}
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`garrysmod.brunner.ninja`)",
"services": [
{
"kind": "Service",
"name": "garrysmod-loading-screen",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,49 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "jellyfin-brunner-ninja",
"namespace": "jellyfin",
"labels": {
"app.kubernetes.io/name": "jellyfin"
}
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`jellyfin.brunner.ninja`) && PathPrefix(`/metrics`)",
"middlewares": [
{
"name": "jellyfin-metrics-internal"
}
],
"priority": 100,
"services": [
{
"kind": "Service",
"name": "jellyfin",
"passHostHeader": true,
"port": "http"
}
]
},
{
"kind": "Rule",
"match": "Host(`jellyfin.brunner.ninja`)",
"priority": 10,
"services": [
{
"kind": "Service",
"name": "jellyfin",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,18 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "jellyfin-metrics-internal",
"namespace": "jellyfin",
"labels": {
"app.kubernetes.io/name": "jellyfin"
}
},
"spec": {
"ipAllowList": {
"sourceRange": [
"10.0.0.0/8"
]
}
}
}
@@ -0,0 +1,31 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "kubernetes-dashboard-ingressroute",
"namespace": "kubernetes-dashboard"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`kubernetes.brunner.ninja`)",
"middlewares": [
{
"name": "kubernetes-dashboard-authentik"
}
],
"services": [
{
"kind": "Service",
"name": "kubernetes-dashboard-auth-proxy",
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,28 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "kubernetes-dashboard-authentik",
"namespace": "kubernetes-dashboard"
},
"spec": {
"forwardAuth": {
"address": "http://authentik-server.authentik.svc.cluster.local/outpost.goauthentik.io/auth/traefik",
"authResponseHeaders": [
"X-authentik-username",
"X-authentik-groups",
"X-authentik-entitlements",
"X-authentik-email",
"X-authentik-name",
"X-authentik-uid",
"X-authentik-jwt",
"X-authentik-meta-jwks",
"X-authentik-meta-outpost",
"X-authentik-meta-provider",
"X-authentik-meta-app",
"X-authentik-meta-version"
],
"trustForwardHeader": true
}
}
}
@@ -0,0 +1,53 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "loops-brunner-ninja",
"namespace": "loops",
"labels": {
"app.kubernetes.io/part-of": "loops"
}
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`loops.brunner.ninja`) && Path(`/api/v1/feed/for-you`)",
"middlewares": [
{
"name": "loops-android-for-you"
},
{
"name": "loops-upload-buffer"
}
],
"priority": 100,
"services": [
{
"name": "loops-web",
"port": 80
}
]
},
{
"kind": "Rule",
"match": "Host(`loops.brunner.ninja`)",
"middlewares": [
{
"name": "loops-upload-buffer"
}
],
"services": [
{
"name": "loops-web",
"port": 80
}
]
}
],
"tls": {}
}
}
@@ -0,0 +1,17 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "loops-android-for-you",
"namespace": "loops",
"labels": {
"app.kubernetes.io/part-of": "loops"
}
},
"spec": {
"replacePathRegex": {
"regex": "^/api/v1/feed/for-you$",
"replacement": "/api/v0/feed/recommended"
}
}
}
@@ -0,0 +1,17 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "loops-upload-buffer",
"namespace": "loops",
"labels": {
"app.kubernetes.io/part-of": "loops"
}
},
"spec": {
"buffering": {
"maxRequestBodyBytes": 524288000,
"memRequestBodyBytes": 2097152
}
}
}
@@ -0,0 +1,34 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "brunner-ninja-webfinger",
"namespace": "mastodon"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`brunner.ninja`) && PathPrefix(`/.well-known/`) && !PathPrefix(`/.well-known/matrix/`)",
"middlewares": [
{
"name": "webfinger-cors"
},
{
"name": "webfinger-redirect"
}
],
"priority": 1000,
"services": [
{
"name": "mastodon-web",
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,15 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "webfinger-cors",
"namespace": "mastodon"
},
"spec": {
"headers": {
"customResponseHeaders": {
"Access-Control-Allow-Origin": "*"
}
}
}
}
@@ -0,0 +1,15 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "webfinger-redirect",
"namespace": "mastodon"
},
"spec": {
"redirectRegex": {
"permanent": true,
"regex": "^https://brunner\\.ninja/(.*)",
"replacement": "https://social.brunner.ninja/${1}"
}
}
}
@@ -0,0 +1,34 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "matrix-well-known",
"namespace": "matrix"
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`brunner.ninja`) && (Path(`/.well-known/matrix/server`) || Path(`/.well-known/matrix/client`))",
"middlewares": [
{
"name": "matrix-well-known-cors"
},
{
"name": "matrix-well-known-rewrite"
}
],
"priority": 1100,
"services": [
{
"name": "element-web",
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,15 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "matrix-well-known-cors",
"namespace": "matrix"
},
"spec": {
"headers": {
"customResponseHeaders": {
"Access-Control-Allow-Origin": "*"
}
}
}
}
@@ -0,0 +1,14 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "matrix-well-known-rewrite",
"namespace": "matrix"
},
"spec": {
"replacePathRegex": {
"regex": "^/\\.well-known/matrix/(server|client)$",
"replacement": "/matrix-well-known/${1}.json"
}
}
}
@@ -0,0 +1,15 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "nextcloud-security-headers",
"namespace": "nextcloud"
},
"spec": {
"headers": {
"stsIncludeSubdomains": false,
"stsPreload": false,
"stsSeconds": 31536000
}
}
}
@@ -0,0 +1,15 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "Middleware",
"metadata": {
"name": "strip-push-prefix",
"namespace": "nextcloud"
},
"spec": {
"stripPrefix": {
"prefixes": [
"/push"
]
}
}
}
@@ -0,0 +1,30 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "open-webui",
"namespace": "ollama",
"labels": {
"app.kubernetes.io/name": "open-webui",
"app.kubernetes.io/part-of": "ollama-chat"
}
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`chat.brunner.ninja`)",
"services": [
{
"kind": "Service",
"name": "open-webui",
"port": "http"
}
]
}
]
}
}
@@ -0,0 +1,29 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "pixels-brunner-ninja",
"namespace": "pixelfed",
"labels": {
"app.kubernetes.io/part-of": "pixelfed"
}
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`pixels.brunner.ninja`)",
"services": [
{
"name": "pixelfed-web",
"port": 80
}
]
}
],
"tls": {}
}
}
@@ -0,0 +1,30 @@
{
"apiVersion": "traefik.io/v1alpha1",
"kind": "IngressRoute",
"metadata": {
"name": "plex-brunner-ninja",
"namespace": "plex",
"labels": {
"app.kubernetes.io/name": "plex"
}
},
"spec": {
"entryPoints": [
"websecure"
],
"routes": [
{
"kind": "Rule",
"match": "Host(`plex.brunner.ninja`)",
"services": [
{
"kind": "Service",
"name": "plex",
"passHostHeader": true,
"port": "http"
}
]
}
]
}
}
+175
View File
@@ -0,0 +1,175 @@
deployment:
kind: Deployment
replicas: 2
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
podDisruptionBudget:
enabled: true
minAvailable: 1
resources:
requests:
cpu: 500m
memory: 1Gi
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: traefik
app.kubernetes.io/instance: traefik-default
topologyKey: kubernetes.io/hostname
service:
enabled: true
annotations:
mikrotik.brunner.ninja/router: newgw
mikrotik.brunner.ninja/forwardings: >-
[{"name":"http","servicePort":"web","dstAddressList":"WANs"},{"name":"https","servicePort":"websecure","dstAddressList":"WANs"}]
spec:
type: LoadBalancer
loadBalancerIP: 192.168.0.10
externalTrafficPolicy: Local
additionalServices:
funkfeuer:
spec:
type: ClusterIP
externalIPs:
- 10.12.4.170
accessLog:
enabled: true
format: json
bufferingSize: 100
fields:
defaultMode: keep
names:
ClientUsername: drop
headers:
defaultMode: drop
names:
User-Agent: keep
Referer: keep
queryParameters:
defaultMode: drop
metrics:
prometheus:
disableAPICheck: true
addEntryPointsLabels: true
addRoutersLabels: true
addServicesLabels: true
buckets: "0.005,0.01,0.025,0.05,0.1,0.25,0.5,1,2.5,5,10"
service:
enabled: true
labels:
app.kubernetes.io/part-of: traefik-observability
serviceMonitor:
enabled: true
interval: 30s
scrapeTimeout: 10s
additionalLabels:
release: prometheus
ports:
web:
expose:
default: true
funkfeuer: true
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
websecure:
expose:
default: true
funkfeuer: true
http:
tls:
enabled: true
transport:
respondingTimeouts:
readTimeout: 3600
writeTimeout: 3600
ingressRoute:
dashboard:
enabled: true
matchRule: Host(`traefik.brunner.ninja`)
entryPoints:
- websecure
additionalArguments:
- --providers.redis.endpoints=valkey-primary.default.svc.cluster.local:6379
- --providers.redis.password=$(REDIS_PASSWORD)
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: valkey
key: valkey-password
persistence:
enabled: false
tlsStore:
default:
defaultCertificate:
secretName: brunner-ninja-tls
providers:
file:
enabled: true
content:
http:
routers:
growatt:
rule: "Host(`growatt.brunner.ninja`)"
service: growatt
entryPoints: [websecure]
opendtu:
rule: "Host(`opendtu.brunner.ninja`)"
service: opendtu
entryPoints: [websecure]
staubsauger:
rule: "Host(`staubsauger.brunner.ninja`)"
service: staubsauger
entryPoints: [websecure]
middlewares: [default-authentik@kubernetescrd]
victron:
rule: "Host(`victron.brunner.ninja`)"
service: victron
entryPoints: [websecure]
middlewares: [default-authentik@kubernetescrd]
victron-websockify:
rule: "Host(`victron.brunner.ninja`) && Path(`/websockify`)"
priority: 100
service: victron-websockify-capture
entryPoints: [websecure]
middlewares: [default-authentik@kubernetescrd, victron-native-origin]
middlewares:
victron-native-origin:
headers:
customRequestHeaders:
Origin: ""
services:
growatt:
loadBalancer:
servers:
- url: http://192.168.0.252:8080
opendtu:
loadBalancer:
servers:
- url: http://OpenDTU-AB9DF8.localdomain
staubsauger:
loadBalancer:
servers:
- url: http://rockrobo.localdomain
victron:
loadBalancer:
servers:
- url: http://nanopi.localdomain
victron-websockify-capture:
loadBalancer:
servers:
- url: http://192.168.0.93:8080
kubernetesGateway:
enabled: true
gateway:
namespacePolicy: All
+2
View File
@@ -12,6 +12,8 @@ resources:
- 30-birthday.yaml
- phppgadmin.yaml
- traefik-error-pages.yaml
- traefik-project.yaml
- traefik.yaml
- mktxp.yaml
- metrics-server-project.yaml
- metrics-server.yaml
+69
View File
@@ -0,0 +1,69 @@
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: traefik
namespace: argocd
spec:
description: Traefik ingress controller and cluster ingress integrations
sourceRepos:
- https://ghcr.io/traefik/helm
- https://code.brunner.ninja/feedc0de/homelab-gitops.git
destinations:
- namespace: default
server: https://kubernetes.default.svc
- namespace: garrysmod
server: https://kubernetes.default.svc
- namespace: jellyfin
server: https://kubernetes.default.svc
- namespace: kubernetes-dashboard
server: https://kubernetes.default.svc
- namespace: loops
server: https://kubernetes.default.svc
- namespace: mastodon
server: https://kubernetes.default.svc
- namespace: matrix
server: https://kubernetes.default.svc
- namespace: ollama
server: https://kubernetes.default.svc
- namespace: pixelfed
server: https://kubernetes.default.svc
- namespace: plex
server: https://kubernetes.default.svc
- namespace: nextcloud
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: apiextensions.k8s.io
kind: CustomResourceDefinition
- group: gateway.networking.k8s.io
kind: GatewayClass
- group: rbac.authorization.k8s.io
kind: ClusterRole
- group: rbac.authorization.k8s.io
kind: ClusterRoleBinding
namespaceResourceWhitelist:
- group: ""
kind: Service
- group: ""
kind: ConfigMap
- group: ""
kind: Service
- group: ""
kind: ServiceAccount
- group: apps
kind: Deployment
- group: gateway.networking.k8s.io
kind: Gateway
- group: monitoring.coreos.com
kind: ServiceMonitor
- group: policy
kind: PodDisruptionBudget
- group: rbac.authorization.k8s.io
kind: Role
- group: rbac.authorization.k8s.io
kind: RoleBinding
- group: traefik.io
kind: IngressRoute
- group: traefik.io
kind: Middleware
- group: traefik.io
kind: TLSStore
+31
View File
@@ -0,0 +1,31 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: traefik
namespace: argocd
spec:
project: traefik
sources:
- repoURL: https://ghcr.io/traefik/helm
chart: traefik
targetRevision: 42.0.0
helm:
releaseName: traefik
valueFiles:
- $values/apps/traefik/values.yaml
- repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
ref: values
- repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
path: apps/traefik/routes
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
enabled: true
prune: false
selfHeal: true
syncOptions:
- CreateNamespace=false