# tailwart > Tailscale × Stalwart. A mailbox with no WAN presence, fronted by a layer-4 > proxy that can live on another machine entirely. A deliberately over-engineered playground: [Stalwart](https://github.com/stalwartlabs/stalwart) mail server wired into **Postgres + Redis + Garage S3** at once, deployed as a Tailscale sidecar, with a separate `caddy-l4` edge that pipes the raw mail ports over the tailnet. For `infinidim.net`. See [CLAUDE.md](./CLAUDE.md) for the architecture and the gotchas. ## Layout ``` tailwart/ ├── docker-compose.yml # the mailbox: ts-stalwart sidecar + stalwart ├── config/config.toml # Stalwart config — PG + Redis + S3 wiring (strawman) ├── caddy/ # the edge: custom Caddy (caddy-l4) layer-4 mail proxy │ ├── Dockerfile # xcaddy build with caddy-l4 + ratelimit │ ├── caddy.json # :25/465/587/143/993 → stalwart over the tailnet │ ├── docker-compose.yml # deploy on any public-IP, tailnet, tag:reverse-proxy host │ └── README.md ├── acl-snippet.hujson # tag:stalwart owner + grants to merge into your policy ├── .env.example # operator surface — copy to .env └── .gitignore ``` ## Quickstart ```bash cp .env.example .env && $EDITOR .env # fill secrets (see CLAUDE.md prereqs) # 1. create the stalwart role/db in shared Postgres + the Garage bucket # (one-off; see CLAUDE.md "Prerequisites") # 2. admin console: assign tag:stalwart to the OAuth client + paste acl-snippet # 3. bring up the mailbox (tailnet-only) docker compose up -d # 4. bring up the edge (binds public mail ports; can be a different host) cd caddy && docker compose up -d --build ``` Then point `infinidim.net`'s MX at the edge host, add SPF/DKIM/DMARC, and finish configuration in Stalwart's web admin (`mail.infinidim.net`). ## Status Scaffold / strawman. The Stalwart `config.toml` keys need verifying against a pinned image version before first real boot — treat it as a starting shape, not a turnkey config.