From ae64628958a10362aa7c65050ca8ff2546220c95 Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Sun, 7 Jan 2024 00:35:54 -0500 Subject: [PATCH] add mail role! --- deploy-mail.yml | 4 ++ group_vars/mail.yml | 5 ++ inventory | 5 +- roles/mail/tasks/main.yml | 57 +++++++++++++++++++ roles/mail/templates/docker-compose.yml.j2 | 46 +++++++++++++++ .../nameservers/templates/db.simponic.xyz.j2 | 6 +- roles/private/tasks/main.yml | 6 +- roles/vpn/templates/config.yml.j2 | 2 +- 8 files changed, 121 insertions(+), 10 deletions(-) create mode 100644 deploy-mail.yml create mode 100644 group_vars/mail.yml create mode 100644 roles/mail/tasks/main.yml create mode 100644 roles/mail/templates/docker-compose.yml.j2 diff --git a/deploy-mail.yml b/deploy-mail.yml new file mode 100644 index 0000000..457edcb --- /dev/null +++ b/deploy-mail.yml @@ -0,0 +1,4 @@ +- name: mail setup + hosts: mail + roles: + - mail diff --git a/group_vars/mail.yml b/group_vars/mail.yml new file mode 100644 index 0000000..56b57b6 --- /dev/null +++ b/group_vars/mail.yml @@ -0,0 +1,5 @@ +--- +domain: mail.simponic.xyz +certbot_email: elizabeth.hunt@simponic.xyz +postmaster_email: postmaster@simponic.xyz +lldap_admin_pass: "{{ lookup('env', 'LLDAP_USER_PASS') }}" diff --git a/inventory b/inventory index b855b00..2e8c9cc 100644 --- a/inventory +++ b/inventory @@ -2,7 +2,7 @@ nijika ansible_user=root ansible_connection=ssh ryo ansible_user=root ansible_connection=ssh levi ansible_user=root ansible_connection=ssh -#ash ansible_user=root ansible_connection=ssh +mail.simponic.xyz ansible_user=root ansible_connection=ssh [private] johan ansible_user=root ansible_connection=ssh @@ -10,7 +10,6 @@ johan ansible_user=root ansible_connection=ssh [webservers] levi ansible_user=root ansible_connection=ssh nijika ansible_user=root ansible_connection=ssh -#ash.internal.simponic.xyz ansible_user=root ansible_connection=ssh [nameservers] ryo ansible_user=root ansible_connection=ssh @@ -41,4 +40,4 @@ johan ansible_user=root ansible_connection=ssh johan ansible_user=root ansible_connection=ssh [mail] -#ash ansible_user=root ansible_connection=ssh +mail.simponic.xyz ansible_user=root ansible_connection=ssh diff --git a/roles/mail/tasks/main.yml b/roles/mail/tasks/main.yml new file mode 100644 index 0000000..4233f68 --- /dev/null +++ b/roles/mail/tasks/main.yml @@ -0,0 +1,57 @@ +--- +- name: install letsencrypt + apt: + name: letsencrypt + state: latest + +- name: allow 80/tcp ufw + ufw: + rule: allow + port: '80' + proto: 'tcp' + +- name: allow 443/tcp ufw + ufw: + rule: allow + port: '443' + proto: 'tcp' + +- name: restart ufw + service: name=ufw state=restarted enabled=yes + +- name: request certificate + shell: > + letsencrypt certonly -n --standalone -d "{{ domain }}" \ + -m "{{ certbot_email }}" --agree-tos + args: + creates: "/etc/letsencrypt/live/{{ domain }}" + +- name: add monthly letsencrypt cronjob for cert renewal + cron: + name: "letsencrypt_renewal_mail" + day: "18" + hour: "2" + minute: "1" + job: "letsencrypt renew --cert-name {{ domain }} -n --standalone --agree-tos -m {{ certbot_email }}" + +- name: ensure mail docker/compose exist + file: + path: /etc/docker/compose/mail + state: directory + owner: root + group: root + mode: 0700 + +- name: build mail docker-compose.yml.j2 + template: + src: ../templates/docker-compose.yml.j2 + dest: /etc/docker/compose/mail/docker-compose.yml + owner: root + group: root + mode: u=rw,g=r,o=r + +- name: daemon-reload and enable mail + ansible.builtin.systemd_service: + state: restarted + enabled: true + name: docker-compose@mail diff --git a/roles/mail/templates/docker-compose.yml.j2 b/roles/mail/templates/docker-compose.yml.j2 new file mode 100644 index 0000000..091ef78 --- /dev/null +++ b/roles/mail/templates/docker-compose.yml.j2 @@ -0,0 +1,46 @@ +services: + mailserver: + image: ghcr.io/docker-mailserver/docker-mailserver:latest + container_name: mailserver + # Provide the FQDN of your mail server here (Your DNS MX record should point to this value) + hostname: {{ domain }} + ports: + - "25:25" + - "465:465" + - "587:587" + - "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/ + - /etc/letsencrypt:/etc/letsencrypt + - /etc/localtime:/etc/localtime:ro + environment: + - SSL_TYPE=letsencrypt + - ENABLE_CLAMAV=0 + - ENABLE_AMAVIS=0 + - ENABLE_FAIL2BAN=0 + - SPOOF_PROTECTION=1 + - ACCOUNT_PROVISIONER=LDAP + - LDAP_SERVER_HOST=ldap://lldap.internal.simponic.xyz:3890 + - LDAP_SEARCH_BASE=dc=simponic,dc=xyz + - LDAP_BIND_DN=uid=admin,ou=people,dc=simponic,dc=xyz + - LDAP_BIND_PW={{ lldap_admin_pass }} + + - LDAP_QUERY_FILTER_USER=(&(objectClass=mailAccount)(|(uid=%u))) + - LDAP_QUERY_FILTER_GROUP=(&(cn=mail)(uniquemember=uid=%u,ou=people,dc=simponic,dc=xyz)) + - LDAP_QUERY_FILTER_ALIAS=(&(objectClass=inetOrgPerson)(|(uid=%u)(mail=%u))) + - LDAP_QUERY_FILTER_DOMAIN=(mail=*@%s) + + - DOVECOT_AUTH_BIND=yes + - DOVECOT_USER_FILTER=(&(objectClass=inetOrgPerson)(|(uid=%u)(mail=%u))) + - DOVECOT_USER_ATTRS==uid=5000,=gid=5000,=home=/var/mail/%Ln,=mail=maildir:~/Maildir + + - ENABLE_SASLAUTHD=1 + - SASLAUTHD_MECHANISMS=rimap + - SASLAUTHD_MECH_OPTIONS=127.0.0.1 + - POSTMASTER_ADDRESS={{ postmaster_email }} + dns: + - {{ johan_ip }} + restart: always diff --git a/roles/nameservers/templates/db.simponic.xyz.j2 b/roles/nameservers/templates/db.simponic.xyz.j2 index 58db1a0..72ff58f 100644 --- a/roles/nameservers/templates/db.simponic.xyz.j2 +++ b/roles/nameservers/templates/db.simponic.xyz.j2 @@ -19,7 +19,6 @@ johan.simponic.xyz. 1 IN A 23.95.20.192 osaka.simponic.xyz. 1 IN A 129.123.76.14 mail.simponic.xyz. 1 IN A 192.3.248.205 -ash.simponic.xyz. 1 IN A 192.3.248.205 levi.simponic.xyz. 1 IN A 23.95.214.176 simponic.xyz. 1 IN A 23.95.214.176 @@ -36,5 +35,8 @@ authelia.simponic.xyz. 1 IN CNAME nijika.simponic.xyz. simponic.xyz. 1 IN MX 10 mail.simponic.xyz. ;; TXT Records -dkim._domainkey.simponic.xyz. 1 IN TXT "v=DKIM1; p= MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoNWLcbrcGq0z8f0fSmxLbfK/Q/ZwmnPyJEfljS2VuDIm7DUXahHIFtB8hfZ/WAocoirb8kUHTvTAgmUOXPpNxTDve3tV9S+CBBYHH2c9XBsuaZn/Vi0TR5vbBDuISmlXT6k+2cdq0LO+PYRwJI65t/JWTR5fQlCmVgxbI5gwDYFRZC0Nl5gEwuKw7pdEJg4Pymyox" "i" "zcikaGk/plXj6BDvv9pK1q8Wa+QPIkuBPFvsEh3KSApMP1p5thzHFaeNyCn5PuYEvbgkal0722px6GvYfR2W/APNRztbmWVewXH6kEWCgOYMkmWiYYLgEwz62rq2SzszP1rrl3WjVi26916wIDAQAB" +mail._domainkey.simponic.xyz. 1 IN TXT ( "v=DKIM1; h=sha256; k=rsa; " + "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2ktysbZaewsAo1Uk+FfLvVeL9ii6ejTDxxYE1RoGTxFDulFYXdpvO+MErDq62IvaQ6E4TYTc0RULoqp3BjuVVG6IG85SmhWME9XYSrxLm1pq7yRN1s1b6pBqNC6+yiyxwSjThS7RzH3sxwBL7R8AHRuEV+2UKsvT2wOCyRXAth+lrB7t9S9niWNOB3lvDqe0/oPf9JDrKjpuO6" + "lKZ3nglGzPfdJEpfLyXBP4l5UlxqWYUIrCzqHY9bNmyPepb1CJT97AD5jGGngCrnMCmllAdyOKa1ds5uoPjjGaLO8bOoBWXQuacn++hDsdyQ78Y673T2935CN/uGgrLBs9UiA0BQIDAQAB" ) ; ----- DKIM key mail for simponic.xyz +_dmarc.simponic.xyz. IN TXT "v=DMARC1; p=none; sp=none; fo=0; adkim=r; aspf=r; pct=100; rf=afrf; ri=86400; rua=mailto:dmarc.report@simponic.xyz; ruf=mailto:dmarc.report@simponic.xyz" simponic.xyz. 1 IN TXT "v=spf1 mx ip4:192.3.248.205 ~all" diff --git a/roles/private/tasks/main.yml b/roles/private/tasks/main.yml index 5c4eb7e..65f544b 100644 --- a/roles/private/tasks/main.yml +++ b/roles/private/tasks/main.yml @@ -84,12 +84,10 @@ - name: reload nginx to activate sites service: name=nginx state=restarted -- name: add monthly letsencrypt cronjob for cert renewal based on hash of domain name to prevent hitting LE rate limits +- name: add daily letsencrypt cronjob for cert renewal based on hash of domain name to prevent hitting LE rate limits cron: name: "letsencrypt_renewal_{{ item.stdout }}" - day: "{{ '%02d' | format(1 + (item.stdout | hash('md5') | int(0, 16) % 27)) }}" - hour: "{{ (item.stdout | hash('md5') | int(0, 16) % 24 ) }}" - minute: "{{ (item.stdout | hash('md5') | int(0, 16) % 60 ) }}" + special_time: "daily" job: "REQUESTS_CA_BUNDLE=/usr/local/share/ca-certificates/{{ step_bootstrap_ca_url }}.crt letsencrypt renew --server https://{{ step_bootstrap_ca_url }}:{{ step_ca_port }}/acme/ACME/directory --cert-name {{ item.stdout }} -n --webroot -w /var/www/letsencrypt --agree-tos --email {{ step_acme_cert_contact }} && service nginx reload" loop: "{{ extracted_domains.results }}" when: item.stdout != "" diff --git a/roles/vpn/templates/config.yml.j2 b/roles/vpn/templates/config.yml.j2 index d083c8f..750a05f 100644 --- a/roles/vpn/templates/config.yml.j2 +++ b/roles/vpn/templates/config.yml.j2 @@ -236,7 +236,7 @@ unix_socket_permission: "0770" # OpenID Connect oidc: # Block further startup until the OIDC provider is healthy and available - only_start_if_oidc_is_available: true + only_start_if_oidc_is_available: false # Specified by your OIDC provider issuer: "https://authelia.simponic.xyz" # Specified/generated by your OIDC provider