first commit
This commit is contained in:
commit
9f5e2946f5
325
mailcow.yml
Normal file
325
mailcow.yml
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: mailcow
|
||||||
|
hosts: ds9.dedyn.io jarvis.olmusic.de
|
||||||
|
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
|
||||||
|
ansible.builtin.shell: docker-compose up -d
|
||||||
|
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:
|
||||||
|
certresolver:
|
||||||
|
- "letsencrypt"
|
||||||
|
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)"
|
||||||
|
./update.sh --no-update-compose -f 2>&1 | sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/" | tee $g_tmp/mailcow-update || g_echo_error "MailCow Update fehlgeschlagen $(cat $g_tmp/mailcow-update)"
|
||||||
|
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
|
||||||
|
ansible.builtin.shell: docker-compose up -d
|
||||||
|
args:
|
||||||
|
chdir: /home/docker/mailcow-dockerized
|
||||||
|
|
||||||
|
- name: Restart autoconfig
|
||||||
|
ansible.builtin.shell: docker-compose up -d
|
||||||
|
args:
|
||||||
|
chdir: /home/docker/autoconfig.{{inventory_hostname}}
|
||||||
|
|
||||||
|
|
||||||
|
- name: Restart postfix
|
||||||
|
service:
|
||||||
|
name: postfix
|
||||||
|
state: restarted
|
||||||
|
|
Loading…
Reference in New Issue
Block a user