v_11
This commit is contained in:
@@ -0,0 +1,302 @@
|
||||
# ==============================================================================
|
||||
# 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}"
|
||||
|
||||
# Allow hocuspocus to reach the web container by its service name
|
||||
OPENPROJECT_ADDITIONAL__HOST__NAMES: "${OPENPROJECT_ADDITIONAL__HOST__NAMES:-web}"
|
||||
|
||||
# --- 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
|
||||
# ================================================================
|
||||
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}"
|
||||
|
||||
OPENPROJECT_MAILER__FROM__ADDRESS: "${MAILER_FROM_ADDRESS:-openproject@example.com}"
|
||||
|
||||
volumes:
|
||||
- "${OPDATA:-opdata}:/var/openproject/assets"
|
||||
|
||||
# ===========================================================================
|
||||
# Services
|
||||
# ===========================================================================
|
||||
|
||||
services:
|
||||
# -----------------------------------------------------------------------
|
||||
# db – PostgreSQL 16
|
||||
# -----------------------------------------------------------------------
|
||||
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
|
||||
# -----------------------------------------------------------------------
|
||||
cache:
|
||||
<<: *restart_policy
|
||||
image: memcached:alpine
|
||||
networks:
|
||||
- backend
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# seeder – one-shot container
|
||||
#
|
||||
# FIX: Must NOT inherit the restart policy from x-op-app. The seeder is a
|
||||
# one-shot job that exits with code 0 on success. If restart: unless-stopped
|
||||
# is in effect Docker will keep restarting it and it will appear permanently
|
||||
# "waiting" to dependent services that expect service_completed_successfully.
|
||||
#
|
||||
# We use the *image anchor only (no *restart_policy) and set
|
||||
# restart: "no" explicitly.
|
||||
# -----------------------------------------------------------------------
|
||||
seeder:
|
||||
<<: *image
|
||||
restart: "no"
|
||||
environment:
|
||||
# Minimal env required for seeder (DB + cache)
|
||||
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_URL: "${DATABASE_URL:-postgres://postgres:${POSTGRES_PASSWORD:-p4ssw0rd}@db/openproject?pool=20&encoding=unicode&reconnect=true}"
|
||||
OPENPROJECT_CACHE__MEMCACHE__SERVER: "cache:11211"
|
||||
OPENPROJECT_RAILS__CACHE__STORE: "memcache"
|
||||
RAILS_MIN_THREADS: "${RAILS_MIN_THREADS:-4}"
|
||||
RAILS_MAX_THREADS: "${RAILS_MAX_THREADS:-16}"
|
||||
volumes:
|
||||
- "${OPDATA:-opdata}:/var/openproject/assets"
|
||||
networks:
|
||||
- backend
|
||||
command: ["./docker/prod/seeder"]
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
cache:
|
||||
condition: service_started
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# web – Puma application server
|
||||
#
|
||||
# FIX: healthcheck timings tightened to match official stable/17 repo
|
||||
# (interval 10s / timeout 3s / retries 3 / start_period 30s).
|
||||
# The previous values (30s/5s/5/60s) caused downstream containers that
|
||||
# depend on service_healthy to wait far too long, making them appear stuck.
|
||||
# -----------------------------------------------------------------------
|
||||
web:
|
||||
<<: *app
|
||||
networks:
|
||||
- frontend
|
||||
- backend
|
||||
command: ["./docker/prod/web"]
|
||||
hostname: "${OPENPROJECT_HOST__NAME:-localhost:8080}"
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
cache:
|
||||
condition: service_started
|
||||
seeder:
|
||||
condition: service_completed_successfully
|
||||
labels:
|
||||
- autoheal=true
|
||||
healthcheck:
|
||||
test:
|
||||
- "CMD"
|
||||
- "curl"
|
||||
- "-f"
|
||||
- "http://localhost:8080${OPENPROJECT_RAILS__RELATIVE__URL__ROOT:-}/health_checks/default"
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
expose:
|
||||
- "8080"
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# autoheal – automatically restarts unhealthy containers
|
||||
# FIX: Added from official stable/17 compose. Without autoheal, an
|
||||
# unhealthy web container (e.g. stuck in a loop) is never restarted even
|
||||
# though Docker marks it unhealthy, which can block the seeder indirectly.
|
||||
# -----------------------------------------------------------------------
|
||||
autoheal:
|
||||
image: willfarrell/autoheal:1.2.0
|
||||
volumes:
|
||||
- "/var/run/docker.sock:/var/run/docker.sock"
|
||||
environment:
|
||||
AUTOHEAL_CONTAINER_LABEL: autoheal
|
||||
AUTOHEAL_START_PERIOD: 600
|
||||
AUTOHEAL_INTERVAL: 30
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# worker – Active Job background processor
|
||||
# -----------------------------------------------------------------------
|
||||
worker:
|
||||
<<: *app
|
||||
networks:
|
||||
- frontend # needs outbound access for SMTP
|
||||
- backend
|
||||
command: ["./docker/prod/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"
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# cron – periodic background tasks (e.g. sending digest emails)
|
||||
# FIX: Added from official stable/17 compose. Missing cron can prevent
|
||||
# certain background jobs from running, which can mask seeder-related
|
||||
# issues or cause incomplete initialisation.
|
||||
# -----------------------------------------------------------------------
|
||||
cron:
|
||||
<<: *app
|
||||
networks:
|
||||
- backend
|
||||
command: ["./docker/prod/cron"]
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
cache:
|
||||
condition: service_started
|
||||
seeder:
|
||||
condition: service_completed_successfully
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# proxy – Caddy reverse proxy
|
||||
# -----------------------------------------------------------------------
|
||||
proxy:
|
||||
<<: *restart_policy
|
||||
image: openproject/openproject:${TAG:-17-slim}
|
||||
networks:
|
||||
- frontend
|
||||
ports:
|
||||
- "${PORT:-8080}:80"
|
||||
volumes:
|
||||
- "${OPDATA:-opdata}:/var/openproject/assets"
|
||||
command: ["./docker/prod/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
|
||||
# -----------------------------------------------------------------------
|
||||
hocuspocus:
|
||||
<<: *restart_policy
|
||||
image: openproject/openproject:${TAG:-17-slim}
|
||||
networks:
|
||||
- frontend
|
||||
- backend
|
||||
command: ["./docker/prod/hocuspocus"]
|
||||
depends_on:
|
||||
web:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
OPENPROJECT_COLLABORATIVE__EDITING__HOCUSPOCUS__SECRET: "${COLLABORATIVE_SERVER_SECRET:-OVERRIDE_ME_PLEASE}"
|
||||
expose:
|
||||
- "3000"
|
||||
@@ -0,0 +1,280 @@
|
||||
# ==============================================================================
|
||||
# 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"
|
||||
@@ -0,0 +1,149 @@
|
||||
# ==============================================================================
|
||||
# .env.example – OpenProject Docker Compose environment template
|
||||
# ==============================================================================
|
||||
# 1. cp .env.example .env
|
||||
# 2. Edit .env with real values (never commit .env to version control)
|
||||
# 3. docker compose up -d --build --pull always
|
||||
# ==============================================================================
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Core – OpenProject behaviour
|
||||
# ---------------------------------------------------------------------------
|
||||
# Docker image tag. Use XX-slim for the compose setup (recommended).
|
||||
TAG=17-slim
|
||||
|
||||
# Protocol flag. Set to "false" for first-run / local dev without TLS.
|
||||
# In production set to "true" and terminate TLS at your reverse proxy.
|
||||
OPENPROJECT_HTTPS=true
|
||||
|
||||
# Public hostname + optional port that appears in every generated URL and
|
||||
# e-mail link. Must match what end-users type in the browser.
|
||||
OPENPROJECT_HOST__NAME=project.martinhal.tech
|
||||
|
||||
# If OpenProject is mounted at a sub-path (e.g. /op), set it here.
|
||||
# Leave empty for root mount.
|
||||
OPENPROJECT_RAILS__RELATIVE__URL__ROOT=
|
||||
|
||||
# Edition: "standard" (community) or "bim"
|
||||
OPENPROJECT_EDITION=standard
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Database – PostgreSQL
|
||||
# ---------------------------------------------------------------------------
|
||||
# Password for the postgres superuser created by the db container.
|
||||
# Must match the :password segment in DATABASE_URL below.
|
||||
POSTGRES_PASSWORD=Chu929qw4Nf67r
|
||||
|
||||
# Full connection string. Edit only if you point at an external database.
|
||||
DATABASE_URL=postgres://postgres:Chu929qw4Nf67r@db/openproject?pool=20&encoding=unicode&reconnect=true
|
||||
|
||||
# Where Docker stores the PostgreSQL data volume.
|
||||
# Use a named volume (default) or an absolute host path.
|
||||
PGDATA=pgdata
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Attachments / assets volume
|
||||
# ---------------------------------------------------------------------------
|
||||
# Use a named volume (default) or an absolute host path, e.g.
|
||||
# OPDATA=/var/openproject/assets
|
||||
# If using an absolute path, run:
|
||||
# sudo mkdir -p /var/openproject/assets
|
||||
# sudo chown 1000:1000 -R /var/openproject/assets
|
||||
OPDATA=opdata
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Networking
|
||||
# ---------------------------------------------------------------------------
|
||||
# Port exposed by the Caddy proxy to the host.
|
||||
# Bind to 0.0.0.0 (public) or 127.0.0.1 (localhost-only).
|
||||
PORT=8080
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Threads
|
||||
# ---------------------------------------------------------------------------
|
||||
RAILS_MIN_THREADS=4
|
||||
RAILS_MAX_THREADS=16
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Collaborative editing – Hocuspocus
|
||||
# ---------------------------------------------------------------------------
|
||||
# URL where the browser connects for real-time collaboration.
|
||||
# Leave empty to use the auto-generated value: wss://<OPENPROJECT_HOST__NAME>/hocuspocus
|
||||
COLLABORATIVE_SERVER_URL=
|
||||
|
||||
# ⚠️ CHANGE THIS in production – it protects the WebSocket endpoint.
|
||||
COLLABORATIVE_SERVER_SECRET=replace_with_a_long_random_string
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Inbound email (IMAP) – optional
|
||||
# ---------------------------------------------------------------------------
|
||||
IMAP_ENABLED=false
|
||||
|
||||
# ===========================================================================
|
||||
# SMTP – Outbound e-mail ← fill these in to enable notification mails
|
||||
# ===========================================================================
|
||||
# Docs:
|
||||
# /docs/installation-and-operations/configuration/outbound-emails/
|
||||
# /docs/installation-and-operations/configuration/environment/
|
||||
#
|
||||
# These variables are forwarded to *every* OpenProject container that may
|
||||
# need to send mail (web, worker). Setting them here disables the manual
|
||||
# SMTP form inside Administration → Emails and notifications.
|
||||
# ===========================================================================
|
||||
|
||||
# Delivery method – keep as "smtp".
|
||||
EMAIL_DELIVERY_METHOD=smtp
|
||||
|
||||
# Hostname of your SMTP relay.
|
||||
# Examples:
|
||||
# Gmail → smtp.gmail.com
|
||||
# Outlook/O365 → smtp-mail.outlook.com (or smtp.office365.com)
|
||||
# SendGrid → smtp.sendgrid.net
|
||||
# Mailgun → smtp.mailgun.org
|
||||
# Custom/on-prem → smtp.yourdomain.com
|
||||
SMTP_ADDRESS=smtp.purelymail.com
|
||||
|
||||
# Port – 587 (STARTTLS, recommended) | 465 (implicit SSL) | 25 (plain, avoid)
|
||||
SMTP_PORT=587
|
||||
|
||||
# HELO / EHLO domain sent to the SMTP server.
|
||||
# Usually the public domain of your OpenProject instance.
|
||||
SMTP_DOMAIN=smtp.purelymail.com
|
||||
|
||||
# Authentication method.
|
||||
# plain – most cloud providers (Gmail, O365, SendGrid, Mailgun …)
|
||||
# login – some on-premises / legacy servers
|
||||
# cram_md5 – rarely used
|
||||
SMTP_AUTHENTICATION=plain
|
||||
|
||||
# SMTP user name.
|
||||
# Gmail → your full Gmail address
|
||||
# SendGrid → apikey (literal string)
|
||||
# Mailgun → postmaster@your-sandbox.mailgun.org
|
||||
# On-premises → usually an e-mail address
|
||||
SMTP_USER_NAME=projects@martinhakl.tech
|
||||
|
||||
# SMTP password / API key.
|
||||
# ⚠️ Never commit this file after editing – use .gitignore on .env.
|
||||
# Gmail → App Password (not your Google password)
|
||||
# SendGrid → API key starting with SG.xxxxx
|
||||
# Mailgun → API key from Mailgun dashboard
|
||||
SMTP_PASSWORD=Chu929qw4Nf67r
|
||||
|
||||
# STARTTLS – upgrade a plain connection to encrypted mid-session.
|
||||
# Set to "true" when SMTP_PORT=587 (the common case).
|
||||
# Set to "false" when SMTP_PORT=465 (implicit SSL) or 25.
|
||||
SMTP_ENABLE_STARTTLS_AUTO=true
|
||||
|
||||
# Implicit SSL – set to "true" only when SMTP_PORT=465.
|
||||
SMTP_SSL=false
|
||||
|
||||
# Connection timeout in seconds. Increase if your SMTP relay is slow.
|
||||
SMTP_TIMEOUT=5
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Envelope sender ("From" address in outgoing mails)
|
||||
# ---------------------------------------------------------------------------
|
||||
# Must be a valid address on the SMTP account, unless your provider
|
||||
# allows arbitrary sender addresses.
|
||||
MAILER_FROM_ADDRESS=projects@martinhakl.tech
|
||||
Reference in New Issue
Block a user