From 0fe5927a0df3808f55de898bef484d5026eeac24 Mon Sep 17 00:00:00 2001 From: karmacoma Date: Sat, 27 Dec 2025 03:14:53 +0100 Subject: [PATCH] poste --- docker-compose.yml | 69 +++++++++++++++-------------- readme.md | 106 ++++++++++++++++++++++----------------------- 2 files changed, 87 insertions(+), 88 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index b16e06a..8e11323 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,38 +1,37 @@ -services: - mailserver: - image: ghcr.io/docker-mailserver/docker-mailserver:latest - container_name: mailserver - # Provide the FQDN of your mail server here (Your DNS MX record should point to this value) - hostname: mail.karmacoma.dev - ports: - - "25:25" - - "465:465" - - "587:587" - - "993:993" - volumes: - - ./docker-data/dms/mail-data/:/var/mail/ - - ./docker-data/dms/mail-state/:/var/mail-state/ - - ./docker-data/dms/mail-logs/:/var/log/mail/ - - ./docker-data/dms/config/:/tmp/docker-mailserver/ - - /etc/localtime:/etc/localtime:ro - environment: - - ENABLE_RSPAMD=1 - - ENABLE_CLAMAV=1 - - ENABLE_FAIL2BAN=1 - cap_add: - - NET_ADMIN # For Fail2Ban to work - restart: always +version: "3.9" - webmail: - image: ghcr.io/the-djmaze/snappymail:latest - container_name: webmail - depends_on: - - mailserver - ports: - - "8080:80" +services: + poste: + image: analogic/poste.io:latest + container_name: poste + restart: unless-stopped + hostname: ${POSTE_HOSTNAME} environment: - # Log to stdout so container logs are visible in Coolify and docker logs - - SNAPPYMAIL_LOG_TO_STDOUT=1 + # Traefik handles TLS termination; keep poste in HTTP mode on an internal port + - HTTPS=OFF + - HTTP_PORT=8080 + - HTTPS_PORT=8443 + - TZ=${TZ:-UTC} + - DISABLE_CLAMAV=${DISABLE_CLAMAV:-false} + - DISABLE_RSPAMD=${DISABLE_RSPAMD:-false} + ports: + - "25:25" # SMTP + - "465:465" # SMTPS + - "587:587" # Submission + - "110:110" # POP3 + - "143:143" # IMAP + - "993:993" # IMAPS + - "995:995" # POP3S + - "4190:4190" # ManageSieve volumes: - - ./docker-data/snappymail/:/snappymail/data/ - restart: unless-stopped \ No newline at end of file + - poste-data:/data + networks: + - poste-mail +volumes: + poste-data: + +networks: + poste-mail: + driver: bridge + ${TRAEFIK_NETWORK:-coolify-overlay}: + external: true diff --git a/readme.md b/readme.md index 91e6063..bf6ae84 100644 --- a/readme.md +++ b/readme.md @@ -1,63 +1,63 @@ -# Mail Stack on Coolify with OIDC Webmail +# Poste.io behind Traefik (Coolify) -This stack pairs **docker-mailserver** with **SnappyMail** as a modern webmail UI that can sit behind your OIDC provider. Deploy it through Coolify with this repository. +Self-hosted poste.io with HTTP(S) served by Traefik (managed by Coolify) and mail protocols exposed directly to the host. -## Components -- docker-mailserver: SMTP/IMAP server with spam/AV/Fail2Ban enabled. -- SnappyMail: lightweight webmail with OAuth2/OIDC login support. +## Network scheme (per poste.io docs) +- Mail ports (SMTP/IMAP/POP3/Sieve) are published directly on the host so clients and remote MTAs reach the real server IP. +- HTTP(S) for the admin UI and webmail is terminated by Traefik and forwarded internally to poste.io on port 8080 (poste runs with `HTTPS=OFF`). +- Set Docker `userland-proxy` to `false` to avoid losing real client IPs when publishing mail ports (poste.io warns about open relay risk when proxying mail ports). ## Prerequisites -- DNS: `MX` record to `mail.your-domain.tld`, plus `A`/`AAAA` for both `mail.your-domain.tld` and `webmail.your-domain.tld`. -- TLS: issue certificates (Coolify can request via Traefik/Let’s Encrypt if you publish through it). -- SMTP ports 25/465/587 and IMAP 993 open to the internet. -- An OIDC provider (e.g., Authentik, Keycloak, Azure AD) with a client ready to configure. +- Domain with A/AAAA record for `POSTE_HOSTNAME` (e.g., `mail.example.com`) pointing to the server public IP. +- MX record pointing to `POSTE_HOSTNAME`. +- Optional but recommended: PTR (rDNS) matching `POSTE_HOSTNAME`. +- DNS access to add SPF/TXT, DKIM (after initial setup), and DMARC records. +- Coolify with its Traefik stack running and an external Docker network available (default name `coolify-overlay`). + +## Configure Docker for real client IPs +Create or update `/etc/docker/daemon.json`: + +```json +{ + "userland-proxy": false +} +``` + +Restart Docker (`sudo systemctl restart docker`). This keeps source IPs visible to poste.io while using published ports. + +## Environment variables +Create `.env` next to `docker-compose.yml` (adjust values): + +``` +POSTE_HOSTNAME=mail.example.com +TZ=UTC +TRAEFIK_NETWORK=coolify-overlay +TRAEFIK_CERTRESOLVER=coolify +DISABLE_CLAMAV=false +DISABLE_RSPAMD=false +``` ## Deploy with Coolify -1. **Create an application from this repo** in Coolify and choose “Docker Compose”. -2. **Volumes**: Coolify will create them from the compose file paths. Ensure the persistent paths below map to durable storage: - - `./docker-data/dms/mail-data/`, `./docker-data/dms/mail-state/`, `./docker-data/dms/mail-logs/`, `./docker-data/dms/config/` - - `./docker-data/snappymail/` -3. **Environment**: adjust `hostname` for the mailserver and expose any extra docker-mailserver envs you need (aliases, relays, etc.). -4. **Networking**: publish ports 25/465/587/993 for mail delivery. Expose port 8080 from the `webmail` service to the internet (ideally behind HTTPS via Coolify/Traefik). If you front it with Traefik, set the appropriate labels and disable the direct `ports` stanza. -5. **Deploy** the stack. Coolify will start `mailserver` and `webmail` containers. +1) Ensure the Traefik network exists (default `coolify-overlay`). If not, create it: `docker network create coolify-overlay`. +2) Import this `docker-compose.yml` into a Coolify “Docker Compose” app. Set the environment variables above in Coolify. +3) Attach the app to Coolify’s Traefik network (`TRAEFIK_NETWORK`). Coolify will inject the network automatically when selected. +4) Deploy. Traefik will request a certificate via `TRAEFIK_CERTRESOLVER` and route `https://POSTE_HOSTNAME` to poste.io on port 8080. -## Bootstrap docker-mailserver -Run these once after the containers are healthy (from the host or via Coolify shell): +If running outside Coolify, you can still deploy with `docker compose up -d` after creating the network. -```bash -docker compose exec mailserver setup email add user@your-domain.tld "SuperSecretPassword" -docker compose exec mailserver setup alias add postmaster@your-domain.tld user@your-domain.tld -``` +## Exposed ports (host) +- 25 SMTP, 465 SMTPS, 587 Submission +- 110 POP3, 995 POP3S +- 143 IMAP, 993 IMAPS +- 4190 ManageSieve -Add DNS TXT records for SPF/DKIM/DMARC using docker-mailserver guidance, then reload: +## First-time setup +1) Wait for containers to start: `docker compose ps`. +2) Open `https://POSTE_HOSTNAME` to reach the admin UI (proxied by Traefik). Complete the poste.io onboarding (admin mailbox + password, DKIM key generation, etc.). +3) Add generated DKIM TXT record and ensure SPF and DMARC records are present. +4) Test SMTP/IMAP with your client against the host IP/hostname. -```bash -docker compose exec mailserver setup reload -``` - -## Configure SnappyMail for IMAP/SMTP -1. Open the admin panel at `https://webmail.your-domain.tld/?admin` (default admin password is shown on first run; change it immediately). -2. Set **IMAP** host to `mailserver`, port `993`, security **SSL/TLS**. -3. Set **SMTP** host to `mailserver`, port `587`, security **STARTTLS**, authentication **Use user credentials**. -4. Save and test with one of the mail accounts you created above. - -## Enable OIDC in SnappyMail -SnappyMail supports OAuth2/OIDC providers. Configure it in the admin UI: -1. In **Admin → Domains/Auth → OAuth**, add a **Custom / Generic OIDC** provider. -2. When prompted, SnappyMail shows a **Redirect URI**; copy this exact value into your OIDC client configuration. -3. In your OIDC provider, create a public/confidential client with these basics: - - **Grant type**: Authorization Code with PKCE (preferred) or standard code. - - **Scopes**: `openid email profile`. - - **Redirect URI**: the one SnappyMail displayed. -4. Back in SnappyMail, fill the provider fields: - - **Authorization endpoint** and **Token endpoint** from your IdP. - - **UserInfo endpoint** (for email/subject mapping). - - **Client ID/Secret** matching the client you created. - - **Login attribute mapping**: map email/subject to the mailbox name (e.g., `email` → `user@your-domain.tld`). -5. Save and test “Login with ”. Successful OIDC login should drop you into the mailbox without prompting for a separate password. - -## Operating tips -- Back up `./docker-data/` regularly; it holds mail, state, and SnappyMail config. -- Use Coolify health checks to surface container issues; restart policies are already defined in the compose file. -- For HTTPS, prefer running `webmail` behind Coolify’s Traefik with automatic certificates instead of exposing port 8080 directly. -- If you rotate OIDC credentials, update them in SnappyMail admin immediately to avoid login failures. +## Notes +- Poste.io still handles STARTTLS on mail ports directly; Traefik is only for HTTP(S). +- If you need Let’s Encrypt inside poste.io instead of Traefik, remove `HTTPS=OFF` and forward `/.well-known` from Traefik, but avoid port conflicts with Traefik’s 80/443. +- Keep an eye on spam/relay checks in the poste.io admin UI to confirm real client IPs are detected.