infra/ansible/roles/mailcow/tasks/main.yml

199 lines
No EOL
5 KiB
YAML

---
# Install and configure Mailcow
- name: Install required packages
apt:
name:
- git
- curl
- docker.io
- docker-compose
- python3-pip
- python3-docker
- jq
state: present
update_cache: true
- name: Ensure docker service is running
systemd:
name: docker
state: started
enabled: true
- name: Create mailcow user
user:
name: mailcow
groups: docker
shell: /bin/bash
home: /home/mailcow
create_home: true
state: present
- name: Ensure mailcow base directory exists
file:
path: "{{ mailcow_base_path }}"
state: directory
owner: mailcow
group: mailcow
mode: '0755'
- name: Check if Mailcow repository exists
stat:
path: "{{ mailcow_base_path }}/.git"
register: mailcow_repo
- name: Remove non-git Mailcow directory
file:
path: "{{ mailcow_base_path }}"
state: absent
when:
- mailcow_base_path is defined
- not mailcow_repo.stat.exists
- name: Clone Mailcow repository
git:
repo: "{{ mailcow_git_repo }}"
dest: "{{ mailcow_base_path }}"
version: "{{ mailcow_git_branch }}"
force: true
when: not mailcow_repo.stat.exists
- name: Add Mailcow directory to git safe directories
command: git config --global --add safe.directory {{ mailcow_base_path }}
when: mailcow_repo.stat.exists
- name: Update Mailcow repository
git:
repo: "{{ mailcow_git_repo }}"
dest: "{{ mailcow_base_path }}"
version: "{{ mailcow_git_branch }}"
update: true
when: mailcow_repo.stat.exists
register: git_update_result
failed_when:
- git_update_result.failed
- "'Local modifications exist' not in git_update_result.msg | default('')"
- name: Change ownership of Mailcow directory
file:
path: "{{ mailcow_base_path }}"
owner: mailcow
group: mailcow
recurse: true
# Let generate_config.sh create the default configuration
- name: Create docker-compose override file
template:
src: docker-compose.override.yml.j2
dest: "{{ mailcow_base_path }}/docker-compose.override.yml"
owner: mailcow
group: mailcow
mode: '0640'
backup: true
notify: restart mailcow
- name: Make generate_config.sh executable
file:
path: "{{ mailcow_base_path }}/generate_config.sh"
mode: '0755'
owner: mailcow
group: mailcow
- name: Check if mailcow is already configured
stat:
path: "{{ mailcow_base_path }}/mailcow.conf"
register: mailcow_configured
- name: Remove incomplete mailcow.conf
file:
path: "{{ mailcow_base_path }}/mailcow.conf"
state: absent
when:
- mailcow_configured.stat.exists
- mailcow_configured.stat.size < 1000 # If config is too small, it's incomplete
- name: Run generate_config.sh script
shell: |
cd {{ mailcow_base_path }}
./generate_config.sh << EOF
{{ mailcow_hostname }}
{{ timezone }}
EOF
args:
creates: "{{ mailcow_base_path }}/mailcow.conf"
- name: Update mailcow.conf with secure passwords
lineinfile:
path: "{{ mailcow_base_path }}/mailcow.conf"
regexp: "^{{ item.key }}="
line: "{{ item.key }}={{ item.value }}"
state: present
loop:
- { key: "DBPASS", value: "{{ vault_mailcow_dbpass }}" }
- { key: "DBROOT", value: "{{ vault_mailcow_dbroot }}" }
- { key: "REDISPASS", value: "{{ vault_mailcow_redispass }}" }
- { key: "API_KEY", value: "{{ vault_mailcow_api_key }}" }
no_log: true
- name: Stop any running Mailcow containers
command: docker compose down
args:
chdir: "{{ mailcow_base_path }}"
failed_when: false
- name: Prune unused Docker networks
command: docker network prune -f
changed_when: true
- name: Pull docker images
command: docker compose pull
args:
chdir: "{{ mailcow_base_path }}"
- name: Start Mailcow services
command: docker compose up -d
args:
chdir: "{{ mailcow_base_path }}"
- name: Check if ufw is installed
command: which ufw
register: ufw_check
changed_when: false
failed_when: false
- name: Configure firewall for mail services
ufw:
rule: allow
port: "{{ item.port }}"
proto: "{{ item.proto }}"
comment: "{{ item.comment }}"
loop:
- { port: "25", proto: "tcp", comment: "SMTP" }
- { port: "587", proto: "tcp", comment: "SMTP Submission" }
- { port: "465", proto: "tcp", comment: "SMTPS" }
# - { port: "143", proto: "tcp", comment: "IMAP" } # Disabled non-TLS
- { port: "993", proto: "tcp", comment: "IMAPS" }
# - { port: "110", proto: "tcp", comment: "POP3" } # Disabled non-TLS
- { port: "995", proto: "tcp", comment: "POP3S" }
- { port: "4190", proto: "tcp", comment: "Sieve" }
when:
- ansible_facts['os_family'] == "Debian"
- ufw_check.rc == 0
- name: Create systemd service for Mailcow
template:
src: mailcow.service.j2
dest: /etc/systemd/system/mailcow.service
owner: root
group: root
mode: '0644'
notify: restart mailcow
- name: Enable Mailcow service
systemd:
name: mailcow
enabled: true
daemon_reload: true
# Caddy not needed - Mailcow includes nginx for SSL termination