Files
LambdaMail/.env.example
T
Lucas RayanandClaude Opus 5 3deb328bbf #19: repair the compose stack and wire Rspamd to Redis
"docker compose up" could not work, which means the F0 acceptance
criterion was not being met:

  - ghcr.io/rspamd/rspamd:3.9 returns "denied" and clamav/clamav:1.3 does
    not exist. Both were verified against the registries; the working
    references are rspamd/rspamd:3.9 and clamav/clamav:1.4.

  - Rspamd received RSPAMD_REDIS_SERVERS and RSPAMD_REDIS_PASSWORD as
    environment variables it never reads. Confirmed in the container that
    it does not expand ${VAR} in UCL: the password reached Redis as that
    literal string. Greylisting and ratelimit keep their state in Redis,
    so both were silently doing nothing while appearing configured. The
    credential is now rendered at startup into override.d, a tmpfs, so it
    touches neither the image nor a volume.

  - The ratelimit module ships enabled with no rates defined, which
    accepts everything. ratelimit.conf defines the per-IP, per-user and
    per-recipient buckets of section 5.2.

Verified by bringing redis and rspamd up: the real password resolves, the
rates load, and a probe message returns "Action: greylist" with the state
written to Redis.

Services also gained an image: alongside build:, so the deploy host pulls
instead of compiling while "docker compose build" still works locally.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 07:57:39 -03:00

82 lines
3.1 KiB
Bash

# --- Container images ---
# Published to GHCR by .github/workflows/release.yml, multi-architecture
# (linux/amd64 and linux/arm64). The deploy host pulls these instead of
# compiling: `docker compose pull && docker compose up -d`. Running
# `docker compose build` locally still overrides them with a local build.
# Pin IMAGE_TAG to a released version (e.g. 1.2.3) or a sha- tag to roll back.
IMAGE_NAMESPACE=ghcr.io/lucasrguerra/lambdamail
IMAGE_TAG=latest
# --- Postgres ---
POSTGRES_DB=lambdamail
POSTGRES_USER=lambdamail
POSTGRES_PASSWORD=change-me-in-local-dev
# --- Redis ---
REDIS_PASSWORD=change-me-in-local-dev
# --- Shared secrets (local dev values — never reuse in production) ---
JWT_SECRET=local-dev-jwt-secret-change-me
# Encrypts DKIM private keys and provider tokens at rest. Losing it makes every
# stored secret unrecoverable — back it up separately from the database.
LAMBDAMAIL_MASTER_KEY=local-dev-master-key-32-bytes-min
# --- Host identity ---
PRIMARY_MAIL_HOST=mail.localhost
MAIL_DOMAIN=localhost
PUBLIC_IPV4=127.0.0.1
PUBLIC_IPV6=
# --- DNS automation (Cloudflare) ---
# The token needs Zone.DNS:Edit plus Zone.Zone:Read on the zone. Leave it empty
# to disable reconciliation; the service then logs that DNS sync is off.
CLOUDFLARE_API_TOKEN=
DNS_SYNC_INTERVAL_SECONDS=21600
# --- TLS ---
# traefik: read the certificate Traefik manages (default, DANE not possible).
# acme: obtain the certificate ourselves via DNS-01. Required for DANE,
# because only this mode can reuse a pre-generated key.
TLS_MODE=traefik
# Used only when TLS_MODE=acme. Leave ACME_DIRECTORY_URL empty for Let's
# Encrypt production; point it at the staging directory while testing, since
# production rate limits can lock a domain out for a week.
ACME_EMAIL=
ACME_DIRECTORY_URL=
COOLIFY_PROXY_DIR=./local/acme
TRAEFIK_ACME_FILENAME=acme.json
CERT_POLL_INTERVAL_SECONDS=60
# Static certificate files, used when no ACME store is available (local dev).
PROTOCOLS_CERT_PATH=/etc/lambdamail/certs/cert.pem
PROTOCOLS_KEY_PATH=/etc/lambdamail/certs/key.pem
PROTOCOLS_SPOOL_DIR=/var/lambdamail/spool
# --- Transport security policy ---
# Start at "testing": senders honour the policy but do not hard-fail on it.
# Promote to "enforce" only once TLS-RPT reports come back clean.
MTA_STS_MODE=testing
OUTBOUND_MTA_STS_ENABLED=true
# DANE stays off unless TLS_MODE=acme. Under Traefik-managed certificates the
# key changes at every renewal and the published TLSA record stops matching,
# which permanently rejects mail at every validating MTA.
OUTBOUND_DANE_ENABLED=false
DNSSEC_RESOLVER=1.1.1.1:53
MAX_MESSAGE_BYTES=52428800
# ARC seals accepted messages so a downstream receiver can still tell that the
# mail authenticated at the first hop. Only worth enabling on a host that
# forwards mail onward.
ARC_SEAL_ENABLED=false
# --- Smarthost (for hosts where outbound port 25 is blocked) ---
# Setting RELAY_HOST routes all delivery through the relay and adds it to the
# published SPF record, without which every relayed message fails SPF.
RELAY_HOST=
RELAY_PORT=587
RELAY_USER=
RELAY_PASS=
# --- Webmail ---
WEBMAIL_HOST=localhost:3000
ADMIN_HOST=