2022-07-10 10:51:01 +02:00
---
- name : mailcow
2022-09-20 14:22:12 +02:00
hosts : all
2022-07-10 10:51:01 +02:00
tasks :
- name : Clone mailcow git repo
become : yes
git :
repo : 'https://github.com/mailcow/mailcow-dockerized.git'
version : "master"
umask : '022'
update : false
dest : "/home/docker/mailcow-dockerized"
- name : disable Postfix Port
ansible.builtin.replace :
path : /etc/postfix/master.cf
regexp : '^smtp *inet'
replace : '#smtp inet'
backup : yes
notify :
- Restart postfix
- name : Generate mailcow.conf file
shell : ./generate_config.sh
environment :
MAILCOW_HOSTNAME : "mail.{{inventory_hostname}}"
MAILCOW_TZ : "Europe/Berlin"
args :
executable : /bin/bash
chdir : "/home/docker/mailcow-dockerized"
creates : /home/docker/mailcow-dockerized/mailcow.conf
notify : Restart mailcow
- name : disable mailcow letsencrypt (done by traefik)
ansible.builtin.replace :
path : /home/docker/mailcow-dockerized/mailcow.conf
regexp : '^SKIP_LETS_ENCRYPT=n'
replace : 'SKIP_LETS_ENCRYPT=y'
backup : yes
notify :
- Restart mailcow
- name : change http port 80->9080 (needed by traefik)
ansible.builtin.replace :
path : /home/docker/mailcow-dockerized/mailcow.conf
regexp : '^HTTP_PORT=80'
replace : 'HTTP_PORT=9080'
backup : yes
notify :
- Restart mailcow
- name : change http bind to localhost (needed by traefik)
ansible.builtin.replace :
path : /home/docker/mailcow-dockerized/mailcow.conf
regexp : '^HTTP_BIND=.*'
replace : 'HTTP_BIND=192.168.41.1'
backup : yes
notify :
- Restart mailcow
- name : change http port 443->9443 (needed by traefik)
ansible.builtin.replace :
path : /home/docker/mailcow-dockerized/mailcow.conf
regexp : '^HTTPS_PORT=443'
replace : 'HTTPS_PORT=9443'
backup : yes
notify :
- Restart mailcow
- name : change httpd bind to localhost (needed by traefik)
ansible.builtin.replace :
path : /home/docker/mailcow-dockerized/mailcow.conf
regexp : '^HTTPS_BIND=.*'
replace : 'HTTPS_BIND=192.168.41.1'
backup : yes
notify :
- Restart mailcow
- name : Start/initialize mailcow
2023-08-25 13:22:30 +02:00
ansible.builtin.shell : docker-compose up -d --force-recreate
2022-07-10 10:51:01 +02:00
args :
chdir : /home/docker/mailcow-dockerized
creates : /home/docker/var-lib-docker/volumes/mailcowdockerized_vmail-vol-1/_data/sieve/global_sieve_after.sieve
- wait_for :
path : /home/docker/var-lib-docker/volumes/mailcowdockerized_vmail-vol-1/_data/sieve/global_sieve_after.sieve
- name : /home/docker/mailcow-dockerized/adminpw.sh
blockinfile :
path : /home/docker/mailcow-dockerized/adminpw.sh
create : yes
mode : 0750
owner : root
group : docker
marker : "# {mark} ANSIBLE MANAGED BLOCK"
block : |
source /home/docker/mailcow-dockerized/mailcow.conf
if [[ -z ${DBUSER} ]] || [[ -z ${DBPASS} ]] || [[ -z ${DBNAME} ]]
then
echo "Cannot find mailcow.conf, make sure this script is run from within the mailcow folder."
exit 1
fi
# Change password
random=$(pwgen -s 32 1)
password=$(docker exec -it $(docker ps -qf name=dovecot-mailcow) doveadm pw -s SSHA256 -p ${random} | tr -d '\r')
docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM admin WHERE username='admin';"
docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM domain_admins WHERE username='admin';"
docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "INSERT INTO admin (username, password, superadmin, active) VALUES ('admin', '${password}', 1, 1);"
docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM tfa WHERE username='admin';"
echo "${random}" >/home/docker/mailcow-dockerized/.adminpw
chmod 400 /home/docker/mailcow-dockerized/.adminpw
backup : yes
validate : /bin/bash -n %s
- name : /home/docker/mailcow-dockerized/adminpw.sh shebang
lineinfile :
path : /home/docker/mailcow-dockerized/adminpw.sh
insertbefore : BOF
line : "#!/bin/bash"
- name : Generate mailcow admin password
ansible.builtin.shell : /home/docker/mailcow-dockerized/adminpw.sh
args :
chdir : /home/docker/mailcow-dockerized
creates : /home/docker/mailcow-dockerized/.adminpw
- name : /home/docker/traefik/providers/mailcow.yml Mailcow<->Traefik provider
blockinfile :
path : /home/docker/traefik/providers/mailcow.yml
create : yes
mode : 0444
owner : root
group : docker
marker : "# {mark} ANSIBLE MANAGED BLOCK"
block : |
http :
routers :
mailcow :
rule : "Host(`mail.{{inventory_hostname}}`)"
service : mailcow
entryPoints :
- "https"
tls :
2022-11-05 15:11:43 +01:00
certresolver : letsencrypt
2022-07-10 10:51:01 +02:00
middlewares : secHeaders@file
services :
mailcow :
loadBalancer :
servers :
- url : "http://192.168.41.1:9080"
- name : /usr/local/sbin/autoupdate.d/mailcow.update
blockinfile :
path : /usr/local/sbin/autoupdate.d/mailcow.update
mode : "0400"
owner : root
group : root
create : yes
marker : "# {mark} ANSIBLE MANAGED BLOCK"
block : |
# mailcow-dockerized
if [ -f /home/docker/mailcow-dockerized/update.sh ]
then
g_echo_ok "Prüfe MailCow Update"
cd /home/docker/mailcow-dockerized
if ./update.sh -c
then
g_echo_warn "Installiere MailCow Update $(./update.sh -c)"
2023-08-02 09:51:39 +02:00
if ! ./update.sh --no-update-compose -f 2>&1 | sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/" | tee $g_tmp/mailcow-update
then
if grep -q "update.sh changed, please run this script again" $g_tmp/mailcow-update
then
if ! ./update.sh --no-update-compose -f 2>&1 | sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/" | tee -a $g_tmp/mailcow-update
then
g_echo_error "MailCow Update fehlgeschlagen $(cat $g_tmp/mailcow-update)"
fi
else
g_echo_error "MailCow Update fehlgeschlagen $(cat $g_tmp/mailcow-update)"
fi
fi
2023-08-25 13:22:30 +02:00
docker compose up -d --force-recreate
2022-07-10 10:51:01 +02:00
fi
fi
# take letsencrypt-certs from traefik
. /home/docker/mailcow-dockerized/mailcow.conf
cat /home/docker/traefik/letsencrypt/acme.json | jq -r ".letsencrypt.Certificates[] | select(.domain.main==\"$MAILCOW_HOSTNAME\") | .key" | base64 -d >/home/docker/mailcow-dockerized/data/assets/ssl/key.pem
cat /home/docker/traefik/letsencrypt/acme.json | jq -r ".letsencrypt.Certificates[] | select(.domain.main==\"$MAILCOW_HOSTNAME\") | .certificate" | base64 -d >/home/docker/mailcow-dockerized/data/assets/ssl/cert.pem
docker restart $(docker ps -qaf name=postfix-mailcow)
docker restart $(docker ps -qaf name=dovecot-mailcow)
backup : yes
validate : /bin/bash -n %s
- name : /usr/local/sbin/backup.d/mailcow.backup
blockinfile :
path : /usr/local/sbin/backup.d/mailcow.backup
mode : "0400"
owner : root
group : root
create : yes
marker : "# {mark} ANSIBLE MANAGED BLOCK"
block : |
cd /home/docker/mailcow-dockerized
mkdir -p ${BACKUPDIR}/mailcow-backup_script
BACKUP_LOCATION=${BACKUPDIR}/mailcow-backup_script /home/docker/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup all --delete-days 3 || g_echo_error "MailCow-Backup (mysql crypt redis) war nicht erfolgreich"
backup : yes
validate : /bin/bash -n %s
- name : /home/docker/autoconfig.{{inventory_hostname}}/docker-compose.yml Container Configuration
blockinfile :
path : /home/docker/autoconfig.{{inventory_hostname}}/docker-compose.yml
create : yes
mode : 0440
owner : root
group : docker
marker : "# {mark} ANSIBLE MANAGED BLOCK"
block : |
version : '3.6'
services :
autoconfig.{{inventory_hostname}}:
image : nginx:latest
restart : unless-stopped
volumes :
- ./htdocs:/usr/share/nginx/html:ro
- /etc/localtime:/etc/localtime:ro
networks :
- traefik
labels :
- traefik.enable=true
# HTTPS
- traefik.http.routers.autoconfig-{{ ansible_facts['hostname'] }}.rule=Host(`autoconfig.{{ ansible_facts['nodename'] }}`) || Host(`autodiscover.{{ ansible_facts['nodename'] }}`)
- traefik.http.routers.autoconfig-{{ ansible_facts['hostname'] }}.entrypoints=https
- traefik.http.routers.autoconfig-{{ ansible_facts['hostname'] }}.tls=true
# Proxy to service-port
- traefik.http.services.autoconfig-{{ ansible_facts['hostname'] }}.loadbalancer.server.port=80
- traefik.http.routers.autoconfig-{{ ansible_facts['hostname'] }}.service=autoconfig-{{ ansible_facts['hostname'] }}
# cert via letsencrypt
- traefik.http.routers.autoconfig-{{ ansible_facts['hostname'] }}.tls.certresolver=letsencrypt
# Traefik network
- traefik.docker.network=traefik
# activate secHeaders@file
- traefik.http.routers.autoconfig-{{ ansible_facts['hostname'] }}.middlewares=secHeaders@file
networks :
traefik :
external : true
backup : yes
notify : Restart autoconfig
- name : /home/docker/autoconfig.{{inventory_hostname}}/htdocs/index.html
blockinfile :
path : /home/docker/autoconfig.{{inventory_hostname}}/htdocs/index.html
create : yes
mode : 0444
owner : root
group : root
marker : "<!-- {mark} ANSIBLE MANAGED BLOCK -->"
block : |
OK
backup : yes
- name : /home/docker/autoconfig.{{inventory_hostname}}/htdocs/mail/config-v1.1.xml
blockinfile :
path : /home/docker/autoconfig.{{inventory_hostname}}/htdocs/mail/config-v1.1.xml
create : yes
mode : 0444
owner : root
group : root
marker : "<!-- {mark} ANSIBLE MANAGED BLOCK -->"
block : |
<clientConfig version="1.1">
<emailProvider id="mail.{{inventory_hostname}}">
<domain>{{inventory_hostname}}</domain>
<displayName>{{inventory_hostname}}</displayName>
<displayShortName>{{ ansible_facts['hostname'] }}</displayShortName>
<incomingServer type="imap">
<hostname>mail.{{inventory_hostname}}</hostname>
<port>993</port>
<socketType>SSL</socketType>
<username>%EMAILADDRESS%</username>
<authentication>password-cleartext</authentication>
</incomingServer>
<outgoingServer type="smtp">
<hostname>mail.{{inventory_hostname}}</hostname>
<port>465</port>
<socketType>SSL</socketType>
<username>%EMAILADDRESS%</username>
<authentication>password-cleartext</authentication>
</outgoingServer>
</emailProvider>
</clientConfig>
backup : yes
- name : Allow all access to tcp port 25 (smtp)
community.general.ufw :
rule : allow
port : '25'
proto : tcp
- name : Allow all access to tcp port 465 (submission/tls)
community.general.ufw :
rule : allow
port : '465'
proto : tcp
- name : Allow all access to tcp port 587 (submission)
community.general.ufw :
rule : allow
port : '587'
proto : tcp
- name : Allow all access to tcp port 993 (imaps)
community.general.ufw :
rule : allow
port : '993'
proto : tcp
handlers :
- name : Restart mailcow
2023-08-25 13:22:30 +02:00
ansible.builtin.shell : docker-compose up -d --force-recreate
2022-07-10 10:51:01 +02:00
args :
chdir : /home/docker/mailcow-dockerized
- name : Restart autoconfig
2023-08-25 13:22:30 +02:00
ansible.builtin.shell : docker-compose up -d --force-recreate
2022-07-10 10:51:01 +02:00
args :
chdir : /home/docker/autoconfig.{{inventory_hostname}}
- name : Restart postfix
service :
name : postfix
state : restarted