name: ita-ito-horaires x-restart: &restart restart: unless-stopped # No privilege escalation inside the containers (setuid binaries are ignored). x-hardening: &hardening security_opt: - no-new-privileges:true services: db: image: postgres:16-alpine <<: [*restart, *hardening] environment: POSTGRES_DB: ${POSTGRES_DB:-horaires} POSTGRES_USER: ${POSTGRES_USER:-horaires} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env} volumes: - pgdata:/var/lib/postgresql/data ports: - "${DB_BIND:-127.0.0.1}:${DB_PORT:-55433}:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] interval: 5s timeout: 5s retries: 20 app: build: context: . target: runner image: ita-ito-horaires:${APP_VERSION:-dev} <<: [*restart, *hardening] cap_drop: [ALL] depends_on: db: condition: service_healthy environment: # Inside the compose network the database is reachable by service name, # whatever DATABASE_URL says for host-side tooling. DATABASE_URL: postgresql://${POSTGRES_USER:-horaires}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB:-horaires}?schema=public TZ: ${TZ:-Europe/Zurich} AUTH_URL: ${AUTH_URL:?Set AUTH_URL in .env} AUTH_SECRET: ${AUTH_SECRET:?Set AUTH_SECRET in .env} AUTH_AUTHENTIK_ID: ${AUTH_AUTHENTIK_ID:-} AUTH_AUTHENTIK_SECRET: ${AUTH_AUTHENTIK_SECRET:-} AUTH_AUTHENTIK_ISSUER: ${AUTH_AUTHENTIK_ISSUER:-} AUTHENTIK_DISPLAY_NAME: ${AUTHENTIK_DISPLAY_NAME:-Loxi} AUTHENTIK_ADMIN_GROUP: ${AUTHENTIK_ADMIN_GROUP:-horaires-admins} DEVICE_IMAGE_FORMAT: ${DEVICE_IMAGE_FORMAT:-bmp} DEVICE_ALLOW_HTTP: ${DEVICE_ALLOW_HTTP:-false} TRANSLATION_API_URL: ${TRANSLATION_API_URL:-} TRANSLATION_API_KEY: ${TRANSLATION_API_KEY:-} TRANSLATION_API_FLAVOR: ${TRANSLATION_API_FLAVOR:-loxi} TRANSLATION_MODEL_NAME: ${TRANSLATION_MODEL_NAME:-haiku} TRANSLATION_TIMEOUT_MS: ${TRANSLATION_TIMEOUT_MS:-30000} HOLIDAYS_API_URL: ${HOLIDAYS_API_URL:-https://openholidaysapi.org} ports: - "${APP_BIND:-127.0.0.1}:${APP_PORT:-3010}:3010" volumes: pgdata: