Files
tessera-ctl/docker-compose.yml
T
schalli f574884b32
Tessera CI/CD / Lint & Type Check (push) Successful in 54s
Tessera CI/CD / Tests (push) Successful in 51s
Tessera CI/CD / Build & Publish Images (push) Successful in 25s
refactor: rename the encryption key to what it actually protects
CALENDAR_ENCRYPTION_KEY was named after the calendar module because that
module needed encryption first, in Phase 5. Every feature since has shared the
same key -- SMTP, the DKV and tender mailboxes, and as of today the LDAP bind
password -- so the name has been describing one of five users rather than the
thing itself, and each new feature inherited the confusion.

TESSERA_ENCRYPTION_KEY is the name now. The old one is still read, because
renaming outright would stop every existing installation at the next start:
their .env carries the old name, and compose was just made to fail hard on a
missing key. When only the old name is present the API logs a deprecation
warning naming both, and when both are set the new one wins -- otherwise a
half-migrated .env would encrypt with one key and decrypt with the other.

CalendarCryptoService becomes CryptoService in its own global CryptoModule.
Four modules used to import CalendarModule purely to reach the provider, which
read as a dependency on calendars where there was none; that import is gone.

Compose keeps the hard failure: without either name the stack refuses to
start. Verified in both files for all three cases -- neither name set (abort),
only the old name (starts), only the new name (starts).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 14:30:46 +02:00

94 lines
3.1 KiB
YAML

services:
web:
build:
context: .
dockerfile: apps/web/Dockerfile
ports:
- "3000:3000"
environment:
HOSTNAME: "0.0.0.0"
NEXT_PUBLIC_API_URL: "http://localhost:3001"
API_INTERNAL_URL: "http://api:3001"
JWT_SECRET: ${JWT_SECRET:-tessera-dev-jwt-secret-change-in-production}
networks:
- frontend-net
- backend-net
depends_on:
api:
condition: service_healthy
api:
build:
context: .
dockerfile: apps/api/Dockerfile
ports:
- "3001:3001"
networks:
- backend-net
- data-net
depends_on:
db:
condition: service_healthy
environment:
DATABASE_URL: ${DATABASE_URL:-postgresql://tessera:tessera_dev@db:5432/tessera}
JWT_SECRET: ${JWT_SECRET:-tessera-dev-jwt-secret-change-in-production}
TESSERA_ADMIN_USER: ${TESSERA_ADMIN_USER:-admin}
TESSERA_ADMIN_EMAIL: ${TESSERA_ADMIN_EMAIL:-admin@tessera.local}
TESSERA_ADMIN_PASSWORD: ${TESSERA_ADMIN_PASSWORD:-admin123}
TESSERA_FORCE_CHANGE: ${TESSERA_FORCE_CHANGE:-false}
TESSERA_SMTP_HOST: ${TESSERA_SMTP_HOST:-mailhog}
TESSERA_SMTP_PORT: ${TESSERA_SMTP_PORT:-1025}
TESSERA_SMTP_SECURE: ${TESSERA_SMTP_SECURE:-false}
TESSERA_SMTP_USER: ${TESSERA_SMTP_USER:-}
TESSERA_SMTP_PASSWORD: ${TESSERA_SMTP_PASSWORD:-}
TESSERA_SMTP_FROM: ${TESSERA_SMTP_FROM:-Tessera <tessera@tessera.local>}
TESSERA_APP_URL: ${TESSERA_APP_URL:-http://localhost:3000}
# No default on purpose: this key decrypts every stored credential
# (LDAP bind, calendar, SMTP, DKV and tender mailboxes). A built-in
# fallback would let a stack start and encrypt everything with a value
# that is public in this repository -- encryption that looks present and
# protects nothing. Failing to start is the honest outcome.
# Generate one with: openssl rand -hex 32
# Keep it with your backups but stored separately from the database dump;
# losing it means re-entering every stored credential by hand.
#
# CALENDAR_ENCRYPTION_KEY is the previous name and is still accepted, so
# an existing .env keeps working; the API logs a deprecation warning when
# it falls back to it.
TESSERA_ENCRYPTION_KEY: "${TESSERA_ENCRYPTION_KEY:-${CALENDAR_ENCRYPTION_KEY:?set TESSERA_ENCRYPTION_KEY in .env, generate one with openssl rand -hex 32}}"
CALENDAR_ENCRYPTION_KEY: "${CALENDAR_ENCRYPTION_KEY:-}"
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3001/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
db:
image: postgres:16-alpine
networks:
- data-net
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_USER: tessera
POSTGRES_PASSWORD: ${DB_PASSWORD:-tessera_dev}
POSTGRES_DB: tessera
healthcheck:
test: ["CMD-SHELL", "pg_isready -U tessera"]
interval: 5s
timeout: 3s
retries: 5
networks:
frontend-net:
driver: bridge
backend-net:
driver: bridge
data-net:
driver: bridge
internal: true
volumes:
pgdata: