diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml new file mode 100644 index 000000000..60ee15abf --- /dev/null +++ b/.github/workflows/gh-pages.yml @@ -0,0 +1,27 @@ +name: Build and deploy to gh-pages +on: + push: + branches: + - master +jobs: + build-and-deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout πŸ“₯ + uses: actions/checkout@v2.3.4 + + - name: Install dependencies πŸ„ + run: | + sudo apt-get -y update + sudo apt-get -y install python3-pip + pip install mkdocs-material==7.2.5 pygments==2.10.0 mkdocs-redirects==1.0.3 + + - name: Build site πŸ”§ + run: | + mkdocs build --verbose --clean + + - name: Deploy πŸš€ + uses: JamesIves/github-pages-deploy-action@4.1.5 + with: + branch: gh-pages # The branch the action should deploy to. + folder: site # The folder the action should deploy. diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 4f65a58ec..000000000 --- a/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: python -install: -- pip install mkdocs-material pygments -script: -- mkdocs build --verbose --clean -deploy: - provider: pages - skip_cleanup: true - github_token: $GITHUB_TOKEN - local_dir: site - name: $BOT_NAME - email: $BOT_EMAIL - on: - branch: master diff --git a/README.md b/README.md index 48fe30ca6..434fa7178 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![TRAVIS-CI](https://api.travis-ci.org/mailcow/mailcow-dockerized-docs.svg?branch=master) +[![Build and deploy to gh-pages](https://github.com/mailcow/mailcow-dockerized-docs/actions/workflows/gh-pages.yml/badge.svg)](https://github.com/mailcow/mailcow-dockerized-docs/actions/workflows/gh-pages.yml) # mailcow: dockerized documentation @@ -9,6 +9,6 @@ https://mailcow.github.io/mailcow-dockerized-docs To build it locally, you need the [Material theme for MkDocs](https://squidfunk.github.io/mkdocs-material/), [MkDocs](https://www.mkdocs.org/) itself and [Pygments](http://pygments.org/). To install these with [pip](https://pip.pypa.io/en/stable/) and get it up and running, fire up your terminal and enter ``` -pip install mkdocs-material +pip install mkdocs-material==7.2.5 pygments==2.10.0 mkdocs-redirects==1.0.3 mkdocs serve -``` \ No newline at end of file +``` diff --git a/docs/b_n_r_accidental_deletion.md b/docs/b_n_r_accidental_deletion.md new file mode 100644 index 000000000..43b731f21 --- /dev/null +++ b/docs/b_n_r_accidental_deletion.md @@ -0,0 +1,40 @@ +So you deleted a mailbox and have no backups, he? + +If you noticed your mistake within a few hours, you can probably recover the users data. + +### SOGo + +We automatically create daily backups (24h interval starting from running up -d) in `/var/lib/docker/volumes/mailcowdockerized_sogo-userdata-backup-vol-1/_data/`. + +**Make sure the user you want to restore exists in your mailcow**. Re-create them if they are missing. + +Copy the file named after the user you want to restore to `__MAILCOW_DIRECTORY__/data/conf/sogo`. + +1\. Copy the backup: `cp /var/lib/docker/volumes/mailcowdockerized_sogo-userdata-backup-vol-1/_data/restoreme@example.org __MAILCOW_DIRECTORY__/data/conf/sogo` + +2\. Run `docker-compose exec -u sogo sogo-mailcow sogo-tool restore -F ALL /etc/sogo restoreme@example.org` + +Run `sogo-tool` without parameters to check for possible restore options. + +3\. Delete the copied backup by running `rm __MAILCOW_DIRECTORY__/data/conf/sogo` + +4\. Restart SOGo and Memcached: `docker-compose restart sogo-mailcow memcached-mailcow` + +### Mail + +In case of an accidental deletion of a mailbox, you will be able to recover for (by default) 5 days. This depends on the `MAILDIR_GC_TIME` parameter in `mailcow.conf`. + +A deleted mailbox is copied in its encrypted form to `/var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/_garbage`. + +The folder inside _garbage follows the structure `[timestamp]_[domain_sanitized][user_sanitized]`, for example `1629109708_exampleorgtest in case of test@example.org deleted on 1629109708. + +To restore make sure you are actually restoring to the same mailcow it was deleted from or you use the same encryption keys in `crypt-vol-1`. + +**Make sure the user you want to restore exists in your mailcow**. Re-create them if they are missing. + +Copy the folders from `/var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/_garbage/[timestamp]_[domain_sanitized][user_sanitized]` back to `/var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/[domain]/[user]` and resync the folder and recalc the quota: + +``` +docker-compose exec dovecot-mailcow doveadm force-resync -u restoreme@example.net '*' +docker-compose exec dovecot-mailcow doveadm quota recalc -u restoreme@example.net +``` diff --git a/docs/b_n_r_backup.md b/docs/b_n_r_backup.md index afc932563..60e6c301e 100644 --- a/docs/b_n_r_backup.md +++ b/docs/b_n_r_backup.md @@ -1,5 +1,7 @@ ### Backup +#### Manual + You can use the provided script `helper-scripts/backup_and_restore.sh` to backup mailcow automatically. Please do not copy this script to another location. @@ -30,3 +32,66 @@ To run a backup unattended, define MAILCOW_BACKUP_LOCATION as environment variab ``` MAILCOW_BACKUP_LOCATION=/opt/backup /opt/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup all ``` + +#### Cronjob + +You can run the backup script regularly via cronjob. Make sure `BACKUP_LOCATION` exists: + +``` +5 4 * * * cd /opt/mailcow-dockerized/; MAILCOW_BACKUP_LOCATION=/mnt/mailcow_backups /opt/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup mysql crypt redis --delete-days 3 +``` + +Per default cron sends the full result of each backup operation by email. If you want cron to only mail on error (non-zero exit code) you may want to use the following snippet. Pathes need to be modified according to your setup (this script is a user contribution). + +This following script may be placed in `/etc/cron.daily/mailcow-backup` - do not forget to mark it as executable via `chmod +x`: + +``` +#!/bin/sh + +# Backup mailcow data +# https://mailcow.github.io/mailcow-dockerized-docs/b_n_r_backup/ + +set -e + +OUT="$(mktemp)" +export MAILCOW_BACKUP_LOCATION="/opt/backup" +SCRIPT="/opt/mailcow-dockerized/helper-scripts/backup_and_restore.sh" +PARAMETERS="backup all" +OPTIONS="--delete-days 30" + +# run command +set +e +"${SCRIPT}" ${PARAMETERS} ${OPTIONS} 2>&1 > "$OUT" +RESULT=$? + +if [ $RESULT -ne 0 ] + then + echo "${SCRIPT} ${PARAMETERS} ${OPTIONS} encounters an error:" + echo "RESULT=$RESULT" + echo "STDOUT / STDERR:" + cat "$OUT" +fi +``` + +# Backup strategy with rsync and mailcow backup script + +Create the destination directory for mailcows helper script: +``` +mkdir -p /external_share/backups/backup_script +``` + +Create cronjobs: +``` +25 1 * * * rsync -aH --delete /opt/mailcow-dockerized /external_share/backups/mailcow-dockerized +40 2 * * * rsync -aH --delete /var/lib/docker/volumes /external_share/backups/var_lib_docker_volumes +5 4 * * * cd /opt/mailcow-dockerized/; BACKUP_LOCATION=/external_share/backups/backup_script /opt/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup mysql crypt redis --delete-days 3 +# If you want to, use the acl util to backup permissions of some/all folders/files: getfacl -Rn /path +``` + +On the destination (in this case `/external_share/backups`) you may want to have snapshot capabilities (ZFS, Btrfs etc.). Snapshot daily and keep for n days for a consistent backup. +Do **not** rsync to a Samba share, you need to keep the correct permissions! + +To restore you'd simply need to run rsync the other way round and restart Docker to re-read the volumes. Run `docker-compose pull` and `docker-compose up -d`. + +If you are lucky Redis and MariaDB can automatically fix the inconsistent databases (if they _are_ inconsistent). +In case of a corrupted database you'd need to use the helper script to restore the inconsistent elements. If a restore fails, try to extract the backups and copy the files back manually. Keep the file permissions! diff --git a/docs/client/client-thunderbird.md b/docs/client/client-thunderbird.md index 900a0577e..c863d4e5f 100644 --- a/docs/client/client-thunderbird.md +++ b/docs/client/client-thunderbird.md @@ -54,3 +54,28 @@ Automatic configuration of calendars and address books in Thunderbird is not cur
Automatic configuration of calendars and address books (from step 9 onward) in Thunderbird is only supported if your server administrator has enabled [SOGo Connector](https://mailcow.github.io/mailcow-dockerized-docs/third_party-thunderbird).
+ +## Different method of connecting Cal-/CardDAV in Thunderbird with automatic detection of address books and calendars + +Instead of using SOGo Connector you can use a combination of + +- https://addons.thunderbird.net/de/thunderbird/addon/tbsync/ and +- https://addons.thunderbird.net/de/thunderbird/addon/dav-4-tbsync/ + +1. To add your Cal-/CardDAV accounts go to `Tools` and find TbSync + +![TbSync](../images/thunderbird-tbsync.png) + +2. You can add new accounts via the CalDAV & CardDAV provider: + +![TbSync - CalDAV & CardDAV Provider](../images/thunderbird-tbsync-caldav.png) + +3. Choose "Automatic Configuration". Use your mail address as account and username. Use your mail password as DAV password. The server URL is your MAILCOW_HOSTNAME (specifying any protocol is not necessary, just enter the full domain). + +4. Now tick the checkbox for "Enable and synchronize this account" in the synchronization status tab: + +![TbSync - Enable](../images/thunderbird-tbsync-enable.png) + +5. Several available resources should appear in the same window area now. Tick all checkboxes of the resources (address books and calendars) that you want to sync. Choose a synchronization period (in minutes) in the same window area before clicking on "Synchronize now". If you leave the sync at "0" it will only sync manually so choose at least 30 minutes for periodic synchronization. + +If you want to manually synchronize you can find this option under "Account actions" - the dropdown-menu where you added the Cal-/CardDAV account (step 2). diff --git a/docs/clients.js b/docs/clients.js index cc6cf1257..78b4365f5 100644 --- a/docs/clients.js +++ b/docs/clients.js @@ -1,7 +1,7 @@ if (window.location.href.indexOf('/client/') >= 0) { window.window.addEventListener('load', function () { function setCookie(name, value) { - document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + "; path=/"; + sessionStorage.setItem(name, value); } function getParameterByName(name) { @@ -39,18 +39,7 @@ if (window.location.href.indexOf('/client/') >= 0) { if (window.location.href.indexOf('/client') >= 0) { window.window.addEventListener('load', function () { function getCookie(cn) { - var fixedcn = encodeURIComponent(cn); - var cs = document.cookie.split(';'); - for (var i = 0; i < cs.length; i++) { - var c = cs[i]; - while (c.charAt(0) == ' ') { - c = c.substring(1); - } - if (c.indexOf(fixedcn + "=") == 0) { - return decodeURIComponent(c.substring(cn.length + 1, c.length)); - } - } - return ""; + return sessionStorage.getItem(cn); } /* Hide variable fields if no values are available */ diff --git a/docs/debug-attach_service.md b/docs/debug-attach_service.md index e20719995..8fde69614 100644 --- a/docs/debug-attach_service.md +++ b/docs/debug-attach_service.md @@ -36,6 +36,8 @@ Here is a brief overview of what container / service does what: | redis-mailcow | Storage back-end for DKIM keys and Rspamd | | rspamd-mailcow | Mail filtering system. Used for av handling, dkim signing, spam handling | | clamd-mailcow | Scans attachments for viruses | +| olefy-mailcow | Scans attached office documents for macro-viruses | +| solr-mailcow | Provides full-text search in Dovecot | | sogo-mailcow | Webmail client that handles Microsoft ActiveSync and Cal- / CardDav | | nginx-mailcow | Nginx remote proxy that handles all mailcow related HTTP / HTTPS requests | | acme-mailcow | Automates HTTPS (SSL/TLS) certificate deployment | diff --git a/docs/debug-common_problems.md b/docs/debug-common_problems.md index 7954a4529..dbc5ace30 100644 --- a/docs/debug-common_problems.md +++ b/docs/debug-common_problems.md @@ -10,7 +10,7 @@ Please check in your mailcow UI if you made the domain a **backup MX**: There are a lot of things that could prevent you from sending mail: -- Check if your IP is on any blacklists. You could use [dnsbl.info](http://www.dnsbl.info/) or any other similar service to check for your IP. +- Check if your IP address is on any blacklists. You could use [dnsbl.info](http://www.dnsbl.info/) or any other similar service to check for your IP address. - There are some consumer ISP routers out there, that block mail ports for non whitelisted domains. Please check if you can reach your server on the ports `465` or `587`: ``` @@ -40,7 +40,7 @@ This error tries to tell you that one of the (health) conditions for a certain c A wrong configured firewall could also cause such a failure. The containers need to be able to talk to each other over the network 172.22.1.1/24. -It might also be wrongly linked file (i.e. SSL certificate) that prevents a crucial container (nginx) from starting, so always check your logs to get an Idea where your problem is coming from. +It might also be wrongly linked file (i.e. SSL certificate) that prevents a crucial container (nginx) from starting, so always check your logs to get an idea where your problem is coming from. ## Address already in use @@ -51,7 +51,7 @@ If you get an error message like: ERROR: for postfix-mailcow Cannot start service postfix-mailcow: driver failed programming external connectivity on endpoint mailcowdockerized_postfix-mailcow_1: Error starting userland proxy: listen tcp 0.0.0.0:25: bind: address already in use ``` -while trying to start / install mailcow: dockerized, make sure you've followed our section on the [prerequisites](prerequisite-system/#firewall-ports). +while trying to start / install mailcow: dockerized, make sure you've followed our section on the [prerequisites](../prerequisite-system/#firewall-ports). ## XYZ can't connect to ... diff --git a/docs/debug-reset-tls.md b/docs/debug-reset-tls.md new file mode 100644 index 000000000..b2584e0f4 --- /dev/null +++ b/docs/debug-reset-tls.md @@ -0,0 +1,17 @@ +In case you encounter problems with your certificate, key or Let's Encrypt account, please try to reset the TLS assets: + +``` +source mailcow.conf +docker-compose down +rm -rf data/assets/ssl +mkdir data/assets/ssl +openssl req -x509 -newkey rsa:4096 -keyout data/assets/ssl-example/key.pem -out data/assets/ssl-example/cert.pem -days 365 -subj "/C=DE/ST=NRW/L=Willich/O=mailcow/OU=mailcow/CN=${MAILCOW_HOSTNAME}" -sha256 -nodes +cp -n -d data/assets/ssl-example/*.pem data/assets/ssl/ +docker-compose up -d +``` + +This will stop mailcow, source the variables we need, create a self-signed certificate and start mailcow. + +If you use Let's Encrypt you should be careful as you will create a new account and a new set of certificates. You will run into a ratelimit sooner or later. + +Please also note that previous TLSA records will be invalid. diff --git a/docs/debug-reset_pw.md b/docs/debug-reset_pw.md index 508701703..485ca877a 100644 --- a/docs/debug-reset_pw.md +++ b/docs/debug-reset_pw.md @@ -1,6 +1,6 @@ ## mailcow Admin Account -Reset mailcow admin to `admin:moohoo`. Older mailcow: dockerized installations may find `mailcow-reset-admin.sh` in their mailcow root directory (mailcow_path). +Resets the mailcow admin account to a random password. Older mailcow: dockerized installations may find the `mailcow-reset-admin.sh` script in their mailcow root directory (mailcow_path). ``` cd mailcow_path @@ -36,6 +36,8 @@ MariaDB [(none)]> show databases; ### 2\. Reset one or more users +#### 2\.1 Maria DB < 10.4 (older mailcow installations) + Both "password" and "authentication_string" exist. Currently "password" is used, but better set both. ``` @@ -43,7 +45,7 @@ MariaDB [(none)]> SELECT user FROM mysql.user; +--------------+ | user | +--------------+ -| mailcow_user | <===== +| mailcow | <===== | root | +--------------+ 2 rows in set (0.00 sec) @@ -54,11 +56,38 @@ MariaDB [(none)]> UPDATE mysql.user SET authentication_string = PASSWORD('mookuh MariaDB [(none)]> FLUSH PRIVILEGES; ``` +#### 2\.2 Maria DB >= 10.4 (current mailcows) + +``` +MariaDB [(none)]> SELECT user FROM mysql.user; ++--------------+ +| user | ++--------------+ +| mailcow | <===== +| root | ++--------------+ +2 rows in set (0.00 sec) + +MariaDB [(none)]> FLUSH PRIVILEGES; +MariaDB [(none)]> ALTER USER 'mailcow'@'%' IDENTIFIED BY 'mookuh'; +MariaDB [(none)]> ALTER USER 'root'@'%' IDENTIFIED BY 'gotr00t'; +MariaDB [(none)]> ALTER USER 'root'@'localhost' IDENTIFIED BY 'gotr00t'; +MariaDB [(none)]> FLUSH PRIVILEGES; +``` + ## Remove Two-Factor Authentication +### For mailcow WebUI: + This works similar to resetting a MySQL password, now we do it from the host without connecting to the MySQL CLI: ``` source mailcow.conf docker-compose exec mysql-mailcow mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM tfa WHERE username='YOUR_USERNAME';" ``` + +### For SOGo: + +``` +docker-compose exec -u sogo sogo-mailcow sogo-tool user-preferences set defaults user@example.com SOGoGoogleAuthenticatorEnabled '{"SOGoGoogleAuthenticatorEnabled":0}' +``` diff --git a/docs/debug-rm_volumes.md b/docs/debug-rm_volumes.md index 1e2d78366..fc8cd7b25 100644 --- a/docs/debug-rm_volumes.md +++ b/docs/debug-rm_volumes.md @@ -1,6 +1,6 @@ You may want to remove a set of persistent data to resolve a conflict or to start over. -`mailcowdockerized` can vary and depends on your compose project name (if it's unchanged, `mailcowdockerized` is the correct value). If you are unsure about volume names, run `docker volumes ls` for a full list. +`mailcowdockerized` can vary and depends on your compose project name (if it's unchanged, `mailcowdockerized` is the correct value). If you are unsure about volume names, run `docker volume ls` for a full list. Delete a single volume: diff --git a/docs/download/build-thunderbird-plugins.sh b/docs/download/build-thunderbird-plugins.sh index 6cc4bd23e..35ff84a26 100755 --- a/docs/download/build-thunderbird-plugins.sh +++ b/docs/download/build-thunderbird-plugins.sh @@ -10,27 +10,28 @@ fi cd $(dirname $0) -wget -O connector.tar.gz https://github.com/inverse-inc/sogo-connector/archive/master.tar.gz - -mkdir -p connector -tar --strip-components=1 -C connector -xf connector.tar.gz +# we have to use the master branch, because there is no tag or release at the moment +wget -O connector.zip https://github.com/inverse-inc/sogo-connector/archive/master.zip +unzip connector.zip # build custom connector while read DOMAINS; do for DOMAIN in $DOMAINS; do echo "Building SOGo Connector for $DOMAIN hosted on $MAILHOST" - cd connector + cd sogo-connector-master mkdir -p custom/${DOMAIN} cp -r custom/sogo-demo/* custom/${DOMAIN}/ - sed -i "s/http:\/\/sogo-demo\.inverse\.ca/https:\/\/${MAILHOST}/g" custom/${DOMAIN}/chrome/content/sogo-connector/global/extensions.rdf - sed -i "s/plugins\/updates\.php[?]/thunderbird-plugins.php?domain=${DOMAIN}\&/g" custom/${DOMAIN}/chrome/content/sogo-connector/global/extensions.rdf - echo > custom/${DOMAIN}/defaults/preferences/site.js - echo 'pref("sogo-connector.autocomplete.server.urlid", "'${DOMAIN}'");' > custom/${DOMAIN}/defaults/preferences/site.js - echo 'pref("mail.collect_email_address_outgoing", false);' >> custom/${DOMAIN}/defaults/preferences/site.js - #sed -i 's/<\/Seq>/
  • <\/li>
  • <\/li><\/Seq>/g' custom/${DOMAIN}/chrome/content/sogo-connector/global/extensions.rdf + sed -i "s/https:\/\/demo\.sogo\.nu/https:\/\/${MAILHOST}/g" custom/${DOMAIN}/chrome/content/sogo-connector/general/custom-preferences.js + sed -i "s/plugins\/updates\.php[?]/thunderbird-plugins.php?domain=${DOMAIN}\&/g" chrome/content/sogo-connector/global/extensions.rdf + # adjust sogo-connector.autocomplete.server.urlid + sed -i "s/\"public\"/\"${MAILHOST}\"/g" custom/${DOMAIN}/chrome/content/sogo-connector/general/custom-preferences.js + # remove wrong timezone setting + sed -i 's/char_pref(\"calendar\.timezone\.local\", \"\/mozilla\.org\/20070129_1\/America\/Montreal\");//g' custom/${DOMAIN}/chrome/content/sogo-connector/general/custom-preferences.js + + echo 'bool_pref("mail.collect_email_address_outgoing", false);' >> custom/${DOMAIN}/chrome/content/sogo-connector/general/custom-preferences.js make build=${DOMAIN} - CONNECTOR_VER=$(grep em:version install.rdf | awk -F '"' '{print $2}') - CONNECTOR_MIN_VER=$(grep em:minVersion install.rdf | grep -Eo '[0-9\.]+' | head -n 1) + CONNECTOR_VER=$(grep \"version\" manifest.json | awk -F '"' '{print $4}') + CONNECTOR_MIN_VER=$(grep strict_min_version manifest.json | grep -Eo '[0-9\.]+' | head -n 1) mv sogo-connector-*.xpi ../sogo-connector-${CONNECTOR_VER}-${DOMAIN}.xpi cd .. done @@ -57,4 +58,4 @@ echo "sogo-connector@inverse.ca;${CONNECTOR_VER};sogo-connector-${CONNECTOR_VER} # echo "sieve@mozdev.org;${SIEVE_VER};sieve-${SIEVE_VER}.xpi" >> version.csv # echo "imap-acl@sirphreak.com;${IMAP_ACL_VER};imap_acl_extension-${IMAP_ACL_VER}-tb.xpi" >> version.csv -rm -rf connector *.tar.gz +rm -rf sogo-connector-master *.zip diff --git a/docs/firststeps-disable_ipv6.md b/docs/firststeps-disable_ipv6.md index 1f0f86abf..3f3480e44 100644 --- a/docs/firststeps-disable_ipv6.md +++ b/docs/firststeps-disable_ipv6.md @@ -38,6 +38,7 @@ version: '2.1' services: ipv6nat-mailcow: + image: bash:latest restart: "no" entrypoint: ["echo", "ipv6nat disabled in compose.override.yml"] ``` @@ -72,6 +73,7 @@ Create `data/conf/postfix/extra.cf` and set `smtp_address_preference` to `ipv4`: ``` smtp_address_preference = ipv4 +inet_protocols = ipv4 ``` Restart Postfix: diff --git a/docs/firststeps-ip_bindings.md b/docs/firststeps-ip_bindings.md index e04d5bbd6..86a1764fd 100644 --- a/docs/firststeps-ip_bindings.md +++ b/docs/firststeps-ip_bindings.md @@ -8,15 +8,16 @@ To adjust one or multiple IPv4 bindings, open `mailcow.conf` and edit one, multi ``` # For technical reasons, http bindings are a bit different from other service bindings. # You will find the following variables, separated by a bind address and its port: +# Example: HTTP_BIND=1.2.3.4 HTTP_PORT=80 -HTTP_BIND=0.0.0.0 +HTTP_BIND= HTTPS_PORT=443 -HTTPS_BIND=0.0.0.0 +HTTPS_BIND= # Other services are bound by using the following format: -# SMTP_PORT=25 equals to SMTP_PORT=0.0.0.0:25 # SMTP_PORT=1.2.3.4:25 will bind SMTP to the IP 1.2.3.4 on port 25 +# Important! Specifying an IPv4 address will skip all IPv6 bindings since Docker 20.x. # doveadm, SQL as well as Solr are bound to local ports only, please do not change that, unless you know what you are doing. SMTP_PORT=25 diff --git a/docs/firststeps-logging.md b/docs/firststeps-logging.md index 8c758a436..56f8d0b7a 100644 --- a/docs/firststeps-logging.md +++ b/docs/firststeps-logging.md @@ -26,6 +26,8 @@ Redis keys will only hold logs from applications and filter out system messages ### Logging drivers +#### Via docker-compose.override.yml + Here is the good news: Since Docker has some great logging drivers, you can integrate mailcow: dockerized into your existing logging environment with ease. Create a `docker-compose.override.yml` and add, for example, this block to use the "gelf" logging plugin for `postfix-mailcow`: @@ -37,10 +39,49 @@ services: logging: driver: "gelf" options: - gelf-address: "udp://graylog:12201" + gelf-address: "udp://graylog:12201" ``` -If you want to change the logging driver globally, edit Dockers daemon configuration file `/etc/docker/daemon.json` and restart the Docker service: +Another example for **Syslog**: + +``` +version: '2.1' +services: + + postfix-mailcow: # or any other + logging: + driver: "syslog" + options: + syslog-address: "udp://127.0.0.1:514" + syslog-facility: "local3" + + dovecot-mailcow: # or any other + logging: + driver: "syslog" + options: + syslog-address: "udp://127.0.0.1:514" + syslog-facility: "local3" + + rspamd-mailcow: # or any other + logging: + driver: "syslog" + options: + syslog-address: "udp://127.0.0.1:514" + syslog-facility: "local3" + +# For Rsyslog only: +# To move local3 input to /var/log/mailcow.log and stop processing, create a file "/etc/rsyslog.d/docker.conf": + +local3.* /var/log/mailcow.logs +& ~ + +# Restart rsyslog afterwards. + +``` + +#### via daemon.json (globally) + +If you want to **change the logging driver globally**, edit Dockers daemon configuration file `/etc/docker/daemon.json` and restart the Docker service: ``` { diff --git a/docs/firststeps-rfc-1918.md b/docs/firststeps-rfc-1918.md deleted file mode 100644 index d99fbb5c0..000000000 --- a/docs/firststeps-rfc-1918.md +++ /dev/null @@ -1,11 +0,0 @@ -Per default, mailcow considers all private RFC1918 networks (i.e. 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) as trusted. Though it is reasonable in most cases, you may want to restrict this setting under certain circumstances. In particular, if you are using some kind of reverse proxy for SMTP TCP ports. If your reverse proxy host is located in a private net, mailcow will consider all traffic from it as trusted, which may result in an open relay. - -To change this behaviour override the default value of `mynetworks` parameter through the `data/conf/postfix/extra.cf` configuration file. - -**Important**: Do **not** remove the networks listed as `IPV4_NETWORK` and `IPV6_NETWORK` in your mailcow.conf. You should also keep local addresses. - -The default values for those variables - `172.22.1.0/24` and `fd4d:6169:6c63:6f77::/64` - would result in the following, minimal configuration: - -``` -mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 [fe80::]/10 172.22.1.0/24 [fd4d:6169:6c63:6f77::]/64 -``` diff --git a/docs/firststeps-rp.md b/docs/firststeps-rp.md index 11b266167..1e3417081 100644 --- a/docs/firststeps-rp.md +++ b/docs/firststeps-rp.md @@ -15,6 +15,11 @@ This will also change the bindings inside the Nginx container! This is important Recreate affected containers by running `docker-compose up -d`. +**Important information, please read them carefully!** + +!!! info + If you plan to use a reverse proxy and want to use another server name that is **not** MAILCOW_HOSTNAME, you need to read **Adding additional server names for mailcow UI** at the bottom of this page. + !!! warning Make sure you run `generate_config.sh` before you enable any site configuration examples below. The script `generate_config.sh` copies snake-oil certificates to the correct location, so the services will not fail to start due to missing files. @@ -50,7 +55,7 @@ Let's Encrypt will follow our rewrite, certificate requests in mailcow will work ServerAlias autoconfig.* RewriteEngine on - RewriteCond %{HTTPS} !=on + RewriteCond %{HTTPS} off RewriteRule ^/?(.*) https://%{HTTP_HOST}/$1 [R=301,L] ProxyPass / http://127.0.0.1:8080/ @@ -176,7 +181,7 @@ For this we'll have to set `SKIP_LETS_ENCRYPT=y` on our `mailcow.conf`, and run Then we'll create a `docker-compose.override.yml` file in order to override the main `docker-compose.yml` found in your mailcow root folder. -``` +```yaml version: '2.1' services: @@ -195,10 +200,10 @@ services: - traefik.http.routers.moo.tls.certresolver=le # Creates a service called "moo" for the container, and specifies which internal port of the container # should traefik route the incoming data to. - - traefik.http.services.moo.loadbalancer.server.port=80 + - traefik.http.services.moo.loadbalancer.server.port=${HTTP_PORT} # Specifies which entrypoint (external port) should traefik listen to, for this container. # websecure being port 443, check the traefik.toml file liked above. - - traefik.http.routers.moo.entrypoints=secure + - traefik.http.routers.moo.entrypoints=websecure # Make sure traefik uses the web network, not the mailcowdockerized_mailcow-network - traefik.docker.network=web @@ -248,3 +253,13 @@ dovecot_c=$(docker ps -qaf name=dovecot-mailcow) nginx_c=$(docker ps -qaf name=nginx-mailcow) docker restart ${postfix_c} ${dovecot_c} ${nginx_c} ``` + +### Adding additional server names for mailcow UI + +If you plan to use a server name that is not `MAILCOW_HOSTNAME` in your reverse proxy, make sure to populate that name in mailcow.conf via `ADDITIONAL_SERVER_NAMES` first. Names must be separated by commas and **must not** contain spaces. If you skip this step, mailcow may respond to your reverse proxy with an incorrect site. + +``` +ADDITIONAL_SERVER_NAMES=webmail.domain.tld,other.example.tld +``` + +Run `docker-compose up -d` to apply. diff --git a/docs/firststeps-rspamd_ui.md b/docs/firststeps-rspamd_ui.md index fb0b49a96..01ae321f1 100644 --- a/docs/firststeps-rspamd_ui.md +++ b/docs/firststeps-rspamd_ui.md @@ -1,4 +1,4 @@ -Rspamd (https://rspamd.com/webui/) is an easy to use spam filtering tool presently installed with mailcow. +[Rspamd](https://rspamd.com/) is an easy to use spam filtering tool presently installed with mailcow. 1. Go to the mailcow web admin interface 2. Navigate to the Access tab. (Configuration > Administration > Access) diff --git a/docs/firststeps-snat.md b/docs/firststeps-snat.md index 3f6179b7e..bdaf53b2e 100644 --- a/docs/firststeps-snat.md +++ b/docs/firststeps-snat.md @@ -1,7 +1,5 @@ -## SNAT - SNAT is used to change the source address of the packets sent by mailcow. -It can be used to change the outgoing IP on systems with multiple IP addresses. +It can be used to change the outgoing IP address on systems with multiple IP addresses. Open `mailcow.conf`, set either or both of the following parameters: diff --git a/docs/firststeps-ssl.md b/docs/firststeps-ssl.md index 8422c0b44..61626c904 100644 --- a/docs/firststeps-ssl.md +++ b/docs/firststeps-ssl.md @@ -4,10 +4,10 @@ The "acme-mailcow" container will try to obtain a LE certificate for `${MAILCOW_ !!! warning mailcow **must** be available on port 80 for the acme-client to work. Our reverse proxy example configurations do cover that. You can also use any external ACME client (certbot for example) to obtain certificates, but you will need to make sure, that they are copied to the correct location and a post-hook reloads affected containers. See more in the Reverse Proxy documentation. - + By default, which means **0 domains** are added to mailcow, it will try to obtain a certificate for `${MAILCOW_HOSTNAME}`. -For each domain you add, it will try to resolve `autodiscover.ADDED_MAIL_DOMAIN` and `autoconfig.ADDED_MAIL_DOMAIN` to its IPv6 or - if IPv6 is not configured in your domain - IPv4 address. If it succeeds, a name will be added as SAN to the certificate request. +For each domain you add, it will try to resolve `autodiscover.ADDED_MAIL_DOMAIN` and `autoconfig.ADDED_MAIL_DOMAIN` to its IPv6 address or - if IPv6 is not configured in your domain - IPv4 address. If it succeeds, a name will be added as SAN to the certificate request. Only names that can be validated, will be added as SAN. @@ -25,12 +25,23 @@ Do not use quotes (`"`) and do not use spaces between the names! ADDITIONAL_SAN=smtp.*,cert1.example.com,cert2.example.org,whatever.* ``` -Each name will be validated against its IPv6 or - if IPv6 is not configured in your domain - IPv4 address. +Each name will be validated against its IPv6 address or - if IPv6 is not configured in your domain - IPv4 address. A wildcard name like `smtp.*` will try to obtain a smtp.DOMAIN_NAME SAN for each domain added to mailcow. Run `docker-compose up -d` to recreate affected containers automatically. +!!! info + Using names other name `MAILCOW_HOSTNAME` to access the mailcow UI may need further configuration. + +If you plan to use a server name that is not `MAILCOW_HOSTNAME` to access the mailcow UI (for example by adding `mail.*` to `ADDITIONAL_SAN` make sure to populate that name in mailcow.conf via `ADDITIONAL_SERVER_NAMES`. Names must be separated by commas and **must not** contain spaces. If you skip this step, mailcow may respond with an incorrect site. + +``` +ADDITIONAL_SERVER_NAMES=webmail.domain.tld,other.example.tld +``` + +Run `docker-compose up -d` to apply. + ### Force renewal To force a renewal, you need to create a file named `force_renew` and restart the `acme-mailcow` container: @@ -47,9 +58,9 @@ The file will be deleted automatically. ### Validation errors and how to skip validation -You can skip the **IP verification** by setting `SKIP_IP_CHECK=y` in mailcow.conf (no quotes). Be warned that a misconfiguration will get you ratelimited by Let's Encrypt! This is primarily useful for multi-IP setups where the IP check would return the incorrect source IP. Due to using dynamic IPs for acme-mailcow, source NAT is not consistent over restarts. +You can skip the **IP verification** by setting `SKIP_IP_CHECK=y` in mailcow.conf (no quotes). Be warned that a misconfiguration will get you ratelimited by Let's Encrypt! This is primarily useful for multi-IP setups where the IP check would return the incorrect source IP address. Due to using dynamic IPs for acme-mailcow, source NAT is not consistent over restarts. -If you encounter problems with "HTTP validation", but your IP confirmation succeeds, you are most likely using firewalld, ufw or any other firewall, that disallows connections from `br-mailcow` to your external interface. Both firewalld and ufw disallow this by default. It is often not enough to just stop these firewall services. You'd need to stop mailcow (`docker-compose down`), stop the firewall service, flush the chains and restart Docker. +If you encounter problems with "HTTP validation", but your IP address confirmation succeeds, you are most likely using firewalld, ufw or any other firewall, that disallows connections from `br-mailcow` to your external interface. Both firewalld and ufw disallow this by default. It is often not enough to just stop these firewall services. You'd need to stop mailcow (`docker-compose down`), stop the firewall service, flush the chains and restart Docker. You can also skip this validation method by setting `SKIP_HTTP_VERIFICATION=y` in "mailcow.conf". Be warned that this is discouraged. In most cases, the HTTP verification is skipped to workaround unknown NAT reflection issues, which are not resolved by ignoring this specific network misconfiguration. If you encounter problems generating TLSA records in the DNS overview within mailcow, you are most likely having issues with NAT reflection you should fix. @@ -73,9 +84,10 @@ By default, "acme-mailcow" will create a single SAN certificate for all validate This provides best compatibility but means the Let's Encrypt limit exceeds if you add too many domains to a single mailcow installation. To solve this, you can configure `ENABLE_SSL_SNI` to generate: -* A main server certificate with `MAILCOW_HOSTNAME` and all fully qualified domain names in the `ADDITIONAL_SAN` config -* One additional certificate for each domain found in the database with autodiscover.*, autoconfig.* and any other `ADDITIONAL_SAN` configured in this format (subdomain.*). -* Limitations: A certificate name `ADDITIONAL_SAN=test.example.com` will be added as SAN to the main certificate. A separate certificate/key pair will **not** be generated for this format. + +- A main server certificate with `MAILCOW_HOSTNAME` and all fully qualified domain names in the `ADDITIONAL_SAN` config +- One additional certificate for each domain found in the database with autodiscover.*, autoconfig.* and any other `ADDITIONAL_SAN` configured in this format (subdomain.*). +- Limitations: A certificate name `ADDITIONAL_SAN=test.example.com` will be added as SAN to the main certificate. A separate certificate/key pair will **not** be generated for this format. Postfix, Dovecot and Nginx will then serve these certificates with SNI. @@ -86,14 +98,16 @@ Set `ENABLE_SSL_SNI=y` in "mailcow.conf" and recreate "acme-mailcow" by running You should make sure these clients use the `MAILCOW_HOSTNAME` for secure connections if you enable this feature. Here is an example: -* `MAILCOW_HOSTNAME=server.email.tld` -* `ADDITIONAL_SAN=webmail.email.tld,mail.*` -* Mailcow email domains: "domain1.tld" and "domain2.tld" + +- `MAILCOW_HOSTNAME=server.email.tld` +- `ADDITIONAL_SAN=webmail.email.tld,mail.*` +- Mailcow email domains: "domain1.tld" and "domain2.tld" The following certificates will be generated: -* `server.email.tld, webmail.email.tld` -> this is the default certificate, all clients can connect with these domains -* `mail.domain1.tld, autoconfig.domain1.tld, autodiscover.domain1.tld` -> individual certificate for domain1.tld, cannot be used by clients without SNI support -* `mail.domain2.tld, autoconfig.domain2.tld, autodiscover.domain2.tld` -> individual certificate for domain2.tld, cannot be used by clients without SNI support + +- `server.email.tld, webmail.email.tld` -> this is the default certificate, all clients can connect with these domains +- `mail.domain1.tld, autoconfig.domain1.tld, autodiscover.domain1.tld` -> individual certificate for domain1.tld, cannot be used by clients without SNI support +- `mail.domain2.tld, autoconfig.domain2.tld, autodiscover.domain2.tld` -> individual certificate for domain2.tld, cannot be used by clients without SNI support ### How to use your own certificate @@ -101,6 +115,8 @@ Make sure you disable mailcows internal LE client (see above). To use your own certificates, just save the combined certificate (containing the certificate and intermediate CA/CA if any) to `data/assets/ssl/cert.pem` and the corresponding key to `data/assets/ssl/key.pem`. +**IMPORTANT:** Do not use symbolic links! Make sure you copy the certificates and do not link them to `data/assets/ssl`. + Restart affected services afterwards: ``` @@ -109,7 +125,7 @@ docker restart $(docker ps -qaf name=nginx-mailcow) docker restart $(docker ps -qaf name=dovecot-mailcow) ``` -See https://mailcow.github.io/mailcow-dockerized-docs/firststeps-rp/#optional-post-hook-script-for-non-mailcow-acme-clients for a full example script. +See [Post-hook script for non-mailcow ACME clients](../firststeps-rp/#optional-post-hook-script-for-non-mailcow-acme-clients) for a full example script. ### Test against staging ACME directory diff --git a/docs/firststeps-sync_jobs_migration.md b/docs/firststeps-sync_jobs_migration.md index 120118498..a519461f4 100644 --- a/docs/firststeps-sync_jobs_migration.md +++ b/docs/firststeps-sync_jobs_migration.md @@ -10,7 +10,7 @@ Sync jobs are used to copy or move existing emails from an external IMAP server 3. Fill in the "Host" and "Port" fields with their respective correct values from the upstream IMAP server. -4. In the "Username" and 'Password" fields, supply the correct access credentials from the upstream IMAP server. +4. In the "Username" and "Password" fields, supply the correct access credentials from the upstream IMAP server. 5. Select the "Encryption Method". If the upstream IMAP server uses port 143, it is likely that the encryption method is TLS and SSL for port 993. Nevertheless, you can use PLAIN authentication, but it is stongly discouraged. @@ -19,4 +19,4 @@ Sync jobs are used to copy or move existing emails from an external IMAP server 7. Make sure to tick "Active" and click "Add". !!! info - Once Completed, log into the mailbox and check if all emails are imported correctly. If all goes well, All your mails shall end up in your new mailbox. And don't forget to delete or deactivate the sync job after it is used. \ No newline at end of file + Once Completed, log into the mailbox and check if all emails are imported correctly. If all goes well, all your mails shall end up in your new mailbox. And don't forget to delete or deactivate the sync job after it is used. \ No newline at end of file diff --git a/docs/firststeps-trust_networks.md b/docs/firststeps-trust_networks.md new file mode 100644 index 000000000..aea044b9e --- /dev/null +++ b/docs/firststeps-trust_networks.md @@ -0,0 +1,39 @@ +By default mailcow considers **all networks as untrusted** excluding its own IPV4_NETWORK and IPV6_NETWORK scopes. Though it is reasonable in most cases, there may be circumstances that you need to loosen this restriction. + +By default mailcow uses `mynetworks_style = subnet` to determine internal subnets and leaves `mynetworks` unconfigured. + +If you decide to set `mynetworks`, Postfix ignores the mynetworks_style setting. This means you **have to** add the IPV4_NETWORK and IPV6_NETWORK scopes as well as loopback subnets manually! + +## Unauthenticated relaying + +!!! Warning + Incorrect setup of `mynetworks` will allow your server to be used as an open relay. If abused, this **will** affect your ability to send emails and can take some time to be resolved. + +### IPv4 hosts/subnets + +To add the subnet `192.168.2.0/24` to the trusted networks you may use the following configuration, depending on your IPV4_NETWORK and IPV6_NETWORK scopes: + +Edit `data/conf/postfix/extra.cf`: + +``` +mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 [fe80::]/10 172.22.1.0/24 [fd4d:6169:6c63:6f77::]/64 192.168.2.0/24 +``` + +Run `docker-compose restart postfix-mailcow` to apply your new settings. + +### IPv6 hosts/subnets + +Adding IPv6 hosts is done the same as IPv4, however the subnet needs to be placed in brackets `[]` with the netmask appended. + +To add the subnet 2001:db8::/32 to the trusted networks you may use the following configuration, depending on your IPV4_NETWORK and IPV6_NETWORK scopes: + +Edit `data/conf/postfix/extra.cf`: + +``` +mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 [fe80::]/10 172.22.1.0/24 [fd4d:6169:6c63:6f77::]/64 [2001:db8::]/32 +``` + +Run `docker-compose restart postfix-mailcow` to apply your new settings. + +!!! Info + More information about mynetworks can be found in the [Postfix documentation](http://www.postfix.org/postconf.5.html#mynetworks). diff --git a/docs/u_e-deinstall.md b/docs/i_u_m_deinstall.md similarity index 100% rename from docs/u_e-deinstall.md rename to docs/i_u_m_deinstall.md diff --git a/docs/i_u_m_install.md b/docs/i_u_m_install.md index 97bea2a66..cd9469a30 100644 --- a/docs/i_u_m_install.md +++ b/docs/i_u_m_install.md @@ -1,9 +1,4 @@ -!!! warning - Make sure you've read ["Prepare Your System"](https://mailcow.github.io/mailcow-dockerized-docs/prerequisite-system) before proceeding! - **Do not** use CentOS 8 with Centos 7 Docker packages. You may create an open relay. - - -You need Docker and Docker Compose. +You need Docker (a version >= `20.10.2` is required) and Docker Compose. **1\.** Learn how to install [Docker](https://docs.docker.com/install/) and [Docker Compose](https://docs.docker.com/compose/install/). @@ -13,8 +8,7 @@ Quick installation for most operation systems: ``` curl -sSL https://get.docker.com/ | CHANNEL=stable sh # After the installation process is finished, you may need to enable the service and make sure it is started (e.g. CentOS 7) -systemctl enable docker.service -systemctl start docker.service +systemctl enable --now docker ``` - Docker-Compose @@ -22,7 +16,7 @@ systemctl start docker.service !!! warning **mailcow requires the latest version of docker-compose.** It is highly recommended to use the commands below to install `docker-compose`. Package managers (e.g. `apt`, `yum`) **likely won't** give you the latest version. _Note: This command downloads docker-compose from the official Docker Github repository and is a safe method. The snippet will determine the latest supported version by mailcow. In almost all cases this is the latest version available (exceptions are broken releases or major changes not yet supported by mailcow)._ - + ``` curl -L https://github.com/docker/compose/releases/download/$(curl -Ls https://www.servercow.de/docker-compose/latest.php)/docker-compose-$(uname -s)-$(uname -m) > /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose @@ -30,6 +24,36 @@ chmod +x /usr/local/bin/docker-compose Please use the latest Docker engine available and do not use the engine that ships with your distros repository. +**1\.1\.** On SELinux enabled systems, e.g. CentOS 7: + +- Check if "container-selinux" package is present on your system: + +``` +rpm -qa | grep container-selinux +``` + +If the above command returns an empty or no output, you should install it via your package manager. + +- Check if docker has SELinux support enabled: + +``` +docker info | grep selinux +``` + +If the above command returns an empty or no output, create or edit `/etc/docker/daemon.json` and add `"selinux-enabled": true`. Example file content: + +``` +{ + "selinux-enabled": true +} +``` + +Restart the docker daemon and verify SELinux is now enabled. + +This step is required to make sure mailcows volumes are properly labeled as declared in the compose file. +If you are interested in how this works, you can check out the readme of https://github.com/containers/container-selinux which links to a lot of useful information on that topic. + + **2\.** Clone the master branch of the repository, make sure your umask equals 0022. Please clone the repository as root user and also control the stack as root. We will modify attributes - if necessary - while boostrapping the containers automatically and make sure everything is secured. The update.sh script must therefore also be run as root. It might be necessary to change ownership and other attributes of files you will otherwise not have access to. **We drop permissions for every exposed application** and will not run an exposed service as root! Controlling the Docker daemon as non-root user does not give you additional security. The unprivileged user will spawn the containers as root likewise. The behaviour of the stack is identical. ``` @@ -78,7 +102,7 @@ networks: If you do not have an IPv6 enabled network on your host and you don't care for a better internet (thehe), it is recommended to [disable IPv6](https://mailcow.github.io/mailcow-dockerized-docs/firststeps-disable_ipv6/) for the mailcow network to prevent unforeseen issues. -**5\.** Pull the images and run the composer file. The parameter `-d` will start mailcow: dockerized detached: +**5\.** Pull the images and run the compose file. The parameter `-d` will start mailcow: dockerized detached: ``` docker-compose pull docker-compose up -d @@ -88,8 +112,8 @@ Done! You can now access **https://${MAILCOW_HOSTNAME}** with the default credentials `admin` + password `moohoo`. - !!! info - If you are not using mailcow behind a reverse proxy, you should [redirect all HTTP requests to HTTPS](https://mailcow.github.io/mailcow-dockerized-docs/u_e-80_to_443/). +!!! info + If you are not using mailcow behind a reverse proxy, you should [redirect all HTTP requests to HTTPS](https://mailcow.github.io/mailcow-dockerized-docs/u_e-80_to_443/). The database will be initialized right after a connection to MySQL can be established. diff --git a/docs/i_u_m_update.md b/docs/i_u_m_update.md index ab8b0bbfb..f3be9af67 100644 --- a/docs/i_u_m_update.md +++ b/docs/i_u_m_update.md @@ -18,7 +18,7 @@ Some minor conflicts will be auto-corrected (in favour for the mailcow: dockeriz ``` # Options can be combined -# - Check for updates +# - Check for updates and show changes ./update.sh --check # Do not try to update docker-compose, **make sure to use the latest docker-compose available** @@ -41,52 +41,34 @@ Some minor conflicts will be auto-corrected (in favour for the mailcow: dockeriz ./update.sh --prefetch ``` -## Manual update (not maintained anymore, please use update.sh) +### I forgot what I changed before running update.sh -### Step 1 +See `git log --pretty=oneline | grep -i "before update"`, you will have an output similar to this: + +``` +22cd00b5e28893ef9ddef3c2b5436453cc5223ab Before update on 2020-09-28_19_25_45 +dacd4fb9b51e9e1c8a37d84485b92ffaf6c59353 Before update on 2020-08-07_13_31_31 +``` + +Run `git diff 22cd00b5e28893ef9ddef3c2b5436453cc5223ab` to see what changed. + +### Can I roll back? + +Yes. + +See the topic above, instead of a diff, you run checkout: ``` docker-compose down -``` - -Fetch new data from GitHub, commit changes and merge remote repository: - -``` -# 1. Get updates/changes -git fetch origin master -# 2. Add all changed files to local clone -git add -A -# 3. Commit changes, ignore git complaining about username and mail address -git commit -m "Local config at $(date)" -# 4. Merge changes, prefer mailcow repository, replace "theirs" by "ours" to change merge strategy -git merge -Xtheirs -Xpatience - -# If it conflicts with files that were deleted from the mailcow repository, just run... -git status --porcelain | grep -E "UD|DU" | awk '{print $2}' | xargs rm -v -# ...and repeat step 2 and 3 -``` - -### Step 2 - -Pull new images (if any) and recreate changed containers: - -``` +# Replace commit ID 22cd00b5e28893ef9ddef3c2b5436453cc5223ab by your ID +git checkout 22cd00b5e28893ef9ddef3c2b5436453cc5223ab docker-compose pull -docker-compose up -d --remove-orphans +docker-compose up -d ``` -### Step 3 -Clean-up dangling (unused) images and volumes: - -It is **very important** to _not_ run these commands when your containers are deleted. -Running `docker-compose down` - for example - will delete your containers. Your volumes are now in a dangling state! Running the commands shown below, _will_ remove your volumes and therefore your data. - - -``` -docker rmi -f $(docker images -f "dangling=true" -q) -docker volume rm $(docker volume ls -qf dangling=true) -``` +### Hooks +You can hook into the update mechanism by adding scripts called `pre_commit_hook.sh` and `post_commit_hook.sh` to your mailcows root directory. See [this](./u_e-update-hooks.md) for more details. ## Footnotes diff --git a/docs/images/favicon.png b/docs/images/favicon.png index 6390041d6..fe6156078 100644 Binary files a/docs/images/favicon.png and b/docs/images/favicon.png differ diff --git a/docs/images/thunderbird-tbsync-caldav.png b/docs/images/thunderbird-tbsync-caldav.png new file mode 100644 index 000000000..b9f60023b Binary files /dev/null and b/docs/images/thunderbird-tbsync-caldav.png differ diff --git a/docs/images/thunderbird-tbsync-enable.png b/docs/images/thunderbird-tbsync-enable.png new file mode 100644 index 000000000..f45298d86 Binary files /dev/null and b/docs/images/thunderbird-tbsync-enable.png differ diff --git a/docs/images/thunderbird-tbsync.png b/docs/images/thunderbird-tbsync.png new file mode 100644 index 000000000..0c8680360 Binary files /dev/null and b/docs/images/thunderbird-tbsync.png differ diff --git a/docs/index.md b/docs/index.md index 4fe59848b..d8b09f192 100644 --- a/docs/index.md +++ b/docs/index.md @@ -64,29 +64,33 @@ The integrated **mailcow UI** allows administrative work on your mail server ins mailcow: dockerized comes with multiple containers linked in one bridged network. Each container represents a single application. -- [Dovecot](https://www.dovecot.org/) +- [ACME](https://letsencrypt.org/) - [ClamAV](https://www.clamav.net/) (optional) -- [Solr](http://lucene.apache.org/solr/) (optional) -- [Oletools](https://github.com/decalage2/oletools) via [Olefy](https://github.com/HeinleinSupport/olefy) -- [Memcached](https://www.memcached.org/) -- [Redis](https://redis.io/) +- [Dovecot](https://www.dovecot.org/) - [MariaDB](https://mariadb.org/) -- [Unbound](https://unbound.net/) +- [Memcached](https://www.memcached.org/) +- [Netfilter](https://www.netfilter.org/) (Fail2ban-like integration by [@mkuron](https://github.com/mkuron)) +- [Nginx](https://nginx.org/) +- [Oletools](https://github.com/decalage2/oletools) via [Olefy](https://github.com/HeinleinSupport/olefy) - [PHP](https://php.net/) - [Postfix](http://www.postfix.org/) -- [ACME](https://letsencrypt.org/) -- [Nginx](https://nginx.org/) +- [Redis](https://redis.io/) - [Rspamd](https://www.rspamd.com/) - [SOGo](https://sogo.nu/) -- [Netfilter](https://www.netfilter.org/) (Fail2ban-like integration by [@mkuron](https://github.com/mkuron)) +- [Solr](https://solr.apache.org/) (optional) +- [Unbound](https://unbound.net/) - A Watchdog to provide basic monitoring **Docker volumes** to keep dynamic data - take care of them! -- vmail-vol-1 -- solr-vol-1 -- redis-vol-1 -- mysql-vol-1 -- rspamd-vol-1 -- postfix-vol-1 - crypt-vol-1 +- mysql-socket-vol-1 +- mysql-vol-1 +- postfix-vol-1 +- redis-vol-1 +- rspamd-vol-1 +- sogo-userdata-backup-vol-1 +- sogo-web-vol-1 +- solr-vol-1 +- vmail-index-vol-1 +- vmail-vol-1 \ No newline at end of file diff --git a/docs/model-passwd.md b/docs/model-passwd.md new file mode 100644 index 000000000..3e74ac6d5 --- /dev/null +++ b/docs/model-passwd.md @@ -0,0 +1,49 @@ +## Fully supported hashing methods + +The most current mailcow fully supports the following hashing methods. +The default hashing method is written in bold: + +- **BLF-CRYPT** +- SSHA +- SSHA256 +- SSHA512 + +The methods above can be used in `mailcow.conf` as `MAILCOW_PASS_SCHEME` value. + +## Read-only hashing methods + +The following methods are supported **read only**. +If you plan to use SOGo (as per default), you need a SOGo compatible hashing method. Please see the note at the bottom of this page how to update the view if necessary. +With SOGo disabled, all hashing methods below will be able to be read by mailcow and Dovecot. + +- ARGON2I (SOGo compatible) +- ARGON2ID (SOGo compatible) +- CLEAR +- CLEARTEXT +- CRYPT (SOGo compatible) +- DES-CRYPT +- LDAP-MD5 (SOGo compatible) +- MD5 (SOGo compatible) +- MD5-CRYPT (SOGo compatible) +- PBKDF2 (SOGo compatible) +- PLAIN (SOGo compatible) +- PLAIN-MD4 +- PLAIN-MD5 +- PLAIN-TRUNC +- SHA (SOGo compatible) +- SHA1 (SOGo compatible) +- SHA256 (SOGo compatible) +- SHA256-CRYPT (SOGo compatible) +- SHA512 (SOGo compatible) +- SHA512-CRYPT (SOGo compatible) +- SMD5 (SOGo compatible) + +That means mailcow is able to verify users with a hash like `{MD5}1a1dc91c907325c69271ddf0c944bc72` from the database. + +The value of `MAILCOW_PASS_SCHEME` will _always_ be used to encrypt new passwords. + +--- + +> I changed the password hashes in the "mailbox" SQL table and cannot login. + +A "view" needs to be updated. You can trigger this by restarting sogo-mailcow: `docker-compose restart sogo-mailcow` diff --git a/docs/prerequisite-dns.md b/docs/prerequisite-dns.md index a5f29fdbf..c0659d55a 100644 --- a/docs/prerequisite-dns.md +++ b/docs/prerequisite-dns.md @@ -8,10 +8,13 @@ Below you can find a list of **recommended DNS records**. While some are mandato ["Best Practices on Email Protection: SPF, DKIM and DMARC"](https://wiki.zimbra.com/wiki/Best_Practices_on_Email_Protection:_SPF,_DKIM_and_DMARC) - An in-depth discussion of SPF, DKIM and DMARC: ["How to eliminate spam and protect your name with DMARC"](https://www.skelleton.net/2015/03/21/how-to-eliminate-spam-and-protect-your-name-with-dmarc/) +- A thorough guide on understanding DMARC: +["Demystifying DMARC: A guide to preventing email spoofing"](https://seanthegeek.net/459/demystifying-dmarc/) -## Reverse DNS of your IP -Make sure that the PTR record of your IP matches the FQDN of your mailcow host: `${MAILCOW_HOSTNAME}` [^1]. This record is usually set at the provider you leased the IP (server) from. +## Reverse DNS of your IP address + +Make sure that the PTR record of your IP address matches the FQDN of your mailcow host: `${MAILCOW_HOSTNAME}` [^1]. This record is usually set at the provider you leased the IP address (server) from. ## The minimal DNS configuration @@ -20,10 +23,9 @@ This example shows you a set of records for one domain managed by mailcow. Each ``` # Name Type Value mail IN A 1.2.3.4 -autodiscover IN CNAME mail -autoconfig IN CNAME mail - -@ IN MX 10 mail +autodiscover IN CNAME mail.example.org. (your ${MAILCOW_HOSTNAME}) +autoconfig IN CNAME mail.example.org. (your ${MAILCOW_HOSTNAME}) +@ IN MX 10 mail.example.org. (your ${MAILCOW_HOSTNAME}) ``` ## DKIM, SPF and DMARC @@ -31,18 +33,21 @@ autoconfig IN CNAME mail In the example DNS zone file snippet below, a simple **SPF** TXT record is used to only allow THIS server (the MX) to send mail for your domain. Every other server is disallowed but able to ("`~all`"). Please refer to [SPF Project](http://www.open-spf.org/) for further reading. ``` +# Name Type Value @ IN TXT "v=spf1 mx a -all" ``` It is highly recommended to create a **DKIM** TXT record in your mailcow UI and set the corresponding TXT record in your DNS records. Please refer to [OpenDKIM](http://www.opendkim.org) for further reading. ``` +# Name Type Value dkim._domainkey IN TXT "v=DKIM1; k=rsa; t=s; s=email; p=..." ``` The last step in protecting yourself and others is the implementation of a **DMARC** TXT record, for example by using the [DMARC Assistant](http://www.kitterman.com/dmarc/assistant.html) ([check](https://dmarcian.com/dmarc-inspector/google.com)). ``` +# Name Type Value _dmarc IN TXT "v=DMARC1; p=reject; rua=mailto:mailauth-reports@example.org" ``` @@ -51,18 +56,19 @@ _dmarc IN TXT "v=DMARC1; p=reject; rua=mailto:mailauth-reports@ **SRV** records specify the server(s) for a specific protocol on your domain. If you want to explicitly announce a service as not provided, give "." as the target address (instead of "mail.example.org."). Please refer to [RFC 2782](https://tools.ietf.org/html/rfc2782). ``` -_imap._tcp IN SRV 0 1 143 mail.example.org. -_imaps._tcp IN SRV 0 1 993 mail.example.org. -_pop3._tcp IN SRV 0 1 110 mail.example.org. -_pop3s._tcp IN SRV 0 1 995 mail.example.org. -_submission._tcp IN SRV 0 1 587 mail.example.org. -_smtps._tcp IN SRV 0 1 465 mail.example.org. -_sieve._tcp IN SRV 0 1 4190 mail.example.org. -_autodiscover._tcp IN SRV 0 1 443 mail.example.org. -_carddavs._tcp IN SRV 0 1 443 mail.example.org. -_carddavs._tcp IN TXT "path=/SOGo/dav/" -_caldavs._tcp IN SRV 0 1 443 mail.example.org. -_caldavs._tcp IN TXT "path=/SOGo/dav/" +# Name Type Priority Weight Port Value +_autodiscover._tcp IN SRV 0 1 443 mail.example.org. (your ${MAILCOW_HOSTNAME}) +_caldavs._tcp IN SRV 0 1 443 mail.example.org. (your ${MAILCOW_HOSTNAME}) +_caldavs._tcp IN TXT "path=/SOGo/dav/" +_carddavs._tcp IN SRV 0 1 443 mail.example.org. (your ${MAILCOW_HOSTNAME}) +_carddavs._tcp IN TXT "path=/SOGo/dav/" +_imap._tcp IN SRV 0 1 143 mail.example.org. (your ${MAILCOW_HOSTNAME}) +_imaps._tcp IN SRV 0 1 993 mail.example.org. (your ${MAILCOW_HOSTNAME}) +_pop3._tcp IN SRV 0 1 110 mail.example.org. (your ${MAILCOW_HOSTNAME}) +_pop3s._tcp IN SRV 0 1 995 mail.example.org. (your ${MAILCOW_HOSTNAME}) +_sieve._tcp IN SRV 0 1 4190 mail.example.org. (your ${MAILCOW_HOSTNAME}) +_smtps._tcp IN SRV 0 1 465 mail.example.org. (your ${MAILCOW_HOSTNAME}) +_submission._tcp IN SRV 0 1 587 mail.example.org. (your ${MAILCOW_HOSTNAME}) ``` ## Testing @@ -73,13 +79,52 @@ Here are some tools you can use to verify your DNS configuration: - [port25.com](https://www.port25.com/dkim-wizard/) (DKIM, SPF) - [Mail-tester](https://www.mail-tester.com/) (DKIM, DMARC, SPF) - [DMARC Analyzer](https://www.dmarcanalyzer.com/spf/checker/) (DMARC, SPF) +- [MultiRBL.valli.org](http://multirbl.valli.org/) (DNSBL, RBL, FCrDNS) ## Misc -If you are interested in statistics, you can additionally register with the [Postmaster Tool](https://gmail.com/postmaster) by Google and supply a **google-site-verification** TXT record, which will give you details about spam-classified mails by your domain. This is clearly optional. +### Optional DMARC Statistics + +If you are interested in statistics, you can additionally register with some of the many below DMARC statistic services - or self-host your own. + +!!! Tip +It is worth considering that if you request DMARC statistic reports to your mailcow server and your mailcow server is not configured correctly to receive these reports, you may not get accurate and complete results. Please consider using an alternative email domain for receiving DMARC reports. + +It is worth mentioning, that the following suggestions are not a comprehensive list of all services and tools available, but only a small few of the many choices. + +- [Postmaster Tool](https://gmail.com/postmaster) +- [parsedmarc](https://github.com/domainaware/parsedmarc) (self-hosted) +- [Fraudmarc](https://fraudmarc.com/) +- [Postmark](https://dmarc.postmarkapp.com) +- [Dmarcian](https://dmarcian.com/) + +!!! Tip + +These services may provide you with a TXT record you need to insert into your DNS records as the provider specifies. Please ensure you read the provider's documentation from the service you choose as this process may vary. + +### Email test for SPF, DKIM and DMARC: + +To run a rudimentary email authentication check, send a mail to `check-auth at verifier.port25.com` and wait for a reply. You will find a report similar to the following: ``` -@ IN TXT "google-site-verification=..." +========================================================== +Summary of Results +========================================================== +SPF check: pass +"iprev" check: pass +DKIM check: pass +DKIM check: pass +SpamAssassin check: ham + +========================================================== +Details: +========================================================== +.... ``` -[^1]: A **Fully Qualified Domain Name** (**FQDN**) is the complete (absolute) domain name for a specific computer or host, on the Internet. The FQDN consists of at least three parts divided by a dot: the hostname (myhost), the domain name (mydomain) and the top level domain in short **tld** (com). In the example of `mx.mailcow.email` the hostname would be `mx`, the domain name 'mailcow' and the tld `email`. +The full report will contain more technical details. + + +### Fully Qualified Domain Name (FQDN) + +[^1]: A **Fully Qualified Domain Name** (**FQDN**) is the complete (absolute) domain name for a specific computer or host, on the Internet. The FQDN consists of at least three parts divided by a dot: the hostname, the domain name, and the Top Level Domain (**TLD** for short). In the example of `mx.mailcow.email` the hostname would be `mx`, the domain name `mailcow` and the TLD `email`. diff --git a/docs/prerequisite-system.md b/docs/prerequisite-system.md index 181411600..4880abe48 100644 --- a/docs/prerequisite-system.md +++ b/docs/prerequisite-system.md @@ -2,7 +2,6 @@ Before you run **mailcow: dockerized**, there are a few requirements that you sh !!! warning Do **not** try to install mailcow on a Synology/QNAP device (any NAS), OpenVZ, LXC or other container platforms. KVM, ESX, Hyper-V and other full virtualization platforms are supported. - Do **not** use CentOS 8 with Centos 7 Docker packages. You may create an open relay. !!! info - mailcow: dockerized requires [some ports](#default-ports) to be open for incoming connections, so make sure that your firewall is not blocking these. @@ -12,59 +11,114 @@ Before you run **mailcow: dockerized**, there are a few requirements that you sh ## Minimum System Resources -**Do not** use OpenVZ or LXC as guests for mailcow. +**OpenVZ, Virtuozzo and LXC are not supported**. Please make sure that your system has at least the following resources: -| Resource | mailcow: dockerized | -| ----------------------- | -------------------------------------------- | -| CPU | 1 GHz | -| RAM Β  Β  Β  Β  Β  Β  Β  Β  Β  Β  | Minimum 4 GiB + Swap | -| Disk | 20 GiB (without emails) | -| System Type | x86_64 | +| Resource | mailcow: dockerized | +| ----------------------- | ------------------------------------------------ | +| CPU | 1 GHz | +| RAM Β  Β  Β  Β  Β  Β  Β  Β  Β  Β  | **Minimum** 6 GiB + 1 GiB swap (default config) | +| Disk | 20 GiB (without emails) | +| System Type | x86_64 | -As of today (29th Dec 2019), we recommend using any distribution listed as supported by Docker CE (check https://docs.docker.com/install/). We test on CentOS 7, Debian 9/10 and Ubuntu 18.04. +We recommend using any distribution listed as supported by Docker CE (check https://docs.docker.com/install/). We test on CentOS 7, Debian 9/10 and Ubuntu 18.04/20.04. -ClamAV and Solr are greedy RAM munchers. You can disable them in `mailcow.conf` by settings SKIP_CLAMD=y and SKIP_SOLR=y. +ClamAV and Solr can be greedy with RAM. You may disable them in `mailcow.conf` by settings `SKIP_CLAMD=y` and `SKIP_SOLR=y`. + +**Info**: We are aware that a pure MTA can run on 128 MiB RAM. mailcow is a full-grown and ready-to-use groupware with many extras making life easier. mailcow comes with a webserver, webmailer, ActiveSync (MS), antivirus, antispam, indexing (Solr), document scanner (Oletools), SQL (MariaDB), Cache (Redis), MDA, MTA, various web services etc. + +A single SOGo worker **can** acquire ~350 MiB RAM before it gets purged. The more ActiveSync connections you plan to use, the more RAM you will need. A default configuration spawns 20 workers. + +#### Usage examples + +A company with 15 phones (EAS enabled) and about 50 concurrent IMAP connections should plan 16 GiB RAM. + +6 GiB RAM + 1 GiB swap are fine for most private installations while 8 GiB RAM are recommended for ~5 to 10 users. + +We can help to correctly plan your setup as part of our support. ## Firewall & Ports Please check if any of mailcow's standard ports are open and not in use by other applications: ``` -ss -tlpn | grep -E -w '25|80|110|143|443|465|587|993|995|4190' +ss -tlpn | grep -E -w '25|80|110|143|443|465|587|993|995|4190|5222|5269|5443' # or: -netstat -tulpn | grep -E -w '25|80|110|143|443|465|587|993|995|4190' +netstat -tulpn | grep -E -w '25|80|110|143|443|465|587|993|995|4190|5222|5269|5443' ``` !!! warning - There are several problems with running mailcow on a firewalld/ufw enabled system. You should disable it (if possible) and move your ruleset to the DOCKER-USER chain, which is not cleared by a Docker service restart, instead. See [this blog post](https://blog.donnex.net/docker-and-iptables-filtering/) for information about how to use iptables-persistent with the DOCKER-USER chain. + There are several problems with running mailcow on a firewalld/ufw enabled system. You should disable it (if possible) and move your ruleset to the DOCKER-USER chain, which is not cleared by a Docker service restart, instead. See [this (blog.donnex.net)](https://blog.donnex.net/docker-and-iptables-filtering/) or [this (unrouted.io)](https://unrouted.io/2017/08/15/docker-firewall/) guide for information about how to use iptables-persistent with the DOCKER-USER chain. As mailcow runs dockerized, INPUT rules have no effect on restricting access to mailcow. Use the FORWARD chain instead. -** - If this command returns any results please remove or stop the application running on that port. You may also adjust mailcows ports via the `mailcow.conf` configuration file. ### Default Ports If you have a firewall in front of mailcow, please make sure that these ports are open for incoming connections: -| Service | Protocol | Port | Container | Variable | -| --------------------|:--------:|:-------|:----------------|----------------------------------| -| Postfix SMTP | TCP | 25 | postfix-mailcow | `${SMTP_PORT}` | -| Postfix SMTPS | TCP | 465 | postfix-mailcow | `${SMTPS_PORT}` | -| Postfix Submission | TCP | 587 | postfix-mailcow | `${SUBMISSION_PORT}` | -| Dovecot IMAP | TCP | 143 | dovecot-mailcow | `${IMAP_PORT}` | -| Dovecot IMAPS | TCP | 993 | dovecot-mailcow | `${IMAPS_PORT}` | -| Dovecot POP3 | TCP | 110 | dovecot-mailcow | `${POP_PORT}` | -| Dovecot POP3S | TCP | 995 | dovecot-mailcow | `${POPS_PORT}` | -| Dovecot ManageSieve | TCP | 4190 | dovecot-mailcow | `${SIEVE_PORT}` | -| HTTP(S) | TCP | 80/443 | nginx-mailcow | `${HTTP_PORT}` / `${HTTPS_PORT}` | +| Service | Protocol | Port | Container | Variable | +| --------------------|:--------:|:-------|:------------------|----------------------------------| +| Postfix SMTP | TCP | 25 | postfix-mailcow | `${SMTP_PORT}` | +| Postfix SMTPS | TCP | 465 | postfix-mailcow | `${SMTPS_PORT}` | +| Postfix Submission | TCP | 587 | postfix-mailcow | `${SUBMISSION_PORT}` | +| Dovecot IMAP | TCP | 143 | dovecot-mailcow | `${IMAP_PORT}` | +| Dovecot IMAPS | TCP | 993 | dovecot-mailcow | `${IMAPS_PORT}` | +| Dovecot POP3 | TCP | 110 | dovecot-mailcow | `${POP_PORT}` | +| Dovecot POP3S | TCP | 995 | dovecot-mailcow | `${POPS_PORT}` | +| Dovecot ManageSieve | TCP | 4190 | dovecot-mailcow | `${SIEVE_PORT}` | +| HTTP(S) | TCP | 80/443 | nginx-mailcow | `${HTTP_PORT}` / `${HTTPS_PORT}` | To bind a service to an IP address, you can prepend the IP like this: `SMTP_PORT=1.2.3.4:25` **Important**: You cannot use IP:PORT bindings in HTTP_PORT and HTTPS_PORT. Please use `HTTP_PORT=1234` and `HTTP_BIND=1.2.3.4` instead. +### Important for Hetzner firewalls + +Quoting https://github.com/chermsen via https://github.com/mailcow/mailcow-dockerized/issues/497#issuecomment-469847380 (THANK YOU!): + +For all who are struggling with the Hetzner firewall: + +Port 53 unimportant for the firewall configuration in this case. According to the documentation unbound uses the port range 1024-65535 for outgoing requests. +Since the Hetzner Robot Firewall is a static firewall (each incoming packet is checked isolated) - the following rules must be applied: + +**For TCP** +``` +SRC-IP: --- +DST IP: --- +SRC Port: --- +DST Port: 1024-65535 +Protocol: tcp +TCP flags: ack +Action: Accept +``` + +**For UDP** +``` +SRC-IP: --- +DST IP: --- +SRC Port: --- +DST Port: 1024-65535 +Protocol: udp +Action: Accept +``` + +If you want to apply a more restrictive port range you have to change the config of unbound first (after installation): + +{mailcow-dockerized}/data/conf/unbound/unbound.conf: +``` +outgoing-port-avoid: 0-32767 +``` + +Now the firewall rules can be adjusted as follows: + +``` +[...] +DST Port: 32768-65535 +[...] +``` + ## Date and Time To ensure that you have the correct date and time setup on your system, please check the output of `timedatectl status`: diff --git a/docs/restrictions_ip_accss.md b/docs/restrictions_ip_accss.md new file mode 100644 index 000000000..f5ae09df4 --- /dev/null +++ b/docs/restrictions_ip_accss.md @@ -0,0 +1,15 @@ +_WIP_ + +# Protocol restrictions and IP access + +Denied access will be shown to the user as failed login attempts. + +## Protocol restrictions in Dovecot + +Protocol restrictions work by filtering the passdb query for IMAP and POP3 as well as reading the JSON value for %s_access where %s reflects the protocol seen by Dovecot. + +In the future we may use virtual colums in SQL to add an index on these values. + +## Protocol restrictions in Postfix + +Filtering SMTP protocol access works by using a check_sasl_map in the smtpd_recipient_restrictions. diff --git a/docs/third_party-borgmatic.md b/docs/third_party-borgmatic.md new file mode 100644 index 000000000..4d9de3d01 --- /dev/null +++ b/docs/third_party-borgmatic.md @@ -0,0 +1,247 @@ +# Borgmatic Backup + +## Introduction + +Borgmatic is a great way to run backups on your Mailcow setup as it securely encrypts your data and is extremely easy to +set up. + +Due to it's deduplication capabilities you can store a great number of backups without wasting large amounts of disk +space. This allows you to run backups in very short intervals to ensure minimal data loss when the need arises to +recover data from a backup. + +This document guides you through the process to enable continuous backups for mailcow with borgmatic. The borgmatic +functionality is provided by the [borgmatic Docker image by b3vis](https://github.com/b3vis/docker-borgmatic). Check out +the `README` in that repository to find out about the other options (such as push notifications) that are available. +This guide only covers the basics. + +## Setting up borgmatic + +### Create or amend `docker-compose.override.yml` + +In the mailcow-dockerized root folder create or edit `docker-compose.override.yml` and insert the following +configuration: + +```yaml +version: '2.1' +services: + borgmatic-mailcow: + image: b3vis/borgmatic + restart: always + dns: ${IPV4_NETWORK:-172.22.1}.254 + volumes: + - vmail-vol-1:/mnt/source/vmail:ro + - mysql-socket-vol-1:/var/run/mysqld/:z + - ./data/conf/borgmatic/etc:/etc/borgmatic.d:Z + - ./data/conf/borgmatic/state:/root/.config/borg:Z + - ./data/conf/borgmatic/ssh:/root/.ssh:Z + environment: + - TZ=${TZ} + - BORG_PASSPHRASE=YouBetterPutSomethingRealGoodHere + networks: + mailcow-network: + aliases: + - borgmatic +``` + +Ensure that you change the `BORG_PASSPHRASE` to a secure passphrase of your choosing. + +For security reasons we mount the maildir as read-only. If you later want to restore data you will need to remove +the `ro` flag prior to restoring the data. This is described in the section on restoring backups. + +### Create `data/conf/borgmatic/etc/config.yaml` + +Next, we need to create the borgmatic configuration. + +```shell +source mailcow.conf +cat < data/conf/borgmatic/etc/config.yaml +location: + source_directories: + - /mnt/source + repositories: + - user@rsync.net:mailcow + remote_path: borg1 + +retention: + keep_hourly: 24 + keep_daily: 7 + keep_weekly: 4 + keep_monthly: 6 + +hooks: + mysql_databases: + - name: ${DBNAME} + username: ${DBUSER} + password: ${DBPASS} + options: --default-character-set=utf8mb4 +EOF +``` + +Creating the file in this way ensures the correct MySQL credentials are pulled in from `mailcow.conf`. + +This file is a minimal example for using borgmatic with an account `user` on the cloud storage provider `rsync.net` for +a repository called `mailcow` (see `repositories` setting). It will backup both the maildir and MySQL database, which is +all you should need to restore your mailcow setup after an incident. The retention settings will keep one archive for +each hour of the past 24 hours, one per day of the week, one per week of the month and one per month of the past half +year. + +Check the [borgmatic documentation](https://torsion.org/borgmatic/) on how to use other types of repositories or +configuration options. If you choose to use a local filesystem as a backup destination make sure to mount it into the +container. The container defines a volume called `/mnt/borg-repository` for this purpose. + +!!! note + If you do not use rsync.net you can most likely drop the `remote_path` element from your config. + +### Create a crontab + +Create a new text file in `data/conf/borgmatic/etc/crontab.txt` with the following content: + +``` +14 * * * * PATH=$PATH:/usr/bin /usr/bin/borgmatic --stats -v 0 2>&1 +``` + +This file expects crontab syntax. The example shown here will trigger the backup to run every hour at 14 minutes past +the hour and log some nice stats at the end. + +### Place SSH keys in folder + +Place the SSH keys you intend to use for remote repository connections in `data/conf/borgmatic/ssh`. OpenSSH expects the +usual `id_rsa`, `id_ed25519` or similar to be in this directory. Ensure the file is `chmod 600` and not world readable +or OpenSSH will refuse to use the SSH key. + +### Bring up the container + +For the next step we need the container to be up and running in a configured state. To do that run: + +```shell +docker-compose up -d +``` + +### Initialize the repository + +By now your borgmatic container is up and running, but the backups will currently fail due to the repository not being +initialized. + +To initialize the repository run: + +```shell +docker-compose exec borgmatic-mailcow borgmatic init --encryption repokey-blake2 +``` + +You will be asked you to authenticate the SSH host key of your remote repository server. See if it matches and confirm +the prompt by entering `yes`. The repository will be initialized with the passphrase you set in the `BORG_PASSPHRASE` +environment variable earlier. + +When using any of the `repokey` encryption methods the encryption key will be stored in the repository itself and not on +the client, so there is no further action required in this regard. If you decide to use a `keyfile` instead of +a `repokey` make sure you export the key and back it up separately. Check the [Exporting Keys](#exporting-keys) section +for how to retrieve the key. + +### Restart container + +Now that we finished configuring and initializing the repository restart the container to ensure it is in a defined +state: + +```shell +docker-compose restart borgmatic-mailcow +``` + +## Restoring from a backup + +Restoring a backup assumes you are starting off with a fresh installation of mailcow, and you currently do not have +any custom data in your maildir or your mailcow database. + +### Restore maildir + +!!! warning + Doing this will overwrite files in your maildir! Do not run this unless you actually intend to recover mail + files from a backup. + +!!! note "If you use SELinux in Enforcing mode" + If you are using mailcow on a host with SELinux in Enforcing mode you will have to temporarily disable it during + extraction of the archive as the mailcow setup labels the vmail volume as private, belonging to the dovecot container + exclusively. SELinux will (rightfully) prevent any other container, such as the borgmatic container, from writing to + this volume. + +Before running a restore you must make the vmail volume writeable in `docker-compose.override.yml` by removing +the `ro` flag from the volume. +Then you can use the following command to restore the maildir from a backup: + +```shell +docker-compose exec borgmatic-mailcow borgmatic extract --path mnt/source --archive latest +``` + +Alternatively you can specify any archive name from the list of archives (see +[Listing all available archives](#listing-all-available-archives)) + +### Restore MySQL + +!!! warning + Running this command will delete and recreate the mailcow database! Do not run this unless you actually + intend to recover the mailcow database from a backup. + +To restore the MySQL database from the latest archive use this command: + +```shell +docker-compose exec borgmatic-mailcow borgmatic restore --archive latest +``` + +Alternatively you can specify any archive name from the list of archives (see +[Listing all available archives](#listing-all-available-archives)) + +### After restoring + +After restoring you need to restart mailcow. If you disabled SELinux enforcing mode now would be a good time to +re-enable it. + +To restart mailcow use the follwing command: + +```shell +docker-compose down && docker-compose up -d +``` + +If you use SELinux this will also trigger the re-labeling of all files in your vmail volume. Be patient, as this may +take a while if you have lots of files. + +## Useful commands + +### Manual archiving run (with debugging output) + +```shell +docker-compose exec borgmatic-mailcow borgmatic -v 2 +``` + +### Listing all available archives + +```shell +docker-compose exec borgmatic-mailcow borgmatic list +``` + +### Break lock + +When borg is interrupted during an archiving run it will leave behind a stale lock that needs to be cleared before any +new operations can be performed: + +```shell +docker-compose exec borgmatic-mailcow borg break-lock user@rsync.net:mailcow +``` + +Where `user@rsync.net:mailcow` is the URI to your repository. + +Now would be a good time to do a manual archiving run to ensure it can be successfully performed. + +### Exporting keys + +When using any of the `keyfile` methods for encryption you **MUST** take care of backing up the key files yourself. The +key files are generated when you initialize the repository. The `repokey` methods store the key file within the +repository, so a manual backup isn't as essential. + +Note that in either case you also must have the passphrase to decrypt any archives. + +To fetch the keyfile run: + +```shell +docker-compose exec borgmatic-mailcow borg key export --paper user@rsync.net:mailcow +``` + +Where `user@rsync.net:mailcow` is the URI to your repository. \ No newline at end of file diff --git a/docs/third_party-exchange_onprem.md b/docs/third_party-exchange_onprem.md new file mode 100644 index 000000000..be105b60c --- /dev/null +++ b/docs/third_party-exchange_onprem.md @@ -0,0 +1,42 @@ +Using Microsoft Exchange in a hybrid setup is possible with mailcow. With this setup you can add mailboxes on your mailcow and still use [Exchange Online Protection](https://docs.microsoft.com/microsoft-365/security/office-365-security/exchange-online-protection-overview?view=o365-worldwide). +**All mailboxes setup in Exchange will receive their mails as usual**, while with the hybrid approach additional Mailboxes can be setup in mailcow without any further configuration. + +This setup becomes very handy if you have enabled the [Office 365 security defaults](https://docs.microsoft.com/azure/active-directory/fundamentals/concept-fundamentals-security-defaults) and third party applications can no longer login into your mailboxes by any of the [supported methods](https://docs.microsoft.com/exchange/mail-flow-best-practices/how-to-set-up-a-multifunction-device-or-application-to-send-email-using-microsoft-365-or-office-365). + + +## Requirements +- The mx Record of your domain needs to point at the Exchange mail service. Log into your Admin center and look out for the dns settings of your domain to find your personalized gateway domain. It should look like this `contoso-com.mail.protection.outlook.com`. Contact your domain registrant to get further information on how to change mx record. +- The domain you want to have additional mailboxes for must be setup as `internal relay domain` in Exchange. + 1. Log in to your [Exchange Admin Center](https://admin.exchange.microsoft.com) + 2. Select the `mail flow` pane and click on `accepted domains` + 3. Select the domain and switch it from `authorative` to `internal relay` + + +## Set up the mailcow +Your mailcow needs to relay all mails to your personalized Exchange Host. It is the same host address we already looked up for the mx Record. + +1. Add the domain to your mailcow +2. [Add your personalized Exchange Host address as relayhost](/firststeps-relayhost) +3. Add your personalized Exchange Host address as forwarding host to unconditionally accepted all relayed mails from Exchange. (Admin > Configuration & Details > Configuration Dropdown > Forwarding Hosts) +4. Go to the domain settings and select the newly added host on the `Sender-dependent transports` dropdown. Enable relaying by ticking the `Relay this domain`, `Relay all recipients` and the `Relay non-existing mailboxes only.` checkboxes + +!!! info + From now on your mailcow will accept all mails relayed from Exchange. The **inbound filtering and so the neural learning of your cow will no longer work**. Because all mails are routed through Exchange the [filtering process is handled there](https://docs.microsoft.com/exchange/antispam-and-antimalware/antispam-and-antimalware?view=exchserver-2019). + + +## Set up Connectors in Exchange +All mail traffic now goes through Exchange. At this point the Exchange Online Protection already filters all incoming and outgoing mails. Now we need to set up two connectors to relay incoming mails from our Exchange Service to the mailcow and another one to allow mails relayed from the mailcow to our exchange service. You can follow the [official guide from Microsoft](https://docs.microsoft.com/exchange/mail-flow-best-practices/use-connectors-to-configure-mail-flow/set-up-connectors-to-route-mail#2-set-up-a-connector-from-microsoft-365-or-office-365-to-your-email-server). + +!!! warning + For the connector that handles mails from your mailcow to Exchange Microsoft offers two ways of authenticating it. The recommended way is to use a tls certificate configured with a subject name that matches an accepted domain in Exchange. Otherwise you need to choose authentication with the static ip address of your mailcow. + +## Validating +The easiest way to validate the hybrid setup is by sending a mail from the internet to a mailbox that only exists on the mailcow and vice versa. + +### Common Issues +- The connector validation from Exchange to your mailcow failed with `550 5.1.10 RESOLVER.ADR.RecipientNotFound; Recipient test@contoso.com not found by SMTP address lookup` +**Possible Solution:** Your domain is not set up as `internal relay`. Exchange therefore cannot find the recipient +- Mails sent from the mailcow to a mailbox in the internet cannot be sent. Non Delivery Report with error `550 5.7.64 TenantAttribution; Relay Access Denied` +**Possible Solution:** The authentication method failed. Make sure the certificate subject matches an accepted domain in Exchange. Try authenticating by static ip instead. + +Microsoft Guide for the connector setup and additional requirements: https://docs.microsoft.com/exchange/mail-flow-best-practices/use-connectors-to-configure-mail-flow/set-up-connectors-to-route-mail#prerequisites-for-your-on-premises-email-environment \ No newline at end of file diff --git a/docs/third_party-gitea.md b/docs/third_party-gitea.md index 92e20fcae..62f8bad42 100644 --- a/docs/third_party-gitea.md +++ b/docs/third_party-gitea.md @@ -33,11 +33,13 @@ GITEA_SSH_PORT=127.0.0.1:4000 5\. Run `docker-compose up -d` to bring up the gitea container and run `docker-compose restart nginx-mailcow` afterwards. -6\. Open `http://${MAILCOW_HOSTNAME}/gitea/`, for example `http://mx.example.org/gitea/`. For database details set `mysql` as database host. Use the value of DBNAME found in mailcow.conf as database name, DBUSER as database user and DBPASS as database password. +6\. If you forced mailcow to https, execute step 9 and restart gitea with `docker-compose restart gitea-mailcow` . Go head with step 7 (Remember to use https instead of http, `https://mx.example.org/gitea/` -7\. Once the installation is complete, login as admin and set "settings" -> "authorization" -> "enable SMTP". SMTP Host should be `postfix` with port `587`, set `Skip TLS Verify` as we are using an unlisted SAN ("postfix" is most likely not part of your certificate). +7\. Open `http://${MAILCOW_HOSTNAME}/gitea/`, for example `http://mx.example.org/gitea/`. For database details set `mysql` as database host. Use the value of DBNAME found in mailcow.conf as database name, DBUSER as database user and DBPASS as database password. -8\. Create `data/gitea/gitea/conf/app.ini` and set following values. You can consult [gitea cheat sheet](https://docs.gitea.io/en-us/config-cheat-sheet/) for their meaning and other possible values. +8\. Once the installation is complete, login as admin and set "settings" -> "authorization" -> "enable SMTP". SMTP Host should be `postfix` with port `587`, set `Skip TLS Verify` as we are using an unlisted SAN ("postfix" is most likely not part of your certificate). + +9\. Create `data/gitea/gitea/conf/app.ini` and set following values. You can consult [gitea cheat sheet](https://docs.gitea.io/en-us/config-cheat-sheet/) for their meaning and other possible values. ``` [server] @@ -49,4 +51,4 @@ SSH_PORT = 4000 ROOT_URL = https://mx.example.org/gitea/ ``` -9\. Restart gitea with `docker-compose restart gitea-mailcow`. Your users should be able to login with mailcow managed accounts. +10\. Restart gitea with `docker-compose restart gitea-mailcow`. Your users should be able to login with mailcow managed accounts. diff --git a/docs/u_e-mailpiler-integration.md b/docs/third_party-mailpiler_integration.md similarity index 90% rename from docs/u_e-mailpiler-integration.md rename to docs/third_party-mailpiler_integration.md index eaea027dd..c3e4f417b 100644 --- a/docs/u_e-mailpiler-integration.md +++ b/docs/third_party-mailpiler_integration.md @@ -2,6 +2,9 @@ This is a simple integration of mailcow aliases and the mailbox name into mailpi **Disclaimer**: This is not officially maintained nor supported by the mailcow project nor its contributors. No warranty or support is being provided, however you're free to open issues on GitHub for filing a bug or provide further ideas. [GitHub repo can be found here](https://github.com/patschi/mailpiler-mailcow-integration). +!!! info + Support for domain wildcards were implemented in Piler 1.3.10 which was released on 03.01.2021. Prior versions basically do work, but after logging in you won't see emails sent from or to the domain alias. (e.g. when @example.com is an alias for admin@example.com) + ## The problem to solve mailpiler offers the authentication based on IMAP, for example: @@ -30,7 +33,7 @@ Note: File paths might vary depending on your setup. ### Requirements - A working mailcow instance -- A working mailpiler instance ([You can find an installation guide here](https://patrik.kernstock.net/2020/08/mailpiler-installation-guide/)) +- A working mailpiler instance ([You can find an installation guide here](https://patrik.kernstock.net/2020/08/mailpiler-installation-guide/), [check supported versions here](https://github.com/patschi/mailpiler-mailcow-integration#piler)) - An mailcow API key (read-only works just fine): `Configuration & Details - Access - Read-Only Access`. Don't forget to allow API access from your mailpiler IP. !!! warning diff --git a/docs/third_party-nextcloud.md b/docs/third_party-nextcloud.md index 8d050de4f..31153440c 100644 --- a/docs/third_party-nextcloud.md +++ b/docs/third_party-nextcloud.md @@ -1,58 +1,105 @@ -NextCloud can be set up with the [helper script](https://github.com/mailcow/mailcow-dockerized/raw/master/helper-scripts/nextcloud.sh) included with mailcow. You can also set up NextCloud on a different server and still use mailcow for authentication. -In the following, we will only assume that you have already set up NextCloud at _cloud.example.com_ and that your mailcow is running at _mail.example.com_. -To set up authentication via mailcow, you can use OAuth2 as described below. +## Manage Nextcloud using the helper script -1. Log into mailcow as administrator. -2. Scroll down to _OAuth2 Apps_ and click the _Add_ button. Specify the redirect URI as `https://cloud.example.com/index.php/apps/sociallogin/custom_oauth2/Mailcow` and click _Add_. Save the client ID and secret for later. +Nextcloud can be set up (parameter `-i`) and removed (parameter `-p`) with the [helper script](https://github.com/mailcow/mailcow-dockerized/raw/master/helper-scripts/nextcloud.sh) included with mailcow. In order to install Nextcloud simply navigate to your mailcow-dockerized root folder and run the helper script as follows: + +`./helper-scripts/nextcloud.sh -i` + +In case you have forgotten the password (e.g. for admin) and can't request a new one [via the password reset link on the login screen](https://docs.nextcloud.com/server/20/admin_manual/configuration_user/reset_admin_password.html?highlight=reset) calling the helper script with `-r` as parameter allows you to set a new password. Only use this option if your Nextcloud isn't configured to use mailcow for authentication as described in the next section. + +## Configure Nextcloud to use mailcow for authentication + +The following describes how set up authentication via mailcow using the OAuth2 protocol. We will only assume that you have already set up Nextcloud at _cloud.example.com_ and that your mailcow is running at _mail.example.com_. It does not matter if your Nextcloud is running on a different server, you can still use mailcow for authentication. + +1\. Log into mailcow as administrator. + +2\. Scroll down to _OAuth2 Apps_ and click the _Add_ button. Specify the redirect URI as `https://cloud.example.com/index.php/apps/sociallogin/custom_oauth2/Mailcow` and click _Add_. Save the client ID and secret for later. !!! info Some installations, including those setup using the helper script of mailcow, need to remove index.php/ from the URL to get a successful redirect: `https://cloud.example.com/apps/sociallogin/custom_oauth2/Mailcow` -3. Log into NextCloud as administrator. -4. Click the button in the top right corner and select _Apps_. Click the search button in the toolbar, search for the [_Social Login_](https://apps.nextcloud.com/apps/sociallogin) plugin and click _Download and enable_ next to it. -5. Click the button in the top right corner and select _Settings_. Scroll down to the _Administration_ section on the left and click _Social login_. -6. Uncheck the following items: - - _Disable auto create new users_, - - _Allow users to connect social logins with their accounts_, - - _Do not prune not available user groups on login_, - - _Automatically create groups if they do not exists_, - - _Restrict login for users without mapped groups_, +3\. Log into Nextcloud as administrator. - and check the following items: - - _Prevent creating an account if the email address exists in another account_, - - _Update user profile every login_, - - _Disable notify admins about new users_. +4\. Click the button in the top right corner and select _Apps_. Click the search button in the toolbar, search for the [_Social Login_](https://apps.nextcloud.com/apps/sociallogin) plugin and click _Download and enable_ next to it. - Click the _Save_ button. +5\. Click the button in the top right corner and select _Settings_. Scroll down to the _Administration_ section on the left and click _Social login_. -7. Scroll down to _Custom OAuth2_ and click the _+_ button. -8. Configure the parameters as follows: - - Internal name: `Mailcow` - - Title: `Mailcow` - - API Base URL: `https://mail.example.com` - - Authorize URL: `https://mail.example.com/oauth/authorize` - - Token URL: `https://mail.example.com/oauth/token` - - Profile URL: `https://mail.example.com/oauth/profile` - - Logout URL: (leave blank) - - Client ID: (what you obtained in step 1) - - Client Secret: (what you obtained in step 1) - - Scope: `profile` +6\. Uncheck the following items: + +- "Disable auto create new users" +- "Allow users to connect social logins with their accounts" +- "Do not prune not available user groups on login" +- "Automatically create groups if they do not exists" +- "Restrict login for users without mapped groups" + +7\. Check the following items: + +- "Prevent creating an account if the email address exists in another account" +- "Update user profile every login" +- "Disable notify admins about new users" + +Click the _Save_ button. + +8\. Scroll down to _Custom OAuth2_ and click the _+_ button. +9\. Configure the parameters as follows: + +- Internal name: `Mailcow` +- Title: `Mailcow` +- API Base URL: `https://mail.example.com` +- Authorize URL: `https://mail.example.com/oauth/authorize` +- Token URL: `https://mail.example.com/oauth/token` +- Profile URL: `https://mail.example.com/oauth/profile` +- Logout URL: (leave blank) +- Client ID: (what you obtained in step 1) +- Client Secret: (what you obtained in step 1) +- Scope: `profile` Click the _Save_ button at the very bottom of the page. -If you have previously used NextCloud with mailcow authentication via user\_external/IMAP, you need to perform some additional steps to link your existing user accounts with OAuth2. +--- -1. Click the button in the top right corner and select _Apps_. Scroll down to the _External user authentication_ app and click _Remove_ next to it. -2. Run the following queries in your Nextcloud database (if you set up Nextcloud using mailcow's script, you can run `source mailcow.conf && docker-compose exec mysql-mailcow mysql -u$DBUSER -p$DBPASS $DBNAME`): +If you have previously used Nextcloud with mailcow authentication via user\_external/IMAP, you need to perform some additional steps to link your existing user accounts with OAuth2. + +1\. Click the button in the top right corner and select _Apps_. Scroll down to the _External user authentication_ app and click _Remove_ next to it. +2\. Run the following queries in your Nextcloud database (if you set up Nextcloud using mailcow's script, you can run `source mailcow.conf && docker-compose exec mysql-mailcow mysql -u$DBUSER -p$DBPASS $DBNAME`): ``` INSERT INTO nc_users (uid, uid_lower) SELECT DISTINCT uid, LOWER(uid) FROM nc_users_external; INSERT INTO nc_sociallogin_connect (uid, identifier) SELECT DISTINCT uid, CONCAT("Mailcow-", uid) FROM nc_users_external; ``` -If you have previously used NextCloud without mailcow authentication, but with the same usernames as mailcow, you can also link your existing user accounts with OAuth2. +--- -1. Run the following queries in your Nextcloud database (if you set up Nextcloud using mailcow's script, you can run `source mailcow.conf && docker-compose exec mysql-mailcow mysql -u$DBUSER -p$DBPASS $DBNAME`): +If you have previously used Nextcloud without mailcow authentication, but with the same usernames as mailcow, you can also link your existing user accounts with OAuth2. + +1\. Run the following queries in your Nextcloud database (if you set up Nextcloud using mailcow's script, you can run `source mailcow.conf && docker-compose exec mysql-mailcow mysql -u$DBUSER -p$DBPASS $DBNAME`): ``` INSERT INTO nc_sociallogin_connect (uid, identifier) SELECT DISTINCT uid, CONCAT("Mailcow-", uid) FROM nc_users; ``` + +--- + +## Update + +The Nextcloud instance can be updated easily with the web update mechanism. In the case of larger updates, there may be further changes to be made after the update. After the Nextcloud instance has been checked, problems are shown. This can be e.g. missing indices in the DB or similar. +It shows which commands have to be executed, these have to be placed in the php-fpm-mailcow container. + +As an an example run the following command to add the missing indices. +`docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "php /web/nextcloud/occ db:add-missing-indices"` + +--- + +## Debugging & Troubleshooting + +It may happen that you cannot reach the Nextcloud instance from your network. This may be due to the fact that the entry of your subnet in the array 'trusted_proxies' is missing. You can make changes in the Nextcloud config.php in `data/web/nextcloud/config/*`. + +``` +'trusted_proxies' => + array ( + 0 => 'fd4d:6169:6c63:6f77::/64', + 1 => '172.22.1.0/24', + 2 => 'NewSubnet/24', + ), +``` + +After the changes have been made, the nginx container must be restarted. +`docker-compose restart nginx-mailcow` diff --git a/docs/third_party-portainer.md b/docs/third_party-portainer.md index c3f4270d6..deebe9d79 100644 --- a/docs/third_party-portainer.md +++ b/docs/third_party-portainer.md @@ -5,7 +5,7 @@ In order to enable Portainer, the docker-compose.yml and site.conf for Nginx mus version: '2.1' services: portainer-mailcow: - image: portainer/portainer + image: portainer/portainer-ce volumes: - /var/run/docker.sock:/var/run/docker.sock - ./data/conf/portainer:/data diff --git a/docs/third_party-roundcube.md b/docs/third_party-roundcube.md index 50b708c0f..877c4273a 100644 --- a/docs/third_party-roundcube.md +++ b/docs/third_party-roundcube.md @@ -1,10 +1,10 @@ -Download Roundcube 1.4.x to the web htdocs directory and extract it (here `rc/`): +Download Roundcube 1.5.x to the web htdocs directory and extract it (here `rc/`): ``` # Check for a newer release! cd data/web -wget -O - https://github.com/roundcube/roundcubemail/releases/download/1.4.8/roundcubemail-1.4.8-complete.tar.gz | tar xfvz - +wget -O - https://github.com/roundcube/roundcubemail/releases/download/1.5-rc/roundcubemail-1.5-rc-complete.tar.gz | tar xfvz - # Change folder name -mv roundcubemail-1.4.8 rc +mv roundcubemail-1.5-rc rc # Change permissions chown -R root: rc/ ``` @@ -102,10 +102,10 @@ $config['password_query'] = "UPDATE mailbox SET password = %P WHERE username = % ### Integrate CardDAV addressbooks in Roundcube -Download the latest release of [RCMCardDAV](https://github.com/blind-coder/rcmcarddav/) to the Roundcube plugin directory and extract it (here `rc/plugins`): +Download the latest release of [RCMCardDAV](https://github.com/mstilkerich/rcmcarddav) to the Roundcube plugin directory and extract it (here `rc/plugins`): ``` cd data/web/rc/plugins -wget -O - https://github.com/blind-coder/rcmcarddav/releases/download/v3.0.3/carddav-3.0.3.tar.bz2 | tar xfvj - +wget -O - https://github.com/mstilkerich/rcmcarddav/releases/download/v4.1.2/carddav-v4.1.2.tar.gz | tar xfvz - chown -R root: carddav/ ``` diff --git a/docs/third_party-thunderbird.md b/docs/third_party-thunderbird.md index fa46e4525..8f018c9de 100644 --- a/docs/third_party-thunderbird.md +++ b/docs/third_party-thunderbird.md @@ -24,5 +24,5 @@ echo example.com example.org | ./build-plugins.sh mailcow.example.com # Install it in Thunderbird -After you have set up your mailcow IMAP account in Thunderbird, download the SOGo Connector plugin for your domain, e.g. https://mailcow.example.com/thunderbird-plugins/sogo-connector-68.0.0-example.com.xpi, and install it into Thunderbird. +After you have set up your mailcow IMAP account in Thunderbird, download the SOGo Connector plugin for your domain, e.g. https://mailcow.example.com/thunderbird-plugins/sogo-connector-68.0.1-example.com.xpi (see `data/web/thunderbird-plugins`), and install it into Thunderbird. All your address books and calendars will be configured automatically. diff --git a/docs/u_e-80_to_443.md b/docs/u_e-80_to_443.md index bfd486665..f18159782 100644 --- a/docs/u_e-80_to_443.md +++ b/docs/u_e-80_to_443.md @@ -2,7 +2,7 @@ Since February the 28th 2017 mailcow does come with port 80 and 443 enabled. **Do not use the config below for reverse proxy setups**, please see our reverse proxy guide for this, which includes a redirect from HTTP to HTTPS. -Open `mailcow.conf` and set `HTTP_BIND=0.0.0.0` - if not already set. +Open `mailcow.conf` and set `HTTP_BIND=` - if not already set. Create a new file `data/conf/nginx/redirect.conf` and add the following server config to the file: diff --git a/docs/u_e-change_config.md b/docs/u_e-change_config.md deleted file mode 100644 index 98b3cb391..000000000 --- a/docs/u_e-change_config.md +++ /dev/null @@ -1,68 +0,0 @@ -The most important configuration files are mounted from the host into the related containers: - -``` -data/conf -β”œβ”€β”€ unbound -β”‚Β Β  └── unbound.conf -β”œβ”€β”€ dovecot -β”‚Β Β  β”œβ”€β”€ dovecot.conf -β”‚Β Β  β”œβ”€β”€ dovecot-master.passwd -β”‚Β Β  β”œβ”€β”€ sieve_after -β”‚Β Β  └── sql -β”‚Β Β  β”œβ”€β”€ dovecot-dict-sql.conf -β”‚Β Β  └── dovecot-mysql.conf -β”œβ”€β”€ mysql -β”‚Β Β  └── my.cnf -β”œβ”€β”€ nginx -β”‚Β Β  β”œβ”€β”€ dynmaps.conf -β”‚Β Β  β”œβ”€β”€ site.conf -β”‚Β Β  └── templates -β”‚Β Β  β”œβ”€β”€ listen_plain.template -β”‚Β Β  β”œβ”€β”€ listen_ssl.template -β”‚Β Β  └── server_name.template -β”œβ”€β”€ postfix -β”‚Β Β  β”œβ”€β”€ main.cf -β”‚Β Β  β”œβ”€β”€ master.cf -β”‚Β Β  β”œβ”€β”€ postscreen_access.cidr -β”‚Β Β  β”œβ”€β”€ smtp_dsn_filter -β”‚Β Β  └── sql -β”‚Β Β  β”œβ”€β”€ mysql_relay_recipient_maps.cf -β”‚Β Β  β”œβ”€β”€ mysql_tls_enforce_in_policy.cf -β”‚Β Β  β”œβ”€β”€ mysql_tls_enforce_out_policy.cf -β”‚Β Β  β”œβ”€β”€ mysql_virtual_alias_domain_catchall_maps.cf -β”‚Β Β  β”œβ”€β”€ mysql_virtual_alias_domain_maps.cf -β”‚Β Β  β”œβ”€β”€ mysql_virtual_alias_maps.cf -β”‚Β Β  β”œβ”€β”€ mysql_virtual_domains_maps.cf -β”‚Β Β  β”œβ”€β”€ mysql_virtual_mailbox_maps.cf -β”‚Β Β  β”œβ”€β”€ mysql_virtual_relay_domain_maps.cf -β”‚Β Β  β”œβ”€β”€ mysql_virtual_sender_acl.cf -β”‚Β Β  └── mysql_virtual_spamalias_maps.cf -β”œβ”€β”€ rspamd -β”‚Β Β  β”œβ”€β”€ dynmaps -β”‚Β Β  β”‚Β Β  β”œβ”€β”€ authoritative.php -β”‚Β Β  β”‚Β Β  β”œβ”€β”€ settings.php -β”‚Β Β  β”‚Β Β  β”œβ”€β”€ tags.php -β”‚Β Β  β”‚Β Β  └── vars.inc.php -> ../../../web/inc/vars.inc.php -β”‚Β Β  β”œβ”€β”€ local.d -β”‚Β Β  β”‚Β Β  β”œβ”€β”€ dkim.conf -β”‚Β Β  β”‚Β Β  β”œβ”€β”€ metrics.conf -β”‚Β Β  β”‚Β Β  β”œβ”€β”€ options.inc -β”‚Β Β  β”‚Β Β  β”œβ”€β”€ redis.conf -β”‚Β Β  β”‚Β Β  β”œβ”€β”€ rspamd.conf.local -β”‚Β Β  β”‚Β Β  └── statistic.conf -β”‚Β Β  β”œβ”€β”€ lua -β”‚Β Β  β”‚Β Β  └── rspamd.local.lua -β”‚Β Β  └── override.d -β”‚Β Β  β”œβ”€β”€ logging.inc -β”‚Β Β  β”œβ”€β”€ worker-controller.inc -β”‚Β Β  └── worker-normal.inc -└── sogo - β”œβ”€β”€ sieve.creds - └── sogo.conf - -``` - -Just change the according configuration file on the host and restart the related service: -``` -docker-compose restart service-mailcow -``` diff --git a/docs/u_e-dovecot-expunge.md b/docs/u_e-dovecot-expunge.md index a3ab62f7e..5c1d3cedc 100644 --- a/docs/u_e-dovecot-expunge.md +++ b/docs/u_e-dovecot-expunge.md @@ -16,6 +16,12 @@ Delete **all** user's mails in the junk folder that are **older** than 7 days docker-compose exec dovecot-mailcow doveadm expunge -A mailbox 'Junk' savedbefore 7d ``` +Delete **all** mails (of all users) in **all** folders that are **older** than 52 weeks (internal date of the mail, not the date it was saved on the system => `before` instead of `savedbefore`). Useful for deleting very old mails on all users and folders (thus especially useful for GDPR-compliance). + +``` +docker-compose exec dovecot-mailcow doveadm expunge -A mailbox % before 52w +``` + Delete mails inside a custom folder **inside** a user's inbox that are **not** flagged and **older** than 2 weeks ``` @@ -25,7 +31,9 @@ docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mai !!! info For possible [time spans](https://wiki.dovecot.org/Tools/Doveadm/SearchQuery#section_date_specification) or [search keys](https://wiki.dovecot.org/Tools/Doveadm/SearchQuery#section_search_keys) have a look at [man doveadm-search-query](https://wiki.dovecot.org/Tools/Doveadm/SearchQuery) -## Make it automatic +## Job scheduler + +### via the host system cron If you want to automate such a task you can create a cron job on your host that calls a script like the one below: @@ -45,3 +53,41 @@ To create a cron job you may execute `crontab -e` and insert something like the # Execute everyday at 04:00 A.M. 0 4 * * * /path/to/your/expunge_mailboxes.sh ``` + +### via Docker job scheduler + +To archive this with a docker job scheduler use this docker-compose.override.yml with your mailcow: + +``` +version: '2.1' + +services: + + ofelia: + image: mcuadros/ofelia:latest + restart: always + command: daemon --docker + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + network_mode: none + + dovecot-mailcow: + labels: + - "ofelia.enabled=true" + - "ofelia.job-exec.dovecot-expunge-trash.schedule=0 4 * * *" + - "ofelia.job-exec.dovecot-expunge-trash.command=doveadm expunge -A mailbox 'Junk' savedbefore 2w" + - "ofelia.job-exec.dovecot-expunge-trash.tty=false" + +``` + +The job controller just need access to the docker control socket to be able to emulate the behavior of "exec". Then we add a few label to our dovecot-container to activate the job scheduler and tell him in a cron compatible scheduling format when to run. If you struggle with that schedule string you can use [crontab guru](https://crontab.guru/). +This docker-compose.override.yml deletes all mails older then 2 weeks from the "Junk" folder every day at 4 am. To see if things ran proper, you can not only see in your mailbox but also check Ofelia's docker log if it looks something like this: + +``` +common.go:124 β–Ά NOTICE [Job "dovecot-expunge-trash" (8759567efa66)] Started - doveadm expunge -A mailbox 'Junk' savedbefore 2w, +common.go:124 β–Ά NOTICE [Job "dovecot-expunge-trash" (8759567efa66)] Finished in "285.032291ms", failed: false, skipped: false, error: none, +``` + +If it failed it will say so and give you the output of the doveadm in the log to make it easy on you to debug. + +In case you want to add more jobs, ensure you change the "dovecot-expunge-trash" part after "ofelia.job-exec." to something else, it defines the name of the job. Syntax of the labels you find at [mcuadros/ofelia](https://github.com/mcuadros/ofelia). diff --git a/docs/u_e-dovecot-static_master.md b/docs/u_e-dovecot-static_master.md new file mode 100644 index 000000000..08c489a95 --- /dev/null +++ b/docs/u_e-dovecot-static_master.md @@ -0,0 +1,21 @@ +Random master usernames and passwords are automatically created on every restart of dovecot-mailcow. + +**That's recommended and should not be changed.** + +If you need the user to be static anyway, please specify two variables in `mailcow.conf`. + +**Both** parameters must not be empty! + +``` +DOVECOT_MASTER_USER=mymasteruser +DOVECOT_MASTER_PASS=mysecretpass +``` + +Run `docker-compose up -d` to apply your changes. + +The static master username will be expanded to `DOVECOT_MASTER_USER@mailcow.local`. + +To login as `test@example.org` this would equal to `test@example.org*mymasteruser@mailcow.local` with the specified password above. + +A login to SOGo is not possible with this username. A click-to-login function for SOGo is available for admins as described [here](https://mailcow.github.io/mailcow-dockerized-docs/debug-admin_login_sogo/) +No master user is required. diff --git a/docs/u_e-dovecot-vmail-volume.md b/docs/u_e-dovecot-vmail-volume.md index 80bdbcd7b..f5cf4fd2e 100644 --- a/docs/u_e-dovecot-vmail-volume.md +++ b/docs/u_e-dovecot-vmail-volume.md @@ -1,11 +1,29 @@ -If you want to use another folder for the vmail-volume, you can create an `docker-compose.override.yml` file and add: +## The "new" way + +**WARNING**: Newer Docker versions seem to complain about existing volumes. You can fix this temporarily by removing the existing volume and start mailcow with the override file. But it seems to be problematic after a reboot (needs to be confirmed). + +An easy, dirty, yet stable workaround is to stop mailcow (`docker-compose down`), remove `/var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data` and create a new link to your remote filesystem location, for example: + +``` +mv /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data_backup +ln -s /mnt/volume-xy/vmail_data /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data +``` + +Start mailcow afterwards. + +--- + +## The "old" way + +If you want to use another folder for the vmail-volume, you can create a `docker-compose.override.yml` file and add the following content: + ``` version: '2.1' volumes: vmail-vol-1: driver_opts: type: none - device: /data/mailcow/vmail + device: /data/mailcow/vmail o: bind ``` diff --git a/docs/u_e-fido2.md b/docs/u_e-fido2.md new file mode 100644 index 000000000..49dc78fb8 --- /dev/null +++ b/docs/u_e-fido2.md @@ -0,0 +1,15 @@ +## How is UV handled in mailcow? + +The UV flag (as in "user verification") enforces WebAuthn to verify the user before it allows access to the key (think of a PIN). We don't enforce UV to allow logins via iOS and NFC (YubiKey). + +## Login and key processing + +mailcow uses **client-side key processing**. We ask the authenticator (i.e. YubiKey) to save the registration in its memory. + +A user does not need to enter a username. The available credentials - if any - will be shown to the user when selecting the "key login" via mailcow UI login. + +When calling the login process, the authenticator is not given any credential IDs. This will force it to lookup credentials in its own memory. + +## Who can use WebAuthn to login to mailcow? + +As of today, only administrators and domain administrators are able to setup WebAuthn/FIDO2. diff --git a/docs/u_e-mailcow_ui-css.md b/docs/u_e-mailcow_ui-css.md new file mode 100644 index 000000000..77a23f5bb --- /dev/null +++ b/docs/u_e-mailcow_ui-css.md @@ -0,0 +1,3 @@ +For custom overrides of specific elements via CSS, use `data/web/css/build/0081-custom-mailcow.css`. + +The file is excluded from tracking and persists over updates. diff --git a/docs/u_e-mailcow_ui-tfa.md b/docs/u_e-mailcow_ui-tfa.md index 4e694e071..58e25c61f 100644 --- a/docs/u_e-mailcow_ui-tfa.md +++ b/docs/u_e-mailcow_ui-tfa.md @@ -1,10 +1,10 @@ -So far three methods for *Two-Factor Authentication* are implemented: U2F, Yubi OTP, and TOTP +So far three methods for _Two-Factor Authentication_ are implemented: U2F, Yubi OTP, and TOTP -- For U2F to work, you need an encrypted connection to the server (HTTPS) as well as a FIDO security key. -- Both U2F and Yubi OTP work well with the fantastic [Yubikey](https://www.yubico.com). -- While Yubi OTP needs an active internet connection and an API ID + key, U2F will work with any FIDO U2F USB key out of the box, but can only be used when mailcow is accessed over HTTPS. -- U2F and Yubi OTP support multiple keys per user. -- As the third TFA method mailcow uses TOTP: time-based one-time passwords. Those passwords can be generated with apps like "Google Authenticator" after initially scanning a QR code or entering the given secret manually. +- For U2F to work, you need an encrypted connection to the server (HTTPS) as well as a FIDO security key. +- Both U2F and Yubi OTP work well with the fantastic [Yubikey](https://www.yubico.com). +- While Yubi OTP needs an active internet connection and an API ID + key, U2F will work with any FIDO U2F USB key out of the box, but can only be used when mailcow is accessed over HTTPS. +- U2F and Yubi OTP support multiple keys per user. +- As the third TFA method mailcow uses TOTP: time-based one-time passwords. Those passwords can be generated with apps like "Google Authenticator" after initially scanning a QR code or entering the given secret manually. As administrator you are able to temporary disable a domain administrators TFA login until they successfully logged in. @@ -19,8 +19,22 @@ The API ID, API key and the first 12 characters (your YubiKeys ID in modhex) are ### U2F -Only Google Chrome (+derivatives) and Opera support U2F authentication to this day natively. -Since version 67 Mozilla Firefox can handle U2F natively. ([Source](https://support.yubico.com/support/solutions/articles/15000017511-enabling-u2f-support-in-mozilla-firefox)) +To use U2F, the browser must support this standard. + +The following desktop browsers support this authentication type: + +- Edge (>=79) +- Firefox (>=47, enabled by default since version 67) +- Chrome (>=41) +- Safari (>=13) +- Opera (40, >=42, not 41) + +The following mobile browsers support this authentication type: + +- Safari on iOS (>=13.3) +- Firefox on Android (>=68) + +Sources: [caniuse.com](https://caniuse.com/u2f), [blog.mozilla.org](https://blog.mozilla.org/security/2019/08/05/web-authentication-in-firefox-for-android/) U2F works without an internet connection. diff --git a/docs/u_e-nginx.md b/docs/u_e-nginx.md index ee975b754..b82081aea 100644 --- a/docs/u_e-nginx.md +++ b/docs/u_e-nginx.md @@ -1,25 +1,46 @@ +## SSL + +Please see [Advanced SSL](https://mailcow.github.io/mailcow-dockerized-docs/firststeps-ssl/) and explicitly check `ADDITIONAL_SERVER_NAMES` for SSL configuration. + +Please do not add ADDITIONAL_SERVER_NAMES when you plan to use a different web root. + +## New site + To create persistent (over updates) sites hosted by mailcow: dockerized, a new site configuration must be placed inside `data/conf/nginx/`: +A good template to begin with: + ``` nano data/conf/nginx/my_custom_site.conf ``` -A good template to begin with: - -``` hl_lines="9" +``` hl_lines="16" server { ssl_certificate /etc/ssl/mail/cert.pem; ssl_certificate_key /etc/ssl/mail/key.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305; + ssl_ecdh_curve X25519:X448:secp384r1:secp256k1; + ssl_session_cache shared:SSL:50m; + ssl_session_timeout 1d; + ssl_session_tickets off; index index.php index.html; client_max_body_size 0; + # Location: data/web root /web; + # Location: data/web/mysite.com + #root /web/mysite.com include /etc/nginx/conf.d/listen_plain.active; include /etc/nginx/conf.d/listen_ssl.active; server_name mysite.example.org; + server_tokens off; + # This allows acme to be validated even with a different web root location ^~ /.well-known/acme-challenge/ { - allow all; default_type "text/plain"; + rewrite /.well-known/acme-challenge/(.*) /$1 break; + root /web/.well-known/acme-challenge/; } if ($scheme = http) { @@ -28,7 +49,56 @@ server { } ``` -The filename is not important, as long as the filename carries a .conf extension. +## New site with proxy to a remote location + +Another example with a reverse proxy configuration: + +``` +nano data/conf/nginx/my_custom_site.conf +``` + +``` hl_lines="16 28" +server { + ssl_certificate /etc/ssl/mail/cert.pem; + ssl_certificate_key /etc/ssl/mail/key.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305; + ssl_ecdh_curve X25519:X448:secp384r1:secp256k1; + ssl_session_cache shared:SSL:50m; + ssl_session_timeout 1d; + ssl_session_tickets off; + index index.php index.html; + client_max_body_size 0; + root /web; + include /etc/nginx/conf.d/listen_plain.active; + include /etc/nginx/conf.d/listen_ssl.active; + server_name example.domain.tld; + server_tokens off; + + location ^~ /.well-known/acme-challenge/ { + allow all; + default_type "text/plain"; + } + + if ($scheme = http) { + return 301 https://$host$request_uri; + } + + location / { + proxy_pass http://service:3000/; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + client_max_body_size 0; + } +} +``` + +## Config expansion in mailcows Nginx + +The filename used for a new site is not important, as long as the filename carries a .conf extension. It is also possible to extend the configuration of the default file `site.conf` file: @@ -36,7 +106,7 @@ It is also possible to extend the configuration of the default file `site.conf` nano data/conf/nginx/site.my_content.custom ``` -This filename does not need to have a ".conf" extension, but follows the pattern `site.*.custom`, where `*` is a custom name. +This filename does not need to have a ".conf" extension but follows the pattern `site.*.custom`, where `*` is a custom name. If PHP is to be included in a custom site, please use the PHP-FPM listener on phpfpm:9002 or create a new listener in `data/conf/phpfpm/php-fpm.d/pools.conf`. @@ -46,3 +116,4 @@ Restart Nginx (and PHP-FPM, if a new listener was created): docker-compose restart nginx-mailcow docker-compose restart php-fpm-mailcow ``` + diff --git a/docs/u_e-postfix-postscreen_whitelist.md b/docs/u_e-postfix-postscreen_whitelist.md index 2104dfb31..62aea3753 100644 --- a/docs/u_e-postfix-postscreen_whitelist.md +++ b/docs/u_e-postfix-postscreen_whitelist.md @@ -1,3 +1,20 @@ -IPs can be removed from Postscreen and therefore _also_ from RBL checks in `data/conf/postfix/custom_postscreen_whitelist.cidr`. - -Postscreen does multiple checks to identify malicious senders. In most cases you want to whitelist an IP to exclude it from blacklist lookups. +IPs can be removed from Postscreen and therefore _also_ from RBL checks in `data/conf/postfix/custom_postscreen_whitelist.cidr`. + +Postscreen does multiple checks to identify malicious senders. In most cases you want to whitelist an IP to exclude it from blacklist lookups. + +The format of the file is as follows: + +`CIDR ACTION` + +Where CIDR is a single IP address or IP range in CIDR notation, and action is either "permit" or "reject". + +Example: + +``` +# Rules are evaluated in the order as specified. +# Blacklist 192.168.* except 192.168.0.1. +192.168.0.1 permit +192.168.0.0/16 reject +``` + +The file is reloaded on the fly, postfix restart is not required. \ No newline at end of file diff --git a/docs/u_e-rspamd.md b/docs/u_e-rspamd.md index 545cd82d6..a3f15b2cb 100644 --- a/docs/u_e-rspamd.md +++ b/docs/u_e-rspamd.md @@ -3,12 +3,14 @@ Rspamd is used for AV handling, DKIM signing and SPAM handling. It's a powerful ## Learn Spam & Ham Rspamd learns mail as spam or ham when you move a message in or out of the junk folder to any mailbox besides trash. -This is achieved by using the Dovecot plugin "antispam" and a simple parser script. +This is achieved by using the Sieve plugin "sieve_imapsieve" and parser scripts. -Rspamd also auto-learns mail when a high or low score is detected (see https://rspamd.com/doc/configuration/statistic.html#autolearning) +Rspamd also auto-learns mail when a high or low score is detected (see https://rspamd.com/doc/configuration/statistic.html#autolearning). We configured the plugin to keep a sane ratio between spam and ham learns. The bayes statistics are written to Redis as keys `BAYES_HAM` and `BAYES_SPAM`. +Besides bayes, a local fuzzy storage is used to learn recurring patterns in text or images that indicate ham or spam. + You can also use Rspamd's web UI to learn ham and / or spam or to adjust certain settings of Rspamd. ### Learn Spam or Ham from existing directory @@ -128,20 +130,20 @@ reject_message = "My custom reject message"; Save the file and restart Rspamd: `docker-compose restart rspamd-mailcow`. -While the above works for rejected mails with a high spam score, global maps (as found in "Global filter maps" in /admin) will ignore this setting. For these maps, the multimap module in Rspamd needs to be adjusted: +While the above works for rejected mails with a high spam score, prefilter reject actions will ignore this setting. For these maps, the multimap module in Rspamd needs to be adjusted: -1. Open `{mailcow-dir}/data/conf/rspamd/local.d/multimap.conf` and find the desired map symbol (e.g. `GLOBAL_SMTP_FROM_BL`). +1. Find prefilet reject symbol for which you want change message, to do it run: `grep -R "SYMBOL_YOU_WANT_TO_ADJUST" /opt/mailcow-dockerized/data/conf/rspamd/` 2. Add your custom message as new line: ``` -GLOBAL_SMTP_FROM_BL { - type = "from"; - message = "Your domain is blacklisted, contact postmaster@your.domain to resolve this case.";` - map = "$LOCAL_CONFDIR/custom/global_smtp_from_blacklist.map"; +GLOBAL_RCPT_BL { + type = "rcpt"; + map = "${LOCAL_CONFDIR}/custom/global_rcpt_blacklist.map"; regexp = true; prefilter = true; action = "reject"; + message = "Sending mail to this recipient is prohibited by postmaster@your.domain"; } ``` @@ -210,3 +212,31 @@ Restart Rspamd: ```bash docker-compose exec redis-mailcow sh ``` + +## Trigger a resend of quarantine notifications + +Should be used for debugging only! + +``` +docker-compose exec dovecot-mailcow bash +mysql -umailcow -p$DBPASS mailcow -e "update quarantine set notified = 0;" +redis-cli -h redis DEL Q_LAST_NOTIFIED +quarantine_notify.py +``` + +## Increase history retention + +By default Rspamd keeps 1000 elements in the history. + +The history is stored compressed. + +It is recommended not to use a disproportionate high value here, try something along 5000 or 10000 and see how your server handles it: + +Edit `data/conf/rspamd/local.d/history_redis.conf`: + +``` +nrows = 1000; # change this value +``` + +Restart Rspamd afterwards: `docker-compose restart rspamd-mailcow` + diff --git a/docs/u_e-sogo.md b/docs/u_e-sogo.md index aead9520b..3fde37361 100644 --- a/docs/u_e-sogo.md +++ b/docs/u_e-sogo.md @@ -1,11 +1,49 @@ SOGo is used for accessing your mails via a webbrowser, adding and sharing your contacts or calendars. For a more in-depth documentation on SOGo please visit its [own documentation](http://wiki.sogo.nu/). -## Change Theme -As of December 21 2018 we removed our custom themes due to complains about missing colors in some address book and calendar sections. Some other problems were still existing and would not be fixed in the near future (switching colors on login screen, for example). +## Apply custom SOGo theme +mailcow builds after 28 January 2021 can change SOGo's theme by editing `data/conf/sogo/custom-theme.js`. +Please check the AngularJS Material [intro](https://material.angularjs.org/latest/Theming/01_introduction) and [documentation](https://material.angularjs.org/latest/Theming/03_configuring_a_theme) as well as the [material style guideline](https://material.io/archive/guidelines/style/color.html#color-color-palette) to learn how this works. -## Change Logo -mailcow builds after 21 December 2018 can change SOGo's logo by replacing `data/conf/sogo/sogo-full.svg`. +You can use the provided `custom-theme.js` as an example starting point by removing the comments. +After you modified `data/conf/sogo/custom-theme.js` and made changes to your new SOGo theme you need to + +* edit `data/conf/sogo/sogo.conf` and append/set `SOGoUIxDebugEnabled = YES;` +* restart SOGo and Memcached containers by executing `docker-compose restart memcached-mailcow sogo-mailcow`. + +## Reset to SOGo default theme +Checkout `data/conf/sogo/custom-theme.js` by executing `git fetch ; git checkout origin/master data/conf/sogo/custom-theme.js data/conf/sogo/custom-theme.js` +Find in `data/conf/sogo/custom-theme.js`: +``` +// Apply new palettes to the default theme, remap some of the hues + $mdThemingProvider.theme('default') + .primaryPalette('green-cow', { + 'default': '400', // background color of top toolbars + 'hue-1': '400', + 'hue-2': '600', // background color of sidebar toolbar + 'hue-3': 'A700' + }) + .accentPalette('green', { + 'default': '600', // background color of fab buttons and login screen + 'hue-1': '300', // background color of center list toolbar + 'hue-2': '300', // highlight color for selected mail and current day calendar + 'hue-3': 'A700' + }) + .backgroundPalette('frost-grey'); +``` +and replace with: +``` + $mdThemingProvider.theme('default'); +``` + +## Change favicon +mailcow builds after 31 January 2021 can change SOGo's favicon by replacing `data/conf/sogo/custom-favicon.ico` for SOGo and `data/web/favicon.png` for mailcow UI. +**Note**: You can use `.png` favicons for SOGo by renaming them to `custom-favicon.ico`. +For both SOGo and mailcow UI favicons you need use one of the standard dimensions: 16x16, 32x32, 64x64, 128x128 and 256x256. +After you replaced said file you need to restart SOGo and Memcached containers by executing `docker-compose restart memcached-mailcow sogo-mailcow`. + +## Change logo +mailcow builds after 21 December 2018 can change SOGo's logo by replacing or creating (if missing) `data/conf/sogo/sogo-full.svg`. After you replaced said file you need to restart SOGo and Memcached containers by executing `docker-compose restart memcached-mailcow sogo-mailcow`. ## Connect domains @@ -34,5 +72,5 @@ Restart SOGo: `docker-compose restart sogo-mailcow` Edit `data/conf/sogo/sogo.conf` and **change** `SOGoPasswordChangeEnabled` to `NO`. Please do not add a new parameter. -Run `docker-compose restart sogo-mailcow memcached-mailcow` to activate the changes. +Run `docker-compose restart memcached-mailcow sogo-mailcow` to activate the changes. diff --git a/docs/u_e-unbound-fwd.md b/docs/u_e-unbound-fwd.md index b8caaf616..e4a64f612 100644 --- a/docs/u_e-unbound-fwd.md +++ b/docs/u_e-unbound-fwd.md @@ -11,8 +11,8 @@ Edit `data/conf/unbound/unbound.conf` and append the following parameters: ``` forward-zone: name: "." - forward-addr: 8.8.8.8 # NO NOT USE PUBLIC DNS SERVERS - JUST AN EXAMPLE - forward-addr: 8.8.4.4 # NO NOT USE PUBLIC DNS SERVERS - JUST AN EXAMPLE + forward-addr: 8.8.8.8 # DO NOT USE PUBLIC DNS SERVERS - JUST AN EXAMPLE + forward-addr: 8.8.4.4 # DO NOT USE PUBLIC DNS SERVERS - JUST AN EXAMPLE ``` Restart Unbound: diff --git a/docs/u_e-update-hooks.md b/docs/u_e-update-hooks.md new file mode 100644 index 000000000..1d61bbe1c --- /dev/null +++ b/docs/u_e-update-hooks.md @@ -0,0 +1,10 @@ +It is possible to add pre- and post-update-hooks to the `update.sh` script that upgrades your whole mailcow installation. + +To do so, just add the corresponding bash script into your mailcows root directory: + +* `pre_update_hook.sh` for commands that should run before the update +* `post_uddate_hook.sh` for commands that should run after the update is completed + +Keep in mind that `pre_update_hook.sh` runs every time you call `update.sh` and `post_update_hook.sh` will only run if the update was successful and the script doesn't have to be re-run. + +The scripts will be run by bash, an interpreter (e.g. `#!/bin/bash`) as well as an execute permission flag ("+x") are not required. diff --git a/docs/u_e-webmail-site.md b/docs/u_e-webmail-site.md index 83b4777a0..f04de862f 100644 --- a/docs/u_e-webmail-site.md +++ b/docs/u_e-webmail-site.md @@ -1,4 +1,4 @@ -**Edit**: TODO: This guide only applies to non SNI enabled configurations. The certificate path needs to be adjusted if SNI is enabled. Something like `ssl_certificate,key /etc/ssl/mail/webmail.example.org/cert.pem,key.pem;` will do. **But**: The certificate should be acquired **first** and only after the certificate exists a site config should be created. Nginx will fail to start if it cannot find the certificate and key. +**IMPORTANT**: This guide only applies to non SNI enabled configurations. The certificate path needs to be adjusted if SNI is enabled. Something like `ssl_certificate,key /etc/ssl/mail/webmail.example.org/cert.pem,key.pem;` will do. **But**: The certificate should be acquired **first** and only after the certificate exists a site config should be created. Nginx will fail to start if it cannot find the certificate and key. To create a subdomain `webmail.example.org` and redirect it to SOGo, you need to create a **new** Nginx site. Take care of "CHANGE_TO_MAILCOW_HOSTNAME"! @@ -14,7 +14,7 @@ server { include /etc/nginx/conf.d/listen_plain.active; include /etc/nginx/conf.d/listen_ssl.active; server_name webmail.example.org; - + server_tokens off; location ^~ /.well-known/acme-challenge/ { allow all; default_type "text/plain"; diff --git a/mkdocs.yml b/mkdocs.yml index 86d4f81fe..3f3a7bf0a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,11 +1,14 @@ -site_name: 'mailcow: dockerized documentation' +site_name: "mailcow: dockerized documentation" site_url: https://mailcow.github.io/mailcow-dockerized-docs/ -copyright: 'Copyright © 2020 AndrΓ© Peters' +copyright: "Copyright © 2021 AndrΓ© Peters" repo_name: mailcow/mailcow-dockerized repo_url: https://github.com/mailcow/mailcow-dockerized edit_uri: ../mailcow-dockerized-docs/edit/master/docs/ remote_branch: gh-pages -theme: material +theme: + name: material + logo: images/logo.svg + favicon: images/favicon.png markdown_extensions: - codehilite: guess_lang: true @@ -20,32 +23,34 @@ markdown_extensions: - pymdownx.extra - footnotes nav: -- 'Information & Support': 'index.md' -- 'Prerequisites': - - 'Prepare your system': 'prerequisite-system.md' - - 'DNS setup': 'prerequisite-dns.md' -- 'Installation, Update & Migration': - - 'Installation': 'i_u_m_install.md' - - 'Update': 'i_u_m_update.md' - - 'Migration': 'i_u_m_migration.md' -- 'First Steps (optional)': - - 'Untrust RFC 1918': 'firststeps-rfc-1918.md' - - 'Advanced SSL': 'firststeps-ssl.md' - - 'Rspamd UI': 'firststeps-rspamd_ui.md' - - 'DMARC Reporting': 'firststeps-dmarc_reporting.md' - - 'Reverse Proxy': 'firststeps-rp.md' - - 'SNAT': 'firststeps-snat.md' - - 'Disable IPv6': 'firststeps-disable_ipv6.md' - - 'Relayhosts': 'firststeps-relayhost.md' - - 'Logging': 'firststeps-logging.md' - - 'Local MTA on Docker host': 'firststeps-local_mta.md' - - 'Sync job migration': 'firststeps-sync_jobs_migration.md' - - 'IP bindings': 'firststeps-ip_bindings.md' -- 'Models': - - 'Sender and receiver model': 'model-sender_rcv.md' - - 'ACL': 'model-acl.md' -- 'Debugging & Troubleshooting': - - 'Introduction': debug.md + - 'Information & Support': 'index.md' + - 'Prerequisites': + - 'Prepare your system': 'prerequisite-system.md' + - 'DNS setup': 'prerequisite-dns.md' + - 'Installation, Update & Migration': + - 'Installation': 'i_u_m_install.md' + - 'Update': 'i_u_m_update.md' + - 'Migration': 'i_u_m_migration.md' + - 'Deinstallation': 'i_u_m_deinstall.md' + - 'Post Installation Tasks': + - 'Advanced SSL': 'firststeps-ssl.md' + - 'Disable IPv6': 'firststeps-disable_ipv6.md' + - 'IP bindings': 'firststeps-ip_bindings.md' + - 'Local MTA on Docker host': 'firststeps-local_mta.md' + - 'Logging': 'firststeps-logging.md' + - 'Relayhosts': 'firststeps-relayhost.md' + - 'Reverse Proxy': 'firststeps-rp.md' + - 'Rspamd UI': 'firststeps-rspamd_ui.md' + - 'DMARC Reporting': 'firststeps-dmarc_reporting.md' + - 'SNAT': 'firststeps-snat.md' + - 'Sync job migration': 'firststeps-sync_jobs_migration.md' + - 'Add trusted networks': 'firststeps-trust_networks.md' + - 'Models': + - 'ACL': 'model-acl.md' + - 'Password hashing': 'model-passwd.md' + - 'Sender and receiver model': 'model-sender_rcv.md' + - 'General Troubleshooting': + - 'Introduction': 'debug.md' - 'Logs': 'debug-logs.md' - 'Attach a Container': 'debug-attach_service.md' - 'Reset Passwords (incl. SQL)': 'debug-reset_pw.md' @@ -53,85 +58,95 @@ nav: - 'Remove Persistent Data': 'debug-rm_volumes.md' - 'Common Problems': 'debug-common_problems.md' - 'Admin login to SOGo': 'debug-admin_login_sogo.md' -- 'Backup & Restore': - - 'Helper script': + - 'Reset TLS certificates': 'debug-reset-tls.md' + - 'Backup & Restore': + - 'Helper script': - 'Backup': 'b_n_r_backup.md' - 'Restore': 'b_n_r_restore.md' - - 'Manually': + - 'Manually': - 'Maildir': 'u_e-backup_restore-maildir.md' - 'MySQL': 'u_e-backup_restore-mysql.md' -- 'Usage & Examples': - - 'mailcow UI': + - 'Automatic backups': + - 'Recover accidentally deleted data': 'b_n_r_accidental_deletion.md' + - 'Manual/Guides/Examples': + - 'mailcow UI': - 'Configuration': 'u_e-mailcow_ui-config.md' + - 'CSS overrides': 'u_e-mailcow_ui-css.md' - 'Blacklist / Whitelist': 'u_e-mailcow_ui-bl_wl.md' - 'Pushover': 'u_e-mailcow_ui-pushover.md' - 'Spamfilter': 'u_e-mailcow_ui-spamfilter.md' - 'Temporary email aliases': 'u_e-mailcow_ui-spamalias.md' - 'Tagging': 'u_e-mailcow_ui-tagging.md' - 'Two-Factor Authentication': 'u_e-mailcow_ui-tfa.md' - - 'Postfix': - - 'Custom transport maps': 'u_e-postfix-custom_transport.md' + - 'WebAuthn / FIDO2': 'u_e-fido2.md' + - 'Postfix': + - 'Custom transport maps': 'u_e-postfix-custom_transport.md' - 'Whitelist IP in Postscreen': 'u_e-postfix-postscreen_whitelist.md' - 'Customize/Expand main.cf': 'u_e-postfix-extra_cf.md' - 'Disable Sender Addresses Verification': 'u_e-postfix-disable_sender_verification.md' - 'Max. message size (attachment size)': 'u_e-postfix-attachment_size.md' - 'Statistics with pflogsumm': 'u_e-postfix-pflogsumm.md' - - 'Unbound': + - 'Unbound': - 'Using an external DNS service': 'u_e-unbound-fwd.md' - - 'Dovecot': + - 'Dovecot': - 'Enable "any" ACL settings': 'u_e-dovecot-any_acl.md' - - 'Public folders': 'u_e-dovecot-public_folder.md' - 'Expunge a Users mails': 'u_e-dovecot-expunge.md' - 'Customize/Expand dovecot.conf': 'u_e-dovecot-extra_conf.md' + - 'FTS (Solr)': 'u_e-dovecot-fts.md' + - 'IMAP IDLE interval': 'u_e-dovecot-idle_interval.md' - 'Mail crypt': 'u_e-dovecot-mail-crypt.md' - 'More Examples with DOVEADM': 'u_e-dovecot-more.md' - - 'Move vmail volume': 'u_e-dovecot-vmail-volume.md' - - 'IMAP IDLE interval': 'u_e-dovecot-idle_interval.md' - - 'FTS (Solr)': 'u_e-dovecot-fts.md' - - 'Nginx': - - 'Custom sites': 'u_e-nginx.md' - - 'Create subdomain webmail.example.org': 'u_e-webmail-site.md' - - 'Redis': 'u_e-redis.md' - - 'Rspamd': 'u_e-rspamd.md' - - 'SOGo': 'u_e-sogo.md' - - 'Docker': + - 'Move Maildir (vmail)': 'u_e-dovecot-vmail-volume.md' + - 'Public folders': 'u_e-dovecot-public_folder.md' + - 'Static master user': 'u_e-dovecot-static_master.md' + - 'Nginx': + - 'Custom sites': 'u_e-nginx.md' + - 'Create subdomain webmail.example.org': 'u_e-webmail-site.md' + - 'Redis': 'u_e-redis.md' + - 'Rspamd': 'u_e-rspamd.md' + - 'SOGo': 'u_e-sogo.md' + - 'Docker': - 'Customize Dockerfiles': 'u_e-docker-cust_dockerfiles.md' - 'Docker Compose Bash Completion': 'u_e-docker-dc_bash_compl.md' - - 'Why unbound?': 'u_e-why_unbound.md' - - 'Autodiscover / Autoconfig': 'u_e-autodiscover_config.md' - - 'Redirect HTTP to HTTPS': 'u_e-80_to_443.md' - - 'Adjust Service Configurations': 'u_e-change_config.md' - - 'Deinstall': 'u_e-deinstall.md' - - 'Re-enable TLS 1.0 and TLS 1.1': 'u_e-reeanble-weak-protocols.md' - - 'Mailpiler Integration': 'u_e-mailpiler-integration.md' -- 'Client Configuration': - - 'Overview': 'client.md' - - 'Android': 'client/client-android.md' - - 'Apple macOS / iOS': 'client/client-apple.md' - - 'eM Client': 'client/client-emclient.md' - - 'KDE Kontact': 'client/client-kontact.md' - - 'Microsoft Outlook': 'client/client-outlook.md' - - 'Mozilla Thunderbird': 'client/client-thunderbird.md' - - 'Windows Mail': 'client/client-windows.md' - - 'Windows Phone': 'client/client-windowsphone.md' - - 'Manual configuration': 'client/client-manual.md' -- 'Third party apps': - - 'SOGo Connector for Thunderbird': 'third_party-thunderbird.md' - - 'Roundcube': 'third_party-roundcube.md' - - 'Portainer': 'third_party-portainer.md' - - 'Gogs': 'third_party-gogs.md' - - 'Gitea': 'third_party-gitea.md' - - 'Nextcloud': 'third_party-nextcloud.md' -icon: - logo: 'images/logo.svg' + - 'Why unbound?': 'u_e-why_unbound.md' + - 'Autodiscover / Autoconfig': 'u_e-autodiscover_config.md' + - 'Redirect HTTP to HTTPS': 'u_e-80_to_443.md' + - 'Re-enable TLS 1.0 and TLS 1.1': 'u_e-reeanble-weak-protocols.md' + - "Run scripts before and after updates": "u_e-update-hooks.md" + - 'Client Configuration': + - 'Overview': 'client.md' + - 'Android': 'client/client-android.md' + - 'Apple macOS / iOS': 'client/client-apple.md' + - 'eM Client': 'client/client-emclient.md' + - 'KDE Kontact': 'client/client-kontact.md' + - 'Microsoft Outlook': 'client/client-outlook.md' + - 'Mozilla Thunderbird': 'client/client-thunderbird.md' + - 'Windows Mail': 'client/client-windows.md' + - 'Windows Phone': 'client/client-windowsphone.md' + - 'Manual configuration': 'client/client-manual.md' + - 'Third party apps': + - 'Borgmatic Backup': 'third_party-borgmatic.md' + - 'Exchange Hybrid Setup': 'third_party-exchange_onprem.md' + - 'Gitea': 'third_party-gitea.md' + - 'Gogs': 'third_party-gogs.md' + - 'Mailpiler Integration': 'third_party-mailpiler_integration.md' + - 'Nextcloud': 'third_party-nextcloud.md' + - 'Portainer': 'third_party-portainer.md' + - 'Roundcube': 'third_party-roundcube.md' + - 'SOGo Connector for Thunderbird': 'third_party-thunderbird.md' extra: palette: - primary: 'indigo' - accent: 'orange' + primary: "indigo" + accent: "orange" social: - icon: fontawesome/solid/globe-americas link: https://mailcow.email - icon: fontawesome/brands/github-alt link: https://github.com/mailcow -extra_css: [extra.css] -extra_javascript: [clients.js] +extra_css: [ extra.css ] +extra_javascript: [ clients.js ] +plugins: + - search + - redirects: + redirect_maps: + 'u_e-mailpiler-integration.md': 'third_party-mailpiler_integration.md'