--- apiVersion: v1 kind: Namespace metadata: name: fc-dns labels: app.kubernetes.io/part-of: flowercore --- # 1Password-backed Secret for the pfSense admin password. # The operator watches this CRD, resolves the vault item, and produces a # K8s Secret of the same name with each 1P field as a key. The `password` # field of the "pfSense Admin" item becomes Secret key `password`. apiVersion: onepassword.com/v1 kind: OnePasswordItem metadata: name: pfsense-admin namespace: fc-dns spec: itemPath: "vaults/IAmWorkin/items/pfSense Admin" --- apiVersion: onepassword.com/v1 kind: OnePasswordItem metadata: name: dns-oidc-client namespace: fc-dns spec: itemPath: "vaults/IAmWorkin/items/dns-oidc-client" --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: dns-web-data namespace: fc-dns spec: accessModes: [ReadWriteOnce] storageClassName: longhorn resources: requests: storage: 1Gi --- apiVersion: v1 kind: ConfigMap metadata: name: dns-web-config namespace: fc-dns data: appsettings.Production.json: | { "FlowerCore": { "Auth": { "Enabled": true, "Oidc": { "Enabled": true, "Audience": "dns", "RequireHttpsMetadata": true } }, "Database": { "Provider": "Sqlite", "ConnectionStrings": { "Sqlite": "Data Source=/data/dns.db" } }, "Tenant": { "DefaultTenantId": "default", "JwtClaimsEnabled": false, "DefaultTenantHosts": [ "dns.iamworkin.lan" ] }, "Audit": { "HashChain": { "BridgeSensitivity": { "Distribution": "Warn" } } } } } --- apiVersion: apps/v1 kind: Deployment metadata: name: dns-web namespace: fc-dns labels: app.kubernetes.io/name: dns-web app.kubernetes.io/managed-by: flowercore spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app.kubernetes.io/name: dns-web template: metadata: labels: app.kubernetes.io/name: dns-web annotations: prometheus.io/scrape: "true" prometheus.io/port: "5320" prometheus.io/path: "/metrics/prometheus" spec: serviceAccountName: dns-web securityContext: runAsNonRoot: true runAsUser: 1654 runAsGroup: 1654 fsGroup: 1654 containers: - name: dns-web image: localhost/fc-dns-web:v20260604-oidc-proper imagePullPolicy: Never securityContext: readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: [ALL] ports: - containerPort: 5320 env: # pfSense admin password resolved by the 1Password operator. # `FallbackPassword` is the Slice A seam exposed by # OptionsFallbackPasswordResolver; Slice B will replace it with # a pull-at-runtime 1P Connect resolver once Shared.Vault ships. - name: FlowerCore__Dns__Providers__PfSenseUnbound__FallbackPassword valueFrom: secretKeyRef: name: pfsense-admin key: password - name: FlowerCore__Auth__Oidc__Authority valueFrom: secretKeyRef: name: dns-oidc-client key: issuer_url optional: true - name: FlowerCore__Auth__Oidc__ClientId valueFrom: secretKeyRef: name: dns-oidc-client key: client_id optional: true - name: FlowerCore__Auth__Oidc__ClientSecret valueFrom: secretKeyRef: name: dns-oidc-client key: client_secret optional: true - name: FlowerCore__Auth__Enabled value: "true" - name: FlowerCore__Auth__Oidc__Enabled value: "true" - name: FlowerCore__Auth__Oidc__Audience value: "dns" volumeMounts: - name: data mountPath: /data - name: tmp mountPath: /tmp - name: logs mountPath: /app/logs - name: config mountPath: /app/appsettings.Production.json subPath: appsettings.Production.json readOnly: true resources: requests: cpu: 50m memory: 96Mi limits: cpu: 300m memory: 384Mi readinessProbe: httpGet: path: /healthz port: 5320 initialDelaySeconds: 10 periodSeconds: 10 livenessProbe: httpGet: path: /healthz port: 5320 initialDelaySeconds: 20 periodSeconds: 30 volumes: - name: data persistentVolumeClaim: claimName: dns-web-data - name: tmp emptyDir: {} - name: logs emptyDir: {} - name: config configMap: name: dns-web-config --- apiVersion: v1 kind: Service metadata: name: dns-web namespace: fc-dns spec: selector: app.kubernetes.io/name: dns-web ports: - port: 5320 targetPort: 5320 type: ClusterIP --- apiVersion: v1 kind: ServiceAccount metadata: name: dns-web namespace: fc-dns --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: dns-web rules: - apiGroups: [""] resources: ["namespaces", "pods", "services", "secrets", "configmaps"] verbs: ["get", "list", "watch"] - apiGroups: ["cert-manager.io"] resources: ["certificates"] verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: dns-web subjects: - kind: ServiceAccount name: dns-web namespace: fc-dns roleRef: kind: ClusterRole name: dns-web apiGroup: rbac.authorization.k8s.io --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: dns-web-cert namespace: fc-dns spec: secretName: dns-web-tls issuerRef: name: step-ca-dns01 kind: ClusterIssuer dnsNames: - dns.iamworkin.lan duration: 720h renewBefore: 240h --- apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: dns-web namespace: fc-dns spec: entryPoints: [websecure] routes: - match: Host(`dns.iamworkin.lan`) kind: Rule services: - name: dns-web port: 5320 tls: secretName: dns-web-tls --- apiVersion: v1 kind: ServiceAccount metadata: name: dns-acme-webhook namespace: fc-dns --- apiVersion: apps/v1 kind: Deployment metadata: name: dns-acme-webhook namespace: fc-dns labels: app.kubernetes.io/name: dns-acme-webhook app.kubernetes.io/managed-by: flowercore spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: dns-acme-webhook template: metadata: labels: app.kubernetes.io/name: dns-acme-webhook spec: serviceAccountName: dns-acme-webhook securityContext: runAsNonRoot: true runAsUser: 1654 runAsGroup: 1654 fsGroup: 1654 containers: - name: dns-acme-webhook image: localhost/fc-dns-acme-webhook:v202604290845 imagePullPolicy: Never securityContext: readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: [ALL] ports: - containerPort: 9443 name: https env: - name: ASPNETCORE_URLS value: https://+:9443 - name: Kestrel__Certificates__Default__Path value: /tls/tls.crt - name: Kestrel__Certificates__Default__KeyPath value: /tls/tls.key - name: FlowerCore__Dns__AcmeWebhook__ServiceBaseUrl value: http://dns-web:5320 - name: FlowerCore__Dns__AcmeWebhook__GroupName value: acme.flowercore.io - name: FlowerCore__Dns__AcmeWebhook__SolverName value: flowercore-dns - name: FlowerCore__Dns__AcmeWebhook__Version value: v1alpha1 volumeMounts: - name: tls mountPath: /tls readOnly: true - name: tmp mountPath: /tmp - name: logs mountPath: /app/logs resources: requests: cpu: 25m memory: 64Mi limits: cpu: 200m memory: 256Mi readinessProbe: httpGet: scheme: HTTPS path: /readyz port: https initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 5 livenessProbe: httpGet: scheme: HTTPS path: /healthz port: https initialDelaySeconds: 10 periodSeconds: 20 timeoutSeconds: 5 volumes: - name: tls secret: secretName: dns-acme-webhook-tls - name: tmp emptyDir: {} - name: logs emptyDir: {} --- apiVersion: v1 kind: Service metadata: name: dns-acme-webhook namespace: fc-dns spec: selector: app.kubernetes.io/name: dns-acme-webhook ports: - port: 443 targetPort: https name: https type: ClusterIP --- apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: dns-acme-webhook-selfsigned namespace: fc-dns spec: selfSigned: {} --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: dns-acme-webhook-ca namespace: fc-dns spec: secretName: dns-acme-webhook-ca duration: 43800h issuerRef: name: dns-acme-webhook-selfsigned commonName: ca.dns-acme-webhook.fc-dns isCA: true --- apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: dns-acme-webhook-ca-issuer namespace: fc-dns spec: ca: secretName: dns-acme-webhook-ca --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: dns-acme-webhook-serving-cert namespace: fc-dns spec: secretName: dns-acme-webhook-tls duration: 8760h issuerRef: name: dns-acme-webhook-ca-issuer dnsNames: - dns-acme-webhook - dns-acme-webhook.fc-dns - dns-acme-webhook.fc-dns.svc --- apiVersion: apiregistration.k8s.io/v1 kind: APIService metadata: name: v1alpha1.acme.flowercore.io annotations: cert-manager.io/inject-ca-from: fc-dns/dns-acme-webhook-serving-cert spec: group: acme.flowercore.io groupPriorityMinimum: 1000 service: name: dns-acme-webhook namespace: fc-dns version: v1alpha1 versionPriority: 15 --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: dns-acme-webhook-solver rules: - apiGroups: ["acme.flowercore.io"] resources: ["flowercore-dns"] verbs: ["create"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: dns-acme-webhook-solver subjects: - kind: ServiceAccount name: cert-manager namespace: cert-manager roleRef: kind: ClusterRole name: dns-acme-webhook-solver apiGroup: rbac.authorization.k8s.io --- apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: step-ca-dns01 spec: acme: caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJ4RENDQVdxZ0F3SUJBZ0lSQVBZMzU3RzZvdzZ6TUFMNSs0YlMya2t3Q2dZSUtvWkl6ajBFQXdJd1FERWEKTUJnR0ExVUVDaE1SU1VGdFYyOXlhMmx1SUVGRFRVVWdRMEV4SWpBZ0JnTlZCQU1UR1VsQmJWZHZjbXRwYmlCQgpRMDFGSUVOQklGSnZiM1FnUTBFd0hoY05Nall3TXpBNE1UZ3dOekV4V2hjTk16WXdNekExTVRnd056RXhXakJBCk1Sb3dHQVlEVlFRS0V4RkpRVzFYYjNKcmFXNGdRVU5OUlNCRFFURWlNQ0FHQTFVRUF4TVpTVUZ0VjI5eWEybHUKSUVGRFRVVWdRMEVnVW05dmRDQkRRVEJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCSjJuMDRYMQpKWm81WmRxL2kxSWR2OCtmcXdaeUF6Qmg3d2hicWowU1dzSkw4VVdSYWJDTXFZQ3M3K2RYTzB4UlN6cWt3RkRMCngrdm9vT2FpOFJnUk5oYWpSVEJETUE0R0ExVWREd0VCL3dRRUF3SUJCakFTQmdOVkhSTUJBZjhFQ0RBR0FRSC8KQWdFQk1CMEdBMVVkRGdRV0JCUm51UFBRUjZpTS9INnZPbHVpVTNTeWdheXo4akFLQmdncWhrak9QUVFEQWdOSQpBREJGQWlFQXJRSzlkWVBHbUFac2RZbmp6aXVGVlZFNU5LWlVjY2VZdkdmR0MrdExYVXNDSUF1ZEYyekpyQ1JxCjNtSzUwWlpFVC9md1RrSndpRUY0ODI0bWpQOHAxQ0tNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K privateKeySecretRef: name: step-ca-dns01-account-key server: https://10.0.56.10:9443/acme/acme/directory solvers: - dns01: webhook: groupName: acme.flowercore.io solverName: flowercore-dns