Skip to content

Mail Server

Mail server configuration: smarthost relay, domains.

All endpoints below are mounted under /api. Authentication: Authorization: Bearer <token> unless noted as public.

Endpoint count: 3

Endpoints

Method Path Handler Guards
POST /api/mail-server/install installMailServer RequireSuperuser(), RequirePlugin(db, "mail-server")
GET /api/mail-server/status getMailServerStatus RequireSuperuser(), RequirePlugin(db, "mail-server")
POST /api/mail-server/uninstall uninstallMailServer RequireSuperuser(), RequirePlugin(db, "mail-server")

Source

Handlers for this section live in api/routes/handlers_*.go in the StarkOne source. Each handler binds its request body with gin.ShouldBindJSON(&req) and responds with the standard envelope:

{ "data": { ... } }

On error:

{ "error": { "code": "string", "message": "string" } }

Reference

POST /api/mail-server/install

Installs the Stalwart mail server (downloading and configuring it, replacing exim4, provisioning the management webapp and optional storage/Roundcube webmail), returning generated admin credentials.

Guards: RequireSuperuser(), RequirePlugin(db, "mail-server")

Request body

{
  "open_firewall_ports": "bool (optional)",
  "install_roundcube": "bool (optional)",
  "storage_backend": "string (optional)"
}
Field Type Required Description
open_firewall_ports bool no When true, opens mail ports (25, 465, 587, 143, 993, 110, 995, 4190) TCP in/out via the firewall CLI.
install_roundcube bool no When true, also installs and configures Roundcube webmail (release 1.6.6).
storage_backend string no Storage backend for Stalwart: "rocksdb" (default when empty) or "mysql".

Response - 200 OK

{
  "data": {
    "success": true,
    "admin_url": "https://203.0.113.10:8443",
    "admin_user": "admin",
    "admin_password": "generated-random-password",
    "roundcube_url": "https://203.0.113.10/",
    "message": "Mail server installed successfully!"
  }
}

The admin_password is a freshly generated 16-character random string. roundcube_url is empty when install_roundcube is false.

Errors

Status Code Meaning
400 bad_request Request body failed JSON binding.
400 already_installed Stalwart is already installed (/opt/stalwart/bin/stalwart exists).
500 install_failed The Stalwart install script returned a non-zero exit; message contains combined output.
500 hash_failed Failed to hash the admin password with openssl passwd -6.

Side effects

  • Runs the Stalwart install script (curl -sL https://get.stalw.art/install.sh | bash).
  • Generates a random admin password, hashes it with openssl passwd -6, and writes the hash into /opt/stalwart/etc/config.toml via sed.
  • Optionally opens mail firewall ports (TCP in/out) when open_firewall_ports is true.
  • Creates a stalwartdata webapp (proxying to port 8080) for the management UI.
  • For mysql backend: creates a mail database, creates/grants the stalwartdata_mail MySQL user, and rewrites the storage section of config.toml to use MySQL; otherwise points RocksDB at /home/stalwartdata/data.
  • Moves Stalwart data and logs directories under /home/stalwartdata, and chowns files to the stalwartdata user.
  • Stops, disables, and masks exim4; edits the systemd unit to run as stalwartdata.
  • Edits config.toml to remove HTTPS/POP3/POP3S/Sieve listeners, add an HTTP listener on :8080, allow non-FQDN EHLO, and restrict relay to authenticated users.
  • Runs systemctl daemon-reload and systemctl restart stalwart.
  • When install_roundcube is true: creates a roundcube webapp and database, downloads/extracts Roundcube 1.6.6, writes its config.inc.php, patches a Hebrew charset alias, and imports its DB schema.

Example

curl -X POST https://panel.example.com:2087/api/mail-server/install \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"open_firewall_ports": true, "install_roundcube": true, "storage_backend": "rocksdb"}'

GET /api/mail-server/status

Reports whether Stalwart is installed and running and whether the Roundcube webmail webapp exists.

Guards: RequireSuperuser(), RequirePlugin(db, "mail-server")

Response - 200 OK

{
  "data": {
    "installed": true,
    "running": true,
    "roundcube_installed": true,
    "roundcube_domain": "webmail.example.com"
  }
}
Field Type Description
installed bool True when /opt/stalwart/bin/stalwart exists.
running bool True when systemctl is-active stalwart reports active.
roundcube_installed bool True when a webapp with username roundcube has a non-empty domain.
roundcube_domain string Domain of the Roundcube webapp, or empty if none.

Example

curl -X GET https://panel.example.com:2087/api/mail-server/status \
  -H "Authorization: Bearer $TOKEN"

POST /api/mail-server/uninstall

Stops and removes Stalwart, restores exim4, and deletes the management and Roundcube webapps while preserving mail data.

Guards: RequireSuperuser(), RequirePlugin(db, "mail-server")

Response - 200 OK

{
  "data": {
    "success": true,
    "message": "Mail server uninstalled. Exim restored. Data preserved at /home/stalwartdata/data"
  }
}

Side effects

  • Stops and disables the stalwart service.
  • Removes Stalwart binaries, config, and logs (/opt/stalwart/bin, /opt/stalwart/etc, /opt/stalwart/logs) and the systemd unit file, then runs systemctl daemon-reload. Data under /home/stalwartdata/data is preserved.
  • Restores exim4: systemctl unmask, enable, and start.
  • Deletes the stalwartdata webapp and the roundcube webapp (if present) via the websites package.

Example

curl -X POST https://panel.example.com:2087/api/mail-server/uninstall \
  -H "Authorization: Bearer $TOKEN"