Files
TOTPVault/docker-compose.yml
2026-05-18 23:35:37 +02:00

146 lines
5.7 KiB
YAML

# ─────────────────────────────────────────────────────────────────────────────
# TOTPVault — Docker Compose
# Usage:
# cp .env.example .env # then fill in real values
# docker compose up -d --build
# open http://localhost:8080
# ─────────────────────────────────────────────────────────────────────────────
services:
# ── PHP + Apache application ───────────────────────────────────────────────
app:
build:
context: .
dockerfile: Dockerfile
container_name: totpvault-app
restart: unless-stopped
ports:
- "8080:80"
environment:
# All env vars are read by config/config.docker.php inside the container.
- APP_URL=${APP_URL:-http://localhost:8080}
- DB_HOST=${DB_HOST:-db}
- DB_PORT=${DB_PORT:-3306}
- DB_NAME=${DB_NAME:-totpvault}
- DB_USER=${DB_USER:-totpvault}
- DB_PASSWORD=${DB_PASSWORD:?DB_PASSWORD is required}
- ENCRYPTION_KEY=${ENCRYPTION_KEY:?ENCRYPTION_KEY is required}
- SESSION_COOKIE_NAME=${SESSION_COOKIE_NAME:-totpvault_session}
- SESSION_LIFETIME=${SESSION_LIFETIME:-2592000}
- MAILERSEND_KEY=${MAILERSEND_KEY:-}
- MAIL_FROM_EMAIL=${MAIL_FROM_EMAIL:-noreply@localhost}
- MAIL_FROM_NAME=${MAIL_FROM_NAME:-TOTPVault}
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID:-}
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET:-}
- MICROSOFT_CLIENT_ID=${MICROSOFT_CLIENT_ID:-}
- MICROSOFT_CLIENT_SECRET=${MICROSOFT_CLIENT_SECRET:-}
- GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID:-}
- GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET:-}
- KEYCLOAK_CLIENT_ID=${KEYCLOAK_CLIENT_ID:-}
- KEYCLOAK_CLIENT_SECRET=${KEYCLOAK_CLIENT_SECRET:-}
- KEYCLOAK_BASE_URL=${KEYCLOAK_BASE_URL:-}
- KEYCLOAK_INTERNAL_BASE_URL=${KEYCLOAK_INTERNAL_BASE_URL:-}
- KEYCLOAK_REALM=${KEYCLOAK_REALM:-}
- KEYCLOAK_REDIRECT_URI=${KEYCLOAK_REDIRECT_URI:-}
- KEYCLOAK_SCOPE=${KEYCLOAK_SCOPE:-openid email profile}
volumes:
# Mount the Docker-specific config as config/config.php inside the container.
# This keeps the original config/config.php on the host untouched.
- ./config/config.docker.php:/var/www/html/config/config.php:ro
# Persist PHP sessions across container restarts.
- totpvault-sessions:/var/www/html/sessions
depends_on:
db:
condition: service_healthy
networks:
totpvault-net:
aliases:
- app
- totpvault-app
healthcheck:
test: ["CMD", "curl", "-f", "-s", "-o", "/dev/null", "http://localhost:80/"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
# ── Keycloak identity provider for local OIDC testing ─────────────────────
keycloak:
profiles:
- keycloak
image: quay.io/keycloak/keycloak:26.6.1
container_name: totpvault-keycloak
restart: unless-stopped
command: ["start-dev", "--import-realm"]
environment:
KC_BOOTSTRAP_ADMIN_USERNAME: ${KEYCLOAK_ADMIN_USERNAME:-admin}
KC_BOOTSTRAP_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD:-admin}
KC_HTTP_ENABLED: "true"
KC_HOSTNAME_STRICT: "false"
KC_HOSTNAME_URL: ${KEYCLOAK_BASE_URL:-http://localhost:8081}
ports:
- "8081:8080"
volumes:
- ./docker/keycloak/totpvault-realm.json:/opt/keycloak/data/import/totpvault-realm.json:ro
- totpvault-keycloak-data:/opt/keycloak/data
networks:
totpvault-net:
aliases:
- keycloak
- totpvault-keycloak
healthcheck:
test:
[
"CMD-SHELL",
"/bin/bash -ec \"exec 3<>/dev/tcp/127.0.0.1/8080; printf 'GET /realms/totpvault/.well-known/openid-configuration HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n' >&3; grep -q 'HTTP/1.1 200' <&3\""
]
interval: 10s
timeout: 5s
retries: 12
start_period: 60s
# ── MariaDB database ──────────────────────────────────────────────────────
db:
image: mariadb:10.11
container_name: totpvault-db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:?DB_ROOT_PASSWORD is required}
MYSQL_DATABASE: ${DB_NAME:-totpvault}
MYSQL_USER: ${DB_USER:-totpvault}
MYSQL_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD is required}
volumes:
# Persist database data across container restarts and rebuilds.
- totpvault-db-data:/var/lib/mysql
# Initialise the schema on first startup only.
# Files in /docker-entrypoint-initdb.d/ run once when the data volume is empty.
- ./docker/init-db.sql:/docker-entrypoint-initdb.d/01-schema.sql:ro
# The database port is NOT exposed to the host by default for security.
# Uncomment the following lines if you need direct access for debugging:
# ports:
# - "3306:3306"
networks:
totpvault-net:
aliases:
- db
- totpvault-db
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
volumes:
totpvault-db-data:
driver: local
totpvault-sessions:
driver: local
totpvault-keycloak-data:
driver: local
networks:
totpvault-net:
driver: bridge