docker-compose.yml
Rama main · réplica de lectura del repositorio original.
# Every service refuses privilege escalation, and the services that run as an unprivileged
# user on a high port also drop every Linux capability. Caddy binds 80 and 443 as root, and
# PostgreSQL, migrate, backup, and restore run one-off root commands, so those keep theirs.
services:
caddy:
security_opt: ["no-new-privileges:true"]
image: caddy:2.10.2-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
environment:
REMENTUM_DOMAIN: ${REMENTUM_DOMAIN:-localhost}
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
depends_on:
api:
condition: service_healthy
web:
condition: service_healthy
docs:
condition: service_healthy
web:
security_opt: ["no-new-privileges:true"]
cap_drop: ["ALL"]
build:
context: .
dockerfile: apps/web/Dockerfile
args:
NEXT_PUBLIC_REMENTUM_API_URL: ${REMENTUM_PUBLIC_URL:-http://localhost}
restart: unless-stopped
environment:
REMENTUM_API_INTERNAL_URL: http://api:8787
NEXT_PUBLIC_REMENTUM_API_URL: ${REMENTUM_PUBLIC_URL:-http://localhost}
depends_on:
api:
condition: service_healthy
healthcheck:
test:
[
"CMD",
"node",
"-e",
"fetch('http://127.0.0.1:3000').then((response) => { if (!response.ok) process.exit(1) }).catch(() => process.exit(1))",
]
interval: 10s
timeout: 5s
retries: 10
docs:
security_opt: ["no-new-privileges:true"]
cap_drop: ["ALL"]
build:
context: .
dockerfile: deploy/docs/Dockerfile
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:8080/docs/"]
interval: 10s
timeout: 5s
retries: 10
migrate:
security_opt: ["no-new-privileges:true"]
build:
context: .
dockerfile: apps/api/Dockerfile
restart: "no"
env_file: .env
command: ["node", "packages/db/dist/migrate.js"]
environment:
REMENTUM_DATABASE_ADMIN_URL: postgres://postgres:${REMENTUM_POSTGRES_SUPER_PASSWORD:?set REMENTUM_POSTGRES_SUPER_PASSWORD in .env}@postgres:5432/owl
depends_on:
postgres:
condition: service_healthy
# Only migrate, backup, and restore need the PostgreSQL superuser. The shared .env carries
# it for them, so the long-running services blank it (and the secrets they never read):
# a superuser connection string inside the API would bypass row-level security for
# anyone who found a way to read that process's environment.
api:
security_opt: ["no-new-privileges:true"]
cap_drop: ["ALL"]
build:
context: .
dockerfile: apps/api/Dockerfile
restart: unless-stopped
env_file: .env
environment:
REMENTUM_DATABASE_ADMIN_URL: ""
REMENTUM_POSTGRES_SUPER_PASSWORD: ""
REMENTUM_DATABASE_URL: postgres://owl_app:${REMENTUM_POSTGRES_PASSWORD:?set REMENTUM_POSTGRES_PASSWORD in .env}@postgres:5432/owl
REMENTUM_EMBEDDINGS_URL: http://embeddings:8790
REMENTUM_BLOB_DIR: /data/blobs
REMENTUM_EXPORT_DIR: /data/exports
volumes:
- owl_data:/data
depends_on:
embeddings:
condition: service_healthy
migrate:
condition: service_completed_successfully
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:8787/healthz"]
interval: 10s
timeout: 5s
retries: 10
worker:
security_opt: ["no-new-privileges:true"]
cap_drop: ["ALL"]
build:
context: .
dockerfile: apps/worker/Dockerfile
restart: unless-stopped
env_file: .env
environment:
REMENTUM_DATABASE_ADMIN_URL: ""
REMENTUM_POSTGRES_SUPER_PASSWORD: ""
REMENTUM_COOKIE_KEYS: ""
REMENTUM_JWT_JWKS: ""
REMENTUM_RESEND_API_KEY: ""
REMENTUM_MAIL_FROM: ""
REMENTUM_TURNSTILE_SITE_KEY: ""
REMENTUM_TURNSTILE_SECRET_KEY: ""
REMENTUM_DATABASE_URL: postgres://owl_app:${REMENTUM_POSTGRES_PASSWORD:?set REMENTUM_POSTGRES_PASSWORD in .env}@postgres:5432/owl
REMENTUM_EMBEDDINGS_URL: http://embeddings:8790
REMENTUM_BLOB_DIR: /data/blobs
REMENTUM_EXPORT_DIR: /data/exports
volumes:
- owl_data:/data
depends_on:
embeddings:
condition: service_healthy
migrate:
condition: service_completed_successfully
embeddings:
security_opt: ["no-new-privileges:true"]
cap_drop: ["ALL"]
build:
context: .
dockerfile: apps/embeddings/Dockerfile
restart: unless-stopped
environment:
REMENTUM_EMBEDDING_MODEL: ${REMENTUM_EMBEDDING_MODEL:-onnx-community/granite-embedding-97m-multilingual-r2-ONNX}
# Optional overrides for models the service does not recognize; empty means unset.
REMENTUM_EMBEDDING_DTYPE: ${REMENTUM_EMBEDDING_DTYPE:-}
REMENTUM_EMBEDDING_POOLING: ${REMENTUM_EMBEDDING_POOLING:-}
REMENTUM_EMBEDDING_QUERY_PREFIX: ${REMENTUM_EMBEDDING_QUERY_PREFIX:-}
REMENTUM_EMBEDDING_PASSAGE_PREFIX: ${REMENTUM_EMBEDDING_PASSAGE_PREFIX:-}
REMENTUM_MODEL_CACHE: /models
volumes:
- model_cache:/models
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:8790/healthz"]
interval: 10s
timeout: 5s
# The first probe pulls the model, a few hundred megabytes, so probes are expected to fail
# until that finishes. The grace period covers a slow link; a cache the container cannot
# write is caught at startup instead, so this budget only has to outlast a download.
start_period: 600s
retries: 30
postgres:
security_opt: ["no-new-privileges:true"]
image: pgvector/pgvector:pg17
restart: unless-stopped
environment:
POSTGRES_DB: owl
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${REMENTUM_POSTGRES_SUPER_PASSWORD:?set REMENTUM_POSTGRES_SUPER_PASSWORD in .env}
REMENTUM_POSTGRES_PASSWORD: ${REMENTUM_POSTGRES_PASSWORD:?set REMENTUM_POSTGRES_PASSWORD in .env}
ports:
- "127.0.0.1:${REMENTUM_POSTGRES_PORT:-55432}:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./deploy/postgres/00-app-role.sh:/docker-entrypoint-initdb.d/00-app-role.sh:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d owl"]
interval: 5s
timeout: 5s
retries: 20
backup:
security_opt: ["no-new-privileges:true"]
profiles: ["backup"]
build:
context: .
dockerfile: deploy/backup/Dockerfile
env_file: .env
environment:
REMENTUM_MASTER_KEY: ""
REMENTUM_COOKIE_KEYS: ""
REMENTUM_JWT_JWKS: ""
REMENTUM_RESEND_API_KEY: ""
REMENTUM_TURNSTILE_SECRET_KEY: ""
REMENTUM_DATABASE_ADMIN_URL: postgres://postgres:${REMENTUM_POSTGRES_SUPER_PASSWORD:?set REMENTUM_POSTGRES_SUPER_PASSWORD in .env}@postgres:5432/owl
REMENTUM_BLOB_DIR: /data/blobs
REMENTUM_BACKUP_DIR: /backups
volumes:
- owl_data:/data:ro
- ${REMENTUM_BACKUP_HOST_DIR:-./backups}:/backups
depends_on:
postgres:
condition: service_healthy
restore:
security_opt: ["no-new-privileges:true"]
profiles: ["restore"]
build:
context: .
dockerfile: deploy/backup/Dockerfile
env_file: .env
entrypoint: ["/usr/local/bin/rementum-restore"]
environment:
REMENTUM_MASTER_KEY: ""
REMENTUM_COOKIE_KEYS: ""
REMENTUM_JWT_JWKS: ""
REMENTUM_RESEND_API_KEY: ""
REMENTUM_TURNSTILE_SECRET_KEY: ""
REMENTUM_DATABASE_ADMIN_URL: postgres://postgres:${REMENTUM_POSTGRES_SUPER_PASSWORD:?set REMENTUM_POSTGRES_SUPER_PASSWORD in .env}@postgres:5432/owl
REMENTUM_BLOB_DIR: /data/blobs
REMENTUM_BACKUP_AGE_IDENTITY_FILE: /run/secrets/age-identity
volumes:
- owl_data:/data
- ${REMENTUM_BACKUP_HOST_DIR:-./backups}:/backups:ro
depends_on:
postgres:
condition: service_healthy
volumes:
caddy_data:
caddy_config:
postgres_data:
owl_data:
model_cache: