name: sam-image services: image-hook: build: context: ./node-hook image: sam-image-hook:1.2.0 restart: unless-stopped user: "${IMAGE_UID:-1000}:${IMAGE_GID:-1000}" read_only: true init: true environment: PORT: "8081" IMAGE_REPOSITORY_PATH: /data/image IMAGE_REMOTE_URL: ${IMAGE_REMOTE_URL:-https://gitea.hided.net/devsam/image.git} IMAGE_REPOSITORY_FULL_NAME: ${IMAGE_REPOSITORY_FULL_NAME:-devsam/image} IMAGE_DEFAULT_BRANCH: ${IMAGE_DEFAULT_BRANCH:-master} IMAGE_ALLOWED_BRANCHES: ${IMAGE_ALLOWED_BRANCHES:-master} IMAGE_PUBLIC_BASES: ${IMAGE_PUBLIC_BASES:-https://sam.hided.net/image,https://sam-image.hided.net} IMAGE_STATE_PATH: /var/lib/image-hook/state.json IMAGE_UPLOAD_ROOT: /var/lib/image-hook/uploads IMAGE_UPLOAD_STATE_PATH: /var/lib/image-hook/upload-state.json GITEA_WEBHOOK_SECRET_FILE: /run/secrets/gitea_webhook_secret IMAGE_ADMIN_SECRET_FILE: /run/secrets/image_admin_secret IMAGE_SYNC_CLIENT_SECRET_FILES: core=/run/secrets/image_sync_core_secret,core2026=/run/secrets/image_sync_core2026_secret IMAGE_UPLOAD_CLIENT_SECRET_FILES: core=/run/secrets/image_upload_core_secret,core2026=/run/secrets/image_upload_core2026_secret MAX_UPLOAD_BYTES: "51200" MAX_CONTENT_UPLOAD_BYTES: "1048576" volumes: - type: bind source: ${IMAGE_REPOSITORY_PATH:-.} target: /data/image - ./runtime-data:/var/lib/image-hook secrets: - gitea_webhook_secret - image_admin_secret - image_sync_core_secret - image_sync_core2026_secret - image_upload_core_secret - image_upload_core2026_secret tmpfs: - /tmp:size=16m,mode=1777 cap_drop: [ALL] security_opt: - no-new-privileges:true pids_limit: 64 mem_limit: 256m cpus: 1.0 healthcheck: test: [CMD, node, -e, "fetch('http://127.0.0.1:8081/healthz').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"] interval: 10s timeout: 3s retries: 6 start_period: 10s networks: [image-internal, image-egress] image-web: build: context: ./deploy/nginx image: sam-image-web:1.2.0 restart: unless-stopped depends_on: image-hook: condition: service_healthy read_only: true environment: TRUSTED_PROXY_CIDRS: ${TRUSTED_PROXY_CIDRS:?Set TRUSTED_PROXY_CIDRS to the direct reverse-proxy source CIDR list} ports: - "${IMAGE_BIND_ADDRESS:-0.0.0.0}:${IMAGE_PORT:-8191}:8080" volumes: - type: bind source: ${IMAGE_REPOSITORY_PATH:-.} target: /srv/image read_only: true - type: bind source: ./runtime-data/uploads target: /srv/uploads read_only: true tmpfs: - /tmp:size=8m,mode=1777 cap_drop: [ALL] security_opt: - no-new-privileges:true pids_limit: 32 mem_limit: 64m cpus: 0.5 healthcheck: test: [CMD, wget, -q, -O, /dev/null, http://127.0.0.1:8080/healthz] interval: 10s timeout: 3s retries: 6 networks: [image-internal, image-edge] networks: image-internal: internal: true image-egress: image-edge: secrets: gitea_webhook_secret: file: ${GITEA_WEBHOOK_SECRET_FILE:-./secrets/gitea_webhook_secret} image_admin_secret: file: ${IMAGE_ADMIN_SECRET_FILE:-./secrets/image_admin_secret} image_sync_core_secret: file: ${IMAGE_SYNC_CORE_SECRET_FILE:-./secrets/image_sync_core_secret} image_sync_core2026_secret: file: ${IMAGE_SYNC_CORE2026_SECRET_FILE:-./secrets/image_sync_core2026_secret} image_upload_core_secret: file: ${IMAGE_UPLOAD_CORE_SECRET_FILE:-./secrets/image_upload_core_secret} image_upload_core2026_secret: file: ${IMAGE_UPLOAD_CORE2026_SECRET_FILE:-./secrets/image_upload_core2026_secret}