# services/finance/actual-budget-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: actual-budget
  namespace: finance
  labels:
    app: actual-budget
spec:
  replicas: 1
  selector:
    matchLabels:
      app: actual-budget
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: actual-budget
      annotations:
        vault.hashicorp.com/agent-inject: "true"
        vault.hashicorp.com/agent-pre-populate-only: "true"
        vault.hashicorp.com/agent-init-first: "true"
        vault.hashicorp.com/role: "finance"
        vault.hashicorp.com/agent-inject-secret-actual-env.sh: "kv/data/atlas/finance/actual-oidc"
        vault.hashicorp.com/agent-inject-template-actual-env.sh: |
          {{ with secret "kv/data/atlas/finance/actual-oidc" }}
          export ACTUAL_OPENID_CLIENT_ID="{{ .Data.data.ACTUAL_OPENID_CLIENT_ID }}"
          export ACTUAL_OPENID_CLIENT_SECRET="{{ .Data.data.ACTUAL_OPENID_CLIENT_SECRET }}"
          {{ end }}
        actual.bstein.dev/bootstrap-rev: "2"
    spec:
      serviceAccountName: finance-vault
      nodeSelector:
        kubernetes.io/arch: arm64
        node-role.kubernetes.io/worker: "true"
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              preference:
                matchExpressions:
                  - key: hardware
                    operator: In
                    values: ["rpi5"]
            - weight: 70
              preference:
                matchExpressions:
                  - key: hardware
                    operator: In
                    values: ["rpi4"]
      securityContext:
        runAsUser: 1000
        runAsGroup: 1000
        fsGroup: 1000
        fsGroupChangePolicy: OnRootMismatch
      initContainers:
        - name: init-data-permissions
          image: docker.io/alpine:3.20
          command: ["/bin/sh", "-c"]
          args:
            - |
              set -e
              mkdir -p /data /data/server-files /data/user-files
              chown -R 1000:1000 /data
          securityContext:
            runAsUser: 0
            runAsGroup: 0
          volumeMounts:
            - name: actual-data
              mountPath: /data
        - name: init-openid
          image: actualbudget/actual-server:26.1.0-alpine@sha256:34aae5813fdfee12af2a50c4d0667df68029f1d61b90f45f282473273eb70d0d
          command: ["/bin/sh", "-c"]
          args:
            - |
              set -eu
              . /vault/secrets/actual-env.sh
              node /app/src/scripts/run-migrations.js
              node /scripts/actual_openid_bootstrap.mjs
          env:
            - name: ACTUAL_DATA_DIR
              value: /data
            - name: ACTUAL_LOGIN_METHOD
              value: openid
            - name: ACTUAL_ALLOWED_LOGIN_METHODS
              value: openid
            - name: ACTUAL_MULTIUSER
              value: "true"
            - name: ACTUAL_USER_CREATION_MODE
              value: login
            - name: ACTUAL_OPENID_DISCOVERY_URL
              value: https://sso.bstein.dev/realms/atlas
            - name: ACTUAL_OPENID_AUTHORIZATION_ENDPOINT
              value: https://sso.bstein.dev/realms/atlas/protocol/openid-connect/auth
            - name: ACTUAL_OPENID_TOKEN_ENDPOINT
              value: https://sso.bstein.dev/realms/atlas/protocol/openid-connect/token
            - name: ACTUAL_OPENID_USERINFO_ENDPOINT
              value: https://sso.bstein.dev/realms/atlas/protocol/openid-connect/userinfo
            - name: ACTUAL_OPENID_PROVIDER_NAME
              value: Atlas SSO
            - name: ACTUAL_OPENID_SERVER_HOSTNAME
              value: https://budget.bstein.dev
          volumeMounts:
            - name: actual-data
              mountPath: /data
            - name: actual-openid-bootstrap-script
              mountPath: /scripts
              readOnly: true
      containers:
        - name: actual-budget
          image: actualbudget/actual-server:26.1.0-alpine@sha256:34aae5813fdfee12af2a50c4d0667df68029f1d61b90f45f282473273eb70d0d
          command: ["/bin/sh", "-c"]
          args:
            - |
              . /vault/secrets/actual-env.sh
              exec node app
          ports:
            - name: http
              containerPort: 5006
          env:
            - name: ACTUAL_DATA_DIR
              value: /data
            - name: ACTUAL_LOGIN_METHOD
              value: openid
            - name: ACTUAL_ALLOWED_LOGIN_METHODS
              value: openid
            - name: ACTUAL_MULTIUSER
              value: "true"
            - name: ACTUAL_USER_CREATION_MODE
              value: login
            - name: ACTUAL_OPENID_DISCOVERY_URL
              value: https://sso.bstein.dev/realms/atlas
            - name: ACTUAL_OPENID_AUTHORIZATION_ENDPOINT
              value: https://sso.bstein.dev/realms/atlas/protocol/openid-connect/auth
            - name: ACTUAL_OPENID_TOKEN_ENDPOINT
              value: https://sso.bstein.dev/realms/atlas/protocol/openid-connect/token
            - name: ACTUAL_OPENID_USERINFO_ENDPOINT
              value: https://sso.bstein.dev/realms/atlas/protocol/openid-connect/userinfo
            - name: ACTUAL_OPENID_PROVIDER_NAME
              value: Atlas SSO
            - name: ACTUAL_OPENID_SERVER_HOSTNAME
              value: https://budget.bstein.dev
          volumeMounts:
            - name: actual-data
              mountPath: /data
          readinessProbe:
            httpGet:
              path: /health
              port: http
            initialDelaySeconds: 10
            periodSeconds: 10
            timeoutSeconds: 3
            failureThreshold: 6
          livenessProbe:
            httpGet:
              path: /health
              port: http
            initialDelaySeconds: 30
            periodSeconds: 20
            timeoutSeconds: 3
            failureThreshold: 6
          resources:
            requests:
              cpu: 200m
              memory: 512Mi
            limits:
              cpu: "1"
              memory: 1Gi
      volumes:
        - name: actual-data
          persistentVolumeClaim:
            claimName: actual-budget-data-encrypted
        - name: actual-openid-bootstrap-script
          configMap:
            name: actual-openid-bootstrap-script
            defaultMode: 0555
