|
| 1 | +# Mail — self-hosted Mailu at `mail.profullstack.com` |
| 2 | + |
| 3 | +AgentBBS gives **Founding Lifetime (paid) members** a real mailbox at |
| 4 | +`<name>@mail.profullstack.com`, reached two ways: |
| 5 | + |
| 6 | +- **Webmail** — `https://mail.profullstack.com` (Roundcube), the only |
| 7 | + member-facing mail surface. |
| 8 | +- **AgentMail** — the in-BBS client (`internal/mailbox`): the `Mail` hub entry |
| 9 | + or `ssh mail@bbs.profullstack.com` (a TUI for humans, a JSON bot mode for |
| 10 | + agents). It connects to this stack. |
| 11 | + |
| 12 | +The apex `profullstack.com` is **reserved for corporate mail** and is not served |
| 13 | +here — member mail lives only on the `mail.` subdomain. |
| 14 | + |
| 15 | +## Architecture |
| 16 | + |
| 17 | +The host already runs **Caddy** (owns `:80`/`:443`) and the **agentbbs** process. |
| 18 | +Mailu (Postfix + Dovecot + Roundcube + rspamd) runs as a Docker Compose stack: |
| 19 | + |
| 20 | +- Mailu owns the **mail ports** on the host: `25, 465, 587, 993, 995`. |
| 21 | +- Mailu's HTTP front is bound to **loopback** (`127.0.0.1:8080`); **Caddy** |
| 22 | + reverse-proxies `https://mail.profullstack.com` to it (webmail + admin). |
| 23 | +- **TLS:** `TLS_FLAVOR=mail` — Mailu does *not* run its own ACME (Caddy is the |
| 24 | + only ACME client). Caddy obtains the `mail.profullstack.com` cert from its site |
| 25 | + block; [`deploy/mailu/refresh-certs.sh`](../deploy/mailu/refresh-certs.sh) |
| 26 | + copies it into Mailu and reloads it on renewal — the same pattern as the |
| 27 | + Ergo/IRC and NNTP cert refreshers. |
| 28 | +- The **agentbbs gateway** reads/sends on behalf of members: IMAP via a Dovecot |
| 29 | + **master user** (one secret opens any mailbox), SMTP via the co-located relay |
| 30 | + on `127.0.0.1:25`. Members therefore never manage an IMAP/SMTP password. |
| 31 | + |
| 32 | +``` |
| 33 | + ┌─────────── Caddy (:443) ───────────┐ |
| 34 | + webmail → │ mail.profullstack.com → 127.0.0.1:8080 (Mailu front, HTTP) |
| 35 | + └───────────────┬─────────────────────┘ |
| 36 | + │ copies LE cert (refresh-certs.sh) |
| 37 | + clients → Mailu front (:25 :465 :587 :993 :995) ──→ Postfix / Dovecot / rspamd |
| 38 | + ▲ |
| 39 | + agentbbs ──IMAP 993 (master user)──┘ ──SMTP 127.0.0.1:25 (local relay)──▶ |
| 40 | +``` |
| 41 | + |
| 42 | +## DNS |
| 43 | + |
| 44 | +`mail.profullstack.com` and `smtp.profullstack.com` A records are added. Also set: |
| 45 | + |
| 46 | +| Type | Host | Value | |
| 47 | +|---|---|---| |
| 48 | +| A | `mail.profullstack.com` | host IP | |
| 49 | +| A | `smtp.profullstack.com` | host IP | |
| 50 | +| MX | `mail.profullstack.com` | `10 mail.profullstack.com.` | |
| 51 | +| TXT (SPF) | `mail.profullstack.com` | `v=spf1 mx -all` | |
| 52 | +| TXT (DMARC) | `_dmarc.mail.profullstack.com` | `v=DMARC1; p=quarantine; rua=mailto:postmaster@mail.profullstack.com` | |
| 53 | +| TXT (DKIM) | `dkim._domainkey.mail.profullstack.com` | from `flask mailu config-export` after first boot | |
| 54 | +| PTR | host IP | `mail.profullstack.com` (set at your VPS provider) | |
| 55 | + |
| 56 | +> **Port 25 / deliverability:** many cloud providers block outbound `:25` by |
| 57 | +> default — request an unblock, set the PTR/rDNS, and warm the IP, or relay |
| 58 | +> outbound through a smarthost. Inbound MX and the gateway's local submission |
| 59 | +> work regardless. |
| 60 | +
|
| 61 | +## Install |
| 62 | + |
| 63 | +```bash |
| 64 | +cd /opt/agentbbs/deploy/mailu |
| 65 | +cp mailu.env.example mailu.env # fill SECRET_KEY, INITIAL_ADMIN_PW, etc. |
| 66 | +docker compose up -d |
| 67 | +# seed the gateway master user + (optionally) backfill member mailboxes: |
| 68 | +AGENTBBS_MAIL_MASTER_USER=gateway ./provision-mailbox.sh --master "$(openssl rand -hex 16)" |
| 69 | +``` |
| 70 | + |
| 71 | +Add the Caddy site (setup.sh writes this when `MAIL=1`): |
| 72 | + |
| 73 | +``` |
| 74 | +mail.profullstack.com { |
| 75 | + encode zstd gzip |
| 76 | + reverse_proxy 127.0.0.1:8080 |
| 77 | +} |
| 78 | +``` |
| 79 | + |
| 80 | +Then install the cert refresher on a timer (setup.sh does this too): |
| 81 | + |
| 82 | +```bash |
| 83 | +install -m 0755 deploy/mailu/refresh-certs.sh /usr/local/bin/agentbbs-mailu-certs |
| 84 | +# systemd timer runs it every ~12h; first run swaps in the real cert once Caddy issues it. |
| 85 | +``` |
| 86 | + |
| 87 | +## agentbbs gateway env |
| 88 | + |
| 89 | +Set these on the agentbbs service so the `Mail` hub entry / `ssh mail@` work: |
| 90 | + |
| 91 | +| Var | Value | |
| 92 | +|---|---| |
| 93 | +| `AGENTBBS_MAIL_DOMAIN` | `mail.profullstack.com` | |
| 94 | +| `AGENTBBS_MAIL_IMAP_ADDR` | `mail.profullstack.com:993` | |
| 95 | +| `AGENTBBS_MAIL_SMTP_ADDR` | `127.0.0.1:25` | |
| 96 | +| `AGENTBBS_MAIL_MASTER_USER` | `gateway` | |
| 97 | +| `AGENTBBS_MAIL_MASTER_PASS` | the master password set above | |
| 98 | + |
| 99 | +## Provisioning member mailboxes |
| 100 | + |
| 101 | +A mailbox must exist before the gateway can open it. Provision when a member |
| 102 | +becomes paid (or backfill): |
| 103 | + |
| 104 | +```bash |
| 105 | +deploy/mailu/provision-mailbox.sh alice # creates alice@mail.profullstack.com |
| 106 | +``` |
| 107 | + |
| 108 | +The Dovecot **master user** (`gateway`) then authenticates as any member with |
| 109 | +the login form `alice*gateway` + the master password — which is exactly what |
| 110 | +`internal/mailbox`'s IMAP adapter sends. See |
| 111 | +[`deploy/mailu/README.md`](../deploy/mailu/README.md) for the master-user |
| 112 | +override and operational details. |
| 113 | + |
| 114 | +## Webmail only for members |
| 115 | + |
| 116 | +Members are pointed at `https://mail.profullstack.com` (Roundcube) and the BBS |
| 117 | +`Mail` client — they are not given the Mailu admin UI or alias management. Admin |
| 118 | +is operator-only. |
0 commit comments