--- # 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: yes - name: Ensure docker service is running systemd: name: docker state: started enabled: yes - name: Create mailcow user user: name: mailcow groups: docker shell: /bin/bash home: /home/mailcow create_home: yes 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: yes 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: yes when: mailcow_repo.stat.exists ignore_errors: yes - name: Change ownership of Mailcow directory file: path: "{{ mailcow_base_path }}" owner: mailcow group: mailcow recurse: yes # 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: yes 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 }}" ignore_errors: yes - 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: yes daemon_reload: yes # Caddy not needed - Mailcow includes nginx for SSL termination