apiVersion: v1 kind: Namespace metadata: name: dns --- # ------------------------------------------------------------- # Persistent Volumes for Technitium & Pi-hole (Longhorn) # ------------------------------------------------------------- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: technitium-config-pvc namespace: dns spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: 5Gi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pihole-etc-pvc namespace: dns spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: 5Gi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pihole-dnsmasq-pvc namespace: dns spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: 2Gi --- # ------------------------------------------------------------- # Technitium DNS Server (Authoritative, Recursive & DoH Upstream) # ------------------------------------------------------------- apiVersion: apps/v1 kind: Deployment metadata: name: technitium-dns namespace: dns labels: app: technitium-dns spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: technitium-dns template: metadata: labels: app: technitium-dns spec: containers: - name: technitium-dns image: technitium/dns-server:latest imagePullPolicy: IfNotPresent env: - name: DNS_SERVER_ADMIN_PASSWORD value: "snarfnetadmin" - name: DNS_SERVER_FORWARDERS value: "https://dns.quad9.net/dns-query,https://1.1.1.1/dns-query" - name: DNS_SERVER_PREFER_IPV6 value: "false" - name: DNS_SERVER_LOG_USING_LOCAL_TIME value: "true" - name: DNS_SERVER_SSO_ENABLED value: "true" - name: DNS_SERVER_SSO_AUTHORITY value: "https://authentik.snarfnet.net/application/o/dns2/" - name: DNS_SERVER_SSO_METADATA_ADDRESS value: "https://authentik.snarfnet.net/application/o/dns2/.well-known/openid-configuration" - name: DNS_SERVER_SSO_CLIENT_ID value: "technitium2-dns-oidc" - name: DNS_SERVER_SSO_CLIENT_SECRET value: "SnarfNetTechnitiumOIDC2026!" - name: DNS_SERVER_SSO_SCOPES value: "openid,profile,email" - name: DNS_SERVER_SSO_ALLOW_SIGNUP value: "true" - name: DNS_SERVER_SSO_ALLOW_SIGNUP_ONLY_FOR_MAPPED_USERS value: "false" - name: DNS_SERVER_SSO_GROUP_MAP value: "authentik Admins:Administrators" ports: - name: dns-udp containerPort: 53 protocol: UDP - name: dns-tcp containerPort: 53 protocol: TCP - name: web-http containerPort: 5380 protocol: TCP volumeMounts: - name: technitium-config mountPath: /etc/dns resources: requests: cpu: 100m memory: 256Mi limits: cpu: 1000m memory: 1024Mi volumes: - name: technitium-config persistentVolumeClaim: claimName: technitium-config-pvc --- apiVersion: v1 kind: Service metadata: name: technitium-service namespace: dns labels: app: technitium-dns spec: type: ClusterIP selector: app: technitium-dns ports: - name: dns-udp port: 53 targetPort: 53 protocol: UDP - name: dns-tcp port: 53 targetPort: 53 protocol: TCP - name: web-http port: 5380 targetPort: 5380 protocol: TCP --- # ------------------------------------------------------------- # Pi-hole (Front-end Filtering, Caching & Ad-blocking) # ------------------------------------------------------------- apiVersion: apps/v1 kind: Deployment metadata: name: pihole namespace: dns labels: app: pihole spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: pihole template: metadata: labels: app: pihole spec: containers: - name: pihole image: pihole/pihole:latest imagePullPolicy: IfNotPresent env: - name: TZ value: "America/New_York" - name: FTLCONF_rateLimit value: "0/0" - name: FTLCONF_dns_upstreams value: "technitium-service.dns.svc.cluster.local#53" - name: FTLCONF_dns_listeningMode value: "all" - name: FTLCONF_dns_dnssec value: "false" - name: FTLCONF_webserver_port value: "80" - name: FTLCONF_webserver_api_password value: "snarfnetadmin" - name: WEBPASSWORD value: "snarfnetadmin" ports: - name: dns-udp containerPort: 53 protocol: UDP - name: dns-tcp containerPort: 53 protocol: TCP - name: http containerPort: 80 protocol: TCP volumeMounts: - name: pihole-etc mountPath: /etc/pihole - name: pihole-dnsmasq mountPath: /etc/dnsmasq.d resources: requests: cpu: 100m memory: 256Mi limits: cpu: 1000m memory: 1024Mi volumes: - name: pihole-etc persistentVolumeClaim: claimName: pihole-etc-pvc - name: pihole-dnsmasq persistentVolumeClaim: claimName: pihole-dnsmasq-pvc --- # ------------------------------------------------------------- # MetalLB LoadBalancer VIP on Port 53 (Spaceport Secondary: 140.44.4.65) # ------------------------------------------------------------- apiVersion: v1 kind: Service metadata: name: pihole-dns-vip namespace: dns annotations: metallb.universe.tf/loadBalancerIPs: 140.44.4.65 metallb.universe.tf/allow-shared-ip: "spaceport-dns-key" labels: app: pihole spec: type: LoadBalancer selector: app: pihole ports: - name: dns-udp port: 53 targetPort: 53 protocol: UDP - name: dns-tcp port: 53 targetPort: 53 protocol: TCP --- apiVersion: v1 kind: Service metadata: name: pihole-web-vip namespace: dns annotations: metallb.universe.tf/loadBalancerIPs: 140.44.4.65 metallb.universe.tf/allow-shared-ip: "spaceport-dns-key" labels: app: pihole spec: type: LoadBalancer selector: app: pihole ports: - name: web-http port: 80 targetPort: 80 protocol: TCP --- apiVersion: v1 kind: Service metadata: name: technitium-web-vip namespace: dns annotations: metallb.universe.tf/loadBalancerIPs: 140.44.4.65 metallb.universe.tf/allow-shared-ip: "spaceport-dns-key" labels: app: technitium-dns spec: type: LoadBalancer selector: app: technitium-dns ports: - name: web-http port: 5380 targetPort: 5380 protocol: TCP --- # ------------------------------------------------------------- # Traefik Redirect Middleware (Root to /admin/) # ------------------------------------------------------------- apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: pihole-redirect namespace: dns spec: redirectRegex: regex: "^https?://([^/]+)/?$" replacement: "https://${1}/admin/" permanent: false --- # ------------------------------------------------------------- # Traefik ForwardAuth Middleware (Authentik Outpost) # ------------------------------------------------------------- apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: authentik-forwardauth namespace: dns spec: forwardAuth: address: https://authentik.snarfnet.net/outpost.goauthentik.io/auth/traefik authResponseHeaders: - X-authentik-username - X-authentik-groups - X-authentik-email - X-authentik-name - X-authentik-uid trustForwardHeader: true --- # ------------------------------------------------------------- # Pi-hole Web Ingress (TLS + Authentik ForwardAuth + Root Redirect) # ------------------------------------------------------------- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: pihole-ingress namespace: dns annotations: traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.tls: "true" traefik.ingress.kubernetes.io/router.middlewares: dns-authentik-forwardauth@kubernetescrd,dns-pihole-redirect@kubernetescrd spec: ingressClassName: traefik rules: - host: pihole2.snarfnet.net http: paths: - path: / pathType: Prefix backend: service: name: pihole-web-vip port: number: 80 tls: - hosts: - pihole2.snarfnet.net secretName: tls-snarfnet-wildcard --- # ------------------------------------------------------------- # Technitium Web Ingress (TLS + Native OIDC) # ------------------------------------------------------------- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: technitium-ingress namespace: dns annotations: traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.tls: "true" spec: ingressClassName: traefik rules: - host: dns2.snarfnet.net http: paths: - path: / pathType: Prefix backend: service: name: technitium-web-vip port: number: 5380 tls: - hosts: - dns2.snarfnet.net secretName: tls-snarfnet-wildcard