Skip to content

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:

  1. A Linux server, amd64 or arm64, with Docker and its compose plugin. docker compose version should work for your user.
  2. A domain whose DNS you control.
  3. A static public IP address for the server.
  4. 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.
  5. Outgoing port 25 allowed. Many providers block it until you ask. Without it you can receive mail but not send it.
  6. 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:

ihasmail-oneshot deploy --local --user alice

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:

ihasmail-oneshot destroy --dir ihasmail-example-test

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
  • --domain is the domain you receive mail for.
  • --email is 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].
  • --user creates 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
  1. Checks Docker, free ports, the deployment directory and your DNS, and reports every problem at once.
  2. Finds ihasmail's newest release and asks you to confirm.
  3. Writes the deployment directory, with a freshly generated secret.
  4. Downloads the images.
  5. Starts Stalwart with a one-time administrator that exists only in the tool's memory, and completes Stalwart's setup through its API.
  6. Starts everything, without the one-time administrator.
  7. Links ihasmail and Stalwart, and creates the mailboxes.
  8. Proves the link by signing in through the webmail.
  9. 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:

ihasmail-oneshot certs --dir ihasmail-example-com
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.com port 993 and SMTP on mail.example.com port 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:

docker compose pull && docker compose up -d
  • 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 as 2026.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

ihasmail-oneshot destroy --dir ihasmail-example-com

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.