Skip to content
English

Container Installation

Besides the grommunio Appliance and a manual installation, grommunio can be run in containers. The official, authoritative project for this is grommunio/gromox-container — a Docker Compose deployment that packages the groupware into a small number of containers managed by supervisord, based on openSUSE Leap 16.0 with MariaDB 11.

The stack is split into a core container plus optional add-on containers, each backed by its own MariaDB database, all on a private Docker network:

  • gromox-core — the main container running all core groupware services (nginx, Postfix, the gromox-* daemons, Admin API, antispam, Redis, …) under supervisord.
  • gromox-archive (optional) — e-mail archiving with full-text search.
  • gromox-office (optional) — document editing and file sync.
  • gromox-db / chat-db / files-db / office-db / archive-db — MariaDB databases for the respective components.

All service containers run unprivileged — no privileged: true, no SYS_ADMIN, no special runtimes. Internal ports are remapped above 1024 and the host ports are mapped back to the standard ones (see Port mapping).

You need a host with Docker and the Docker Compose plugin, a fully qualified domain name (FQDN) pointing at the host, and the standard mail/web ports free.

  1. Get the project

    Terminal window
    git clone https://github.com/grommunio/gromox-container.git
    cd gromox-container
  2. Configure the environment — copy the example and edit it with your domain, passwords and feature flags:

    Terminal window
    cp var.env.example var.env
    $EDITOR var.env

    At minimum set FQDN, DOMAIN and ADMIN_PASS (see Configuration).

  3. Prepare the bind-mounted volumes (or run ./pre-launch.sh, which does this for you):

    Terminal window
    mkdir -p variables_data gromox_letsencrypt
    cp var.env variables_data/var.env
  4. Start the stack:

    Terminal window
    docker compose up -d

    The first start takes several minutes while each container initializes its databases, generates certificates and configures its services.

Once the stack is up, sign in to the Admin UI with the user admin and the password from ADMIN_PASS:

ServiceURL
Webmail (grommunio Web)https://<FQDN>
Admin UIhttps://<FQDN>:8443
Exchange ActiveSynchttps://<FQDN>/Microsoft-Server-ActiveSync
CalDAV / CardDAVhttps://<FQDN>/dav
Files (if enabled)https://<FQDN>/files
Archive (if enabled)https://<FQDN>/archive

gromox-core runs the full set of groupware services under supervisord:

ServiceDescription
nginxReverse proxy (web, admin, sync, DAV)
postfixMail transport agent
gromox-httpHTTP / MAPI / AutoDiscover
gromox-imap / gromox-pop3IMAP / POP3 servers
gromox-delivery / gromox-delivery-queueLocal delivery + queue
gromox-zcorePHP-MAPI core
gromox-midbMessage index database
gromox-event / gromox-timerEvent bus / scheduled tasks
grommunio-admin-apiAdmin REST API (uWSGI)
grommunio-antispamSpam filtering (rspamd)
grommunio-chat (optional)Messaging
php-fpmPHP FastCGI
redisCache / session store
saslauthdSMTP authentication
crondScheduled tasks (certbot renewal, …)

The optional gromox-archive container adds grommunio-archive, grommunio-archive-smtp and a Sphinx searchd; gromox-office adds the document-service and converter daemons plus RabbitMQ.

All configuration is done through environment variables in var.env.

VariableDescriptionExample
FQDNServer fully qualified domain namemail.example.com
DOMAINMail domainexample.com
ADMIN_PASSgrommunio admin passwordSecurePassword123
MYSQL_HOSTDatabase host for the coregromox-db
MYSQL_USER / MYSQL_PASS / MYSQL_DBCore DB credentials / namegrommunio
VariableDescriptionDefault
SSL_INSTALL_TYPE0 = self-signed, 2 = Let's Encrypt0
SSL_BUNDLE / SSL_KEYPaths to your own certificate + key
SSL_EMAILE-mail for Let's Encrypt notificationsadmin@DOMAIN

With Let's Encrypt (SSL_INSTALL_TYPE=2), certbot runs on first start and a cron job renews every 12 hours; port 80 must be reachable from the internet. If Let's Encrypt provisioning fails, the stack falls back to a self-signed certificate so services still come up.

Each add-on is toggled with an ENABLE_* flag and configured with its own database credentials:

ComponentEnable flagExtra variables
Chat(starts if CHAT_CONFIG exists)CHAT_MYSQL_*, CHAT_ADMIN_PASS, CHAT_CONFIG
FilesENABLE_FILES=trueFILES_MYSQL_*, FILES_ADMIN_PASS
OfficeENABLE_OFFICE=trueOFFICE_HOST, OFFICE_MYSQL_*
ArchiveENABLE_ARCHIVE=trueARCHIVE_HOST, ARCHIVE_MYSQL_*, ARCHIVE_INDEXER_*_INTERVAL
Keycloak SSOENABLE_KEYCLOAK=trueKEYCLOAK_REALM, KEYCLOAK_URL, KEYCLOAK_CLIENT_ID, KEYCLOAK_CLIENT_SECRET
VariableDescriptionDefault
RELAYHOSTSMTP relay host for outbound mail(empty)
ORGANIZATIONOrganization name for AutoDiscover
TIMEZONEContainer timezoneEurope/Vienna
FORCE_RECONFIGRe-run the setup scripts on next restartfalse
CLEAR_DBSDrop and recreate databases on startup (needs MYSQL_ROOT_PASS)false
X500X.500 organization identifier (auto-generated if empty)

Internal ports are all above 1024 (so containers need no privileges); the host maps them back to the standard ports:

Host portContainer portService
252525SMTP (Postfix inbound)
808080HTTP (Let's Encrypt challenge, HTTP→HTTPS redirect)
4438443HTTPS (webmail, sync, DAV, files, office, archive)
4652465SMTPS (implicit TLS)
5872587Submission (authenticated)
9932993IMAPS
1432143IMAP (STARTTLS)
9952995POP3S
1102110POP3 (STARTTLS)
84439443Admin Web UI

Named volumes hold all state, so containers can be rebuilt without data loss. The most important ones to back up:

VolumeMount pointPurpose
gromox/var/lib/gromoxMailbox data
gromox_config/etc/gromoxGromox configuration
cert_data/etc/grommunio-common/sslTLS certificates (shared)
gromox_mysql_dataMariaDB dataCore database
*_mysql_dataMariaDB dataChat / Files / Office / Archive databases
gromox_letsencrypt/etc/letsencryptLet's Encrypt state

The services inside a container are managed with supervisorctl:

Terminal window
# Status of all services in the core container
docker exec gromox-core supervisorctl status
# Restart a single service
docker exec gromox-core supervisorctl restart nginx
# Per-service logs
docker exec gromox-core tail -f /var/log/supervisor-nginx.log
docker exec gromox-core cat /var/log/grommunio-setup.log # initial setup log

The setup scripts run only once (guarded by marker files). To re-apply changes:

Terminal window
echo "FORCE_RECONFIG=true" >> variables_data/var.env
docker compose restart gromox-core

Back up the database and data volumes, for example:

Terminal window
docker run --rm -v gromox_mysql_data:/data -v "$(pwd)/backup:/backup" \
busybox tar czf /backup/gromox-db.tar.gz /data
docker run --rm -v gromox:/data -v "$(pwd)/backup:/backup" \
busybox tar czf /backup/gromox-data.tar.gz /data
docker run --rm -v gromox_config:/data -v "$(pwd)/backup:/backup" \
busybox tar czf /backup/gromox-config.tar.gz /data
Terminal window
git pull
docker compose build
docker compose up -d

The container images apply current TLS hardening out of the box:

  • Postfix (25/587): the legacy and DH-family ciphers are excluded (aNULL, eNULL, EXP, MD5, RC4, DES, 3DES, DHE, EDH, kDHE, kEDH, ADH) while the forward-secret ECDHE suites are kept (smtpd_tls_eecdh_grade = strong); SSLv2/SSLv3 and TLS 1.0/1.1 are disabled. Excluding only the DH family mitigates CVE-2002-20001 (a DHE-only key-exchange denial of service) without sacrificing forward secrecy.
  • Gromox http / imap / pop3: tls_min_proto = tls1.2 — SSLv3 and TLS 1.0/1.1 are disabled, with TLS 1.2 as the floor. (993/995 are client-facing with no proxy in front, so a TLS 1.3 floor would lock out TLS-1.2-only mail clients such as older Thunderbird, mobile and Outlook builds.)
  • All containers run unprivileged.

For production, additionally place the deployment behind a firewall, use Let's Encrypt or your own CA-signed certificates, and keep the images up to date.

Terminal window
docker compose ps # container + database health
docker compose logs gromox-core
# a service stuck in FATAL — read its error log:
docker exec gromox-core cat /var/log/supervisor-<service>-err.log

Common causes: a missing FQDN/DOMAIN in var.env (Postfix fails), missing OFFICE_MYSQL_* (document service fails), or grommunio Files rejecting a self-signed certificate — use Let's Encrypt, or add the host to Files' trusted domains. See the project's README troubleshooting section for details.