Files
Story Crater Bot 89f01b6f2e feat: add homelab-wide Authentik RBAC model and k8s OIDC auth wiring
Adds permissions claim + per-service admin groups in Authentik, scoped
Role/RoleBinding per service, public PKCE kubernetes OAuth2 client, and
kube-apiserver OIDC extraArgs. Also fixes paperless OIDC signup permissions
via adapter override and adds CoreDNS rewrite for authentik.riotpiao.com.
2026-08-25 15:03:44 -07:00

223 lines
7.0 KiB
Plaintext

version: ${version}
debug: false
persist: true
machine:
type: controlplane
token: ${token}
ca:
crt: ${ca_crt}
key: ${ca_key}
certSANs:
- ${lan_ip}
%{ for san in cloudflare_talos_sans ~}
- ${san}
%{ endfor ~}
network:
hostname: ${hostname}
interfaces:
- interface: eno1
addresses:
- ${lan_ip}/24
routes:
- network: 0.0.0.0/0
gateway: ${lan_gateway}
dhcp: false
dhcpOptions:
ipv6: false
nameservers:
%{ for ns in dns_servers ~}
- ${ns}
%{ endfor ~}
extraHostEntries:
- ip: ${forgejo_registry_ip}
aliases:
- ${forgejo_hostname}
# kube-apiserver's static pod runs on the host network, so it resolves
# authentik.riotpiao.com via THIS node's DNS, not cluster CoreDNS - the
# OIDC issuer discovery call would otherwise hit the public
# Cloudflare-fronted IP instead of nginx directly. Same reasoning as
# the forgejo entry above.
- ip: 192.168.1.160
aliases:
- authentik.riotpiao.com
kubelet:
image: ${kubelet_image}
defaultRuntimeSeccompProfileEnabled: true
disableManifestsDirectory: true
clusterDNS:
- ${cluster_dns_ip}
extraArgs:
rotate-server-certificates: true
nodeIP:
validSubnets:
- 192.168.1.0/24
install:
disk: ${install_disk}
image: factory.talos.dev/installer/613e1592b2da41ae5e265e8789429f22e121aab91cb4deb6bc3c0b6262961245:${talos_version}
# false: these are already-installed, running control-plane nodes. wipe:
# true here would only be correct for a first-boot/bare-metal install
# flow; applying it to a live node via apply-config risks the install
# controller treating this as a reinstall request. Live config on all 3
# CPs already reports wipe: false - keep template and reality in sync.
wipe: false
grubUseUKICmdline: true
%{ if length(longhorn_disks) > 0 ~}
disks:
%{ for idx, disk in longhorn_disks ~}
# ${disk.kind} — ${disk.device}
- device: ${disk.device}
partitions:
- mountpoint: ${coalesce(disk.mountpoint, format("/var/lib/longhorn-disk%d", idx + 1))}
%{ endfor ~}
%{ endif ~}
features:
diskQuotaSupport: true
kubePrism:
enabled: true
port: 7445
hostDNS:
enabled: false
nodeLabels:
node.kubernetes.io/exclude-from-external-load-balancers: ""
topology.kubernetes.io/region: homelab
topology.kubernetes.io/zone: ${zone}
%{ if !allow_scheduling ~}
# Dedicated control plane — re-apply the control-plane taint that
# allowSchedulingOnControlPlanes=true removed cluster-wide.
nodeTaints:
node-role.kubernetes.io/control-plane: ":NoSchedule"
%{ endif ~}
cluster:
id: ${cluster_id}
secret: ${cluster_secret}
controlPlane:
endpoint: https://${controlplane_ip}:6443
clusterName: ${cluster_name}
# true removes the default control-plane taint from ALL CP nodes; dedicated
# nodes (allow_scheduling=false) get it re-added via machine.nodeTaints above.
allowSchedulingOnControlPlanes: true
network:
dnsDomain: ${dns_domain}
podSubnets:
%{ for subnet in pod_subnets ~}
- ${subnet}
%{ endfor ~}
serviceSubnets:
%{ for subnet in service_subnets ~}
- ${subnet}
%{ endfor ~}
cni:
name: none
token: ${bootstrap_token}
secretboxEncryptionSecret: ${secretbox_encryption_secret}
ca:
crt: ${kubernetes_ca_crt}
key: ${kubernetes_ca_key}
aggregatorCA:
crt: ${aggregator_ca_crt}
key: ${aggregator_ca_key}
serviceAccount:
key: ${service_account_key}
apiServer:
certSANs:
- ${controlplane_ip}
- ${lan_ip}
%{ for san in cloudflare_apiserver_sans ~}
- ${san}
%{ endfor ~}
image: ${kube_apiserver_img}
# Foundation for the Authentik group -> k8s RBAC pattern in
# k8s/infra/rbac/ - additive only, existing client-cert auth
# (system:masters, this session's own admin@homelab-cluster kubeconfig)
# keeps working unchanged; a bad OIDC config just means OIDC logins fail,
# not a lockout. Prefixes avoid collision with built-in system:* users
# and groups.
extraArgs:
oidc-issuer-url: https://authentik.riotpiao.com/application/o/kubernetes/
oidc-client-id: kubernetes
oidc-username-claim: email
oidc-groups-claim: groups
oidc-username-prefix: "oidc:"
oidc-groups-prefix: "oidc:"
admissionControl:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1alpha1
defaults:
audit: restricted
audit-version: latest
enforce: baseline
enforce-version: latest
warn: restricted
warn-version: latest
exemptions:
namespaces:
- kube-system
runtimeClasses: []
usernames: []
kind: PodSecurityConfiguration
auditPolicy:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
controllerManager:
image: ${controller_mgr_img}
proxy:
image: ${kube_proxy_img}
disabled: true
scheduler:
image: ${scheduler_img}
discovery:
enabled: true
registries:
kubernetes:
disabled: true
service: {}
etcd:
# Pin etcd peer/advertise addresses to the LAN subnet explicitly.
advertisedSubnets:
- 192.168.1.0/24
ca:
crt: ${etcd_ca_crt}
key: ${etcd_ca_key}
extraManifests:
- https://raw.githubusercontent.com/alex1989hu/kubelet-serving-cert-approver/main/deploy/standalone-install.yaml
- https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
inlineManifests:
- name: cilium
contents: |
apiVersion: v1
kind: Namespace
metadata:
name: kube-system
# Cilium LoadBalancer IPAM pool + L2 announcement policy. Substrate networking
# (owned here alongside the Cilium install), single source of truth in
# terraform/files/cilium/*.yaml. Provides LAN LoadBalancer IPs for ingress-nginx
# (.160) and forgejo-ssh (.161). Was previously an ArgoCD app whose empty
# kustomization never actually applied it (the live pool came from manual
# kubectl); moved here so LB-IPAM exists before any LoadBalancer Service syncs.
- name: cilium-lb-ippool
contents: |
${indent(8, cilium_lb_ippool)}
- name: cilium-l2-announcement
contents: |
${indent(8, cilium_l2_announcement)}
# CoreDNS Corefile with homelab hostname rewrites (single source of truth in
# terraform/files/coredns/Corefile). In-cluster pods resolve *.riotpiao.com to
# the nginx ingress controller so OIDC auto-discovery against
# authentik.riotpiao.com works and the Host header is preserved. Owned by
# Talos — do NOT also manage the coredns ConfigMap via ArgoCD.
- name: coredns-config
contents: |
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
${indent(12, coredns_corefile)}