209 lines
6.9 KiB
YAML
209 lines
6.9 KiB
YAML
---
|
|
- name: Mailbox password is set
|
|
ansible.builtin.assert:
|
|
that: mail_relay.password | length > 0
|
|
fail_msg: "mail_relay.password of {{ inventory_hostname }} is empty (host_vars)"
|
|
quiet: true
|
|
|
|
- name: Postfix state
|
|
ansible.builtin.stat:
|
|
path: /usr/sbin/postfix
|
|
register: mail_relay_postfix
|
|
|
|
- name: Exim state
|
|
ansible.builtin.stat:
|
|
path: /usr/sbin/exim4
|
|
register: mail_relay_exim
|
|
|
|
# Postfix replaces exim4 as the mail-transport-agent; the package scripts do not stop a running exim4
|
|
# while policy-rc.d denies service actions, and its listener would block postfix on port 25.
|
|
- name: Stop exim4
|
|
ansible.builtin.systemd_service:
|
|
name: exim4
|
|
state: stopped
|
|
enabled: false
|
|
when: mail_relay_exim.stat.exists and not mail_relay_postfix.stat.exists
|
|
|
|
- name: Preseed postfix
|
|
ansible.builtin.debconf:
|
|
name: postfix
|
|
question: "{{ item.question }}"
|
|
vtype: "{{ item.vtype }}"
|
|
value: "{{ item.value }}"
|
|
loop:
|
|
- { question: postfix/main_mailer_type, vtype: select, value: Internet Site }
|
|
- { question: postfix/mailname, vtype: string, value: "{{ mail_relay.myhostname }}" }
|
|
loop_control:
|
|
label: "{{ item.question }}"
|
|
when: not mail_relay_postfix.stat.exists
|
|
|
|
# A third-party repository with a bad signature makes the refresh fail on some hosts; the install
|
|
# below still fails if the index lacks the packages.
|
|
- name: Refresh apt cache
|
|
ansible.builtin.apt:
|
|
update_cache: true
|
|
cache_valid_time: 3600
|
|
failed_when: false
|
|
|
|
# The package starts postfix with the Debian defaults, which listen on all interfaces; on a host whose
|
|
# port 25 is taken (tranio: mailcow) that start fails. policy-rc.d keeps the start until the
|
|
# configuration is in place.
|
|
- name: Install postfix
|
|
ansible.builtin.apt:
|
|
name:
|
|
- postfix
|
|
- libsasl2-modules
|
|
- ca-certificates
|
|
policy_rc_d: "{{ omit if mail_relay_postfix.stat.exists else 101 }}"
|
|
|
|
- name: Postfix configuration
|
|
when: not ansible_check_mode or mail_relay_postfix.stat.exists
|
|
block:
|
|
- name: Local names of the host
|
|
ansible.builtin.set_fact:
|
|
mail_relay_local_names: >-
|
|
{{ [mail_relay.myhostname, inventory_hostname, inventory_hostname_short, ansible_facts['hostname'],
|
|
'localhost', 'localhost.localdomain'] | unique }}
|
|
|
|
- name: Sender rewrite map
|
|
ansible.builtin.template:
|
|
src: generic.regexp.j2
|
|
dest: /etc/postfix/generic
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
notify: Restart postfix
|
|
|
|
- name: Relay settings in main.cf
|
|
ansible.builtin.lineinfile:
|
|
path: /etc/postfix/main.cf
|
|
regexp: "^{{ item.key }}\\s*="
|
|
line: "{{ item.key }} = {{ item.value }}"
|
|
loop: "{{ mail_relay_settings | dict2items }}"
|
|
vars:
|
|
mail_relay_settings:
|
|
myhostname: "{{ mail_relay.myhostname }}"
|
|
myorigin: $myhostname
|
|
inet_interfaces: "{{ mail_relay.inet_interfaces }}"
|
|
relayhost: "[{{ mail_relay.host }}]:{{ mail_relay.port }}"
|
|
smtp_sasl_auth_enable: "yes"
|
|
smtp_sasl_password_maps: hash:/etc/postfix/sasl_passwd
|
|
smtp_sasl_security_options: noanonymous
|
|
smtp_tls_security_level: verify
|
|
smtp_tls_CAfile: /etc/ssl/certs/ca-certificates.crt
|
|
smtp_generic_maps: regexp:/etc/postfix/generic
|
|
loop_control:
|
|
label: "{{ item.key }}"
|
|
notify: Restart postfix
|
|
|
|
- name: SASL credentials
|
|
ansible.builtin.copy:
|
|
dest: /etc/postfix/sasl_passwd
|
|
content: "[{{ mail_relay.host }}]:{{ mail_relay.port }} {{ mail_relay.username }}:{{ mail_relay.password }}\n"
|
|
owner: root
|
|
group: root
|
|
mode: "0600"
|
|
no_log: true
|
|
register: mail_relay_sasl
|
|
|
|
- name: SASL database state
|
|
ansible.builtin.stat:
|
|
path: /etc/postfix/sasl_passwd.db
|
|
register: mail_relay_sasl_db
|
|
|
|
# A task instead of a handler: a failed run would drop the notification and leave the database missing.
|
|
- name: Rebuild sasl_passwd database
|
|
ansible.builtin.command:
|
|
cmd: postmap /etc/postfix/sasl_passwd
|
|
when: mail_relay_sasl.changed or not mail_relay_sasl_db.stat.exists
|
|
changed_when: true
|
|
notify: Restart postfix
|
|
|
|
# inet_interfaces cannot switch the listener off ("none" is resolved as a host name): the service
|
|
# is commented out in master.cf instead.
|
|
- name: SMTP listener in master.cf
|
|
ansible.builtin.lineinfile:
|
|
path: /etc/postfix/master.cf
|
|
regexp: "^#?smtp\\s+inet\\s+n\\s+-\\s+y\\s+-\\s+-\\s+smtpd\\s*$"
|
|
line: "{{ '' if mail_relay.smtpd_listener else '#' }}smtp inet n - y - - smtpd"
|
|
notify: Restart postfix
|
|
|
|
- name: Root alias
|
|
ansible.builtin.lineinfile:
|
|
path: /etc/aliases
|
|
regexp: "^root:"
|
|
line: "root: {{ mail_relay.root_mail }}"
|
|
create: true
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
|
|
- name: Alias file state
|
|
ansible.builtin.stat:
|
|
path: /etc/aliases
|
|
register: mail_relay_aliases
|
|
|
|
- name: Alias database state
|
|
ansible.builtin.stat:
|
|
path: /etc/aliases.db
|
|
register: mail_relay_aliases_db
|
|
|
|
# Postfix reads /etc/aliases through the compiled /etc/aliases.db; without a current db local
|
|
# delivery defers or misroutes. A task instead of a handler, so a failed run cannot lose the rebuild.
|
|
- name: Rebuild alias database
|
|
ansible.builtin.command:
|
|
cmd: newaliases
|
|
when: >-
|
|
not mail_relay_aliases_db.stat.exists
|
|
or mail_relay_aliases_db.stat.mtime < mail_relay_aliases.stat.mtime
|
|
changed_when: true
|
|
|
|
- name: Apply pending changes
|
|
ansible.builtin.meta: flush_handlers
|
|
|
|
- name: SASL database permissions
|
|
ansible.builtin.file:
|
|
path: /etc/postfix/sasl_passwd.db
|
|
owner: root
|
|
group: root
|
|
mode: "0600"
|
|
|
|
- name: Postfix running
|
|
ansible.builtin.service:
|
|
name: postfix
|
|
state: started
|
|
enabled: true
|
|
|
|
- name: Proxmox state
|
|
ansible.builtin.stat:
|
|
path: /usr/sbin/pveum
|
|
register: mail_relay_pve
|
|
|
|
# The built-in mail-to-root notification target mails the email of root@pam.
|
|
- name: Email of root@pam
|
|
when: mail_relay_pve.stat.exists
|
|
block:
|
|
- name: Read root@pam
|
|
ansible.builtin.command:
|
|
cmd: pvesh get /access/users/root@pam --output-format json
|
|
register: mail_relay_pve_root
|
|
changed_when: false
|
|
check_mode: false
|
|
|
|
- name: Set the email of root@pam
|
|
ansible.builtin.command:
|
|
cmd: "pveum user modify root@pam --email {{ mail_relay.root_mail }}"
|
|
when: (mail_relay_pve_root.stdout | from_json).email | default('') != mail_relay.root_mail
|
|
|
|
# Run with --tags mail_relay_test: the mail takes the root alias through the relay.
|
|
- name: Test mail to root
|
|
ansible.builtin.command:
|
|
cmd: sendmail -t
|
|
stdin: |
|
|
To: root
|
|
Subject: mail_relay test from {{ inventory_hostname }}
|
|
|
|
Test mail of the mail_relay role.
|
|
changed_when: true
|
|
tags: [never, mail_relay_test]
|