# FlowerCore.Network.Web — the pfSense automation plane (read-only Phase 0, ADR-189). # # Phase 0 is READ-ONLY: the service holds NO pfSense credentials and has no write # path to pfSense anywhere. The only mutating endpoint is POST /api/v1/snapshots, # which ingests a config.xml the noc1 exporter collected READ-ONLY and stores it # (redacted projection) on the PVC. Auth ships gate-OFF. # # Image localhost/fc-network-web: is built by FlowerCore.Network # scripts/deploy-k8s.sh and imported to all schedulable RKE2 nodes (rke2-server + # rke2-agent1; agent2 retired). imagePullPolicy: Never — bump the tag here, sync # ArgoCD, then scale 0->1 for the RWO PVC and verify the running pod imageID. --- apiVersion: apps/v1 kind: Deployment metadata: name: fc-network-web namespace: fc-network labels: app: fc-network-web app.kubernetes.io/name: fc-network-web app.kubernetes.io/component: web app.kubernetes.io/part-of: flowercore app.kubernetes.io/managed-by: argocd flowercore.io/tenant-id: system flowercore.io/created-by: bluejay-infra annotations: flowercore.io/traceability-standard: k8s-pod-ownership-and-traceability-standard spec: replicas: 1 revisionHistoryLimit: 3 # RWO PVC: a single replica can't be surged (the new pod can't mount the volume # while the old one holds it). maxSurge 0 / maxUnavailable 1 is the rwo-safe shape; # for image bumps scale 0->1 rather than rollout restart. strategy: type: RollingUpdate rollingUpdate: maxSurge: 0 maxUnavailable: 1 selector: matchLabels: app: fc-network-web template: metadata: labels: app: fc-network-web app.kubernetes.io/name: fc-network-web app.kubernetes.io/component: web app.kubernetes.io/part-of: flowercore app.kubernetes.io/managed-by: argocd flowercore.io/tenant-id: system flowercore.io/created-by: bluejay-infra annotations: fc.flowercore.io/healthz-anon: "true" fc.flowercore.io/probe-path: "/healthz" prometheus.io/scrape: "true" prometheus.io/port: "5340" prometheus.io/path: "/metrics/prometheus" flowercore.io/audit-trace-id: "runtime-activity-trace" spec: securityContext: fsGroup: 1654 fsGroupChangePolicy: OnRootMismatch containers: - name: web image: localhost/fc-network-web:v20260612-0b5b049 imagePullPolicy: Never ports: - name: http containerPort: 5340 # fc-safe-to-expose: read-only plane, auth gate-OFF; X-Forwarded-Proto handled # by AddFlowerCoreWebAuth (ADR-178) before any future public/OIDC flip. env: - name: ASPNETCORE_URLS value: "http://+:5340" - name: ASPNETCORE_ENVIRONMENT value: "Production" - name: DOTNET_SYSTEM_GLOBALIZATION_INVARIANT value: "false" - name: HOME value: "/data" - name: FlowerCore__Auth__Enabled value: "false" - name: FlowerCore__Database__Provider value: "Sqlite" - name: FlowerCore__Database__ConnectionStrings__Sqlite value: "Data Source=/data/network.db" # Snapshot store + intended-model paths MUST be absolute on the PVC — # the default is relative to the read-only content root. - name: FlowerCore__Network__SnapshotStore__RootDirectory value: "/data/snapshots" - name: FlowerCore__Network__SnapshotStore__UseGitHistory value: "true" - name: FlowerCore__Network__IntendedModel__FilePath value: "/data/intended.json" resources: requests: cpu: 50m memory: 128Mi limits: cpu: 500m memory: 512Mi startupProbe: httpGet: path: /healthz port: 5340 initialDelaySeconds: 5 periodSeconds: 5 failureThreshold: 30 readinessProbe: httpGet: path: /healthz port: 5340 periodSeconds: 10 failureThreshold: 3 livenessProbe: httpGet: path: /healthz port: 5340 initialDelaySeconds: 30 periodSeconds: 30 failureThreshold: 3 securityContext: runAsNonRoot: true runAsUser: 1654 runAsGroup: 1654 allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL volumeMounts: - name: data mountPath: /data - name: tmp mountPath: /tmp - name: logs mountPath: /app/logs volumes: - name: data persistentVolumeClaim: claimName: fc-network-web-data - name: tmp emptyDir: {} - name: logs emptyDir: {}