From b544f9a78d0851d2127f32435e01456a6f7f5974 Mon Sep 17 00:00:00 2001 From: Viyurz Date: Thu, 2 May 2024 22:49:00 +0200 Subject: [PATCH] Update Stalwart mailserver to 0.7.3 from 0.6.0. --- README.md | 8 -- env.yml | 3 +- roles/mailserver/tasks/backup.yml | 3 +- roles/mailserver/tasks/setup.yml | 22 ++-- roles/mailserver/templates/common-server.toml | 10 -- roles/mailserver/templates/common-tls.toml | 10 -- .../mailserver/templates/common-tracing.toml | 3 - roles/mailserver/templates/config.toml | 105 ++++++++++++++++++ .../mailserver/templates/directory-ldap.toml | 28 ----- .../mailserver/templates/docker-compose.yaml | 12 +- roles/mailserver/templates/smtp-listener.toml | 9 -- .../templates/store-postgresql.toml | 17 --- .../sites-enabled/{jmap.conf => mail.conf} | 4 +- secrets.yml.example | 3 + 14 files changed, 122 insertions(+), 115 deletions(-) delete mode 100644 roles/mailserver/templates/common-server.toml delete mode 100644 roles/mailserver/templates/common-tls.toml delete mode 100644 roles/mailserver/templates/common-tracing.toml create mode 100644 roles/mailserver/templates/config.toml delete mode 100644 roles/mailserver/templates/directory-ldap.toml delete mode 100644 roles/mailserver/templates/smtp-listener.toml delete mode 100644 roles/mailserver/templates/store-postgresql.toml rename roles/nginx/templates/sites-enabled/{jmap.conf => mail.conf} (63%) diff --git a/README.md b/README.md index d8a74aa..c46c629 100644 --- a/README.md +++ b/README.md @@ -45,11 +45,3 @@ After that, you can create a root cronjob to run this playbook without requiring ``` Here we leave `selected_projects` empty to backup all projects. - - -## Mailserver -When starting the container for the first time, run the initial setup: -``` -docker exec -it mailserver /bin/sh /usr/local/bin/configure.sh -``` -After that, re-run the setup tasks because `configure.sh` overrides the config files. diff --git a/env.yml b/env.yml index e6799ff..1037f11 100644 --- a/env.yml +++ b/env.yml @@ -95,7 +95,7 @@ ports: mailserver_smtp: 1025 mailserver_smtps: 1465 mailserver_imaps: 1993 - mailserver_jmap: 1443 + mailserver_https: 1443 postgres: 5432 searxng: 8083 stump: 10801 @@ -139,7 +139,6 @@ volumes: etebase_datadir: /mnt/etebasedata hedgedoc_uploadsdir: /mnt/hedgedocuploads lldap_datadir: /mnt/lldapdata - mailserver_datadir: /mnt/mailserverdata mailserver_tls_certificate_file: "/etc/letsencrypt/live/mail.{{ domain }}/fullchain.pem" mailserver_tls_certificate_key_file: "/etc/letsencrypt/live/mail.{{ domain }}/privkey.pem" postgres_datadir: /mnt/postgresdata diff --git a/roles/mailserver/tasks/backup.yml b/roles/mailserver/tasks/backup.yml index a36a2eb..a5ecaf0 100644 --- a/roles/mailserver/tasks/backup.yml +++ b/roles/mailserver/tasks/backup.yml @@ -1,11 +1,10 @@ -- name: "Backup PostgreSQL stalwart database & {{ volumes['mailserver_datadir'] }} directory" +- name: "Backup PostgreSQL stalwart database" shell: > docker exec postgres pg_dump -c {{ role_name }} | borg create --compression lzma "{{ borg_repodir }}::{{ role_name }}-{now:%Y-%m-%d_%H-%M-%S}" - "{{ volumes['mailserver_datadir'] }}" - --stdin-name dump_{{ role_name }}.sql environment: diff --git a/roles/mailserver/tasks/setup.yml b/roles/mailserver/tasks/setup.yml index bb1b504..85b0e1b 100644 --- a/roles/mailserver/tasks/setup.yml +++ b/roles/mailserver/tasks/setup.yml @@ -6,24 +6,16 @@ - absent - directory -- name: Template configuration files to project directory +- name: Template docker-compose.yaml & config.toml to project directory template: - src: "{{ item.src }}" - dest: "{{ project_dir }}/{{ item.path }}" + src: "{{ item }}" + dest: "{{ project_dir }}/{{ item }}" owner: "{{ host_uid }}" group: "{{ users['mailserver'] + uid_shift }}" - mode: '640' - with_filetree: ../templates/ - when: item.state == 'file' - become: true - -- name: "Create (if not exists) directory {{ volumes['mailserver_datadir'] }} & set permissions" - file: - path: "{{ volumes['mailserver_datadir'] }}" - state: directory - owner: "{{ users['mailserver'] + uid_shift }}" - group: "{{ users['mailserver'] + uid_shift }}" - mode: '700' + mode: '660' + loop: + - docker-compose.yaml + - config.toml become: true - name: Set limited permissions on certificate directories diff --git a/roles/mailserver/templates/common-server.toml b/roles/mailserver/templates/common-server.toml deleted file mode 100644 index 4e55ded..0000000 --- a/roles/mailserver/templates/common-server.toml +++ /dev/null @@ -1,10 +0,0 @@ -[server] -hostname = "%{HOST}%" -max-connections = 8192 - -[server.security] -fail2ban = "100/1d" - -[server.run-as] -user = "mail" -group = "mail" diff --git a/roles/mailserver/templates/common-tls.toml b/roles/mailserver/templates/common-tls.toml deleted file mode 100644 index 03913b1..0000000 --- a/roles/mailserver/templates/common-tls.toml +++ /dev/null @@ -1,10 +0,0 @@ -[server.tls] -enable = true -implicit = true -timeout = "1m" -certificate = "default" -ignore-client-order = true - -[certificate."default"] -cert = "file:///etc/fullchain.pem" -private-key = "file:///etc/privkey.pem" diff --git a/roles/mailserver/templates/common-tracing.toml b/roles/mailserver/templates/common-tracing.toml deleted file mode 100644 index 3b43356..0000000 --- a/roles/mailserver/templates/common-tracing.toml +++ /dev/null @@ -1,3 +0,0 @@ -[global.tracing] -method = "stdout" -level = "debug" diff --git a/roles/mailserver/templates/config.toml b/roles/mailserver/templates/config.toml new file mode 100644 index 0000000..2793ef0 --- /dev/null +++ b/roles/mailserver/templates/config.toml @@ -0,0 +1,105 @@ +authentication.fallback-admin.secret = "{{ mailserver_secrets['admin_secret'] }}" +authentication.fallback-admin.user = "{{ mailserver_secrets['admin_user'] }}" +cluster.node-id = 1 +lookup.default.hostname = "mail.{{ domain }}" + + +# Server settings +server.http.permissive-cors = false +server.http.url = "protocol + '://' + key_get('default', 'hostname') + ':' + local_port" +server.http.use-x-forwarded = true +server.max-connections = 8192 +server.run-as.group = "mail" +server.run-as.user = "mail" +server.socket.backlog = 1024 +server.socket.nodelay = true +server.socket.reuse-addr = true +server.socket.reuse-port = true + + +# Listeners +server.listener.https.bind = "[::]:443" +server.listener.https.protocol = "http" +server.listener.https.tls.implicit = true +server.listener.imaptls.bind = "[::]:993" +server.listener.imaptls.protocol = "imap" +server.listener.imaptls.tls.implicit = true +server.listener.smtp.bind = "[::]:25" +server.listener.smtp.protocol = "smtp" +server.listener.smtp.tls.implicit = false +server.listener.submissions.bind = "[::]:465" +server.listener.submissions.protocol = "smtp" +server.listener.submissions.tls.implicit = true + + +# Certificate settings +certificate."default".cert = "%{file:///etc/fullchain.pem}%" +certificate."default".default = true +certificate."default".private-key = "%{file:///etc/privkey.pem}%" + + +# Storage settings +storage.blob = "postgresql" +storage.data = "postgresql" +storage.directory = "ldap" +storage.fts = "postgresql" +storage.lookup = "postgresql" + + +# Directory settings +# Note: 'directory.ldap.attributes.secret' must not be defined +# to correctly disable OAuth, if the LDAP server doesn't expose passwords hashes. +directory.ldap.attributes.class = "objectClass" +directory.ldap.attributes.description = "distinguishedName" +directory.ldap.attributes.email = "mail" +directory.ldap.attributes.email-alias = "mailAlias" +directory.ldap.attributes.groups = "memberOf" +directory.ldap.attributes.name = "uid" +directory.ldap.attributes.quota = "diskQuota" +directory.ldap.base-dn = "{{ ldap_base_dn }}" +directory.ldap.bind.auth.dn = "uid=?,ou=people,{{ ldap_base_dn }}" +directory.ldap.bind.auth.enable = true +directory.ldap.bind.dn = "{{ mailserver_secrets['ldap_user'] }}" +directory.ldap.bind.secret = "{{ mailserver_secrets['ldap_password'] }}" +directory.ldap.cache.entries = 500 +directory.ldap.cache.ttl.negative = "10m" +directory.ldap.cache.ttl.positive = "1h" +directory.ldap.filter.domains = "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(|(mail=*@?)(mailAlias=*@?)))" +directory.ldap.filter.email = "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(|(mail=?)(mailAlias=?)(mailList=?))(mail=*@{{ domain }}))" +directory.ldap.filter.expand = "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(mailList=?))" +directory.ldap.filter.name = "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(uid=?))" +directory.ldap.filter.verify = "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(|(mail=*?*)(mailAlias=*?*)))" +directory.ldap.timeout = "15s" +directory.ldap.tls.allow-invalid-certs = false +directory.ldap.tls.enable = false +directory.ldap.type = "ldap" +directory.ldap.url = "ldap://lldap:3890" + + +# Store settings +store.postgresql.compression = "lz4" +store.postgresql.database = "stalwart" +store.postgresql.host = "postgres.{{ domain }}" +store.postgresql.password = "{{ mailserver_secrets['postgres_password'] }}" +store.postgresql.pool.max-connections = 10 +store.postgresql.port = "5432" +store.postgresql.purge.frequency = "0 3 *" +store.postgresql.query.domains = "SELECT 1 FROM emails WHERE address LIKE '%@' || $1 LIMIT 1" +store.postgresql.query.emails = "SELECT address FROM emails WHERE name = $1 AND type != 'list' ORDER BY type DESC, address ASC" +store.postgresql.query.expand = "SELECT p.address FROM emails AS p JOIN emails AS l ON p.name = l.name WHERE p.type = 'primary' AND l.address = $1 AND l.type = 'list' ORDER BY p.address LIMIT 50" +store.postgresql.query.members = "SELECT member_of FROM group_members WHERE name = $1" +store.postgresql.query.name = "SELECT name, type, secret, description, quota FROM accounts WHERE name = $1 AND active = true" +store.postgresql.query.recipients = "SELECT name FROM emails WHERE address = $1 ORDER BY name ASC" +store.postgresql.query.verify = "SELECT address FROM emails WHERE address LIKE '%' || $1 || '%' AND type = 'primary' ORDER BY address LIMIT 5" +store.postgresql.timeout = "15s" +store.postgresql.tls.allow-invalid-certs = true +store.postgresql.tls.enable = true +store.postgresql.type = "postgresql" +store.postgresql.user = "{{ mailserver_secrets['postgres_user'] }}" + + +# Logs settings +tracer.stdout.ansi = true +tracer.stdout.enable = true +tracer.stdout.level = "debug" +tracer.stdout.type = "stdout" diff --git a/roles/mailserver/templates/directory-ldap.toml b/roles/mailserver/templates/directory-ldap.toml deleted file mode 100644 index 40b0eed..0000000 --- a/roles/mailserver/templates/directory-ldap.toml +++ /dev/null @@ -1,28 +0,0 @@ -[directory."ldap"] -type = "ldap" -address = "ldap://lldap:3890" -base-dn = "{{ ldap_base_dn }}" -timeout = "30s" -tls.enable = false - -[directory."ldap".bind] -dn = "{{ mailserver_secrets['ldap_user'] }}" -secret = "{{ mailserver_secrets['ldap_password'] }}" - -[directory."ldap".bind.auth] -enable = true -dn = "uid=?,ou=people,{{ ldap_base_dn }}" - -[directory."ldap".filter] -name = "(&(|(objectClass=person)(objectClass=posixGroup))(uid=?))" -email = "(&(|(objectClass=person)(objectClass=posixGroup))(|(mail=?)(mailAlias=?)(mailList=?))(mail=*@{{ domain }}))" -verify = "(&(|(objectClass=person)(objectClass=posixGroup))(|(mail=*?*)(mailAlias=*?*)))" -expand = "(&(|(objectClass=person)(objectClass=posixGroup))(mailList=?))" -domains = "(&(|(objectClass=person)(objectClass=posixGroup))(|(mail=*@?)(mailAlias=*@?)))" - -[directory."ldap".attributes] -name = "uid" -type = "objectClass" -description = ["distinguishedName"] -email = "mail" -email-alias = "mailAlias" diff --git a/roles/mailserver/templates/docker-compose.yaml b/roles/mailserver/templates/docker-compose.yaml index 7595cd0..499171d 100644 --- a/roles/mailserver/templates/docker-compose.yaml +++ b/roles/mailserver/templates/docker-compose.yaml @@ -1,6 +1,6 @@ services: mailserver: - image: docker.io/stalwartlabs/mail-server:v0.6.0 + image: docker.io/stalwartlabs/mail-server:v0.7.3 container_name: mailserver restart: always networks: @@ -9,17 +9,11 @@ services: - "{{ ports['mailserver_smtp'] }}:25" - {{ ports['mailserver_smtps'] }}:465 - {{ ports['mailserver_imaps'] }}:993 - - {{ ports['mailserver_jmap'] }}:443 + - {{ ports['mailserver_https'] }}:443 volumes: - {{ volumes['mailserver_tls_certificate_file'] }}:/etc/fullchain.pem - {{ volumes['mailserver_tls_certificate_key_file'] }}:/etc/privkey.pem - - {{ volumes['mailserver_datadir' ] }}:/opt/stalwart-mail - - ./common-server.toml:/opt/stalwart-mail/etc/common/server.toml - - ./common-tls.toml:/opt/stalwart-mail/etc/common/tls.toml - - ./common-tracing.toml:/opt/stalwart-mail/etc/common/tracing.toml - - ./directory-ldap.toml:/opt/stalwart-mail/etc/directory/ldap.toml - - ./store-postgresql.toml:/opt/stalwart-mail/etc/store/postgresql.toml - - ./smtp-listener.toml:/opt/stalwart-mail/etc/smtp/listener.toml + - ./config.toml:/opt/stalwart-mail/etc/config.toml networks: mailserver: diff --git a/roles/mailserver/templates/smtp-listener.toml b/roles/mailserver/templates/smtp-listener.toml deleted file mode 100644 index 951c9be..0000000 --- a/roles/mailserver/templates/smtp-listener.toml +++ /dev/null @@ -1,9 +0,0 @@ -[server.listener."smtp"] -bind = ["[::]:25"] -protocol = "smtp" -tls.implicit = false - -[server.listener."submissions"] -bind = ["[::]:465"] -protocol = "smtp" -tls.implicit = true diff --git a/roles/mailserver/templates/store-postgresql.toml b/roles/mailserver/templates/store-postgresql.toml deleted file mode 100644 index 8ad0405..0000000 --- a/roles/mailserver/templates/store-postgresql.toml +++ /dev/null @@ -1,17 +0,0 @@ -[store."postgresql"] -type = "postgresql" -host = "postgres.{{ domain }}" -port = 5432 -database = "stalwart" -user = "{{ mailserver_secrets['postgres_user'] }}" -password = "{{ mailserver_secrets['postgres_password'] }}" - -[store."postgresql".timeout] -connect = "15s" - -[store."postgresql".tls] -enable = false -allow-invalid-certs = false - -[store."postgresql".purge] -frequency = "0 3 *" diff --git a/roles/nginx/templates/sites-enabled/jmap.conf b/roles/nginx/templates/sites-enabled/mail.conf similarity index 63% rename from roles/nginx/templates/sites-enabled/jmap.conf rename to roles/nginx/templates/sites-enabled/mail.conf index 943771d..d8599d5 100644 --- a/roles/nginx/templates/sites-enabled/jmap.conf +++ b/roles/nginx/templates/sites-enabled/mail.conf @@ -2,10 +2,10 @@ server { listen 443 ssl; listen [::]:443 ssl; - server_name jmap.{{ domain }}; + server_name mail.{{ domain }}; location / { - proxy_pass https://127.0.0.1:{{ ports['mailserver_jmap'] }}; + proxy_pass https://127.0.0.1:{{ ports['mailserver_https'] }}; include /etc/nginx/snippets/websocket.conf; include /etc/nginx/snippets/proxy.conf; diff --git a/secrets.yml.example b/secrets.yml.example index 3dfbb73..f1fe6d9 100644 --- a/secrets.yml.example +++ b/secrets.yml.example @@ -36,6 +36,9 @@ lldap_secrets: postgres_password: mailserver_secrets: + admin_user: + # Hash obtained with openssl passwd -6 + admin_secret: ldap_user: ldap_password: postgres_user: