mirror of
https://gitlab.kube.huskypup.net/Scooby/Homelabv4.git
synced 2026-08-21 05:26:49 +00:00
Reduce replicas to 1 for workloads that don't need HA in a homelab: - Prometheus 2→1, Alertmanager 2→1 (~4.4GB RAM saved) - cert-manager 3→1 - GitLab: registry 2→1, kas 2→1, sidekiq 2→1, praefect 2→1, pgbouncer-ro 3→1 - Guacamole + guacd 2→1 - Kiali 2→1, ArgoCD server 2→1 - Kyverno background-controller 2→1 - Scylla operator 2→1 - ext-authz-proxy 2→1, netbird-cluster-router 2→1 Kept multi-replica: coredns, envoy-gateway, kyverno admission, vault, argocd-repo-server, gitlab-webservice, istiod, rook-ceph CSI. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
180 lines
5.1 KiB
YAML
180 lines
5.1 KiB
YAML
# Nginx proxy that rewrites Host header for Authentik ext_authz
|
|
#
|
|
# Problem: Envoy's ext_authz HTTP filter forwards the ORIGINAL request's Host
|
|
# header (e.g., prometheus.kube.huskypup.net) to Authentik. But Authentik's
|
|
# embedded outpost only serves /outpost.goauthentik.io/auth/nginx on the
|
|
# brand domain (auth.kube.huskypup.net), returning 404 for other hosts.
|
|
#
|
|
# Solution: This lightweight nginx proxy sits between Istio's ext_authz filter
|
|
# and Authentik. It rewrites the Host header to auth.kube.huskypup.net while
|
|
# preserving all other headers (X-Forwarded-Host, cookies, etc.) so Authentik
|
|
# knows the original service being accessed.
|
|
#
|
|
# Flow:
|
|
# 1. Client → Istio ingress gateway (Host: prometheus.kube.huskypup.net)
|
|
# 2. ext_authz filter → this proxy (Host: prometheus.kube.huskypup.net)
|
|
# 3. This proxy → Authentik (Host: auth.kube.huskypup.net, X-Forwarded-Host preserved)
|
|
# 4. Authentik checks auth, returns 200 (allow) or 302 (redirect to login)
|
|
---
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: ext-authz-proxy-config
|
|
namespace: authentik
|
|
data:
|
|
nginx.conf: |
|
|
load_module modules/ngx_http_js_module.so;
|
|
|
|
worker_processes 1;
|
|
error_log /dev/stderr warn;
|
|
pid /tmp/nginx.pid;
|
|
|
|
events {
|
|
worker_connections 256;
|
|
}
|
|
|
|
http {
|
|
access_log /dev/stdout;
|
|
proxy_temp_path /tmp/proxy_temp;
|
|
client_body_temp_path /tmp/client_temp;
|
|
|
|
js_path /etc/nginx/njs/;
|
|
js_import cookie from cookie_domain.js;
|
|
|
|
server {
|
|
listen 4180;
|
|
|
|
location / {
|
|
# Rewrite all paths to the exact Authentik traefik handler path.
|
|
# Envoy ext_authz appends the original request path to pathPrefix,
|
|
# creating paths like /auth/traefik/ which Authentik's Go router
|
|
# doesn't match (exact path only, no trailing slash).
|
|
rewrite ^ /outpost.goauthentik.io/auth/traefik break;
|
|
proxy_pass http://authentik-server.authentik.svc.cluster.local;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host auth.kube.huskypup.net;
|
|
proxy_set_header Connection "";
|
|
proxy_pass_request_headers on;
|
|
|
|
# Add Domain=kube.huskypup.net to Set-Cookie headers from Authentik.
|
|
# The outpost creates session cookies without Domain attribute, causing
|
|
# browser to scope them to the original request domain (e.g., frigate.kube.huskypup.net).
|
|
# The callback goes to auth.kube.huskypup.net, so the cookie must be domain-scoped.
|
|
js_header_filter cookie.addDomain;
|
|
}
|
|
}
|
|
}
|
|
|
|
cookie_domain.js: |
|
|
function addDomain(r) {
|
|
var cookies = r.headersOut['Set-Cookie'];
|
|
if (cookies) {
|
|
if (!Array.isArray(cookies)) {
|
|
cookies = [cookies];
|
|
}
|
|
var modified = cookies.map(function(c) {
|
|
if (c.indexOf('Domain=') === -1) {
|
|
return c + '; Domain=kube.huskypup.net';
|
|
}
|
|
return c;
|
|
});
|
|
r.headersOut['Set-Cookie'] = modified;
|
|
}
|
|
}
|
|
|
|
export default { addDomain };
|
|
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: ext-authz-proxy
|
|
namespace: authentik
|
|
labels:
|
|
app: ext-authz-proxy
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: ext-authz-proxy
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: ext-authz-proxy
|
|
spec:
|
|
automountServiceAccountToken: false
|
|
containers:
|
|
- name: nginx
|
|
image: nginx:1.27-alpine
|
|
ports:
|
|
- containerPort: 4180
|
|
protocol: TCP
|
|
volumeMounts:
|
|
- name: config
|
|
mountPath: /etc/nginx/nginx.conf
|
|
subPath: nginx.conf
|
|
readOnly: true
|
|
- name: njs
|
|
mountPath: /etc/nginx/njs/cookie_domain.js
|
|
subPath: cookie_domain.js
|
|
readOnly: true
|
|
- name: tmp
|
|
mountPath: /tmp
|
|
- name: cache
|
|
mountPath: /var/cache/nginx
|
|
resources:
|
|
requests:
|
|
cpu: 10m
|
|
memory: 32Mi
|
|
limits:
|
|
cpu: 50m
|
|
memory: 64Mi
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 10101
|
|
runAsGroup: 10101
|
|
allowPrivilegeEscalation: false
|
|
readOnlyRootFilesystem: true
|
|
capabilities:
|
|
drop:
|
|
- ALL
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
readinessProbe:
|
|
tcpSocket:
|
|
port: 4180
|
|
initialDelaySeconds: 2
|
|
periodSeconds: 5
|
|
livenessProbe:
|
|
tcpSocket:
|
|
port: 4180
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 10
|
|
volumes:
|
|
- name: config
|
|
configMap:
|
|
name: ext-authz-proxy-config
|
|
- name: njs
|
|
configMap:
|
|
name: ext-authz-proxy-config
|
|
- name: tmp
|
|
emptyDir: {}
|
|
- name: cache
|
|
emptyDir: {}
|
|
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: ext-authz-proxy
|
|
namespace: authentik
|
|
labels:
|
|
app: ext-authz-proxy
|
|
spec:
|
|
selector:
|
|
app: ext-authz-proxy
|
|
ports:
|
|
- port: 4180
|
|
targetPort: 4180
|
|
protocol: TCP
|