# Test deploy on Jambotron (v0.2.3 75.3): pick this file in the deploy wizard. # Outside, only the web client + API (service "mail", port 8080) through Jambotron's Caddy — give it a domain. # SMTP (3025) stays inside the VM's docker network; nothing is sent outside (OUTBOUND_MODE=off). # Secrets are generated on the first start into the "secrets" volume — nothing to type in, nothing in git. # Mailboxes admin@ and trap@mail.test (catch-all): passwords in the "mail" log on the first start # (Jambotron: project → Services → mail → Logs) and in /app/data/initial-passwords.txt # of the "mail" container (docker exec cat /app/data/initial-passwords.txt). name: reactive-mail services: secrets-init: image: alpine:3.20 restart: "no" command: - sh - -c - | umask 077 for name in DB_PASSWORD JWT_SECRET SERVICE_TOKEN; do [ -s /secrets/$$name ] || head -c 48 /dev/urandom | base64 | tr -dc 'A-Za-z0-9' > /secrets/$$name done # postgres reads it as uid 70, the app as uid 10001 — readable inside these containers only chmod 644 /secrets/DB_PASSWORD /secrets/JWT_SECRET volumes: - secrets:/secrets db: # Debian, not -alpine: on Jambotron staging VMs (Alpine 3.24, kernel 6.18) the Alpine build of postgres # dies with "Bus error" even on --version; the Debian build works (2026-11-05) image: postgres:17 restart: unless-stopped depends_on: secrets-init: condition: service_completed_successfully environment: POSTGRES_DB: mailserver POSTGRES_USER: mail POSTGRES_PASSWORD_FILE: /run/mail-secrets/DB_PASSWORD volumes: - pgdata:/var/lib/postgresql/data - secrets:/run/mail-secrets:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U mail -d mailserver"] interval: 10s timeout: 5s retries: 10 mem_limit: 256m mail: build: context: . dockerfile: backend/Dockerfile restart: unless-stopped depends_on: db: condition: service_healthy expose: - "8080" # web client + API → domain in Jambotron - "3025" # SMTP, inside the network only - "3143" # IMAP (STARTTLS), inside the network only — open it in Jambotron as an internal TCP port environment: DB_HOST: db MAILSERVER_SECRETS_DIR: /run/mail-secrets MAIL_DOMAINS: ${MAIL_DOMAINS:-mail.test} MAIL_HOSTNAME: ${MAIL_HOSTNAME:-mail.test} DKIM_DOMAIN: ${MAIL_DOMAINS:-mail.test} # mail trap: mail to any address without its own mailbox here (also gmail.com etc.) goes into this mailbox MAIL_CATCH_ALL: ${MAIL_CATCH_ALL:-trap@mail.test} MAIL_REGISTRATION: ${MAIL_REGISTRATION:-true} # test stand: anyone can create a mailbox in MAIL_DOMAINS (nothing goes outside) OUTBOUND_MODE: "off" SMTP_AUTH_WITHOUT_TLS: "true" # SMTP is not reachable from outside the VM SPF_ENABLED: "false" DMARC_ENABLED: "false" volumes: - data:/app/data - secrets:/run/mail-secrets:ro mem_limit: 512m volumes: secrets: pgdata: data: