# NOTE: based on https://github.com/suitenumerique/docs/pull/855/ and https://github.com/suitenumerique/docs/pull/583/ x-common-env: &common-env DJANGO_CONFIGURATION: Production DJANGO_ALLOWED_HOSTS: "*" # DJANGO_SECRET_KEY supplied via secrets DJANGO_SETTINGS_MODULE: impress.settings # DJANGO_SUPERUSER_PASSWORD supplied via secrets # Logging # Set to DEBUG level for dev only LOGGING_LEVEL_HANDLERS_CONSOLE: LOGGING_LEVEL_LOGGERS_ROOT: LOGGING_LEVEL_LOGGERS_APP: # Python PYTHONPATH: /app # Mail DJANGO_EMAIL_BRAND_NAME: DJANGO_EMAIL_HOST: DJANGO_EMAIL_LOGO_IMG: DJANGO_EMAIL_PORT: DJANGO_EMAIL_HOST_USER: # DJANGO_EMAIL_HOST_PASSWORD supplied via secret DJANGO_EMAIL_USE_SSL: DJANGO_EMAIL_USE_TLS: DJANGO_EMAIL_FROM: # Backend url IMPRESS_BASE_URL: "https://${DOMAIN}" # Media STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage AWS_S3_ENDPOINT_URL: http://minio:9000 # AWS_S3_ACCESS_KEY_ID supplied via secret (this is same MINIO_ROOT_USER) # AWS_S3_SECRET_ACCESS_KEY supplied via secret (this is same as MINIO_ROOT_PASSWORD) MEDIA_BASE_URL: https://${DOMAIN} AWS_STORAGE_BUCKET_NAME: docs-media-storage # OIDC - settings from .env, see .env.sample OIDC_OP_JWKS_ENDPOINT: OIDC_OP_AUTHORIZATION_ENDPOINT: OIDC_OP_TOKEN_ENDPOINT: OIDC_OP_USER_ENDPOINT: OIDC_RP_CLIENT_ID: # OIDC_RP_CLIENT_SECRET supplied via secrets OIDC_RP_SIGN_ALGO: OIDC_RP_SCOPES: LOGIN_REDIRECT_URL: LOGIN_REDIRECT_URL_FAILURE: LOGOUT_REDIRECT_URL: OIDC_REDIRECT_ALLOWED_HOSTS: OIDC_AUTH_REQUEST_EXTRA_PARAMS: # AI AI_FEATURE_ENABLED: "false" OPENAI_SDK_BASE_URL: https://openaiendpoint.com OPENAI_SDK_API_KEY: password AI_MODEL: llama # Collaboration COLLABORATION_API_URL: https://$DOMAIN/collaboration/api/ # Email app URL (used in email templates; matches recipe DOMAIN) DJANGO_EMAIL_URL_APP: "https://${DOMAIN}" # Conversion (file upload → Yjs via y-provider) CONVERSION_UPLOAD_ENABLED: "${CONVERSION_UPLOAD_ENABLED:-true}" CONVERSION_FILE_MAX_SIZE: CONVERSION_FILE_EXTENSIONS_ALLOWED: CONVERSION_API_ENDPOINT: CONVERSION_API_CONTENT_FIELD: CONVERSION_API_TIMEOUT: CONVERSION_API_SECURE: # Y-Provider base URL + API key (needed when CONVERSION_UPLOAD_ENABLED is true) Y_PROVIDER_API_BASE_URL: http://y-provider:4444/api/ Y_PROVIDER_API_KEY_FILE: /run/secrets/y_api_key # DocSpec — converts .docx → BlockNote JSON, then y-provider turns that into Yjs DOCSPEC_API_URL: http://docspec:4000/conversion # Database connection pool DB_PSYCOPG_POOL_ENABLED: # Media auth header (matches recipe nginx by default) MEDIA_AUTH_ORIGINAL_URL_HEADER: x-postgres-env: &postgres-env # Postgresql db container configuration POSTGRES_DB: docs POSTGRES_USER: docs POSTGRES_PASSWORD_FILE: /run/secrets/postgres_p # App database configuration DB_HOST: db DB_NAME: docs DB_USER: docs DB_PORT: 5432 # DB_PASSWORD supplied via secrets (this is same as POSTGRES_PASSWORD) x-yprovider-env: &yprovider-env COLLABORATION_LOGGING: "true" # Y_PROVIDER_API_KEY supplied via secrets COLLABORATION_API_URL: http://y-provider:4444/api/ COLLABORATION_SERVER_ORIGIN: https://${DOMAIN} # COLLABORATION_SERVER_SECRET supplied via secrets COLLABORATION_BACKEND_BASE_URL: https://${DOMAIN} COLLABORATION_WS_URL: wss://${DOMAIN}/collaboration/ws/ x-minio-env: &minio-env MINIO_ROOT_USER_FILE: /run/secrets/minio_ru MINIO_ROOT_PASSWORD_FILE: /run/secrets/minio_rp services: app: image: lasuite/impress-frontend:v5.1.0 networks: - backend deploy: labels: - "traefik.enable=false" - "coop-cloud.${STACK_NAME}.timeout=${TIMEOUT:-120}" - "coop-cloud.${STACK_NAME}.version=0.3.2+v5.1.0" user: "${DOCKER_USER:-1000}" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080"] interval: 15s timeout: 30s retries: 20 start_period: 10s backend: image: lasuite/impress-backend:v5.1.0 networks: - backend environment: <<: [*common-env, *postgres-env, *yprovider-env] AUTO_MIGRATIONS: "${AUTO_MIGRATIONS:-true}" healthcheck: test: ["CMD", "/abra-entrypoint.sh", "python", "manage.py", "check"] interval: 15s timeout: 30s retries: 20 start_period: 10s user: "${DOCKER_USER:-1000}" command: ["gunicorn", "-c", "/usr/local/etc/gunicorn/impress.py", "impress.wsgi:application"] entrypoint: > sh -c "if [ \"$$AUTO_MIGRATIONS\" = \"true\" ]; then /migrate.sh; fi && exec /abra-entrypoint.sh /usr/local/bin/entrypoint \"$$@\"" -- configs: - source: abra_entrypoint target: /abra-entrypoint.sh mode: 0555 - source: migrate target: /migrate.sh mode: 0555 secrets: - django_sk - django_sp - oidc_rpcs - collab_ss - minio_rp - minio_ru - postgres_p - y_api_key - email_pass celery: image: lasuite/impress-backend:v5.1.0 networks: - backend healthcheck: test: ["CMD", "celery", "-A", "impress.celery_app", "inspect", "ping", "--timeout", "5"] interval: 30s timeout: 10s retries: 3 start_period: 30s user: "${DOCKER_USER:-1000}" command: ["celery", "-A", "impress.celery_app", "worker", "-l", "INFO"] environment: <<: [*common-env, *postgres-env, *yprovider-env] entrypoint: ["/abra-entrypoint.sh", "/usr/local/bin/entrypoint"] configs: - source: abra_entrypoint target: /abra-entrypoint.sh mode: 0555 secrets: - django_sk - django_sp - oidc_rpcs - collab_ss - minio_rp - postgres_p - y_api_key - email_pass y-provider: image: lasuite/impress-y-provider:v5.1.0 networks: - backend healthcheck: # y-provider returns 403 on unauthenticated requests; wget exit 4 = network error (server down), anything else = server is responding test: ["CMD-SHELL", "wget -qO /dev/null http://localhost:4444/ 2>/dev/null; test $$? -ne 4"] interval: 15s timeout: 5s retries: 3 start_period: 10s environment: *yprovider-env user: "${DOCKER_USER:-1000}" entrypoint: > sh -c "export Y_PROVIDER_API_KEY=\"$$(cat /run/secrets/y_api_key)\" && exec /usr/local/bin/entrypoint \"$$@\"" -- command: ["yarn", "start"] secrets: - y_api_key docspec: image: ghcr.io/docspecio/api:3.0.1 networks: - backend healthcheck: # Use 127.0.0.1, which is required instead of localhost for this healtcheck because of elixir/busybox bindings test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:4000/health"] interval: 15s timeout: 5s retries: 3 start_period: 10s db: image: pgautoupgrade/pgautoupgrade:18-debian networks: - backend healthcheck: test: ["CMD", "pg_isready", "-q", "-U", "docs", "-d", "docs"] interval: 1s timeout: 2s retries: 300 environment: <<: *postgres-env PGDATA: /var/lib/postgresql/data/pgdata volumes: - postgres:/var/lib/postgresql/data/pgdata deploy: labels: backupbot.backup: "${ENABLE_BACKUPS:-true}" backupbot.backup.pre-hook: "/pg_backup.sh backup" backupbot.backup.volumes.postgres.path: "backup.sql" backupbot.restore.post-hook: '/pg_backup.sh restore' configs: - source: pg_backup target: /pg_backup.sh mode: 0555 secrets: - postgres_p redis: image: redis:8.2.6 healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 15s timeout: 5s retries: 3 networks: - backend minio: image: minio/minio:RELEASE.2025-05-24T17-08-30Z environment: *minio-env healthcheck: test: ["CMD", "mc", "ready", "local"] interval: 1s timeout: 20s retries: 300 networks: - backend command: minio server /data entrypoint: > sh -c "/minio-initialize.sh & exec /usr/bin/docker-entrypoint.sh \"$$@\"" -- volumes: - minio:/data deploy: labels: backupbot.backup: "${ENABLE_BACKUPS:-true}" entrypoint: /abra-entrypoint.sh configs: - source: abra_entrypoint target: /abra-entrypoint.sh mode: 0555 - source: minio_initialize target: /minio-initialize.sh mode: 0555 secrets: - minio_rp - minio_ru web: image: nginx:1.30.0 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8083"] interval: 15s timeout: 5s retries: 3 start_period: 10s configs: - source: nginx_conf target: /etc/nginx/conf.d/default.conf networks: proxy: backend: depends_on: - backend - app environment: - STACK_NAME deploy: labels: - "traefik.enable=true" - "traefik.docker.network=proxy" - "traefik.http.routers.${STACK_NAME}.tls=true" - "traefik.http.services.${STACK_NAME}.loadbalancer.server.port=8083" - "traefik.http.routers.${STACK_NAME}.rule=Host(`${DOMAIN}`${EXTRA_DOMAINS})" - "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}" - "traefik.http.routers.${STACK_NAME}.entrypoints=web-secure" networks: proxy: external: true backend: volumes: postgres: minio: configs: nginx_conf: name: ${STACK_NAME}_nginx_conf_${NGINX_CONF_VERSION} file: nginx.conf.tmpl template_driver: golang pg_backup: name: ${STACK_NAME}_pg_backup_${PG_BACKUP_VERSION} file: pg_backup.sh abra_entrypoint: name: ${STACK_NAME}_entrypoint_${ABRA_ENTRYPOINT_VERSION} file: abra-entrypoint.sh minio_initialize: name: ${STACK_NAME}_minio_initialize_${MINIO_INITIALIZE_VERSION} file: minio-initialize.sh migrate: name: ${STACK_NAME}_migrate_${MIGRATE_VERSION} file: migrate.sh secrets: django_sk: external: true name: ${STACK_NAME}_django_sk_${SECRET_DJANGO_SK_VERSION} oidc_rpcs: external: true name: ${STACK_NAME}_oidc_rpcs_${SECRET_OIDC_RPCS_VERSION} django_sp: external: true name: ${STACK_NAME}_django_sp_${SECRET_DJANGO_SP_VERSION} postgres_p: external: true name: ${STACK_NAME}_postgres_p_${SECRET_POSTGRES_P_VERSION} collab_ss: external: true name: ${STACK_NAME}_collab_ss_${SECRET_COLLAB_SS_VERSION} minio_rp: external: true name: ${STACK_NAME}_minio_rp_${SECRET_MINIO_RP_VERSION} minio_ru: external: true name: ${STACK_NAME}_minio_ru_${SECRET_MINIO_RP_VERSION} y_api_key: external: true name: ${STACK_NAME}_y_api_key_${SECRET_Y_API_KEY_VERSION} email_pass: external: true name: ${STACK_NAME}_email_pass_${SECRET_EMAIL_PASS_VERSION}