ihasmail-oneshot¶
This page takes you from an empty Linux server to working mail and webmail. One command does the setup. You publish some DNS records, and mail flows.
Use this if you don't run a mail server yet. ihasmail-oneshot sets up a fresh Stalwart mail server and ihasmail side by side, and links them. If you already run Stalwart, follow Installing instead.
What you get¶
When it finishes, for a domain such as example.com, you have:
- Webmail at
https://webmail.example.com. - Stalwart's admin page at
https://mail.example.com/admin, for every server setting. - An administrator account,
[email protected], and a mailbox for each person you name. - Certificates for the webmail and for the mail ports, so connections are encrypted.
- A list of DNS records to publish, in a file called
dns-records.zone.
It runs three containers on the machine:
| Container | What it does |
|---|---|
| Stalwart | The mail server. It sends and receives mail and holds every mailbox |
| ihasmail | The webmail. It holds nothing but who is signed in |
| Caddy | A reverse proxy: it gives the webmail and Stalwart's web pages their HTTPS addresses |
What it leaves behind is an ordinary Docker Compose project. You manage it with
the usual docker compose commands, and it doesn't need this tool again.
Why a tool for this
Stalwart and ihasmail each install easily. Making them a safe mail host together means getting a series of details right. Stalwart has no settings file to fill in. Both want the same port for certificates. And Stalwart's automatic blocking of attackers can lock everyone out when a proxy sits in front of it. The tool makes each of those choices the same way every time, and checks the result. How it works explains each one.
Before you start¶
You need:
- A Linux server, amd64 or arm64, with Docker and its compose plugin.
docker compose versionshould work for your user. - A domain whose DNS you control.
- A static public IP address for the server.
- These ports open in the server's firewall and your provider's firewall: TCP 25, 80, 443, 465, 993, 995 and 4190, and UDP 443.
- Outgoing port 25 allowed. Many providers block it until you ask. Without it you can receive mail but not send it.
- Reverse DNS for the server's address, naming
mail.example.com. You set this at your hosting provider, not in your DNS zone. Many mail servers refuse mail from an address without it.
Size the server for Stalwart. Its needs grow with the mail it stores and the people using it. ihasmail alone needs 256 MiB of memory.
Install the tool¶
Download the tool for your server's architecture, check it, and put it on your path:
ARCH=amd64 # or arm64
curl -fsSLO https://github.com/Coffey-Labs/ihasmail-oneshot/releases/latest/download/ihasmail-oneshot-linux-$ARCH.tar.gz
curl -fsSLO https://github.com/Coffey-Labs/ihasmail-oneshot/releases/latest/download/SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS
tar -xzf ihasmail-oneshot-linux-$ARCH.tar.gz
sudo install -m 0755 ihasmail-oneshot /usr/local/bin/
ihasmail-oneshot version
sha256sum should print OK for your file. If it doesn't, don't use the
download.
Try it on your own machine first¶
You can see ihasmail with a real Stalwart behind it, with no domain and no open ports:
It shows its plan and asks before doing anything. When it finishes, open
http://127.0.0.1:8080 and sign in as [email protected]. Her password is in
ihasmail-example-test/credentials.txt.
Nothing outside your machine can reach this pair, and no mail can be delivered to it. When you're done, remove it:
Deploy a mail host¶
The steps use example.com. Use your own domain throughout.
1. Point two names at the server¶
At your DNS provider, create these records with your server's addresses:
mail.example.com. IN A 203.0.113.10
webmail.example.com. IN A 203.0.113.10
; and, if the server has IPv6:
mail.example.com. IN AAAA 2001:db8::10
webmail.example.com. IN AAAA 2001:db8::10
Do this first, so certificates can be issued during the deploy. If you skip it, the deploy still finishes and tells you how to get certificates later.
Turn off any proxy mode on these records
If your DNS provider can proxy traffic through its own network, set these two records to DNS only. Mail ports can't go through such a proxy, and certificate checks must reach your server directly.
2. Run the deploy¶
On the server:
ihasmail-oneshot deploy \
--domain example.com \
--email [email protected] \
--user alice --user bob
--domainis the domain you receive mail for.--emailis where the certificate authority, Let's Encrypt, sends notices about your certificates. Use an address that doesn't depend on this new server. It defaults to[email protected].--usercreates a mailbox. Repeat it for each person.
The tool checks the server and finds ihasmail's newest release. Then it shows the plan, including the exact ihasmail version, and asks you to confirm. A run takes a minute or two, mostly downloading. It ends with a summary like this:
==> done
webmail https://webmail.example.com
Stalwart https://mail.example.com/admin
sign in as [email protected] (password in /root/ihasmail-example-com/credentials.txt)
the administrator gets the webmail's Administration menu
mailbox [email protected]
mailbox [email protected]
DNS /root/ihasmail-example-com/dns-records.zone -- publish every record in it
certificate issued by <Let's Encrypt intermediate>, valid until <date>
https webmail.example.com: issued by <Let's Encrypt intermediate>
https mail.example.com: issued by <Let's Encrypt intermediate>
The certificate and https lines mean certificates were issued. If one is a
warning instead, see step 4.
What the deploy does, in order
- Checks Docker, free ports, the deployment directory and your DNS, and reports every problem at once.
- Finds ihasmail's newest release and asks you to confirm.
- Writes the deployment directory, with a freshly generated secret.
- Downloads the images.
- Starts Stalwart with a one-time administrator that exists only in the tool's memory, and completes Stalwart's setup through its API.
- Starts everything, without the one-time administrator.
- Links ihasmail and Stalwart, and creates the mailboxes.
- Proves the link by signing in through the webmail.
- Gets certificates, and writes the DNS records to publish.
How it works covers each step in detail.
3. Publish the DNS records¶
dns-records.zone holds every record your mail server needs, including the
DKIM keys it just made. (DKIM signs your outgoing mail, so other servers can
tell it really came from you.) Publish all of them. Many DNS providers can
import the file directly.
Four kinds matter most for delivery:
| Record | What it does |
|---|---|
| MX | Tells other servers where to deliver mail for your domain |
| SPF | Lists which servers may send mail as your domain |
| DKIM | Publishes the keys that prove your mail is genuine |
| DMARC | Tells other servers what to do with mail that fails those checks |
The rest let mail apps set themselves up from just an email address.
DMARC starts strict
The DMARC record says p=reject: other servers should refuse mail that
fails the checks. That's right for a domain that only sends from this
server. If another service also sends mail as your domain, change it to
p=none until that service is set up too.
4. Get Stalwart's certificate, if DNS came late¶
If your names didn't resolve during the deploy, the summary says Stalwart has
no certificate yet. Caddy keeps trying on its own. Stalwart doesn't. Once DNS
points at the server, and the records from dns-records.zone are published,
run:
Why Stalwart needs the extra records first
Stalwart's certificate also covers autoconfig, autodiscover, mta-sts
and ua-auto-config under your domain. Those names come from
dns-records.zone, so the order can only succeed once they resolve to your
server. Stalwart doesn't retry a failed order by itself, which is why
certs starts a new one.
5. Sign in¶
- Webmail:
https://webmail.example.com, as any mailbox. As[email protected]you also get the Administration menu, for adding people and domains. - Stalwart's admin page:
https://mail.example.com/admin, as[email protected]. - Mail apps on computers and phones: add the account with the email address
and password. Once the DNS records are published, most apps find the servers
themselves. By hand, use IMAP on
mail.example.comport 993 and SMTP onmail.example.comport 465, both with TLS.
Change the generated passwords after you first sign in. Then delete them
from credentials.txt, or keep that file somewhere safe. An account with
two-factor sign-in turned on needs an app password for the webmail, created in
Stalwart.
What it leaves on the server¶
The deploy writes a directory named after your domain, such as
./ihasmail-example-com:
| File | What it is |
|---|---|
compose.yaml |
The whole deployment, with comments |
Caddyfile |
The reverse proxy's settings |
.env |
The secret that protects webmail sign-ins. Private to you |
credentials.txt |
The generated passwords. Private to you |
dns-records.zone |
The DNS records to publish |
Your mail, accounts and settings live in Docker volumes, not in the directory.
The one that matters is ihasmail-example-com_stalwart-data. ihasmail keeps
nothing: restarting it only signs people out.
The reference lists every file and volume.
Day to day¶
Run these from inside the deployment directory:
docker compose ps # what's running
docker compose logs -f stalwart # watch the mail server's log
docker compose restart ihasmail # signs everyone out of the webmail; nothing else is lost
docker compose down # stop everything; your mail stays in the volumes
docker compose up -d # start it again
The containers start again by themselves after a crash or a reboot.
Upgrade¶
Nothing upgrades on its own. Every image in compose.yaml is a fixed version,
ihasmail included. To upgrade one, change its tag in compose.yaml, then run:
- ihasmail: move to any newer release that supports your Stalwart version.
Releases are listed on GitHub.
The image tag is the version with
+written as-, such as2026.9.15-pr369. - Stalwart: read its upgrade notes, check your ihasmail version supports the new release, and back up first. A Stalwart upgrade can't be undone.
- Caddy: minor releases are routine.
Back up¶
Everything you can't recreate is in the stalwart-data volume. Stop Stalwart
for a moment so the copy is consistent:
docker compose stop stalwart
docker run --rm -v ihasmail-example-com_stalwart-data:/data -v "$PWD":/backup alpine \
tar -czf /backup/stalwart-data-$(date +%F).tar.gz -C /data .
docker compose start stalwart
Keep the caddy-data volume too, or certificates are requested again after a
rebuild. Keep the deployment directory as well: it's small, and holds your
secrets.
Remove it¶
This deletes every message and account
destroy removes the containers, the network, the volumes with all your
mail, and the files the tool wrote. It asks first unless you add --yes.
Files you added to the directory yourself are left alone.
If something goes wrong¶
- A check fails before anything starts, such as a port already in use: the message says what to fix. Nothing has changed yet.
- A deploy stops partway: the error names the step and shows the last lines
of the log. To start again, run
ihasmail-oneshot destroy --dir DIR --yes, fix the cause, and deploy again. - Mail arrives, but mail you send never does: outgoing port 25 is almost always blocked. Ask your provider, and check reverse DNS.
Troubleshooting covers every message and symptom, and the tool's known limits. For the webmail itself, see ihasmail's own Troubleshooting.