From 9f72ccca0af2ed4337d17509ea3b9737cb80e4db Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Fri, 22 Mar 2024 18:43:42 -0400 Subject: [PATCH] ldap + dockermailserver --- TODO.md | 3 + deploy.yml | 3 + group_vars/certbot.yml | 1 + group_vars/host_domains.yml | 2 +- group_vars/mail.yml | 22 ++++++++ inventory | 5 +- playbooks/deploy-mail.yml | 6 ++ playbooks/roles/kanidm/templates/kanidm.sh | 13 +++++ playbooks/roles/mail/tasks/main.yml | 56 +++++++++++++++++++ .../mail/templates/docker-compose.yml.j2 | 45 +++++++++++++++ .../roles/mail/templates/dovecot-ldap.conf.j2 | 10 ++++ .../roles/mail/templates/user-patches.sh.j2 | 10 ++++ .../http.mail.hatecomputers.club.conf | 8 +++ .../https.mail.hatecomputers.club.conf | 21 +++++++ secrets.txt | 1 + 15 files changed, 204 insertions(+), 2 deletions(-) create mode 100644 TODO.md create mode 100644 group_vars/mail.yml create mode 100644 playbooks/deploy-mail.yml create mode 100644 playbooks/roles/kanidm/templates/kanidm.sh create mode 100644 playbooks/roles/mail/tasks/main.yml create mode 100644 playbooks/roles/mail/templates/docker-compose.yml.j2 create mode 100644 playbooks/roles/mail/templates/dovecot-ldap.conf.j2 create mode 100644 playbooks/roles/mail/templates/user-patches.sh.j2 create mode 100644 playbooks/roles/nginx/templates/fern.hatecomputers.club/http.mail.hatecomputers.club.conf create mode 100644 playbooks/roles/nginx/templates/fern.hatecomputers.club/https.mail.hatecomputers.club.conf diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..83feb2d --- /dev/null +++ b/TODO.md @@ -0,0 +1,3 @@ +- [ ] nameservers for users +- [ ] create dmarc.report, postmaster email users, give access to infra users +- [ ] figure oute mailbox permissions, ensure users can't just set random senders and stuff, domain fixing diff --git a/deploy.yml b/deploy.yml index 6d51670..1d57439 100644 --- a/deploy.yml +++ b/deploy.yml @@ -11,3 +11,6 @@ - name: Kanidm ansible.builtin.import_playbook: playbooks/deploy-kanidm.yml + +- name: Mail + ansible.builtin.import_playbook: playbooks/deploy-mail.yml diff --git a/group_vars/certbot.yml b/group_vars/certbot.yml index 9d8a227..4498765 100644 --- a/group_vars/certbot.yml +++ b/group_vars/certbot.yml @@ -3,3 +3,4 @@ cloudflare_credentials_destination: /root/.cloudflare-dns-api-key.ini certbot_post_hook_dir: /etc/letsencrypt/renewal-hooks/post certbot_live_dir: /etc/letsencrypt/live +certbot_email: infra@hatecomputers.club diff --git a/group_vars/host_domains.yml b/group_vars/host_domains.yml index aa81c0f..cf16d66 100644 --- a/group_vars/host_domains.yml +++ b/group_vars/host_domains.yml @@ -4,4 +4,4 @@ host_domains: fern.hatecomputers.club: - fern.hatecomputers.club - auth.hatecomputers.club - - vpn.hatecomputers.club + - mail.hatecomputers.club diff --git a/group_vars/mail.yml b/group_vars/mail.yml new file mode 100644 index 0000000..2a46f19 --- /dev/null +++ b/group_vars/mail.yml @@ -0,0 +1,22 @@ +--- + +postmaster_email: postmaster@hatecomputers.club + +domain: hatecomputers.club +mail_domain: mail.hatecomputers.club + +ldap_server_host: "ldaps://auth.hatecomputers.club:3636" +ldap_search_base: "dc=auth,dc=hatecomputers,dc=club" +ldap_bind_dn: "dn=token" + +ldap_query_filter_user: "(&(objectClass=posixAccount)(mail=%s))" +ldap_query_filter_group: "(&(objectClass=posixAccount)(|(mail=%s)(uid=%s)))" +ldap_query_filter_alias: "(&(objectClass=posixAccount)(emailalternative=%s))" +ldap_query_filter_domain: "(&(objectClass=posixAccount)(|(mail=%s)(uid=%s)))" +ldap_query_filter_senders: "(&(objectClass=posixAccount)(|(mail=%s)(uid=%s)))" + +sasl_ldap_filter: "(&(|(uid=%U)(mail=%U))(class=posixAccount))" + +dovecot_user_filter: "(&(class=posixAccount)(uid=%u))" +dovecot_auth_bind_userdn: "uid=%u,dc=auth,dc=hatecomputers,dc=club" +dovecot_user_attrs: "=mail=maildir:~/Maildir,uidNumber=uid,gidNumber=gid" diff --git a/inventory b/inventory index 56faa32..a1b4dcc 100644 --- a/inventory +++ b/inventory @@ -4,11 +4,14 @@ fern.hatecomputers.club ansible_user=root ansible_connection=ssh [host_domains] fern.hatecomputers.club ansible_user=root ansible_connection=ssh +[nginx] +fern.hatecomputers.club ansible_user=root ansible_connection=ssh + [certbot] fern.hatecomputers.club ansible_user=root ansible_connection=ssh [kanidm] fern.hatecomputers.club ansible_user=root ansible_connection=ssh -[nginx] +[mail] fern.hatecomputers.club ansible_user=root ansible_connection=ssh diff --git a/playbooks/deploy-mail.yml b/playbooks/deploy-mail.yml new file mode 100644 index 0000000..dc9a7b2 --- /dev/null +++ b/playbooks/deploy-mail.yml @@ -0,0 +1,6 @@ +--- + +- name: Mail setup + hosts: mail + roles: + - mail diff --git a/playbooks/roles/kanidm/templates/kanidm.sh b/playbooks/roles/kanidm/templates/kanidm.sh new file mode 100644 index 0000000..c3f6f9f --- /dev/null +++ b/playbooks/roles/kanidm/templates/kanidm.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +echo '{}' > ~/.cache/kanidm_tokens +chmod 666 ~/.cache/kanidm_tokens +docker pull kanidm/tools:latest +docker run --rm -i -t \ + --network host \ + -v /etc/kanidm/config:/etc/kanidm/config:ro \ + -v ~/.config/kanidm:/home/kanidm/.config/kanidm:ro \ + -v ~/.cache/kanidm_tokens:/home/kanidm/.cache/kanidm_tokens \ + kanidm/tools:latest \ + /sbin/kanidm --help + diff --git a/playbooks/roles/mail/tasks/main.yml b/playbooks/roles/mail/tasks/main.yml new file mode 100644 index 0000000..8296d28 --- /dev/null +++ b/playbooks/roles/mail/tasks/main.yml @@ -0,0 +1,56 @@ +--- + +- name: Ensure mail docker/compose exist + ansible.builtin.file: + path: /etc/docker/compose/mail + state: directory + owner: root + group: root + mode: 0700 + +- name: Ensure mail config volume exist + file: + path: /etc/docker/compose/mail/docker-data/dms/config + state: directory + owner: root + group: root + mode: 0700 + +- name: Ensure mail entries volume exist with correct permission + file: + path: /etc/docker/compose/mail/docker-data/dms/mail-data/ + state: directory + owner: root + group: root + mode: 0777 + recurse: true + +- name: Ensure dovecot ldap config exist + ansible.builtin.template: + src: user-patches.sh.j2 + dest: /etc/docker/compose/mail/docker-data/dms/config/user-patches.sh + owner: root + group: root + mode: 0755 + +- name: Ensure config user overrides config exist + ansible.builtin.template: + src: dovecot-ldap.conf.j2 + dest: /etc/docker/compose/mail/docker-data/dms/config/dovecot-ldap.conf + owner: root + group: root + mode: 0700 + +- name: Build mail docker-compose.yml.j2 + ansible.builtin.template: + src: docker-compose.yml.j2 + dest: /etc/docker/compose/mail/docker-compose.yml + owner: root + group: root + mode: 0700 + +- name: Daemon-reload and enable mail + ansible.builtin.systemd_service: + state: restarted + enabled: true + name: docker-compose@mail diff --git a/playbooks/roles/mail/templates/docker-compose.yml.j2 b/playbooks/roles/mail/templates/docker-compose.yml.j2 new file mode 100644 index 0000000..e493458 --- /dev/null +++ b/playbooks/roles/mail/templates/docker-compose.yml.j2 @@ -0,0 +1,45 @@ +services: + mailserver: + image: ghcr.io/docker-mailserver/docker-mailserver:latest + container_name: mailserver + hostname: {{ mail_domain }} + ports: + - "0.0.0.0:25:25" + - "0.0.0.0:465:465" + - "0.0.0.0:587:587" + - "0.0.0.0: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/ + - ./docker-data/dms/config/dovecot-ldap.conf:/etc/dovecot/dovecot-ldap.conf.ext + - /etc/letsencrypt:/etc/letsencrypt:ro + - /etc/localtime:/etc/localtime:ro + environment: + - SSL_TYPE=letsencrypt + - ENABLE_CLAMAV=1 + - ENABLE_AMAVIS=1 + - ENABLE_FAIL2BAN=1 + - ENABLE_SASLAUTHD=1 + - ENABLE_POSTGREY=0 + + - SPOOF_PROTECTION=1 + - ACCOUNT_PROVISIONER=LDAP + - LDAP_SERVER_HOST={{ ldap_server_host }} + - LDAP_SEARCH_BASE={{ ldap_search_base }} + - LDAP_BIND_DN={{ ldap_bind_dn }} + - LDAP_BIND_PW={{ email_ldap_api_token }} + + - LDAP_QUERY_FILTER_USER={{ ldap_query_filter_user }} + - LDAP_QUERY_FILTER_GROUP={{ ldap_query_filter_group }} + - LDAP_QUERY_FILTER_ALIAS={{ ldap_query_filter_alias }} + - LDAP_QUERY_FILTER_DOMAIN={{ ldap_query_filter_domain }} + - LDAP_QUERY_FILTER_SENDERS={{ ldap_query_filter_senders }} + + - POSTMASTER_ADDRESS={{ postmaster_email }} + + - ENABLE_SASLAUTHD=1 + - SASLAUTHD_MECHANISMS=ldap + - SASLAUTHD_LDAP_FILTER={{ sasl_ldap_filter }} + restart: always diff --git a/playbooks/roles/mail/templates/dovecot-ldap.conf.j2 b/playbooks/roles/mail/templates/dovecot-ldap.conf.j2 new file mode 100644 index 0000000..92bfcbd --- /dev/null +++ b/playbooks/roles/mail/templates/dovecot-ldap.conf.j2 @@ -0,0 +1,10 @@ +base = {{ ldap_search_base }} +uris = {{ ldap_server_host }} +tls = no +ldap_version = 3 +default_pass_scheme = SSHA + +auth_bind = yes +auth_bind_userdn = {{ dovecot_auth_bind_userdn }} +user_filter = {{ dovecot_user_filter }} +user_attrs = {{ dovecot_user_attrs }} diff --git a/playbooks/roles/mail/templates/user-patches.sh.j2 b/playbooks/roles/mail/templates/user-patches.sh.j2 new file mode 100644 index 0000000..313b30b --- /dev/null +++ b/playbooks/roles/mail/templates/user-patches.sh.j2 @@ -0,0 +1,10 @@ +#!/bin/bash + +postconf -e 'smtpd_sasl_auth_enable = yes' + +postconf -e 'smtpd_sasl_type = dovecot' +postconf -e 'smtpd_sasl_path = /dev/shm/sasl-auth.sock' +postconf -e 'smtpd_sasl_auth_enable = yes' +postconf -e 'broken_sasl_auth_clients = yes' + +echo 'auth_username_format = %Ln' >> /etc/dovecot/conf.d/10-auth.conf diff --git a/playbooks/roles/nginx/templates/fern.hatecomputers.club/http.mail.hatecomputers.club.conf b/playbooks/roles/nginx/templates/fern.hatecomputers.club/http.mail.hatecomputers.club.conf new file mode 100644 index 0000000..59982ab --- /dev/null +++ b/playbooks/roles/nginx/templates/fern.hatecomputers.club/http.mail.hatecomputers.club.conf @@ -0,0 +1,8 @@ +server { + listen 80; + server_name mail.hatecomputers.club; + + location / { + rewrite ^ https://mail.hatecomputers.club$request_uri? permanent; + } +} diff --git a/playbooks/roles/nginx/templates/fern.hatecomputers.club/https.mail.hatecomputers.club.conf b/playbooks/roles/nginx/templates/fern.hatecomputers.club/https.mail.hatecomputers.club.conf new file mode 100644 index 0000000..1c6d579 --- /dev/null +++ b/playbooks/roles/nginx/templates/fern.hatecomputers.club/https.mail.hatecomputers.club.conf @@ -0,0 +1,21 @@ +server { + server_name mail.hatecomputers.club; + listen 443 ssl; + + ssl_dhparam /etc/nginx/dhparams.pem; + + ssl_session_timeout 1d; + ssl_session_tickets off; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305; + ssl_prefer_server_ciphers off; + + ssl_certificate /etc/letsencrypt/live/mail.hatecomputers.club/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/mail.hatecomputers.club/privkey.pem; + + location / { + proxy_pass http://127.0.0.1:8331; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $host; + } +} diff --git a/secrets.txt b/secrets.txt index 57e0480..59f81b8 100644 --- a/secrets.txt +++ b/secrets.txt @@ -1,2 +1,3 @@ cloudflare_api_token certbot_email +email_ldap_api_token