281 lines
11 KiB
YAML
281 lines
11 KiB
YAML
# ==============================================================================
|
||||
|
|
# OpenProject — Docker Compose (stable/17)
|
|||
|
|
# With SMTP outbound-email support
|
|||
|
|
# ==============================================================================
|
|||
|
|
# Based on:
|
|||
|
|
# https://www.openproject.org/docs/installation-and-operations/installation/docker-compose/
|
|||
|
|
# https://github.com/opf/openproject-docker-compose (branch: stable/17)
|
|||
|
|
# https://www.openproject.org/docs/installation-and-operations/configuration/outbound-emails/
|
|||
|
|
# https://www.openproject.org/docs/installation-and-operations/configuration/environment/
|
|||
|
|
#
|
|||
|
|
# Usage:
|
|||
|
|
# 1. cp .env.example .env # then edit .env with your real values
|
|||
|
|
# 2. sudo mkdir -p /var/openproject/assets
|
|||
|
|
# 3. sudo chown 1000:1000 -R /var/openproject/assets
|
|||
|
|
# 4. docker compose up -d --build --pull always
|
|||
|
|
#
|
|||
|
|
# SMTP variables live in the .env file (see .env.example).
|
|||
|
|
# They are injected into every OpenProject container via the x-op-app anchor.
|
|||
|
|
# ==============================================================================
|
|||
|
|
|
|||
|
|
version: "3.7"
|
|||
|
|
|
|||
|
|
# ---------------------------------------------------------------------------
|
|||
|
|
# Networks – frontend faces the proxy; backend is DB / cache only.
|
|||
|
|
# ---------------------------------------------------------------------------
|
|||
|
|
networks:
|
|||
|
|
frontend:
|
|||
|
|
backend:
|
|||
|
|
|
|||
|
|
# ---------------------------------------------------------------------------
|
|||
|
|
# Volumes – persisted between restarts / upgrades.
|
|||
|
|
# pgdata – PostgreSQL WAL + tables
|
|||
|
|
# opdata – uploaded attachments & assets
|
|||
|
|
# ---------------------------------------------------------------------------
|
|||
|
|
volumes:
|
|||
|
|
pgdata:
|
|||
|
|
opdata:
|
|||
|
|
|
|||
|
|
# ===========================================================================
|
|||
|
|
# YAML Anchors – shared restart policy, image tag, and environment block.
|
|||
|
|
# ===========================================================================
|
|||
|
|
|
|||
|
|
x-op-restart-policy: &restart_policy
|
|||
|
|
restart: unless-stopped
|
|||
|
|
|
|||
|
|
x-op-image: &image
|
|||
|
|
image: openproject/openproject:${TAG:-17-slim}
|
|||
|
|
|
|||
|
|
# ---------------------------------------------------------------------------
|
|||
|
|
# x-op-app – merged into every OpenProject container.
|
|||
|
|
# All SMTP_* variables are pulled from the .env file so that secrets are
|
|||
|
|
# never hard-coded in this file. See .env.example for every placeholder.
|
|||
|
|
# ---------------------------------------------------------------------------
|
|||
|
|
x-op-app: &app
|
|||
|
|
<<: [*image, *restart_policy]
|
|||
|
|
environment:
|
|||
|
|
# --- Core OpenProject ------------------------------------------------
|
|||
|
|
OPENPROJECT_HTTPS: "${OPENPROJECT_HTTPS:-true}"
|
|||
|
|
OPENPROJECT_HOST__NAME: "${OPENPROJECT_HOST__NAME:-localhost:8080}"
|
|||
|
|
OPENPROJECT_RAILS__RELATIVE__URL__ROOT: "${OPENPROJECT_RAILS__RELATIVE__URL__ROOT:-}"
|
|||
|
|
OPENPROJECT_EDITION: "${OPENPROJECT_EDITION:-standard}"
|
|||
|
|
|
|||
|
|
# --- Database ---------------------------------------------------------
|
|||
|
|
DATABASE_URL: "${DATABASE_URL:-postgres://postgres:${POSTGRES_PASSWORD:-p4ssw0rd}@db/openproject?pool=20&encoding=unicode&reconnect=true}"
|
|||
|
|
|
|||
|
|
# --- Cache ------------------------------------------------------------
|
|||
|
|
OPENPROJECT_CACHE__MEMCACHE__SERVER: "cache:11211"
|
|||
|
|
OPENPROJECT_RAILS__CACHE__STORE: "memcache"
|
|||
|
|
|
|||
|
|
# --- Threads ----------------------------------------------------------
|
|||
|
|
RAILS_MIN_THREADS: "${RAILS_MIN_THREADS:-4}"
|
|||
|
|
RAILS_MAX_THREADS: "${RAILS_MAX_THREADS:-16}"
|
|||
|
|
|
|||
|
|
# --- Collaborative editing (Hocuspocus) ------------------------------
|
|||
|
|
OPENPROJECT_COLLABORATIVE__EDITING__HOCUSPOCUS__URL: "${COLLABORATIVE_SERVER_URL:-wss://${OPENPROJECT_HOST__NAME}/hocuspocus}"
|
|||
|
|
OPENPROJECT_COLLABORATIVE__EDITING__HOCUSPOCUS__SECRET: "${COLLABORATIVE_SERVER_SECRET:-OVERRIDE_ME_PLEASE}"
|
|||
|
|
|
|||
|
|
# --- Inbound email (IMAP) – disabled by default -----------------------
|
|||
|
|
IMAP_ENABLED: "${IMAP_ENABLED:-false}"
|
|||
|
|
|
|||
|
|
# ================================================================
|
|||
|
|
# SMTP – Outbound e-mail configuration
|
|||
|
|
# ================================================================
|
|||
|
|
# Every variable below maps to an OpenProject environment variable
|
|||
|
|
# that is documented at:
|
|||
|
|
# /docs/installation-and-operations/configuration/outbound-emails/
|
|||
|
|
# /docs/installation-and-operations/configuration/environment/
|
|||
|
|
#
|
|||
|
|
# Setting these via environment variables **disables** the matching
|
|||
|
|
# form in Administration → Emails and notifications (by design).
|
|||
|
|
#
|
|||
|
|
# Common SMTP_PORT values:
|
|||
|
|
# 587 – submission with STARTTLS (most providers, recommended)
|
|||
|
|
# 465 – implicit SSL/TLS
|
|||
|
|
# 25 – unencrypted (never use in production)
|
|||
|
|
#
|
|||
|
|
# Common SMTP_AUTHENTICATION values:
|
|||
|
|
# plain – most cloud providers (Gmail, Outlook, SendGrid …)
|
|||
|
|
# login – some legacy / on-premises servers
|
|||
|
|
# cram_md5
|
|||
|
|
#
|
|||
|
|
# For SendGrid specifically:
|
|||
|
|
# SMTP_USER_NAME=apikey
|
|||
|
|
# SMTP_PASSWORD=<your-sendgrid-api-key>
|
|||
|
|
# ================================================================
|
|||
|
|
EMAIL_DELIVERY_METHOD: "${EMAIL_DELIVERY_METHOD:-smtp}"
|
|||
|
|
SMTP_ADDRESS: "${SMTP_ADDRESS}"
|
|||
|
|
SMTP_PORT: "${SMTP_PORT:-587}"
|
|||
|
|
SMTP_DOMAIN: "${SMTP_DOMAIN}"
|
|||
|
|
SMTP_AUTHENTICATION: "${SMTP_AUTHENTICATION:-plain}"
|
|||
|
|
SMTP_USER_NAME: "${SMTP_USER_NAME}"
|
|||
|
|
SMTP_PASSWORD: "${SMTP_PASSWORD}"
|
|||
|
|
SMTP_ENABLE_STARTTLS_AUTO: "${SMTP_ENABLE_STARTTLS_AUTO:-true}"
|
|||
|
|
SMTP_SSL: "${SMTP_SSL:-false}"
|
|||
|
|
SMTP_TIMEOUT: "${SMTP_TIMEOUT:-5}"
|
|||
|
|
|
|||
|
|
# Envelope sender – the "From" address that appears in every mail.
|
|||
|
|
# Must be a valid address on your SMTP account unless your provider
|
|||
|
|
# allows arbitrary senders.
|
|||
|
|
OPENPROJECT_MAILER__FROM__ADDRESS: "${MAILER_FROM_ADDRESS:-openproject@example.com}"
|
|||
|
|
|
|||
|
|
volumes:
|
|||
|
|
- "${OPDATA:-opdata}:/var/openproject/assets"
|
|||
|
|
|
|||
|
|
# ===========================================================================
|
|||
|
|
# Services
|
|||
|
|
# ===========================================================================
|
|||
|
|
|
|||
|
|
services:
|
|||
|
|
# -----------------------------------------------------------------------
|
|||
|
|
# db – PostgreSQL 16
|
|||
|
|
# Stores all application data. The named volume pgdata persists the
|
|||
|
|
# data directory so it survives container re-creations.
|
|||
|
|
# -----------------------------------------------------------------------
|
|||
|
|
db:
|
|||
|
|
<<: *restart_policy
|
|||
|
|
image: postgres:16-alpine
|
|||
|
|
networks:
|
|||
|
|
- backend
|
|||
|
|
volumes:
|
|||
|
|
- pgdata:/var/lib/postgresql/data
|
|||
|
|
environment:
|
|||
|
|
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-p4ssw0rd}"
|
|||
|
|
POSTGRES_DB: openproject
|
|||
|
|
POSTGRES_USER: postgres
|
|||
|
|
healthcheck:
|
|||
|
|
test: ["CMD-SHELL", "pg_isready -U postgres -d openproject"]
|
|||
|
|
interval: 10s
|
|||
|
|
timeout: 5s
|
|||
|
|
retries: 5
|
|||
|
|
|
|||
|
|
# -----------------------------------------------------------------------
|
|||
|
|
# cache – Memcached
|
|||
|
|
# Used by Rails for fragment / page caching.
|
|||
|
|
# -----------------------------------------------------------------------
|
|||
|
|
cache:
|
|||
|
|
<<: *restart_policy
|
|||
|
|
image: memcached:alpine
|
|||
|
|
networks:
|
|||
|
|
- backend
|
|||
|
|
|
|||
|
|
# -----------------------------------------------------------------------
|
|||
|
|
# seeder – one-shot container
|
|||
|
|
# Runs database migrations and seeds the initial admin user.
|
|||
|
|
# Exits with code 0 after the first successful run; subsequent starts
|
|||
|
|
# are no-ops.
|
|||
|
|
# -----------------------------------------------------------------------
|
|||
|
|
seeder:
|
|||
|
|
<<: *app
|
|||
|
|
networks:
|
|||
|
|
- backend
|
|||
|
|
command: ["seeds"]
|
|||
|
|
depends_on:
|
|||
|
|
db:
|
|||
|
|
condition: service_healthy
|
|||
|
|
cache:
|
|||
|
|
condition: service_started
|
|||
|
|
|
|||
|
|
# -----------------------------------------------------------------------
|
|||
|
|
# web – Puma application server (serves HTTP requests)
|
|||
|
|
# -----------------------------------------------------------------------
|
|||
|
|
web:
|
|||
|
|
<<: *app
|
|||
|
|
networks:
|
|||
|
|
- frontend
|
|||
|
|
- backend
|
|||
|
|
command: ["web"]
|
|||
|
|
depends_on:
|
|||
|
|
db:
|
|||
|
|
condition: service_healthy
|
|||
|
|
cache:
|
|||
|
|
condition: service_started
|
|||
|
|
seeder:
|
|||
|
|
condition: service_completed_successfully
|
|||
|
|
healthcheck:
|
|||
|
|
test:
|
|||
|
|
- "CMD"
|
|||
|
|
- "curl"
|
|||
|
|
- "-f"
|
|||
|
|
- "http://localhost:8080${OPENPROJECT_RAILS__RELATIVE__URL__ROOT:-}/health_checks/default"
|
|||
|
|
interval: 30s
|
|||
|
|
timeout: 5s
|
|||
|
|
retries: 5
|
|||
|
|
start_period: 60s
|
|||
|
|
expose:
|
|||
|
|
- "8080"
|
|||
|
|
|
|||
|
|
# -----------------------------------------------------------------------
|
|||
|
|
# worker – Active Job background processor
|
|||
|
|
# Handles asynchronous tasks such as sending notification mails,
|
|||
|
|
# exporting, repository indexing, etc.
|
|||
|
|
#
|
|||
|
|
# DNS block below resolves the SMTP issue documented in OP#44515:
|
|||
|
|
# "SMTP setup fails: Network is unreachable."
|
|||
|
|
# If your corporate DNS is sufficient, replace 8.8.8.8 with your
|
|||
|
|
# internal resolver.
|
|||
|
|
# -----------------------------------------------------------------------
|
|||
|
|
worker:
|
|||
|
|
<<: *app
|
|||
|
|
networks:
|
|||
|
|
- frontend # needs outbound access for SMTP
|
|||
|
|
- backend
|
|||
|
|
command: ["worker"]
|
|||
|
|
depends_on:
|
|||
|
|
db:
|
|||
|
|
condition: service_healthy
|
|||
|
|
cache:
|
|||
|
|
condition: service_started
|
|||
|
|
seeder:
|
|||
|
|
condition: service_completed_successfully
|
|||
|
|
# Explicit DNS – prevents "Network is unreachable" when the container
|
|||
|
|
# tries to connect to an external SMTP server. See OP#44515.
|
|||
|
|
dns:
|
|||
|
|
- "8.8.8.8"
|
|||
|
|
|
|||
|
|
# -----------------------------------------------------------------------
|
|||
|
|
# proxy – Caddy reverse proxy
|
|||
|
|
# Terminates TLS (if a certificate is available) and forwards to web.
|
|||
|
|
# Exposes the single public port defined by $PORT (default 8080).
|
|||
|
|
#
|
|||
|
|
# NOTE: In production, it is strongly recommended to place OpenProject
|
|||
|
|
# behind your own TLS-terminating reverse proxy (Nginx, Traefik, …)
|
|||
|
|
# and configure Caddy's trusted_proxies accordingly.
|
|||
|
|
# -----------------------------------------------------------------------
|
|||
|
|
proxy:
|
|||
|
|
<<: *restart_policy
|
|||
|
|
image: openproject/openproject:${TAG:-17-slim}
|
|||
|
|
networks:
|
|||
|
|
- frontend
|
|||
|
|
ports:
|
|||
|
|
- "${PORT:-8080}:80"
|
|||
|
|
volumes:
|
|||
|
|
- "${OPDATA:-opdata}:/var/openproject/assets"
|
|||
|
|
command: ["proxy"]
|
|||
|
|
depends_on:
|
|||
|
|
web:
|
|||
|
|
condition: service_healthy
|
|||
|
|
environment:
|
|||
|
|
OPENPROJECT_HTTPS: "${OPENPROJECT_HTTPS:-true}"
|
|||
|
|
OPENPROJECT_HOST__NAME: "${OPENPROJECT_HOST__NAME:-localhost:8080}"
|
|||
|
|
OPENPROJECT_RAILS__RELATIVE__URL__ROOT: "${OPENPROJECT_RAILS__RELATIVE__URL__ROOT:-}"
|
|||
|
|
|
|||
|
|
# -----------------------------------------------------------------------
|
|||
|
|
# hocuspocus – WebSocket collaboration server
|
|||
|
|
# Enables real-time co-editing of documents.
|
|||
|
|
# -----------------------------------------------------------------------
|
|||
|
|
hocuspocus:
|
|||
|
|
<<: *restart_policy
|
|||
|
|
image: openproject/openproject:${TAG:-17-slim}
|
|||
|
|
networks:
|
|||
|
|
- frontend
|
|||
|
|
- backend
|
|||
|
|
command: ["hocuspocus"]
|
|||
|
|
depends_on:
|
|||
|
|
web:
|
|||
|
|
condition: service_healthy
|
|||
|
|
environment:
|
|||
|
|
OPENPROJECT_COLLABORATIVE__EDITING__HOCUSPOCUS__SECRET: "${COLLABORATIVE_SERVER_SECRET:-OVERRIDE_ME_PLEASE}"
|
|||
|
|
expose:
|
|||
|
|
- "3000"
|