- Seed postfix-accounts.cf before mailserver start to satisfy Dovecot's requirement for at least one account on first boot - Add failed_when: false to mail user/alias list tasks (files don't exist on first run) - Add forgejo_runner_version (was undefined); default to 12 - Create /srv/forgejo/data/gitea/conf before deploying app.ini - Decouple goaccess sync from restic: new enable_goaccess_sync flag with its own goaccess_sync_* variables - Move Docker installation to bootstrap exclusively; rename docker.yml to networks.yml (runs docker_network role only) - Add radicale_password to vault template and setup.sh - Fix goaccess sync tasks gated on enable_goaccess_sync - Add upstream bug comment to authorized_key deprecation warning - Update CLAUDE.md and README.md throughout Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
167 lines
4.2 KiB
YAML
167 lines
4.2 KiB
YAML
- name: Allow SMTP traffic
|
|
ufw:
|
|
rule: allow
|
|
port: 25
|
|
proto: tcp
|
|
|
|
- name: Allow mail submission traffic
|
|
ufw:
|
|
rule: allow
|
|
port: 587
|
|
proto: tcp
|
|
|
|
- name: Allow IMAP over TLS traffic
|
|
ufw:
|
|
rule: allow
|
|
port: 993
|
|
proto: tcp
|
|
|
|
- name: Create docker-mailserver directory
|
|
file:
|
|
path: "/srv/mail"
|
|
state: directory
|
|
owner: root
|
|
group: docker # to allow access to the compose file
|
|
mode: '0755'
|
|
|
|
- name: Create docker-mailserver directories
|
|
file:
|
|
path: "/srv/mail/{{ item }}"
|
|
state: directory
|
|
owner: root
|
|
group: docker
|
|
mode: '0750'
|
|
loop:
|
|
- env
|
|
- config/rspamd/override.d
|
|
|
|
- name: Create maillogs directory
|
|
file:
|
|
path: /srv/mail/maillogs
|
|
state: directory
|
|
mode: '0755' # container startup script needs to traverse and chown subdirs
|
|
|
|
# stat+chown: avoids UID/GID lookup warnings for container-internal UIDs not present on host
|
|
- name: Stat maillogs directory
|
|
stat:
|
|
path: /srv/mail/maillogs
|
|
register: maillogs_stat
|
|
|
|
- name: Set maillogs directory ownership
|
|
command: chown 113:0 /srv/mail/maillogs
|
|
when: maillogs_stat.stat.uid != 113 or maillogs_stat.stat.gid != 0
|
|
|
|
- name: Create mailstate directory
|
|
file:
|
|
path: /srv/mail/mailstate
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: '0755' # container startup script needs to traverse and chown subdirs
|
|
|
|
- name: Create maildata directory
|
|
file:
|
|
path: /srv/mail/maildata
|
|
state: directory
|
|
mode: '0751' # container startup script needs to traverse and chown subdirs
|
|
|
|
- name: Create config directory
|
|
file:
|
|
path: /srv/mail/config
|
|
state: directory
|
|
mode: '0751' # container startup script needs to traverse and chown subdirs
|
|
|
|
- name: Create rainloop data directory
|
|
file:
|
|
path: /srv/mail/rainloop/data
|
|
state: directory
|
|
mode: '0755'
|
|
|
|
# stat+chown: avoids UID/GID lookup warnings for container-internal UIDs not present on host
|
|
- name: Stat rainloop data directory
|
|
stat:
|
|
path: /srv/mail/rainloop/data
|
|
register: rainloop_data_stat
|
|
|
|
- name: Set rainloop data directory ownership
|
|
command: chown 991:991 /srv/mail/rainloop/data
|
|
when: rainloop_data_stat.stat.uid != 991 or rainloop_data_stat.stat.gid != 991
|
|
|
|
- name: Ensure certbot is installed
|
|
apt:
|
|
name: certbot
|
|
state: present
|
|
|
|
- name: Check if mail TLS certificate already exists
|
|
ansible.builtin.stat:
|
|
path: /etc/letsencrypt/live/{{ mail_hostname }}/fullchain.pem
|
|
register: mail_cert
|
|
|
|
- name: Stop Caddy to free port 80 for certbot
|
|
community.docker.docker_compose_v2:
|
|
project_src: /srv/caddy
|
|
state: stopped
|
|
when: not mail_cert.stat.exists
|
|
|
|
- name: Obtain a Let's Encrypt certificate for {{ mail_hostname }}
|
|
command: >
|
|
certbot certonly --standalone
|
|
-d {{ mail_hostname }}
|
|
--non-interactive --agree-tos -m postmaster@{{ domain }}
|
|
when: not mail_cert.stat.exists
|
|
tags: config
|
|
|
|
- name: Restart Caddy after certbot
|
|
community.docker.docker_compose_v2:
|
|
project_src: /srv/caddy
|
|
state: present
|
|
build: never
|
|
when: not mail_cert.stat.exists
|
|
|
|
- name: Deploy mail compose file
|
|
template:
|
|
src: compose.yml.j2
|
|
dest: /srv/mail/compose.yml
|
|
notify: Restart mail stack
|
|
tags: config
|
|
|
|
- name: Deploy mailserver environment file
|
|
template:
|
|
src: mailserver.env.j2
|
|
dest: /srv/mail/env/mailserver.env
|
|
mode: '0640'
|
|
owner: root
|
|
group: docker
|
|
notify: Restart mailserver
|
|
tags: config
|
|
|
|
- name: Deploy rspamd web UI config
|
|
template:
|
|
src: worker-controller.inc.j2
|
|
dest: /srv/mail/config/rspamd/override.d/worker-controller.inc
|
|
mode: '0644'
|
|
notify: Restart mailserver
|
|
tags: config
|
|
|
|
- name: Seed mail accounts into postfix-accounts.cf before first start
|
|
ansible.builtin.shell: |
|
|
grep -qF "{{ item.address }}" /srv/mail/config/postfix-accounts.cf 2>/dev/null && exit 0
|
|
hash=$(openssl passwd -6 {{ item.password | quote }})
|
|
printf '%s|{SHA512-CRYPT}%s\n' "{{ item.address }}" "${hash}" >> /srv/mail/config/postfix-accounts.cf
|
|
loop: "{{ mail_users }}"
|
|
no_log: true
|
|
args:
|
|
executable: /bin/bash
|
|
tags: users
|
|
|
|
- name: Start mailserver
|
|
community.docker.docker_compose_v2:
|
|
project_src: /srv/mail
|
|
state: present
|
|
build: never
|
|
tags: config
|
|
|
|
- import_tasks: users.yml
|
|
- import_tasks: aliases.yml
|
|
# webmail interface
|
|
- import_tasks: rainloop.yml
|