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.
Architecture
Section titled “Architecture”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).
Quick start
Section titled “Quick start”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.
-
Get the project
Terminal window git clone https://github.com/grommunio/gromox-container.gitcd gromox-container -
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.envAt minimum set
FQDN,DOMAINandADMIN_PASS(see Configuration). -
Prepare the bind-mounted volumes (or run
./pre-launch.sh, which does this for you):Terminal window mkdir -p variables_data gromox_letsencryptcp var.env variables_data/var.env -
Start the stack:
Terminal window docker compose up -dThe first start takes several minutes while each container initializes its databases, generates certificates and configures its services.
Accessing the services
Section titled “Accessing the services”Once the stack is up, sign in to the Admin UI with the user admin and the
password from ADMIN_PASS:
| Service | URL |
|---|---|
| Webmail (grommunio Web) | https://<FQDN> |
| Admin UI | https://<FQDN>:8443 |
| Exchange ActiveSync | https://<FQDN>/Microsoft-Server-ActiveSync |
| CalDAV / CardDAV | https://<FQDN>/dav |
| Files (if enabled) | https://<FQDN>/files |
| Archive (if enabled) | https://<FQDN>/archive |
Services in the core container
Section titled “Services in the core container”gromox-core runs the full set of groupware services under supervisord:
| Service | Description |
|---|---|
nginx |
Reverse proxy (web, admin, sync, DAV) |
postfix |
Mail transport agent |
gromox-http |
HTTP / MAPI / AutoDiscover |
gromox-imap / gromox-pop3 |
IMAP / POP3 servers |
gromox-delivery / gromox-delivery-queue |
Local delivery + queue |
gromox-zcore |
PHP-MAPI core |
gromox-midb |
Message index database |
gromox-event / gromox-timer |
Event bus / scheduled tasks |
grommunio-admin-api |
Admin REST API (uWSGI) |
grommunio-antispam |
Spam filtering (rspamd) |
grommunio-chat (optional) |
Messaging |
php-fpm |
PHP FastCGI |
redis |
Cache / session store |
saslauthd |
SMTP authentication |
crond |
Scheduled 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.
Configuration
Section titled “Configuration”All configuration is done through environment variables in var.env.
Required
Section titled “Required”| Variable | Description | Example |
|---|---|---|
FQDN |
Server fully qualified domain name | mail.example.com |
DOMAIN |
Mail domain | example.com |
ADMIN_PASS |
grommunio admin password | SecurePassword123 |
MYSQL_HOST |
Database host for the core | gromox-db |
MYSQL_USER / MYSQL_PASS / MYSQL_DB |
Core DB credentials / name | grommunio |
TLS certificates
Section titled “TLS certificates”| Variable | Description | Default |
|---|---|---|
SSL_INSTALL_TYPE |
0 = self-signed, 2 = Let's Encrypt |
0 |
SSL_BUNDLE / SSL_KEY |
Paths to your own certificate + key | |
SSL_EMAIL |
E-mail for Let's Encrypt notifications | admin@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.
Optional components
Section titled “Optional components”Each add-on is toggled with an ENABLE_* flag and configured with its own
database credentials:
| Component | Enable flag | Extra variables |
|---|---|---|
| Chat | (starts if CHAT_CONFIG exists) |
CHAT_MYSQL_*, CHAT_ADMIN_PASS, CHAT_CONFIG |
| Files | ENABLE_FILES=true |
FILES_MYSQL_*, FILES_ADMIN_PASS |
| Office | ENABLE_OFFICE=true |
OFFICE_HOST, OFFICE_MYSQL_* |
| Archive | ENABLE_ARCHIVE=true |
ARCHIVE_HOST, ARCHIVE_MYSQL_*, ARCHIVE_INDEXER_*_INTERVAL |
| Keycloak SSO | ENABLE_KEYCLOAK=true |
KEYCLOAK_REALM, KEYCLOAK_URL, KEYCLOAK_CLIENT_ID, KEYCLOAK_CLIENT_SECRET |
Advanced
Section titled “Advanced”| Variable | Description | Default |
|---|---|---|
RELAYHOST |
SMTP relay host for outbound mail | (empty) |
ORGANIZATION |
Organization name for AutoDiscover | |
TIMEZONE |
Container timezone | Europe/Vienna |
FORCE_RECONFIG |
Re-run the setup scripts on next restart | false |
CLEAR_DBS |
Drop and recreate databases on startup (needs MYSQL_ROOT_PASS) |
false |
X500 |
X.500 organization identifier (auto-generated if empty) |
Port mapping
Section titled “Port mapping”Internal ports are all above 1024 (so containers need no privileges); the host maps them back to the standard ports:
| Host port | Container port | Service |
|---|---|---|
| 25 | 2525 | SMTP (Postfix inbound) |
| 80 | 8080 | HTTP (Let's Encrypt challenge, HTTP→HTTPS redirect) |
| 443 | 8443 | HTTPS (webmail, sync, DAV, files, office, archive) |
| 465 | 2465 | SMTPS (implicit TLS) |
| 587 | 2587 | Submission (authenticated) |
| 993 | 2993 | IMAPS |
| 143 | 2143 | IMAP (STARTTLS) |
| 995 | 2995 | POP3S |
| 110 | 2110 | POP3 (STARTTLS) |
| 8443 | 9443 | Admin Web UI |
Persistent data (volumes)
Section titled “Persistent data (volumes)”Named volumes hold all state, so containers can be rebuilt without data loss. The most important ones to back up:
| Volume | Mount point | Purpose |
|---|---|---|
gromox |
/var/lib/gromox |
Mailbox data |
gromox_config |
/etc/gromox |
Gromox configuration |
cert_data |
/etc/grommunio-common/ssl |
TLS certificates (shared) |
gromox_mysql_data |
MariaDB data | Core database |
*_mysql_data |
MariaDB data | Chat / Files / Office / Archive databases |
gromox_letsencrypt |
/etc/letsencrypt |
Let's Encrypt state |
Operations
Section titled “Operations”The services inside a container are managed with supervisorctl:
# Status of all services in the core containerdocker exec gromox-core supervisorctl status
# Restart a single servicedocker exec gromox-core supervisorctl restart nginx
# Per-service logsdocker exec gromox-core tail -f /var/log/supervisor-nginx.logdocker exec gromox-core cat /var/log/grommunio-setup.log # initial setup logReconfiguring after var.env changes
Section titled “Reconfiguring after var.env changes”The setup scripts run only once (guarded by marker files). To re-apply changes:
echo "FORCE_RECONFIG=true" >> variables_data/var.envdocker compose restart gromox-coreBackup
Section titled “Backup”Back up the database and data volumes, for example:
docker run --rm -v gromox_mysql_data:/data -v "$(pwd)/backup:/backup" \ busybox tar czf /backup/gromox-db.tar.gz /datadocker run --rm -v gromox:/data -v "$(pwd)/backup:/backup" \ busybox tar czf /backup/gromox-data.tar.gz /datadocker run --rm -v gromox_config:/data -v "$(pwd)/backup:/backup" \ busybox tar czf /backup/gromox-config.tar.gz /dataUpdating
Section titled “Updating”git pulldocker compose builddocker compose up -dSecurity
Section titled “Security”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.
Troubleshooting
Section titled “Troubleshooting”docker compose ps # container + database healthdocker compose logs gromox-core# a service stuck in FATAL — read its error log:docker exec gromox-core cat /var/log/supervisor-<service>-err.logCommon 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.