# k8s/backend.yaml # ============================================ # Chat Switchboard - Backend Deployment # ============================================ # Secrets: # switchboard-db-credentials - POSTGRES_USER, POSTGRES_PASSWORD # switchboard-admin - username, password, email (optional) # switchboard-encryption - ENCRYPTION_KEY (required for v0.9.4+) # # PVC: # switchboard-storage - Extraction scratch (always needed) # Requires ReadWriteMany (RWX) — see k8s/storage-pvc.yaml # With S3 backend, PVC is small (extraction status only, not blobs) # # Variables (Gitea CI): # STORAGE_CLASS - StorageClass for PVC (e.g. "cephfs") # STORAGE_SIZE - PVC size (e.g. "10Gi" for PVC, "1Gi" for S3) # STORAGE_BACKEND - "pvc" or "s3" (default: "pvc") # EXTRACTION_CONCURRENCY - Max concurrent extractions (default "3") # EXTRACTOR_IMAGE - Sidecar image (LibreOffice headless) # # S3 secrets (Gitea Secrets — only when STORAGE_BACKEND=s3): # S3_ENDPOINT - e.g. "http://minio:9000" or Ceph RGW URL # S3_BUCKET - bucket name (must exist before deploy) # S3_ACCESS_KEY - S3 access key # S3_SECRET_KEY - S3 secret key # # Admin bootstrap: on every pod start, if SWITCHBOARD_ADMIN_* env vars # are set, the backend upserts an admin user. Change the secret and # restart the pod to reset the admin password. # ============================================ apiVersion: apps/v1 kind: Deployment metadata: name: switchboard-be${DEPLOY_SUFFIX} namespace: ${NAMESPACE} labels: app: switchboard component: backend env: ${ENVIRONMENT} spec: replicas: ${BE_REPLICAS} selector: matchLabels: app: switchboard component: backend env: ${ENVIRONMENT} template: metadata: labels: app: switchboard component: backend env: ${ENVIRONMENT} spec: containers: - name: backend image: ${BE_IMAGE}:${IMAGE_TAG} imagePullPolicy: Always ports: - containerPort: 8080 name: http env: - name: ENVIRONMENT value: "${ENVIRONMENT}" - name: GIN_MODE value: "${GIN_MODE}" - name: PORT value: "8080" - name: BASE_PATH value: "${BASE_PATH}" - name: POSTGRES_HOST value: "${POSTGRES_HOST}" - name: POSTGRES_PORT value: "${POSTGRES_PORT}" - name: POSTGRES_DB value: "${DB_NAME}" - name: POSTGRES_USER valueFrom: secretKeyRef: name: switchboard-db-credentials key: POSTGRES_USER - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: switchboard-db-credentials key: POSTGRES_PASSWORD - name: DATABASE_URL value: "postgres://$(POSTGRES_USER):$(POSTGRES_PASSWORD)@$(POSTGRES_HOST):$(POSTGRES_PORT)/$(POSTGRES_DB)?sslmode=disable" - name: SWITCHBOARD_ADMIN_USERNAME valueFrom: secretKeyRef: name: switchboard-admin key: username optional: true - name: SWITCHBOARD_ADMIN_PASSWORD valueFrom: secretKeyRef: name: switchboard-admin key: password optional: true - name: SWITCHBOARD_ADMIN_EMAIL valueFrom: secretKeyRef: name: switchboard-admin key: email optional: true - name: SEED_USERS valueFrom: secretKeyRef: name: switchboard-seed-users key: users optional: true - name: ENCRYPTION_KEY valueFrom: secretKeyRef: name: switchboard-encryption key: ENCRYPTION_KEY optional: true # File storage (v0.12.0+) - name: STORAGE_BACKEND value: "${STORAGE_BACKEND}" - name: STORAGE_PATH value: "/data/storage" - name: EXTRACTION_MODE value: "sidecar" - name: EXTRACTION_CONCURRENCY value: "${EXTRACTION_CONCURRENCY}" # S3 storage (optional — only used when STORAGE_BACKEND=s3) - name: S3_ENDPOINT valueFrom: secretKeyRef: name: switchboard-s3 key: S3_ENDPOINT optional: true - name: S3_BUCKET valueFrom: secretKeyRef: name: switchboard-s3 key: S3_BUCKET optional: true - name: S3_ACCESS_KEY valueFrom: secretKeyRef: name: switchboard-s3 key: S3_ACCESS_KEY optional: true - name: S3_SECRET_KEY valueFrom: secretKeyRef: name: switchboard-s3 key: S3_SECRET_KEY optional: true - name: S3_REGION valueFrom: secretKeyRef: name: switchboard-s3 key: S3_REGION optional: true - name: S3_PREFIX valueFrom: secretKeyRef: name: switchboard-s3 key: S3_PREFIX optional: true - name: S3_FORCE_PATH_STYLE value: "true" volumeMounts: - name: storage mountPath: /data/storage resources: requests: memory: "${BE_MEMORY_REQUEST}" cpu: "${BE_CPU_REQUEST}" limits: memory: "${BE_MEMORY_LIMIT}" cpu: "${BE_CPU_LIMIT}" readinessProbe: httpGet: path: ${BASE_PATH}/health port: 8080 initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 livenessProbe: httpGet: path: ${BASE_PATH}/health port: 8080 initialDelaySeconds: 10 periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 3 # Extractor sidecar (v0.12.0 Phase 2): # Uncomment when switchboard-extractor image is built. # See DESIGN-0.12.0.md — Phase 2: Extraction Pipeline. # # - name: extractor # image: ${EXTRACTOR_IMAGE}:${IMAGE_TAG} # imagePullPolicy: Always # env: # - name: STORAGE_PATH # value: "/data/storage" # - name: EXTRACTION_CONCURRENCY # value: "${EXTRACTION_CONCURRENCY}" # volumeMounts: # - name: storage # mountPath: /data/storage # resources: # requests: # memory: "256Mi" # cpu: "100m" # limits: # memory: "1Gi" # cpu: "1000m" volumes: - name: storage persistentVolumeClaim: claimName: switchboard-storage${DEPLOY_SUFFIX} --- apiVersion: v1 kind: Service metadata: name: switchboard-be${DEPLOY_SUFFIX} namespace: ${NAMESPACE} labels: app: switchboard component: backend env: ${ENVIRONMENT} spec: selector: app: switchboard component: backend env: ${ENVIRONMENT} ports: - protocol: TCP port: 8080 targetPort: 8080 name: http