apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "tod.fullname" . }}-api labels: {{- include "tod.componentLabels" (dict "context" . "component" "api") | nindent 4 }} spec: replicas: {{ .Values.api.replicaCount }} selector: matchLabels: {{- include "tod.componentSelectorLabels" (dict "context" . "component" "api") | nindent 6 }} template: metadata: labels: {{- include "tod.componentSelectorLabels" (dict "context" . "component" "api") | nindent 8 }} spec: initContainers: # Init 1: Set up VPN route (only if WireGuard enabled) {{- if .Values.wireguard.enabled }} - name: route-setup image: "{{ .Values.api.image.repository }}:{{ .Values.api.image.tag }}" imagePullPolicy: {{ .Values.api.image.pullPolicy }} command: - sh - -c - | apt-get update -qq && apt-get install -y -qq iproute2 >/dev/null 2>&1 || true GW_IP=$(getent hosts ${WIREGUARD_GATEWAY} 2>/dev/null | awk '{print $1}') [ -z "$GW_IP" ] && GW_IP=${WIREGUARD_GATEWAY} ip route add 10.10.0.0/16 via $GW_IP 2>/dev/null || true echo "VPN route: 10.10.0.0/16 via $GW_IP" env: - name: WIREGUARD_GATEWAY valueFrom: configMapKeyRef: name: {{ include "tod.fullname" . }} key: WIREGUARD_GATEWAY securityContext: runAsUser: 0 capabilities: add: ["NET_ADMIN"] {{- end }} # Init 2: Run database migrations - name: migrations image: "{{ .Values.api.image.repository }}:{{ .Values.api.image.tag }}" imagePullPolicy: {{ .Values.api.image.pullPolicy }} command: ["python", "-m", "alembic", "upgrade", "head"] env: - name: DATABASE_URL valueFrom: configMapKeyRef: name: {{ include "tod.fullname" . }} key: DATABASE_URL - name: SYNC_DATABASE_URL valueFrom: configMapKeyRef: name: {{ include "tod.fullname" . }} key: SYNC_DATABASE_URL securityContext: runAsUser: 1001 runAsNonRoot: true containers: - name: api image: "{{ .Values.api.image.repository }}:{{ .Values.api.image.tag }}" imagePullPolicy: {{ .Values.api.image.pullPolicy }} ports: - name: http containerPort: 8000 protocol: TCP envFrom: - configMapRef: name: {{ include "tod.fullname" . }} env: - name: JWT_SECRET_KEY valueFrom: secretKeyRef: name: {{ include "tod.fullname" . }}-secrets key: JWT_SECRET_KEY - name: CREDENTIAL_ENCRYPTION_KEY valueFrom: secretKeyRef: name: {{ include "tod.fullname" . }}-secrets key: CREDENTIAL_ENCRYPTION_KEY - name: OPENBAO_TOKEN valueFrom: secretKeyRef: name: {{ include "tod.fullname" . }}-secrets key: OPENBAO_TOKEN - name: FIRST_ADMIN_EMAIL valueFrom: secretKeyRef: name: {{ include "tod.fullname" . }}-secrets key: FIRST_ADMIN_EMAIL - name: FIRST_ADMIN_PASSWORD valueFrom: secretKeyRef: name: {{ include "tod.fullname" . }}-secrets key: FIRST_ADMIN_PASSWORD - name: SMTP_USER valueFrom: secretKeyRef: name: {{ include "tod.fullname" . }}-secrets key: SMTP_USER - name: SMTP_PASSWORD valueFrom: secretKeyRef: name: {{ include "tod.fullname" . }}-secrets key: SMTP_PASSWORD volumeMounts: - name: git-store mountPath: /data/git-store - name: firmware-cache mountPath: /data/firmware-cache {{- if .Values.wireguard.enabled }} - name: wireguard-config mountPath: /data/wireguard {{- end }} livenessProbe: httpGet: path: {{ .Values.api.probes.liveness.path }} port: http initialDelaySeconds: {{ .Values.api.probes.liveness.initialDelaySeconds }} periodSeconds: {{ .Values.api.probes.liveness.periodSeconds }} failureThreshold: {{ .Values.api.probes.liveness.failureThreshold }} readinessProbe: httpGet: path: {{ .Values.api.probes.readiness.path }} port: http initialDelaySeconds: {{ .Values.api.probes.readiness.initialDelaySeconds }} periodSeconds: {{ .Values.api.probes.readiness.periodSeconds }} failureThreshold: {{ .Values.api.probes.readiness.failureThreshold }} resources: {{- toYaml .Values.api.resources | nindent 12 }} securityContext: runAsUser: 1001 runAsNonRoot: true allowPrivilegeEscalation: false readOnlyRootFilesystem: false capabilities: drop: ["ALL"] volumes: - name: git-store persistentVolumeClaim: claimName: {{ include "tod.fullname" . }}-git-store - name: firmware-cache persistentVolumeClaim: claimName: {{ include "tod.fullname" . }}-firmware-cache {{- if .Values.wireguard.enabled }} - name: wireguard-config persistentVolumeClaim: claimName: {{ include "tod.fullname" . }}-wireguard-config {{- end }}