diff --git a/.env b/.env
deleted file mode 120000
index 9400869..0000000
--- a/.env
+++ /dev/null
@@ -1 +0,0 @@
-mailcow.conf
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 5e05448..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,85 +0,0 @@
-!data/conf/nginx/dynmaps.conf
-!data/conf/nginx/meta_exporter.conf
-!data/conf/nginx/site.conf
-!/**/.gitkeep
-*.iml
-.idea
-.vscode/*
-data/assets/ssl-example/*
-data/assets/ssl/*
-data/conf/borgmatic/
-data/conf/clamav/whitelist.ign2
-data/conf/dovecot/acl_anyone
-data/conf/dovecot/dovecot-master.passwd
-data/conf/dovecot/dovecot-master.userdb
-data/conf/dovecot/extra.conf
-data/conf/dovecot/mail_replica.conf
-data/conf/dovecot/global_sieve_*
-data/conf/dovecot/last_login
-data/conf/dovecot/lua
-data/conf/dovecot/mail_plugins*
-data/conf/dovecot/shared_namespace.conf
-data/conf/dovecot/sni.conf
-data/conf/dovecot/sogo-sso.conf
-data/conf/dovecot/sogo_trusted_ip.conf
-data/conf/dovecot/sql
-data/conf/dovecot/conf.d/fts.conf
-data/conf/nextcloud-*.bak
-data/conf/nginx/*.active
-data/conf/nginx/*.bak
-data/conf/nginx/*.conf
-data/conf/nginx/*.custom
-data/conf/phpfpm/sogo-sso/sogo-sso.pass
-data/conf/portainer/
-data/conf/postfix/allow_mailcow_local.regexp
-data/conf/postfix/custom_postscreen_whitelist.cidr
-data/conf/postfix/custom_transport.pcre
-data/conf/postfix/extra.cf
-data/conf/postfix/sni.map
-data/conf/postfix/sni.map.db
-data/conf/postfix/sql
-data/conf/postfix/dns_blocklists.cf
-data/conf/postfix/dnsbl_reply.map
-data/conf/rspamd/custom/*
-data/conf/rspamd/local.d/*
-data/conf/rspamd/override.d/*
-data/conf/sogo/custom-theme.js
-data/conf/sogo/plist_ldap
-data/conf/sogo/plist_ldap.sh
-data/conf/sogo/sieve.creds
-data/conf/sogo/cron.creds
-data/conf/sogo/custom-fulllogo.svg
-data/conf/sogo/custom-shortlogo.svg
-data/conf/sogo/custom-fulllogo.png
-data/gitea/
-data/gogs/
-data/hooks/dovecot/*
-data/hooks/phpfpm/*
-data/hooks/postfix/*
-data/hooks/rspamd/*
-data/hooks/sogo/*
-data/hooks/unbound/*
-data/web/templates/cache/*
-!data/web/templates/cache/.gitkeep
-data/web/.well-known/acme-challenge
-data/web/css/build/0081-custom-mailcow.css
-data/web/inc/vars.local.inc.php
-data/web/inc/app_info.inc.php
-data/web/nextcloud*/
-data/web/rc*/
-docker-compose.override.yml
-mailcow.conf
-mailcow.conf_backup
-rebuild-images.sh
-refresh_images.sh
-update_diffs/
-create_cold_standby.sh
-!data/conf/nginx/mailcow_auth.conf
-data/conf/postfix/postfix-tlspol
-.github
-data
-helper-scripts
-scripts
-.editorconfig
-CODE_OF_CONDUCT.md
-CONTRIBUTING.md
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..791be1f
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
deleted file mode 100644
index 40288f1..0000000
--- a/README.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# mailcow: dockerized - 🐮 + 🐋 = 💕
-
-[](https://translate.mailcow.email/engage/mailcow-dockerized/)
-[](https://twitter.com/mailcow_email)
-
-
-
-## Want to support mailcow?
-
-Please [consider a support contract with Servercow](https://www.servercow.de/mailcow?lang=en#support) to support further development. _We_ support _you_ while _you_ support _us_. :)
-
-You can also [get a SAL](https://www.servercow.de/mailcow?lang=en#sal) which is a one-time payment with no liabilities or returning fees.
-
-Or just spread the word: moo.
-
-## Many thanks to our GitHub Sponsors ❤️
-A big thank you to everyone supporting us on GitHub Sponsors—your contributions mean the world to us! Special thanks to the following amazing supporters:
-
-### 100$/Month Sponsors
-
-
-
-### 50$/Month Sponsors
-
-
-## Info, documentation and support
-
-Please see [the official documentation](https://docs.mailcow.email/) for installation and support instructions. 🐄
-
-🐛 **If you found a critical security issue, please mail us to [info at servercow.de](mailto:info@servercow.de).**
-
-## Cowmunity
-
-[mailcow community](https://community.mailcow.email)
-
-[Telegram mailcow channel](https://telegram.me/mailcow)
-
-[Telegram mailcow Off-Topic channel](https://t.me/mailcowOfftopic)
-
-[Official 𝕏 (Twitter) Account](https://twitter.com/mailcow_email)
-
-[Official Mastodon Account](https://mailcow.social/@doncow)
-
-Telegram desktop clients are available for [multiple platforms](https://desktop.telegram.org). You can search the groups history for keywords.
-
-## Misc
-
-**Important**: mailcow makes use of various open-source software. Please assure you agree with their license before using mailcow.
-Any part of mailcow itself is released under **GNU General Public License, Version 3**.
-
-mailcow is a registered word mark of The Infrastructure Company GmbH, Parkstr. 42, 47877 Willich, Germany.
-
-The project is managed and maintained by The Infrastructure Company GmbH.
-
-Originated from @andryyy (André)
diff --git a/SECURITY.md b/SECURITY.md
deleted file mode 100644
index de63ca3..0000000
--- a/SECURITY.md
+++ /dev/null
@@ -1,42 +0,0 @@
-# Security Policies and Procedures
-
-This document outlines security procedures and general policies for the _mailcow: dockerized_ project as found on [mailcow-dockerized](https://github.com/mailcow/mailcow-dockerized).
-
- * [Reporting a Vulnerability](#reporting-a-vulnerability)
- * [Disclosure Policy](#disclosure-policy)
- * [Comments on this Policy](#comments-on-this-policy)
-
-## Reporting a Vulnerability
-
-The mailcow team and community take all security vulnerabilities
-seriously. Thank you for improving the security of our open source
-software. We appreciate your efforts and responsible disclosure and will
-make every effort to acknowledge your contributions.
-
-Report security vulnerabilities by emailing the mailcow team at:
-
- info at servercow.de
-
-mailcow team will acknowledge your email as soon as possible, and will
-send a more detailed response afterwards indicating the next steps in
-handling your report. After the initial reply to your report, the mailcow
-team will endeavor to keep you informed of the progress towards a fix and
-full announcement, and may ask for additional information or guidance.
-
-Report security vulnerabilities in third-party modules to the person or
-team maintaining the module.
-
-## Disclosure Policy
-
-When the mailcow team receives a security bug report, they will assign it
-to a primary handler. This person will coordinate the fix and release
-process, involving the following steps:
-
- * Confirm the problem and determine the affected versions.
- * Audit code to find any potential similar problems.
- * Prepare fixes for all releases still under maintenance.
-
-## Comments on this Policy
-
-If you have suggestions on how this process could be improved please submit a
-pull request.
diff --git a/coolify.md b/coolify.md
deleted file mode 100644
index 6c70231..0000000
--- a/coolify.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# Deploying mailcow-dockerized with Coolify + Traefik
-
-This repository ships the upstream `mailcow-dockerized` stack plus a single Coolify-ready compose file (`docker-compose.coolify.yml`) that already contains the Traefik wiring for `mail.karmacoma.dev`. Mail protocols (SMTP/IMAP/POP3/Sieve) stay bound directly on the host; only HTTP/HTTPS are proxied by Traefik.
-
-Official docs to keep handy:
-- mailcow: https://docs.mailcow.email/
-- Reverse proxy notes (mailcow): https://docs.mailcow.email/post_installation/reverse-proxy/
-- Coolify: https://docs.coolify.io/
-
-## Prerequisites
-- DNS already points `mail.karmacoma.dev` A/AAAA and MX to this host; PTR records match.
-- Host firewall allows TCP 25, 465, 587, 993, 995, 143, 110, 4190 and UDP/TCP 53 for DNS resolver traffic. Ports 80/443 stay open but will be used by Traefik.
-- Coolify is running with its built-in Traefik proxy. Note the proxy network name (UI: Infrastructure → Networks or `docker network ls`), typically `coolify-proxy`.
-
-## Prepare configuration
-1. From the repo root, generate the base config if you have not already:
- ```sh
- ./generate_config.sh
- ```
-2. Edit `mailcow.conf`:
- - `MAILCOW_HOSTNAME=mail.karmacoma.dev`
- - Leave `HTTP_PORT=80` and `HTTPS_PORT=443` (Traefik attaches via Docker network, not host binds).
- - Ensure `HTTP_REDIRECT=n` so ACME HTTP-01 works through Traefik.
- - Keep `SKIP_LETS_ENCRYPT=n` so mailcow issues its own cert for mail protocols.
- - Optionally set `TRUSTED_PROXIES=172.16.0.0/12` (defaulted in the compose) to trust Coolify's proxy IP range.
-3. Create a small `.env` (or set in Coolify) for the Traefik network if the default differs:
- ```sh
- echo "TRAEFIK_NETWORK=coolify-proxy" > .env
- ```
-
-## Coolify deployment steps
-1. Add a new **Docker Compose** service in Coolify pointing to this repository/branch.
-2. Compose file: select only `docker-compose.coolify.yml` (it already includes the upstream stack plus Traefik labels/network).
-3. Environment file: point Coolify to `mailcow.conf` (and `.env` if you created one), or copy its contents into the UI env editor.
-4. No additional ports need to be declared for HTTP/HTTPS—Traefik handles routing. Mail ports remain published as defined in the compose.
-5. Deploy. First start will pull all mailcow images and generate certificates in `data/assets/ssl`.
-
-## Routing behavior
-- Traefik forwards HTTP on entrypoint `web` to `nginx-mailcow` port 80 and enforces an HTTPS redirect.
-- Traefik passes through TLS on entrypoint `websecure` to `nginx-mailcow` port 443 so mailcow presents its own certificate (also used by Postfix/Dovecot/SOGo).
-- Other mail protocols continue to bind to the host as defined in the compose.
-
-## Post-deploy checks
-- Browse https://mail.karmacoma.dev and ensure the UI loads through Traefik.
-- Verify certificates exist in `data/assets/ssl/` and that Postfix/Dovecot advertise the correct hostname.
-- Send/receive a test message and confirm DNSBL lookups work (unbound container must resolve outbound DNS).
-
-If you need to adjust anything later, edit `mailcow.conf` or tweak `docker-compose.coolify.yml` and redeploy from Coolify.
diff --git a/docker-compose.coolify.yml b/docker-compose.coolify.yml
deleted file mode 100644
index 43fc12f..0000000
--- a/docker-compose.coolify.yml
+++ /dev/null
@@ -1,696 +0,0 @@
-services:
-
- unbound-mailcow:
- image: ghcr.io/mailcow/unbound:1.24
- environment:
- - TZ=${TZ}
- - SKIP_UNBOUND_HEALTHCHECK=${SKIP_UNBOUND_HEALTHCHECK:-n}
- volumes:
- - ./data/hooks/unbound:/hooks:Z
- - ./data/conf/unbound/unbound.conf:/etc/unbound/unbound.conf:ro,Z
- restart: always
- tty: true
- networks:
- mailcow-network:
- ipv4_address: ${IPV4_NETWORK:-172.22.1}.254
- aliases:
- - unbound
-
- mysql-mailcow:
- image: mariadb:10.11
- depends_on:
- - unbound-mailcow
- - netfilter-mailcow
- stop_grace_period: 45s
- volumes:
- - mysql-vol-1:/var/lib/mysql/
- - mysql-socket-vol-1:/var/run/mysqld/:z
- - ./data/conf/mysql/:/etc/mysql/conf.d/:ro,Z
- environment:
- - TZ=${TZ}
- - MYSQL_ROOT_PASSWORD=${DBROOT}
- - MYSQL_DATABASE=${DBNAME}
- - MYSQL_USER=${DBUSER}
- - MYSQL_PASSWORD=${DBPASS}
- - MYSQL_INITDB_SKIP_TZINFO=1
- restart: always
- ports:
- - "${SQL_PORT:-127.0.0.1:13306}:3306"
- networks:
- mailcow-network:
- aliases:
- - mysql
-
- redis-mailcow:
- image: redis:7.4.6-alpine
- entrypoint: ["/bin/sh","/redis-conf.sh"]
- volumes:
- - redis-vol-1:/data/
- - ./data/conf/redis/redis-conf.sh:/redis-conf.sh:z
- restart: always
- depends_on:
- - netfilter-mailcow
- ports:
- - "${REDIS_PORT:-127.0.0.1:7654}:6379"
- environment:
- - TZ=${TZ}
- - REDISPASS=${REDISPASS}
- - REDISMASTERPASS=${REDISMASTERPASS:-}
- sysctls:
- - net.core.somaxconn=4096
- networks:
- mailcow-network:
- ipv4_address: ${IPV4_NETWORK:-172.22.1}.249
- aliases:
- - redis
-
- clamd-mailcow:
- image: ghcr.io/mailcow/clamd:1.71
- restart: always
- depends_on:
- unbound-mailcow:
- condition: service_healthy
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- environment:
- - TZ=${TZ}
- - SKIP_CLAMD=${SKIP_CLAMD:-n}
- volumes:
- - ./data/conf/clamav/:/etc/clamav/:Z
- - clamd-db-vol-1:/var/lib/clamav
- networks:
- mailcow-network:
- aliases:
- - clamd
-
- rspamd-mailcow:
- image: ghcr.io/mailcow/rspamd:2.4
- stop_grace_period: 30s
- depends_on:
- - dovecot-mailcow
- - clamd-mailcow
- environment:
- - TZ=${TZ}
- - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- - IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-}
- volumes:
- - ./data/hooks/rspamd:/hooks:Z
- - ./data/conf/rspamd/custom/:/etc/rspamd/custom:z
- - ./data/conf/rspamd/override.d/:/etc/rspamd/override.d:Z
- - ./data/conf/rspamd/local.d/:/etc/rspamd/local.d:Z
- - ./data/conf/rspamd/plugins.d/:/etc/rspamd/plugins.d:Z
- - ./data/conf/rspamd/lua/:/etc/rspamd/lua/:ro,Z
- - ./data/conf/rspamd/rspamd.conf.local:/etc/rspamd/rspamd.conf.local:Z
- - ./data/conf/rspamd/rspamd.conf.override:/etc/rspamd/rspamd.conf.override:Z
- - rspamd-vol-1:/var/lib/rspamd
- restart: always
- hostname: rspamd
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- networks:
- mailcow-network:
- aliases:
- - rspamd
-
- php-fpm-mailcow:
- image: ghcr.io/mailcow/phpfpm:8.2.29
- command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
- depends_on:
- - redis-mailcow
- volumes:
- - ./data/hooks/phpfpm:/hooks:Z
- - ./data/web:/web:z
- - ./data/conf/rspamd/dynmaps:/dynmaps:ro,z
- - ./data/conf/rspamd/custom/:/rspamd_custom_maps:z
- - ./data/conf/dovecot/auth/mailcowauth.php:/mailcowauth/mailcowauth.php:z
- - ./data/web/inc/functions.inc.php:/mailcowauth/functions.inc.php:z
- - ./data/web/inc/functions.auth.inc.php:/mailcowauth/functions.auth.inc.php:z
- - ./data/web/inc/sessions.inc.php:/mailcowauth/sessions.inc.php:z
- - ./data/web/inc/functions.mailbox.inc.php:/mailcowauth/functions.mailbox.inc.php:z
- - ./data/web/inc/functions.ratelimit.inc.php:/mailcowauth/functions.ratelimit.inc.php:z
- - ./data/web/inc/functions.acl.inc.php:/mailcowauth/functions.acl.inc.php:z
- - rspamd-vol-1:/var/lib/rspamd
- - mysql-socket-vol-1:/var/run/mysqld/:z
- - ./data/conf/sogo/:/etc/sogo/:z
- - ./data/conf/rspamd/meta_exporter:/meta_exporter:ro,z
- - ./data/conf/phpfpm/crons:/crons:z
- - ./data/conf/phpfpm/sogo-sso/:/etc/sogo-sso/:z
- - ./data/conf/phpfpm/php-fpm.d/pools.conf:/usr/local/etc/php-fpm.d/z-pools.conf:Z
- - ./data/conf/phpfpm/php-conf.d/opcache-recommended.ini:/usr/local/etc/php/conf.d/opcache-recommended.ini:Z
- - ./data/conf/phpfpm/php-conf.d/upload.ini:/usr/local/etc/php/conf.d/upload.ini:Z
- - ./data/conf/phpfpm/php-conf.d/other.ini:/usr/local/etc/php/conf.d/zzz-other.ini:Z
- - ./data/conf/dovecot/global_sieve_before:/global_sieve/before:z
- - ./data/conf/dovecot/global_sieve_after:/global_sieve/after:z
- - ./data/assets/templates:/tpls:z
- - ./data/conf/nginx/:/etc/nginx/conf.d/:z
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- environment:
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - LOG_LINES=${LOG_LINES:-9999}
- - TZ=${TZ}
- - DBNAME=${DBNAME}
- - DBUSER=${DBUSER}
- - DBPASS=${DBPASS}
- - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- - MAILCOW_PASS_SCHEME=${MAILCOW_PASS_SCHEME:-BLF-CRYPT}
- - IMAP_PORT=${IMAP_PORT:-143}
- - IMAPS_PORT=${IMAPS_PORT:-993}
- - POP_PORT=${POP_PORT:-110}
- - POPS_PORT=${POPS_PORT:-995}
- - SIEVE_PORT=${SIEVE_PORT:-4190}
- - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- - IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
- - SUBMISSION_PORT=${SUBMISSION_PORT:-587}
- - SMTPS_PORT=${SMTPS_PORT:-465}
- - SMTP_PORT=${SMTP_PORT:-25}
- - API_KEY=${API_KEY:-invalid}
- - API_KEY_READ_ONLY=${API_KEY_READ_ONLY:-invalid}
- - API_ALLOW_FROM=${API_ALLOW_FROM:-invalid}
- - COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
- - SKIP_FTS=${SKIP_FTS:-y}
- - SKIP_CLAMD=${SKIP_CLAMD:-n}
- - SKIP_OLEFY=${SKIP_OLEFY:-n}
- - SKIP_SOGO=${SKIP_SOGO:-n}
- - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
- - MASTER=${MASTER:-y}
- - DEV_MODE=${DEV_MODE:-n}
- - DEMO_MODE=${DEMO_MODE:-n}
- - WEBAUTHN_ONLY_TRUSTED_VENDORS=${WEBAUTHN_ONLY_TRUSTED_VENDORS:-n}
- - CLUSTERMODE=${CLUSTERMODE:-}
- - ADDITIONAL_SERVER_NAMES=${ADDITIONAL_SERVER_NAMES:-}
- restart: always
- labels:
- ofelia.enabled: "true"
- ofelia.job-exec.phpfpm_keycloak_sync.schedule: "0 * * * * *"
- ofelia.job-exec.phpfpm_keycloak_sync.no-overlap: "true"
- ofelia.job-exec.phpfpm_keycloak_sync.command: "/bin/bash -c \"php /crons/keycloak-sync.php || exit 0\""
- ofelia.job-exec.phpfpm_ldap_sync.schedule: "0 * * * * *"
- ofelia.job-exec.phpfpm_ldap_sync.no-overlap: "true"
- ofelia.job-exec.phpfpm_ldap_sync.command: "/bin/bash -c \"php /crons/ldap-sync.php || exit 0\""
- networks:
- mailcow-network:
- aliases:
- - phpfpm
-
- sogo-mailcow:
- image: ghcr.io/mailcow/sogo:5.12.4
- environment:
- - DBNAME=${DBNAME}
- - DBUSER=${DBUSER}
- - DBPASS=${DBPASS}
- - TZ=${TZ}
- - LOG_LINES=${LOG_LINES:-9999}
- - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- - MAILCOW_PASS_SCHEME=${MAILCOW_PASS_SCHEME:-BLF-CRYPT}
- - ACL_ANYONE=${ACL_ANYONE:-disallow}
- - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
- - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- - SOGO_EXPIRE_SESSION=${SOGO_EXPIRE_SESSION:-480}
- - SOGO_URL_ENCRYPTION_KEY=${SOGO_URL_ENCRYPTION_KEY:-SOGoSuperSecret0}
- - SKIP_SOGO=${SKIP_SOGO:-n}
- - MASTER=${MASTER:-y}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- volumes:
- - ./data/hooks/sogo:/hooks:Z
- - ./data/conf/sogo/:/etc/sogo/:z
- - ./data/web/inc/init_db.inc.php:/init_db.inc.php:z
- - ./data/conf/sogo/custom-favicon.ico:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo.ico:z
- - ./data/conf/sogo/custom-shortlogo.svg:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-compact.svg:z
- - ./data/conf/sogo/custom-fulllogo.svg:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg:z
- - ./data/conf/sogo/custom-fulllogo.png:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-logo.png:z
- - ./data/conf/sogo/custom-theme.js:/usr/lib/GNUstep/SOGo/WebServerResources/js/theme.js:z
- - ./data/conf/sogo/custom-sogo.js:/usr/lib/GNUstep/SOGo/WebServerResources/js/custom-sogo.js:z
- - mysql-socket-vol-1:/var/run/mysqld/:z
- - sogo-web-vol-1:/sogo_web
- - sogo-userdata-backup-vol-1:/sogo_backup
- labels:
- ofelia.enabled: "true"
- ofelia.job-exec.sogo_sessions.schedule: "0 * * * * *"
- ofelia.job-exec.sogo_sessions.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-tool -v expire-sessions $${SOGO_EXPIRE_SESSION} || exit 0\""
- ofelia.job-exec.sogo_ealarms.schedule: "0 * * * * *"
- ofelia.job-exec.sogo_ealarms.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-ealarms-notify -p /etc/sogo/cron.creds || exit 0\""
- ofelia.job-exec.sogo_eautoreply.schedule: "0 */5 * * * *"
- ofelia.job-exec.sogo_eautoreply.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-tool update-autoreply -p /etc/sogo/sieve.creds || exit 0\""
- ofelia.job-exec.sogo_backup.schedule: "0 0 0 * * *"
- ofelia.job-exec.sogo_backup.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-tool backup /sogo_backup ALL || exit 0\""
- restart: always
- networks:
- mailcow-network:
- ipv4_address: ${IPV4_NETWORK:-172.22.1}.248
- aliases:
- - sogo
-
- dovecot-mailcow:
- image: ghcr.io/mailcow/dovecot:2.3.21.1
- depends_on:
- - mysql-mailcow
- - netfilter-mailcow
- - redis-mailcow
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- cap_add:
- - NET_BIND_SERVICE
- volumes:
- - ./data/hooks/dovecot:/hooks:Z
- - ./data/conf/dovecot:/etc/dovecot:z
- - ./data/assets/ssl:/etc/ssl/mail/:ro,z
- - ./data/conf/sogo/:/etc/sogo/:z
- - ./data/conf/phpfpm/sogo-sso/:/etc/phpfpm/:z
- - vmail-vol-1:/var/vmail
- - vmail-index-vol-1:/var/vmail_index
- - crypt-vol-1:/mail_crypt/
- - ./data/conf/rspamd/custom/:/etc/rspamd/custom:z
- - ./data/assets/templates:/templates:z
- - rspamd-vol-1:/var/lib/rspamd
- - mysql-socket-vol-1:/var/run/mysqld/:z
- environment:
- - DOVECOT_MASTER_USER=${DOVECOT_MASTER_USER:-}
- - DOVECOT_MASTER_PASS=${DOVECOT_MASTER_PASS:-}
- - MAILCOW_REPLICA_IP=${MAILCOW_REPLICA_IP:-}
- - DOVEADM_REPLICA_PORT=${DOVEADM_REPLICA_PORT:-}
- - LOG_LINES=${LOG_LINES:-9999}
- - DBNAME=${DBNAME}
- - DBUSER=${DBUSER}
- - DBPASS=${DBPASS}
- - TZ=${TZ}
- - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- - MAILCOW_PASS_SCHEME=${MAILCOW_PASS_SCHEME:-BLF-CRYPT}
- - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
- - MAILDIR_GC_TIME=${MAILDIR_GC_TIME:-7200}
- - ACL_ANYONE=${ACL_ANYONE:-disallow}
- - SKIP_FTS=${SKIP_FTS:-y}
- - FTS_HEAP=${FTS_HEAP:-512}
- - FTS_PROCS=${FTS_PROCS:-3}
- - MAILDIR_SUB=${MAILDIR_SUB:-}
- - MASTER=${MASTER:-y}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
- ports:
- - "${DOVEADM_PORT:-127.0.0.1:19991}:12345"
- - "${IMAP_PORT:-143}:143"
- - "${IMAPS_PORT:-993}:993"
- - "${POP_PORT:-110}:110"
- - "${POPS_PORT:-995}:995"
- - "${SIEVE_PORT:-4190}:4190"
- restart: always
- tty: true
- labels:
- ofelia.enabled: "true"
- ofelia.job-exec.dovecot_imapsync_runner.schedule: "0 * * * * *"
- ofelia.job-exec.dovecot_imapsync_runner.no-overlap: "true"
- ofelia.job-exec.dovecot_imapsync_runner.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu nobody /usr/local/bin/imapsync_runner.pl || exit 0\""
- ofelia.job-exec.dovecot_trim_logs.schedule: "0 * * * * *"
- ofelia.job-exec.dovecot_trim_logs.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu vmail /usr/local/bin/trim_logs.sh || exit 0\""
- ofelia.job-exec.dovecot_quarantine.schedule: "0 */20 * * * *"
- ofelia.job-exec.dovecot_quarantine.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu vmail /usr/local/bin/quarantine_notify.py || exit 0\""
- ofelia.job-exec.dovecot_clean_q_aged.schedule: "0 0 0 * * *"
- ofelia.job-exec.dovecot_clean_q_aged.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu vmail /usr/local/bin/clean_q_aged.sh || exit 0\""
- ofelia.job-exec.dovecot_maildir_gc.schedule: "0 */30 * * * *"
- ofelia.job-exec.dovecot_maildir_gc.command: "/bin/bash -c \"source /source_env.sh ; /usr/local/bin/gosu vmail /usr/local/bin/maildir_gc.sh\""
- ofelia.job-exec.dovecot_sarules.schedule: "@every 24h"
- ofelia.job-exec.dovecot_sarules.command: "/bin/bash -c \"/usr/local/bin/sa-rules.sh\""
- ofelia.job-exec.dovecot_fts.schedule: "0 0 0 * * *"
- ofelia.job-exec.dovecot_fts.command: "/bin/bash -c \"/usr/local/bin/gosu vmail /usr/local/bin/optimize-fts.sh\""
- ofelia.job-exec.dovecot_repl_health.schedule: "0 */5 * * * *"
- ofelia.job-exec.dovecot_repl_health.command: "/bin/bash -c \"/usr/local/bin/gosu vmail /usr/local/bin/repl_health.sh\""
- ulimits:
- nproc: 65535
- nofile:
- soft: 20000
- hard: 40000
- networks:
- mailcow-network:
- ipv4_address: ${IPV4_NETWORK:-172.22.1}.250
- aliases:
- - dovecot
-
- postfix-mailcow:
- image: ghcr.io/mailcow/postfix:3.7.11
- depends_on:
- mysql-mailcow:
- condition: service_started
- unbound-mailcow:
- condition: service_healthy
- postfix-tlspol-mailcow:
- condition: service_started
- volumes:
- - ./data/hooks/postfix:/hooks:Z
- - ./data/conf/postfix:/opt/postfix/conf:z
- - ./data/assets/ssl:/etc/ssl/mail/:ro,z
- - postfix-vol-1:/var/spool/postfix
- - crypt-vol-1:/var/lib/zeyple
- - rspamd-vol-1:/var/lib/rspamd
- - mysql-socket-vol-1:/var/run/mysqld/:z
- environment:
- - LOG_LINES=${LOG_LINES:-9999}
- - TZ=${TZ}
- - DBNAME=${DBNAME}
- - DBUSER=${DBUSER}
- - DBPASS=${DBPASS}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- - SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-}
- cap_add:
- - NET_BIND_SERVICE
- ports:
- - "${SMTP_PORT:-25}:25"
- - "${SMTPS_PORT:-465}:465"
- - "${SUBMISSION_PORT:-587}:587"
- restart: always
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- networks:
- mailcow-network:
- ipv4_address: ${IPV4_NETWORK:-172.22.1}.253
- aliases:
- - postfix
-
- postfix-tlspol-mailcow:
- image: ghcr.io/mailcow/postfix-tlspol:1.8.22
- depends_on:
- unbound-mailcow:
- condition: service_healthy
- volumes:
- - postfix-tlspol-vol-1:/var/lib/postfix-tlspol
- environment:
- - LOG_LINES=${LOG_LINES:-9999}
- - TZ=${TZ}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - DEV_MODE=${DEV_MODE:-n}
- restart: always
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- networks:
- mailcow-network:
- aliases:
- - postfix-tlspol
-
- memcached-mailcow:
- image: memcached:alpine
- restart: always
- environment:
- - TZ=${TZ}
- networks:
- mailcow-network:
- aliases:
- - memcached
-
- nginx-mailcow:
- depends_on:
- - redis-mailcow
- - php-fpm-mailcow
- - sogo-mailcow
- - rspamd-mailcow
- image: ghcr.io/mailcow/nginx:1.05
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- environment:
- - HTTPS_PORT=${HTTPS_PORT:-443}
- - HTTP_PORT=${HTTP_PORT:-80}
- - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- - ADDITIONAL_SERVER_NAMES=${ADDITIONAL_SERVER_NAMES:-}
- - TZ=${TZ}
- - SKIP_SOGO=${SKIP_SOGO:-n}
- - SKIP_RSPAMD=${SKIP_RSPAMD:-n}
- - ENABLE_IPV6=${ENABLE_IPV6:-true}
- - HTTP_REDIRECT=${HTTP_REDIRECT:-n}
- - PHPFPMHOST=${PHPFPMHOST:-}
- - SOGOHOST=${SOGOHOST:-}
- - RSPAMDHOST=${RSPAMDHOST:-}
- - REDISHOST=${REDISHOST:-}
- - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- - NGINX_USE_PROXY_PROTOCOL=${NGINX_USE_PROXY_PROTOCOL:-n}
- - TRUSTED_PROXIES=${TRUSTED_PROXIES:-172.16.0.0/12}
- volumes:
- - ./data/web:/web:ro,z
- - ./data/conf/rspamd/dynmaps:/dynmaps:ro,z
- - ./data/assets/ssl/:/etc/ssl/mail/:ro,z
- - ./data/conf/nginx/:/etc/nginx/conf.d/:z
- - ./data/conf/rspamd/meta_exporter:/meta_exporter:ro,z
- - ./data/conf/dovecot/auth/mailcowauth.php:/mailcowauth/mailcowauth.php:z
- - ./data/web/inc/functions.inc.php:/mailcowauth/functions.inc.php:z
- - ./data/web/inc/functions.auth.inc.php:/mailcowauth/functions.auth.inc.php:z
- - ./data/web/inc/sessions.inc.php:/mailcowauth/sessions.inc.php:z
- - sogo-web-vol-1:/usr/lib/GNUstep/SOGo/
- ports: []
- restart: always
- networks:
- mailcow-network:
- aliases:
- - nginx
- traefik-proxy: {}
- labels:
- traefik.enable: "true"
- traefik.docker.network: ${TRAEFIK_NETWORK:-coolify}
-
- traefik.http.routers.mailcow-http.rule: Host(`mail.karmacoma.dev`)
- traefik.http.routers.mailcow-http.entrypoints: web
- traefik.http.routers.mailcow-http.service: mailcow-http
- traefik.http.middlewares.mailcow-https-redirect.redirectscheme.scheme: https
- traefik.http.routers.mailcow-http.middlewares: mailcow-https-redirect
- traefik.http.services.mailcow-http.loadbalancer.server.port: 80
- traefik.http.routers.mailcow-https.rule: Host(`mail.karmacoma.dev`)
- traefik.http.routers.mailcow-https.entrypoints: websecure
- traefik.http.routers.mailcow-https.tls: "true"
- traefik.http.routers.mailcow-https.service: mailcow-http
-
- acme-mailcow:
- depends_on:
- nginx-mailcow:
- condition: service_started
- unbound-mailcow:
- condition: service_healthy
- image: ghcr.io/mailcow/acme:1.94
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- environment:
- - LOG_LINES=${LOG_LINES:-9999}
- - ADDITIONAL_SAN=${ADDITIONAL_SAN}
- - AUTODISCOVER_SAN=${AUTODISCOVER_SAN:-y}
- - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- - DBNAME=${DBNAME}
- - DBUSER=${DBUSER}
- - DBPASS=${DBPASS}
- - SKIP_LETS_ENCRYPT=${SKIP_LETS_ENCRYPT:-n}
- - COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
- - DIRECTORY_URL=${DIRECTORY_URL:-}
- - ENABLE_SSL_SNI=${ENABLE_SSL_SNI:-n}
- - SKIP_IP_CHECK=${SKIP_IP_CHECK:-n}
- - SKIP_HTTP_VERIFICATION=${SKIP_HTTP_VERIFICATION:-n}
- - ONLY_MAILCOW_HOSTNAME=${ONLY_MAILCOW_HOSTNAME:-n}
- - LE_STAGING=${LE_STAGING:-n}
- - TZ=${TZ}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - SNAT_TO_SOURCE=${SNAT_TO_SOURCE:-n}
- - SNAT6_TO_SOURCE=${SNAT6_TO_SOURCE:-n}
- volumes:
- - ./data/web/.well-known/acme-challenge:/var/www/acme:z
- - ./data/assets/ssl:/var/lib/acme/:z
- - ./data/assets/ssl-example:/var/lib/ssl-example/:ro,Z
- - mysql-socket-vol-1:/var/run/mysqld/:z
- restart: always
- networks:
- mailcow-network:
- aliases:
- - acme
-
- netfilter-mailcow:
- image: ghcr.io/mailcow/netfilter:1.63
- stop_grace_period: 30s
- restart: always
- privileged: true
- environment:
- - TZ=${TZ}
- - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- - IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
- - SNAT_TO_SOURCE=${SNAT_TO_SOURCE:-n}
- - SNAT6_TO_SOURCE=${SNAT6_TO_SOURCE:-n}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - MAILCOW_REPLICA_IP=${MAILCOW_REPLICA_IP:-}
- - DISABLE_NETFILTER_ISOLATION_RULE=${DISABLE_NETFILTER_ISOLATION_RULE:-n}
- network_mode: "host"
- volumes:
- - /lib/modules:/lib/modules:ro
-
- watchdog-mailcow:
- image: ghcr.io/mailcow/watchdog:2.09
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- tmpfs:
- - /tmp
- volumes:
- - rspamd-vol-1:/var/lib/rspamd
- - mysql-socket-vol-1:/var/run/mysqld/:z
- - postfix-vol-1:/var/spool/postfix
- - ./data/assets/ssl:/etc/ssl/mail/:ro,z
- restart: always
- depends_on:
- - postfix-mailcow
- - dovecot-mailcow
- - mysql-mailcow
- - acme-mailcow
- - redis-mailcow
- environment:
- - IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
- - LOG_LINES=${LOG_LINES:-9999}
- - TZ=${TZ}
- - DBNAME=${DBNAME}
- - DBUSER=${DBUSER}
- - DBPASS=${DBPASS}
- - DBROOT=${DBROOT}
- - USE_WATCHDOG=${USE_WATCHDOG:-n}
- - WATCHDOG_NOTIFY_EMAIL=${WATCHDOG_NOTIFY_EMAIL:-}
- - WATCHDOG_NOTIFY_BAN=${WATCHDOG_NOTIFY_BAN:-y}
- - WATCHDOG_NOTIFY_START=${WATCHDOG_NOTIFY_START:-y}
- - WATCHDOG_SUBJECT=${WATCHDOG_SUBJECT:-Watchdog ALERT}
- - WATCHDOG_NOTIFY_WEBHOOK=${WATCHDOG_NOTIFY_WEBHOOK:-}
- - WATCHDOG_NOTIFY_WEBHOOK_BODY=${WATCHDOG_NOTIFY_WEBHOOK_BODY:-}
- - WATCHDOG_EXTERNAL_CHECKS=${WATCHDOG_EXTERNAL_CHECKS:-n}
- - WATCHDOG_MYSQL_REPLICATION_CHECKS=${WATCHDOG_MYSQL_REPLICATION_CHECKS:-n}
- - WATCHDOG_VERBOSE=${WATCHDOG_VERBOSE:-n}
- - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- - COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
- - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- - IP_BY_DOCKER_API=${IP_BY_DOCKER_API:-0}
- - CHECK_UNBOUND=${CHECK_UNBOUND:-1}
- - SKIP_CLAMD=${SKIP_CLAMD:-n}
- - SKIP_OLEFY=${SKIP_OLEFY:-n}
- - SKIP_LETS_ENCRYPT=${SKIP_LETS_ENCRYPT:-n}
- - SKIP_SOGO=${SKIP_SOGO:-n}
- - HTTPS_PORT=${HTTPS_PORT:-443}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - EXTERNAL_CHECKS_THRESHOLD=${EXTERNAL_CHECKS_THRESHOLD:-1}
- - NGINX_THRESHOLD=${NGINX_THRESHOLD:-5}
- - UNBOUND_THRESHOLD=${UNBOUND_THRESHOLD:-5}
- - REDIS_THRESHOLD=${REDIS_THRESHOLD:-5}
- - MYSQL_THRESHOLD=${MYSQL_THRESHOLD:-5}
- - MYSQL_REPLICATION_THRESHOLD=${MYSQL_REPLICATION_THRESHOLD:-1}
- - SOGO_THRESHOLD=${SOGO_THRESHOLD:-3}
- - POSTFIX_THRESHOLD=${POSTFIX_THRESHOLD:-8}
- - POSTFIX_TLSPOL_THRESHOLD=${POSTFIX_TLSPOL_THRESHOLD:-8}
- - CLAMD_THRESHOLD=${CLAMD_THRESHOLD:-15}
- - DOVECOT_THRESHOLD=${DOVECOT_THRESHOLD:-12}
- - DOVECOT_REPL_THRESHOLD=${DOVECOT_REPL_THRESHOLD:-20}
- - PHPFPM_THRESHOLD=${PHPFPM_THRESHOLD:-5}
- - RATELIMIT_THRESHOLD=${RATELIMIT_THRESHOLD:-1}
- - FAIL2BAN_THRESHOLD=${FAIL2BAN_THRESHOLD:-1}
- - ACME_THRESHOLD=${ACME_THRESHOLD:-1}
- - RSPAMD_THRESHOLD=${RSPAMD_THRESHOLD:-5}
- - OLEFY_THRESHOLD=${OLEFY_THRESHOLD:-5}
- - MAILQ_THRESHOLD=${MAILQ_THRESHOLD:-20}
- - MAILQ_CRIT=${MAILQ_CRIT:-30}
- - DEV_MODE=${DEV_MODE:-n}
- networks:
- mailcow-network:
- aliases:
- - watchdog
-
- dockerapi-mailcow:
- image: ghcr.io/mailcow/dockerapi:2.11
- security_opt:
- - label=disable
- restart: always
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- environment:
- - DBROOT=${DBROOT}
- - TZ=${TZ}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- volumes:
- - /var/run/docker.sock:/var/run/docker.sock:ro
- networks:
- mailcow-network:
- aliases:
- - dockerapi
-
- olefy-mailcow:
- image: ghcr.io/mailcow/olefy:1.15
- restart: always
- environment:
- - TZ=${TZ}
- - OLEFY_BINDADDRESS=0.0.0.0
- - OLEFY_BINDPORT=10055
- - OLEFY_TMPDIR=/tmp
- - OLEFY_PYTHON_PATH=/usr/bin/python3
- - OLEFY_OLEVBA_PATH=/usr/bin/olevba
- - OLEFY_LOGLVL=20
- - OLEFY_MINLENGTH=500
- - OLEFY_DEL_TMP=1
- - SKIP_OLEFY=${SKIP_OLEFY:-n}
- networks:
- mailcow-network:
- aliases:
- - olefy
-
- ofelia-mailcow:
- image: mcuadros/ofelia:latest
- restart: always
- command: daemon --docker -f label=com.docker.compose.project=${COMPOSE_PROJECT_NAME}
- environment:
- - TZ=${TZ}
- - COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME}
- depends_on:
- - sogo-mailcow
- - dovecot-mailcow
- labels:
- ofelia.enabled: "true"
- security_opt:
- - label=disable
- volumes:
- - /var/run/docker.sock:/var/run/docker.sock:ro
- networks:
- mailcow-network:
- aliases:
- - ofelia
-
-networks:
- mailcow-network:
- driver: bridge
- driver_opts:
- com.docker.network.bridge.name: br-mailcow
- enable_ipv6: ${ENABLE_IPV6:-true}
- ipam:
- driver: default
- config:
- - subnet: ${IPV4_NETWORK:-172.22.1}.0/24
- - subnet: ${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
-
-volumes:
- vmail-vol-1:
- vmail-index-vol-1:
- mysql-vol-1:
- mysql-socket-vol-1:
- redis-vol-1:
- rspamd-vol-1:
- postfix-vol-1:
- postfix-tlspol-vol-1:
- crypt-vol-1:
- sogo-web-vol-1:
- sogo-userdata-backup-vol-1:
- clamd-db-vol-1:
diff --git a/docker-compose.yml b/docker-compose.yml
index ae9a18d..b16e06a 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,683 +1,38 @@
services:
+ mailserver:
+ image: ghcr.io/docker-mailserver/docker-mailserver:latest
+ container_name: mailserver
+ # Provide the FQDN of your mail server here (Your DNS MX record should point to this value)
+ hostname: mail.karmacoma.dev
+ ports:
+ - "25:25"
+ - "465:465"
+ - "587:587"
+ - "993:993"
+ volumes:
+ - ./docker-data/dms/mail-data/:/var/mail/
+ - ./docker-data/dms/mail-state/:/var/mail-state/
+ - ./docker-data/dms/mail-logs/:/var/log/mail/
+ - ./docker-data/dms/config/:/tmp/docker-mailserver/
+ - /etc/localtime:/etc/localtime:ro
+ environment:
+ - ENABLE_RSPAMD=1
+ - ENABLE_CLAMAV=1
+ - ENABLE_FAIL2BAN=1
+ cap_add:
+ - NET_ADMIN # For Fail2Ban to work
+ restart: always
- unbound-mailcow:
- image: ghcr.io/mailcow/unbound:1.24
- environment:
- - TZ=${TZ}
- - SKIP_UNBOUND_HEALTHCHECK=${SKIP_UNBOUND_HEALTHCHECK:-n}
- volumes:
- - ./data/hooks/unbound:/hooks:Z
- - ./data/conf/unbound/unbound.conf:/etc/unbound/unbound.conf:ro,Z
- restart: always
- tty: true
- networks:
- mailcow-network:
- ipv4_address: ${IPV4_NETWORK:-172.22.1}.254
- aliases:
- - unbound
-
- mysql-mailcow:
- image: mariadb:10.11
- depends_on:
- - unbound-mailcow
- - netfilter-mailcow
- stop_grace_period: 45s
- volumes:
- - mysql-vol-1:/var/lib/mysql/
- - mysql-socket-vol-1:/var/run/mysqld/:z
- - ./data/conf/mysql/:/etc/mysql/conf.d/:ro,Z
- environment:
- - TZ=${TZ}
- - MYSQL_ROOT_PASSWORD=${DBROOT}
- - MYSQL_DATABASE=${DBNAME}
- - MYSQL_USER=${DBUSER}
- - MYSQL_PASSWORD=${DBPASS}
- - MYSQL_INITDB_SKIP_TZINFO=1
- restart: always
- ports:
- - "${SQL_PORT:-127.0.0.1:13306}:3306"
- networks:
- mailcow-network:
- aliases:
- - mysql
-
- redis-mailcow:
- image: redis:7.4.6-alpine
- entrypoint: ["/bin/sh","/redis-conf.sh"]
- volumes:
- - redis-vol-1:/data/
- - ./data/conf/redis/redis-conf.sh:/redis-conf.sh:z
- restart: always
- depends_on:
- - netfilter-mailcow
- ports:
- - "${REDIS_PORT:-127.0.0.1:7654}:6379"
- environment:
- - TZ=${TZ}
- - REDISPASS=${REDISPASS}
- - REDISMASTERPASS=${REDISMASTERPASS:-}
- sysctls:
- - net.core.somaxconn=4096
- networks:
- mailcow-network:
- ipv4_address: ${IPV4_NETWORK:-172.22.1}.249
- aliases:
- - redis
-
- clamd-mailcow:
- image: ghcr.io/mailcow/clamd:1.71
- restart: always
- depends_on:
- unbound-mailcow:
- condition: service_healthy
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- environment:
- - TZ=${TZ}
- - SKIP_CLAMD=${SKIP_CLAMD:-n}
- volumes:
- - ./data/conf/clamav/:/etc/clamav/:Z
- - clamd-db-vol-1:/var/lib/clamav
- networks:
- mailcow-network:
- aliases:
- - clamd
-
- rspamd-mailcow:
- image: ghcr.io/mailcow/rspamd:2.4
- stop_grace_period: 30s
- depends_on:
- - dovecot-mailcow
- - clamd-mailcow
- environment:
- - TZ=${TZ}
- - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- - IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-}
- volumes:
- - ./data/hooks/rspamd:/hooks:Z
- - ./data/conf/rspamd/custom/:/etc/rspamd/custom:z
- - ./data/conf/rspamd/override.d/:/etc/rspamd/override.d:Z
- - ./data/conf/rspamd/local.d/:/etc/rspamd/local.d:Z
- - ./data/conf/rspamd/plugins.d/:/etc/rspamd/plugins.d:Z
- - ./data/conf/rspamd/lua/:/etc/rspamd/lua/:ro,Z
- - ./data/conf/rspamd/rspamd.conf.local:/etc/rspamd/rspamd.conf.local:Z
- - ./data/conf/rspamd/rspamd.conf.override:/etc/rspamd/rspamd.conf.override:Z
- - rspamd-vol-1:/var/lib/rspamd
- restart: always
- hostname: rspamd
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- networks:
- mailcow-network:
- aliases:
- - rspamd
-
- php-fpm-mailcow:
- image: ghcr.io/mailcow/phpfpm:8.2.29
- command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
- depends_on:
- - redis-mailcow
- volumes:
- - ./data/hooks/phpfpm:/hooks:Z
- - ./data/web:/web:z
- - ./data/conf/rspamd/dynmaps:/dynmaps:ro,z
- - ./data/conf/rspamd/custom/:/rspamd_custom_maps:z
- - ./data/conf/dovecot/auth/mailcowauth.php:/mailcowauth/mailcowauth.php:z
- - ./data/web/inc/functions.inc.php:/mailcowauth/functions.inc.php:z
- - ./data/web/inc/functions.auth.inc.php:/mailcowauth/functions.auth.inc.php:z
- - ./data/web/inc/sessions.inc.php:/mailcowauth/sessions.inc.php:z
- - ./data/web/inc/functions.mailbox.inc.php:/mailcowauth/functions.mailbox.inc.php:z
- - ./data/web/inc/functions.ratelimit.inc.php:/mailcowauth/functions.ratelimit.inc.php:z
- - ./data/web/inc/functions.acl.inc.php:/mailcowauth/functions.acl.inc.php:z
- - rspamd-vol-1:/var/lib/rspamd
- - mysql-socket-vol-1:/var/run/mysqld/:z
- - ./data/conf/sogo/:/etc/sogo/:z
- - ./data/conf/rspamd/meta_exporter:/meta_exporter:ro,z
- - ./data/conf/phpfpm/crons:/crons:z
- - ./data/conf/phpfpm/sogo-sso/:/etc/sogo-sso/:z
- - ./data/conf/phpfpm/php-fpm.d/pools.conf:/usr/local/etc/php-fpm.d/z-pools.conf:Z
- - ./data/conf/phpfpm/php-conf.d/opcache-recommended.ini:/usr/local/etc/php/conf.d/opcache-recommended.ini:Z
- - ./data/conf/phpfpm/php-conf.d/upload.ini:/usr/local/etc/php/conf.d/upload.ini:Z
- - ./data/conf/phpfpm/php-conf.d/other.ini:/usr/local/etc/php/conf.d/zzz-other.ini:Z
- - ./data/conf/dovecot/global_sieve_before:/global_sieve/before:z
- - ./data/conf/dovecot/global_sieve_after:/global_sieve/after:z
- - ./data/assets/templates:/tpls:z
- - ./data/conf/nginx/:/etc/nginx/conf.d/:z
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- environment:
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - LOG_LINES=${LOG_LINES:-9999}
- - TZ=${TZ}
- - DBNAME=${DBNAME}
- - DBUSER=${DBUSER}
- - DBPASS=${DBPASS}
- - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- - MAILCOW_PASS_SCHEME=${MAILCOW_PASS_SCHEME:-BLF-CRYPT}
- - IMAP_PORT=${IMAP_PORT:-143}
- - IMAPS_PORT=${IMAPS_PORT:-993}
- - POP_PORT=${POP_PORT:-110}
- - POPS_PORT=${POPS_PORT:-995}
- - SIEVE_PORT=${SIEVE_PORT:-4190}
- - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- - IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
- - SUBMISSION_PORT=${SUBMISSION_PORT:-587}
- - SMTPS_PORT=${SMTPS_PORT:-465}
- - SMTP_PORT=${SMTP_PORT:-25}
- - API_KEY=${API_KEY:-invalid}
- - API_KEY_READ_ONLY=${API_KEY_READ_ONLY:-invalid}
- - API_ALLOW_FROM=${API_ALLOW_FROM:-invalid}
- - COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
- - SKIP_FTS=${SKIP_FTS:-y}
- - SKIP_CLAMD=${SKIP_CLAMD:-n}
- - SKIP_OLEFY=${SKIP_OLEFY:-n}
- - SKIP_SOGO=${SKIP_SOGO:-n}
- - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
- - MASTER=${MASTER:-y}
- - DEV_MODE=${DEV_MODE:-n}
- - DEMO_MODE=${DEMO_MODE:-n}
- - WEBAUTHN_ONLY_TRUSTED_VENDORS=${WEBAUTHN_ONLY_TRUSTED_VENDORS:-n}
- - CLUSTERMODE=${CLUSTERMODE:-}
- - ADDITIONAL_SERVER_NAMES=${ADDITIONAL_SERVER_NAMES:-}
- restart: always
- labels:
- ofelia.enabled: "true"
- ofelia.job-exec.phpfpm_keycloak_sync.schedule: "0 * * * * *"
- ofelia.job-exec.phpfpm_keycloak_sync.no-overlap: "true"
- ofelia.job-exec.phpfpm_keycloak_sync.command: "/bin/bash -c \"php /crons/keycloak-sync.php || exit 0\""
- ofelia.job-exec.phpfpm_ldap_sync.schedule: "0 * * * * *"
- ofelia.job-exec.phpfpm_ldap_sync.no-overlap: "true"
- ofelia.job-exec.phpfpm_ldap_sync.command: "/bin/bash -c \"php /crons/ldap-sync.php || exit 0\""
- networks:
- mailcow-network:
- aliases:
- - phpfpm
-
- sogo-mailcow:
- image: ghcr.io/mailcow/sogo:5.12.4
- environment:
- - DBNAME=${DBNAME}
- - DBUSER=${DBUSER}
- - DBPASS=${DBPASS}
- - TZ=${TZ}
- - LOG_LINES=${LOG_LINES:-9999}
- - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- - MAILCOW_PASS_SCHEME=${MAILCOW_PASS_SCHEME:-BLF-CRYPT}
- - ACL_ANYONE=${ACL_ANYONE:-disallow}
- - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
- - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- - SOGO_EXPIRE_SESSION=${SOGO_EXPIRE_SESSION:-480}
- - SOGO_URL_ENCRYPTION_KEY=${SOGO_URL_ENCRYPTION_KEY:-SOGoSuperSecret0}
- - SKIP_SOGO=${SKIP_SOGO:-n}
- - MASTER=${MASTER:-y}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- volumes:
- - ./data/hooks/sogo:/hooks:Z
- - ./data/conf/sogo/:/etc/sogo/:z
- - ./data/web/inc/init_db.inc.php:/init_db.inc.php:z
- - ./data/conf/sogo/custom-favicon.ico:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo.ico:z
- - ./data/conf/sogo/custom-shortlogo.svg:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-compact.svg:z
- - ./data/conf/sogo/custom-fulllogo.svg:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg:z
- - ./data/conf/sogo/custom-fulllogo.png:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-logo.png:z
- - ./data/conf/sogo/custom-theme.js:/usr/lib/GNUstep/SOGo/WebServerResources/js/theme.js:z
- - ./data/conf/sogo/custom-sogo.js:/usr/lib/GNUstep/SOGo/WebServerResources/js/custom-sogo.js:z
- - mysql-socket-vol-1:/var/run/mysqld/:z
- - sogo-web-vol-1:/sogo_web
- - sogo-userdata-backup-vol-1:/sogo_backup
- labels:
- ofelia.enabled: "true"
- ofelia.job-exec.sogo_sessions.schedule: "0 * * * * *"
- ofelia.job-exec.sogo_sessions.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-tool -v expire-sessions $${SOGO_EXPIRE_SESSION} || exit 0\""
- ofelia.job-exec.sogo_ealarms.schedule: "0 * * * * *"
- ofelia.job-exec.sogo_ealarms.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-ealarms-notify -p /etc/sogo/cron.creds || exit 0\""
- ofelia.job-exec.sogo_eautoreply.schedule: "0 */5 * * * *"
- ofelia.job-exec.sogo_eautoreply.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-tool update-autoreply -p /etc/sogo/sieve.creds || exit 0\""
- ofelia.job-exec.sogo_backup.schedule: "0 0 0 * * *"
- ofelia.job-exec.sogo_backup.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-tool backup /sogo_backup ALL || exit 0\""
- restart: always
- networks:
- mailcow-network:
- ipv4_address: ${IPV4_NETWORK:-172.22.1}.248
- aliases:
- - sogo
-
- dovecot-mailcow:
- image: ghcr.io/mailcow/dovecot:2.3.21.1
- depends_on:
- - mysql-mailcow
- - netfilter-mailcow
- - redis-mailcow
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- cap_add:
- - NET_BIND_SERVICE
- volumes:
- - ./data/hooks/dovecot:/hooks:Z
- - ./data/conf/dovecot:/etc/dovecot:z
- - ./data/assets/ssl:/etc/ssl/mail/:ro,z
- - ./data/conf/sogo/:/etc/sogo/:z
- - ./data/conf/phpfpm/sogo-sso/:/etc/phpfpm/:z
- - vmail-vol-1:/var/vmail
- - vmail-index-vol-1:/var/vmail_index
- - crypt-vol-1:/mail_crypt/
- - ./data/conf/rspamd/custom/:/etc/rspamd/custom:z
- - ./data/assets/templates:/templates:z
- - rspamd-vol-1:/var/lib/rspamd
- - mysql-socket-vol-1:/var/run/mysqld/:z
- environment:
- - DOVECOT_MASTER_USER=${DOVECOT_MASTER_USER:-}
- - DOVECOT_MASTER_PASS=${DOVECOT_MASTER_PASS:-}
- - MAILCOW_REPLICA_IP=${MAILCOW_REPLICA_IP:-}
- - DOVEADM_REPLICA_PORT=${DOVEADM_REPLICA_PORT:-}
- - LOG_LINES=${LOG_LINES:-9999}
- - DBNAME=${DBNAME}
- - DBUSER=${DBUSER}
- - DBPASS=${DBPASS}
- - TZ=${TZ}
- - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- - MAILCOW_PASS_SCHEME=${MAILCOW_PASS_SCHEME:-BLF-CRYPT}
- - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
- - MAILDIR_GC_TIME=${MAILDIR_GC_TIME:-7200}
- - ACL_ANYONE=${ACL_ANYONE:-disallow}
- - SKIP_FTS=${SKIP_FTS:-y}
- - FTS_HEAP=${FTS_HEAP:-512}
- - FTS_PROCS=${FTS_PROCS:-3}
- - MAILDIR_SUB=${MAILDIR_SUB:-}
- - MASTER=${MASTER:-y}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
- ports:
- - "${DOVEADM_PORT:-127.0.0.1:19991}:12345"
- - "${IMAP_PORT:-143}:143"
- - "${IMAPS_PORT:-993}:993"
- - "${POP_PORT:-110}:110"
- - "${POPS_PORT:-995}:995"
- - "${SIEVE_PORT:-4190}:4190"
- restart: always
- tty: true
- labels:
- ofelia.enabled: "true"
- ofelia.job-exec.dovecot_imapsync_runner.schedule: "0 * * * * *"
- ofelia.job-exec.dovecot_imapsync_runner.no-overlap: "true"
- ofelia.job-exec.dovecot_imapsync_runner.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu nobody /usr/local/bin/imapsync_runner.pl || exit 0\""
- ofelia.job-exec.dovecot_trim_logs.schedule: "0 * * * * *"
- ofelia.job-exec.dovecot_trim_logs.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu vmail /usr/local/bin/trim_logs.sh || exit 0\""
- ofelia.job-exec.dovecot_quarantine.schedule: "0 */20 * * * *"
- ofelia.job-exec.dovecot_quarantine.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu vmail /usr/local/bin/quarantine_notify.py || exit 0\""
- ofelia.job-exec.dovecot_clean_q_aged.schedule: "0 0 0 * * *"
- ofelia.job-exec.dovecot_clean_q_aged.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu vmail /usr/local/bin/clean_q_aged.sh || exit 0\""
- ofelia.job-exec.dovecot_maildir_gc.schedule: "0 */30 * * * *"
- ofelia.job-exec.dovecot_maildir_gc.command: "/bin/bash -c \"source /source_env.sh ; /usr/local/bin/gosu vmail /usr/local/bin/maildir_gc.sh\""
- ofelia.job-exec.dovecot_sarules.schedule: "@every 24h"
- ofelia.job-exec.dovecot_sarules.command: "/bin/bash -c \"/usr/local/bin/sa-rules.sh\""
- ofelia.job-exec.dovecot_fts.schedule: "0 0 0 * * *"
- ofelia.job-exec.dovecot_fts.command: "/bin/bash -c \"/usr/local/bin/gosu vmail /usr/local/bin/optimize-fts.sh\""
- ofelia.job-exec.dovecot_repl_health.schedule: "0 */5 * * * *"
- ofelia.job-exec.dovecot_repl_health.command: "/bin/bash -c \"/usr/local/bin/gosu vmail /usr/local/bin/repl_health.sh\""
- ulimits:
- nproc: 65535
- nofile:
- soft: 20000
- hard: 40000
- networks:
- mailcow-network:
- ipv4_address: ${IPV4_NETWORK:-172.22.1}.250
- aliases:
- - dovecot
-
- postfix-mailcow:
- image: ghcr.io/mailcow/postfix:3.7.11
- depends_on:
- mysql-mailcow:
- condition: service_started
- unbound-mailcow:
- condition: service_healthy
- postfix-tlspol-mailcow:
- condition: service_started
- volumes:
- - ./data/hooks/postfix:/hooks:Z
- - ./data/conf/postfix:/opt/postfix/conf:z
- - ./data/assets/ssl:/etc/ssl/mail/:ro,z
- - postfix-vol-1:/var/spool/postfix
- - crypt-vol-1:/var/lib/zeyple
- - rspamd-vol-1:/var/lib/rspamd
- - mysql-socket-vol-1:/var/run/mysqld/:z
- environment:
- - LOG_LINES=${LOG_LINES:-9999}
- - TZ=${TZ}
- - DBNAME=${DBNAME}
- - DBUSER=${DBUSER}
- - DBPASS=${DBPASS}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- - SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-}
- cap_add:
- - NET_BIND_SERVICE
- ports:
- - "${SMTP_PORT:-25}:25"
- - "${SMTPS_PORT:-465}:465"
- - "${SUBMISSION_PORT:-587}:587"
- restart: always
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- networks:
- mailcow-network:
- ipv4_address: ${IPV4_NETWORK:-172.22.1}.253
- aliases:
- - postfix
-
- postfix-tlspol-mailcow:
- image: ghcr.io/mailcow/postfix-tlspol:1.8.22
- depends_on:
- unbound-mailcow:
- condition: service_healthy
- volumes:
- - postfix-tlspol-vol-1:/var/lib/postfix-tlspol
- environment:
- - LOG_LINES=${LOG_LINES:-9999}
- - TZ=${TZ}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - DEV_MODE=${DEV_MODE:-n}
- restart: always
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- networks:
- mailcow-network:
- aliases:
- - postfix-tlspol
-
- memcached-mailcow:
- image: memcached:alpine
- restart: always
- environment:
- - TZ=${TZ}
- networks:
- mailcow-network:
- aliases:
- - memcached
-
- nginx-mailcow:
- depends_on:
- - redis-mailcow
- - php-fpm-mailcow
- - sogo-mailcow
- - rspamd-mailcow
- image: ghcr.io/mailcow/nginx:1.05
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- environment:
- - HTTPS_PORT=${HTTPS_PORT:-443}
- - HTTP_PORT=${HTTP_PORT:-80}
- - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- - ADDITIONAL_SERVER_NAMES=${ADDITIONAL_SERVER_NAMES:-}
- - TZ=${TZ}
- - SKIP_SOGO=${SKIP_SOGO:-n}
- - SKIP_RSPAMD=${SKIP_RSPAMD:-n}
- - ENABLE_IPV6=${ENABLE_IPV6:-true}
- - HTTP_REDIRECT=${HTTP_REDIRECT:-n}
- - PHPFPMHOST=${PHPFPMHOST:-}
- - SOGOHOST=${SOGOHOST:-}
- - RSPAMDHOST=${RSPAMDHOST:-}
- - REDISHOST=${REDISHOST:-}
- - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- - NGINX_USE_PROXY_PROTOCOL=${NGINX_USE_PROXY_PROTOCOL:-n}
- - TRUSTED_PROXIES=${TRUSTED_PROXIES:-}
- volumes:
- - ./data/web:/web:ro,z
- - ./data/conf/rspamd/dynmaps:/dynmaps:ro,z
- - ./data/assets/ssl/:/etc/ssl/mail/:ro,z
- - ./data/conf/nginx/:/etc/nginx/conf.d/:z
- - ./data/conf/rspamd/meta_exporter:/meta_exporter:ro,z
- - ./data/conf/dovecot/auth/mailcowauth.php:/mailcowauth/mailcowauth.php:z
- - ./data/web/inc/functions.inc.php:/mailcowauth/functions.inc.php:z
- - ./data/web/inc/functions.auth.inc.php:/mailcowauth/functions.auth.inc.php:z
- - ./data/web/inc/sessions.inc.php:/mailcowauth/sessions.inc.php:z
- - sogo-web-vol-1:/usr/lib/GNUstep/SOGo/
- ports:
- - "${HTTPS_BIND:-}:${HTTPS_PORT:-443}:${HTTPS_PORT:-443}"
- - "${HTTP_BIND:-}:${HTTP_PORT:-80}:${HTTP_PORT:-80}"
- restart: always
- networks:
- mailcow-network:
- aliases:
- - nginx
-
- acme-mailcow:
- depends_on:
- nginx-mailcow:
- condition: service_started
- unbound-mailcow:
- condition: service_healthy
- image: ghcr.io/mailcow/acme:1.94
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- environment:
- - LOG_LINES=${LOG_LINES:-9999}
- - ADDITIONAL_SAN=${ADDITIONAL_SAN}
- - AUTODISCOVER_SAN=${AUTODISCOVER_SAN:-y}
- - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- - DBNAME=${DBNAME}
- - DBUSER=${DBUSER}
- - DBPASS=${DBPASS}
- - SKIP_LETS_ENCRYPT=${SKIP_LETS_ENCRYPT:-n}
- - COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
- - DIRECTORY_URL=${DIRECTORY_URL:-}
- - ENABLE_SSL_SNI=${ENABLE_SSL_SNI:-n}
- - SKIP_IP_CHECK=${SKIP_IP_CHECK:-n}
- - SKIP_HTTP_VERIFICATION=${SKIP_HTTP_VERIFICATION:-n}
- - ONLY_MAILCOW_HOSTNAME=${ONLY_MAILCOW_HOSTNAME:-n}
- - LE_STAGING=${LE_STAGING:-n}
- - TZ=${TZ}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - SNAT_TO_SOURCE=${SNAT_TO_SOURCE:-n}
- - SNAT6_TO_SOURCE=${SNAT6_TO_SOURCE:-n}
- volumes:
- - ./data/web/.well-known/acme-challenge:/var/www/acme:z
- - ./data/assets/ssl:/var/lib/acme/:z
- - ./data/assets/ssl-example:/var/lib/ssl-example/:ro,Z
- - mysql-socket-vol-1:/var/run/mysqld/:z
- restart: always
- networks:
- mailcow-network:
- aliases:
- - acme
-
- netfilter-mailcow:
- image: ghcr.io/mailcow/netfilter:1.63
- stop_grace_period: 30s
- restart: always
- privileged: true
- environment:
- - TZ=${TZ}
- - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- - IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
- - SNAT_TO_SOURCE=${SNAT_TO_SOURCE:-n}
- - SNAT6_TO_SOURCE=${SNAT6_TO_SOURCE:-n}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - MAILCOW_REPLICA_IP=${MAILCOW_REPLICA_IP:-}
- - DISABLE_NETFILTER_ISOLATION_RULE=${DISABLE_NETFILTER_ISOLATION_RULE:-n}
- network_mode: "host"
- volumes:
- - /lib/modules:/lib/modules:ro
-
- watchdog-mailcow:
- image: ghcr.io/mailcow/watchdog:2.09
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- tmpfs:
- - /tmp
- volumes:
- - rspamd-vol-1:/var/lib/rspamd
- - mysql-socket-vol-1:/var/run/mysqld/:z
- - postfix-vol-1:/var/spool/postfix
- - ./data/assets/ssl:/etc/ssl/mail/:ro,z
- restart: always
- depends_on:
- - postfix-mailcow
- - dovecot-mailcow
- - mysql-mailcow
- - acme-mailcow
- - redis-mailcow
- environment:
- - IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
- - LOG_LINES=${LOG_LINES:-9999}
- - TZ=${TZ}
- - DBNAME=${DBNAME}
- - DBUSER=${DBUSER}
- - DBPASS=${DBPASS}
- - DBROOT=${DBROOT}
- - USE_WATCHDOG=${USE_WATCHDOG:-n}
- - WATCHDOG_NOTIFY_EMAIL=${WATCHDOG_NOTIFY_EMAIL:-}
- - WATCHDOG_NOTIFY_BAN=${WATCHDOG_NOTIFY_BAN:-y}
- - WATCHDOG_NOTIFY_START=${WATCHDOG_NOTIFY_START:-y}
- - WATCHDOG_SUBJECT=${WATCHDOG_SUBJECT:-Watchdog ALERT}
- - WATCHDOG_NOTIFY_WEBHOOK=${WATCHDOG_NOTIFY_WEBHOOK:-}
- - WATCHDOG_NOTIFY_WEBHOOK_BODY=${WATCHDOG_NOTIFY_WEBHOOK_BODY:-}
- - WATCHDOG_EXTERNAL_CHECKS=${WATCHDOG_EXTERNAL_CHECKS:-n}
- - WATCHDOG_MYSQL_REPLICATION_CHECKS=${WATCHDOG_MYSQL_REPLICATION_CHECKS:-n}
- - WATCHDOG_VERBOSE=${WATCHDOG_VERBOSE:-n}
- - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- - COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
- - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- - IP_BY_DOCKER_API=${IP_BY_DOCKER_API:-0}
- - CHECK_UNBOUND=${CHECK_UNBOUND:-1}
- - SKIP_CLAMD=${SKIP_CLAMD:-n}
- - SKIP_OLEFY=${SKIP_OLEFY:-n}
- - SKIP_LETS_ENCRYPT=${SKIP_LETS_ENCRYPT:-n}
- - SKIP_SOGO=${SKIP_SOGO:-n}
- - HTTPS_PORT=${HTTPS_PORT:-443}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- - EXTERNAL_CHECKS_THRESHOLD=${EXTERNAL_CHECKS_THRESHOLD:-1}
- - NGINX_THRESHOLD=${NGINX_THRESHOLD:-5}
- - UNBOUND_THRESHOLD=${UNBOUND_THRESHOLD:-5}
- - REDIS_THRESHOLD=${REDIS_THRESHOLD:-5}
- - MYSQL_THRESHOLD=${MYSQL_THRESHOLD:-5}
- - MYSQL_REPLICATION_THRESHOLD=${MYSQL_REPLICATION_THRESHOLD:-1}
- - SOGO_THRESHOLD=${SOGO_THRESHOLD:-3}
- - POSTFIX_THRESHOLD=${POSTFIX_THRESHOLD:-8}
- - POSTFIX_TLSPOL_THRESHOLD=${POSTFIX_TLSPOL_THRESHOLD:-8}
- - CLAMD_THRESHOLD=${CLAMD_THRESHOLD:-15}
- - DOVECOT_THRESHOLD=${DOVECOT_THRESHOLD:-12}
- - DOVECOT_REPL_THRESHOLD=${DOVECOT_REPL_THRESHOLD:-20}
- - PHPFPM_THRESHOLD=${PHPFPM_THRESHOLD:-5}
- - RATELIMIT_THRESHOLD=${RATELIMIT_THRESHOLD:-1}
- - FAIL2BAN_THRESHOLD=${FAIL2BAN_THRESHOLD:-1}
- - ACME_THRESHOLD=${ACME_THRESHOLD:-1}
- - RSPAMD_THRESHOLD=${RSPAMD_THRESHOLD:-5}
- - OLEFY_THRESHOLD=${OLEFY_THRESHOLD:-5}
- - MAILQ_THRESHOLD=${MAILQ_THRESHOLD:-20}
- - MAILQ_CRIT=${MAILQ_CRIT:-30}
- - DEV_MODE=${DEV_MODE:-n}
- networks:
- mailcow-network:
- aliases:
- - watchdog
-
- dockerapi-mailcow:
- image: ghcr.io/mailcow/dockerapi:2.11
- security_opt:
- - label=disable
- restart: always
- dns:
- - ${IPV4_NETWORK:-172.22.1}.254
- environment:
- - DBROOT=${DBROOT}
- - TZ=${TZ}
- - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- - REDISPASS=${REDISPASS}
- volumes:
- - /var/run/docker.sock:/var/run/docker.sock:ro
- networks:
- mailcow-network:
- aliases:
- - dockerapi
-
- olefy-mailcow:
- image: ghcr.io/mailcow/olefy:1.15
- restart: always
- environment:
- - TZ=${TZ}
- - OLEFY_BINDADDRESS=0.0.0.0
- - OLEFY_BINDPORT=10055
- - OLEFY_TMPDIR=/tmp
- - OLEFY_PYTHON_PATH=/usr/bin/python3
- - OLEFY_OLEVBA_PATH=/usr/bin/olevba
- - OLEFY_LOGLVL=20
- - OLEFY_MINLENGTH=500
- - OLEFY_DEL_TMP=1
- - SKIP_OLEFY=${SKIP_OLEFY:-n}
- networks:
- mailcow-network:
- aliases:
- - olefy
-
- ofelia-mailcow:
- image: mcuadros/ofelia:latest
- restart: always
- command: daemon --docker -f label=com.docker.compose.project=${COMPOSE_PROJECT_NAME}
- environment:
- - TZ=${TZ}
- - COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME}
- depends_on:
- - sogo-mailcow
- - dovecot-mailcow
- labels:
- ofelia.enabled: "true"
- security_opt:
- - label=disable
- volumes:
- - /var/run/docker.sock:/var/run/docker.sock:ro
- networks:
- mailcow-network:
- aliases:
- - ofelia
-
-networks:
- mailcow-network:
- driver: bridge
- driver_opts:
- com.docker.network.bridge.name: br-mailcow
- enable_ipv6: ${ENABLE_IPV6:-true}
- ipam:
- driver: default
- config:
- - subnet: ${IPV4_NETWORK:-172.22.1}.0/24
- - subnet: ${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
-
-volumes:
- vmail-vol-1:
- vmail-index-vol-1:
- mysql-vol-1:
- mysql-socket-vol-1:
- redis-vol-1:
- rspamd-vol-1:
- postfix-vol-1:
- postfix-tlspol-vol-1:
- crypt-vol-1:
- sogo-web-vol-1:
- sogo-userdata-backup-vol-1:
- clamd-db-vol-1:
+ webmail:
+ image: ghcr.io/the-djmaze/snappymail:latest
+ container_name: webmail
+ depends_on:
+ - mailserver
+ ports:
+ - "8080:80"
+ environment:
+ # Log to stdout so container logs are visible in Coolify and docker logs
+ - SNAPPYMAIL_LOG_TO_STDOUT=1
+ volumes:
+ - ./docker-data/snappymail/:/snappymail/data/
+ restart: unless-stopped
\ No newline at end of file
diff --git a/generate_config.sh b/generate_config.sh
deleted file mode 100755
index 393d2fc..0000000
--- a/generate_config.sh
+++ /dev/null
@@ -1,517 +0,0 @@
-#!/usr/bin/env bash
-
-# Ensure the script is run from the directory that contains a link of .env
-# Resolve the directory this script lives in for consistent behavior when invoked from elsewhere
-SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" >/dev/null 2>&1 && pwd)"
-
-# Ensure script is executed in the mailcow installation directory by checking for a .env symlink that points to mailcow.conf
-if [ ! -L "${PWD}/.env" ]; then
- echo -e "\e[33mPlease run this script from the mailcow installation directory.\e[0m"
- echo -e " \e[36mcd /path/to/mailcow && ./generate_config.sh\e[0m"
- exit 1
-fi
-
-# Verify the .env symlink points to a mailcow.conf file
-env_target="$(readlink -f "${PWD}/.env" 2>/dev/null || true)"
-if [ -z "$env_target" ] || [ "$(basename "$env_target")" != "mailcow.conf" ]; then
- echo -e "\e[31mThe found .env symlink does not point to a mailcow.conf file.\e[0m"
- echo -e "\e[33mPlease create a symbolic link .env -> mailcow.conf inside the mailcow directory and run this script there.\e[0m"
- echo -e "\e[33mNote: 'ln -s mailcow.conf .env' will create the symlink even if mailcow.conf does not yet exist.\e[0m"
- echo -e " \e[36mcd /path/to/mailcow && ln -s mailcow.conf .env && ./generate_config.sh\e[0m"
- exit 1
-fi
-
-# Load mailcow Generic Scripts
-source _modules/scripts/core.sh
-source _modules/scripts/ipv6_controller.sh
-
-set -o pipefail
-
-get_installed_tools
-get_docker_version
-
-if [[ $docker_version -lt 24 ]]; then
- echo -e "\e[31mCannot find Docker with a Version higher or equals 24.0.0\e[0m"
- echo -e "\e[33mmailcow needs a newer Docker version to work properly...\e[0m"
- echo -e "\e[31mPlease update your Docker installation... exiting\e[0m"
- exit 1
-fi
-
-detect_bad_asn
-
-### If generate_config.sh is started with --dev or -d it will not check out nightly or master branch and will keep on the current branch
-if [[ ${1} == "--dev" || ${1} == "-d" ]]; then
- SKIP_BRANCH=y
-else
- SKIP_BRANCH=n
-fi
-
-if [ -f mailcow.conf ]; then
- read -r -p "A config file exists and will be overwritten, are you sure you want to continue? [y/N] " response
- case $response in
- [yY][eE][sS]|[yY])
- mv mailcow.conf mailcow.conf_backup
- chmod 600 mailcow.conf_backup
- ;;
- *)
- exit 1
- ;;
- esac
-fi
-
-echo "Press enter to confirm the detected value '[value]' where applicable or enter a custom value."
-while [ -z "${MAILCOW_HOSTNAME}" ]; do
- read -p "Mail server hostname (FQDN) - this is not your mail domain, but your mail servers hostname: " -e MAILCOW_HOSTNAME
- DOTS=${MAILCOW_HOSTNAME//[^.]};
- if [ ${#DOTS} -lt 1 ]; then
- echo -e "\e[31mMAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) is not a FQDN!\e[0m"
- sleep 1
- echo "Please change it to a FQDN and redeploy the stack with docker(-)compose up -d"
- exit 1
- elif [[ "${MAILCOW_HOSTNAME: -1}" == "." ]]; then
- echo "MAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) is ending with a dot. This is not a valid FQDN!"
- exit 1
- elif [ ${#DOTS} -eq 1 ]; then
- echo -e "\e[33mMAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) does not contain a Subdomain. This is not fully tested and may cause issues.\e[0m"
- echo "Find more information about why this message exists here: https://github.com/mailcow/mailcow-dockerized/issues/1572"
- read -r -p "Do you want to proceed anyway? [y/N] " response
- if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
- echo "OK. Procceding."
- else
- echo "OK. Exiting."
- exit 1
- fi
- fi
-done
-
-if [ -a /etc/timezone ]; then
- DETECTED_TZ=$(cat /etc/timezone)
-elif [ -a /etc/localtime ]; then
- DETECTED_TZ=$(readlink /etc/localtime|sed -n 's|^.*zoneinfo/||p')
-fi
-
-while [ -z "${MAILCOW_TZ}" ]; do
- if [ -z "${DETECTED_TZ}" ]; then
- read -p "Timezone: " -e MAILCOW_TZ
- else
- read -p "Timezone [${DETECTED_TZ}]: " -e MAILCOW_TZ
- [ -z "${MAILCOW_TZ}" ] && MAILCOW_TZ=${DETECTED_TZ}
- fi
-done
-
-MEM_TOTAL=$(awk '/MemTotal/ {print $2}' /proc/meminfo)
-
-if [ -z "${SKIP_CLAMD}" ]; then
- if [ "${MEM_TOTAL}" -le "2621440" ]; then
- echo "Installed memory is <= 2.5 GiB. It is recommended to disable ClamAV to prevent out-of-memory situations."
- echo "ClamAV can be re-enabled by setting SKIP_CLAMD=n in mailcow.conf."
- read -r -p "Do you want to disable ClamAV now? [Y/n] " response
- case $response in
- [nN][oO]|[nN])
- SKIP_CLAMD=n
- ;;
- *)
- SKIP_CLAMD=y
- ;;
- esac
- else
- SKIP_CLAMD=n
- fi
-fi
-
-if [[ ${SKIP_BRANCH} != y ]]; then
- echo "Which branch of mailcow do you want to use?"
- echo ""
- echo "Available Branches:"
- echo "- master branch (stable updates) | default, recommended [1]"
- echo "- nightly branch (unstable updates, testing) | not-production ready [2]"
- echo "- legacy branch (supported until February 2026) | deprecated, security updates only [3]"
- sleep 1
-
- while [ -z "${MAILCOW_BRANCH}" ]; do
- read -r -p "Choose the Branch with it's number [1/2/3] " branch
- case $branch in
- [3])
- MAILCOW_BRANCH="legacy"
- ;;
- [2])
- MAILCOW_BRANCH="nightly"
- ;;
- *)
- MAILCOW_BRANCH="master"
- ;;
- esac
- done
-
- git fetch --all
- git checkout -f "$MAILCOW_BRANCH"
-
-elif [[ ${SKIP_BRANCH} == y ]]; then
- echo -e "\033[33mEnabled Dev Mode.\033[0m"
- echo -e "\033[33mNot checking out a different branch!\033[0m"
- MAILCOW_BRANCH=$(git rev-parse --short $(git rev-parse @{upstream}))
-
-else
- echo -e "\033[31mCould not determine branch input..."
- echo -e "\033[31mExiting."
- exit 1
-fi
-
-if [ ! -z "${MAILCOW_BRANCH}" ]; then
- git_branch=${MAILCOW_BRANCH}
-fi
-
-configure_ipv6
-
-[ ! -f ./data/conf/rspamd/override.d/worker-controller-password.inc ] && echo '# Placeholder' > ./data/conf/rspamd/override.d/worker-controller-password.inc
-
-cat << EOF > mailcow.conf
-# ------------------------------
-# mailcow web ui configuration
-# ------------------------------
-# example.org is _not_ a valid hostname, use a fqdn here.
-# Default admin user is "admin"
-# Default password is "moohoo"
-MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
-
-# Password hash algorithm
-# Only certain password hash algorithm are supported. For a fully list of supported schemes,
-# see https://docs.mailcow.email/models/model-passwd/
-MAILCOW_PASS_SCHEME=BLF-CRYPT
-
-# ------------------------------
-# SQL database configuration
-# ------------------------------
-DBNAME=mailcow
-DBUSER=mailcow
-
-# Please use long, random alphanumeric strings (A-Za-z0-9)
-DBPASS=$(LC_ALL=C /dev/null | head -c 28)
-DBROOT=$(LC_ALL=C /dev/null | head -c 28)
-
-# ------------------------------
-# REDIS configuration
-# ------------------------------
-REDISPASS=$(LC_ALL=C /dev/null | head -c 28)
-
-# ------------------------------
-# HTTP/S Bindings
-# ------------------------------
-
-# You should use HTTPS, but in case of SSL offloaded reverse proxies:
-# Might be important: This will also change the binding within the container.
-# If you use a proxy within Docker, point it to the ports you set below.
-# Do _not_ use IP:PORT in HTTP(S)_BIND or HTTP(S)_PORT
-# IMPORTANT: Do not use port 8081, 9081, 9082 or 65510!
-# Example: HTTP_BIND=1.2.3.4
-# For IPv4 leave it as it is: HTTP_BIND= & HTTPS_PORT=
-# For IPv6 see https://docs.mailcow.email/post_installation/firststeps-ip_bindings/
-HTTP_PORT=80
-HTTP_BIND=
-
-HTTPS_PORT=443
-HTTPS_BIND=
-
-# Redirect HTTP connections to HTTPS - y/n
-HTTP_REDIRECT=y
-
-# ------------------------------
-# Other bindings
-# ------------------------------
-# You should leave that alone
-# Format: 11.22.33.44:25 or 12.34.56.78:465 etc.
-SMTP_PORT=25
-SMTPS_PORT=465
-SUBMISSION_PORT=587
-IMAP_PORT=143
-IMAPS_PORT=993
-POP_PORT=110
-POPS_PORT=995
-SIEVE_PORT=4190
-DOVEADM_PORT=127.0.0.1:19991
-SQL_PORT=127.0.0.1:13306
-REDIS_PORT=127.0.0.1:7654
-
-# Your timezone
-# See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for a list of timezones
-# Use the column named 'TZ identifier' + pay attention for the column named 'Notes'
-TZ=${MAILCOW_TZ}
-
-# Fixed project name
-# Please use lowercase letters only
-COMPOSE_PROJECT_NAME=mailcowdockerized
-
-# Used Docker Compose version
-# Switch here between native (compose plugin) and standalone
-# For more information take a look at the mailcow docs regarding the configuration options.
-# Normally this should be untouched but if you decided to use either of those you can switch it manually here.
-# Please be aware that at least one of those variants should be installed on your machine or mailcow will fail.
-DOCKER_COMPOSE_VERSION=${COMPOSE_VERSION}
-
-# Set this to "allow" to enable the anyone pseudo user. Disabled by default.
-# When enabled, ACL can be created, that apply to "All authenticated users"
-# This should probably only be activated on mail hosts, that are used exclusively by one organisation.
-# Otherwise a user might share data with too many other users.
-ACL_ANYONE=disallow
-
-# Garbage collector cleanup
-# Deleted domains and mailboxes are moved to /var/vmail/_garbage/timestamp_sanitizedstring
-# How long should objects remain in the garbage until they are being deleted? (value in minutes)
-# Check interval is hourly
-MAILDIR_GC_TIME=7200
-
-# Additional SAN for the certificate
-#
-# You can use wildcard records to create specific names for every domain you add to mailcow.
-# Example: Add domains "example.com" and "example.net" to mailcow, change ADDITIONAL_SAN to a value like:
-#ADDITIONAL_SAN=imap.*,smtp.*
-# This will expand the certificate to "imap.example.com", "smtp.example.com", "imap.example.net", "smtp.example.net"
-# plus every domain you add in the future.
-#
-# You can also just add static names...
-#ADDITIONAL_SAN=srv1.example.net
-# ...or combine wildcard and static names:
-#ADDITIONAL_SAN=imap.*,srv1.example.com
-ADDITIONAL_SAN=
-
-# Obtain certificates for autodiscover.* and autoconfig.* domains.
-# This can be useful to switch off in case you are in a scenario where a reverse proxy already handles those.
-# There are mixed scenarios where ports 80,443 are occupied and you do not want to share certs
-# between services. So acme-mailcow obtains for maildomains and all web-things get handled
-# in the reverse proxy.
-AUTODISCOVER_SAN=y
-
-# Additional server names for mailcow UI
-#
-# Specify alternative addresses for the mailcow UI to respond to
-# This is useful when you set mail.* as ADDITIONAL_SAN and want to make sure mail.maildomain.com will always point to the mailcow UI.
-# If the server name does not match a known site, Nginx decides by best-guess and may redirect users to the wrong web root.
-# You can understand this as server_name directive in Nginx.
-# Comma separated list without spaces! Example: ADDITIONAL_SERVER_NAMES=a.b.c,d.e.f
-ADDITIONAL_SERVER_NAMES=
-
-# Skip running ACME (acme-mailcow, Let's Encrypt certs) - y/n
-SKIP_LETS_ENCRYPT=n
-
-# Create separate certificates for all domains - y/n
-# this will allow adding more than 100 domains, but some email clients will not be able to connect with alternative hostnames
-# see https://doc.dovecot.org/admin_manual/ssl/sni_support
-ENABLE_SSL_SNI=n
-
-# Skip IPv4 check in ACME container - y/n
-SKIP_IP_CHECK=n
-
-# Skip HTTP verification in ACME container - y/n
-SKIP_HTTP_VERIFICATION=n
-
-# Skip Unbound (DNS Resolver) Healthchecks (NOT Recommended!) - y/n
-SKIP_UNBOUND_HEALTHCHECK=n
-
-# Skip ClamAV (clamd-mailcow) anti-virus (Rspamd will auto-detect a missing ClamAV container) - y/n
-SKIP_CLAMD=${SKIP_CLAMD}
-
-# Skip Olefy (olefy-mailcow) anti-virus for Office documents (Rspamd will auto-detect a missing Olefy container) - y/n
-SKIP_OLEFY=n
-
-# Skip SOGo: Will disable SOGo integration and therefore webmail, DAV protocols and ActiveSync support (experimental, unsupported, not fully implemented) - y/n
-SKIP_SOGO=n
-
-# Skip FTS (Fulltext Search) for Dovecot on low-memory, low-threaded systems or if you simply want to disable it.
-# Dovecot inside mailcow use Flatcurve as FTS Backend.
-SKIP_FTS=n
-
-# Dovecot Indexing (FTS) Process maximum heap size in MB, there is no recommendation, please see Dovecot docs.
-# Flatcurve (Xapian backend) is used as the FTS Indexer. It is supposed to be efficient in CPU and RAM consumption.
-# However: Please always monitor your Resource consumption!
-FTS_HEAP=128
-
-# Controls how many processes the Dovecot indexing process can spawn at max.
-# Too many indexing processes can use a lot of CPU and Disk I/O.
-# Please visit: https://doc.dovecot.org/configuration_manual/service_configuration/#indexer-worker for more information
-FTS_PROCS=1
-
-# Allow admins to log into SOGo as email user (without any password)
-ALLOW_ADMIN_EMAIL_LOGIN=n
-
-# Enable watchdog (watchdog-mailcow) to restart unhealthy containers
-USE_WATCHDOG=y
-
-# Send watchdog notifications by mail (sent from watchdog@MAILCOW_HOSTNAME)
-# CAUTION:
-# 1. You should use external recipients
-# 2. Mails are sent unsigned (no DKIM)
-# 3. If you use DMARC, create a separate DMARC policy ("v=DMARC1; p=none;" in _dmarc.MAILCOW_HOSTNAME)
-# Multiple rcpts allowed, NO quotation marks, NO spaces
-#WATCHDOG_NOTIFY_EMAIL=a@example.com,b@example.com,c@example.com
-#WATCHDOG_NOTIFY_EMAIL=
-
-# Send notifications to a webhook URL that receives a POST request with the content type "application/json".
-# You can use this to send notifications to services like Discord, Slack and others.
-#WATCHDOG_NOTIFY_WEBHOOK=https://discord.com/api/webhooks/XXXXXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-# JSON body included in the webhook POST request. Needs to be in single quotes.
-# Following variables are available: SUBJECT, BODY
-#WATCHDOG_NOTIFY_WEBHOOK_BODY='{"username": "mailcow Watchdog", "content": "**${SUBJECT}**\n${BODY}"}'
-
-# Notify about banned IP (includes whois lookup)
-WATCHDOG_NOTIFY_BAN=n
-
-# Send a notification when the watchdog is started.
-WATCHDOG_NOTIFY_START=y
-
-# Subject for watchdog mails. Defaults to "Watchdog ALERT" followed by the error message.
-#WATCHDOG_SUBJECT=
-
-# Checks if mailcow is an open relay. Requires a SAL. More checks will follow.
-# https://www.servercow.de/mailcow?lang=en
-# https://www.servercow.de/mailcow?lang=de
-# No data is collected. Opt-in and anonymous.
-# Will only work with unmodified mailcow setups.
-WATCHDOG_EXTERNAL_CHECKS=n
-
-# Enable watchdog verbose logging
-WATCHDOG_VERBOSE=n
-
-# Max log lines per service to keep in Redis logs
-LOG_LINES=9999
-
-# Internal IPv4 /24 subnet, format n.n.n (expands to n.n.n.0/24)
-# Use private IPv4 addresses only, see https://en.wikipedia.org/wiki/Private_network#Private_IPv4_addresses
-IPV4_NETWORK=172.22.1
-
-# Internal IPv6 subnet in fc00::/7
-# Use private IPv6 addresses only, see https://en.wikipedia.org/wiki/Private_network#Private_IPv6_addresses
-IPV6_NETWORK=fd4d:6169:6c63:6f77::/64
-
-# Use this IPv4 for outgoing connections (SNAT)
-#SNAT_TO_SOURCE=
-
-# Use this IPv6 for outgoing connections (SNAT)
-#SNAT6_TO_SOURCE=
-
-# Create or override an API key for the web UI
-# You _must_ define API_ALLOW_FROM, which is a comma separated list of IPs
-# An API key defined as API_KEY has read-write access
-# An API key defined as API_KEY_READ_ONLY has read-only access
-# Allowed chars for API_KEY and API_KEY_READ_ONLY: a-z, A-Z, 0-9, -
-# You can define API_KEY and/or API_KEY_READ_ONLY
-
-#API_KEY=
-#API_KEY_READ_ONLY=
-#API_ALLOW_FROM=172.22.1.1,127.0.0.1
-
-# mail_home is ~/Maildir
-MAILDIR_SUB=Maildir
-
-# SOGo session timeout in minutes
-SOGO_EXPIRE_SESSION=480
-
-# SOGo URL encryption key (exactly 16 characters, limited to A–Z, a–z, 0–9)
-# This key is used to encrypt email addresses within SOGo URLs
-SOGO_URL_ENCRYPTION_KEY=$(LC_ALL=C /dev/null | head -c 16)
-
-# DOVECOT_MASTER_USER and DOVECOT_MASTER_PASS must both be provided. No special chars.
-# Empty by default to auto-generate master user and password on start.
-# User expands to DOVECOT_MASTER_USER@mailcow.local
-# LEAVE EMPTY IF UNSURE
-DOVECOT_MASTER_USER=
-# LEAVE EMPTY IF UNSURE
-DOVECOT_MASTER_PASS=
-
-# WebAuthn device manufacturer verification
-# After setting WEBAUTHN_ONLY_TRUSTED_VENDORS=y only devices from trusted manufacturers are allowed
-# root certificates can be placed for validation under mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates
-WEBAUTHN_ONLY_TRUSTED_VENDORS=n
-
-# Spamhaus Data Query Service Key
-# Optional: Leave empty for none
-# Enter your key here if you are using a blocked ASN (OVH, AWS, Cloudflare e.g) for the unregistered Spamhaus Blocklist.
-# If empty, it will completely disable Spamhaus blocklists if it detects that you are running on a server using a blocked AS.
-# Otherwise it will work normally.
-SPAMHAUS_DQS_KEY=
-
-# IPv6 Controller Section
-# This variable controls the usage of IPv6 within mailcow.
-# Can either be true or false | Defaults to true
-# WARNING: MAKE SURE TO PROPERLY CONFIGURE IPv6 ON YOUR HOST FIRST BEFORE ENABLING THIS AS FAULTY CONFIGURATIONS CAN LEAD TO OPEN RELAYS!
-# A COMPLETE DOCKER STACK REBUILD (compose down && compose up -d) IS NEEDED TO APPLY THIS.
-ENABLE_IPV6=${IPV6_BOOL}
-
-# Prevent netfilter from setting an iptables/nftables rule to isolate the mailcow docker network - y/n
-# CAUTION: Disabling this may expose container ports to other neighbors on the same subnet, even if the ports are bound to localhost
-DISABLE_NETFILTER_ISOLATION_RULE=n
-EOF
-
-mkdir -p data/assets/ssl
-
-chmod 600 mailcow.conf
-
-# copy but don't overwrite existing certificate
-echo "Generating snake-oil certificate..."
-# Making Willich more popular
-openssl req -x509 -newkey rsa:4096 -keyout data/assets/ssl-example/key.pem -out data/assets/ssl-example/cert.pem -days 365 -subj "/C=DE/ST=NRW/L=Willich/O=mailcow/OU=mailcow/CN=${MAILCOW_HOSTNAME}" -sha256 -nodes
-echo "Copying snake-oil certificate..."
-cp -n -d data/assets/ssl-example/*.pem data/assets/ssl/
-
-# Set app_info.inc.php
-case ${git_branch} in
- master)
- mailcow_git_version=$(git describe --tags `git rev-list --tags --max-count=1`)
- ;;
- nightly)
- mailcow_git_version=$(git rev-parse --short $(git rev-parse @{upstream}))
- mailcow_last_git_version=""
- ;;
- legacy)
- mailcow_git_version=$(git rev-parse --short $(git rev-parse @{upstream}))
- mailcow_last_git_version=""
- ;;
- *)
- mailcow_git_version=$(git rev-parse --short HEAD)
- mailcow_last_git_version=""
- ;;
-esac
-# if [ ${git_branch} == "master" ]; then
-# mailcow_git_version=$(git describe --tags `git rev-list --tags --max-count=1`)
-# elif [ ${git_branch} == "nightly" ]; then
-# mailcow_git_version=$(git rev-parse --short $(git rev-parse @{upstream}))
-# mailcow_last_git_version=""
-# else
-# mailcow_git_version=$(git rev-parse --short HEAD)
-# mailcow_last_git_version=""
-# fi
-
-if [[ $SKIP_BRANCH != "y" ]]; then
-mailcow_git_commit=$(git rev-parse origin/${git_branch})
-mailcow_git_commit_date=$(git log -1 --format=%ci @{upstream} )
-else
-mailcow_git_commit=$(git rev-parse ${git_branch})
-mailcow_git_commit_date=$(git log -1 --format=%ci @{upstream} )
-git_branch=$(git rev-parse --abbrev-ref HEAD)
-fi
-
-if [ $? -eq 0 ]; then
- echo ' data/web/inc/app_info.inc.php
- echo ' $MAILCOW_GIT_VERSION="'$mailcow_git_version'";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_LAST_GIT_VERSION="";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_GIT_OWNER="mailcow";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_GIT_REPO="mailcow-dockerized";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_GIT_URL="https://github.com/mailcow/mailcow-dockerized";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_GIT_COMMIT="'$mailcow_git_commit'";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_GIT_COMMIT_DATE="'$mailcow_git_commit_date'";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_BRANCH="'$git_branch'";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_UPDATEDAT='$(date +%s)';' >> data/web/inc/app_info.inc.php
- echo '?>' >> data/web/inc/app_info.inc.php
-else
- echo ' data/web/inc/app_info.inc.php
- echo ' $MAILCOW_GIT_VERSION="'$mailcow_git_version'";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_LAST_GIT_VERSION="";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_GIT_OWNER="mailcow";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_GIT_REPO="mailcow-dockerized";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_GIT_URL="https://github.com/mailcow/mailcow-dockerized";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_GIT_COMMIT="";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_GIT_COMMIT_DATE="";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_BRANCH="'$git_branch'";' >> data/web/inc/app_info.inc.php
- echo ' $MAILCOW_UPDATEDAT='$(date +%s)';' >> data/web/inc/app_info.inc.php
- echo '?>' >> data/web/inc/app_info.inc.php
- echo -e "\e[33mCannot determine current git repository version...\e[0m"
-fi
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..91e6063
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,63 @@
+# Mail Stack on Coolify with OIDC Webmail
+
+This stack pairs **docker-mailserver** with **SnappyMail** as a modern webmail UI that can sit behind your OIDC provider. Deploy it through Coolify with this repository.
+
+## Components
+- docker-mailserver: SMTP/IMAP server with spam/AV/Fail2Ban enabled.
+- SnappyMail: lightweight webmail with OAuth2/OIDC login support.
+
+## Prerequisites
+- DNS: `MX` record to `mail.your-domain.tld`, plus `A`/`AAAA` for both `mail.your-domain.tld` and `webmail.your-domain.tld`.
+- TLS: issue certificates (Coolify can request via Traefik/Let’s Encrypt if you publish through it).
+- SMTP ports 25/465/587 and IMAP 993 open to the internet.
+- An OIDC provider (e.g., Authentik, Keycloak, Azure AD) with a client ready to configure.
+
+## Deploy with Coolify
+1. **Create an application from this repo** in Coolify and choose “Docker Compose”.
+2. **Volumes**: Coolify will create them from the compose file paths. Ensure the persistent paths below map to durable storage:
+ - `./docker-data/dms/mail-data/`, `./docker-data/dms/mail-state/`, `./docker-data/dms/mail-logs/`, `./docker-data/dms/config/`
+ - `./docker-data/snappymail/`
+3. **Environment**: adjust `hostname` for the mailserver and expose any extra docker-mailserver envs you need (aliases, relays, etc.).
+4. **Networking**: publish ports 25/465/587/993 for mail delivery. Expose port 8080 from the `webmail` service to the internet (ideally behind HTTPS via Coolify/Traefik). If you front it with Traefik, set the appropriate labels and disable the direct `ports` stanza.
+5. **Deploy** the stack. Coolify will start `mailserver` and `webmail` containers.
+
+## Bootstrap docker-mailserver
+Run these once after the containers are healthy (from the host or via Coolify shell):
+
+```bash
+docker compose exec mailserver setup email add user@your-domain.tld "SuperSecretPassword"
+docker compose exec mailserver setup alias add postmaster@your-domain.tld user@your-domain.tld
+```
+
+Add DNS TXT records for SPF/DKIM/DMARC using docker-mailserver guidance, then reload:
+
+```bash
+docker compose exec mailserver setup reload
+```
+
+## Configure SnappyMail for IMAP/SMTP
+1. Open the admin panel at `https://webmail.your-domain.tld/?admin` (default admin password is shown on first run; change it immediately).
+2. Set **IMAP** host to `mailserver`, port `993`, security **SSL/TLS**.
+3. Set **SMTP** host to `mailserver`, port `587`, security **STARTTLS**, authentication **Use user credentials**.
+4. Save and test with one of the mail accounts you created above.
+
+## Enable OIDC in SnappyMail
+SnappyMail supports OAuth2/OIDC providers. Configure it in the admin UI:
+1. In **Admin → Domains/Auth → OAuth**, add a **Custom / Generic OIDC** provider.
+2. When prompted, SnappyMail shows a **Redirect URI**; copy this exact value into your OIDC client configuration.
+3. In your OIDC provider, create a public/confidential client with these basics:
+ - **Grant type**: Authorization Code with PKCE (preferred) or standard code.
+ - **Scopes**: `openid email profile`.
+ - **Redirect URI**: the one SnappyMail displayed.
+4. Back in SnappyMail, fill the provider fields:
+ - **Authorization endpoint** and **Token endpoint** from your IdP.
+ - **UserInfo endpoint** (for email/subject mapping).
+ - **Client ID/Secret** matching the client you created.
+ - **Login attribute mapping**: map email/subject to the mailbox name (e.g., `email` → `user@your-domain.tld`).
+5. Save and test “Login with ”. Successful OIDC login should drop you into the mailbox without prompting for a separate password.
+
+## Operating tips
+- Back up `./docker-data/` regularly; it holds mail, state, and SnappyMail config.
+- Use Coolify health checks to surface container issues; restart policies are already defined in the compose file.
+- For HTTPS, prefer running `webmail` behind Coolify’s Traefik with automatic certificates instead of exposing port 8080 directly.
+- If you rotate OIDC credentials, update them in SnappyMail admin immediately to avoid login failures.