Run a mail server
In this guide a superuser sets up mail for a domain on the panel node: sending
and receiving for addresses like hello@example.com, with DKIM signing.
Prerequisites
Section titled “Prerequisites”- A superuser account.
- A public IPv4 address on the server, and the ability to set its reverse DNS (PTR) at your provider.
- Port 25 unblocked, inbound and outbound. Many clouds block it until you ask.
- DNS control for the domain.
PANEL=https://panel.example.comH='Authorization: Bearer gsl_xxxxxxxxxxxxxxxx'J='Content-Type: application/json'1. Install the mail tooling
Section titled “1. Install the mail tooling”curl -sX POST $PANEL/mail/install -H "$H"# poll until installedcurl -s $PANEL/mail/status -H "$H" # {"installed": true}The worker installs Postfix (SMTP), Dovecot (IMAP, POP3, LMTP) and OpenDKIM,
creates a vmail user, and, if ufw is present, allows TCP 25, 465, 587, 143,
993, 110 and 995, plus 80 for the mail hostname’s certificate.
2. Add the domain
Section titled “2. Add the domain”Use the apex (example.com, not mail.example.com):
curl -sX POST $PANEL/mail/domains -H "$H" -H "$J" -d '{"domain": "example.com"}'A sync adds the domain to Postfix, generates a DKIM key (selector gisila),
detects the public IPv4 for SPF, and requests a Let’s Encrypt certificate for
the mail hostname, falling back to a self-signed one until DNS is ready.
The defaults are mail hostname mail.<domain> and DMARC policy none.
Change them with:
curl -sX PATCH $PANEL/mail/domains/{id} -H "$H" -H "$J" \ -d '{"mailHostname": "mail.example.com", "dmarcPolicy": "quarantine"}'3. Publish DNS
Section titled “3. Publish DNS”curl -s $PANEL/mail/domains/{id}/dns -H "$H" | jq '.records'The response lists the A, MX, SPF, DKIM and DMARC records with their
values. Wait for dkimConfigured: true before publishing the DKIM record. For
the mail hostname’s A record, use DNS only: a proxied (CDN) record never
receives SMTP.
Then set the server IP’s reverse DNS to the mail hostname at your provider. Large providers reject mail whose HELO name doesn’t match the PTR.
POST /mail/domains/{id}/sync re-runs the sync, for example after DNS
propagates.
4. Create mailboxes
Section titled “4. Create mailboxes”curl -sX POST $PANEL/mail/domains/{id}/accounts -H "$H" -H "$J" \ -d '{"localPart": "hello", "password": "<strong-password>", "quotaMb": 2048}'Leave out quotaMb for no quota. The password is stored as a hash and never
shown again. Reset it with PUT /mail/accounts/{accountId}/password.
Each mailbox in the response has connection settings for mail clients. Use
the full address as the username, submission on 587 (STARTTLS) or 465
(TLS), and IMAP on 993.
Verify it works
Section titled “Verify it works”dig +short MX example.comdig +short -x <server-ip> # must equal the mail hostnamecurl -s $PANEL/mail/health -H "$H" # cached health of the stackSend a message to an external mailbox and check that SPF, DKIM and DMARC pass
in the message headers. If health reports a problem,
POST /mail/repair queues a repair, and the health snapshot shows its result
(lastRepairStatus, lastRepairDetail).