diff --git a/.env.example b/.env.example index 711c624..bafecdb 100644 --- a/.env.example +++ b/.env.example @@ -9,4 +9,6 @@ K3S_NODE_TOKEN=your_token_here GITEA_RUNNER_TOKEN=your_token_here # Grafana admin password -GRAFANA_ADMIN_PASSWORD=your_password_here \ No newline at end of file +GRAFANA_ADMIN_PASSWORD=your_password_here + +AUTHENTIK_PROXY_TOKEN=your_token_here \ No newline at end of file diff --git a/manifests/authentik-ingress.yaml b/manifests/authentik-ingress.yaml new file mode 100644 index 0000000..330a029 --- /dev/null +++ b/manifests/authentik-ingress.yaml @@ -0,0 +1,29 @@ +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: authentik-tls + namespace: authentik +spec: + secretName: authentik-tls + issuerRef: + name: internal-ca + kind: ClusterIssuer + dnsNames: + - auth.home.arpa +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: authentik + namespace: authentik +spec: + entryPoints: + - websecure + routes: + - match: Host(`auth.home.arpa`) + kind: Rule + services: + - name: authentik-server + port: 80 + tls: + secretName: authentik-tls diff --git a/manifests/authentik-middleware.yaml b/manifests/authentik-middleware.yaml new file mode 100644 index 0000000..9653b71 --- /dev/null +++ b/manifests/authentik-middleware.yaml @@ -0,0 +1,31 @@ +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: authentik-auth + namespace: authentik +spec: + forwardAuth: + address: http://authentik-proxy-outpost.authentik.svc.cluster.local:9000/outpost.goauthentik.io/auth/traefik + trustForwardHeader: true + authResponseHeaders: + - X-authentik-username + - X-authentik-groups + - 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 +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: lan-bypass + namespace: authentik +spec: + ipAllowList: + sourceRange: + - 192.168.7.0/24 \ No newline at end of file diff --git a/manifests/authentik-proxy-outpost.yaml b/manifests/authentik-proxy-outpost.yaml new file mode 100644 index 0000000..f131512 --- /dev/null +++ b/manifests/authentik-proxy-outpost.yaml @@ -0,0 +1,53 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: authentik-proxy-outpost + namespace: authentik +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: authentik-proxy-outpost + namespace: authentik +spec: + replicas: 1 + selector: + matchLabels: + app: authentik-proxy-outpost + template: + metadata: + labels: + app: authentik-proxy-outpost + spec: + serviceAccountName: authentik-proxy-outpost + containers: + - name: proxy + image: ghcr.io/goauthentik/proxy:2026.2.1 + env: + - name: AUTHENTIK_HOST + value: "https://auth.home.arpa" + - name: AUTHENTIK_INSECURE + value: "true" + - name: AUTHENTIK_TOKEN + valueFrom: + secretKeyRef: + name: authentik-proxy-token + key: token + ports: + - containerPort: 9000 + name: http + - containerPort: 9443 + name: https +--- +apiVersion: v1 +kind: Service +metadata: + name: authentik-proxy-outpost + namespace: authentik +spec: + selector: + app: authentik-proxy-outpost + ports: + - name: http + port: 9000 + targetPort: 9000 \ No newline at end of file diff --git a/manifests/authentik-proxy-secret.sh b/manifests/authentik-proxy-secret.sh new file mode 100755 index 0000000..2ffb057 --- /dev/null +++ b/manifests/authentik-proxy-secret.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -euo pipefail +source "$(dirname "$0")/../.env" + +kubectl create secret generic authentik-proxy-token \ + --namespace authentik \ + --from-literal=token="${AUTHENTIK_PROXY_TOKEN}" \ + --dry-run=client -o yaml | kubectl apply -f - \ No newline at end of file diff --git a/manifests/authentik-secret.sh b/manifests/authentik-secret.sh new file mode 100755 index 0000000..f1e89b6 --- /dev/null +++ b/manifests/authentik-secret.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Run once to create the Authentik secret. Safe to re-run (dry-run + apply). +kubectl create secret generic authentik-secrets \ + --namespace authentik \ + --from-literal=secret-key="$(openssl rand -base64 50)" \ + --from-literal=postgresql-password="$(openssl rand -base64 24)" \ + --dry-run=client -o yaml | kubectl apply -f - diff --git a/manifests/pihole-debian-patch.sh b/manifests/pihole-debian-patch.sh old mode 100644 new mode 100755 diff --git a/manifests/traefik-dashboard-ingress.yaml b/manifests/traefik-dashboard-ingress.yaml new file mode 100644 index 0000000..7b96fa8 --- /dev/null +++ b/manifests/traefik-dashboard-ingress.yaml @@ -0,0 +1,48 @@ +# Traefik dashboard IngressRoute and TLS certificate for accessing the dashboard at https://traefik.home.arpa. The dashboard is protected by the authentik authentication middleware, with a bypass for LAN clients. +# Apply: kubectl apply -f manifests/traefik-dashboard-ingress.yaml +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: traefik-dashboard + namespace: traefik +spec: + entryPoints: + - websecure + routes: + - match: Host(`traefik.home.arpa`) && PathPrefix(`/outpost.goauthentik.io`) + kind: Rule + services: + - name: authentik-proxy-outpost + namespace: authentik + port: 9000 + - match: Host(`traefik.home.arpa`) && PathPrefix(`/dashboard`) + kind: Rule + middlewares: + - name: authentik-auth + namespace: authentik + services: + - name: api@internal + kind: TraefikService + - match: Host(`traefik.home.arpa`) && PathPrefix(`/api`) + kind: Rule + middlewares: + - name: authentik-auth + namespace: authentik + services: + - name: api@internal + kind: TraefikService + tls: + secretName: traefik-dashboard-tls +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: traefik-dashboard-tls + namespace: traefik +spec: + secretName: traefik-dashboard-tls + issuerRef: + name: internal-ca + kind: ClusterIssuer + dnsNames: + - traefik.home.arpa \ No newline at end of file diff --git a/values/authentik.yaml b/values/authentik.yaml new file mode 100644 index 0000000..3330531 --- /dev/null +++ b/values/authentik.yaml @@ -0,0 +1,88 @@ +# authentik Helm values +# Deploy: +# helm upgrade --install authentik authentik/authentik \ +# --namespace authentik \ +# --version 2026.2.1 \ +# --values values/authentik.yaml \ +# --wait --timeout 5m + +authentik: + secret_key: "" # kept blank — comes from existingSecret via env below + existingSecret: + secretName: "" # kept blank — not used directly, but required to avoid Helm validation error + log_level: info + error_reporting: + enabled: false + +server: + env: + - name: AUTHENTIK_SECRET_KEY + valueFrom: + secretKeyRef: + name: authentik-secrets + key: secret-key + - name: AUTHENTIK_POSTGRESQL__PASSWORD + valueFrom: + secretKeyRef: + name: authentik-secrets + key: postgresql-password + - name: AUTHENTIK_POSTGRESQL__HOST + value: "authentik-postgresql" + - name: AUTHENTIK_POSTGRESQL__USER + value: "authentik" + - name: AUTHENTIK_POSTGRESQL__NAME + value: "authentik" + +worker: + env: + - name: AUTHENTIK_SECRET_KEY + valueFrom: + secretKeyRef: + name: authentik-secrets + key: secret-key + - name: AUTHENTIK_POSTGRESQL__PASSWORD + valueFrom: + secretKeyRef: + name: authentik-secrets + key: postgresql-password + - name: AUTHENTIK_POSTGRESQL__HOST + value: "authentik-postgresql" + - name: AUTHENTIK_POSTGRESQL__USER + value: "authentik" + - name: AUTHENTIK_POSTGRESQL__NAME + value: "authentik" + +postgresql: + enabled: true + auth: + username: authentik + database: authentik + existingSecret: authentik-secrets + secretKeys: + adminPasswordKey: postgresql-password + userPasswordKey: postgresql-password + primary: + persistence: + enabled: true + podAnnotations: + helm.sh/resource-policy: keep + +redis: + enabled: true + auth: + enabled: false + +additionalObjects: + - apiVersion: v1 + kind: Service + metadata: + name: authentik-worker + namespace: authentik + spec: + selector: + app.kubernetes.io/component: worker + app.kubernetes.io/instance: authentik + ports: + - name: http + port: 9000 + targetPort: 9000 diff --git a/values/pihole.yaml b/values/pihole.yaml index 8241adc..d4cd043 100644 --- a/values/pihole.yaml +++ b/values/pihole.yaml @@ -79,4 +79,6 @@ dnsmasq: - address=/jdownloader.home.arpa/192.168.7.77 - address=/glances.home.arpa/192.168.7.77 - address=/glances-debian.home.arpa/192.168.7.77 - - address=/ca.home.arpa/1 \ No newline at end of file + - address=/ca.home.arpa/192.168.7.77 + - address=/auth.home.arpa/192.168.7.77 + - address=/traefik.home.arpa/192.168.7.77 \ No newline at end of file diff --git a/values/traefik.yaml b/values/traefik.yaml index 7fca2a6..6afd3a5 100644 --- a/values/traefik.yaml +++ b/values/traefik.yaml @@ -49,6 +49,10 @@ additionalArguments: - "--certificatesresolvers.letsencrypt.acme.email=nik.afiq98@ymail.com" - "--certificatesresolvers.letsencrypt.acme.storage=/data/traefik/acme.json" +providers: + kubernetesCRD: + allowCrossNamespace: true + volumes: - name: traefik-data hostPath: @@ -60,4 +64,8 @@ logs: general: level: INFO access: - enabled: true \ No newline at end of file + enabled: true + +api: + dashboard: true + insecure: false \ No newline at end of file