continuous-integration/drone/pr Build is passing
- /api/oauth/start → JAMBOTRON_URL/oauth/authorize (client mail, PKCE S256); /api/oauth/callback: код меняется на сервере у Jambotron /api/oauth/token (Bearer SERVICE_TOKEN) → рабочий ящик сотрудника → сессия, ADMIN Jambotron — ADMIN. - Вход по паролю в веб — только встроенный администратор (когда вход через Jambotron включён). - Пароли приложений (V9 app_passwords): User panel → APP PASSWORDS, только SMTP/IMAP. - Системные ящики (V9 users.is_system): без входа в веб, открывают встроенные администраторы, не в USERS; Admin panel → MAILBOXES → кнопка SYSTEM. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
162 lines
6.1 KiB
YAML
162 lines
6.1 KiB
YAML
# Real mail on the internet (v0.2.3 75.6): receives mail for MAIL_DOMAINS and sends it straight to the recipients'
|
|
# MX servers (port 25), DKIM-signed. From the ready image, like docker-compose.image.yml.
|
|
#
|
|
# Needs a VM of its own with a public address (Jambotron 60.8: «Публичный адрес» of the VM, SMTP «да» — port 25
|
|
# is closed by default) — the ports below are published on that address:
|
|
# 25 SMTP: mail from other servers (STARTTLS) and from mail programs
|
|
# 587 submission: mail programs (STARTTLS + login) — the same SMTP listener as 25
|
|
# 465 SMTPS: mail programs, implicit TLS
|
|
# 993 IMAPS: mail programs, implicit TLS
|
|
# 80 only for Let's Encrypt (HTTP-01) — service "acme"
|
|
# 443 web client + API over HTTPS, same Let's Encrypt certificate (acme): https://mail.jambocheck.com
|
|
# The web client + API can also go through Jambotron's Caddy (plain port 8080) under ANOTHER name
|
|
# (webmail.<domain>): the name MAIL_HOSTNAME points at the VM's public address, not at Caddy.
|
|
#
|
|
# DNS before the first start (the certificate is issued over HTTP on MAIL_HOSTNAME):
|
|
# A mail.<domain> → public address of the VM
|
|
# PTR public address → mail.<domain> (hoster's panel: Reverse DNS)
|
|
# MX <domain> → 10 mail.<domain>
|
|
# TXT <domain> → "v=spf1 ip4:<public address> -all"
|
|
# TXT _dmarc.<domain> → "v=DMARC1; p=none; rua=mailto:postmaster@<domain>"
|
|
# TXT mail._domainkey.<domain> → printed in the "mail" log on the first start (DKIM key, kept in the data volume)
|
|
#
|
|
# Mailbox admin@<domain>: its password is in the "mail" log on the first start and in /app/data/initial-passwords.txt.
|
|
# Registration is closed: new mailboxes only by the admin. No catch-all.
|
|
# Defaults are ours (mail.jambocheck.com / jambocheck.com) — Jambotron deploys without a .env; another domain:
|
|
# MAIL_HOSTNAME, MAIL_DOMAINS, ACME_EMAIL in .env next to this file.
|
|
name: reactive-mail-public
|
|
|
|
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
|
|
chmod 644 /secrets/DB_PASSWORD /secrets/JWT_SECRET /secrets/SERVICE_TOKEN
|
|
volumes:
|
|
- secrets:/secrets
|
|
|
|
# Let's Encrypt for MAIL_HOSTNAME: issued on the first start, renewed 30 days before the end (checked twice a day).
|
|
# The deploy hook copies the pair to /tls (readable by the "mail" user 10001); the server reads it again within
|
|
# a minute — no restart
|
|
acme:
|
|
image: goacme/lego:v5.5.2
|
|
restart: unless-stopped
|
|
ports:
|
|
- "80:80"
|
|
entrypoint:
|
|
- sh
|
|
- -c
|
|
- |
|
|
cat > /usr/local/bin/jb-deploy <<'EOF'
|
|
#!/bin/sh
|
|
set -e
|
|
cp "$$LEGO_HOOK_CERT_PATH" /tls/cert.pem.new
|
|
cp "$$LEGO_HOOK_CERT_KEY_PATH" /tls/key.pem.new
|
|
chown 10001 /tls/cert.pem.new /tls/key.pem.new
|
|
chmod 600 /tls/key.pem.new
|
|
chmod 644 /tls/cert.pem.new
|
|
mv /tls/key.pem.new /tls/key.pem
|
|
mv /tls/cert.pem.new /tls/cert.pem
|
|
echo "certificate for $$LEGO_HOOK_CERT_DOMAINS copied to /tls"
|
|
EOF
|
|
chmod 755 /usr/local/bin/jb-deploy
|
|
while true; do
|
|
/lego run --accept-tos --email "$$ACME_EMAIL" --domains "$$MAIL_HOSTNAME" --key-type EC256 \
|
|
--http --http.address :80 --path /var/lib/lego --renew-days 30 --no-random-sleep \
|
|
--deploy-hook /usr/local/bin/jb-deploy || echo "lego failed — next try in 1 hour"
|
|
[ -s /tls/cert.pem ] && sleep 43200 || sleep 3600
|
|
done
|
|
environment:
|
|
MAIL_HOSTNAME: ${MAIL_HOSTNAME:-mail.jambocheck.com}
|
|
ACME_EMAIL: ${ACME_EMAIL:-postmaster@jambocheck.com}
|
|
LEGO_LOG_FORMAT: text
|
|
volumes:
|
|
- lego:/var/lib/lego
|
|
- tls:/tls
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "test -s /tls/cert.pem && test -s /tls/key.pem"]
|
|
interval: 15s
|
|
timeout: 5s
|
|
start_period: 10m
|
|
retries: 3
|
|
mem_limit: 128m
|
|
|
|
db:
|
|
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:
|
|
image: gitea.jambotron.com/jambotron_gang/reactive-mail-server:${MAIL_IMAGE_TAG:-latest}
|
|
pull_policy: always
|
|
restart: unless-stopped
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
acme:
|
|
condition: service_healthy # waits for the first certificate
|
|
ports:
|
|
- "25:3025"
|
|
- "587:3025"
|
|
- "465:3465"
|
|
- "993:3993"
|
|
- "443:8443" # web client + API over HTTPS: https://mail.jambocheck.com
|
|
expose:
|
|
- "8080" # plain HTTP, for a reverse proxy inside the network (not needed on the public address)
|
|
environment:
|
|
DB_HOST: db
|
|
MAILSERVER_SECRETS_DIR: /run/mail-secrets
|
|
# «Sign in with Jambotron» (OAuth code + PKCE, SERVICE_TOKEN as the client secret); empty — password login
|
|
JAMBOTRON_URL: ${JAMBOTRON_URL:-https://jambotron.com}
|
|
MAIL_DOMAINS: ${MAIL_DOMAINS:-jambocheck.com}
|
|
MAIL_HOSTNAME: ${MAIL_HOSTNAME:-mail.jambocheck.com}
|
|
MAIL_TLS_CERT: /tls/cert.pem
|
|
MAIL_TLS_KEY: /tls/key.pem
|
|
SMTPS_PORT: "3465"
|
|
IMAPS_PORT: "3993"
|
|
HTTPS_PORT: "8443"
|
|
DKIM_DOMAIN: ${MAIL_DOMAINS:-jambocheck.com}
|
|
DKIM_SELECTOR: mail
|
|
DKIM_KEYS_DIR: /app/data/dkim-keys
|
|
MAIL_CATCH_ALL: ""
|
|
MAIL_REGISTRATION: "false"
|
|
OUTBOUND_MODE: mx
|
|
SMTP_AUTH_WITHOUT_TLS: "false"
|
|
IMAP_AUTH_WITHOUT_TLS: "false"
|
|
SPF_ENABLED: "true"
|
|
DMARC_ENABLED: "true"
|
|
volumes:
|
|
- data:/app/data
|
|
- secrets:/run/mail-secrets:ro
|
|
- tls:/tls:ro
|
|
mem_limit: 512m
|
|
|
|
volumes:
|
|
secrets:
|
|
pgdata:
|
|
data:
|
|
lego:
|
|
tls:
|