# services/health/wger-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: wger namespace: health spec: replicas: 1 revisionHistoryLimit: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 0 maxUnavailable: 1 selector: matchLabels: app: wger template: metadata: labels: app: wger annotations: vault.hashicorp.com/agent-inject: "true" vault.hashicorp.com/role: "health" vault.hashicorp.com/agent-inject-secret-wger-env: "kv/data/atlas/health/wger-db" vault.hashicorp.com/agent-inject-template-wger-env: | {{ with secret "kv/data/atlas/health/wger-db" }} export DJANGO_DB_HOST="{{ .Data.data.DJANGO_DB_HOST }}" export DJANGO_DB_PORT="{{ .Data.data.DJANGO_DB_PORT }}" export DJANGO_DB_DATABASE="{{ .Data.data.DJANGO_DB_DATABASE }}" export DJANGO_DB_USER="{{ .Data.data.DJANGO_DB_USER }}" export DJANGO_DB_PASSWORD="$(cat /vault/secrets/wger-db-password)" {{ end }} {{ with secret "kv/data/atlas/health/wger-secrets" }} export SECRET_KEY="$(cat /vault/secrets/wger-secret-key)" export SIGNING_KEY="$(cat /vault/secrets/wger-signing-key)" {{ end }} vault.hashicorp.com/agent-inject-secret-wger-db-password: "kv/data/atlas/health/wger-db" vault.hashicorp.com/agent-inject-template-wger-db-password: | {{- with secret "kv/data/atlas/health/wger-db" -}} {{ .Data.data.DJANGO_DB_PASSWORD }} {{- end -}} vault.hashicorp.com/agent-inject-secret-wger-secret-key: "kv/data/atlas/health/wger-secrets" vault.hashicorp.com/agent-inject-template-wger-secret-key: | {{- with secret "kv/data/atlas/health/wger-secrets" -}} {{ .Data.data.SECRET_KEY }} {{- end -}} vault.hashicorp.com/agent-inject-secret-wger-signing-key: "kv/data/atlas/health/wger-secrets" vault.hashicorp.com/agent-inject-template-wger-signing-key: | {{- with secret "kv/data/atlas/health/wger-secrets" -}} {{ .Data.data.SIGNING_KEY }} {{- end -}} spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 preference: matchExpressions: - key: hardware operator: In values: ["rpi5"] - weight: 70 preference: matchExpressions: - key: hardware operator: In values: ["rpi4"] securityContext: fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch nodeSelector: kubernetes.io/arch: arm64 node-role.kubernetes.io/worker: "true" serviceAccountName: health-vault-sync initContainers: - name: init-storage image: alpine:3.20 command: ["/bin/sh", "-c"] args: - | set -e mkdir -p /wger/static /wger/media chown -R 1000:1000 /wger securityContext: runAsUser: 0 runAsGroup: 0 volumeMounts: - name: wger-static mountPath: /wger/static - name: wger-media mountPath: /wger/media containers: - name: wger image: wger/server@sha256:710588b78af4e0aa0b4d8a8061e4563e16eae80eeaccfe7f9e0d9cbdd7f0cbc5 imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c"] args: - | set -eu . /vault/secrets/wger-env exec /home/wger/entrypoint.sh ports: - name: app containerPort: 8000 env: - name: SITE_URL value: https://health.bstein.dev - name: CSRF_TRUSTED_ORIGINS value: https://health.bstein.dev - name: X_FORWARDED_PROTO_HEADER_SET value: "true" - name: NUMBER_OF_PROXIES value: "1" - name: TIME_ZONE value: Etc/UTC - name: TZ value: Etc/UTC - name: DJANGO_DEBUG value: "False" - name: DJANGO_PERFORM_MIGRATIONS value: "True" - name: DJANGO_DB_ENGINE value: django.db.backends.postgresql - name: DJANGO_CACHE_BACKEND value: django.core.cache.backends.locmem.LocMemCache - name: DJANGO_CACHE_LOCATION value: wger-cache - name: DJANGO_CACHE_TIMEOUT value: "3600" - name: ALLOW_REGISTRATION value: "False" - name: ALLOW_GUEST_USERS value: "False" - name: ALLOW_UPLOAD_VIDEOS value: "False" - name: USE_CELERY value: "False" - name: SYNC_EXERCISES_CELERY value: "False" - name: SYNC_INGREDIENTS_CELERY value: "False" - name: SYNC_EXERCISE_IMAGES_CELERY value: "False" - name: SYNC_EXERCISE_VIDEOS_CELERY value: "False" - name: CACHE_API_EXERCISES_CELERY value: "False" - name: DOWNLOAD_INGREDIENTS_FROM value: "None" - name: ENABLE_EMAIL value: "False" volumeMounts: - name: wger-static mountPath: /home/wger/static - name: wger-media mountPath: /home/wger/media startupProbe: httpGet: path: /api/v2/version/ port: app failureThreshold: 60 periodSeconds: 10 timeoutSeconds: 3 readinessProbe: httpGet: path: /api/v2/version/ port: app initialDelaySeconds: 20 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 6 livenessProbe: httpGet: path: /api/v2/version/ port: app initialDelaySeconds: 45 periodSeconds: 20 timeoutSeconds: 3 failureThreshold: 6 resources: requests: cpu: 200m memory: 512Mi limits: cpu: "1" memory: 2Gi - name: nginx image: nginx:1.27.5-alpine@sha256:65645c7bb6a0661892a8b03b89d0743208a18dd2f3f17a54ef4b76fb8e2f2a10 imagePullPolicy: IfNotPresent command: - nginx args: - -g - daemon off; ports: - name: http containerPort: 8080 securityContext: runAsUser: 101 runAsGroup: 101 allowPrivilegeEscalation: false volumeMounts: - name: wger-nginx-config mountPath: /etc/nginx/conf.d/default.conf subPath: default.conf - name: wger-nginx-config mountPath: /etc/nginx/nginx.conf subPath: nginx.conf - name: wger-static mountPath: /wger/static - name: wger-media mountPath: /wger/media startupProbe: httpGet: path: /api/v2/version/ port: http failureThreshold: 60 periodSeconds: 10 timeoutSeconds: 3 readinessProbe: httpGet: path: /api/v2/version/ port: http initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 6 livenessProbe: httpGet: path: /api/v2/version/ port: http initialDelaySeconds: 30 periodSeconds: 20 timeoutSeconds: 3 failureThreshold: 6 resources: requests: cpu: 50m memory: 64Mi limits: cpu: 200m memory: 256Mi volumes: - name: wger-static persistentVolumeClaim: claimName: wger-static - name: wger-media persistentVolumeClaim: claimName: wger-media - name: wger-nginx-config configMap: name: wger-nginx-config defaultMode: 0444