Documentation
Installation
This page takes you from the downloaded file to a running service. After that, continue with First steps.
Allow about half an hour if your database and DNS are already in place.
Before you start
| Operating system | macOS 14 or newer · Linux with systemd |
| Database | MariaDB 11 or MySQL 8, reachable (may run on the same machine) |
| Memory | 2 GB is enough for small installations |
| Disk | about 33 MB per 1,000 messages, raw data and search index combined |
| Network | a static address or DynDNS, and a DNS record pointing at the machine |
The database must be running before the service starts. The installer deliberately does not create it — it does not know whether you run your own instance, and it does not guess at your data.
1. Verify the package
Every package has a checksum on the download page. Verify it before you unpack anything:
shasum -a 256 annexgroup-<version>-<platform>.tar.gz
If it does not match, stop and download again. Then unpack:
tar xzf annexgroup-<version>-<platform>.tar.gz
cd annexgroup-<version>-<platform>
The package contains the program as a single file, an example
configuration, the service definition, and one script that does both —
install, and remove again with --uninstall.
2. Install
Linux:
sudo ./install-linux.sh
macOS:
sudo ./install-macos.sh
macOS 14 or newer is required. On an older system the installer stops before it writes anything, naming the cause: “AnnexGroup needs macOS 14 or newer; this Mac has macOS …”. The installation is verified on Apple Silicon; the Intel package is built, notarized and has run under Rosetta, but has not yet been measured on an Intel Mac with macOS 14.
The script creates the service user, the directories and the system service, and deliberately does not start the service. It ends by listing the steps that follow — the same ones as here.
Where it writes:
| Linux | macOS | |
|---|---|---|
| Program | /usr/local/bin/annexgroup |
/usr/local/bin/annexgroup |
| Configuration | /etc/annexgroup/config.yaml |
/usr/local/etc/annexgroup/config.yaml |
| Data | /var/lib/annexgroup |
/usr/local/var/annexgroup |
| Logs | /var/log/annexgroup |
/usr/local/var/log/annexgroup |
| Service | annexgroup.service |
biz.ma-kom.annexgroup.plist |
An existing config.yaml is never overwritten.
3. Create the database
mariadb -e "CREATE DATABASE annexgroup CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mariadb -e "CREATE USER 'annexgroup'@'localhost' IDENTIFIED BY '<password>';"
mariadb -e "GRANT ALL ON annexgroup.* TO 'annexgroup'@'localhost';"
utf8mb4 is not a recommendation but a requirement: without it, accented
characters, emoji and many attachment names break.
4. Adjust the configuration
Two settings in config.yaml are required; everything else has sensible
defaults:
domain: your-domain.com
database_dsn: "annexgroup:<password>@tcp(127.0.0.1:3306)/annexgroup?parseTime=true&loc=UTC"
Behind a reverse proxy (nginx and similar): enter it under
trusted_proxies, otherwise the login lockout, blacklist and log always
treat requests as coming from it:
trusted_proxies:
- 192.168.1.5 # the address of the nginx forwarding to this server
- 10.0.0.0/24 # or a network that only proxies come from
5. Start the service
Linux:
sudo systemctl enable --now annexgroup
systemctl status annexgroup
macOS:
sudo launchctl bootstrap system /Library/LaunchDaemons/biz.ma-kom.annexgroup.plist
6. Ports — on macOS this is where it gets stuck
On Linux the service listens on the usual ports: 25, 143, 993, 443 and 587.
On macOS it does not. The service runs as _annexgroup and therefore
cannot bind ports below 1024. It listens on high ports, and your router maps
the public ones onto them:
| public | on this machine | purpose |
|---|---|---|
| 25 | 1025 | delivery from other mail servers (MX) |
| 587 | 1587 | submission, STARTTLS |
| 465 | 1465 | submission, implicit TLS |
| 143 | 1143 | IMAP, STARTTLS |
| 993 | 1993 | IMAP, implicit TLS |
| 443 | 8443 | web interface |
Without this mapping no mail reaches you from outside — the server still runs and reports no error. This is the most common cause of "everything is green, but nothing arrives".
6a. The certificate — without it, two ports do not start
Between "start the service" and the assistant there is a step the server cannot solve on its own. The implicit-TLS ports — 465 (submission) and 993 (IMAP) — do not start without a certificate. A port that mail clients consider encrypted must not be encrypted only sometimes.
Three ways, and you need exactly one:
| Way | When | What goes into config.yaml |
|---|---|---|
| Let's Encrypt, automatic | The server is reachable from the internet under its name, ports 80 and 443 open | acme: true and acme_email: … |
| Your own certificate | You have one, or an in-house certificate authority | tls_cert: and tls_key: with full paths |
| Self-signed | for trying it out on your own network only | leave it empty — the server generates one on first start |
With a self-signed certificate every mail client warns, and setup with just an email address does not work: the discovery names
autoconfig.andautodiscover.must be inside the same certificate, otherwise the client drops the connection before it reads the settings.
7. Open the setup assistant
https://<your-host>/setup (Linux)
https://<your-host>:8443/setup (macOS)
There you create the first domain, the first administrator and a separate root password. The first 14 days run with full functionality without a licence.
What comes next — DNS records, deliverability, setup with just an email address — is in First steps.
When something does not work
| Symptom | Likely cause |
|---|---|
| Service does not start, log mentions the database | wrong database_dsn, database not created, or MariaDB is not running |
| Web interface does not answer | on macOS the port mapping (section 6); on Linux the firewall |
| 465 and 993 do not answer, 25 and 143 do | no certificate — see 6a. The implicit-TLS ports do not start without one |
| Mail client warns about the certificate | self-signed certificate, or autoconfig./autodiscover. missing from it |
| Other mail servers cannot reach you | port 25 is blocked on many connections — ask your provider to open it |
| Mail clients cannot find the server names | the SRV and CNAME records from First steps are missing |
Logs are in /var/log/annexgroup (Linux) or /usr/local/var/log/annexgroup
(macOS).
Uninstalling
sudo ./install-linux.sh --uninstall # or install-macos.sh
This removes only the program and the service. Configuration, data, logs, the database and the service user are deliberately left in place — an uninstaller that deletes mailboxes is a bug, not a feature.
Something unclear or described wrong? Tell us — we will fix it. Your question shows us where the text falls short.