Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • infrastruktur/ansible-warpzone
  • specki/ansible-warpzone
2 results
Show changes
Showing
with 551 additions and 679 deletions
......@@ -3,3 +3,18 @@ object UserGroup "icingaadmins" {
display_name = "Icinga 2 Admin Group"
}
object User "matrix" {
import "generic-user"
display_name = "Matrix User"
vars.matrix = {
token = "{{ matrix_notification_access_token }}"
channel = "!iYefxbySFEfFQfUGEK:matrix.warpzone.ms"
server = "https://matrix.warpzone.ms"
}
}
object UserGroup "matrix" {
display_name = "Matrix Group"
assign where user.vars.matrix
}
......@@ -2,6 +2,7 @@
- include_tasks: ../functions/get_secret.yml
with_items:
- { path: /srv/shared/noreply_email_pass, length: -1 }
- { path: /srv/keycloak/keycloak_admin_pass, length: 32 }
- { path: /srv/keycloak/postgres_user_pass, length: 24 }
......
......@@ -6,7 +6,7 @@ services:
app:
# values set in configuration: noreply_email_user - noreply_email_pass - smtp_host - smtp_port
image: jboss/keycloak:16.1.1
restart: always
depends_on:
......@@ -31,7 +31,6 @@ services:
- traefik.http.services.{{ servicename }}.loadbalancer.server.port=8080
networks:
- default
- mail
- web
......@@ -64,7 +63,5 @@ services:
networks:
mail:
external: true
web:
external: true
---
servicename: mail
basedir: /srv/mail
......@@ -2,21 +2,23 @@
- include_tasks: ../functions/get_secret.yml
with_items:
- { path: "{{ basedir }}/secrets/mailcow_admin_pass", length: 28 }
- { path: "{{ basedir }}/secrets/mysql_mailcow_pass", length: 28 }
- { path: "{{ basedir }}/secrets/mysql_root_pass", length: 28 }
# mailman
- { path: "{{ basedir }}/secrets/mailu_secret_key", length: 32 }
- { path: "{{ basedir }}/secrets/mailu_admin_pass", length: 32 }
- { path: "{{ basedir }}/secrets/mailu_api_token", length: 32 }
- { path: "{{ basedir }}/secrets/mailu_db_pass", length: 28 }
- { path: "{{ basedir }}/secrets/roundcube_db_pass", length: 28 }
- { path: "{{ basedir }}/secrets/hyperkitty_api_key", length: 28 }
- { path: "{{ basedir }}/secrets/postgres_mailman_pass", length: 28 }
- { path: "{{ basedir }}/secrets/mailman_db_pass", length: 28 }
- { path: "{{ basedir }}/secrets/mailman_secret_key", length: 28 }
- { path: "{{ basedir }}/secrets/mailman_restapi_pass", length: 28 }
- { path: "{{ basedir }}/secrets/mysql_root_pass", length: 28 }
- name: pakete installieren
apt:
pkg: ['git', 'logrotate', 'openssl']
update_cache: no
state: present
# - name: pakete installieren
# apt:
# pkg: ['logrotate']
# update_cache: no
# state: present
- name: "create folder struct for {{ servicename }}"
......@@ -26,139 +28,85 @@
with_items:
- "{{ basedir }}"
- "{{ basedir }}/secrets"
# mailcow
- "{{ basedir }}/data/mysql"
- "{{ basedir }}/data/mysql-socket"
- "{{ basedir }}/data/redis"
- "{{ basedir }}/data/rspamd"
- "{{ basedir }}/data/solr"
- "{{ basedir }}/data/postfix"
- "{{ basedir }}/data/sogo-web"
- "{{ basedir }}/data/sogo-userdata-backup"
- "{{ basedir }}/data/xmpp-vol-1"
- "{{ basedir }}/data/xmpp-upload-vol-1"
# mailmann
- "{{ basedir }}/data/mailman-core"
- "{{ basedir }}/data/mailman-core/var"
- "{{ basedir }}/data/mailman-core/var/data"
- "{{ basedir }}/data/mailman-web"
- "{{ basedir }}/data/mailman-postgres"
- name: "create folder struct for {{ servicename }} with rights"
file:
path: "{{ item }}"
state: "directory"
owner: "5000"
group: "5000"
mode: "ugo+rwx"
with_items:
- "{{ basedir }}/data/crypt"
- "{{ basedir }}/data/vmail"
- "{{ basedir }}/data/vmail-index"
- name: check if git dir exists
stat:
path: "{{ basedir }}/mailcow-dockerized/.git"
register: mailcow_dotgit
- name: revert main.cf to avoid local changes
command: "git checkout data/conf/postfix/main.cf"
args:
chdir: "{{ basedir }}/mailcow-dockerized"
when: mailcow_dotgit.stat.exists == True
- name: Git checkout mailcow
git:
repo: 'https://github.com/mailcow/mailcow-dockerized.git'
dest: "{{ basedir }}/mailcow-dockerized"
version: d6a3094bcc8b3d748994978ca7e274301b39e583
# current version 2021-05-18
- name: Git checkout mailman-dockerized
git:
repo: 'https://github.com/maxking/docker-mailman.git'
dest: "{{ basedir }}/docker-mailman"
version: v0.4.4
# current version 2020-03-15
- name: "create folder struct for {{ servicename }} 3"
file:
path: "{{ item }}"
state: "directory"
with_items:
- "{{ basedir }}/mailcow-dockerized/data/assets/ssl/"
- name: check if DH Params exists
stat:
path: "{{ basedir }}/mailcow-dockerized/data/assets/ssl/dhparams.pem"
register: dhparams
- name: generate new DH Params
command: "openssl dhparam -out {{ basedir }}/mailcow-dockerized/data/assets/ssl/dhparams.pem 2048"
when: dhparams.stat.exists == False
- name: deploy mailcow config files
template:
dest: "{{ basedir }}/{{ item }}"
src: "{{ item }}"
mode: 0644
with_items:
- mailcow-dockerized/mailcow.conf
- mailcow-dockerized/docker-compose.override.yml
- mailcow-dockerized/data/conf/postfix/extra.cf
register: config_mailcow
- name: deploy mailman config files
- "{{ basedir }}/db"
- "{{ basedir }}/db-init"
- "{{ basedir }}/mailu"
- "{{ basedir }}/mailu/overrides"
- "{{ basedir }}/mailu/overrides/postfix"
- "{{ basedir }}/mailman-core"
- "{{ basedir }}/mailman-core/var"
- "{{ basedir }}/mailman-core/var/data"
- "{{ basedir }}/mailman-web"
# - "{{ basedir }}/mailman-db"
# - name: "create folder struct for {{ servicename }} with rights"
# file:
# path: "{{ item }}"
# state: "directory"
# owner: "5000"
# group: "5000"
# mode: "ugo+rwx"
# with_items:
# - "{{ basedir }}/data/crypt"
# - "{{ basedir }}/data/vmail"
# - "{{ basedir }}/data/vmail-index"
- name: "deploy {{ servicename }} config files"
template:
dest: "{{ basedir }}/{{ item }}"
src: "{{ item }}"
mode: 0644
with_items:
- docker-mailman/docker-compose.override.yml
- docker-mailman/nginx.conf
- data/mailman-core/mailman-extra.cfg
- data/mailman-web/settings_local.py
register: config_mailman
- name: deploy LogRotate configs
template:
src: "logrotate/{{item}}"
dest: "/etc/logrotate.d/{{item}}"
with_items:
- mailman-core
- mailman-web
# Start mailcow containers
- name: "stop {{ servicename }} (mailcow) docker"
- docker-compose.yml
- mailu.env
- mailman.env
- mailman-nginx.conf
- db-init/mailman.sql
- db-init/roundcube.sql
- mailu/overrides/postfix/postfix.cf
register: config
- name: "set local dns record"
become: true
blockinfile:
path: /etc/hosts
create: yes
block: |
{{ ext_ip4 }} mailserver.warpzone.ms
# - name: deploy LogRotate configs
# template:
# src: "logrotate/{{item}}"
# dest: "/etc/logrotate.d/{{item}}"
# with_items:
# - mailman-core
# - mailman-web
# Start containers
- name: "stop {{ servicename }} docker"
docker_compose:
project_src: "{{ basedir }}/mailcow-dockerized"
project_src: "{{ basedir }}"
state: absent
when: config_mailcow.changed
when: config.changed
- name: "start {{ servicename }} (mailcow) docker"
- name: "start {{ servicename }} docker"
docker_compose:
project_src: "{{ basedir }}/mailcow-dockerized"
project_src: "{{ basedir }}"
state: present
# Start mailman containers
- name: "stop {{ servicename }} (mailman) docker"
docker_compose:
project_src: "{{ basedir }}/docker-mailman"
state: absent
when: config_mailcow.changed
- name: "start {{ servicename }} (mailman) docker"
docker_compose:
project_src: "{{ basedir }}/docker-mailman"
state: present
# - name: "stop {{ servicename }} (mailman) docker"
# docker_compose:
# project_src: "{{ basedir }}/docker-mailman"
# state: absent
# when: config_mailcow.changed
# - name: "start {{ servicename }} (mailman) docker"
# docker_compose:
# project_src: "{{ basedir }}/docker-mailman"
# state: present
[mailman]
site_owner: listmaster@warpzone.ms
[mta]
remove_dkim_headers: yes
from settings import *
import socket
# Archivierung für Mailman-Core Container erlauben
MAILMAN_ARCHIVER_FROM = (socket.gethostbyname('mailman-core'),)
# disable social logins (google, facebook, etc. )
INSTALLED_APPS = [a for a in INSTALLED_APPS if not
a.startswith('allauth.socialaccount.providers') and not
a.startswith('django_mailman3.lib.auth.fedora')]
# Mail backend settings
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'postfix'
EMAIL_PORT = 25
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
DEFAULT_FROM_EMAIL = 'listmaster@warpzone.ms'
SERVER_EMAIL = 'listmaster@warpzone.ms'
CREATE DATABASE IF NOT EXISTS mailman;
CREATE USER IF NOT EXISTS mailman@'%' IDENTIFIED BY '{{ mailman_db_pass }}';
GRANT ALL ON mailman.* TO mailman@'%';
FLUSH PRIVILEGES;
CREATE DATABASE IF NOT EXISTS roundcube;
CREATE USER IF NOT EXISTS roundcube@'%' IDENTIFIED BY '{{ roundcube_db_pass }}';
GRANT ALL ON roundcube.* TO roundcube@'%';
FLUSH PRIVILEGES;
version: '2.2'
services:
# External dependencies
redis:
image: redis:alpine
restart: always
volumes:
- "{{ basedir }}/mailu/redis:/data"
depends_on:
- resolver
dns:
- 192.168.203.254
# Certdumper
certdumper:
image: ${DOCKER_ORG:-ghcr.io/mailu}/${DOCKER_PREFIX:-}traefik-certdumper:${MAILU_VERSION:-2.0}
restart: always
environment:
- DOMAIN={{ mailserver }}
- TRAEFIK_VERSION=v2
volumes:
- "/srv/traefik:/traefik"
- "{{ basedir }}/mailu/certs:/output"
# Core services
front:
image: ${DOCKER_ORG:-ghcr.io/mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-2.0}
restart: always
depends_on:
- db
- resolver
env_file: mailu.env
ports:
- "25:25" #smtp
- "465:465" #submissions
- "587:587" #submission
- "143:143" #imap
- "993:993" #imaps
volumes:
- "{{ basedir }}/mailu/certs:/certs"
- "{{ basedir }}/mailu/overrides/nginx:/overrides:ro"
labels:
- "traefik.enable=true"
- "traefik.http.routers.{{ servicename }}.entrypoints=websecure"
- "traefik.http.routers.{{ servicename }}.rule=Host(`{{ mailserver }}`)"
- "traefik.http.routers.{{ servicename }}.tls"
- "traefik.http.routers.{{ servicename }}.tls.certresolver=letsencrypt"
- "traefik.http.routers.{{ servicename }}.tls.domains[0].main={{ domain }}"
- "traefik.http.routers.{{ servicename }}.tls.domains[0].sans={{ mailserver }}"
- "traefik.http.routers.{{ servicename }}.service={{ servicename }}"
- "traefik.http.services.{{ servicename }}.loadbalancer.server.port=80"
networks:
- default
- web
dns:
- 192.168.203.254
resolver:
image: ${DOCKER_ORG:-ghcr.io/mailu}/${DOCKER_PREFIX:-}unbound:${MAILU_VERSION:-2.0}
env_file: mailu.env
restart: always
networks:
default:
ipv4_address: 192.168.203.254
admin:
image: ${DOCKER_ORG:-ghcr.io/mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-2.0}
restart: always
depends_on:
- db
- redis
- resolver
env_file: mailu.env
volumes:
- "{{ basedir }}/mailu/data:/data"
- "{{ basedir }}/mailu/dkim:/dkim"
dns:
- 192.168.203.254
imap:
image: ${DOCKER_ORG:-ghcr.io/mailu}/${DOCKER_PREFIX:-}dovecot:${MAILU_VERSION:-2.0}
restart: always
depends_on:
- db
- front
- resolver
env_file: mailu.env
volumes:
- "{{ basedir }}/mailu/mail:/mail"
- "{{ basedir }}/mailu/overrides/dovecot:/overrides:ro"
dns:
- 192.168.203.254
smtp:
image: ${DOCKER_ORG:-ghcr.io/mailu}/${DOCKER_PREFIX:-}postfix:${MAILU_VERSION:-2.0}
restart: always
depends_on:
- db
- front
- resolver
- mailman-core
env_file: mailu.env
volumes:
- "{{ basedir }}/mailu/mailqueue:/queue"
- "{{ basedir }}/mailu/overrides/postfix:/overrides:ro"
- "{{ basedir }}/mailman-core/var/data:/opt/mailman:ro"
dns:
- 192.168.203.254
oletools:
image: ${DOCKER_ORG:-ghcr.io/mailu}/${DOCKER_PREFIX:-}oletools:${MAILU_VERSION:-2.0}
hostname: oletools
restart: always
depends_on:
- resolver
networks:
- noinet
dns:
- 192.168.203.254
antispam:
image: ${DOCKER_ORG:-ghcr.io/mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-2.0}
hostname: antispam
restart: always
depends_on:
- front
- redis
- oletools
- resolver
env_file: mailu.env
volumes:
- "{{ basedir }}/mailu/filter:/var/lib/rspamd"
- "{{ basedir }}/mailu/overrides/rspamd:/overrides:ro"
networks:
default:
ipv4_address: 192.168.203.253
noinet:
dns:
- 192.168.203.254
# Optional mailu services: Database
db:
image: mariadb:10.5
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
restart: always
volumes:
- "{{ basedir }}/db:/var/lib/mysql"
- "{{ basedir }}/db-init:/docker-entrypoint-initdb.d:ro"
environment:
- MYSQL_DATABASE=mailu
- MYSQL_USER=mailu
- MYSQL_PASSWORD={{ mailu_db_pass }}
- MYSQL_ROOT_PASSWORD={{ mysql_root_pass }}
# Optional mailu services: Webmail
webmail:
image: ${DOCKER_ORG:-ghcr.io/mailu}/${DOCKER_PREFIX:-}webmail:${MAILU_VERSION:-2.0}
restart: always
depends_on:
- front
env_file: mailu.env
volumes:
- "{{ basedir }}/mailu/webmail:/data"
- "{{ basedir }}/mailu/overrides/roundcube:/overrides:ro"
# Additional Services: mailman
mailman-core:
image: maxking/mailman-core:0.4
restart: always
env_file: mailman.env
depends_on:
- db
volumes:
- "{{ basedir }}/mailman-core:/opt/mailman:rw,z"
mailman-web:
image: maxking/mailman-web:0.4
restart: always
env_file: mailman.env
depends_on:
- db
volumes:
- "{{ basedir }}/mailman-web:/opt/mailman-web-data:rw,z"
mailman-nginx:
image: nginx:1.19
restart: always
depends_on:
- mailman-web
volumes:
- "{{ basedir }}/mailman-web/:/opt/mailman-web-data:ro,z"
- "{{ basedir }}/mailman-nginx.conf:/etc/nginx/conf.d/default.conf:ro"
labels:
- traefik.enable=true
- traefik.http.routers.{{ servicename }}-mailman.rule=Host(`{{ listserver }}`)
- traefik.http.routers.{{ servicename }}-mailman.entrypoints=websecure
- traefik.http.services.{{ servicename }}-mailman.loadbalancer.server.port=80
networks:
- default
- web
networks:
default:
driver: bridge
enable_ipv6: true
ipam:
driver: default
config:
# must be a ULA range
- subnet: fd00:dead:beef:25::/64
- subnet: 192.168.203.0/24
noinet:
driver: bridge
internal: true
web:
external: true
version: '2'
services:
mailman-core:
container_name: mail_mailman-core
restart: always
volumes:
- "{{ basedir }}/data/mailman-core:/opt/mailman:rw,z"
environment:
- DATABASE_URL=postgres://mailman:{{ postgres_mailman_pass }}@database/mailmandb
- MTA=postfix
- MM_HOSTNAME=mailman-core-mail
- SMTP_HOST=postfix
- SMTP_PORT=25
- MAILMAN_REST_USER=mailman
- MAILMAN_REST_PASSWORD={{ mailman_restapi_pass }}
- HYPERKITTY_URL=http://mailman-web:8000/hyperkitty
- HYPERKITTY_API_KEY={{ hyperkitty_api_key }}
networks:
mailman:
aliases:
- mailman-core
mail:
aliases:
- mailman-core
- mailman-core-mail
mailman-web:
container_name: mail_mailman-web
restart: always
volumes:
- "{{ basedir }}/data/mailman-web:/opt/mailman-web-data:rw,z"
environment:
- DATABASE_URL=postgres://mailman:{{ postgres_mailman_pass }}@database/mailmandb
- HYPERKITTY_API_KEY={{ hyperkitty_api_key }}
- SECRET_KEY={{ mailman_secret_key }}
- SERVE_FROM_DOMAIN=listserver.warpzone.ms
- MAILMAN_REST_URL=http://mailman-core-mail:8001
- MAILMAN_REST_USER=mailman
- MAILMAN_REST_PASSWORD={{ mailman_restapi_pass }}
networks:
- mail
- mailman
nginx:
container_name: mail_mailman-nginx
image: nginx:1.19
restart: always
depends_on:
- mailman-web
volumes:
- "{{ basedir }}/data/mailman-web/:/opt/mailman-web-data:ro,z"
- "{{ basedir }}/docker-mailman/nginx.conf:/etc/nginx/conf.d/default.conf:ro"
labels:
- traefik.enable=true
- traefik.http.routers.{{ servicename }}-mailman.rule=Host(`listserver.warpzone.ms`) || Host(`lists.warpzone.ms`)
- traefik.http.routers.{{ servicename }}-mailman.entrypoints=websecure
- traefik.http.services.{{ servicename }}-mailman.loadbalancer.server.port=80
networks:
- mailman
- web
database:
container_name: mail_mailman-db
restart: always
environment:
- POSTGRES_PASSWORD={{ postgres_mailman_pass }}
volumes:
- "{{ basedir }}/data/mailman-postgres:/var/lib/postgresql/data"
networks:
- mailman
networks:
mailman:
driver: bridge
ipam:
driver: default
mail:
external: true
web:
external: true
/srv/mail/data/mailman-core/var/logs/*.log {
rotate 12
monthly
compress
missingok
notifempty
}
/srv/mail/data/mailman-web/logs/*.log {
rotate 12
monthly
compress
missingok
notifempty
}
# Support the default VERP delimiter.
recipient_delimiter = +
unknown_local_recipient_reject_code = 550
owner_request_special = no
# use relay_recipient_maps instead of local_recipient_maps
relay_recipient_maps =
regexp:/opt/mailman/postfix_lmtp
# Wert aus main.cf übernommen und ergänzt
transport_maps =
pcre:/opt/postfix/conf/custom_transport.pcre,
pcre:/opt/postfix/conf/local_transport,
proxy:mysql:/opt/postfix/conf/sql/mysql_relay_ne.cf,
proxy:mysql:/opt/postfix/conf/sql/mysql_transport_maps.cf,
regexp:/opt/mailman/postfix_lmtp
# Wert aus main.cf übernommen und ergänzt
relay_domains =
proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_relay_domain_maps.cf,
regexp:/opt/mailman/postfix_domains
version: '2.1'
services:
# Export der Letsencrypt-Zertifikate von traefik zur Verwendung in Postfix und Dovecot
traefik-certdumper:
image: humenius/traefik-certs-dumper
restart: always
network_mode: none
command: --restart-containers mail_dovecot-mailcow_1,mail_postfix-mailcow_1,mail_nginx-mailcow_1,mail_watchdog-mailcow_1
volumes:
# mount the folder which contains Traefik's `acme.json' file
- /srv/traefik/acme.json:/traefik/acme.json:ro
# mount mailcow's SSL folder
- ./data/assets/ssl/:/output:rw
# Docker API for Container restart
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
# only change this, if you're using another domain for mailcow's web frontend compared to the standard config
- DOMAIN=${MAILCOW_HOSTNAME}
# Prometheus Postfix Exporter
postfix-exporter:
image: unikum/postfix_exporter:latest
restart: always
depends_on:
- postfix-mailcow
ports:
- "{{ int_ip4 }}:9154:9154"
volumes:
- "postfix-vol-1:/var/spool/postfix:z"
# Labels für traefik Konfiguration
# Der Container nginx-mailcow benötigt zusätzlich den Alias sogo, damit der Container wegfallen kann
nginx-mailcow:
labels:
- traefik.enable=true
- traefik.http.routers.{{ servicename }}-mailcow.rule=Host(`${MAILCOW_HOSTNAME}`) || Host(`mail.warpzone.ms`)
- traefik.http.routers.{{ servicename }}-mailcow.entrypoints=websecure
- traefik.http.services.{{ servicename }}-mailcow.loadbalancer.server.port=42012
networks:
mailcow-network:
aliases:
- nginx
- sogo
- ejabberd
web:
aliases:
- mailcow
# Mailman konfiguration in Postfix-Container mounten
# postfix ans mail netzwerk um mit mailman zu kommunizieren
postfix-mailcow:
volumes:
- "{{ basedir }}/data/mailman-core/var/data:/opt/mailman:rw,z"
networks:
mail:
aliases:
- postfix
# Container anpassen um start zu unterbinden
clamd-mailcow:
image: stakater/exit-container
restart: 'no'
sogo-mailcow:
image: stakater/exit-container
restart: 'no'
acme-mailcow:
image: stakater/exit-container
restart: 'no'
solr-mailcow:
image: stakater/exit-container
restart: 'no'
ejabberd-mailcow:
image: stakater/exit-container
restart: 'no'
# Externes Netzwerk
networks:
web:
external: true
mail:
external: true
# Volumes auf lokale Verzeichnise umlenken
volumes:
# Storage for email files
vmail-vol-1:
driver: local
driver_opts:
o: bind
type: none
device: "{{ basedir }}/data/vmail"
# Storage for index (deduplicated)
vmail-index-vol-1:
driver: local
driver_opts:
o: bind
type: none
device: "{{ basedir }}/data/vmail-index"
mysql-vol-1:
driver: local
driver_opts:
o: bind
type: none
device: "{{ basedir }}/data/mysql"
mysql-socket-vol-1:
driver: local
driver_opts:
o: bind
type: none
device: "{{ basedir }}/data/mysql-socket"
redis-vol-1:
driver: local
driver_opts:
o: bind
type: none
device: "{{ basedir }}/data/redis"
rspamd-vol-1:
driver: local
driver_opts:
o: bind
type: none
device: "{{ basedir }}/data/rspamd"
solr-vol-1:
driver: local
driver_opts:
o: bind
type: none
device: "{{ basedir }}/data/solr"
postfix-vol-1:
driver: local
driver_opts:
o: bind
type: none
device: "{{ basedir }}/data/postfix"
crypt-vol-1:
driver: local
driver_opts:
o: bind
type: none
device: "{{ basedir }}/data/crypt"
sogo-web-vol-1:
driver: local
driver_opts:
o: bind
type: none
device: "{{ basedir }}/data/sogo-web"
sogo-userdata-backup-vol-1:
driver: local
driver_opts:
o: bind
type: none
device: "{{ basedir }}/data/sogo-userdata-backup"
xmpp-vol-1:
driver: local
driver_opts:
o: bind
type: none
device: "{{ basedir }}/data/xmpp-vol-1"
xmpp-upload-vol-1:
driver: local
driver_opts:
o: bind
type: none
device: "{{ basedir }}/data/xmpp-upload-vol-1"
# ------------------------------
# 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=mailserver.warpzone.ms
# ------------------------------
# SQL database configuration
# ------------------------------
DBNAME=mailcow
DBUSER=mailcow
# Please use long, random alphanumeric strings (A-Za-z0-9)
DBPASS={{ mysql_mailcow_pass }}
DBROOT={{ mysql_root_pass }}
# ------------------------------
# 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!
HTTP_PORT=42012
HTTP_BIND=127.0.0.1
HTTPS_PORT=42013
HTTPS_BIND=127.0.0.1
# ------------------------------
# Other bindings
# ------------------------------
# You should leave that alone
# Format: 11.22.33.44:25 or 0.0.0.0:465 etc.
SMTP_PORT=25
SMTPS_PORT=465
SUBMISSION_PORT=587
IMAP_PORT=127.0.0.1:143
IMAPS_PORT=993
POP_PORT=127.0.0.1:110
POPS_PORT=127.0.0.1:995
SIEVE_PORT=127.0.0.1:4190
DOVEADM_PORT=127.0.0.1:19991
SQL_PORT=127.0.0.1:23306
SOLR_PORT=127.0.0.1:18983
REDIS_PORT=127.0.0.1:7654
# bind jabber to nonstandard port because we already have a jabber running
# no (vig) risk as we use the exit container
XMPP_C2S_PORT=127:0.0.1:15222
XMPP_S2S_PORT=127:0.0.1:15269
XMPP_HTTPS_PORT=127:0.0.1:15443
# Your timezone
TZ=Europe/Berlin
# Fixed project name
# Please use lowercase letters only
COMPOSE_PROJECT_NAME=mail
# 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=
# 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_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=y
# Skip SOGo: Will disable SOGo integration and therefore webmail, DAV protocols and ActiveSync support (experimental, unsupported, not fully implemented) - y/n
SKIP_SOGO=y
# 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=y
# 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=1024
# 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=warpzone-server-issues@void.ms
# Notify about banned IP (includes whois lookup)
WATCHDOG_NOTIFY_BAN=n
# 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=y
# 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=192.168.15
# 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:dead:beef:2342::/64
# Use this IPv4 for outgoing connections (SNAT)
SNAT_TO_SOURCE={{ ext_ip4 }}
# Use this IPv6 for outgoing connections (SNAT)
SNAT6_TO_SOURCE={{ ext_ip6 }}
# 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=
# Admin User
MAILMAN_ADMIN_USER=listadmin
MAILMAN_ADMIN_EMAIL=listadmin@warpzone.ms
# MTA to use
MTA=postfix
# SMTP Host and Port
SMTP_HOST=smtp
SMTP_PORT=25
# External Domain for Mailman web Interface
SERVE_FROM_DOMAIN={{ listserver }}
# Mailman Secret Key
SECRET_KEY={{ mailman_secret_key }}
# Database for mailman and Hyperkitty
DATABASE_URL=mysql://mailman:{{ mailman_db_pass }}@db/mailman?charset=utf8mb4
# Internal hostname of the Mailman Core Container
MM_HOSTNAME=mailman-core
# User and Password for Mailman API
MAILMAN_REST_USER=mailman
MAILMAN_REST_PASSWORD={{ mailman_restapi_pass }}
# internal URL and API Key for Hyperkitty
HYPERKITTY_URL=http://mailman-web:8000/hyperkitty
HYPERKITTY_API_KEY={{ hyperkitty_api_key }}
###################################
# Additional Setings
###################################
# Set Version
MAILU_VERSION=2.0.4
# Autocreate Admin User
INITIAL_ADMIN_ACCOUNT=mailadmin
INITIAL_ADMIN_DOMAIN={{ domain }}
INITIAL_ADMIN_PW={{ mailu_admin_pass }}
INITIAL_ADMIN_MODE=ifmissing
# force internel connect to rspamd with ipv4
ANTISPAM_ADDRESS=192.168.203.253
# Use Mysql as Database
SQLALCHEMY_DATABASE_URI=mysql+mysqlconnector://mailu:{{ mailu_db_pass }}@db/mailu
# Use Mysql as Database
SQLALCHEMY_DATABASE_URI_ROUNDCUBE=mysql://roundcube:{{ roundcube_db_pass }}@db/roundcube
###################################
# Common configuration variables
###################################
# Set mailu version
MAILU_VERSION=2.0
# Set to a randomly generated 16 bytes string
SECRET_KEY={{ mailu_secret_key }}
# Subnet of the docker network. This should not conflict with any networks to which your system is connected. (Internal and external!)
SUBNET=192.168.203.0/24
# Main mail domain
DOMAIN={{ domain }}
# Hostnames for this server, separated with comas
HOSTNAMES={{ mailserver }}
# Postmaster local part (will append the main mail domain)
POSTMASTER=admin
# Choose how secure connections will behave (value: letsencrypt, cert, notls, mail, mail-letsencrypt)
TLS_FLAVOR=mail
# Authentication rate limit per IP (per /24 on ipv4 and /48 on ipv6)
AUTH_RATELIMIT_IP=60/hour
# Authentication rate limit per user (regardless of the source-IP)
AUTH_RATELIMIT_USER=100/day
# Opt-out of statistics, replace with "True" to opt out
DISABLE_STATISTICS=True
###################################
# Optional features
###################################
# Expose the admin interface (value: true, false)
ADMIN=true
# Choose which webmail to run if any (values: roundcube, snappymail, none)
WEBMAIL=roundcube
# Expose the API interface (value: true, false)
API=false
# Dav server implementation (value: radicale, none)
WEBDAV=none
# Antivirus solution (value: clamav, none)
ANTIVIRUS=none
# Scan Macros solution (value: true, false)
SCAN_MACROS=true
###################################
# Mail settings
###################################
# Message size limit in bytes
# Default: accept messages up to 50MB
# Max attachment size will be 33% smaller
MESSAGE_SIZE_LIMIT=50000000
# Message rate limit (per user)
MESSAGE_RATELIMIT=200/day
# Networks granted relay permissions
# Use this with care, all hosts in this networks will be able to send mail without authentication!
RELAYNETS=
# Will relay all outgoing mails if configured
RELAYHOST=
# Enable fetchmail
FETCHMAIL_ENABLED=False
# Fetchmail delay
FETCHMAIL_DELAY=600
# Recipient delimiter, character used to delimiter localpart from custom address part
# must be set to + for mailman
RECIPIENT_DELIMITER=+
# DMARC rua and ruf email
DMARC_RUA=admin
DMARC_RUF=admin
# Welcome email, enable and set a topic and body if you wish to send welcome
# emails to all users.
WELCOME=false
WELCOME_SUBJECT=Welcome to your new email account
WELCOME_BODY=Welcome to your new email account, if you can read this, then it is configured properly!
# Maildir Compression
# choose compression-method, default: none (value: gz, bz2)
COMPRESSION=
# change compression-level, default: 6 (value: 1-9)
COMPRESSION_LEVEL=
# IMAP full-text search is enabled by default. Set the following variable to off in order to disable the feature.
FULL_TEXT_SEARCH=on
###################################
# Web settings
###################################
# Path to redirect / to
WEBROOT_REDIRECT=/webmail
# Path to the admin interface if enabled
WEB_ADMIN=/admin
# Path to the webmail if enabled
WEB_WEBMAIL=/webmail
# Path to the API interface if enabled
WEB_API=
# Website name
SITENAME=warpzone mail
# Linked Website URL
WEBSITE=https://listserver.{{ domain }}
###################################
# Advanced settings
###################################
# Docker-compose project name, this will prepended to containers names.
COMPOSE_PROJECT_NAME=mailu
# Number of rounds used by the password hashing scheme
CREDENTIAL_ROUNDS=12
# Header to take the real ip from
REAL_IP_HEADER=X-Real-Ip
# IPs for nginx set_real_ip_from (CIDR list separated by commas)
REAL_IP_FROM=0.0.0.0/0
# choose wether mailu bounces (no) or rejects (yes) mail when recipient is unknown (value: yes, no)
REJECT_UNLISTED_RECIPIENT=
# Log level threshold in start.py (value: CRITICAL, ERROR, WARNING, INFO, DEBUG, NOTSET)
LOG_LEVEL=WARNING
# Timezone for the Mailu containers. See this link for all possible values https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
TZ=Europe/Berlin
# Default spam threshold used for new users
DEFAULT_SPAM_THRESHOLD=80
# API token required for authenticating to the RESTful API.
# This is a mandatory setting for using the RESTful API.
API_TOKEN={{ mailu_api_token }}
# Overrides for mailman3 integration
# see https://patrick.georgi.family/2019/01/12/combining-mailman-3-with-mailu/
always_add_missing_headers = yes
append_at_myorigin=no
append_dot_mydomain=no
local_header_rewrite_clients = permit_sasl_authenticated
owner_request_special = no
unknown_local_recipient_reject_code = 550
local_recipient_maps = regexp:/opt/mailman/postfix_lmtp
transport_maps = regexp:/opt/mailman/postfix_lmtp, lmdb:/etc/postfix/transport.map, \${podop}transport
virtual_mailbox_maps = regexp:/opt/mailman/postfix_lmtp, \${podop}mailbox