Stalwart mail: Migrate to PostgreSQL & LLDAP.

This commit is contained in:
Viyurz 2024-04-06 21:43:34 +02:00
parent 1c1c7c22df
commit 9638075580
Signed by: Viyurz
SSH key fingerprint: SHA256:IskOHTmhHSJIvAt04N6aaxd5SZCVWW1Guf9tEcxIMj8
11 changed files with 129 additions and 27 deletions

View file

@ -115,7 +115,7 @@ users:
hedgedoc: 1004 hedgedoc: 1004
homepage: 8686 homepage: 8686
lldap: 1007 lldap: 1007
mailserver: 8 mailserver: 8 # Do not change
postgres: 70 postgres: 70
searxng: 977 searxng: 977
searxng_redis: 999 searxng_redis: 999

View file

@ -1,22 +1,25 @@
- name: - name: "Backup PostgreSQL stalwart database & {{ volumes['mailserver_datadir'] }} directory"
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:
DOCKER_HOST: "{{ docker_host }}"
BORG_PASSCOMMAND: "cat {{ borg_passphrase_file }}"
become: true become: true
block:
- name: Create borg backup
command:
cmd: |
borg create
--compression=lzma
"{{ borg_repodir }}::{{ role_name }}-{now:%Y-%m-%d_%H-%M-%S}"
{{ volumes['mailserver_datadir'] }}
environment:
BORG_PASSCOMMAND: "cat {{ borg_passphrase_file }}"
- name: Prune borg repository - name: Prune borg repository
command: command:
cmd: | cmd: |
borg prune borg prune
--glob-archives='{{ role_name }}-*' --glob-archives='{{ role_name }}-*'
{{ borg_prune_options }} {{ borg_prune_options }}
{{ borg_repodir }} {{ borg_repodir }}
environment: environment:
BORG_PASSCOMMAND: "cat {{ borg_passphrase_file }}" BORG_PASSCOMMAND: "cat {{ borg_passphrase_file }}"
become: true

View file

@ -3,21 +3,24 @@
path: "{{ project_dir }}" path: "{{ project_dir }}"
state: directory state: directory
- name: Template docker-compose.yaml to project directory - name: Template configuration files to project directory
template: template:
src: docker-compose.yaml src: "{{ item.src }}"
dest: "{{ project_dir }}/docker-compose.yaml" dest: "{{ project_dir }}/{{ item.path }}"
owner: "{{ host_uid }}" owner: "{{ host_uid }}"
group: "{{ host_uid }}" group: "{{ users['mailserver'] + uid_shift }}"
mode: '640' mode: '640'
with_filetree: ../templates/
when: item.state == 'file'
become: true
- name: "Create directory {{ volumes['mailserver_datadir'] }} with correct permissions" - name: "Create (if not exists) directory {{ volumes['mailserver_datadir'] }} & set permissions"
file: file:
path: "{{ volumes['mailserver_datadir'] }}" path: "{{ volumes['mailserver_datadir'] }}"
state: directory state: directory
owner: "{{ users['mailserver'] + uid_shift }}" owner: "{{ users['mailserver'] + uid_shift }}"
group: "{{ users['mailserver'] + uid_shift }}" group: "{{ users['mailserver'] + uid_shift }}"
mode: '770' mode: '700'
become: true become: true
- name: Set limited permissions on certificate directories - name: Set limited permissions on certificate directories
@ -76,3 +79,4 @@
- name: Create/Restart project services - name: Create/Restart project services
community.docker.docker_compose: community.docker.docker_compose:
project_src: "{{ project_dir }}" project_src: "{{ project_dir }}"
restarted: true

View file

@ -0,0 +1,10 @@
[server]
hostname = "%{HOST}%"
max-connections = 8192
[server.security]
fail2ban = "100/1d"
[server.run-as]
user = "mail"
group = "mail"

View file

@ -0,0 +1,10 @@
[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"

View file

@ -0,0 +1,3 @@
[global.tracing]
method = "stdout"
level = "debug"

View file

@ -0,0 +1,28 @@
[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"

View file

@ -3,6 +3,8 @@ services:
image: docker.io/stalwartlabs/mail-server:v0.6.0 image: docker.io/stalwartlabs/mail-server:v0.6.0
container_name: mailserver container_name: mailserver
restart: always restart: always
networks:
- mailserver
ports: ports:
- "{{ ports['mailserver_smtp'] }}:25" - "{{ ports['mailserver_smtp'] }}:25"
- {{ ports['mailserver_smtps'] }}:465 - {{ ports['mailserver_smtps'] }}:465
@ -12,3 +14,13 @@ services:
- {{ volumes['mailserver_tls_certificate_file'] }}:/etc/fullchain.pem - {{ volumes['mailserver_tls_certificate_file'] }}:/etc/fullchain.pem
- {{ volumes['mailserver_tls_certificate_key_file'] }}:/etc/privkey.pem - {{ volumes['mailserver_tls_certificate_key_file'] }}:/etc/privkey.pem
- {{ volumes['mailserver_datadir' ] }}:/opt/stalwart-mail - {{ 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
networks:
mailserver:
name: mailserver

View file

@ -0,0 +1,9 @@
[server.listener."smtp"]
bind = ["[::]:25"]
protocol = "smtp"
tls.implicit = false
[server.listener."submissions"]
bind = ["[::]:465"]
protocol = "smtp"
tls.implicit = true

View file

@ -0,0 +1,17 @@
[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 *"

View file

@ -35,6 +35,12 @@ lldap_secrets:
postgres_user: postgres_user:
postgres_password: postgres_password:
mailserver_secrets:
ldap_user:
ldap_password:
postgres_user:
postgres_password:
searxng_secrets: searxng_secrets:
searxng_secret: searxng_secret: