Adds docker-mailserver (SMTP_ONLY mode) to the tools stack so Outline can send magic-link emails without depending on an external SMTP provider. Changes: - docker-compose.yml.j2: add mailserver service + mail-internal network outline gets mail-internal network to reach mailserver - env.j2: point Outline SMTP at local mailserver:587 with noreply account - defaults/main.yml: add mailserver_image (v14) - tasks/main.yml: create mailserver dirs, wait for postfix ready, idempotent account creation, DKIM key generation + DNS instructions - inventory/group_vars/all/main.yml: add mailserver_noreply_password alias - vault.yml: add vault_mailserver_noreply_password After deploy, Ansible will print DKIM/SPF/DMARC DNS records to add to Cloudflare. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
105 lines
3.1 KiB
YAML
105 lines
3.1 KiB
YAML
---
|
|
- name: Create tools root directory
|
|
ansible.builtin.file:
|
|
path: "{{ tools_root }}"
|
|
state: directory
|
|
owner: "{{ deploy_user }}"
|
|
group: "{{ deploy_group }}"
|
|
mode: "0750"
|
|
|
|
- name: Create mailserver directories
|
|
ansible.builtin.file:
|
|
path: "{{ tools_root }}/mailserver/{{ item }}"
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: "0755"
|
|
loop:
|
|
- mail-data
|
|
- mail-state
|
|
- mail-logs
|
|
- config
|
|
|
|
- name: Deploy docker-compose.yml
|
|
ansible.builtin.template:
|
|
src: docker-compose.yml.j2
|
|
dest: "{{ tools_root }}/docker-compose.yml"
|
|
owner: "{{ deploy_user }}"
|
|
group: "{{ deploy_group }}"
|
|
mode: "0640"
|
|
|
|
- name: Deploy .env
|
|
ansible.builtin.template:
|
|
src: env.j2
|
|
dest: "{{ tools_root }}/.env"
|
|
owner: "{{ deploy_user }}"
|
|
group: "{{ deploy_group }}"
|
|
mode: "0600"
|
|
|
|
- name: Pull images
|
|
community.docker.docker_image:
|
|
name: "{{ item }}"
|
|
source: pull
|
|
loop:
|
|
- "{{ outline_image }}"
|
|
- "{{ outline_db_image }}"
|
|
- "{{ outline_redis_image }}"
|
|
- "{{ n8n_image }}"
|
|
- "{{ mailserver_image }}"
|
|
|
|
- name: Start tools stack
|
|
community.docker.docker_compose_v2:
|
|
project_src: "{{ tools_root }}"
|
|
state: present
|
|
pull: missing
|
|
|
|
- name: Wait for mailserver to be ready
|
|
ansible.builtin.command: docker exec mailserver postfix status
|
|
register: postfix_status
|
|
changed_when: false
|
|
retries: 12
|
|
delay: 10
|
|
until: postfix_status.rc == 0
|
|
|
|
- name: Check if noreply mail account exists
|
|
ansible.builtin.command: >
|
|
docker exec mailserver setup email list
|
|
register: mail_accounts
|
|
changed_when: false
|
|
|
|
- name: Create noreply mail account
|
|
ansible.builtin.command: >
|
|
docker exec mailserver setup email add noreply@{{ domain_base }} {{ mailserver_noreply_password }}
|
|
when: "'noreply@' + domain_base not in mail_accounts.stdout"
|
|
|
|
- name: Check if DKIM key exists
|
|
ansible.builtin.stat:
|
|
path: "{{ tools_root }}/mailserver/config/rspamd/dkim/{{ domain_base }}.private"
|
|
register: dkim_key
|
|
|
|
- name: Generate DKIM key
|
|
ansible.builtin.command: >
|
|
docker exec mailserver setup config dkim domain {{ domain_base }}
|
|
when: not dkim_key.stat.exists
|
|
register: dkim_generated
|
|
|
|
- name: Show DKIM DNS record
|
|
ansible.builtin.command: >
|
|
cat {{ tools_root }}/mailserver/config/rspamd/dkim/{{ domain_base }}.txt
|
|
when: dkim_generated is changed
|
|
register: dkim_record
|
|
|
|
- name: Print DKIM DNS instructions
|
|
ansible.builtin.debug:
|
|
msg: |
|
|
══════════════════════════════════════════════════════════════════
|
|
DKIM key generated! Add this TXT record to Cloudflare DNS:
|
|
{{ dkim_record.stdout }}
|
|
|
|
Also add SPF record:
|
|
Type: TXT Name: @ Value: v=spf1 ip4:{{ ip_tools }} ~all
|
|
|
|
And DMARC record:
|
|
Type: TXT Name: _dmarc Value: v=DMARC1; p=none; rua=mailto:admin@{{ domain_base }}
|
|
══════════════════════════════════════════════════════════════════
|
|
when: dkim_generated is changed
|