Skip to content

First-boot setup (browser)

When to use: after mailctl install (without --answers) has printed the Setup Wizard URL, or whenever GET /api/v1/health reports setup: pending. Preconditions: the stack is up (mailctl doctor shows the containers healthy); you know the hostname you want, its A record points at this host (or you will use the IP for now), and you have decided on TLS (Let’s Encrypt needs ports 80 and 443 reachable from the internet).

  1. Open http://<public-ip>/ (or http://<hostname>/ once DNS resolves). Plain HTTP only at this point: the bootstrap docker/caddy/Caddyfile has auto_https off and listens on :80, so HTTPS — and any certificate — exists only after the Apply step renders the real configuration. The wizard opens; anything else redirects here until setup is complete.
  2. Hostname — enter the FQDN (mail.example.com). Continue.
  3. TLS — Automatic + contact email (recommended), Bring my own (paste certificate chain and private key PEM), or None — for a stack whose mail ports are published on loopback only; on a public address the wizard refuses it unless you tick the acknowledgement that the server will accept passwords in clear text on 143 and 587 (and 110 while POP3 is on), and mailctl doctor then reports that as ✖. The same screen has offer POP3 on ports 110 and 995, on by default; untick it if no client of yours downloads-and-deletes over POP3 — webmail, phones and modern desktop clients use IMAP — and the ports refuse at Dovecot. Continue.
  4. First domain — the domain that will receive mail (example.com) and the default per-mailbox quota, which starts at 0, meaning unlimited. 5 GB appears in the field’s hint as an example of the format it accepts, not as the value it will use — type something there if you want a cap. Continue.
  5. Owner account — email and password (≥10 characters). Leave Also create a mailbox ticked if the address belongs to the first domain. Continue.
  6. AI (optional) — skip it unless you already have a provider key or a model running on your own hardware; Skip for now leaves AI off, which is how the server ships, and everything here can be set later under AI in the admin sidebar. To configure it now: pick a provider, paste the model id from that vendor’s documentation, add the key (and an endpoint if the provider is self-hosted), Save, then Test connection — the endpoint’s own model list comes back, which is how you find out you typed the model id wrong. Tick Local only to refuse any endpoint that is not on a private network; hosted vendors disappear from the picker while it is on. Per-domain policy and each mailbox’s opt-in are not here — they are admin screens, and no mail reaches a provider until a mailbox opts in (AI providers, Setting up an AI provider).
  7. Apply — review, then Apply and finish. The API renders the configuration, each daemon validates it, and it goes live (a few seconds). A validation failure is shown with the daemon’s output and nothing changes — fix the input (usually the hostname or certificate) and retry.
  8. DNS records — copy each record (including the DKIM TXT) into your DNS provider; set the PTR at your VPS provider. Then Sign in and verify DNS. With TLS on, it opens https://<hostname>/login in a full page load, because from here plain HTTP only redirects to HTTPS. With Automatic TLS that needs the hostname’s A record to resolve and its certificate to be issued first. Log in as the owner, and click Verify now in the domain’s DNS & routing section until it reports Domain ready.
  9. Immediately: Account → Set up 2FA for the owner, and add further administrators under Users & roles.

mailctl doctor is all ✔; https://<hostname>/ shows the sign-in page over a valid certificate; GET /api/v1/health reports setup: complete; an IMAP client connects to <hostname>:993 and sends through :587 with the owner mailbox; Domains → <domain> → DNS & routing matches what you published.

Setup is one-shot: once complete, change settings under Settings (with history and rollback) and the admin screens. To start from scratch, mailctl install again after docker compose … down -v (destroys mail and database — see Install). If you closed the browser mid-way, simply reopen the URL; the wizard resumes at the first step the server has not recorded.