From 01da6ddafef02de1ea17bda689229a9ff77031e8 Mon Sep 17 00:00:00 2001 From: Georg Date: Sun, 8 Aug 2021 15:34:55 +0200 Subject: Init Mailcow Signed-off-by: Georg --- mailcow/data/conf/nginx/custom_sogo_external.conf | 52 ++ mailcow/data/conf/postfix/extra.cf | 4 + mailcow/docker-compose.yml | 675 ++++++++++++++++++++++ mailcow/mailcow.conf | 244 ++++++++ mailcow/mailcow.service | 14 + 5 files changed, 989 insertions(+) create mode 100644 mailcow/data/conf/nginx/custom_sogo_external.conf create mode 100644 mailcow/data/conf/postfix/extra.cf create mode 100644 mailcow/docker-compose.yml create mode 100644 mailcow/mailcow.conf create mode 100644 mailcow/mailcow.service diff --git a/mailcow/data/conf/nginx/custom_sogo_external.conf b/mailcow/data/conf/nginx/custom_sogo_external.conf new file mode 100644 index 0000000..4965263 --- /dev/null +++ b/mailcow/data/conf/nginx/custom_sogo_external.conf @@ -0,0 +1,52 @@ +server { + listen 8081; + #server_name sogo.zz0.email; + location ^~ /SOGo/ { + location ~* ^/SOGo/so/.*\.(xml|js|html|xhtml)$ { + include /etc/nginx/conf.d/sogo_proxy_auth.active; + include /etc/nginx/conf.d/sogo.active; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header x-webobjects-server-protocol HTTP/1.0; + proxy_set_header x-webobjects-remote-host $remote_addr; + proxy_set_header x-webobjects-server-name $server_name; + proxy_set_header x-webobjects-server-url $client_req_scheme://$http_host; + proxy_set_header x-webobjects-server-port $server_port; + proxy_hide_header Content-Type; + add_header Content-Type text/plain; + break; + } + include /etc/nginx/conf.d/sogo_proxy_auth.active; + include /etc/nginx/conf.d/sogo.active; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header x-webobjects-server-protocol HTTP/1.0; + proxy_set_header x-webobjects-remote-host $remote_addr; + proxy_set_header x-webobjects-server-name $server_name; + proxy_set_header x-webobjects-server-url $client_req_scheme://$http_host; + proxy_set_header x-webobjects-server-port $server_port; + proxy_send_timeout 3600; + proxy_read_timeout 3600; + client_body_buffer_size 128k; + client_max_body_size 0; + break; + } + + location /SOGo.woa/WebServerResources/ { + alias /usr/lib/GNUstep/SOGo/WebServerResources/; + } + + location /.woa/WebServerResources/ { + alias /usr/lib/GNUstep/SOGo/WebServerResources/; + } + + location /SOGo/WebServerResources/ { + alias /usr/lib/GNUstep/SOGo/WebServerResources/; + } + + location (^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\.(jpg|png|gif|css|js)$) { + alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2; + } +} diff --git a/mailcow/data/conf/postfix/extra.cf b/mailcow/data/conf/postfix/extra.cf new file mode 100644 index 0000000..112bae0 --- /dev/null +++ b/mailcow/data/conf/postfix/extra.cf @@ -0,0 +1,4 @@ +myhostname = 3gy.de + +mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 [fe80::]/10 172.22.1.0/24 [fd4d:6169:6c63:6f77::]/64 192.168.0.0/24 172.16.9.2 [2a03:4000:53:64::] 172.16.9.8/29 172.16.24.0/29 +mail_name = FREEDOM diff --git a/mailcow/docker-compose.yml b/mailcow/docker-compose.yml new file mode 100644 index 0000000..3d747c5 --- /dev/null +++ b/mailcow/docker-compose.yml @@ -0,0 +1,675 @@ +version: '2.1' +services: + + unbound-mailcow: + image: mailcow/unbound:1.13 + environment: + - TZ=${TZ} + 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.5 + depends_on: + - unbound-mailcow + stop_grace_period: 45s + volumes: + - mysql-vol-1:/var/lib/mysql/:Z + - 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:5-alpine + volumes: + - redis-vol-1:/data/:Z + restart: always + ports: + - "${REDIS_PORT:-127.0.0.1:7654}:6379" + environment: + - TZ=${TZ} + networks: + mailcow-network: + ipv4_address: ${IPV4_NETWORK:-172.22.1}.249 + aliases: + - redis + + clamd-mailcow: + image: mailcow/clamd:1.40 + restart: always + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + environment: + - TZ=${TZ} + - SKIP_CLAMD=${SKIP_CLAMD:-n} + volumes: + - ./data/conf/clamav/:/etc/clamav/:Z + networks: + mailcow-network: + aliases: + - clamd + + rspamd-mailcow: + image: mailcow/rspamd:1.76 + stop_grace_period: 30s + depends_on: + - dovecot-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:-} + 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:z + restart: always + hostname: rspamd + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + networks: + mailcow-network: + aliases: + - rspamd + + php-fpm-mailcow: + image: mailcow/phpfpm:1.75 + 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 + - rspamd-vol-1:/var/lib/rspamd:z + - 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/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/ejabberd/autogen:/ejabberd/: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:-} + - 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} + - XMPP_C2S_PORT=${XMPP_C2S_PORT:-5222} + - XMPP_S2S_PORT=${XMPP_S2S_PORT:-5269} + - 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_SOLR=${SKIP_SOLR:-y} + - SKIP_CLAMD=${SKIP_CLAMD:-n} + - SKIP_SOGO=${SKIP_SOGO:-n} + - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} + - MASTER=${MASTER:-y} + restart: always + networks: + mailcow-network: + aliases: + - phpfpm + + sogo-mailcow: + image: mailcow/sogo:1.99 + 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} + - SKIP_SOGO=${SKIP_SOGO:-n} + - MASTER=${MASTER:-y} + - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-} + - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-} + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + volumes: + - ./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-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:z + - sogo-userdata-backup-vol-1:/sogo_backup:Z + labels: + ofelia.enabled: "true" + ofelia.job-exec.sogo_sessions.schedule: "@every 1m" + ofelia.job-exec.sogo_sessions.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-tool expire-sessions $${SOGO_EXPIRE_SESSION} || exit 0\"" + ofelia.job-exec.sogo_ealarms.schedule: "@every 1m" + ofelia.job-exec.sogo_ealarms.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-ealarms-notify -p /etc/sogo/sieve.creds || exit 0\"" + ofelia.job-exec.sogo_eautoreply.schedule: "@every 24h" + 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: "@every 24h" + 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 + ports: + - 127.0.0.2:20000:20000 + networks: + mailcow-network: + ipv4_address: ${IPV4_NETWORK:-172.22.1}.248 + aliases: + - sogo + + dovecot-mailcow: + image: mailcow/dovecot:1.145 + depends_on: + - mysql-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:Z + - vmail-index-vol-1:/var/vmail_index:Z + - crypt-vol-1:/mail_crypt/:z + - ./data/conf/rspamd/custom/:/etc/rspamd/custom:z + - ./data/assets/templates:/templates:z + - rspamd-vol-1:/var/lib/rspamd:z + - mysql-socket-vol-1:/var/run/mysqld/:z + environment: + - DOVECOT_MASTER_USER=${DOVECOT_MASTER_USER:-} + - DOVECOT_MASTER_PASS=${DOVECOT_MASTER_PASS:-} + - 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:-1440} + - ACL_ANYONE=${ACL_ANYONE:-disallow} + - SKIP_SOLR=${SKIP_SOLR:-y} + - MAILDIR_SUB=${MAILDIR_SUB:-} + - MASTER=${MASTER:-y} + - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-} + - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-} + - 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: "@every 1m" + 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: "@every 1m" + 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: "@every 20m" + 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: "@every 24h" + 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: "@every 30m" + 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: "@every 24h" + ofelia.job-exec.dovecot_fts.command: "/usr/bin/curl http://solr:8983/solr/dovecot-fts/update?optimize=true" + ofelia.job-exec.dovecot_repl_health.schedule: "@every 5m" + 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: mailcow/postfix:1.61 + depends_on: + - mysql-mailcow + 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:z + - crypt-vol-1:/var/lib/zeyple:z + - rspamd-vol-1:/var/lib/rspamd:z + - 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:-} + - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + 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: + aliases: + - postfix + + memcached-mailcow: + image: memcached:alpine + restart: always + environment: + - TZ=${TZ} + networks: + mailcow-network: + aliases: + - memcached + + nginx-mailcow: + depends_on: + - sogo-mailcow + - php-fpm-mailcow + - redis-mailcow + image: nginx:mainline-alpine + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + command: /bin/sh -c "envsubst < /etc/nginx/conf.d/templates/listen_plain.template > /etc/nginx/conf.d/listen_plain.active && + envsubst < /etc/nginx/conf.d/templates/listen_ssl.template > /etc/nginx/conf.d/listen_ssl.active && + envsubst < /etc/nginx/conf.d/templates/sogo.template > /etc/nginx/conf.d/sogo.active && + . /etc/nginx/conf.d/templates/sogo.auth_request.template.sh > /etc/nginx/conf.d/sogo_proxy_auth.active && + . /etc/nginx/conf.d/templates/server_name.template.sh > /etc/nginx/conf.d/server_name.active && + . /etc/nginx/conf.d/templates/sites.template.sh > /etc/nginx/conf.d/sites.active && + . /etc/nginx/conf.d/templates/sogo_eas.template.sh > /etc/nginx/conf.d/sogo_eas.active && + nginx -qt && + until ping phpfpm -c1 > /dev/null; do sleep 1; done && + until ping sogo -c1 > /dev/null; do sleep 1; done && + until ping redis -c1 > /dev/null; do sleep 1; done && + until ping rspamd -c1 > /dev/null; do sleep 1; done && + until ping ejabberd -c1 > /dev/null; do sleep 1; done && + exec nginx -g 'daemon off;'" + environment: + - HTTPS_PORT=${HTTPS_PORT:-443} + - HTTP_PORT=${HTTP_PORT:-80} + - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} + - TZ=${TZ} + - SKIP_SOGO=${SKIP_SOGO:-n} + - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} + - ADDITIONAL_SERVER_NAMES=${ADDITIONAL_SERVER_NAMES:-} + 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 + - sogo-web-vol-1:/usr/lib/GNUstep/SOGo/:z + ports: + - "${HTTPS_BIND:-:}:${HTTPS_PORT:-443}:${HTTPS_PORT:-443}" + - "${HTTP_BIND:-:}:${HTTP_PORT:-80}:${HTTP_PORT:-80}" + - 127.0.0.2:8081:8081 + restart: always + networks: + mailcow-network: + aliases: + - nginx + + acme-mailcow: + depends_on: + - nginx-mailcow + image: mailcow/acme:1.79 + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + environment: + - LOG_LINES=${LOG_LINES:-9999} + - ACME_CONTACT=${ACME_CONTACT:-} + - ADDITIONAL_SAN=${ADDITIONAL_SAN} + - 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:-} + - 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: mailcow/netfilter:1.43 + stop_grace_period: 30s + depends_on: + - dovecot-mailcow + - postfix-mailcow + - sogo-mailcow + - php-fpm-mailcow + - redis-mailcow + 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:-} + network_mode: "host" + volumes: + - /lib/modules:/lib/modules:ro + + watchdog-mailcow: + image: mailcow/watchdog:1.91 + # Debug + #command: /watchdog.sh + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + tmpfs: + - /tmp + volumes: + - rspamd-vol-1:/var/lib/rspamd:z + - mysql-socket-vol-1:/var/run/mysqld/:z + - postfix-vol-1:/var/spool/postfix:z + - ./data/assets/ssl:/etc/ssl/mail/:ro,z + restart: always + 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_SUBJECT=${WATCHDOG_SUBJECT:-Watchdog ALERT} + - WATCHDOG_EXTERNAL_CHECKS=${WATCHDOG_EXTERNAL_CHECKS:-n} + - WATCHDOG_MYSQL_REPLICATION_CHECKS=${WATCHDOG_MYSQL_REPLICATION_CHECKS:-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_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:-} + - 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} + - 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} + - IPV6NAT_THRESHOLD=${IPV6NAT_THRESHOLD:-1} + - RSPAMD_THRESHOLD=${RSPAMD_THRESHOLD:-5} + - OLEFY_THRESHOLD=${OLEFY_THRESHOLD:-5} + - MAILQ_THRESHOLD=${MAILQ_THRESHOLD:-20} + - MAILQ_CRIT=${MAILQ_CRIT:-30} + networks: + mailcow-network: + aliases: + - watchdog + + dockerapi-mailcow: + image: mailcow/dockerapi:1.38 + security_opt: + - label=disable + restart: always + oom_kill_disable: true + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + environment: + - DBROOT=${DBROOT} + - TZ=${TZ} + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + networks: + mailcow-network: + aliases: + - dockerapi + + solr-mailcow: + image: mailcow/solr:1.7 + restart: always + volumes: + - solr-vol-1:/opt/solr/server/solr/dovecot-fts/data:Z + ports: + - "${SOLR_PORT:-127.0.0.1:18983}:8983" + environment: + - TZ=${TZ} + - SOLR_HEAP=${SOLR_HEAP:-1024} + - SKIP_SOLR=${SKIP_SOLR:-y} + networks: + mailcow-network: + aliases: + - solr + + olefy-mailcow: + image: mailcow/olefy:1.7 + 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/olevba3 + - OLEFY_LOGLVL=20 + - OLEFY_MINLENGTH=500 + - OLEFY_DEL_TMP=1 + networks: + mailcow-network: + aliases: + - olefy + + ejabberd-mailcow: + image: mailcow/ejabberd:1.6 + volumes: + - ./data/conf/ejabberd/ejabberd.yml:/home/ejabberd/conf/ejabberd.yml:z + - xmpp-vol-1:/home/ejabberd/database:z + - xmpp-upload-vol-1:/var/www/upload:z + - ./data/assets/ejabberd/sqlite:/sqlite:z + - ./data/conf/ejabberd/autogen:/ejabberd/:z + - mysql-socket-vol-1:/var/run/mysqld/:z + - ./data/assets/ssl:/ssl:ro,z + restart: always + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + hostname: ejabberd.mailcow.local + labels: + ofelia.enabled: "true" + ofelia.job-exec.ejabberd_certs.schedule: "@every 168h" + ofelia.job-exec.ejabberd_certs.command: "/sbin/su-exec ejabberd /home/ejabberd/bin/ejabberdctl --node ejabberd@$${MAILCOW_HOSTNAME} request-certificate all" + extra_hosts: + - "${MAILCOW_HOSTNAME}:127.0.0.1" + environment: + - TZ=${TZ} + - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + - MASTER=${MASTER:-y} + - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} + - XMPP_HTTPS_PORT=${XMPP_HTTPS_PORT:-5443} + - DBNAME=${DBNAME} + - DBUSER=${DBUSER} + - DBPASS=${DBPASS} + ports: + - "${XMPP_C2S_PORT:-5222}:5222" + - "${XMPP_S2S_PORT:-5269}:5269" + - "${XMPP_HTTPS_PORT:-5443}:5443" + networks: + mailcow-network: + aliases: + - ejabberd + + ofelia-mailcow: + image: mcuadros/ofelia:latest + restart: always + command: daemon --docker + - TZ=${TZ} + depends_on: + - sogo-mailcow + - dovecot-mailcow + - ejabberd-mailcow + labels: + ofelia.enabled: "true" + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + networks: + mailcow-network: + aliases: + - ofelia + + ipv6nat-mailcow: + depends_on: + - unbound-mailcow + - mysql-mailcow + - redis-mailcow + - clamd-mailcow + - rspamd-mailcow + - php-fpm-mailcow + - sogo-mailcow + - dovecot-mailcow + - postfix-mailcow + - memcached-mailcow + - nginx-mailcow + - acme-mailcow + - netfilter-mailcow + - watchdog-mailcow + - dockerapi-mailcow + - solr-mailcow + environment: + - TZ=${TZ} + image: robbertkl/ipv6nat + security_opt: + - label=disable + restart: always + privileged: true + network_mode: "host" + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - /lib/modules:/lib/modules:ro + +networks: + mailcow-network: + driver: bridge + driver_opts: + com.docker.network.bridge.name: br-mailcow + 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: + solr-vol-1: + postfix-vol-1: + crypt-vol-1: + sogo-web-vol-1: + sogo-userdata-backup-vol-1: + xmpp-vol-1: + xmpp-upload-vol-1: diff --git a/mailcow/mailcow.conf b/mailcow/mailcow.conf new file mode 100644 index 0000000..2b1f13b --- /dev/null +++ b/mailcow/mailcow.conf @@ -0,0 +1,244 @@ +# ------------------------------ +# 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=3gy.de + +# Password hash algorithm +# Only certain password hash algorithm are supported. For a fully list of supported schemes, +# see https://mailcow.github.io/mailcow-dockerized-docs/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=$DBPASS +DBROOT=$DBROOT + +# ------------------------------ +# 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 or 65510! +# Example: HTTP_BIND=1.2.3.4 +# For IPv6 see https://mailcow.github.io/mailcow-dockerized-docs/firststeps-ip_bindings/ + +HTTP_PORT=8080 +HTTP_BIND=127.0.0.2 + +HTTPS_PORT=4433 +HTTPS_BIND=127.0.0.2 + +# ------------------------------ +# 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=127.0.0.9:143 +IMAPS_PORT=993 +POP_PORT=127.0.0.9:110 +POPS_PORT=127.0.0.9:995 +SIEVE_PORT=4190 +DOVEADM_PORT=127.0.0.1:19991 +SQL_PORT=127.0.0.1:13306 +SOLR_PORT=127.0.0.1:18983 +REDIS_PORT=127.0.0.1:7654 +XMPP_C2S_PORT=127.0.0.9:5222 +XMPP_S2S_PORT=127.0.0.9:5269 +XMPP_HTTPS_PORT=127.0.0.9:5443 + +# Your timezone +# See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for a list of timezones +# Use the row named 'TZ database name' + pay attention for 'Notes' row + +TZ=Europe/Berlin + +# Fixed project name +# Please use lowercase letters only + +COMPOSE_PROJECT_NAME=mailcowdockerized + +# 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 exclusivly 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", "imap.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= + +# 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=zz0.email + +# Skip running ACME (acme-mailcow, Let's Encrypt certs) - y/n + +SKIP_LETS_ENCRYPT=y + +# Create seperate 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://wiki.dovecot.org/SSL/SNIClientSupport +ENABLE_SSL_SNI=n + +# Skip IPv4 check in ACME container - y/n + +SKIP_LETS_ENCRYPT=y + +# Create seperate 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://wiki.dovecot.org/SSL/SNIClientSupport +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 ClamAV (clamd-mailcow) anti-virus (Rspamd will auto-detect a missing ClamAV container) - y/n + +SKIP_CLAMD=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 Solr on low-memory systems or if you do not want to store a readable index of your mails in solr-vol-1. + +SKIP_SOLR=n + +# Solr heap size in MB, there is no recommendation, please see Solr docs. +# Solr is a prone to run OOM and should be monitored. Unmonitored Solr setups are not recommended. + +SOLR_HEAP=4096 + +# 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=mail@georg-pfuetzenreuter.net,georg@pfuetzenreuter.pw,system@lysergic.dev +#WATCHDOG_NOTIFY_EMAIL= + +# Notify about banned IP (includes whois lookup) +WATCHDOG_NOTIFY_BAN=y + +# Subject for watchdog mails. Defaults to "Watchdog ALERT" followed by the error message. +WATCHDOG_SUBJECT=Mail ALERT + +# 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 + +# 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 + +# 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= + +# Let's Encrypt registration contact information +# Optional: Leave empty for none +# This value is only used on first order! +# Setting it at a later point will require the following steps: +# https://mailcow.github.io/mailcow-dockerized-docs/debug-reset-tls/ +ACME_CONTACT= + diff --git a/mailcow/mailcow.service b/mailcow/mailcow.service new file mode 100644 index 0000000..af2d974 --- /dev/null +++ b/mailcow/mailcow.service @@ -0,0 +1,14 @@ +[Unit] +Description=Mailcow +Requires=docker.service +After=docker.service + +[Service] +Type=oneshot +RemainAfterExit=true +WorkingDirectory=/opt/mailcow-dockerized +ExecStart=/usr/local/bin/docker-compose up -d +ExecStop=/usr/local/bin/docker-compose down + +[Install] +WantedBy=multi-user.target -- cgit v1.2.3