Skip to content
English

Post-installation checklist

When grommunio-setup finishes, the appliance is configured but empty: no mail domain, no user, no DNS records that other mail servers could trust. This page covers everything between that point and a system that delivers mail reliably in both directions. Work through the numbered steps in order; each one ends with a check you should pass before moving on.

The installation itself is documented elsewhere and is not repeated here: downloading the ISO and sizing the machine in the Quickstart, the console user interface and every dialog of the setup wizard in Guided Installation. If the wizard did not complete, fix that first (the log is /var/log/grommunio-setup.log).

A grommunio appliance is a set of cooperating services. After setup, all of them should be running; the checks in this guide follow the path a message takes through them.

UnitRoleListens on
nginxReverse proxy for grommunio Web, Admin UI, AutoDiscover, EAS, DAV; TLS termination80, 443, 8080/8443 (Admin)
postfixMTA: receives mail from the Internet and from clients, hands it to the antispam milter and to local delivery25, 587 (465 where implicit-TLS submission is enabled)
grommunio-antispamRspamd-based filter: spam scoring, DKIM signing, optional anti-virus11332 (milter), 11334 (controller), local only
gromox-delivery-queue, gromox-deliveryLocal delivery: receive from Postfix, convert to MAPI objects, store in the mailbox24 (LMTP/SMTP), local only
gromox-httpMAPI/HTTP, RPC over HTTP, EWS, AutoDiscover backend behind nginxlocal only
gromox-imap, gromox-pop3IMAP and POP3 access143/993, 110/995
gromox-midb, gromox-zcore, gromox-event, gromox-timerMessage index, PHP-MAPI core, event bus, scheduled taskslocal only
grommunio-admin-apiAdmin REST API behind nginx (Admin UI, grommunio-admin CLI)via nginx
mariadb, redis@grommunio, php-fpm, saslauthdDatabase, cache, PHP runtime for Web/Sync/DAV, SMTP authenticationlocal only

The public ports and the firewall defaults are listed in the Quickstart; the complete mail flow is described in Architecture.

  • grommunio-setup has completed; you know the FQDN (for example mail.example.com) and the primary mail domain (example.com) you entered, and the admin password.
  • Root access to the appliance (console or SSH).
  • Control over the public DNS zone of the mail domain and over the reverse DNS (PTR) of the public IP address, usually via the hosting provider.
  • Inbound TCP 25 and 443 reachable from the Internet on the public IP; TCP 80 if you use Let's Encrypt.
  • An external mailbox (another provider) to test delivery in both directions.

A loaded web page does not prove that the mail path works. Verify the service set, the listening sockets and the package repositories before creating anything.

Terminal window
systemctl --failed
systemctl --type=service --state=running | grep -E 'gromox|grommunio|postfix|nginx|mariadb|redis|saslauthd|php-fpm'
ss -tulpn
hostname -f
timedatectl
getent hosts download.grommunio.com
zypper lr -u
zypper refresh
zypper list-patches

Expected results:

  • systemctl --failed lists no units.
  • The running services include grommunio-admin-api, grommunio-antispam, the gromox-* daemons from the table above, mariadb, nginx, php-fpm, postfix, redis@grommunio and saslauthd.
  • ss -tulpn shows listeners on 25, 80, 443, 587, 110, 143, 993, 995 and on the Admin ports (8080; 8443 in addition after the TLS switch in step 2). Internal listeners on 24 (delivery-queue), 11332/11334 (rspamd), 3306 (mysqld) and 6379 (redis-server) are bound to localhost only.
  • hostname -f returns the FQDN, not localhost or a short name; timedatectl reports a synchronised clock and the intended time zone.
  • getent hosts download.grommunio.com resolves and zypper refresh succeeds. If it does not, fix the resolver first: a broken resolver is the most common reason for failing repository access and, later, for failing outbound mail. Hostname, resolver and time settings are changed through the CUI, see Guided Installation.

The appliance ships with firewalld, and grommunio-setup opens the service ports listed in the Quickstart in the public zone. Confirm the rule set and close what you do not offer:

Terminal window
systemctl is-active firewalld
firewall-cmd --list-all

Expected result: the services and ports from the Quickstart list, nothing more. Remove the entries for protocols you do not provide (for example POP3) and, on systems without a host firewall (firewalld not installed or inactive), restrict the Admin ports and unused services on the perimeter firewall or the hypervisor instead.

Open the Admin UI at https://<FQDN>:8443/ and sign in as admin. The Admin UI is served on its own ports, not below the /web/ path of grommunio Web. If the page does not load on 8443, the Admin API is still served unencrypted on port 8080 only, as it is during provisioning; switch it to TLS as described in Admin API TLS configuration before exposing it anywhere.

On the Dashboard, the services panel must show all grommunio and Gromox services as running, and the versions panel lists the installed components. Then open grommunio Web at https://<FQDN>/web/; the login page must load over HTTPS without an error other than the expected certificate warning if you chose a self-signed certificate.

Two housekeeping tasks belong here:

  • The setup log /var/log/grommunio-setup.log contains generated credentials. Copy it to a safe place and remove it from the appliance, or at least restrict access to it.
  • Change the admin password if you kept the generated one: grommunio-admin passwd (no user argument sets the password of admin). The admin account and the system root account are independent; see grommunio Admin User.

The wizard records the primary mail domain but does not create it as a mail domain. Create the domain, then a first user. Both can be done in the Admin UI (Adding a domain, Adding a user) or on the command line. The CLI is reproducible and easy to script, so it is used here.

Terminal window
grommunio-admin domain create -u 25 --title "Example Inc." example.com
grommunio-admin user create --lang en_US --pop3-imap true --privWeb true --smtp true [email protected]
grommunio-admin passwd [email protected]
grommunio-admin user query username maildir pop3_imap smtp privWeb status
  • -u sets the maximum number of users of the domain and is required. Add --create-role if you want a domain administrator role created together with the domain.
  • The domain of the user is taken from the address; the domain must exist. --privWeb, --smtp and --pop3-imap grant login to grommunio Web, sending via SMTP and IMAP/POP3 access. Defaults for these flags can be preset in the Admin UI under Defaults.
  • grommunio-admin passwd prompts for the password; -a generates one.

Expected result: the query lists the user with a maildir path below /var/lib/gromox/user/ and status normal (0). Confirm the credentials without a browser:

Terminal window
grommunio-admin user login [email protected]

Further recipes, including aliases, feature switches and bulk operations, are in Common administration tasks; the complete option lists are in grommunio-admin domain and grommunio-admin user.

Sign in to https://<FQDN>/web/ as [email protected]. An empty Inbox and a working calendar view confirm that the mailbox store, gromox-zcore and PHP are functional.

Next, inject a message on the server itself. This exercises Postfix, the antispam milter and the Gromox local delivery path without depending on DNS or the Internet:

Terminal window
printf 'From: [email protected]\nTo: [email protected]\nSubject: Local delivery test\n\nThis message was injected locally.\n' | sendmail [email protected]
postqueue -p
gromox-mailq
journalctl -u postfix -u gromox-delivery -u gromox-delivery-queue --since "10 minutes ago"

Expected result: the message appears in the Inbox in grommunio Web within seconds, both queues are empty and the journal shows Postfix handing the message to the local transport on port 24 and gromox-delivery storing it. A message that stays in the queue points to a problem in the local chain; see Troubleshooting below and Mail requeueing.

The same queues are visible in the Admin UI under Mail queue, together with flush, requeue and delete actions.

A server can run perfectly and still be unable to exchange mail with the rest of the Internet. Receiving mail requires an MX record; being accepted by other servers requires a matching forward and reverse name, SPF, DKIM and DMARC; Outlook, mobile devices and other clients find the server through AutoDiscover. Publish the following records in the public zone of example.com, replacing the example IP address:

RecordNameValue (example)Purpose
A / AAAAmail.example.compublic IPv4 / IPv6 of the applianceName of the server; must match the certificate and the HELO name
MXexample.com10 mail.example.comInbound delivery
PTRreverse of the public IPmail.example.comReverse DNS; set at the hosting provider; must resolve back to the same IP
A / AAAA or CNAMEautodiscover.example.commail.example.comAutoDiscover for Outlook, EAS devices and other clients
SRV (optional)_autodiscover._tcp.example.com0 0 443 mail.example.comAutoDiscover for clients that use the SRV method
TXTexample.comv=spf1 a mx -allSPF: only hosts in the A and MX records may send for the domain
TXTdkim._domainkey.example.comv=DKIM1; k=rsa; p=<public key>DKIM public key; generated in step 6
TXT_dmarc.example.comv=DMARC1; p=none; rua=mailto:[email protected]DMARC policy and aggregate reports

Notes on the values:

  • The certificate must cover every name clients connect to, at least mail.example.com and autodiscover.example.com. If you chose Let's Encrypt in the wizard, both names must point to the appliance before the certificate can be issued; see TLS configuration and Certificate management.
  • The SPF value above is the one the Admin UI proposes. If outbound mail leaves through a relayhost or a third-party service, add that sender with an include: or ip4: mechanism, otherwise your own mail fails SPF. Use ~all (softfail) while you are still validating, then move to -all.
  • Start DMARC with p=none: receivers report but do not act, and the aggregate reports sent to the rua address tell you whether SPF and DKIM align for all legitimate mail. Tighten to p=quarantine and finally p=reject once the reports are clean for a while. The rua mailbox must exist; create it as a user or alias.
  • The Admin UI additionally checks autoconfig.example.com (Thunderbird-style Mail Autoconfig) and SRV records for _submission, _imaps, _pop3s, _caldavs and _carddavs. They are optional; add them if you want clients to auto-configure without AutoDiscover. See autoconfig(7) and autodiscover(7).
  • Split-horizon setups must publish the autodiscover record in the public view as well; see the AutoDiscover KB article.

Verify from outside the appliance's own network where possible, because your internal resolver may answer differently from the Internet:

Terminal window
dig +short MX example.com
dig +short A mail.example.com
dig +short -x 203.0.113.10
dig +short TXT example.com
dig +short TXT _dmarc.example.com
dig +short SRV _autodiscover._tcp.example.com

The Admin UI performs the same checks: open Domains, select the domain and look at the DNS health section. Each record is queried through the local resolver and through an external resolver, and the reachability check compares the server's detected public IP with the MX target. A new domain shows most items as missing; after publishing, every item you configured should turn green. DNS changes take up to the zone's TTL to propagate.

DKIM signing is done by grommunio-antispam; the key pair is generated per domain from the Admin UI, which also hands you the DNS record to publish.

  1. In the Admin UI, open Domains, select example.com and open the DKIM entry in the DNS health section. On a new domain, the dialog reports that the record dkim._domainkey.example.com is not resolvable and shows a placeholder for the public key.
  2. Click Generate DKIM keypair. Keep Type rsa (ed25519 is offered, but not every receiver verifies it) and Output mode dns for a standard TXT record. Leave Selector empty to use the default selector dkim; if you set another selector, the record name changes accordingly.
  3. Click Generate. The dialog now shows the TXT record for DNS and a list of commands to run on the server.

On the server, the private key is written to /var/lib/grommunio-admin-api/example.com.dkim.key (owner grommunio, mode 0440; the public key is stored alongside with the suffix .pub, and a previous key pair is kept with the suffix .old). Publish only the TXT record; the private key never leaves the server.

The Admin API cannot write into the antispam data directory, so the key must be made available to grommunio-antispam manually. Run the commands shown in the dialog, which correspond to the following (replace example.com):

Terminal window
postconf -e 'non_smtpd_milters = $smtpd_milters'
mkdir -m 0700 /var/lib/grommunio-antispam/dkim
cp /var/lib/grommunio-admin-api/example.com.dkim.key /var/lib/grommunio-antispam/dkim/
chown -Rf groas:grommunio /var/lib/grommunio-antispam/dkim
chmod 600 /var/lib/grommunio-antispam/dkim/example.com.dkim.key
systemctl restart postfix
  • smtpd_milters already points to inet:localhost:11332, but non_smtpd_milters is empty by default. Setting it passes mail that enters Postfix locally (the sendmail command, bounces, notifications) through the same milter as SMTP mail, so that it is signed as well.
  • grommunio-antispam runs as user groas in group grommunio; the key must be readable by that user and by nobody else. If the package already created /var/lib/grommunio-antispam/dkim, mkdir reports that the directory exists; continue with the next command.
  • The signing configuration in /etc/grommunio-antispam/local.d/dkim_signing.conf looks for the key at /var/lib/grommunio-antispam/dkim/$domain.$selector.key with the selector dkim, which is exactly the file name the Admin UI produces. If you chose a different selector in the dialog, rename the copied key to example.com.<selector>.key and change selector in that file accordingly. The default configuration signs mail from authenticated clients and from local senders.
  • Repeat the copy for every additional domain you create; the directory only needs to be created once.

Check the result by sending a message from grommunio Web to an external mailbox and inspecting its headers there: a DKIM-Signature: header with d=example.com; s=dkim must be present and the receiver's Authentication-Results: header must report dkim=pass. A locally delivered message does not prove signing, because it never passes an external verifier.

With DNS and DKIM in place, test the complete path in both directions against a real external mailbox.

Outbound:

  1. In grommunio Web, send a message from [email protected] to the external mailbox.
  2. postqueue -p on the appliance must return an empty queue within a few seconds; journalctl -u postfix --since "5 minutes ago" must show status=sent for the recipient's MX.
  3. At the receiver, open the headers. Authentication-Results: should show spf=pass, dkim=pass and dmarc=pass, and the message must not land in the spam folder.

Inbound:

  1. Reply from the external mailbox to [email protected].
  2. journalctl -u postfix -u gromox-delivery --since "5 minutes ago" must show the connection from the remote MX, the milter verdict and the local delivery.
  3. The reply appears in the Inbox in grommunio Web; the antispam headers added by grommunio-antispam are visible in the message source.

Client access:

Terminal window
PASS='<strong-password>' gromox-dscli -e [email protected]
openssl s_client -connect mail.example.com:993 -servername mail.example.com </dev/null

gromox-dscli performs the AutoDiscover lookup the way a client does and prints the resulting configuration (gromox-dscli(8)); the openssl call shows the certificate chain presented on IMAPS, which must be trusted by your clients and cover the name they connect to. For Outlook specifics, see the Outlook KB article.

Finally, confirm from a network you do not control (a mobile connection, a remote host) that the server is not an open relay: connecting to port 25 and issuing RCPT TO for a foreign domain without authentication must be rejected with 554 5.7.1 Relay access denied. A test from inside your own network says nothing about this.

8. Updates, backup and mailbox maintenance

Section titled “8. Updates, backup and mailbox maintenance”

Treat the appliance like any production Linux mail server: refresh, review, patch in a maintenance window, then re-check the services.

Terminal window
zypper refresh
zypper list-patches
zypper patch
zypper ps -s
systemctl --failed
gromox-mailq

zypper ps -s lists services that still run old binaries after an update and should be restarted. Updates can also be triggered from the Admin UI (Updates tab). Repository types, subscription channels and the full procedure are in Updating grommunio; the reasoning behind the release cadence is in Update Cycle.

Define the backup before the first real mailbox arrives. The artefacts are the mailbox stores under /var/lib/gromox/user/ and /var/lib/gromox/domain/, the MariaDB database grommunio, /etc/grommunio*, the certificates and, from step 6, the DKIM keys. Snapshot-based and file-based approaches are described in Backup & Disaster Recovery; a complete restore procedure including single-mailbox recovery is in Backup and restore. Test the restore, not just the backup.

Gromox ships gromox-cleaner.timer and the one-shot gromox-cleaner.service. The service runs gromox-mbop over every local mailbox, hard-deletes messages that have been soft-deleted for longer than the retention period, and removes attachment files that are no longer referenced by any message (gromox-cleaner.service(8)). Soft-deleted means the message is flagged as deleted and recoverable by the client until it is purged; the cleaner is what finally frees the space. It is not a backup, not an archive and does not empty the Deleted Items folder by itself.

The retention is taken from softdelete_purgetime in /etc/gromox/gromox.cfg; if the directive is not set, the unit falls back to 30d. The timer runs daily, but it is not enabled after installation.

Terminal window
systemctl cat gromox-cleaner.service
systemctl status gromox-cleaner.timer
systemctl list-timers --all | grep gromox-cleaner

Once retention, backup and any archiving requirements are agreed, enable the timer and run one pass by hand:

Terminal window
systemctl enable --now gromox-cleaner.timer
systemctl start gromox-cleaner.service
journalctl -u gromox-cleaner.service --since "10 minutes ago"

Expected result: the service exits successfully and logs the mailboxes it processed; on a fresh system there is nothing to purge. The service requires gromox-http to be running. To also empty the Deleted Items folder of all users after a set time, extend the unit as shown in Mailbox maintenance.

AreaCheckExpected result
Servicessystemctl --failed; services panel on the DashboardNo failed units; all grommunio and Gromox services running
Networkss -tulpn; perimeter firewall rulesListeners on 25, 80, 443, 587, 110/995, 143/993 and the Admin ports; only intended ports reachable from outside
Name resolution and timehostname -f, getent hosts download.grommunio.com, timedatectlFQDN returned; external names resolve; clock synchronised
Repositorieszypper refresh, zypper list-patchesRefresh succeeds; patch list is known and applied in a maintenance window
Admin UIhttps://<FQDN>:8443/Login as admin works over TLS; Dashboard shows versions and services
grommunio Webhttps://<FQDN>/web/Login as the test user works; Inbox and calendar open
Domain and usergrommunio-admin domain list, grommunio-admin user query ..., grommunio-admin user loginDomain active; user has a maildir, status normal, login succeeds
Local deliverysendmail test, postqueue -p, gromox-mailqMessage in Inbox; both queues empty
DNSdig checks; DNS health in the Admin UIMX, A/AAAA, PTR, autodiscover, SPF, DKIM and DMARC resolve externally and match
TLSBrowser, openssl s_client on 443 and 993Trusted chain; certificate covers mail. and autodiscover. names
DKIMHeaders of a message received externallyDKIM-Signature present, dkim=pass
Outbound deliveryMessage to an external mailboxDelivered to Inbox; spf=pass, dkim=pass, dmarc=pass
Inbound deliveryReply from the external mailboxDelivered to the user's Inbox; logged by Postfix and gromox-delivery
RelayRCPT TO a foreign domain from outside, unauthenticatedRejected with Relay access denied
AutoDiscovergromox-dscli -e [email protected]Configuration returned for the mailbox
Rebootsystemctl reboot, then repeat the service and login checksAll services return; Web and Admin UI reachable
Maintenancesystemctl list-timersgromox-cleaner.timer and, with Let's Encrypt, grommunio-certbot-renew.timer scheduled
BackupDocumented procedure, first run completedMail stores, database, /etc/grommunio*, certificates and DKIM keys covered; restore tested

Work from the symptom to the cause: check the service state, read the relevant journal, verify the URL or DNS name, and only then change configuration. Log locations are listed in Troubleshooting; verbose logging options in Debugging messaging services.

SymptomLikely causeWhat to check / fix
zypper refresh fails, repositories unreachableResolver or gateway not configured on the appliancegetent hosts download.grommunio.com, ip route; correct DNS and gateway via the CUI network configuration
Admin UI does not answer on 8443Admin API still served unencrypted on 8080Follow Admin API TLS configuration; nginx -t, systemctl restart nginx
Browser or client rejects the certificateSelf-signed certificate, or autodiscover.example.com missing from the SAN listImport a proper certificate or re-issue it with all names, see Certificate management
Let's Encrypt issuance failed during setupPort 80 not reachable from the Internet, or DNS not yet pointing to the appliance/var/log/grommunio-setup.log; fix DNS/firewall and request the certificate again as shown in TLS configuration
User cannot log in to grommunio WebWrong password, privWeb not set, or user status not normalgrommunio-admin user login, grommunio-admin user query username privWeb status, grommunio-admin passwd
Local test mail never reaches the InboxMessage stuck in Postfix or in the Gromox queue; gromox-delivery or gromox-http not runningpostqueue -p, gromox-mailq, journalctl -u postfix -u gromox-delivery -u gromox-delivery-queue; Mail requeueing
Outbound mail rejected or filed as spamMissing or mismatching PTR, SPF failure, no DKIM signature, dynamic or listed IP addressDNS health in the Admin UI; Authentication-Results at the receiver; dig -x on the public IP; check the IP against common blocklists
No DKIM-Signature header on outgoing mailKey not readable by groas, key file name does not match <domain>.<selector>.key, or locally submitted mail bypasses the milterRepeat the commands from step 6; ls -l /var/lib/grommunio-antispam/dkim/; postconf non_smtpd_milters; journalctl -u grommunio-antispam
Mail from the Internet never arrivesMX record wrong, port 25 blocked by the provider or firewall, or domain not created in grommuniodig MX example.com; ss -tulpn for port 25; journalctl -u postfix; grommunio-admin domain list
Outlook or mobile device cannot auto-configureautodiscover record missing in the public zone, or certificate does not cover the namegromox-dscli -e [email protected]; autodiscover(7); Outlook KB
Login or TLS errors after a reboot, timestamps wrongTime not synchronisedtimedatectl; configure NTP via the CUI timesync dialog
gromox-cleaner.service fails to startgromox-http not running (the unit requires it)systemctl status gromox-http; then systemctl start gromox-cleaner.service
  • Logs: all grommunio and Gromox services log to the journal (journalctl -u <unit>); nginx and the PHP services for Web, Sync and DAV write to files under /var/log/nginx/, /var/log/grommunio-sync/ and /var/log/grommunio-dav/. The Admin UI exposes the journals under Logs.
  • Queues: watch postqueue -p and gromox-mailq, or the Mail queue view in the Admin UI. A growing queue is the earliest sign of a delivery problem.
  • Certificates: with Let's Encrypt, grommunio-certbot-renew.timer renews weekly; port 80 must stay reachable. With imported certificates, track the expiry date yourself and restart the services after replacing the files.
  • Monitoring: service state, queue length, disk usage of /var/lib/gromox, certificate expiry and the DMARC aggregate reports are the minimum set to watch.
  • Firewall: firewalld on the appliance opens every service port after setup. Keep the Admin ports (8080/8443) restricted to administrative networks, on the host firewall (firewall-cmd --remove-port=8080/tcp --zone=public --permanent, then firewall-cmd --reload, once the TLS switch is done) and on the perimeter, and expose only 25, 80, 443, 587 and the IMAP/POP3 ports you need.