From c94e0c629f698d3162b713e4aba1464f5caf3496 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Mon, 25 Apr 2022 15:15:18 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20mailcow/?= =?UTF-8?q?mailcow-dockerized-docs@217032d1c8c794531a119c7406029a10a7ad6b1?= =?UTF-8?q?6=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 404.html | 4 +- ...df45aa19.min.css => main.8c5ef100.min.css} | 2 +- ....min.css.map => main.8c5ef100.min.css.map} | 2 +- .../b_n_r-accidental_deletion/index.html | 8 +- backup_restore/b_n_r-backup/index.html | 28 +-- .../b_n_r-backup_restore-maildir/index.html | 12 +- .../b_n_r-backup_restore-mysql/index.html | 12 +- backup_restore/b_n_r-coldstandby/index.html | 32 +-- backup_restore/b_n_r-restore/index.html | 8 +- client/client-android/index.html | 4 +- client/client-apple/index.html | 4 +- client/client-emclient/index.html | 4 +- client/client-kontact/index.html | 4 +- client/client-manual/index.html | 4 +- client/client-outlook/index.html | 4 +- client/client-thunderbird/index.html | 4 +- client/client-windows/index.html | 4 +- client/client/index.html | 4 +- .../b_n_r-accidental_deletion/index.html | 8 +- de/backup_restore/b_n_r-backup/index.html | 28 +-- .../b_n_r-backup_restore-maildir/index.html | 12 +- .../b_n_r-backup_restore-mysql/index.html | 12 +- .../b_n_r-coldstandby/index.html | 32 +-- de/backup_restore/b_n_r-restore/index.html | 8 +- de/client/client-android/index.html | 4 +- de/client/client-apple/index.html | 4 +- de/client/client-emclient/index.html | 4 +- de/client/client-kontact/index.html | 4 +- de/client/client-manual/index.html | 4 +- de/client/client-outlook/index.html | 4 +- de/client/client-thunderbird/index.html | 4 +- de/client/client-windows/index.html | 4 +- de/client/client/index.html | 4 +- de/i_u_m/i_u_m_deinstall/index.html | 8 +- de/i_u_m/i_u_m_install/index.html | 44 ++--- de/i_u_m/i_u_m_migration/index.html | 36 ++-- de/i_u_m/i_u_m_update/index.html | 20 +- de/index.html | 4 +- .../u_e-clamav-additional_dbs/index.html | 24 +-- .../ClamAV/u_e-clamav-whitelist/index.html | 24 +-- .../u_e-docker-cust_dockerfiles/index.html | 16 +- .../u_e-docker-dc_bash_compl/index.html | 8 +- .../Dovecot/u_e-dovecot-any_acl/index.html | 8 +- .../u_e-dovecot-catchall_vacation/index.html | 4 +- .../Dovecot/u_e-dovecot-expunge/index.html | 36 ++-- .../Dovecot/u_e-dovecot-extra_conf/index.html | 8 +- .../Dovecot/u_e-dovecot-fts/index.html | 12 +- .../u_e-dovecot-idle_interval/index.html | 16 +- .../Dovecot/u_e-dovecot-mail-crypt/index.html | 8 +- .../Dovecot/u_e-dovecot-more/index.html | 28 +-- .../u_e-dovecot-public_folder/index.html | 16 +- .../u_e-dovecot-static_master/index.html | 8 +- .../u_e-dovecot-vmail-volume/index.html | 16 +- .../Nginx/u_e-nginx_custom/index.html | 28 +-- .../Nginx/u_e-nginx_webmail-site/index.html | 12 +- .../u_e-postfix-attachment_size/index.html | 8 +- .../u_e-postfix-custom_transport/index.html | 4 +- .../index.html | 16 +- .../Postfix/u_e-postfix-extra_cf/index.html | 8 +- .../Postfix/u_e-postfix-pflogsumm/index.html | 12 +- .../index.html | 8 +- .../Postfix/u_e-postfix-relayhost/index.html | 4 +- .../u_e-postfix-trust_networks/index.html | 12 +- de/manual-guides/Redis/u_e-redis/index.html | 20 +- de/manual-guides/Rspamd/u_e-rspamd/index.html | 80 ++++---- de/manual-guides/SOGo/u_e-sogo/index.html | 32 +-- .../Unbound/u_e-unbound-fwd/index.html | 16 +- .../u_e-watchdog-thresholds/index.html | 8 +- .../u_e-mailcow_ui-bl_wl/index.html | 4 +- .../u_e-mailcow_ui-config/index.html | 4 +- .../mailcow-UI/u_e-mailcow_ui-css/index.html | 4 +- .../mailcow-UI/u_e-mailcow_ui-fido/index.html | 4 +- .../u_e-mailcow_ui-pushover/index.html | 4 +- .../u_e-mailcow_ui-spamalias/index.html | 4 +- .../u_e-mailcow_ui-spamfilter/index.html | 4 +- .../u_e-mailcow_ui-tagging/index.html | 8 +- .../mailcow-UI/u_e-mailcow_ui-tfa/index.html | 4 +- de/manual-guides/u_e-80_to_443/index.html | 16 +- .../u_e-autodiscover_config/index.html | 8 +- .../u_e-reeanble-weak-protocols/index.html | 16 +- de/manual-guides/u_e-update-hooks/index.html | 4 +- de/manual-guides/u_e-why_unbound/index.html | 4 +- de/models/model-acl/index.html | 4 +- de/models/model-passwd/index.html | 4 +- de/models/model-sender_rcv/index.html | 4 +- .../firststeps-disable_ipv6/index.html | 36 ++-- .../firststeps-dmarc_reporting/index.html | 32 +-- .../firststeps-ip_bindings/index.html | 12 +- .../firststeps-local_mta/index.html | 12 +- .../firststeps-logging/index.html | 20 +- de/post_installation/firststeps-rp/index.html | 182 +++++++++--------- .../firststeps-rspamd_ui/index.html | 4 +- .../firststeps-snat/index.html | 8 +- .../firststeps-ssl/index.html | 32 +-- .../firststeps-sync_jobs_migration/index.html | 4 +- de/prerequisite/prerequisite-dns/index.html | 28 +-- .../prerequisite-system/index.html | 36 ++-- .../third_party-borgmatic/index.html | 102 +++++----- .../third_party-exchange_onprem/index.html | 4 +- de/third_party/third_party-gitea/index.html | 20 +- de/third_party/third_party-gogs/index.html | 20 +- .../third_party-mailman3/index.html | 64 +++--- .../index.html | 20 +- .../third_party-nextcloud/index.html | 20 +- .../third_party-portainer/index.html | 20 +- .../third_party-roundcube/index.html | 76 ++++---- .../debug-admin_login_sogo/index.html | 12 +- .../debug-attach_service/index.html | 16 +- .../debug-common_problems/index.html | 24 +-- de/troubleshooting/debug-logs/index.html | 4 +- .../debug-mysql_aria/index.html | 8 +- .../debug-mysql_upgrade/index.html | 12 +- de/troubleshooting/debug-reset_pw/index.html | 32 +-- de/troubleshooting/debug-reset_tls/index.html | 8 +- .../debug-rm_volumes/index.html | 8 +- .../debug-rspamd_memory_leaks/index.html | 8 +- de/troubleshooting/debug/index.html | 4 +- .../b_n_r-accidental_deletion/index.html | 8 +- en/backup_restore/b_n_r-backup/index.html | 28 +-- .../b_n_r-backup_restore-maildir/index.html | 12 +- .../b_n_r-backup_restore-mysql/index.html | 12 +- .../b_n_r-coldstandby/index.html | 32 +-- en/backup_restore/b_n_r-restore/index.html | 8 +- en/client/client-android/index.html | 4 +- en/client/client-apple/index.html | 4 +- en/client/client-emclient/index.html | 4 +- en/client/client-kontact/index.html | 4 +- en/client/client-manual/index.html | 4 +- en/client/client-outlook/index.html | 4 +- en/client/client-thunderbird/index.html | 4 +- en/client/client-windows/index.html | 4 +- en/client/client/index.html | 4 +- en/i_u_m/i_u_m_deinstall/index.html | 8 +- en/i_u_m/i_u_m_install/index.html | 44 ++--- en/i_u_m/i_u_m_migration/index.html | 36 ++-- en/i_u_m/i_u_m_update/index.html | 20 +- en/index.html | 4 +- .../u_e-clamav-additional_dbs/index.html | 24 +-- .../ClamAV/u_e-clamav-whitelist/index.html | 24 +-- .../u_e-docker-cust_dockerfiles/index.html | 16 +- .../u_e-docker-dc_bash_compl/index.html | 8 +- .../Dovecot/u_e-dovecot-any_acl/index.html | 8 +- .../u_e-dovecot-catchall_vacation/index.html | 4 +- .../Dovecot/u_e-dovecot-expunge/index.html | 36 ++-- .../Dovecot/u_e-dovecot-extra_conf/index.html | 8 +- .../Dovecot/u_e-dovecot-fts/index.html | 12 +- .../u_e-dovecot-idle_interval/index.html | 16 +- .../Dovecot/u_e-dovecot-mail-crypt/index.html | 8 +- .../Dovecot/u_e-dovecot-more/index.html | 28 +-- .../u_e-dovecot-public_folder/index.html | 16 +- .../u_e-dovecot-static_master/index.html | 8 +- .../u_e-dovecot-vmail-volume/index.html | 16 +- .../Nginx/u_e-nginx_custom/index.html | 28 +-- .../Nginx/u_e-nginx_webmail-site/index.html | 12 +- .../u_e-postfix-attachment_size/index.html | 8 +- .../u_e-postfix-custom_transport/index.html | 4 +- .../index.html | 16 +- .../Postfix/u_e-postfix-extra_cf/index.html | 8 +- .../Postfix/u_e-postfix-pflogsumm/index.html | 12 +- .../index.html | 8 +- .../Postfix/u_e-postfix-relayhost/index.html | 4 +- .../u_e-postfix-trust_networks/index.html | 12 +- en/manual-guides/Redis/u_e-redis/index.html | 20 +- en/manual-guides/Rspamd/u_e-rspamd/index.html | 88 ++++----- en/manual-guides/SOGo/u_e-sogo/index.html | 32 +-- .../Unbound/u_e-unbound-fwd/index.html | 16 +- .../u_e-watchdog-thresholds/index.html | 8 +- .../u_e-mailcow_ui-bl_wl/index.html | 4 +- .../u_e-mailcow_ui-config/index.html | 4 +- .../mailcow-UI/u_e-mailcow_ui-css/index.html | 4 +- .../mailcow-UI/u_e-mailcow_ui-fido/index.html | 4 +- .../u_e-mailcow_ui-pushover/index.html | 4 +- .../u_e-mailcow_ui-spamalias/index.html | 4 +- .../u_e-mailcow_ui-spamfilter/index.html | 4 +- .../u_e-mailcow_ui-tagging/index.html | 8 +- .../mailcow-UI/u_e-mailcow_ui-tfa/index.html | 4 +- en/manual-guides/u_e-80_to_443/index.html | 16 +- .../u_e-autodiscover_config/index.html | 8 +- .../u_e-reeanble-weak-protocols/index.html | 16 +- en/manual-guides/u_e-update-hooks/index.html | 4 +- en/manual-guides/u_e-why_unbound/index.html | 4 +- en/models/model-acl/index.html | 4 +- en/models/model-passwd/index.html | 4 +- en/models/model-sender_rcv/index.html | 4 +- .../firststeps-disable_ipv6/index.html | 36 ++-- .../firststeps-dmarc_reporting/index.html | 32 +-- .../firststeps-ip_bindings/index.html | 12 +- .../firststeps-local_mta/index.html | 12 +- .../firststeps-logging/index.html | 20 +- en/post_installation/firststeps-rp/index.html | 182 +++++++++--------- .../firststeps-rspamd_ui/index.html | 4 +- .../firststeps-snat/index.html | 8 +- .../firststeps-ssl/index.html | 32 +-- .../firststeps-sync_jobs_migration/index.html | 4 +- en/prerequisite/prerequisite-dns/index.html | 28 +-- .../prerequisite-system/index.html | 36 ++-- .../third_party-borgmatic/index.html | 110 +++++------ .../third_party-exchange_onprem/index.html | 4 +- en/third_party/third_party-gitea/index.html | 20 +- en/third_party/third_party-gogs/index.html | 20 +- .../third_party-mailman3/index.html | 64 +++--- .../index.html | 20 +- .../third_party-nextcloud/index.html | 20 +- .../third_party-portainer/index.html | 20 +- .../third_party-roundcube/index.html | 76 ++++---- .../debug-admin_login_sogo/index.html | 12 +- .../debug-attach_service/index.html | 16 +- .../debug-common_problems/index.html | 24 +-- en/troubleshooting/debug-logs/index.html | 4 +- .../debug-mysql_aria/index.html | 8 +- .../debug-mysql_upgrade/index.html | 12 +- en/troubleshooting/debug-reset_pw/index.html | 32 +-- en/troubleshooting/debug-reset_tls/index.html | 8 +- .../debug-rm_volumes/index.html | 8 +- .../debug-rspamd_memory_leaks/index.html | 8 +- en/troubleshooting/debug/index.html | 4 +- i_u_m/i_u_m_deinstall/index.html | 8 +- i_u_m/i_u_m_install/index.html | 44 ++--- i_u_m/i_u_m_migration/index.html | 36 ++-- i_u_m/i_u_m_update/index.html | 20 +- index.html | 4 +- .../u_e-clamav-additional_dbs/index.html | 24 +-- .../ClamAV/u_e-clamav-whitelist/index.html | 24 +-- .../u_e-docker-cust_dockerfiles/index.html | 16 +- .../u_e-docker-dc_bash_compl/index.html | 8 +- .../Dovecot/u_e-dovecot-any_acl/index.html | 8 +- .../u_e-dovecot-catchall_vacation/index.html | 4 +- .../Dovecot/u_e-dovecot-expunge/index.html | 36 ++-- .../Dovecot/u_e-dovecot-extra_conf/index.html | 8 +- .../Dovecot/u_e-dovecot-fts/index.html | 12 +- .../u_e-dovecot-idle_interval/index.html | 16 +- .../Dovecot/u_e-dovecot-mail-crypt/index.html | 8 +- .../Dovecot/u_e-dovecot-more/index.html | 28 +-- .../u_e-dovecot-public_folder/index.html | 16 +- .../u_e-dovecot-static_master/index.html | 8 +- .../u_e-dovecot-vmail-volume/index.html | 16 +- .../Nginx/u_e-nginx_custom/index.html | 28 +-- .../Nginx/u_e-nginx_webmail-site/index.html | 12 +- .../u_e-postfix-attachment_size/index.html | 8 +- .../u_e-postfix-custom_transport/index.html | 4 +- .../index.html | 16 +- .../Postfix/u_e-postfix-extra_cf/index.html | 8 +- .../Postfix/u_e-postfix-pflogsumm/index.html | 12 +- .../index.html | 8 +- .../Postfix/u_e-postfix-relayhost/index.html | 4 +- .../u_e-postfix-trust_networks/index.html | 12 +- manual-guides/Redis/u_e-redis/index.html | 20 +- manual-guides/Rspamd/u_e-rspamd/index.html | 88 ++++----- manual-guides/SOGo/u_e-sogo/index.html | 32 +-- .../Unbound/u_e-unbound-fwd/index.html | 16 +- .../u_e-watchdog-thresholds/index.html | 8 +- .../u_e-mailcow_ui-bl_wl/index.html | 4 +- .../u_e-mailcow_ui-config/index.html | 4 +- .../mailcow-UI/u_e-mailcow_ui-css/index.html | 4 +- .../mailcow-UI/u_e-mailcow_ui-fido/index.html | 4 +- .../u_e-mailcow_ui-pushover/index.html | 4 +- .../u_e-mailcow_ui-spamalias/index.html | 4 +- .../u_e-mailcow_ui-spamfilter/index.html | 4 +- .../u_e-mailcow_ui-tagging/index.html | 8 +- .../mailcow-UI/u_e-mailcow_ui-tfa/index.html | 4 +- manual-guides/u_e-80_to_443/index.html | 16 +- .../u_e-autodiscover_config/index.html | 8 +- .../u_e-reeanble-weak-protocols/index.html | 16 +- manual-guides/u_e-update-hooks/index.html | 4 +- manual-guides/u_e-why_unbound/index.html | 4 +- models/model-acl/index.html | 4 +- models/model-passwd/index.html | 4 +- models/model-sender_rcv/index.html | 4 +- .../firststeps-disable_ipv6/index.html | 36 ++-- .../firststeps-dmarc_reporting/index.html | 32 +-- .../firststeps-ip_bindings/index.html | 12 +- .../firststeps-local_mta/index.html | 12 +- .../firststeps-logging/index.html | 20 +- post_installation/firststeps-rp/index.html | 182 +++++++++--------- .../firststeps-rspamd_ui/index.html | 4 +- post_installation/firststeps-snat/index.html | 8 +- post_installation/firststeps-ssl/index.html | 32 +-- .../firststeps-sync_jobs_migration/index.html | 4 +- prerequisite/prerequisite-dns/index.html | 28 +-- prerequisite/prerequisite-system/index.html | 36 ++-- sitemap.xml.gz | Bin 2180 -> 2180 bytes third_party/third_party-borgmatic/index.html | 110 +++++------ .../third_party-exchange_onprem/index.html | 4 +- third_party/third_party-gitea/index.html | 20 +- third_party/third_party-gogs/index.html | 20 +- third_party/third_party-mailman3/index.html | 64 +++--- .../index.html | 20 +- third_party/third_party-nextcloud/index.html | 20 +- third_party/third_party-portainer/index.html | 20 +- third_party/third_party-roundcube/index.html | 76 ++++---- .../debug-admin_login_sogo/index.html | 12 +- .../debug-attach_service/index.html | 16 +- .../debug-common_problems/index.html | 24 +-- troubleshooting/debug-logs/index.html | 4 +- troubleshooting/debug-mysql_aria/index.html | 8 +- .../debug-mysql_upgrade/index.html | 12 +- troubleshooting/debug-reset_pw/index.html | 32 +-- troubleshooting/debug-reset_tls/index.html | 8 +- troubleshooting/debug-rm_volumes/index.html | 8 +- .../debug-rspamd_memory_leaks/index.html | 8 +- troubleshooting/debug/index.html | 4 +- 301 files changed, 2624 insertions(+), 2624 deletions(-) rename assets/stylesheets/{main.df45aa19.min.css => main.8c5ef100.min.css} (51%) rename assets/stylesheets/{main.df45aa19.min.css.map => main.8c5ef100.min.css.map} (58%) diff --git a/404.html b/404.html index 96c7a1258..21943b9a6 100644 --- a/404.html +++ b/404.html @@ -9,7 +9,7 @@ - + @@ -17,7 +17,7 @@ - + diff --git a/assets/stylesheets/main.df45aa19.min.css b/assets/stylesheets/main.8c5ef100.min.css similarity index 51% rename from assets/stylesheets/main.df45aa19.min.css rename to assets/stylesheets/main.8c5ef100.min.css index bde741f0f..897156052 100644 --- a/assets/stylesheets/main.df45aa19.min.css +++ b/assets/stylesheets/main.8c5ef100.min.css @@ -1 +1 @@ -@charset "UTF-8";html{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;-ms-text-size-adjust:none;text-size-adjust:none;box-sizing:border-box}*,:after,:before{box-sizing:inherit}@media (prefers-reduced-motion){*,:after,:before{transition:none!important}}body{margin:0}a,button,input,label{-webkit-tap-highlight-color:transparent}a{color:inherit;text-decoration:none}hr{border:0;box-sizing:initial;display:block;height:.05rem;overflow:visible;padding:0}small{font-size:80%}sub,sup{line-height:1em}img{border-style:none}table{border-collapse:initial;border-spacing:0}td,th{font-weight:400;vertical-align:top}button{background:transparent;border:0;font-family:inherit;font-size:inherit;margin:0;padding:0}input{border:0;outline:none}:root{--md-default-fg-color:rgba(0,0,0,.87);--md-default-fg-color--light:rgba(0,0,0,.54);--md-default-fg-color--lighter:rgba(0,0,0,.32);--md-default-fg-color--lightest:rgba(0,0,0,.07);--md-default-bg-color:#fff;--md-default-bg-color--light:hsla(0,0%,100%,.7);--md-default-bg-color--lighter:hsla(0,0%,100%,.3);--md-default-bg-color--lightest:hsla(0,0%,100%,.12);--md-primary-fg-color:#4051b5;--md-primary-fg-color--light:#5d6cc0;--md-primary-fg-color--dark:#303fa1;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7);--md-accent-fg-color:#526cfe;--md-accent-fg-color--transparent:rgba(82,108,254,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7);--md-shadow-z1:0 0.2rem 0.5rem rgba(0,0,0,.05),0 0 0.05rem rgba(0,0,0,.1);--md-shadow-z2:0 0.2rem 0.5rem rgba(0,0,0,.1),0 0 0.05rem rgba(0,0,0,.25);--md-shadow-z3:0 0.2rem 0.5rem rgba(0,0,0,.2),0 0 0.05rem rgba(0,0,0,.35)}:root>*{--md-code-fg-color:#36464e;--md-code-bg-color:#f5f5f5;--md-code-hl-color:rgba(255,255,0,.5);--md-code-hl-number-color:#d52a2a;--md-code-hl-special-color:#db1457;--md-code-hl-function-color:#a846b9;--md-code-hl-constant-color:#6e59d9;--md-code-hl-keyword-color:#3f6ec6;--md-code-hl-string-color:#1c7d4d;--md-code-hl-name-color:var(--md-code-fg-color);--md-code-hl-operator-color:var(--md-default-fg-color--light);--md-code-hl-punctuation-color:var(--md-default-fg-color--light);--md-code-hl-comment-color:var(--md-default-fg-color--light);--md-code-hl-generic-color:var(--md-default-fg-color--light);--md-code-hl-variable-color:var(--md-default-fg-color--light);--md-typeset-color:var(--md-default-fg-color);--md-typeset-a-color:var(--md-primary-fg-color);--md-typeset-mark-color:rgba(255,255,0,.5);--md-typeset-del-color:rgba(245,80,61,.15);--md-typeset-ins-color:rgba(11,213,112,.15);--md-typeset-kbd-color:#fafafa;--md-typeset-kbd-accent-color:#fff;--md-typeset-kbd-border-color:#b8b8b8;--md-typeset-table-color:rgba(0,0,0,.12);--md-admonition-fg-color:var(--md-default-fg-color);--md-admonition-bg-color:var(--md-default-bg-color);--md-footer-fg-color:#fff;--md-footer-fg-color--light:hsla(0,0%,100%,.7);--md-footer-fg-color--lighter:hsla(0,0%,100%,.3);--md-footer-bg-color:rgba(0,0,0,.87);--md-footer-bg-color--dark:rgba(0,0,0,.32)}.md-icon svg{fill:currentcolor;display:block;height:1.2rem;width:1.2rem}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;--md-text-font-family:var(--md-text-font,_),-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif;--md-code-font-family:var(--md-code-font,_),SFMono-Regular,Consolas,Menlo,monospace}body,input{font-feature-settings:"kern","liga";font-family:var(--md-text-font-family)}body,code,input,kbd,pre{color:var(--md-typeset-color)}code,kbd,pre{font-feature-settings:"kern";font-family:var(--md-code-font-family)}:root{--md-typeset-table-sort-icon:url('data:image/svg+xml;charset=utf-8,');--md-typeset-table-sort-icon--asc:url('data:image/svg+xml;charset=utf-8,');--md-typeset-table-sort-icon--desc:url('data:image/svg+xml;charset=utf-8,')}.md-typeset{-webkit-print-color-adjust:exact;color-adjust:exact;font-size:.8rem;line-height:1.6}@media print{.md-typeset{font-size:.68rem}}.md-typeset blockquote,.md-typeset dl,.md-typeset figure,.md-typeset ol,.md-typeset pre,.md-typeset ul{margin-bottom:1em;margin-top:1em}.md-typeset h1{color:var(--md-default-fg-color--light);font-size:2em;line-height:1.3;margin:0 0 1.25em}.md-typeset h1,.md-typeset h2{font-weight:300;letter-spacing:-.01em}.md-typeset h2{font-size:1.5625em;line-height:1.4;margin:1.6em 0 .64em}.md-typeset h3{font-size:1.25em;font-weight:400;letter-spacing:-.01em;line-height:1.5;margin:1.6em 0 .8em}.md-typeset h2+h3{margin-top:.8em}.md-typeset h4{font-weight:700;letter-spacing:-.01em;margin:1em 0}.md-typeset h5,.md-typeset h6{color:var(--md-default-fg-color--light);font-size:.8em;font-weight:700;letter-spacing:-.01em;margin:1.25em 0}.md-typeset h5{text-transform:uppercase}.md-typeset hr{border-bottom:.05rem solid var(--md-default-fg-color--lightest);display:flow-root;margin:1.5em 0}.md-typeset a{color:var(--md-typeset-a-color);word-break:break-word}.md-typeset a,.md-typeset a:before{transition:color 125ms}.md-typeset a:focus,.md-typeset a:hover{color:var(--md-accent-fg-color)}.md-typeset a:focus code,.md-typeset a:hover code{background-color:var(--md-accent-fg-color--transparent)}.md-typeset a code{color:currentcolor;transition:background-color 125ms}.md-typeset a.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-typeset code,.md-typeset kbd,.md-typeset pre{color:var(--md-code-fg-color);direction:ltr}@media print{.md-typeset code,.md-typeset kbd,.md-typeset pre{white-space:pre-wrap}}.md-typeset code{background-color:var(--md-code-bg-color);border-radius:.1rem;-webkit-box-decoration-break:clone;box-decoration-break:clone;font-size:.85em;padding:0 .2941176471em;word-break:break-word}.md-typeset code:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}.md-typeset pre{display:flow-root;line-height:1.4;position:relative}.md-typeset pre>code{-webkit-box-decoration-break:slice;box-decoration-break:slice;box-shadow:none;display:block;margin:0;outline-color:var(--md-accent-fg-color);overflow:auto;padding:.7720588235em 1.1764705882em;scrollbar-color:var(--md-default-fg-color--lighter) transparent;scrollbar-width:thin;touch-action:auto;word-break:normal}.md-typeset pre>code:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-typeset pre>code::-webkit-scrollbar{height:.2rem;width:.2rem}.md-typeset pre>code::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-typeset pre>code::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}.md-typeset kbd{background-color:var(--md-typeset-kbd-color);border-radius:.1rem;box-shadow:0 .1rem 0 .05rem var(--md-typeset-kbd-border-color),0 .1rem 0 var(--md-typeset-kbd-border-color),0 -.1rem .2rem var(--md-typeset-kbd-accent-color) inset;color:var(--md-default-fg-color);display:inline-block;font-size:.75em;padding:0 .6666666667em;vertical-align:text-top;word-break:break-word}.md-typeset mark{background-color:var(--md-typeset-mark-color);-webkit-box-decoration-break:clone;box-decoration-break:clone;color:inherit;word-break:break-word}.md-typeset abbr{border-bottom:.05rem dotted var(--md-default-fg-color--light);cursor:help;text-decoration:none}@media (hover:none){.md-typeset abbr{position:relative}.md-typeset abbr[title]:-webkit-any(:focus,:hover):after{background-color:var(--md-default-fg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z3);color:var(--md-default-bg-color);content:attr(title);display:inline-block;font-size:.7rem;margin-top:2em;max-width:80%;min-width:-webkit-max-content;min-width:max-content;padding:.2rem .3rem;position:absolute;width:auto}.md-typeset abbr[title]:-moz-any(:focus,:hover):after{background-color:var(--md-default-fg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z3);color:var(--md-default-bg-color);content:attr(title);display:inline-block;font-size:.7rem;margin-top:2em;max-width:80%;min-width:-moz-max-content;min-width:max-content;padding:.2rem .3rem;position:absolute;width:auto}[dir=ltr] .md-typeset abbr[title]:-webkit-any(:focus,:hover):after{left:0}[dir=ltr] .md-typeset abbr[title]:-moz-any(:focus,:hover):after{left:0}[dir=ltr] .md-typeset abbr[title]:is(:focus,:hover):after{left:0}[dir=rtl] .md-typeset abbr[title]:-webkit-any(:focus,:hover):after{right:0}[dir=rtl] .md-typeset abbr[title]:-moz-any(:focus,:hover):after{right:0}[dir=rtl] .md-typeset abbr[title]:is(:focus,:hover):after{right:0}.md-typeset abbr[title]:is(:focus,:hover):after{background-color:var(--md-default-fg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z3);color:var(--md-default-bg-color);content:attr(title);display:inline-block;font-size:.7rem;margin-top:2em;max-width:80%;min-width:-webkit-max-content;min-width:-moz-max-content;min-width:max-content;padding:.2rem .3rem;position:absolute;width:auto}}.md-typeset small{opacity:.75}[dir=ltr] .md-typeset sub,[dir=ltr] .md-typeset sup{margin-left:.078125em}[dir=rtl] .md-typeset sub,[dir=rtl] .md-typeset sup{margin-right:.078125em}[dir=ltr] .md-typeset blockquote{padding-left:.6rem}[dir=rtl] .md-typeset blockquote{padding-right:.6rem}[dir=ltr] .md-typeset blockquote{border-left:.2rem solid var(--md-default-fg-color--lighter)}[dir=rtl] .md-typeset blockquote{border-right:.2rem solid var(--md-default-fg-color--lighter)}.md-typeset blockquote{color:var(--md-default-fg-color--light);margin-left:0;margin-right:0}.md-typeset ul{list-style-type:disc}[dir=ltr] .md-typeset ol,[dir=ltr] .md-typeset ul{margin-left:.625em}[dir=rtl] .md-typeset ol,[dir=rtl] .md-typeset ul{margin-right:.625em}.md-typeset ol,.md-typeset ul{padding:0}.md-typeset ol:not([hidden]),.md-typeset ul:not([hidden]){display:flow-root}.md-typeset ol ol,.md-typeset ul ol{list-style-type:lower-alpha}.md-typeset ol ol ol,.md-typeset ul ol ol{list-style-type:lower-roman}[dir=ltr] .md-typeset ol li,[dir=ltr] .md-typeset ul li{margin-left:1.25em}[dir=rtl] .md-typeset ol li,[dir=rtl] .md-typeset ul li{margin-right:1.25em}.md-typeset ol li,.md-typeset ul li{margin-bottom:.5em}.md-typeset ol li blockquote,.md-typeset ol li p,.md-typeset ul li blockquote,.md-typeset ul li p{margin:.5em 0}.md-typeset ol li:last-child,.md-typeset ul li:last-child{margin-bottom:0}.md-typeset ol li :-webkit-any(ul,ol),.md-typeset ul li :-webkit-any(ul,ol){margin-bottom:.5em;margin-top:.5em}.md-typeset ol li :-moz-any(ul,ol),.md-typeset ul li :-moz-any(ul,ol){margin-bottom:.5em;margin-top:.5em}[dir=ltr] .md-typeset ol li :-webkit-any(ul,ol),[dir=ltr] .md-typeset ul li :-webkit-any(ul,ol){margin-left:.625em}[dir=ltr] .md-typeset ol li :-moz-any(ul,ol),[dir=ltr] .md-typeset ul li :-moz-any(ul,ol){margin-left:.625em}[dir=ltr] .md-typeset ol li :is(ul,ol),[dir=ltr] .md-typeset ul li :is(ul,ol){margin-left:.625em}[dir=rtl] .md-typeset ol li :-webkit-any(ul,ol),[dir=rtl] .md-typeset ul li :-webkit-any(ul,ol){margin-right:.625em}[dir=rtl] .md-typeset ol li :-moz-any(ul,ol),[dir=rtl] .md-typeset ul li :-moz-any(ul,ol){margin-right:.625em}[dir=rtl] .md-typeset ol li :is(ul,ol),[dir=rtl] .md-typeset ul li :is(ul,ol){margin-right:.625em}.md-typeset ol li :is(ul,ol),.md-typeset ul li :is(ul,ol){margin-bottom:.5em;margin-top:.5em}[dir=ltr] .md-typeset dd{margin-left:1.875em}[dir=rtl] .md-typeset dd{margin-right:1.875em}.md-typeset dd{margin-bottom:1.5em;margin-top:1em}.md-typeset img,.md-typeset svg{height:auto;max-width:100%}.md-typeset img[align=left],.md-typeset svg[align=left]{margin:1em 1em 1em 0}.md-typeset img[align=right],.md-typeset svg[align=right]{margin:1em 0 1em 1em}.md-typeset img[align]:only-child,.md-typeset svg[align]:only-child{margin-top:0}.md-typeset img[src$="#only-dark"]{display:none}.md-typeset figure{display:flow-root;margin:1em auto;max-width:100%;text-align:center;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.md-typeset figure img{display:block}.md-typeset figcaption{font-style:italic;margin:1em auto;max-width:24rem}.md-typeset iframe{max-width:100%}.md-typeset table:not([class]){background-color:var(--md-default-bg-color);border:.05rem solid var(--md-typeset-table-color);border-radius:.1rem;display:inline-block;font-size:.64rem;max-width:100%;overflow:auto;touch-action:auto}@media print{.md-typeset table:not([class]){display:table}}.md-typeset table:not([class])+*{margin-top:1.5em}.md-typeset table:not([class]) :-webkit-any(th,td)>:first-child{margin-top:0}.md-typeset table:not([class]) :-moz-any(th,td)>:first-child{margin-top:0}.md-typeset table:not([class]) :is(th,td)>:first-child{margin-top:0}.md-typeset table:not([class]) :-webkit-any(th,td)>:last-child{margin-bottom:0}.md-typeset table:not([class]) :-moz-any(th,td)>:last-child{margin-bottom:0}.md-typeset table:not([class]) :is(th,td)>:last-child{margin-bottom:0}.md-typeset table:not([class]) :-webkit-any(th,td):not([align]){text-align:left}.md-typeset table:not([class]) :-moz-any(th,td):not([align]){text-align:left}.md-typeset table:not([class]) :is(th,td):not([align]){text-align:left}[dir=rtl] .md-typeset table:not([class]) :-webkit-any(th,td):not([align]){text-align:right}[dir=rtl] .md-typeset table:not([class]) :-moz-any(th,td):not([align]){text-align:right}[dir=rtl] .md-typeset table:not([class]) :is(th,td):not([align]){text-align:right}.md-typeset table:not([class]) th{font-weight:700;min-width:5rem;padding:.9375em 1.25em;vertical-align:top}.md-typeset table:not([class]) th a{color:inherit}.md-typeset table:not([class]) td{border-top:.05rem solid var(--md-typeset-table-color);padding:.9375em 1.25em;vertical-align:top}.md-typeset table:not([class]) tbody tr{transition:background-color 125ms}.md-typeset table:not([class]) tbody tr:hover{background-color:rgba(0,0,0,.035);box-shadow:0 .05rem 0 var(--md-default-bg-color) inset}.md-typeset table:not([class]) a{word-break:normal}.md-typeset table th[role=columnheader]{cursor:pointer}[dir=ltr] .md-typeset table th[role=columnheader]:after{margin-left:.5em}[dir=rtl] .md-typeset table th[role=columnheader]:after{margin-right:.5em}.md-typeset table th[role=columnheader]:after{content:"";display:inline-block;height:1.2em;-webkit-mask-image:var(--md-typeset-table-sort-icon);mask-image:var(--md-typeset-table-sort-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color 125ms;vertical-align:text-bottom;width:1.2em}.md-typeset table th[role=columnheader]:hover:after{background-color:var(--md-default-fg-color--lighter)}.md-typeset table th[role=columnheader][aria-sort=ascending]:after{background-color:var(--md-default-fg-color--light);-webkit-mask-image:var(--md-typeset-table-sort-icon--asc);mask-image:var(--md-typeset-table-sort-icon--asc)}.md-typeset table th[role=columnheader][aria-sort=descending]:after{background-color:var(--md-default-fg-color--light);-webkit-mask-image:var(--md-typeset-table-sort-icon--desc);mask-image:var(--md-typeset-table-sort-icon--desc)}.md-typeset__scrollwrap{margin:1em -.8rem;overflow-x:auto;touch-action:auto}.md-typeset__table{display:inline-block;margin-bottom:.5em;padding:0 .8rem}@media print{.md-typeset__table{display:block}}html .md-typeset__table table{display:table;margin:0;overflow:hidden;width:100%}@media screen and (max-width:44.9375em){.md-content__inner>pre{margin:1em -.8rem}.md-content__inner>pre code{border-radius:0}}.md-banner{background-color:var(--md-footer-bg-color);color:var(--md-footer-fg-color);overflow:auto}@media print{.md-banner{display:none}}.md-banner--warning{background:var(--md-typeset-mark-color);color:var(--md-default-fg-color)}.md-banner__inner{font-size:.7rem;margin:.6rem auto;padding:0 .8rem}html{font-size:125%;height:100%;overflow-x:hidden}@media screen and (min-width:100em){html{font-size:137.5%}}@media screen and (min-width:125em){html{font-size:150%}}body{background-color:var(--md-default-bg-color);display:flex;flex-direction:column;font-size:.5rem;min-height:100%;position:relative;width:100%}@media print{body{display:block}}@media screen and (max-width:59.9375em){body[data-md-state=lock]{position:fixed}}.md-grid{margin-left:auto;margin-right:auto;max-width:61rem}.md-container{display:flex;flex-direction:column;flex-grow:1}@media print{.md-container{display:block}}.md-main{flex-grow:1}.md-main__inner{display:flex;height:100%;margin-top:1.5rem}.md-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.md-toggle{display:none}.md-option{height:0;opacity:0;position:absolute;width:0}.md-option:checked+label:not([hidden]){display:block}.md-option.focus-visible+label{outline-color:var(--md-accent-fg-color);outline-style:auto}.md-skip{background-color:var(--md-default-fg-color);border-radius:.1rem;color:var(--md-default-bg-color);font-size:.64rem;margin:.5rem;opacity:0;outline-color:var(--md-accent-fg-color);padding:.3rem .5rem;position:fixed;transform:translateY(.4rem);z-index:-1}.md-skip:focus{opacity:1;transform:translateY(0);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity 175ms 75ms;z-index:10}@page{margin:25mm}:root{--md-clipboard-icon:url('data:image/svg+xml;charset=utf-8,')}.md-clipboard{border-radius:.1rem;color:var(--md-default-fg-color--lightest);cursor:pointer;height:1.5em;outline-color:var(--md-accent-fg-color);outline-offset:.1rem;position:absolute;right:.5em;top:.5em;transition:color .25s;width:1.5em;z-index:1}@media print{.md-clipboard{display:none}}.md-clipboard:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}:hover>.md-clipboard{color:var(--md-default-fg-color--light)}.md-clipboard:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-clipboard:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-clipboard:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-clipboard:after{background-color:currentcolor;content:"";display:block;height:1.125em;margin:0 auto;-webkit-mask-image:var(--md-clipboard-icon);mask-image:var(--md-clipboard-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:1.125em}.md-clipboard--inline{cursor:pointer}.md-clipboard--inline code{transition:color .25s,background-color .25s}.md-clipboard--inline:-webkit-any(:focus,:hover) code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-clipboard--inline:-moz-any(:focus,:hover) code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-clipboard--inline:is(:focus,:hover) code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-content{flex-grow:1;min-width:0}.md-content__inner{margin:0 .8rem 1.2rem;padding-top:.6rem}@media screen and (min-width:76.25em){[dir=ltr] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}[dir=ltr] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner,[dir=rtl] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem}[dir=rtl] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}}.md-content__inner:before{content:"";display:block;height:.4rem}.md-content__inner>:last-child{margin-bottom:0}[dir=ltr] .md-content__button{margin-left:.4rem}[dir=rtl] .md-content__button{margin-right:.4rem}.md-content__button{float:right;margin:.4rem 0;padding:0}@media print{.md-content__button{display:none}}[dir=rtl] .md-content__button{float:left}.md-typeset .md-content__button{color:var(--md-default-fg-color--lighter)}.md-content__button svg{display:inline;vertical-align:top}[dir=rtl] .md-content__button svg{transform:scaleX(-1)}[dir=ltr] .md-dialog{right:.8rem}[dir=rtl] .md-dialog{left:.8rem}.md-dialog{background-color:var(--md-default-fg-color);border-radius:.1rem;bottom:.8rem;box-shadow:var(--md-shadow-z3);min-width:11.1rem;opacity:0;padding:.4rem .6rem;pointer-events:none;position:fixed;transform:translateY(100%);transition:transform 0ms .4s,opacity .4s;z-index:4}@media print{.md-dialog{display:none}}.md-dialog[data-md-state=open]{opacity:1;pointer-events:auto;transform:translateY(0);transition:transform .4s cubic-bezier(.075,.85,.175,1),opacity .4s}.md-dialog__inner{color:var(--md-default-bg-color);font-size:.7rem}.md-footer{background-color:var(--md-footer-bg-color);color:var(--md-footer-fg-color)}@media print{.md-footer{display:none}}.md-footer__inner{display:flex;justify-content:space-between;overflow:auto;padding:.2rem}.md-footer__link{display:flex;flex-grow:0.01;outline-color:var(--md-accent-fg-color);overflow:hidden;padding-bottom:.4rem;padding-top:1.4rem;transition:opacity .25s}.md-footer__link:-webkit-any(:focus,:hover){opacity:.7}.md-footer__link:-moz-any(:focus,:hover){opacity:.7}.md-footer__link:is(:focus,:hover){opacity:.7}[dir=rtl] .md-footer__link svg{transform:scaleX(-1)}@media screen and (max-width:44.9375em){.md-footer__link--prev .md-footer__title{display:none}}[dir=ltr] .md-footer__link--next{margin-left:auto}[dir=rtl] .md-footer__link--next{margin-right:auto}.md-footer__link--next{text-align:right}[dir=rtl] .md-footer__link--next{text-align:left}.md-footer__title{flex-grow:1;font-size:.9rem;line-height:2.4rem;max-width:calc(100% - 2.4rem);padding:0 1rem;position:relative}.md-footer__button{margin:.2rem;padding:.4rem}.md-footer__direction{font-size:.64rem;left:0;margin-top:-1rem;opacity:.7;padding:0 1rem;position:absolute;right:0}.md-footer-meta{background-color:var(--md-footer-bg-color--dark)}.md-footer-meta__inner{display:flex;flex-wrap:wrap;justify-content:space-between;padding:.2rem}html .md-footer-meta.md-typeset a{color:var(--md-footer-fg-color--light)}html .md-footer-meta.md-typeset a:-webkit-any(:focus,:hover){color:var(--md-footer-fg-color)}html .md-footer-meta.md-typeset a:-moz-any(:focus,:hover){color:var(--md-footer-fg-color)}html .md-footer-meta.md-typeset a:is(:focus,:hover){color:var(--md-footer-fg-color)}.md-copyright{color:var(--md-footer-fg-color--lighter);font-size:.64rem;margin:auto .6rem;padding:.4rem 0;width:100%}@media screen and (min-width:45em){.md-copyright{width:auto}}.md-copyright__highlight{color:var(--md-footer-fg-color--light)}.md-social{margin:0 .4rem;padding:.2rem 0 .6rem}@media screen and (min-width:45em){.md-social{padding:.6rem 0}}.md-social__link{display:inline-block;height:1.6rem;text-align:center;width:1.6rem}.md-social__link:before{line-height:1.9}.md-social__link svg{fill:currentcolor;max-height:.8rem;vertical-align:-25%}.md-typeset .md-button{border:.1rem solid;border-radius:.1rem;color:var(--md-primary-fg-color);cursor:pointer;display:inline-block;font-weight:700;padding:.625em 2em;transition:color 125ms,background-color 125ms,border-color 125ms}.md-typeset .md-button--primary{background-color:var(--md-primary-fg-color);border-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color)}.md-typeset .md-button:-webkit-any(:focus,:hover){background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-typeset .md-button:-moz-any(:focus,:hover){background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-typeset .md-button:is(:focus,:hover){background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}[dir=ltr] .md-typeset .md-input{border-top-left-radius:.1rem}[dir=ltr] .md-typeset .md-input,[dir=rtl] .md-typeset .md-input{border-top-right-radius:.1rem}[dir=rtl] .md-typeset .md-input{border-top-left-radius:.1rem}.md-typeset .md-input{border-bottom:.1rem solid var(--md-default-fg-color--lighter);box-shadow:var(--md-shadow-z1);font-size:.8rem;height:1.8rem;padding:0 .6rem;transition:border .25s,box-shadow .25s}.md-typeset .md-input:-webkit-any(:focus,:hover){border-bottom-color:var(--md-accent-fg-color);box-shadow:var(--md-shadow-z2)}.md-typeset .md-input:-moz-any(:focus,:hover){border-bottom-color:var(--md-accent-fg-color);box-shadow:var(--md-shadow-z2)}.md-typeset .md-input:is(:focus,:hover){border-bottom-color:var(--md-accent-fg-color);box-shadow:var(--md-shadow-z2)}.md-typeset .md-input--stretch{width:100%}.md-header{background-color:var(--md-primary-fg-color);box-shadow:0 0 .2rem transparent,0 .2rem .4rem transparent;color:var(--md-primary-bg-color);left:0;position:-webkit-sticky;position:sticky;right:0;top:0;z-index:4}@media print{.md-header{display:none}}.md-header[data-md-state=shadow]{box-shadow:0 0 .2rem rgba(0,0,0,.1),0 .2rem .4rem rgba(0,0,0,.2);transition:transform .25s cubic-bezier(.1,.7,.1,1),box-shadow .25s}.md-header[data-md-state=hidden]{transform:translateY(-100%);transition:transform .25s cubic-bezier(.8,0,.6,1),box-shadow .25s}.md-header__inner{align-items:center;display:flex;padding:0 .2rem}.md-header__button{color:currentcolor;cursor:pointer;margin:.2rem;outline-color:var(--md-accent-fg-color);padding:.4rem;position:relative;transition:opacity .25s;vertical-align:middle;z-index:1}.md-header__button:hover{opacity:.7}.md-header__button:not([hidden]){display:inline-block}.md-header__button:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}.md-header__button.md-logo{margin:.2rem;padding:.4rem}@media screen and (max-width:76.1875em){.md-header__button.md-logo{display:none}}.md-header__button.md-logo :-webkit-any(img,svg){fill:currentcolor;display:block;height:1.2rem;width:auto}.md-header__button.md-logo :-moz-any(img,svg){fill:currentcolor;display:block;height:1.2rem;width:auto}.md-header__button.md-logo :is(img,svg){fill:currentcolor;display:block;height:1.2rem;width:auto}@media screen and (min-width:60em){.md-header__button[for=__search]{display:none}}.no-js .md-header__button[for=__search]{display:none}[dir=rtl] .md-header__button[for=__search] svg{transform:scaleX(-1)}@media screen and (min-width:76.25em){.md-header__button[for=__drawer]{display:none}}.md-header__topic{display:flex;max-width:100%;position:absolute;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s}.md-header__topic+.md-header__topic{opacity:0;pointer-events:none;transform:translateX(1.25rem);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;z-index:-1}[dir=rtl] .md-header__topic+.md-header__topic{transform:translateX(-1.25rem)}.md-header__topic:first-child{font-weight:700}[dir=ltr] .md-header__title{margin-right:.4rem}[dir=rtl] .md-header__title{margin-left:.4rem}[dir=ltr] .md-header__title{margin-left:1rem}[dir=rtl] .md-header__title{margin-right:1rem}.md-header__title{flex-grow:1;font-size:.9rem;height:2.4rem;line-height:2.4rem}.md-header__title[data-md-state=active] .md-header__topic{opacity:0;pointer-events:none;transform:translateX(-1.25rem);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;z-index:-1}[dir=rtl] .md-header__title[data-md-state=active] .md-header__topic{transform:translateX(1.25rem)}.md-header__title[data-md-state=active] .md-header__topic+.md-header__topic{opacity:1;pointer-events:auto;transform:translateX(0);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s;z-index:0}.md-header__title>.md-header__ellipsis{height:100%;position:relative;width:100%}.md-header__option{display:flex;flex-shrink:0;max-width:100%;transition:max-width 0ms .25s,opacity .25s .25s;white-space:nowrap}[data-md-toggle=search]:checked~.md-header .md-header__option{max-width:0;opacity:0;transition:max-width 0ms,opacity 0ms}.md-header__source{display:none}@media screen and (min-width:60em){[dir=ltr] .md-header__source{margin-left:1rem}[dir=rtl] .md-header__source{margin-right:1rem}.md-header__source{display:block;max-width:11.7rem;width:11.7rem}}@media screen and (min-width:76.25em){[dir=ltr] .md-header__source{margin-left:1.4rem}[dir=rtl] .md-header__source{margin-right:1.4rem}}:root{--md-nav-icon--prev:url('data:image/svg+xml;charset=utf-8,');--md-nav-icon--next:url('data:image/svg+xml;charset=utf-8,');--md-toc-icon:url('data:image/svg+xml;charset=utf-8,')}.md-nav{font-size:.7rem;line-height:1.3}.md-nav__title{display:block;font-weight:700;overflow:hidden;padding:0 .6rem;text-overflow:ellipsis}.md-nav__title .md-nav__button{display:none}.md-nav__title .md-nav__button img{height:100%;width:auto}.md-nav__title .md-nav__button.md-logo :-webkit-any(img,svg){fill:currentcolor;display:block;height:2.4rem;max-width:100%;object-fit:contain;width:auto}.md-nav__title .md-nav__button.md-logo :-moz-any(img,svg){fill:currentcolor;display:block;height:2.4rem;max-width:100%;object-fit:contain;width:auto}.md-nav__title .md-nav__button.md-logo :is(img,svg){fill:currentcolor;display:block;height:2.4rem;max-width:100%;object-fit:contain;width:auto}.md-nav__list{list-style:none;margin:0;padding:0}.md-nav__item{padding:0 .6rem}[dir=ltr] .md-nav__item .md-nav__item{padding-right:0}[dir=rtl] .md-nav__item .md-nav__item{padding-left:0}.md-nav__link{align-items:center;cursor:pointer;display:flex;justify-content:space-between;margin-top:.625em;overflow:hidden;scroll-snap-align:start;text-overflow:ellipsis;transition:color 125ms}.md-nav__link[data-md-state=blur]{color:var(--md-default-fg-color--light)}.md-nav__item .md-nav__link--active{color:var(--md-typeset-a-color)}.md-nav__item .md-nav__link--index [href]{width:100%}.md-nav__link:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav__link:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav__link:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav__link.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-nav--primary .md-nav__link[for=__toc]{display:none}.md-nav--primary .md-nav__link[for=__toc] .md-icon:after{background-color:currentcolor;display:block;height:100%;-webkit-mask-image:var(--md-toc-icon);mask-image:var(--md-toc-icon);width:100%}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:none}.md-nav__link>*{cursor:pointer;display:flex}.md-nav__icon{flex-shrink:0}.md-nav__source{display:none}@media screen and (max-width:76.1875em){.md-nav--primary,.md-nav--primary .md-nav{background-color:var(--md-default-bg-color);display:flex;flex-direction:column;height:100%;left:0;position:absolute;right:0;top:0;z-index:1}.md-nav--primary :-webkit-any(.md-nav__title,.md-nav__item){font-size:.8rem;line-height:1.5}.md-nav--primary :-moz-any(.md-nav__title,.md-nav__item){font-size:.8rem;line-height:1.5}.md-nav--primary :is(.md-nav__title,.md-nav__item){font-size:.8rem;line-height:1.5}.md-nav--primary .md-nav__title{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light);cursor:pointer;height:5.6rem;line-height:2.4rem;padding:3rem .8rem .2rem;position:relative;white-space:nowrap}[dir=ltr] .md-nav--primary .md-nav__title .md-nav__icon{left:.4rem}[dir=rtl] .md-nav--primary .md-nav__title .md-nav__icon{right:.4rem}.md-nav--primary .md-nav__title .md-nav__icon{display:block;height:1.2rem;margin:.2rem;position:absolute;top:.4rem;width:1.2rem}.md-nav--primary .md-nav__title .md-nav__icon:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-nav-icon--prev);mask-image:var(--md-nav-icon--prev);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}.md-nav--primary .md-nav__title~.md-nav__list{background-color:var(--md-default-bg-color);box-shadow:0 .05rem 0 var(--md-default-fg-color--lightest) inset;overflow-y:auto;-ms-scroll-snap-type:y mandatory;scroll-snap-type:y mandatory;touch-action:pan-y}.md-nav--primary .md-nav__title~.md-nav__list>:first-child{border-top:0}.md-nav--primary .md-nav__title[for=__drawer]{background-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color);font-weight:700}.md-nav--primary .md-nav__title .md-logo{display:block;left:.2rem;margin:.2rem;padding:.4rem;position:absolute;right:.2rem;top:.2rem}.md-nav--primary .md-nav__list{flex:1}.md-nav--primary .md-nav__item{border-top:.05rem solid var(--md-default-fg-color--lightest);padding:0}.md-nav--primary .md-nav__item--active>.md-nav__link{color:var(--md-typeset-a-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link{margin-top:0;padding:.6rem .8rem}[dir=ltr] .md-nav--primary .md-nav__link .md-nav__icon{margin-right:-.2rem}[dir=rtl] .md-nav--primary .md-nav__link .md-nav__icon{margin-left:-.2rem}.md-nav--primary .md-nav__link .md-nav__icon{font-size:1.2rem;height:1.2rem;width:1.2rem}.md-nav--primary .md-nav__link .md-nav__icon:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}[dir=rtl] .md-nav--primary .md-nav__icon:after{transform:scale(-1)}.md-nav--primary .md-nav--secondary .md-nav{background-color:initial;position:static}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-left:1.4rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-right:1.4rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-left:2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-right:2rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-left:2.6rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-right:2.6rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-left:3.2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-right:3.2rem}.md-nav--secondary{background-color:initial}.md-nav__toggle~.md-nav{display:flex;opacity:0;transform:translateX(100%);transition:transform .25s cubic-bezier(.8,0,.6,1),opacity 125ms 50ms}[dir=rtl] .md-nav__toggle~.md-nav{transform:translateX(-100%)}.md-nav__toggle:checked~.md-nav{opacity:1;transform:translateX(0);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity 125ms 125ms}.md-nav__toggle:checked~.md-nav>.md-nav__list{-webkit-backface-visibility:hidden;backface-visibility:hidden}}@media screen and (max-width:59.9375em){.md-nav--primary .md-nav__link[for=__toc]{display:flex}.md-nav--primary .md-nav__link[for=__toc] .md-icon:after{content:""}.md-nav--primary .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:flex}.md-nav__source{background-color:var(--md-primary-fg-color--dark);color:var(--md-primary-bg-color);display:block;padding:0 .2rem}}@media screen and (min-width:60em) and (max-width:76.1875em){.md-nav--integrated .md-nav__link[for=__toc]{display:flex}.md-nav--integrated .md-nav__link[for=__toc] .md-icon:after{content:""}.md-nav--integrated .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:flex}}@media screen and (min-width:60em){.md-nav--secondary .md-nav__title[for=__toc]{scroll-snap-align:start}.md-nav--secondary .md-nav__title .md-nav__icon{display:none}}@media screen and (min-width:76.25em){.md-nav{transition:max-height .25s cubic-bezier(.86,0,.07,1)}.md-nav--primary .md-nav__title[for=__drawer]{scroll-snap-align:start}.md-nav--primary .md-nav__title .md-nav__icon,.md-nav__toggle~.md-nav{display:none}.md-nav__toggle:-webkit-any(:checked,:indeterminate)~.md-nav{display:block}.md-nav__toggle:-moz-any(:checked,:indeterminate)~.md-nav{display:block}.md-nav__toggle:is(:checked,:indeterminate)~.md-nav{display:block}.md-nav__item--nested>.md-nav>.md-nav__title{display:none}.md-nav__item--section{display:block;margin:1.25em 0}.md-nav__item--section:last-child{margin-bottom:0}.md-nav__item--section>.md-nav__link{font-weight:700;pointer-events:none}.md-nav__item--section>.md-nav__link--index [href]{pointer-events:auto}.md-nav__item--section>.md-nav__link .md-nav__icon{display:none}.md-nav__item--section>.md-nav{display:block}.md-nav__item--section>.md-nav>.md-nav__list>.md-nav__item{padding:0}.md-nav__icon{border-radius:100%;float:right;height:.9rem;transition:background-color .25s,transform .25s;width:.9rem}[dir=rtl] .md-nav__icon{float:left;transform:rotate(180deg)}.md-nav__icon:hover{background-color:var(--md-accent-fg-color--transparent)}.md-nav__icon:after{background-color:currentcolor;content:"";display:inline-block;height:100%;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;vertical-align:-.1rem;width:100%}.md-nav__item--nested .md-nav__toggle:checked~.md-nav__link .md-nav__icon,.md-nav__item--nested .md-nav__toggle:indeterminate~.md-nav__link .md-nav__icon{transform:rotate(90deg)}.md-nav--lifted>.md-nav__list>.md-nav__item,.md-nav--lifted>.md-nav__list>.md-nav__item--nested,.md-nav--lifted>.md-nav__title{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active{display:block;padding:0}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link{font-weight:700;margin-top:0;padding:0 .6rem;pointer-events:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link--index [href]{pointer-events:auto}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link .md-nav__icon{display:none}.md-nav--lifted .md-nav[data-md-level="1"]{display:block}[dir=ltr] .md-nav--lifted .md-nav[data-md-level="1"]>.md-nav__list>.md-nav__item{padding-right:.6rem}[dir=rtl] .md-nav--lifted .md-nav[data-md-level="1"]>.md-nav__list>.md-nav__item{padding-left:.6rem}.md-nav--integrated>.md-nav__list>.md-nav__item--active:not(.md-nav__item--nested){padding:0 .6rem}.md-nav--integrated>.md-nav__list>.md-nav__item--active:not(.md-nav__item--nested)>.md-nav__link{padding:0}[dir=ltr] .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{border-left:.05rem solid var(--md-primary-fg-color)}[dir=rtl] .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{border-right:.05rem solid var(--md-primary-fg-color)}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{display:block;margin-bottom:1.25em}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary>.md-nav__title{display:none}}:root{--md-search-result-icon:url('data:image/svg+xml;charset=utf-8,')}.md-search{position:relative}@media screen and (min-width:60em){.md-search{padding:.2rem 0}}.no-js .md-search{display:none}.md-search__overlay{opacity:0;z-index:1}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__overlay{left:-2.2rem}[dir=rtl] .md-search__overlay{right:-2.2rem}.md-search__overlay{background-color:var(--md-default-bg-color);border-radius:1rem;height:2rem;overflow:hidden;pointer-events:none;position:absolute;top:-1rem;transform-origin:center;transition:transform .3s .1s,opacity .2s .2s;width:2rem}[data-md-toggle=search]:checked~.md-header .md-search__overlay{opacity:1;transition:transform .4s,opacity .1s}}@media screen and (min-width:60em){[dir=ltr] .md-search__overlay{left:0}[dir=rtl] .md-search__overlay{right:0}.md-search__overlay{background-color:rgba(0,0,0,.54);cursor:pointer;height:0;position:fixed;top:0;transition:width 0ms .25s,height 0ms .25s,opacity .25s;width:0}[data-md-toggle=search]:checked~.md-header .md-search__overlay{height:200vh;opacity:1;transition:width 0ms,height 0ms,opacity .25s;width:100%}}@media screen and (max-width:29.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(45)}}@media screen and (min-width:30em) and (max-width:44.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(60)}}@media screen and (min-width:45em) and (max-width:59.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(75)}}.md-search__inner{-webkit-backface-visibility:hidden;backface-visibility:hidden}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__inner{left:0}[dir=rtl] .md-search__inner{right:0}.md-search__inner{height:0;opacity:0;overflow:hidden;position:fixed;top:0;transform:translateX(5%);transition:width 0ms .3s,height 0ms .3s,transform .15s cubic-bezier(.4,0,.2,1) .15s,opacity .15s .15s;width:0;z-index:2}[dir=rtl] .md-search__inner{transform:translateX(-5%)}[data-md-toggle=search]:checked~.md-header .md-search__inner{height:100%;opacity:1;transform:translateX(0);transition:width 0ms 0ms,height 0ms 0ms,transform .15s cubic-bezier(.1,.7,.1,1) .15s,opacity .15s .15s;width:100%}}@media screen and (min-width:60em){.md-search__inner{float:right;padding:.1rem 0;position:relative;transition:width .25s cubic-bezier(.1,.7,.1,1);width:11.7rem}[dir=rtl] .md-search__inner{float:left}}@media screen and (min-width:60em) and (max-width:76.1875em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:23.4rem}}@media screen and (min-width:76.25em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:34.4rem}}.md-search__form{background-color:var(--md-default-bg-color);box-shadow:0 0 .6rem transparent;height:2.4rem;position:relative;transition:color .25s,background-color .25s;z-index:2}@media screen and (min-width:60em){.md-search__form{background-color:rgba(0,0,0,.26);border-radius:.1rem;height:1.8rem}.md-search__form:hover{background-color:hsla(0,0%,100%,.12)}}[data-md-toggle=search]:checked~.md-header .md-search__form{background-color:var(--md-default-bg-color);border-radius:.1rem .1rem 0 0;box-shadow:0 0 .6rem rgba(0,0,0,.07);color:var(--md-default-fg-color)}[dir=ltr] .md-search__input{padding-left:3.6rem;padding-right:2.2rem}[dir=rtl] .md-search__input{padding-left:2.2rem;padding-right:3.6rem}.md-search__input{background:transparent;font-size:.9rem;height:100%;position:relative;text-overflow:ellipsis;width:100%;z-index:2}.md-search__input::-moz-placeholder{-moz-transition:color .25s;transition:color .25s}.md-search__input::-ms-input-placeholder{-ms-transition:color .25s;transition:color .25s}.md-search__input::placeholder{transition:color .25s}.md-search__input::-moz-placeholder{color:var(--md-default-fg-color--light)}.md-search__input::-ms-input-placeholder{color:var(--md-default-fg-color--light)}.md-search__input::placeholder,.md-search__input~.md-search__icon{color:var(--md-default-fg-color--light)}.md-search__input::-ms-clear{display:none}@media screen and (max-width:59.9375em){.md-search__input{font-size:.9rem;height:2.4rem;width:100%}}@media screen and (min-width:60em){[dir=ltr] .md-search__input{padding-left:2.2rem}[dir=rtl] .md-search__input{padding-right:2.2rem}.md-search__input{color:inherit;font-size:.8rem}.md-search__input::-moz-placeholder{color:var(--md-primary-bg-color--light)}.md-search__input::-ms-input-placeholder{color:var(--md-primary-bg-color--light)}.md-search__input::placeholder{color:var(--md-primary-bg-color--light)}.md-search__input+.md-search__icon{color:var(--md-primary-bg-color)}[data-md-toggle=search]:checked~.md-header .md-search__input{text-overflow:clip}[data-md-toggle=search]:checked~.md-header .md-search__input::-moz-placeholder{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input::-ms-input-placeholder{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input+.md-search__icon,[data-md-toggle=search]:checked~.md-header .md-search__input::placeholder{color:var(--md-default-fg-color--light)}}.md-search__icon{cursor:pointer;display:inline-block;height:1.2rem;transition:color .25s,opacity .25s;width:1.2rem}.md-search__icon:hover{opacity:.7}[dir=ltr] .md-search__icon[for=__search]{left:.5rem}[dir=rtl] .md-search__icon[for=__search]{right:.5rem}.md-search__icon[for=__search]{position:absolute;top:.3rem;z-index:2}[dir=rtl] .md-search__icon[for=__search] svg{transform:scaleX(-1)}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__icon[for=__search]{left:.8rem}[dir=rtl] .md-search__icon[for=__search]{right:.8rem}.md-search__icon[for=__search]{top:.6rem}.md-search__icon[for=__search] svg:first-child{display:none}}@media screen and (min-width:60em){.md-search__icon[for=__search]{pointer-events:none}.md-search__icon[for=__search] svg:last-child{display:none}}[dir=ltr] .md-search__options{right:.5rem}[dir=rtl] .md-search__options{left:.5rem}.md-search__options{pointer-events:none;position:absolute;top:.3rem;z-index:2}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__options{right:.8rem}[dir=rtl] .md-search__options{left:.8rem}.md-search__options{top:.6rem}}[dir=ltr] .md-search__options>*{margin-left:.2rem}[dir=rtl] .md-search__options>*{margin-right:.2rem}.md-search__options>*{color:var(--md-default-fg-color--light);opacity:0;transform:scale(.75);transition:transform .15s cubic-bezier(.1,.7,.1,1),opacity .15s}.md-search__options>:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__options>*{opacity:1;pointer-events:auto;transform:scale(1)}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__options>:hover{opacity:.7}[dir=ltr] .md-search__suggest{padding-left:3.6rem;padding-right:2.2rem}[dir=rtl] .md-search__suggest{padding-left:2.2rem;padding-right:3.6rem}.md-search__suggest{align-items:center;color:var(--md-default-fg-color--lighter);display:flex;font-size:.9rem;height:100%;opacity:0;position:absolute;top:0;transition:opacity 50ms;white-space:nowrap;width:100%}@media screen and (min-width:60em){[dir=ltr] .md-search__suggest{padding-left:2.2rem}[dir=rtl] .md-search__suggest{padding-right:2.2rem}.md-search__suggest{font-size:.8rem}}[data-md-toggle=search]:checked~.md-header .md-search__suggest{opacity:1;transition:opacity .3s .1s}[dir=ltr] .md-search__output{border-bottom-left-radius:.1rem}[dir=ltr] .md-search__output,[dir=rtl] .md-search__output{border-bottom-right-radius:.1rem}[dir=rtl] .md-search__output{border-bottom-left-radius:.1rem}.md-search__output{overflow:hidden;position:absolute;width:100%;z-index:1}@media screen and (max-width:59.9375em){.md-search__output{bottom:0;top:2.4rem}}@media screen and (min-width:60em){.md-search__output{opacity:0;top:1.9rem;transition:opacity .4s}[data-md-toggle=search]:checked~.md-header .md-search__output{box-shadow:var(--md-shadow-z3);opacity:1}}.md-search__scrollwrap{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:var(--md-default-bg-color);height:100%;overflow-y:auto;touch-action:pan-y}@media (-webkit-max-device-pixel-ratio:1),(max-resolution:1dppx){.md-search__scrollwrap{transform:translateZ(0)}}@media screen and (min-width:60em) and (max-width:76.1875em){.md-search__scrollwrap{width:23.4rem}}@media screen and (min-width:76.25em){.md-search__scrollwrap{width:34.4rem}}@media screen and (min-width:60em){.md-search__scrollwrap{max-height:0;scrollbar-color:var(--md-default-fg-color--lighter) transparent;scrollbar-width:thin}[data-md-toggle=search]:checked~.md-header .md-search__scrollwrap{max-height:75vh}.md-search__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-search__scrollwrap::-webkit-scrollbar{height:.2rem;width:.2rem}.md-search__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}}.md-search-result{color:var(--md-default-fg-color);word-break:break-word}.md-search-result__meta{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.8rem;padding:0 .8rem;scroll-snap-align:start}@media screen and (min-width:60em){[dir=ltr] .md-search-result__meta{padding-left:2.2rem}[dir=rtl] .md-search-result__meta{padding-right:2.2rem}}.md-search-result__list{list-style:none;margin:0;padding:0}.md-search-result__item{box-shadow:0 -.05rem var(--md-default-fg-color--lightest)}.md-search-result__item:first-child{box-shadow:none}.md-search-result__link{display:block;outline:none;scroll-snap-align:start;transition:background-color .25s}.md-search-result__link:-webkit-any(:focus,:hover){background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:-moz-any(:focus,:hover){background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:is(:focus,:hover){background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:last-child p:last-child{margin-bottom:.6rem}.md-search-result__more summary{color:var(--md-typeset-a-color);cursor:pointer;display:block;font-size:.64rem;outline:none;padding:.75em .8rem;scroll-snap-align:start;transition:color .25s,background-color .25s}@media screen and (min-width:60em){[dir=ltr] .md-search-result__more summary{padding-left:2.2rem}[dir=rtl] .md-search-result__more summary{padding-right:2.2rem}}.md-search-result__more summary:-webkit-any(:focus,:hover){background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-search-result__more summary:-moz-any(:focus,:hover){background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-search-result__more summary:is(:focus,:hover){background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-search-result__more summary::marker{display:none}.md-search-result__more summary::-webkit-details-marker{display:none}.md-search-result__more summary~*>*{opacity:.65}.md-search-result__article{overflow:hidden;padding:0 .8rem;position:relative}@media screen and (min-width:60em){[dir=ltr] .md-search-result__article{padding-left:2.2rem}[dir=rtl] .md-search-result__article{padding-right:2.2rem}}.md-search-result__article--document .md-search-result__title{font-size:.8rem;font-weight:400;line-height:1.4;margin:.55rem 0}[dir=ltr] .md-search-result__icon{left:0}[dir=rtl] .md-search-result__icon{right:0}.md-search-result__icon{color:var(--md-default-fg-color--light);height:1.2rem;margin:.5rem;position:absolute;width:1.2rem}@media screen and (max-width:59.9375em){.md-search-result__icon{display:none}}.md-search-result__icon:after{background-color:currentcolor;content:"";display:inline-block;height:100%;-webkit-mask-image:var(--md-search-result-icon);mask-image:var(--md-search-result-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}[dir=rtl] .md-search-result__icon:after{transform:scaleX(-1)}.md-search-result__title{font-size:.64rem;font-weight:700;line-height:1.6;margin:.5em 0}.md-search-result__teaser{-webkit-box-orient:vertical;-webkit-line-clamp:2;color:var(--md-default-fg-color--light);display:-webkit-box;font-size:.64rem;line-height:1.6;margin:.5em 0;max-height:2rem;overflow:hidden;text-overflow:ellipsis}@media screen and (max-width:44.9375em){.md-search-result__teaser{-webkit-line-clamp:3;max-height:3rem}}@media screen and (min-width:60em) and (max-width:76.1875em){.md-search-result__teaser{-webkit-line-clamp:3;max-height:3rem}}.md-search-result__teaser mark{background-color:initial;text-decoration:underline}.md-search-result__terms{font-size:.64rem;font-style:italic;margin:.5em 0}.md-search-result mark{background-color:initial;color:var(--md-accent-fg-color)}.md-select{position:relative;z-index:1}.md-select__inner{background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);left:50%;margin-top:.2rem;max-height:0;opacity:0;position:absolute;top:calc(100% - .2rem);transform:translate3d(-50%,.3rem,0);transition:transform .25s 375ms,opacity .25s .25s,max-height 0ms .5s}.md-select:-webkit-any(:focus-within,:hover) .md-select__inner{max-height:10rem;opacity:1;transform:translate3d(-50%,0,0);-webkit-transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms;transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms}.md-select:-moz-any(:focus-within,:hover) .md-select__inner{max-height:10rem;opacity:1;transform:translate3d(-50%,0,0);-moz-transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms;transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms}.md-select:is(:focus-within,:hover) .md-select__inner{max-height:10rem;opacity:1;transform:translate3d(-50%,0,0);transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms}.md-select__inner:after{border-bottom:.2rem solid transparent;border-bottom-color:var(--md-default-bg-color);border-left:.2rem solid transparent;border-right:.2rem solid transparent;border-top:0;content:"";height:0;left:50%;margin-left:-.2rem;margin-top:-.2rem;position:absolute;top:0;width:0}.md-select__list{border-radius:.1rem;font-size:.8rem;list-style-type:none;margin:0;max-height:inherit;overflow:auto;padding:0}.md-select__item{line-height:1.8rem}[dir=ltr] .md-select__link{padding-left:.6rem;padding-right:1.2rem}[dir=rtl] .md-select__link{padding-left:1.2rem;padding-right:.6rem}.md-select__link{cursor:pointer;display:block;outline:none;scroll-snap-align:start;transition:background-color .25s,color .25s;width:100%}.md-select__link:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-select__link:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-select__link:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-select__link:focus{background-color:var(--md-default-fg-color--lightest)}.md-sidebar{align-self:flex-start;flex-shrink:0;padding:1.2rem 0;position:-webkit-sticky;position:sticky;top:2.4rem;width:12.1rem}@media print{.md-sidebar{display:none}}@media screen and (max-width:76.1875em){[dir=ltr] .md-sidebar--primary{left:-12.1rem}[dir=rtl] .md-sidebar--primary{right:-12.1rem}.md-sidebar--primary{background-color:var(--md-default-bg-color);display:block;height:100%;position:fixed;top:0;transform:translateX(0);transition:transform .25s cubic-bezier(.4,0,.2,1),box-shadow .25s;width:12.1rem;z-index:5}[data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{box-shadow:var(--md-shadow-z3);transform:translateX(12.1rem)}[dir=rtl] [data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{transform:translateX(-12.1rem)}.md-sidebar--primary .md-sidebar__scrollwrap{bottom:0;left:0;margin:0;overflow:hidden;position:absolute;right:0;-ms-scroll-snap-type:none;scroll-snap-type:none;top:0}}@media screen and (min-width:76.25em){.md-sidebar{height:0}.no-js .md-sidebar{height:auto}}.md-sidebar--secondary{display:none;order:2}@media screen and (min-width:60em){.md-sidebar--secondary{height:0}.no-js .md-sidebar--secondary{height:auto}.md-sidebar--secondary:not([hidden]){display:block}.md-sidebar--secondary .md-sidebar__scrollwrap{touch-action:pan-y}}.md-sidebar__scrollwrap{-webkit-backface-visibility:hidden;backface-visibility:hidden;margin:0 .2rem;overflow-y:auto;scrollbar-color:var(--md-default-fg-color--lighter) transparent;scrollbar-width:thin}.md-sidebar__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-sidebar__scrollwrap::-webkit-scrollbar{height:.2rem;width:.2rem}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@media screen and (max-width:76.1875em){.md-overlay{background-color:rgba(0,0,0,.54);height:0;opacity:0;position:fixed;top:0;transition:width 0ms .25s,height 0ms .25s,opacity .25s;width:0;z-index:5}[data-md-toggle=drawer]:checked~.md-overlay{height:100%;opacity:1;transition:width 0ms,height 0ms,opacity .25s;width:100%}}@-webkit-keyframes facts{0%{height:0}to{height:.65rem}}@keyframes facts{0%{height:0}to{height:.65rem}}@-webkit-keyframes fact{0%{opacity:0;transform:translateY(100%)}50%{opacity:0}to{opacity:1;transform:translateY(0)}}@keyframes fact{0%{opacity:0;transform:translateY(100%)}50%{opacity:0}to{opacity:1;transform:translateY(0)}}:root{--md-source-forks-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-repositories-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-stars-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-version-icon:url('data:image/svg+xml;charset=utf-8,')}.md-source{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:block;font-size:.65rem;line-height:1.2;outline-color:var(--md-accent-fg-color);transition:opacity .25s;white-space:nowrap}.md-source:hover{opacity:.7}.md-source__icon{display:inline-block;height:2.4rem;vertical-align:middle;width:2rem}[dir=ltr] .md-source__icon svg{margin-left:.6rem}[dir=rtl] .md-source__icon svg{margin-right:.6rem}.md-source__icon svg{margin-top:.6rem}[dir=ltr] .md-source__icon+.md-source__repository{margin-left:-2rem}[dir=rtl] .md-source__icon+.md-source__repository{margin-right:-2rem}[dir=ltr] .md-source__icon+.md-source__repository{padding-left:2rem}[dir=rtl] .md-source__icon+.md-source__repository{padding-right:2rem}[dir=ltr] .md-source__repository{margin-left:.6rem}[dir=rtl] .md-source__repository{margin-right:.6rem}.md-source__repository{display:inline-block;max-width:calc(100% - 1.2rem);overflow:hidden;text-overflow:ellipsis;vertical-align:middle}.md-source__facts{font-size:.55rem;list-style-type:none;margin:.1rem 0 0;opacity:.75;overflow:hidden;padding:0}[data-md-state=done] .md-source__facts{-webkit-animation:facts .25s ease-in;animation:facts .25s ease-in}.md-source__fact{display:inline-block}[data-md-state=done] .md-source__fact{-webkit-animation:fact .4s ease-out;animation:fact .4s ease-out}[dir=ltr] .md-source__fact:before{margin-right:.1rem}[dir=rtl] .md-source__fact:before{margin-left:.1rem}.md-source__fact:before{background-color:currentcolor;content:"";display:inline-block;height:.6rem;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;vertical-align:text-top;width:.6rem}[dir=ltr] .md-source__fact:nth-child(1n+2):before{margin-left:.4rem}[dir=rtl] .md-source__fact:nth-child(1n+2):before{margin-right:.4rem}.md-source__fact--version:before{-webkit-mask-image:var(--md-source-version-icon);mask-image:var(--md-source-version-icon)}.md-source__fact--stars:before{-webkit-mask-image:var(--md-source-stars-icon);mask-image:var(--md-source-stars-icon)}.md-source__fact--forks:before{-webkit-mask-image:var(--md-source-forks-icon);mask-image:var(--md-source-forks-icon)}.md-source__fact--repositories:before{-webkit-mask-image:var(--md-source-repositories-icon);mask-image:var(--md-source-repositories-icon)}.md-tabs{background-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color);overflow:auto;width:100%}@media print{.md-tabs{display:none}}@media screen and (max-width:76.1875em){.md-tabs{display:none}}.md-tabs[data-md-state=hidden]{pointer-events:none}[dir=ltr] .md-tabs__list{margin-left:.2rem}[dir=rtl] .md-tabs__list{margin-right:.2rem}.md-tabs__list{contain:content;list-style:none;margin:0;padding:0;white-space:nowrap}.md-tabs__item{display:inline-block;height:2.4rem;padding-left:.6rem;padding-right:.6rem}.md-tabs__link{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:block;font-size:.7rem;margin-top:.8rem;opacity:.7;outline-color:var(--md-accent-fg-color);outline-offset:.2rem;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .25s}.md-tabs__link--active,.md-tabs__link:-webkit-any(:focus,:hover){color:inherit;opacity:1}.md-tabs__link--active,.md-tabs__link:-moz-any(:focus,:hover){color:inherit;opacity:1}.md-tabs__link--active,.md-tabs__link:is(:focus,:hover){color:inherit;opacity:1}.md-tabs__item:nth-child(2) .md-tabs__link{transition-delay:20ms}.md-tabs__item:nth-child(3) .md-tabs__link{transition-delay:40ms}.md-tabs__item:nth-child(4) .md-tabs__link{transition-delay:60ms}.md-tabs__item:nth-child(5) .md-tabs__link{transition-delay:80ms}.md-tabs__item:nth-child(6) .md-tabs__link{transition-delay:.1s}.md-tabs__item:nth-child(7) .md-tabs__link{transition-delay:.12s}.md-tabs__item:nth-child(8) .md-tabs__link{transition-delay:.14s}.md-tabs__item:nth-child(9) .md-tabs__link{transition-delay:.16s}.md-tabs__item:nth-child(10) .md-tabs__link{transition-delay:.18s}.md-tabs__item:nth-child(11) .md-tabs__link{transition-delay:.2s}.md-tabs__item:nth-child(12) .md-tabs__link{transition-delay:.22s}.md-tabs__item:nth-child(13) .md-tabs__link{transition-delay:.24s}.md-tabs__item:nth-child(14) .md-tabs__link{transition-delay:.26s}.md-tabs__item:nth-child(15) .md-tabs__link{transition-delay:.28s}.md-tabs__item:nth-child(16) .md-tabs__link{transition-delay:.3s}.md-tabs[data-md-state=hidden] .md-tabs__link{opacity:0;transform:translateY(50%);transition:transform 0ms .1s,opacity .1s}.md-tags{margin-bottom:.75em}[dir=ltr] .md-tag{margin-right:.5em}[dir=rtl] .md-tag{margin-left:.5em}.md-tag{background:var(--md-default-fg-color--lightest);border-radius:.4rem;display:inline-block;font-size:.64rem;font-weight:700;line-height:1.6;margin-bottom:.5em;padding:.3125em .9375em}.md-tag[href]{-webkit-tap-highlight-color:transparent;color:inherit;outline:none;transition:color 125ms,background-color 125ms}.md-tag[href]:focus,.md-tag[href]:hover{background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}[id]>.md-tag{vertical-align:text-top}@-webkit-keyframes pulse{0%{box-shadow:0 0 0 0 var(--md-default-fg-color--lightest)}75%{box-shadow:0 0 0 .625em transparent}to{box-shadow:0 0 0 0 transparent}}@keyframes pulse{0%{box-shadow:0 0 0 0 var(--md-default-fg-color--lightest)}75%{box-shadow:0 0 0 .625em transparent}to{box-shadow:0 0 0 0 transparent}}:root{--md-tooltip-width:20rem}.md-tooltip{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);left:clamp(var(--md-tooltip-0,0rem) + .8rem,var(--md-tooltip-x),(100vw + var(--md-tooltip-0,0rem) + .8rem - var(--md-tooltip-width) - 2 * .8rem));max-height:0;max-width:calc(100vw - 1.6rem);opacity:0;position:absolute;top:var(--md-tooltip-y);transform:translateY(-.4rem);transition:transform 0ms .25s,opacity .25s,max-height 0ms .25s,z-index .25s;width:var(--md-tooltip-width);z-index:0}:focus-within>.md-tooltip{max-height:1000%;opacity:1;transform:translateY(0);transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height .25s,z-index 0ms}.focus-visible>.md-tooltip{outline:var(--md-accent-fg-color) auto}.md-tooltip__inner{font-size:.64rem;padding:.8rem}.md-tooltip__inner.md-typeset>:first-child{margin-top:0}.md-tooltip__inner.md-typeset>:last-child{margin-bottom:0}.md-annotation{outline:none;white-space:normal}[dir=rtl] .md-annotation{direction:rtl}.md-annotation:not([hidden]){display:inline-block;line-height:1.325}.md-annotation:focus-within>*{z-index:2}.md-annotation__inner{font-family:var(--md-text-font-family);top:calc(var(--md-tooltip-y) + 1.2ch)}:not(:focus-within)>.md-annotation__inner{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.md-annotation__index{color:#fff;cursor:pointer;margin:0 1ch;position:relative;transition:z-index .25s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:0}.md-annotation__index:after{-webkit-animation:pulse 2s infinite;animation:pulse 2s infinite;background-color:var(--md-default-fg-color--lighter);border-radius:2ch;content:"";height:2.2ch;left:-.126em;margin:0 -.4ch;padding:0 .4ch;position:absolute;transition:color .25s,background-color .25s;width:calc(100% + 1.2ch);width:max(2.2ch,100% + 1.2ch);z-index:-1}@media (prefers-reduced-motion){.md-annotation__index:after{-webkit-animation:none;animation:none}}:-webkit-any(:focus-within,:hover)>.md-annotation__index:after{background-color:var(--md-accent-fg-color)}:-moz-any(:focus-within,:hover)>.md-annotation__index:after{background-color:var(--md-accent-fg-color)}:is(:focus-within,:hover)>.md-annotation__index:after{background-color:var(--md-accent-fg-color)}:focus-within>.md-annotation__index:after{-webkit-animation:none;animation:none;transition:color .25s,background-color .25s}.md-annotation__index [data-md-annotation-id]{display:inline-block;line-height:90%}.md-annotation__index [data-md-annotation-id]:before{content:attr(data-md-annotation-id);display:inline-block;padding-bottom:.1em;transition:transform .4s cubic-bezier(.1,.7,.1,1);vertical-align:.0625em}@media not print{.md-annotation__index [data-md-annotation-id]:before{content:"+"}:focus-within>.md-annotation__index [data-md-annotation-id]:before{transform:rotate(45deg)}}:-webkit-any(:focus-within,:hover)>.md-annotation__index{color:var(--md-accent-bg-color)}:-moz-any(:focus-within,:hover)>.md-annotation__index{color:var(--md-accent-bg-color)}:is(:focus-within,:hover)>.md-annotation__index{color:var(--md-accent-bg-color)}:focus-within>.md-annotation__index{-webkit-animation:none;animation:none;transition:none}[dir=ltr] .md-top{margin-left:50%}[dir=rtl] .md-top{margin-right:50%}.md-top{background-color:var(--md-default-bg-color);border-radius:1.6rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color--light);font-size:.7rem;outline:none;padding:.4rem .8rem;position:fixed;top:3.2rem;transform:translate(-50%);transition:color 125ms,background-color 125ms,transform 125ms cubic-bezier(.4,0,.2,1),opacity 125ms;z-index:2}@media print{.md-top{display:none}}[dir=rtl] .md-top{transform:translate(50%)}.md-top[data-md-state=hidden]{opacity:0;pointer-events:none;transform:translate(-50%,.2rem);transition-duration:0ms}[dir=rtl] .md-top[data-md-state=hidden]{transform:translate(50%,.2rem)}.md-top:-webkit-any(:focus,:hover){background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-top:-moz-any(:focus,:hover){background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-top:is(:focus,:hover){background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-top svg{display:inline-block;vertical-align:-.5em}@-webkit-keyframes hoverfix{0%{pointer-events:none}}@keyframes hoverfix{0%{pointer-events:none}}:root{--md-version-icon:url('data:image/svg+xml;charset=utf-8,')}.md-version{flex-shrink:0;font-size:.8rem;height:2.4rem}[dir=ltr] .md-version__current{margin-left:1.4rem;margin-right:.4rem}[dir=rtl] .md-version__current{margin-left:.4rem;margin-right:1.4rem}.md-version__current{color:inherit;cursor:pointer;outline:none;position:relative;top:.05rem}[dir=ltr] .md-version__current:after{margin-left:.4rem}[dir=rtl] .md-version__current:after{margin-right:.4rem}.md-version__current:after{background-color:currentcolor;content:"";display:inline-block;height:.6rem;-webkit-mask-image:var(--md-version-icon);mask-image:var(--md-version-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;width:.4rem}.md-version__list{background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);list-style-type:none;margin:.2rem .8rem;max-height:0;opacity:0;overflow:auto;padding:0;position:absolute;-ms-scroll-snap-type:y mandatory;scroll-snap-type:y mandatory;top:.15rem;transition:max-height 0ms .5s,opacity .25s .25s;z-index:3}.md-version:-webkit-any(:focus-within,:hover) .md-version__list{max-height:10rem;opacity:1;-webkit-transition:max-height 0ms,opacity .25s;transition:max-height 0ms,opacity .25s}.md-version:-moz-any(:focus-within,:hover) .md-version__list{max-height:10rem;opacity:1;-moz-transition:max-height 0ms,opacity .25s;transition:max-height 0ms,opacity .25s}.md-version:is(:focus-within,:hover) .md-version__list{max-height:10rem;opacity:1;transition:max-height 0ms,opacity .25s}@media (pointer:coarse){.md-version:hover .md-version__list{-webkit-animation:hoverfix .25s forwards;animation:hoverfix .25s forwards}.md-version:focus-within .md-version__list{-webkit-animation:none;animation:none}}.md-version__item{line-height:1.8rem}[dir=ltr] .md-version__link{padding-left:.6rem;padding-right:1.2rem}[dir=rtl] .md-version__link{padding-left:1.2rem;padding-right:.6rem}.md-version__link{cursor:pointer;display:block;outline:none;scroll-snap-align:start;transition:color .25s,background-color .25s;white-space:nowrap;width:100%}.md-version__link:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-version__link:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-version__link:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-version__link:focus{background-color:var(--md-default-fg-color--lightest)}:root{--md-admonition-icon--note:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--abstract:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--info:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--tip:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--success:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--question:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--warning:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--failure:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--danger:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--bug:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--example:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--quote:url('data:image/svg+xml;charset=utf-8,')}.md-typeset :-webkit-any(.admonition,details){background-color:var(--md-admonition-bg-color);border:0 solid #448aff;border-radius:.1rem;box-shadow:var(--md-shadow-z1);color:var(--md-admonition-fg-color);display:flow-root;font-size:.64rem;margin:1.5625em 0;padding:0 .6rem;page-break-inside:avoid}.md-typeset :-moz-any(.admonition,details){background-color:var(--md-admonition-bg-color);border:0 solid #448aff;border-radius:.1rem;box-shadow:var(--md-shadow-z1);color:var(--md-admonition-fg-color);display:flow-root;font-size:.64rem;margin:1.5625em 0;padding:0 .6rem;page-break-inside:avoid}[dir=ltr] .md-typeset :-webkit-any(.admonition,details){border-left-width:.2rem}[dir=ltr] .md-typeset :-moz-any(.admonition,details){border-left-width:.2rem}[dir=ltr] .md-typeset :is(.admonition,details){border-left-width:.2rem}[dir=rtl] .md-typeset :-webkit-any(.admonition,details){border-right-width:.2rem}[dir=rtl] .md-typeset :-moz-any(.admonition,details){border-right-width:.2rem}[dir=rtl] .md-typeset :is(.admonition,details){border-right-width:.2rem}.md-typeset :is(.admonition,details){background-color:var(--md-admonition-bg-color);border:0 solid #448aff;border-radius:.1rem;box-shadow:var(--md-shadow-z1);color:var(--md-admonition-fg-color);display:flow-root;font-size:.64rem;margin:1.5625em 0;padding:0 .6rem;page-break-inside:avoid}@media print{.md-typeset :-webkit-any(.admonition,details){box-shadow:none}.md-typeset :-moz-any(.admonition,details){box-shadow:none}.md-typeset :is(.admonition,details){box-shadow:none}}.md-typeset :-webkit-any(.admonition,details)>*{box-sizing:border-box}.md-typeset :-moz-any(.admonition,details)>*{box-sizing:border-box}.md-typeset :is(.admonition,details)>*{box-sizing:border-box}.md-typeset :-webkit-any(.admonition,details) :-webkit-any(.admonition,details){margin-bottom:1em;margin-top:1em}.md-typeset :-moz-any(.admonition,details) :-moz-any(.admonition,details){margin-bottom:1em;margin-top:1em}.md-typeset :is(.admonition,details) :is(.admonition,details){margin-bottom:1em;margin-top:1em}.md-typeset :-webkit-any(.admonition,details) .md-typeset__scrollwrap{margin:1em -.6rem}.md-typeset :-moz-any(.admonition,details) .md-typeset__scrollwrap{margin:1em -.6rem}.md-typeset :is(.admonition,details) .md-typeset__scrollwrap{margin:1em -.6rem}.md-typeset :-webkit-any(.admonition,details) .md-typeset__table{padding:0 .6rem}.md-typeset :-moz-any(.admonition,details) .md-typeset__table{padding:0 .6rem}.md-typeset :is(.admonition,details) .md-typeset__table{padding:0 .6rem}.md-typeset :-webkit-any(.admonition,details)>.tabbed-set:only-child{margin-top:0}.md-typeset :-moz-any(.admonition,details)>.tabbed-set:only-child{margin-top:0}.md-typeset :is(.admonition,details)>.tabbed-set:only-child{margin-top:0}html .md-typeset :-webkit-any(.admonition,details)>:last-child{margin-bottom:.6rem}html .md-typeset :-moz-any(.admonition,details)>:last-child{margin-bottom:.6rem}html .md-typeset :is(.admonition,details)>:last-child{margin-bottom:.6rem}.md-typeset :-webkit-any(.admonition-title,summary){background-color:rgba(68,138,255,.1);border:none;font-weight:700;margin-bottom:0;margin-top:0;padding-bottom:.4rem;padding-top:.4rem;position:relative}.md-typeset :-moz-any(.admonition-title,summary){background-color:rgba(68,138,255,.1);border:none;font-weight:700;margin-bottom:0;margin-top:0;padding-bottom:.4rem;padding-top:.4rem;position:relative}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary){margin-left:-.8rem;margin-right:-.6rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary){margin-left:-.8rem;margin-right:-.6rem}[dir=ltr] .md-typeset :is(.admonition-title,summary){margin-left:-.8rem;margin-right:-.6rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary){margin-left:-.6rem;margin-right:-.8rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary){margin-left:-.6rem;margin-right:-.8rem}[dir=rtl] .md-typeset :is(.admonition-title,summary){margin-left:-.6rem;margin-right:-.8rem}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary){padding-left:2.2rem;padding-right:.6rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary){padding-left:2.2rem;padding-right:.6rem}[dir=ltr] .md-typeset :is(.admonition-title,summary){padding-left:2.2rem;padding-right:.6rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary){padding-left:.6rem;padding-right:2.2rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary){padding-left:.6rem;padding-right:2.2rem}[dir=rtl] .md-typeset :is(.admonition-title,summary){padding-left:.6rem;padding-right:2.2rem}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary){border-left-width:.2rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary){border-left-width:.2rem}[dir=ltr] .md-typeset :is(.admonition-title,summary){border-left-width:.2rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary){border-right-width:.2rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary){border-right-width:.2rem}[dir=rtl] .md-typeset :is(.admonition-title,summary){border-right-width:.2rem}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary){border-top-left-radius:.1rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary){border-top-left-radius:.1rem}[dir=ltr] .md-typeset :is(.admonition-title,summary){border-top-left-radius:.1rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary){border-top-right-radius:.1rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary){border-top-right-radius:.1rem}[dir=rtl] .md-typeset :is(.admonition-title,summary){border-top-right-radius:.1rem}.md-typeset :is(.admonition-title,summary){background-color:rgba(68,138,255,.1);border:none;font-weight:700;margin-bottom:0;margin-top:0;padding-bottom:.4rem;padding-top:.4rem;position:relative}html .md-typeset :-webkit-any(.admonition-title,summary):last-child{margin-bottom:0}html .md-typeset :-moz-any(.admonition-title,summary):last-child{margin-bottom:0}html .md-typeset :is(.admonition-title,summary):last-child{margin-bottom:0}.md-typeset :-webkit-any(.admonition-title,summary):before{background-color:#448aff;content:"";height:1rem;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;width:1rem}.md-typeset :-moz-any(.admonition-title,summary):before{background-color:#448aff;content:"";height:1rem;mask-image:var(--md-admonition-icon--note);mask-repeat:no-repeat;mask-size:contain;position:absolute;top:.625em;width:1rem}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary):before{left:.8rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary):before{left:.8rem}[dir=ltr] .md-typeset :is(.admonition-title,summary):before{left:.8rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary):before{right:.8rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary):before{right:.8rem}[dir=rtl] .md-typeset :is(.admonition-title,summary):before{right:.8rem}.md-typeset :is(.admonition-title,summary):before{background-color:#448aff;content:"";height:1rem;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;width:1rem}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.note){border-color:#448aff}.md-typeset :-moz-any(.admonition,details):-moz-any(.note){border-color:#448aff}.md-typeset :is(.admonition,details):is(.note){border-color:#448aff}.md-typeset :-webkit-any(.note)>:-webkit-any(.admonition-title,summary){background-color:rgba(68,138,255,.1)}.md-typeset :-moz-any(.note)>:-moz-any(.admonition-title,summary){background-color:rgba(68,138,255,.1)}.md-typeset :is(.note)>:is(.admonition-title,summary){background-color:rgba(68,138,255,.1)}.md-typeset :-webkit-any(.note)>:-webkit-any(.admonition-title,summary):before{background-color:#448aff;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.note)>:-moz-any(.admonition-title,summary):before{background-color:#448aff;mask-image:var(--md-admonition-icon--note);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.note)>:is(.admonition-title,summary):before{background-color:#448aff;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.abstract,.summary,.tldr){border-color:#00b0ff}.md-typeset :-moz-any(.admonition,details):-moz-any(.abstract,.summary,.tldr){border-color:#00b0ff}.md-typeset :is(.admonition,details):is(.abstract,.summary,.tldr){border-color:#00b0ff}.md-typeset :-webkit-any(.abstract,.summary,.tldr)>:-webkit-any(.admonition-title,summary){background-color:rgba(0,176,255,.1)}.md-typeset :-moz-any(.abstract,.summary,.tldr)>:-moz-any(.admonition-title,summary){background-color:rgba(0,176,255,.1)}.md-typeset :is(.abstract,.summary,.tldr)>:is(.admonition-title,summary){background-color:rgba(0,176,255,.1)}.md-typeset :-webkit-any(.abstract,.summary,.tldr)>:-webkit-any(.admonition-title,summary):before{background-color:#00b0ff;-webkit-mask-image:var(--md-admonition-icon--abstract);mask-image:var(--md-admonition-icon--abstract);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.abstract,.summary,.tldr)>:-moz-any(.admonition-title,summary):before{background-color:#00b0ff;mask-image:var(--md-admonition-icon--abstract);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.abstract,.summary,.tldr)>:is(.admonition-title,summary):before{background-color:#00b0ff;-webkit-mask-image:var(--md-admonition-icon--abstract);mask-image:var(--md-admonition-icon--abstract);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.info,.todo){border-color:#00b8d4}.md-typeset :-moz-any(.admonition,details):-moz-any(.info,.todo){border-color:#00b8d4}.md-typeset :is(.admonition,details):is(.info,.todo){border-color:#00b8d4}.md-typeset :-webkit-any(.info,.todo)>:-webkit-any(.admonition-title,summary){background-color:rgba(0,184,212,.1)}.md-typeset :-moz-any(.info,.todo)>:-moz-any(.admonition-title,summary){background-color:rgba(0,184,212,.1)}.md-typeset :is(.info,.todo)>:is(.admonition-title,summary){background-color:rgba(0,184,212,.1)}.md-typeset :-webkit-any(.info,.todo)>:-webkit-any(.admonition-title,summary):before{background-color:#00b8d4;-webkit-mask-image:var(--md-admonition-icon--info);mask-image:var(--md-admonition-icon--info);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.info,.todo)>:-moz-any(.admonition-title,summary):before{background-color:#00b8d4;mask-image:var(--md-admonition-icon--info);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.info,.todo)>:is(.admonition-title,summary):before{background-color:#00b8d4;-webkit-mask-image:var(--md-admonition-icon--info);mask-image:var(--md-admonition-icon--info);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.tip,.hint,.important){border-color:#00bfa5}.md-typeset :-moz-any(.admonition,details):-moz-any(.tip,.hint,.important){border-color:#00bfa5}.md-typeset :is(.admonition,details):is(.tip,.hint,.important){border-color:#00bfa5}.md-typeset :-webkit-any(.tip,.hint,.important)>:-webkit-any(.admonition-title,summary){background-color:rgba(0,191,165,.1)}.md-typeset :-moz-any(.tip,.hint,.important)>:-moz-any(.admonition-title,summary){background-color:rgba(0,191,165,.1)}.md-typeset :is(.tip,.hint,.important)>:is(.admonition-title,summary){background-color:rgba(0,191,165,.1)}.md-typeset :-webkit-any(.tip,.hint,.important)>:-webkit-any(.admonition-title,summary):before{background-color:#00bfa5;-webkit-mask-image:var(--md-admonition-icon--tip);mask-image:var(--md-admonition-icon--tip);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.tip,.hint,.important)>:-moz-any(.admonition-title,summary):before{background-color:#00bfa5;mask-image:var(--md-admonition-icon--tip);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.tip,.hint,.important)>:is(.admonition-title,summary):before{background-color:#00bfa5;-webkit-mask-image:var(--md-admonition-icon--tip);mask-image:var(--md-admonition-icon--tip);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.success,.check,.done){border-color:#00c853}.md-typeset :-moz-any(.admonition,details):-moz-any(.success,.check,.done){border-color:#00c853}.md-typeset :is(.admonition,details):is(.success,.check,.done){border-color:#00c853}.md-typeset :-webkit-any(.success,.check,.done)>:-webkit-any(.admonition-title,summary){background-color:rgba(0,200,83,.1)}.md-typeset :-moz-any(.success,.check,.done)>:-moz-any(.admonition-title,summary){background-color:rgba(0,200,83,.1)}.md-typeset :is(.success,.check,.done)>:is(.admonition-title,summary){background-color:rgba(0,200,83,.1)}.md-typeset :-webkit-any(.success,.check,.done)>:-webkit-any(.admonition-title,summary):before{background-color:#00c853;-webkit-mask-image:var(--md-admonition-icon--success);mask-image:var(--md-admonition-icon--success);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.success,.check,.done)>:-moz-any(.admonition-title,summary):before{background-color:#00c853;mask-image:var(--md-admonition-icon--success);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.success,.check,.done)>:is(.admonition-title,summary):before{background-color:#00c853;-webkit-mask-image:var(--md-admonition-icon--success);mask-image:var(--md-admonition-icon--success);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.question,.help,.faq){border-color:#64dd17}.md-typeset :-moz-any(.admonition,details):-moz-any(.question,.help,.faq){border-color:#64dd17}.md-typeset :is(.admonition,details):is(.question,.help,.faq){border-color:#64dd17}.md-typeset :-webkit-any(.question,.help,.faq)>:-webkit-any(.admonition-title,summary){background-color:rgba(100,221,23,.1)}.md-typeset :-moz-any(.question,.help,.faq)>:-moz-any(.admonition-title,summary){background-color:rgba(100,221,23,.1)}.md-typeset :is(.question,.help,.faq)>:is(.admonition-title,summary){background-color:rgba(100,221,23,.1)}.md-typeset :-webkit-any(.question,.help,.faq)>:-webkit-any(.admonition-title,summary):before{background-color:#64dd17;-webkit-mask-image:var(--md-admonition-icon--question);mask-image:var(--md-admonition-icon--question);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.question,.help,.faq)>:-moz-any(.admonition-title,summary):before{background-color:#64dd17;mask-image:var(--md-admonition-icon--question);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.question,.help,.faq)>:is(.admonition-title,summary):before{background-color:#64dd17;-webkit-mask-image:var(--md-admonition-icon--question);mask-image:var(--md-admonition-icon--question);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.warning,.caution,.attention){border-color:#ff9100}.md-typeset :-moz-any(.admonition,details):-moz-any(.warning,.caution,.attention){border-color:#ff9100}.md-typeset :is(.admonition,details):is(.warning,.caution,.attention){border-color:#ff9100}.md-typeset :-webkit-any(.warning,.caution,.attention)>:-webkit-any(.admonition-title,summary){background-color:rgba(255,145,0,.1)}.md-typeset :-moz-any(.warning,.caution,.attention)>:-moz-any(.admonition-title,summary){background-color:rgba(255,145,0,.1)}.md-typeset :is(.warning,.caution,.attention)>:is(.admonition-title,summary){background-color:rgba(255,145,0,.1)}.md-typeset :-webkit-any(.warning,.caution,.attention)>:-webkit-any(.admonition-title,summary):before{background-color:#ff9100;-webkit-mask-image:var(--md-admonition-icon--warning);mask-image:var(--md-admonition-icon--warning);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.warning,.caution,.attention)>:-moz-any(.admonition-title,summary):before{background-color:#ff9100;mask-image:var(--md-admonition-icon--warning);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.warning,.caution,.attention)>:is(.admonition-title,summary):before{background-color:#ff9100;-webkit-mask-image:var(--md-admonition-icon--warning);mask-image:var(--md-admonition-icon--warning);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.failure,.fail,.missing){border-color:#ff5252}.md-typeset :-moz-any(.admonition,details):-moz-any(.failure,.fail,.missing){border-color:#ff5252}.md-typeset :is(.admonition,details):is(.failure,.fail,.missing){border-color:#ff5252}.md-typeset :-webkit-any(.failure,.fail,.missing)>:-webkit-any(.admonition-title,summary){background-color:rgba(255,82,82,.1)}.md-typeset :-moz-any(.failure,.fail,.missing)>:-moz-any(.admonition-title,summary){background-color:rgba(255,82,82,.1)}.md-typeset :is(.failure,.fail,.missing)>:is(.admonition-title,summary){background-color:rgba(255,82,82,.1)}.md-typeset :-webkit-any(.failure,.fail,.missing)>:-webkit-any(.admonition-title,summary):before{background-color:#ff5252;-webkit-mask-image:var(--md-admonition-icon--failure);mask-image:var(--md-admonition-icon--failure);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.failure,.fail,.missing)>:-moz-any(.admonition-title,summary):before{background-color:#ff5252;mask-image:var(--md-admonition-icon--failure);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.failure,.fail,.missing)>:is(.admonition-title,summary):before{background-color:#ff5252;-webkit-mask-image:var(--md-admonition-icon--failure);mask-image:var(--md-admonition-icon--failure);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.danger,.error){border-color:#ff1744}.md-typeset :-moz-any(.admonition,details):-moz-any(.danger,.error){border-color:#ff1744}.md-typeset :is(.admonition,details):is(.danger,.error){border-color:#ff1744}.md-typeset :-webkit-any(.danger,.error)>:-webkit-any(.admonition-title,summary){background-color:rgba(255,23,68,.1)}.md-typeset :-moz-any(.danger,.error)>:-moz-any(.admonition-title,summary){background-color:rgba(255,23,68,.1)}.md-typeset :is(.danger,.error)>:is(.admonition-title,summary){background-color:rgba(255,23,68,.1)}.md-typeset :-webkit-any(.danger,.error)>:-webkit-any(.admonition-title,summary):before{background-color:#ff1744;-webkit-mask-image:var(--md-admonition-icon--danger);mask-image:var(--md-admonition-icon--danger);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.danger,.error)>:-moz-any(.admonition-title,summary):before{background-color:#ff1744;mask-image:var(--md-admonition-icon--danger);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.danger,.error)>:is(.admonition-title,summary):before{background-color:#ff1744;-webkit-mask-image:var(--md-admonition-icon--danger);mask-image:var(--md-admonition-icon--danger);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.bug){border-color:#f50057}.md-typeset :-moz-any(.admonition,details):-moz-any(.bug){border-color:#f50057}.md-typeset :is(.admonition,details):is(.bug){border-color:#f50057}.md-typeset :-webkit-any(.bug)>:-webkit-any(.admonition-title,summary){background-color:rgba(245,0,87,.1)}.md-typeset :-moz-any(.bug)>:-moz-any(.admonition-title,summary){background-color:rgba(245,0,87,.1)}.md-typeset :is(.bug)>:is(.admonition-title,summary){background-color:rgba(245,0,87,.1)}.md-typeset :-webkit-any(.bug)>:-webkit-any(.admonition-title,summary):before{background-color:#f50057;-webkit-mask-image:var(--md-admonition-icon--bug);mask-image:var(--md-admonition-icon--bug);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.bug)>:-moz-any(.admonition-title,summary):before{background-color:#f50057;mask-image:var(--md-admonition-icon--bug);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.bug)>:is(.admonition-title,summary):before{background-color:#f50057;-webkit-mask-image:var(--md-admonition-icon--bug);mask-image:var(--md-admonition-icon--bug);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.example){border-color:#7c4dff}.md-typeset :-moz-any(.admonition,details):-moz-any(.example){border-color:#7c4dff}.md-typeset :is(.admonition,details):is(.example){border-color:#7c4dff}.md-typeset :-webkit-any(.example)>:-webkit-any(.admonition-title,summary){background-color:rgba(124,77,255,.1)}.md-typeset :-moz-any(.example)>:-moz-any(.admonition-title,summary){background-color:rgba(124,77,255,.1)}.md-typeset :is(.example)>:is(.admonition-title,summary){background-color:rgba(124,77,255,.1)}.md-typeset :-webkit-any(.example)>:-webkit-any(.admonition-title,summary):before{background-color:#7c4dff;-webkit-mask-image:var(--md-admonition-icon--example);mask-image:var(--md-admonition-icon--example);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.example)>:-moz-any(.admonition-title,summary):before{background-color:#7c4dff;mask-image:var(--md-admonition-icon--example);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.example)>:is(.admonition-title,summary):before{background-color:#7c4dff;-webkit-mask-image:var(--md-admonition-icon--example);mask-image:var(--md-admonition-icon--example);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.quote,.cite){border-color:#9e9e9e}.md-typeset :-moz-any(.admonition,details):-moz-any(.quote,.cite){border-color:#9e9e9e}.md-typeset :is(.admonition,details):is(.quote,.cite){border-color:#9e9e9e}.md-typeset :-webkit-any(.quote,.cite)>:-webkit-any(.admonition-title,summary){background-color:hsla(0,0%,62%,.1)}.md-typeset :-moz-any(.quote,.cite)>:-moz-any(.admonition-title,summary){background-color:hsla(0,0%,62%,.1)}.md-typeset :is(.quote,.cite)>:is(.admonition-title,summary){background-color:hsla(0,0%,62%,.1)}.md-typeset :-webkit-any(.quote,.cite)>:-webkit-any(.admonition-title,summary):before{background-color:#9e9e9e;-webkit-mask-image:var(--md-admonition-icon--quote);mask-image:var(--md-admonition-icon--quote);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.quote,.cite)>:-moz-any(.admonition-title,summary):before{background-color:#9e9e9e;mask-image:var(--md-admonition-icon--quote);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.quote,.cite)>:is(.admonition-title,summary):before{background-color:#9e9e9e;-webkit-mask-image:var(--md-admonition-icon--quote);mask-image:var(--md-admonition-icon--quote);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}:root{--md-footnotes-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .footnote{color:var(--md-default-fg-color--light);font-size:.64rem}[dir=ltr] .md-typeset .footnote>ol{margin-left:0}[dir=rtl] .md-typeset .footnote>ol{margin-right:0}.md-typeset .footnote>ol>li{transition:color 125ms}.md-typeset .footnote>ol>li:target{color:var(--md-default-fg-color)}.md-typeset .footnote>ol>li:focus-within .footnote-backref{opacity:1;transform:translateX(0);transition:none}.md-typeset .footnote>ol>li:-webkit-any(:hover,:target) .footnote-backref{opacity:1;transform:translateX(0)}.md-typeset .footnote>ol>li:-moz-any(:hover,:target) .footnote-backref{opacity:1;transform:translateX(0)}.md-typeset .footnote>ol>li:is(:hover,:target) .footnote-backref{opacity:1;transform:translateX(0)}.md-typeset .footnote>ol>li>:first-child{margin-top:0}.md-typeset .footnote-ref{font-size:.75em;font-weight:700}html .md-typeset .footnote-ref{outline-offset:.1rem}.md-typeset [id^="fnref:"]:target>.footnote-ref{outline:auto}.md-typeset .footnote-backref{color:var(--md-typeset-a-color);display:inline-block;font-size:0;opacity:0;transform:translateX(.25rem);transition:color .25s,transform .25s .25s,opacity 125ms .25s;vertical-align:text-bottom}@media print{.md-typeset .footnote-backref{color:var(--md-typeset-a-color);opacity:1;transform:translateX(0)}}[dir=rtl] .md-typeset .footnote-backref{transform:translateX(-.25rem)}.md-typeset .footnote-backref:hover{color:var(--md-accent-fg-color)}.md-typeset .footnote-backref:before{background-color:currentcolor;content:"";display:inline-block;height:.8rem;-webkit-mask-image:var(--md-footnotes-icon);mask-image:var(--md-footnotes-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:.8rem}[dir=rtl] .md-typeset .footnote-backref:before svg{transform:scaleX(-1)}[dir=ltr] .md-typeset .headerlink{margin-left:.5rem}[dir=rtl] .md-typeset .headerlink{margin-right:.5rem}.md-typeset .headerlink{color:var(--md-default-fg-color--lighter);display:inline-block;opacity:0;transition:color .25s,opacity 125ms}@media print{.md-typeset .headerlink{display:none}}.md-typeset .headerlink:focus,.md-typeset :-webkit-any(:hover,:target)>.headerlink{opacity:1;-webkit-transition:color .25s,opacity 125ms;transition:color .25s,opacity 125ms}.md-typeset .headerlink:focus,.md-typeset :-moz-any(:hover,:target)>.headerlink{opacity:1;-moz-transition:color .25s,opacity 125ms;transition:color .25s,opacity 125ms}.md-typeset .headerlink:focus,.md-typeset :is(:hover,:target)>.headerlink{opacity:1;transition:color .25s,opacity 125ms}.md-typeset .headerlink:-webkit-any(:focus,:hover),.md-typeset :target>.headerlink{color:var(--md-accent-fg-color)}.md-typeset .headerlink:-moz-any(:focus,:hover),.md-typeset :target>.headerlink{color:var(--md-accent-fg-color)}.md-typeset .headerlink:is(:focus,:hover),.md-typeset :target>.headerlink{color:var(--md-accent-fg-color)}.md-typeset :target{--md-scroll-margin:3.6rem;--md-scroll-offset:0rem;scroll-margin-top:calc(var(--md-scroll-margin) - var(--md-scroll-offset))}@media screen and (min-width:76.25em){.md-header--lifted~.md-container .md-typeset :target{--md-scroll-margin:6rem}}.md-typeset :-webkit-any(h1,h2,h3):target{--md-scroll-offset:0.2rem}.md-typeset :-moz-any(h1,h2,h3):target{--md-scroll-offset:0.2rem}.md-typeset :is(h1,h2,h3):target{--md-scroll-offset:0.2rem}.md-typeset h4:target{--md-scroll-offset:0.15rem}.md-typeset div.arithmatex{overflow:auto}@media screen and (max-width:44.9375em){.md-typeset div.arithmatex{margin:0 -.8rem}}.md-typeset div.arithmatex>*{margin-left:auto!important;margin-right:auto!important;padding:0 .8rem;touch-action:auto;width:-webkit-min-content;width:-moz-min-content;width:min-content}.md-typeset div.arithmatex>* mjx-container{margin:0!important}.md-typeset :-webkit-any(del,ins,.comment).critic{-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset :-moz-any(del,ins,.comment).critic{box-decoration-break:clone}.md-typeset :is(del,ins,.comment).critic{-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset del.critic{background-color:var(--md-typeset-del-color)}.md-typeset ins.critic{background-color:var(--md-typeset-ins-color)}.md-typeset .critic.comment{color:var(--md-code-hl-comment-color)}.md-typeset .critic.comment:before{content:"/* "}.md-typeset .critic.comment:after{content:" */"}.md-typeset .critic.block{box-shadow:none;display:block;margin:1em 0;overflow:auto;padding-left:.8rem;padding-right:.8rem}.md-typeset .critic.block>:first-child{margin-top:.5em}.md-typeset .critic.block>:last-child{margin-bottom:.5em}:root{--md-details-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset details{display:flow-root;overflow:visible;padding-top:0}.md-typeset details[open]>summary:after{transform:rotate(90deg)}.md-typeset details:not([open]){box-shadow:none;padding-bottom:0}.md-typeset details:not([open])>summary{border-radius:.1rem}[dir=ltr] .md-typeset summary{padding-right:1.8rem}[dir=rtl] .md-typeset summary{padding-left:1.8rem}[dir=ltr] .md-typeset summary{border-top-left-radius:.1rem}[dir=ltr] .md-typeset summary,[dir=rtl] .md-typeset summary{border-top-right-radius:.1rem}[dir=rtl] .md-typeset summary{border-top-left-radius:.1rem}.md-typeset summary{cursor:pointer;display:block;min-height:1rem}.md-typeset summary.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-typeset summary:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}[dir=ltr] .md-typeset summary:after{right:.4rem}[dir=rtl] .md-typeset summary:after{left:.4rem}.md-typeset summary:after{background-color:currentcolor;content:"";height:1rem;-webkit-mask-image:var(--md-details-icon);mask-image:var(--md-details-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;transform:rotate(0deg);transition:transform .25s;width:1rem}[dir=rtl] .md-typeset summary:after{transform:rotate(180deg)}.md-typeset summary::marker{display:none}.md-typeset summary::-webkit-details-marker{display:none}.md-typeset :-webkit-any(.emojione,.twemoji,.gemoji){display:inline-flex;height:1.125em;vertical-align:text-top}.md-typeset :-moz-any(.emojione,.twemoji,.gemoji){display:inline-flex;height:1.125em;vertical-align:text-top}.md-typeset :is(.emojione,.twemoji,.gemoji){display:inline-flex;height:1.125em;vertical-align:text-top}.md-typeset :-webkit-any(.emojione,.twemoji,.gemoji) svg{fill:currentcolor;max-height:100%;width:1.125em}.md-typeset :-moz-any(.emojione,.twemoji,.gemoji) svg{fill:currentcolor;max-height:100%;width:1.125em}.md-typeset :is(.emojione,.twemoji,.gemoji) svg{fill:currentcolor;max-height:100%;width:1.125em}.highlight :-webkit-any(.o,.ow){color:var(--md-code-hl-operator-color)}.highlight :-moz-any(.o,.ow){color:var(--md-code-hl-operator-color)}.highlight :is(.o,.ow){color:var(--md-code-hl-operator-color)}.highlight .p{color:var(--md-code-hl-punctuation-color)}.highlight :-webkit-any(.cpf,.l,.s,.sb,.sc,.s2,.si,.s1,.ss){color:var(--md-code-hl-string-color)}.highlight :-moz-any(.cpf,.l,.s,.sb,.sc,.s2,.si,.s1,.ss){color:var(--md-code-hl-string-color)}.highlight :is(.cpf,.l,.s,.sb,.sc,.s2,.si,.s1,.ss){color:var(--md-code-hl-string-color)}.highlight :-webkit-any(.cp,.se,.sh,.sr,.sx){color:var(--md-code-hl-special-color)}.highlight :-moz-any(.cp,.se,.sh,.sr,.sx){color:var(--md-code-hl-special-color)}.highlight :is(.cp,.se,.sh,.sr,.sx){color:var(--md-code-hl-special-color)}.highlight :-webkit-any(.m,.mb,.mf,.mh,.mi,.il,.mo){color:var(--md-code-hl-number-color)}.highlight :-moz-any(.m,.mb,.mf,.mh,.mi,.il,.mo){color:var(--md-code-hl-number-color)}.highlight :is(.m,.mb,.mf,.mh,.mi,.il,.mo){color:var(--md-code-hl-number-color)}.highlight :-webkit-any(.k,.kd,.kn,.kp,.kr,.kt){color:var(--md-code-hl-keyword-color)}.highlight :-moz-any(.k,.kd,.kn,.kp,.kr,.kt){color:var(--md-code-hl-keyword-color)}.highlight :is(.k,.kd,.kn,.kp,.kr,.kt){color:var(--md-code-hl-keyword-color)}.highlight :-webkit-any(.kc,.n){color:var(--md-code-hl-name-color)}.highlight :-moz-any(.kc,.n){color:var(--md-code-hl-name-color)}.highlight :is(.kc,.n){color:var(--md-code-hl-name-color)}.highlight :-webkit-any(.no,.nb,.bp){color:var(--md-code-hl-constant-color)}.highlight :-moz-any(.no,.nb,.bp){color:var(--md-code-hl-constant-color)}.highlight :is(.no,.nb,.bp){color:var(--md-code-hl-constant-color)}.highlight :-webkit-any(.nc,.ne,.nf,.nn){color:var(--md-code-hl-function-color)}.highlight :-moz-any(.nc,.ne,.nf,.nn){color:var(--md-code-hl-function-color)}.highlight :is(.nc,.ne,.nf,.nn){color:var(--md-code-hl-function-color)}.highlight :-webkit-any(.nd,.ni,.nl,.nt){color:var(--md-code-hl-keyword-color)}.highlight :-moz-any(.nd,.ni,.nl,.nt){color:var(--md-code-hl-keyword-color)}.highlight :is(.nd,.ni,.nl,.nt){color:var(--md-code-hl-keyword-color)}.highlight :-webkit-any(.c,.cm,.c1,.ch,.cs,.sd){color:var(--md-code-hl-comment-color)}.highlight :-moz-any(.c,.cm,.c1,.ch,.cs,.sd){color:var(--md-code-hl-comment-color)}.highlight :is(.c,.cm,.c1,.ch,.cs,.sd){color:var(--md-code-hl-comment-color)}.highlight :-webkit-any(.na,.nv,.vc,.vg,.vi){color:var(--md-code-hl-variable-color)}.highlight :-moz-any(.na,.nv,.vc,.vg,.vi){color:var(--md-code-hl-variable-color)}.highlight :is(.na,.nv,.vc,.vg,.vi){color:var(--md-code-hl-variable-color)}.highlight :-webkit-any(.ge,.gr,.gh,.go,.gp,.gs,.gu,.gt){color:var(--md-code-hl-generic-color)}.highlight :-moz-any(.ge,.gr,.gh,.go,.gp,.gs,.gu,.gt){color:var(--md-code-hl-generic-color)}.highlight :is(.ge,.gr,.gh,.go,.gp,.gs,.gu,.gt){color:var(--md-code-hl-generic-color)}.highlight :-webkit-any(.gd,.gi){border-radius:.1rem;margin:0 -.125em;padding:0 .125em}.highlight :-moz-any(.gd,.gi){border-radius:.1rem;margin:0 -.125em;padding:0 .125em}.highlight :is(.gd,.gi){border-radius:.1rem;margin:0 -.125em;padding:0 .125em}.highlight .gd{background-color:var(--md-typeset-del-color)}.highlight .gi{background-color:var(--md-typeset-ins-color)}.highlight .hll{background-color:var(--md-code-hl-color);display:block;margin:0 -1.1764705882em;padding:0 1.1764705882em}.highlight span.filename{background-color:var(--md-code-bg-color);border-bottom:.05rem solid var(--md-default-fg-color--lightest);border-top-left-radius:.1rem;border-top-right-radius:.1rem;display:flow-root;font-size:.85em;font-weight:700;margin-top:1em;padding:.6617647059em 1.1764705882em;position:relative}.highlight span.filename+pre{margin-top:0}.highlight span.filename+pre>code{border-top-left-radius:0;border-top-right-radius:0}.highlight [data-linenos]:before{background-color:var(--md-code-bg-color);box-shadow:-.05rem 0 var(--md-default-fg-color--lightest) inset;color:var(--md-default-fg-color--light);content:attr(data-linenos);float:left;left:-1.1764705882em;margin-left:-1.1764705882em;margin-right:1.1764705882em;padding-left:1.1764705882em;position:-webkit-sticky;position:sticky;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:3}.highlight code a[id]{position:absolute;visibility:hidden}.highlight code[data-md-copying] .hll{display:contents}.highlight code[data-md-copying] .md-annotation{display:none}.highlighttable{display:flow-root}.highlighttable :-webkit-any(tbody,td){display:block;padding:0}.highlighttable :-moz-any(tbody,td){display:block;padding:0}.highlighttable :is(tbody,td){display:block;padding:0}.highlighttable tr{display:flex}.highlighttable pre{margin:0}.highlighttable th.filename{flex-grow:1;padding:0;text-align:left}.highlighttable th.filename span.filename{margin-top:0}.highlighttable .linenos{background-color:var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-top-left-radius:.1rem;font-size:.85em;padding:.7720588235em 0 .7720588235em 1.1764705882em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.highlighttable .linenodiv{box-shadow:-.05rem 0 var(--md-default-fg-color--lightest) inset;padding-right:.5882352941em}.highlighttable .linenodiv pre{color:var(--md-default-fg-color--light);text-align:right}.highlighttable .code{flex:1;min-width:0}.linenodiv a{color:inherit}.md-typeset .highlighttable{direction:ltr;margin:1em 0}.md-typeset .highlighttable code{border-bottom-left-radius:0;border-top-left-radius:0}.md-typeset :-webkit-any(.highlight,.highlighttable)+.result{border:.05rem solid var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-bottom-right-radius:.1rem;border-top-width:.1rem;margin-top:-1.125em;overflow:visible;padding:0 1em}.md-typeset :-moz-any(.highlight,.highlighttable)+.result{border:.05rem solid var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-bottom-right-radius:.1rem;border-top-width:.1rem;margin-top:-1.125em;overflow:visible;padding:0 1em}.md-typeset :is(.highlight,.highlighttable)+.result{border:.05rem solid var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-bottom-right-radius:.1rem;border-top-width:.1rem;margin-top:-1.125em;overflow:visible;padding:0 1em}.md-typeset :-webkit-any(.highlight,.highlighttable)+.result:after{clear:both;content:"";display:block}.md-typeset :-moz-any(.highlight,.highlighttable)+.result:after{clear:both;content:"";display:block}.md-typeset :is(.highlight,.highlighttable)+.result:after{clear:both;content:"";display:block}@media screen and (max-width:44.9375em){.md-content__inner>.highlight{margin:1em -.8rem}.md-content__inner>.highlight .hll{margin:0 -.8rem;padding:0 .8rem}.md-content__inner>.highlight code{border-radius:0}.md-content__inner>.highlight+.result{border-left-width:0;border-radius:0;border-right-width:0;margin-left:-.8rem;margin-right:-.8rem}.md-content__inner>.highlighttable{border-radius:0;margin:1em -.8rem}.md-content__inner>.highlighttable .hll{margin:0 -.8rem;padding:0 .8rem}}.md-typeset .keys kbd:-webkit-any(:before,:after){-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;color:inherit;margin:0;position:relative}.md-typeset .keys kbd:-moz-any(:before,:after){-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;color:inherit;margin:0;position:relative}.md-typeset .keys kbd:is(:before,:after){-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;color:inherit;margin:0;position:relative}.md-typeset .keys span{color:var(--md-default-fg-color--light);padding:0 .2em}.md-typeset .keys .key-alt:before,.md-typeset .keys .key-left-alt:before,.md-typeset .keys .key-right-alt:before{content:"⎇";padding-right:.4em}.md-typeset .keys .key-command:before,.md-typeset .keys .key-left-command:before,.md-typeset .keys .key-right-command:before{content:"⌘";padding-right:.4em}.md-typeset .keys .key-control:before,.md-typeset .keys .key-left-control:before,.md-typeset .keys .key-right-control:before{content:"⌃";padding-right:.4em}.md-typeset .keys .key-left-meta:before,.md-typeset .keys .key-meta:before,.md-typeset .keys .key-right-meta:before{content:"◆";padding-right:.4em}.md-typeset .keys .key-left-option:before,.md-typeset .keys .key-option:before,.md-typeset .keys .key-right-option:before{content:"⌥";padding-right:.4em}.md-typeset .keys .key-left-shift:before,.md-typeset .keys .key-right-shift:before,.md-typeset .keys .key-shift:before{content:"⇧";padding-right:.4em}.md-typeset .keys .key-left-super:before,.md-typeset .keys .key-right-super:before,.md-typeset .keys .key-super:before{content:"❖";padding-right:.4em}.md-typeset .keys .key-left-windows:before,.md-typeset .keys .key-right-windows:before,.md-typeset .keys .key-windows:before{content:"⊞";padding-right:.4em}.md-typeset .keys .key-arrow-down:before{content:"↓";padding-right:.4em}.md-typeset .keys .key-arrow-left:before{content:"←";padding-right:.4em}.md-typeset .keys .key-arrow-right:before{content:"→";padding-right:.4em}.md-typeset .keys .key-arrow-up:before{content:"↑";padding-right:.4em}.md-typeset .keys .key-backspace:before{content:"⌫";padding-right:.4em}.md-typeset .keys .key-backtab:before{content:"⇤";padding-right:.4em}.md-typeset .keys .key-caps-lock:before{content:"⇪";padding-right:.4em}.md-typeset .keys .key-clear:before{content:"⌧";padding-right:.4em}.md-typeset .keys .key-context-menu:before{content:"☰";padding-right:.4em}.md-typeset .keys .key-delete:before{content:"⌦";padding-right:.4em}.md-typeset .keys .key-eject:before{content:"⏏";padding-right:.4em}.md-typeset .keys .key-end:before{content:"⤓";padding-right:.4em}.md-typeset .keys .key-escape:before{content:"⎋";padding-right:.4em}.md-typeset .keys .key-home:before{content:"⤒";padding-right:.4em}.md-typeset .keys .key-insert:before{content:"⎀";padding-right:.4em}.md-typeset .keys .key-page-down:before{content:"⇟";padding-right:.4em}.md-typeset .keys .key-page-up:before{content:"⇞";padding-right:.4em}.md-typeset .keys .key-print-screen:before{content:"⎙";padding-right:.4em}.md-typeset .keys .key-tab:after{content:"⇥";padding-left:.4em}.md-typeset .keys .key-num-enter:after{content:"⌤";padding-left:.4em}.md-typeset .keys .key-enter:after{content:"⏎";padding-left:.4em}.md-typeset .tabbed-set{border-radius:.1rem;display:flex;flex-flow:column wrap;margin:1em 0;position:relative}.md-typeset .tabbed-set>input{height:0;opacity:0;position:absolute;width:0}.md-typeset .tabbed-set>input:target{--md-scroll-offset:0.625em}.md-typeset .tabbed-labels{-ms-overflow-style:none;box-shadow:0 -.05rem var(--md-default-fg-color--lightest) inset;display:flex;max-width:100%;overflow:auto;-ms-scroll-snap-type:x proximity;scroll-snap-type:x proximity;scrollbar-width:none}@media print{.md-typeset .tabbed-labels{display:contents}}@media screen{.js .md-typeset .tabbed-labels{position:relative}.js .md-typeset .tabbed-labels:before{background:var(--md-accent-fg-color);bottom:0;content:"";display:block;height:2px;left:0;position:absolute;transform:translateX(var(--md-indicator-x));transition:width 225ms,transform .25s;transition-timing-function:cubic-bezier(.4,0,.2,1);width:var(--md-indicator-width)}}.md-typeset .tabbed-labels::-webkit-scrollbar{display:none}.md-typeset .tabbed-labels>label{border-bottom:.1rem solid transparent;border-radius:.1rem .1rem 0 0;color:var(--md-default-fg-color--light);cursor:pointer;flex-shrink:0;font-size:.64rem;font-weight:700;padding:.78125em 1.25em .625em;scroll-snap-align:start;transition:background-color .25s,color .25s;white-space:nowrap;width:auto}@media print{.md-typeset .tabbed-labels>label:first-child{order:1}.md-typeset .tabbed-labels>label:nth-child(2){order:2}.md-typeset .tabbed-labels>label:nth-child(3){order:3}.md-typeset .tabbed-labels>label:nth-child(4){order:4}.md-typeset .tabbed-labels>label:nth-child(5){order:5}.md-typeset .tabbed-labels>label:nth-child(6){order:6}.md-typeset .tabbed-labels>label:nth-child(7){order:7}.md-typeset .tabbed-labels>label:nth-child(8){order:8}.md-typeset .tabbed-labels>label:nth-child(9){order:9}.md-typeset .tabbed-labels>label:nth-child(10){order:10}.md-typeset .tabbed-labels>label:nth-child(11){order:11}.md-typeset .tabbed-labels>label:nth-child(12){order:12}.md-typeset .tabbed-labels>label:nth-child(13){order:13}.md-typeset .tabbed-labels>label:nth-child(14){order:14}.md-typeset .tabbed-labels>label:nth-child(15){order:15}.md-typeset .tabbed-labels>label:nth-child(16){order:16}.md-typeset .tabbed-labels>label:nth-child(17){order:17}.md-typeset .tabbed-labels>label:nth-child(18){order:18}.md-typeset .tabbed-labels>label:nth-child(19){order:19}.md-typeset .tabbed-labels>label:nth-child(20){order:20}}.md-typeset .tabbed-labels>label:hover{color:var(--md-accent-fg-color)}.md-typeset .tabbed-content{width:100%}@media print{.md-typeset .tabbed-content{display:contents}}.md-typeset .tabbed-block{display:none}@media print{.md-typeset .tabbed-block{display:block}.md-typeset .tabbed-block:first-child{order:1}.md-typeset .tabbed-block:nth-child(2){order:2}.md-typeset .tabbed-block:nth-child(3){order:3}.md-typeset .tabbed-block:nth-child(4){order:4}.md-typeset .tabbed-block:nth-child(5){order:5}.md-typeset .tabbed-block:nth-child(6){order:6}.md-typeset .tabbed-block:nth-child(7){order:7}.md-typeset .tabbed-block:nth-child(8){order:8}.md-typeset .tabbed-block:nth-child(9){order:9}.md-typeset .tabbed-block:nth-child(10){order:10}.md-typeset .tabbed-block:nth-child(11){order:11}.md-typeset .tabbed-block:nth-child(12){order:12}.md-typeset .tabbed-block:nth-child(13){order:13}.md-typeset .tabbed-block:nth-child(14){order:14}.md-typeset .tabbed-block:nth-child(15){order:15}.md-typeset .tabbed-block:nth-child(16){order:16}.md-typeset .tabbed-block:nth-child(17){order:17}.md-typeset .tabbed-block:nth-child(18){order:18}.md-typeset .tabbed-block:nth-child(19){order:19}.md-typeset .tabbed-block:nth-child(20){order:20}}.md-typeset .tabbed-block>.highlight:first-child>pre:first-child,.md-typeset .tabbed-block>.highlighttable:first-child,.md-typeset .tabbed-block>pre:first-child{margin:0}[dir=ltr] .md-typeset .tabbed-block>.highlight:first-child>pre:first-child>code,[dir=ltr] .md-typeset .tabbed-block>.highlighttable:first-child>code,[dir=ltr] .md-typeset .tabbed-block>pre:first-child>code{border-top-left-radius:0}[dir=ltr] .md-typeset .tabbed-block>.highlight:first-child>pre:first-child>code,[dir=ltr] .md-typeset .tabbed-block>.highlighttable:first-child>code,[dir=ltr] .md-typeset .tabbed-block>pre:first-child>code,[dir=rtl] .md-typeset .tabbed-block>.highlight:first-child>pre:first-child>code,[dir=rtl] .md-typeset .tabbed-block>.highlighttable:first-child>code,[dir=rtl] .md-typeset .tabbed-block>pre:first-child>code{border-top-right-radius:0}[dir=ltr] .md-typeset .tabbed-block>.highlighttable:first-child .linenos,[dir=rtl] .md-typeset .tabbed-block>.highlight:first-child>pre:first-child>code,[dir=rtl] .md-typeset .tabbed-block>.highlighttable:first-child>code,[dir=rtl] .md-typeset .tabbed-block>pre:first-child>code{border-top-left-radius:0}[dir=ltr] .md-typeset .tabbed-block>.highlighttable:first-child .linenos,[dir=rtl] .md-typeset .tabbed-block>.highlighttable:first-child .linenos{border-top-right-radius:0}[dir=rtl] .md-typeset .tabbed-block>.highlighttable:first-child .linenos{border-top-left-radius:0}.md-typeset .tabbed-block>.tabbed-set{margin:0}@media screen and (max-width:44.9375em){[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels{padding-left:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels{padding-right:.8rem}.md-content__inner>.tabbed-set .tabbed-labels{margin:0 -.8rem;max-width:100vw;scroll-padding-inline-start:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels:after{padding-right:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels:after{padding-left:.8rem}.md-content__inner>.tabbed-set .tabbed-labels:after{content:""}}@media screen{.md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9){color:var(--md-accent-fg-color)}.md-typeset .no-js .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset .no-js .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset .no-js .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset .no-js .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset .no-js .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset .no-js .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset .no-js .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset .no-js .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset .no-js .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset .no-js .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset .no-js .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset .no-js .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset .no-js .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset .no-js .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset .no-js .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset .no-js .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset .no-js .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset .no-js .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset .no-js .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset .no-js .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9),.no-js .md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.no-js .md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.no-js .md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.no-js .md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.no-js .md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.no-js .md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.no-js .md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.no-js .md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.no-js .md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.no-js .md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.no-js .md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.no-js .md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.no-js .md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.no-js .md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.no-js .md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.no-js .md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.no-js .md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.no-js .md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.no-js .md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.no-js .md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9){border-color:var(--md-accent-fg-color)}}.md-typeset .tabbed-set>input:first-child.focus-visible~.tabbed-labels>:first-child,.md-typeset .tabbed-set>input:nth-child(10).focus-visible~.tabbed-labels>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11).focus-visible~.tabbed-labels>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12).focus-visible~.tabbed-labels>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13).focus-visible~.tabbed-labels>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14).focus-visible~.tabbed-labels>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15).focus-visible~.tabbed-labels>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16).focus-visible~.tabbed-labels>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17).focus-visible~.tabbed-labels>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18).focus-visible~.tabbed-labels>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19).focus-visible~.tabbed-labels>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2).focus-visible~.tabbed-labels>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20).focus-visible~.tabbed-labels>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3).focus-visible~.tabbed-labels>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4).focus-visible~.tabbed-labels>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5).focus-visible~.tabbed-labels>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6).focus-visible~.tabbed-labels>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7).focus-visible~.tabbed-labels>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8).focus-visible~.tabbed-labels>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9).focus-visible~.tabbed-labels>:nth-child(9){background-color:var(--md-accent-fg-color--transparent)}.md-typeset .tabbed-set>input:first-child:checked~.tabbed-content>:first-child,.md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-content>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-content>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-content>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-content>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-content>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-content>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-content>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-content>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-content>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-content>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-content>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-content>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-content>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-content>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-content>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-content>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-content>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-content>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-content>:nth-child(9){display:block}:root{--md-tasklist-icon:url('data:image/svg+xml;charset=utf-8,');--md-tasklist-icon--checked:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .task-list-item{list-style-type:none;position:relative}[dir=ltr] .md-typeset .task-list-item [type=checkbox]{left:-2em}[dir=rtl] .md-typeset .task-list-item [type=checkbox]{right:-2em}.md-typeset .task-list-item [type=checkbox]{position:absolute;top:.45em}.md-typeset .task-list-control [type=checkbox]{opacity:0;z-index:-1}[dir=ltr] .md-typeset .task-list-indicator:before{left:-1.5em}[dir=rtl] .md-typeset .task-list-indicator:before{right:-1.5em}.md-typeset .task-list-indicator:before{background-color:var(--md-default-fg-color--lightest);content:"";height:1.25em;-webkit-mask-image:var(--md-tasklist-icon);mask-image:var(--md-tasklist-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.15em;width:1.25em}.md-typeset [type=checkbox]:checked+.task-list-indicator:before{background-color:#00e676;-webkit-mask-image:var(--md-tasklist-icon--checked);mask-image:var(--md-tasklist-icon--checked)}:root>*{--md-mermaid-font-family:var(--md-text-font-family),sans-serif;--md-mermaid-edge-color:var(--md-code-fg-color);--md-mermaid-node-bg-color:var(--md-accent-fg-color--transparent);--md-mermaid-node-fg-color:var(--md-accent-fg-color);--md-mermaid-label-bg-color:var(--md-default-bg-color);--md-mermaid-label-fg-color:var(--md-code-fg-color)}.mermaid{line-height:normal;margin:1em 0}@media screen and (min-width:45em){[dir=ltr] .md-typeset .inline{margin-right:.8rem}[dir=rtl] .md-typeset .inline{margin-left:.8rem}.md-typeset .inline{float:left;margin-bottom:.8rem;margin-top:0;width:11.7rem}[dir=rtl] .md-typeset .inline{float:right}[dir=ltr] .md-typeset .inline.end{margin-left:.8rem;margin-right:0}[dir=rtl] .md-typeset .inline.end{margin-left:0;margin-right:.8rem}.md-typeset .inline.end{float:right}[dir=rtl] .md-typeset .inline.end{float:left}} \ No newline at end of file +@charset "UTF-8";html{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;-ms-text-size-adjust:none;text-size-adjust:none;box-sizing:border-box}*,:after,:before{box-sizing:inherit}@media (prefers-reduced-motion){*,:after,:before{transition:none!important}}body{margin:0}a,button,input,label{-webkit-tap-highlight-color:transparent}a{color:inherit;text-decoration:none}hr{border:0;box-sizing:initial;display:block;height:.05rem;overflow:visible;padding:0}small{font-size:80%}sub,sup{line-height:1em}img{border-style:none}table{border-collapse:initial;border-spacing:0}td,th{font-weight:400;vertical-align:top}button{background:transparent;border:0;font-family:inherit;font-size:inherit;margin:0;padding:0}input{border:0;outline:none}:root{--md-default-fg-color:rgba(0,0,0,.87);--md-default-fg-color--light:rgba(0,0,0,.54);--md-default-fg-color--lighter:rgba(0,0,0,.32);--md-default-fg-color--lightest:rgba(0,0,0,.07);--md-default-bg-color:#fff;--md-default-bg-color--light:hsla(0,0%,100%,.7);--md-default-bg-color--lighter:hsla(0,0%,100%,.3);--md-default-bg-color--lightest:hsla(0,0%,100%,.12);--md-primary-fg-color:#4051b5;--md-primary-fg-color--light:#5d6cc0;--md-primary-fg-color--dark:#303fa1;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7);--md-accent-fg-color:#526cfe;--md-accent-fg-color--transparent:rgba(82,108,254,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7);--md-shadow-z1:0 0.2rem 0.5rem rgba(0,0,0,.05),0 0 0.05rem rgba(0,0,0,.1);--md-shadow-z2:0 0.2rem 0.5rem rgba(0,0,0,.1),0 0 0.05rem rgba(0,0,0,.25);--md-shadow-z3:0 0.2rem 0.5rem rgba(0,0,0,.2),0 0 0.05rem rgba(0,0,0,.35)}:root>*{--md-code-fg-color:#36464e;--md-code-bg-color:#f5f5f5;--md-code-hl-color:rgba(255,255,0,.5);--md-code-hl-number-color:#d52a2a;--md-code-hl-special-color:#db1457;--md-code-hl-function-color:#a846b9;--md-code-hl-constant-color:#6e59d9;--md-code-hl-keyword-color:#3f6ec6;--md-code-hl-string-color:#1c7d4d;--md-code-hl-name-color:var(--md-code-fg-color);--md-code-hl-operator-color:var(--md-default-fg-color--light);--md-code-hl-punctuation-color:var(--md-default-fg-color--light);--md-code-hl-comment-color:var(--md-default-fg-color--light);--md-code-hl-generic-color:var(--md-default-fg-color--light);--md-code-hl-variable-color:var(--md-default-fg-color--light);--md-typeset-color:var(--md-default-fg-color);--md-typeset-a-color:var(--md-primary-fg-color);--md-typeset-mark-color:rgba(255,255,0,.5);--md-typeset-del-color:rgba(245,80,61,.15);--md-typeset-ins-color:rgba(11,213,112,.15);--md-typeset-kbd-color:#fafafa;--md-typeset-kbd-accent-color:#fff;--md-typeset-kbd-border-color:#b8b8b8;--md-typeset-table-color:rgba(0,0,0,.12);--md-admonition-fg-color:var(--md-default-fg-color);--md-admonition-bg-color:var(--md-default-bg-color);--md-footer-fg-color:#fff;--md-footer-fg-color--light:hsla(0,0%,100%,.7);--md-footer-fg-color--lighter:hsla(0,0%,100%,.3);--md-footer-bg-color:rgba(0,0,0,.87);--md-footer-bg-color--dark:rgba(0,0,0,.32)}.md-icon svg{fill:currentcolor;display:block;height:1.2rem;width:1.2rem}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;--md-text-font-family:var(--md-text-font,_),-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif;--md-code-font-family:var(--md-code-font,_),SFMono-Regular,Consolas,Menlo,monospace}body,input{font-feature-settings:"kern","liga";font-family:var(--md-text-font-family)}body,code,input,kbd,pre{color:var(--md-typeset-color)}code,kbd,pre{font-feature-settings:"kern";font-family:var(--md-code-font-family)}:root{--md-typeset-table-sort-icon:url('data:image/svg+xml;charset=utf-8,');--md-typeset-table-sort-icon--asc:url('data:image/svg+xml;charset=utf-8,');--md-typeset-table-sort-icon--desc:url('data:image/svg+xml;charset=utf-8,')}.md-typeset{-webkit-print-color-adjust:exact;color-adjust:exact;font-size:.8rem;line-height:1.6}@media print{.md-typeset{font-size:.68rem}}.md-typeset blockquote,.md-typeset dl,.md-typeset figure,.md-typeset ol,.md-typeset pre,.md-typeset ul{margin-bottom:1em;margin-top:1em}.md-typeset h1{color:var(--md-default-fg-color--light);font-size:2em;line-height:1.3;margin:0 0 1.25em}.md-typeset h1,.md-typeset h2{font-weight:300;letter-spacing:-.01em}.md-typeset h2{font-size:1.5625em;line-height:1.4;margin:1.6em 0 .64em}.md-typeset h3{font-size:1.25em;font-weight:400;letter-spacing:-.01em;line-height:1.5;margin:1.6em 0 .8em}.md-typeset h2+h3{margin-top:.8em}.md-typeset h4{font-weight:700;letter-spacing:-.01em;margin:1em 0}.md-typeset h5,.md-typeset h6{color:var(--md-default-fg-color--light);font-size:.8em;font-weight:700;letter-spacing:-.01em;margin:1.25em 0}.md-typeset h5{text-transform:uppercase}.md-typeset hr{border-bottom:.05rem solid var(--md-default-fg-color--lightest);display:flow-root;margin:1.5em 0}.md-typeset a{color:var(--md-typeset-a-color);word-break:break-word}.md-typeset a,.md-typeset a:before{transition:color 125ms}.md-typeset a:focus,.md-typeset a:hover{color:var(--md-accent-fg-color)}.md-typeset a:focus code,.md-typeset a:hover code{background-color:var(--md-accent-fg-color--transparent)}.md-typeset a code{color:currentcolor;transition:background-color 125ms}.md-typeset a.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-typeset code,.md-typeset kbd,.md-typeset pre{color:var(--md-code-fg-color);direction:ltr}@media print{.md-typeset code,.md-typeset kbd,.md-typeset pre{white-space:pre-wrap}}.md-typeset code{background-color:var(--md-code-bg-color);border-radius:.1rem;-webkit-box-decoration-break:clone;box-decoration-break:clone;font-size:.85em;padding:0 .2941176471em;word-break:break-word}.md-typeset code:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}.md-typeset pre{display:flow-root;line-height:1.4;position:relative}.md-typeset pre>code{-webkit-box-decoration-break:slice;box-decoration-break:slice;box-shadow:none;display:block;margin:0;outline-color:var(--md-accent-fg-color);overflow:auto;padding:.7720588235em 1.1764705882em;scrollbar-color:var(--md-default-fg-color--lighter) transparent;scrollbar-width:thin;touch-action:auto;word-break:normal}.md-typeset pre>code:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-typeset pre>code::-webkit-scrollbar{height:.2rem;width:.2rem}.md-typeset pre>code::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-typeset pre>code::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}.md-typeset kbd{background-color:var(--md-typeset-kbd-color);border-radius:.1rem;box-shadow:0 .1rem 0 .05rem var(--md-typeset-kbd-border-color),0 .1rem 0 var(--md-typeset-kbd-border-color),0 -.1rem .2rem var(--md-typeset-kbd-accent-color) inset;color:var(--md-default-fg-color);display:inline-block;font-size:.75em;padding:0 .6666666667em;vertical-align:text-top;word-break:break-word}.md-typeset mark{background-color:var(--md-typeset-mark-color);-webkit-box-decoration-break:clone;box-decoration-break:clone;color:inherit;word-break:break-word}.md-typeset abbr{border-bottom:.05rem dotted var(--md-default-fg-color--light);cursor:help;text-decoration:none}@media (hover:none){.md-typeset abbr{position:relative}.md-typeset abbr[title]:-webkit-any(:focus,:hover):after{background-color:var(--md-default-fg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z3);color:var(--md-default-bg-color);content:attr(title);display:inline-block;font-size:.7rem;margin-top:2em;max-width:80%;min-width:-webkit-max-content;min-width:max-content;padding:.2rem .3rem;position:absolute;width:auto}.md-typeset abbr[title]:-moz-any(:focus,:hover):after{background-color:var(--md-default-fg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z3);color:var(--md-default-bg-color);content:attr(title);display:inline-block;font-size:.7rem;margin-top:2em;max-width:80%;min-width:-moz-max-content;min-width:max-content;padding:.2rem .3rem;position:absolute;width:auto}[dir=ltr] .md-typeset abbr[title]:-webkit-any(:focus,:hover):after{left:0}[dir=ltr] .md-typeset abbr[title]:-moz-any(:focus,:hover):after{left:0}[dir=ltr] .md-typeset abbr[title]:is(:focus,:hover):after{left:0}[dir=rtl] .md-typeset abbr[title]:-webkit-any(:focus,:hover):after{right:0}[dir=rtl] .md-typeset abbr[title]:-moz-any(:focus,:hover):after{right:0}[dir=rtl] .md-typeset abbr[title]:is(:focus,:hover):after{right:0}.md-typeset abbr[title]:is(:focus,:hover):after{background-color:var(--md-default-fg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z3);color:var(--md-default-bg-color);content:attr(title);display:inline-block;font-size:.7rem;margin-top:2em;max-width:80%;min-width:-webkit-max-content;min-width:-moz-max-content;min-width:max-content;padding:.2rem .3rem;position:absolute;width:auto}}.md-typeset small{opacity:.75}[dir=ltr] .md-typeset sub,[dir=ltr] .md-typeset sup{margin-left:.078125em}[dir=rtl] .md-typeset sub,[dir=rtl] .md-typeset sup{margin-right:.078125em}[dir=ltr] .md-typeset blockquote{padding-left:.6rem}[dir=rtl] .md-typeset blockquote{padding-right:.6rem}[dir=ltr] .md-typeset blockquote{border-left:.2rem solid var(--md-default-fg-color--lighter)}[dir=rtl] .md-typeset blockquote{border-right:.2rem solid var(--md-default-fg-color--lighter)}.md-typeset blockquote{color:var(--md-default-fg-color--light);margin-left:0;margin-right:0}.md-typeset ul{list-style-type:disc}[dir=ltr] .md-typeset ol,[dir=ltr] .md-typeset ul{margin-left:.625em}[dir=rtl] .md-typeset ol,[dir=rtl] .md-typeset ul{margin-right:.625em}.md-typeset ol,.md-typeset ul{padding:0}.md-typeset ol:not([hidden]),.md-typeset ul:not([hidden]){display:flow-root}.md-typeset ol ol,.md-typeset ul ol{list-style-type:lower-alpha}.md-typeset ol ol ol,.md-typeset ul ol ol{list-style-type:lower-roman}[dir=ltr] .md-typeset ol li,[dir=ltr] .md-typeset ul li{margin-left:1.25em}[dir=rtl] .md-typeset ol li,[dir=rtl] .md-typeset ul li{margin-right:1.25em}.md-typeset ol li,.md-typeset ul li{margin-bottom:.5em}.md-typeset ol li blockquote,.md-typeset ol li p,.md-typeset ul li blockquote,.md-typeset ul li p{margin:.5em 0}.md-typeset ol li:last-child,.md-typeset ul li:last-child{margin-bottom:0}.md-typeset ol li :-webkit-any(ul,ol),.md-typeset ul li :-webkit-any(ul,ol){margin-bottom:.5em;margin-top:.5em}.md-typeset ol li :-moz-any(ul,ol),.md-typeset ul li :-moz-any(ul,ol){margin-bottom:.5em;margin-top:.5em}[dir=ltr] .md-typeset ol li :-webkit-any(ul,ol),[dir=ltr] .md-typeset ul li :-webkit-any(ul,ol){margin-left:.625em}[dir=ltr] .md-typeset ol li :-moz-any(ul,ol),[dir=ltr] .md-typeset ul li :-moz-any(ul,ol){margin-left:.625em}[dir=ltr] .md-typeset ol li :is(ul,ol),[dir=ltr] .md-typeset ul li :is(ul,ol){margin-left:.625em}[dir=rtl] .md-typeset ol li :-webkit-any(ul,ol),[dir=rtl] .md-typeset ul li :-webkit-any(ul,ol){margin-right:.625em}[dir=rtl] .md-typeset ol li :-moz-any(ul,ol),[dir=rtl] .md-typeset ul li :-moz-any(ul,ol){margin-right:.625em}[dir=rtl] .md-typeset ol li :is(ul,ol),[dir=rtl] .md-typeset ul li :is(ul,ol){margin-right:.625em}.md-typeset ol li :is(ul,ol),.md-typeset ul li :is(ul,ol){margin-bottom:.5em;margin-top:.5em}[dir=ltr] .md-typeset dd{margin-left:1.875em}[dir=rtl] .md-typeset dd{margin-right:1.875em}.md-typeset dd{margin-bottom:1.5em;margin-top:1em}.md-typeset img,.md-typeset svg{height:auto;max-width:100%}.md-typeset img[align=left],.md-typeset svg[align=left]{margin:1em 1em 1em 0}.md-typeset img[align=right],.md-typeset svg[align=right]{margin:1em 0 1em 1em}.md-typeset img[align]:only-child,.md-typeset svg[align]:only-child{margin-top:0}.md-typeset img[src$="#only-dark"]{display:none}.md-typeset figure{display:flow-root;margin:1em auto;max-width:100%;text-align:center;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.md-typeset figure img{display:block}.md-typeset figcaption{font-style:italic;margin:1em auto;max-width:24rem}.md-typeset iframe{max-width:100%}.md-typeset table:not([class]){background-color:var(--md-default-bg-color);border:.05rem solid var(--md-typeset-table-color);border-radius:.1rem;display:inline-block;font-size:.64rem;max-width:100%;overflow:auto;touch-action:auto}@media print{.md-typeset table:not([class]){display:table}}.md-typeset table:not([class])+*{margin-top:1.5em}.md-typeset table:not([class]) :-webkit-any(th,td)>:first-child{margin-top:0}.md-typeset table:not([class]) :-moz-any(th,td)>:first-child{margin-top:0}.md-typeset table:not([class]) :is(th,td)>:first-child{margin-top:0}.md-typeset table:not([class]) :-webkit-any(th,td)>:last-child{margin-bottom:0}.md-typeset table:not([class]) :-moz-any(th,td)>:last-child{margin-bottom:0}.md-typeset table:not([class]) :is(th,td)>:last-child{margin-bottom:0}.md-typeset table:not([class]) :-webkit-any(th,td):not([align]){text-align:left}.md-typeset table:not([class]) :-moz-any(th,td):not([align]){text-align:left}.md-typeset table:not([class]) :is(th,td):not([align]){text-align:left}[dir=rtl] .md-typeset table:not([class]) :-webkit-any(th,td):not([align]){text-align:right}[dir=rtl] .md-typeset table:not([class]) :-moz-any(th,td):not([align]){text-align:right}[dir=rtl] .md-typeset table:not([class]) :is(th,td):not([align]){text-align:right}.md-typeset table:not([class]) th{font-weight:700;min-width:5rem;padding:.9375em 1.25em;vertical-align:top}.md-typeset table:not([class]) th a{color:inherit}.md-typeset table:not([class]) td{border-top:.05rem solid var(--md-typeset-table-color);padding:.9375em 1.25em;vertical-align:top}.md-typeset table:not([class]) tbody tr{transition:background-color 125ms}.md-typeset table:not([class]) tbody tr:hover{background-color:rgba(0,0,0,.035);box-shadow:0 .05rem 0 var(--md-default-bg-color) inset}.md-typeset table:not([class]) a{word-break:normal}.md-typeset table th[role=columnheader]{cursor:pointer}[dir=ltr] .md-typeset table th[role=columnheader]:after{margin-left:.5em}[dir=rtl] .md-typeset table th[role=columnheader]:after{margin-right:.5em}.md-typeset table th[role=columnheader]:after{content:"";display:inline-block;height:1.2em;-webkit-mask-image:var(--md-typeset-table-sort-icon);mask-image:var(--md-typeset-table-sort-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color 125ms;vertical-align:text-bottom;width:1.2em}.md-typeset table th[role=columnheader]:hover:after{background-color:var(--md-default-fg-color--lighter)}.md-typeset table th[role=columnheader][aria-sort=ascending]:after{background-color:var(--md-default-fg-color--light);-webkit-mask-image:var(--md-typeset-table-sort-icon--asc);mask-image:var(--md-typeset-table-sort-icon--asc)}.md-typeset table th[role=columnheader][aria-sort=descending]:after{background-color:var(--md-default-fg-color--light);-webkit-mask-image:var(--md-typeset-table-sort-icon--desc);mask-image:var(--md-typeset-table-sort-icon--desc)}.md-typeset__scrollwrap{margin:1em -.8rem;overflow-x:auto;touch-action:auto}.md-typeset__table{display:inline-block;margin-bottom:.5em;padding:0 .8rem}@media print{.md-typeset__table{display:block}}html .md-typeset__table table{display:table;margin:0;overflow:hidden;width:100%}@media screen and (max-width:44.9375em){.md-content__inner>pre{margin:1em -.8rem}.md-content__inner>pre code{border-radius:0}}.md-banner{background-color:var(--md-footer-bg-color);color:var(--md-footer-fg-color);overflow:auto}@media print{.md-banner{display:none}}.md-banner--warning{background:var(--md-typeset-mark-color);color:var(--md-default-fg-color)}.md-banner__inner{font-size:.7rem;margin:.6rem auto;padding:0 .8rem}html{font-size:125%;height:100%;overflow-x:hidden}@media screen and (min-width:100em){html{font-size:137.5%}}@media screen and (min-width:125em){html{font-size:150%}}body{background-color:var(--md-default-bg-color);display:flex;flex-direction:column;font-size:.5rem;min-height:100%;position:relative;width:100%}@media print{body{display:block}}@media screen and (max-width:59.9375em){body[data-md-state=lock]{position:fixed}}.md-grid{margin-left:auto;margin-right:auto;max-width:61rem}.md-container{display:flex;flex-direction:column;flex-grow:1}@media print{.md-container{display:block}}.md-main{flex-grow:1}.md-main__inner{display:flex;height:100%;margin-top:1.5rem}.md-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.md-toggle{display:none}.md-option{height:0;opacity:0;position:absolute;width:0}.md-option:checked+label:not([hidden]){display:block}.md-option.focus-visible+label{outline-color:var(--md-accent-fg-color);outline-style:auto}.md-skip{background-color:var(--md-default-fg-color);border-radius:.1rem;color:var(--md-default-bg-color);font-size:.64rem;margin:.5rem;opacity:0;outline-color:var(--md-accent-fg-color);padding:.3rem .5rem;position:fixed;transform:translateY(.4rem);z-index:-1}.md-skip:focus{opacity:1;transform:translateY(0);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity 175ms 75ms;z-index:10}@page{margin:25mm}:root{--md-clipboard-icon:url('data:image/svg+xml;charset=utf-8,')}.md-clipboard{border-radius:.1rem;color:var(--md-default-fg-color--lightest);cursor:pointer;height:1.5em;outline-color:var(--md-accent-fg-color);outline-offset:.1rem;position:absolute;right:.5em;top:.5em;transition:color .25s;width:1.5em;z-index:1}@media print{.md-clipboard{display:none}}.md-clipboard:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}:hover>.md-clipboard{color:var(--md-default-fg-color--light)}.md-clipboard:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-clipboard:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-clipboard:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-clipboard:after{background-color:currentcolor;content:"";display:block;height:1.125em;margin:0 auto;-webkit-mask-image:var(--md-clipboard-icon);mask-image:var(--md-clipboard-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:1.125em}.md-clipboard--inline{cursor:pointer}.md-clipboard--inline code{transition:color .25s,background-color .25s}.md-clipboard--inline:-webkit-any(:focus,:hover) code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-clipboard--inline:-moz-any(:focus,:hover) code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-clipboard--inline:is(:focus,:hover) code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-content{flex-grow:1;min-width:0}.md-content__inner{margin:0 .8rem 1.2rem;padding-top:.6rem}@media screen and (min-width:76.25em){[dir=ltr] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}[dir=ltr] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner,[dir=rtl] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem}[dir=rtl] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}}.md-content__inner:before{content:"";display:block;height:.4rem}.md-content__inner>:last-child{margin-bottom:0}[dir=ltr] .md-content__button{margin-left:.4rem}[dir=rtl] .md-content__button{margin-right:.4rem}.md-content__button{float:right;margin:.4rem 0;padding:0}@media print{.md-content__button{display:none}}[dir=rtl] .md-content__button{float:left}.md-typeset .md-content__button{color:var(--md-default-fg-color--lighter)}.md-content__button svg{display:inline;vertical-align:top}[dir=rtl] .md-content__button svg{transform:scaleX(-1)}[dir=ltr] .md-dialog{right:.8rem}[dir=rtl] .md-dialog{left:.8rem}.md-dialog{background-color:var(--md-default-fg-color);border-radius:.1rem;bottom:.8rem;box-shadow:var(--md-shadow-z3);min-width:11.1rem;opacity:0;padding:.4rem .6rem;pointer-events:none;position:fixed;transform:translateY(100%);transition:transform 0ms .4s,opacity .4s;z-index:4}@media print{.md-dialog{display:none}}.md-dialog[data-md-state=open]{opacity:1;pointer-events:auto;transform:translateY(0);transition:transform .4s cubic-bezier(.075,.85,.175,1),opacity .4s}.md-dialog__inner{color:var(--md-default-bg-color);font-size:.7rem}.md-footer{background-color:var(--md-footer-bg-color);color:var(--md-footer-fg-color)}@media print{.md-footer{display:none}}.md-footer__inner{display:flex;justify-content:space-between;overflow:auto;padding:.2rem}.md-footer__link{display:flex;flex-grow:0.01;outline-color:var(--md-accent-fg-color);overflow:hidden;padding-bottom:.4rem;padding-top:1.4rem;transition:opacity .25s}.md-footer__link:-webkit-any(:focus,:hover){opacity:.7}.md-footer__link:-moz-any(:focus,:hover){opacity:.7}.md-footer__link:is(:focus,:hover){opacity:.7}[dir=rtl] .md-footer__link svg{transform:scaleX(-1)}@media screen and (max-width:44.9375em){.md-footer__link--prev .md-footer__title{display:none}}[dir=ltr] .md-footer__link--next{margin-left:auto}[dir=rtl] .md-footer__link--next{margin-right:auto}.md-footer__link--next{text-align:right}[dir=rtl] .md-footer__link--next{text-align:left}.md-footer__title{flex-grow:1;font-size:.9rem;line-height:2.4rem;max-width:calc(100% - 2.4rem);padding:0 1rem;position:relative}.md-footer__button{margin:.2rem;padding:.4rem}.md-footer__direction{font-size:.64rem;left:0;margin-top:-1rem;opacity:.7;padding:0 1rem;position:absolute;right:0}.md-footer-meta{background-color:var(--md-footer-bg-color--dark)}.md-footer-meta__inner{display:flex;flex-wrap:wrap;justify-content:space-between;padding:.2rem}html .md-footer-meta.md-typeset a{color:var(--md-footer-fg-color--light)}html .md-footer-meta.md-typeset a:-webkit-any(:focus,:hover){color:var(--md-footer-fg-color)}html .md-footer-meta.md-typeset a:-moz-any(:focus,:hover){color:var(--md-footer-fg-color)}html .md-footer-meta.md-typeset a:is(:focus,:hover){color:var(--md-footer-fg-color)}.md-copyright{color:var(--md-footer-fg-color--lighter);font-size:.64rem;margin:auto .6rem;padding:.4rem 0;width:100%}@media screen and (min-width:45em){.md-copyright{width:auto}}.md-copyright__highlight{color:var(--md-footer-fg-color--light)}.md-social{margin:0 .4rem;padding:.2rem 0 .6rem}@media screen and (min-width:45em){.md-social{padding:.6rem 0}}.md-social__link{display:inline-block;height:1.6rem;text-align:center;width:1.6rem}.md-social__link:before{line-height:1.9}.md-social__link svg{fill:currentcolor;max-height:.8rem;vertical-align:-25%}.md-typeset .md-button{border:.1rem solid;border-radius:.1rem;color:var(--md-primary-fg-color);cursor:pointer;display:inline-block;font-weight:700;padding:.625em 2em;transition:color 125ms,background-color 125ms,border-color 125ms}.md-typeset .md-button--primary{background-color:var(--md-primary-fg-color);border-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color)}.md-typeset .md-button:-webkit-any(:focus,:hover){background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-typeset .md-button:-moz-any(:focus,:hover){background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-typeset .md-button:is(:focus,:hover){background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}[dir=ltr] .md-typeset .md-input{border-top-left-radius:.1rem}[dir=ltr] .md-typeset .md-input,[dir=rtl] .md-typeset .md-input{border-top-right-radius:.1rem}[dir=rtl] .md-typeset .md-input{border-top-left-radius:.1rem}.md-typeset .md-input{border-bottom:.1rem solid var(--md-default-fg-color--lighter);box-shadow:var(--md-shadow-z1);font-size:.8rem;height:1.8rem;padding:0 .6rem;transition:border .25s,box-shadow .25s}.md-typeset .md-input:-webkit-any(:focus,:hover){border-bottom-color:var(--md-accent-fg-color);box-shadow:var(--md-shadow-z2)}.md-typeset .md-input:-moz-any(:focus,:hover){border-bottom-color:var(--md-accent-fg-color);box-shadow:var(--md-shadow-z2)}.md-typeset .md-input:is(:focus,:hover){border-bottom-color:var(--md-accent-fg-color);box-shadow:var(--md-shadow-z2)}.md-typeset .md-input--stretch{width:100%}.md-header{background-color:var(--md-primary-fg-color);box-shadow:0 0 .2rem transparent,0 .2rem .4rem transparent;color:var(--md-primary-bg-color);left:0;position:-webkit-sticky;position:sticky;right:0;top:0;z-index:4}@media print{.md-header{display:none}}.md-header[data-md-state=shadow]{box-shadow:0 0 .2rem rgba(0,0,0,.1),0 .2rem .4rem rgba(0,0,0,.2);transition:transform .25s cubic-bezier(.1,.7,.1,1),box-shadow .25s}.md-header[data-md-state=hidden]{transform:translateY(-100%);transition:transform .25s cubic-bezier(.8,0,.6,1),box-shadow .25s}.md-header__inner{align-items:center;display:flex;padding:0 .2rem}.md-header__button{color:currentcolor;cursor:pointer;margin:.2rem;outline-color:var(--md-accent-fg-color);padding:.4rem;position:relative;transition:opacity .25s;vertical-align:middle;z-index:1}.md-header__button:hover{opacity:.7}.md-header__button:not([hidden]){display:inline-block}.md-header__button:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}.md-header__button.md-logo{margin:.2rem;padding:.4rem}@media screen and (max-width:76.1875em){.md-header__button.md-logo{display:none}}.md-header__button.md-logo :-webkit-any(img,svg){fill:currentcolor;display:block;height:1.2rem;width:auto}.md-header__button.md-logo :-moz-any(img,svg){fill:currentcolor;display:block;height:1.2rem;width:auto}.md-header__button.md-logo :is(img,svg){fill:currentcolor;display:block;height:1.2rem;width:auto}@media screen and (min-width:60em){.md-header__button[for=__search]{display:none}}.no-js .md-header__button[for=__search]{display:none}[dir=rtl] .md-header__button[for=__search] svg{transform:scaleX(-1)}@media screen and (min-width:76.25em){.md-header__button[for=__drawer]{display:none}}.md-header__topic{display:flex;max-width:100%;position:absolute;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s}.md-header__topic+.md-header__topic{opacity:0;pointer-events:none;transform:translateX(1.25rem);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;z-index:-1}[dir=rtl] .md-header__topic+.md-header__topic{transform:translateX(-1.25rem)}.md-header__topic:first-child{font-weight:700}[dir=ltr] .md-header__title{margin-right:.4rem}[dir=rtl] .md-header__title{margin-left:.4rem}[dir=ltr] .md-header__title{margin-left:1rem}[dir=rtl] .md-header__title{margin-right:1rem}.md-header__title{flex-grow:1;font-size:.9rem;height:2.4rem;line-height:2.4rem}.md-header__title[data-md-state=active] .md-header__topic{opacity:0;pointer-events:none;transform:translateX(-1.25rem);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;z-index:-1}[dir=rtl] .md-header__title[data-md-state=active] .md-header__topic{transform:translateX(1.25rem)}.md-header__title[data-md-state=active] .md-header__topic+.md-header__topic{opacity:1;pointer-events:auto;transform:translateX(0);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s;z-index:0}.md-header__title>.md-header__ellipsis{height:100%;position:relative;width:100%}.md-header__option{display:flex;flex-shrink:0;max-width:100%;transition:max-width 0ms .25s,opacity .25s .25s;white-space:nowrap}[data-md-toggle=search]:checked~.md-header .md-header__option{max-width:0;opacity:0;transition:max-width 0ms,opacity 0ms}.md-header__source{display:none}@media screen and (min-width:60em){[dir=ltr] .md-header__source{margin-left:1rem}[dir=rtl] .md-header__source{margin-right:1rem}.md-header__source{display:block;max-width:11.7rem;width:11.7rem}}@media screen and (min-width:76.25em){[dir=ltr] .md-header__source{margin-left:1.4rem}[dir=rtl] .md-header__source{margin-right:1.4rem}}:root{--md-nav-icon--prev:url('data:image/svg+xml;charset=utf-8,');--md-nav-icon--next:url('data:image/svg+xml;charset=utf-8,');--md-toc-icon:url('data:image/svg+xml;charset=utf-8,')}.md-nav{font-size:.7rem;line-height:1.3}.md-nav__title{display:block;font-weight:700;overflow:hidden;padding:0 .6rem;text-overflow:ellipsis}.md-nav__title .md-nav__button{display:none}.md-nav__title .md-nav__button img{height:100%;width:auto}.md-nav__title .md-nav__button.md-logo :-webkit-any(img,svg){fill:currentcolor;display:block;height:2.4rem;max-width:100%;object-fit:contain;width:auto}.md-nav__title .md-nav__button.md-logo :-moz-any(img,svg){fill:currentcolor;display:block;height:2.4rem;max-width:100%;object-fit:contain;width:auto}.md-nav__title .md-nav__button.md-logo :is(img,svg){fill:currentcolor;display:block;height:2.4rem;max-width:100%;object-fit:contain;width:auto}.md-nav__list{list-style:none;margin:0;padding:0}.md-nav__item{padding:0 .6rem}[dir=ltr] .md-nav__item .md-nav__item{padding-right:0}[dir=rtl] .md-nav__item .md-nav__item{padding-left:0}.md-nav__link{align-items:center;cursor:pointer;display:flex;justify-content:space-between;margin-top:.625em;overflow:hidden;scroll-snap-align:start;text-overflow:ellipsis;transition:color 125ms}.md-nav__link[data-md-state=blur]{color:var(--md-default-fg-color--light)}.md-nav__item .md-nav__link--active{color:var(--md-typeset-a-color)}.md-nav__item .md-nav__link--index [href]{width:100%}.md-nav__link:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav__link:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav__link:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav__link.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-nav--primary .md-nav__link[for=__toc]{display:none}.md-nav--primary .md-nav__link[for=__toc] .md-icon:after{background-color:currentcolor;display:block;height:100%;-webkit-mask-image:var(--md-toc-icon);mask-image:var(--md-toc-icon);width:100%}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:none}.md-nav__link>*{cursor:pointer;display:flex}.md-nav__icon{flex-shrink:0}.md-nav__source{display:none}@media screen and (max-width:76.1875em){.md-nav--primary,.md-nav--primary .md-nav{background-color:var(--md-default-bg-color);display:flex;flex-direction:column;height:100%;left:0;position:absolute;right:0;top:0;z-index:1}.md-nav--primary :-webkit-any(.md-nav__title,.md-nav__item){font-size:.8rem;line-height:1.5}.md-nav--primary :-moz-any(.md-nav__title,.md-nav__item){font-size:.8rem;line-height:1.5}.md-nav--primary :is(.md-nav__title,.md-nav__item){font-size:.8rem;line-height:1.5}.md-nav--primary .md-nav__title{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light);cursor:pointer;height:5.6rem;line-height:2.4rem;padding:3rem .8rem .2rem;position:relative;white-space:nowrap}[dir=ltr] .md-nav--primary .md-nav__title .md-nav__icon{left:.4rem}[dir=rtl] .md-nav--primary .md-nav__title .md-nav__icon{right:.4rem}.md-nav--primary .md-nav__title .md-nav__icon{display:block;height:1.2rem;margin:.2rem;position:absolute;top:.4rem;width:1.2rem}.md-nav--primary .md-nav__title .md-nav__icon:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-nav-icon--prev);mask-image:var(--md-nav-icon--prev);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}.md-nav--primary .md-nav__title~.md-nav__list{background-color:var(--md-default-bg-color);box-shadow:0 .05rem 0 var(--md-default-fg-color--lightest) inset;overflow-y:auto;-ms-scroll-snap-type:y mandatory;scroll-snap-type:y mandatory;touch-action:pan-y}.md-nav--primary .md-nav__title~.md-nav__list>:first-child{border-top:0}.md-nav--primary .md-nav__title[for=__drawer]{background-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color);font-weight:700}.md-nav--primary .md-nav__title .md-logo{display:block;left:.2rem;margin:.2rem;padding:.4rem;position:absolute;right:.2rem;top:.2rem}.md-nav--primary .md-nav__list{flex:1}.md-nav--primary .md-nav__item{border-top:.05rem solid var(--md-default-fg-color--lightest);padding:0}.md-nav--primary .md-nav__item--active>.md-nav__link{color:var(--md-typeset-a-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link{margin-top:0;padding:.6rem .8rem}[dir=ltr] .md-nav--primary .md-nav__link .md-nav__icon{margin-right:-.2rem}[dir=rtl] .md-nav--primary .md-nav__link .md-nav__icon{margin-left:-.2rem}.md-nav--primary .md-nav__link .md-nav__icon{font-size:1.2rem;height:1.2rem;width:1.2rem}.md-nav--primary .md-nav__link .md-nav__icon:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}[dir=rtl] .md-nav--primary .md-nav__icon:after{transform:scale(-1)}.md-nav--primary .md-nav--secondary .md-nav{background-color:initial;position:static}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-left:1.4rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-right:1.4rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-left:2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-right:2rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-left:2.6rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-right:2.6rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-left:3.2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-right:3.2rem}.md-nav--secondary{background-color:initial}.md-nav__toggle~.md-nav{display:flex;opacity:0;transform:translateX(100%);transition:transform .25s cubic-bezier(.8,0,.6,1),opacity 125ms 50ms}[dir=rtl] .md-nav__toggle~.md-nav{transform:translateX(-100%)}.md-nav__toggle:checked~.md-nav{opacity:1;transform:translateX(0);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity 125ms 125ms}.md-nav__toggle:checked~.md-nav>.md-nav__list{-webkit-backface-visibility:hidden;backface-visibility:hidden}}@media screen and (max-width:59.9375em){.md-nav--primary .md-nav__link[for=__toc]{display:flex}.md-nav--primary .md-nav__link[for=__toc] .md-icon:after{content:""}.md-nav--primary .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:flex}.md-nav__source{background-color:var(--md-primary-fg-color--dark);color:var(--md-primary-bg-color);display:block;padding:0 .2rem}}@media screen and (min-width:60em) and (max-width:76.1875em){.md-nav--integrated .md-nav__link[for=__toc]{display:flex}.md-nav--integrated .md-nav__link[for=__toc] .md-icon:after{content:""}.md-nav--integrated .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:flex}}@media screen and (min-width:60em){.md-nav--secondary .md-nav__title[for=__toc]{scroll-snap-align:start}.md-nav--secondary .md-nav__title .md-nav__icon{display:none}}@media screen and (min-width:76.25em){.md-nav{transition:max-height .25s cubic-bezier(.86,0,.07,1)}.md-nav--primary .md-nav__title[for=__drawer]{scroll-snap-align:start}.md-nav--primary .md-nav__title .md-nav__icon,.md-nav__toggle~.md-nav{display:none}.md-nav__toggle:-webkit-any(:checked,:indeterminate)~.md-nav{display:block}.md-nav__toggle:-moz-any(:checked,:indeterminate)~.md-nav{display:block}.md-nav__toggle:is(:checked,:indeterminate)~.md-nav{display:block}.md-nav__item--nested>.md-nav>.md-nav__title{display:none}.md-nav__item--section{display:block;margin:1.25em 0}.md-nav__item--section:last-child{margin-bottom:0}.md-nav__item--section>.md-nav__link{font-weight:700;pointer-events:none}.md-nav__item--section>.md-nav__link--index [href]{pointer-events:auto}.md-nav__item--section>.md-nav__link .md-nav__icon{display:none}.md-nav__item--section>.md-nav{display:block}.md-nav__item--section>.md-nav>.md-nav__list>.md-nav__item{padding:0}.md-nav__icon{border-radius:100%;float:right;height:.9rem;transition:background-color .25s,transform .25s;width:.9rem}[dir=rtl] .md-nav__icon{float:left;transform:rotate(180deg)}.md-nav__icon:hover{background-color:var(--md-accent-fg-color--transparent)}.md-nav__icon:after{background-color:currentcolor;content:"";display:inline-block;height:100%;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;vertical-align:-.1rem;width:100%}.md-nav__item--nested .md-nav__toggle:checked~.md-nav__link .md-nav__icon,.md-nav__item--nested .md-nav__toggle:indeterminate~.md-nav__link .md-nav__icon{transform:rotate(90deg)}.md-nav--lifted>.md-nav__list>.md-nav__item,.md-nav--lifted>.md-nav__list>.md-nav__item--nested,.md-nav--lifted>.md-nav__title{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active{display:block;padding:0}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link{font-weight:700;margin-top:0;padding:0 .6rem;pointer-events:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link--index [href]{pointer-events:auto}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link .md-nav__icon{display:none}.md-nav--lifted .md-nav[data-md-level="1"]{display:block}[dir=ltr] .md-nav--lifted .md-nav[data-md-level="1"]>.md-nav__list>.md-nav__item{padding-right:.6rem}[dir=rtl] .md-nav--lifted .md-nav[data-md-level="1"]>.md-nav__list>.md-nav__item{padding-left:.6rem}.md-nav--integrated>.md-nav__list>.md-nav__item--active:not(.md-nav__item--nested){padding:0 .6rem}.md-nav--integrated>.md-nav__list>.md-nav__item--active:not(.md-nav__item--nested)>.md-nav__link{padding:0}[dir=ltr] .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{border-left:.05rem solid var(--md-primary-fg-color)}[dir=rtl] .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{border-right:.05rem solid var(--md-primary-fg-color)}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{display:block;margin-bottom:1.25em}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary>.md-nav__title{display:none}}:root{--md-search-result-icon:url('data:image/svg+xml;charset=utf-8,')}.md-search{position:relative}@media screen and (min-width:60em){.md-search{padding:.2rem 0}}.no-js .md-search{display:none}.md-search__overlay{opacity:0;z-index:1}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__overlay{left:-2.2rem}[dir=rtl] .md-search__overlay{right:-2.2rem}.md-search__overlay{background-color:var(--md-default-bg-color);border-radius:1rem;height:2rem;overflow:hidden;pointer-events:none;position:absolute;top:-1rem;transform-origin:center;transition:transform .3s .1s,opacity .2s .2s;width:2rem}[data-md-toggle=search]:checked~.md-header .md-search__overlay{opacity:1;transition:transform .4s,opacity .1s}}@media screen and (min-width:60em){[dir=ltr] .md-search__overlay{left:0}[dir=rtl] .md-search__overlay{right:0}.md-search__overlay{background-color:rgba(0,0,0,.54);cursor:pointer;height:0;position:fixed;top:0;transition:width 0ms .25s,height 0ms .25s,opacity .25s;width:0}[data-md-toggle=search]:checked~.md-header .md-search__overlay{height:200vh;opacity:1;transition:width 0ms,height 0ms,opacity .25s;width:100%}}@media screen and (max-width:29.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(45)}}@media screen and (min-width:30em) and (max-width:44.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(60)}}@media screen and (min-width:45em) and (max-width:59.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(75)}}.md-search__inner{-webkit-backface-visibility:hidden;backface-visibility:hidden}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__inner{left:0}[dir=rtl] .md-search__inner{right:0}.md-search__inner{height:0;opacity:0;overflow:hidden;position:fixed;top:0;transform:translateX(5%);transition:width 0ms .3s,height 0ms .3s,transform .15s cubic-bezier(.4,0,.2,1) .15s,opacity .15s .15s;width:0;z-index:2}[dir=rtl] .md-search__inner{transform:translateX(-5%)}[data-md-toggle=search]:checked~.md-header .md-search__inner{height:100%;opacity:1;transform:translateX(0);transition:width 0ms 0ms,height 0ms 0ms,transform .15s cubic-bezier(.1,.7,.1,1) .15s,opacity .15s .15s;width:100%}}@media screen and (min-width:60em){.md-search__inner{float:right;padding:.1rem 0;position:relative;transition:width .25s cubic-bezier(.1,.7,.1,1);width:11.7rem}[dir=rtl] .md-search__inner{float:left}}@media screen and (min-width:60em) and (max-width:76.1875em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:23.4rem}}@media screen and (min-width:76.25em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:34.4rem}}.md-search__form{background-color:var(--md-default-bg-color);box-shadow:0 0 .6rem transparent;height:2.4rem;position:relative;transition:color .25s,background-color .25s;z-index:2}@media screen and (min-width:60em){.md-search__form{background-color:rgba(0,0,0,.26);border-radius:.1rem;height:1.8rem}.md-search__form:hover{background-color:hsla(0,0%,100%,.12)}}[data-md-toggle=search]:checked~.md-header .md-search__form{background-color:var(--md-default-bg-color);border-radius:.1rem .1rem 0 0;box-shadow:0 0 .6rem rgba(0,0,0,.07);color:var(--md-default-fg-color)}[dir=ltr] .md-search__input{padding-left:3.6rem;padding-right:2.2rem}[dir=rtl] .md-search__input{padding-left:2.2rem;padding-right:3.6rem}.md-search__input{background:transparent;font-size:.9rem;height:100%;position:relative;text-overflow:ellipsis;width:100%;z-index:2}.md-search__input::-moz-placeholder{-moz-transition:color .25s;transition:color .25s}.md-search__input::-ms-input-placeholder{-ms-transition:color .25s;transition:color .25s}.md-search__input::placeholder{transition:color .25s}.md-search__input::-moz-placeholder{color:var(--md-default-fg-color--light)}.md-search__input::-ms-input-placeholder{color:var(--md-default-fg-color--light)}.md-search__input::placeholder,.md-search__input~.md-search__icon{color:var(--md-default-fg-color--light)}.md-search__input::-ms-clear{display:none}@media screen and (max-width:59.9375em){.md-search__input{font-size:.9rem;height:2.4rem;width:100%}}@media screen and (min-width:60em){[dir=ltr] .md-search__input{padding-left:2.2rem}[dir=rtl] .md-search__input{padding-right:2.2rem}.md-search__input{color:inherit;font-size:.8rem}.md-search__input::-moz-placeholder{color:var(--md-primary-bg-color--light)}.md-search__input::-ms-input-placeholder{color:var(--md-primary-bg-color--light)}.md-search__input::placeholder{color:var(--md-primary-bg-color--light)}.md-search__input+.md-search__icon{color:var(--md-primary-bg-color)}[data-md-toggle=search]:checked~.md-header .md-search__input{text-overflow:clip}[data-md-toggle=search]:checked~.md-header .md-search__input::-moz-placeholder{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input::-ms-input-placeholder{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input+.md-search__icon,[data-md-toggle=search]:checked~.md-header .md-search__input::placeholder{color:var(--md-default-fg-color--light)}}.md-search__icon{cursor:pointer;display:inline-block;height:1.2rem;transition:color .25s,opacity .25s;width:1.2rem}.md-search__icon:hover{opacity:.7}[dir=ltr] .md-search__icon[for=__search]{left:.5rem}[dir=rtl] .md-search__icon[for=__search]{right:.5rem}.md-search__icon[for=__search]{position:absolute;top:.3rem;z-index:2}[dir=rtl] .md-search__icon[for=__search] svg{transform:scaleX(-1)}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__icon[for=__search]{left:.8rem}[dir=rtl] .md-search__icon[for=__search]{right:.8rem}.md-search__icon[for=__search]{top:.6rem}.md-search__icon[for=__search] svg:first-child{display:none}}@media screen and (min-width:60em){.md-search__icon[for=__search]{pointer-events:none}.md-search__icon[for=__search] svg:last-child{display:none}}[dir=ltr] .md-search__options{right:.5rem}[dir=rtl] .md-search__options{left:.5rem}.md-search__options{pointer-events:none;position:absolute;top:.3rem;z-index:2}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__options{right:.8rem}[dir=rtl] .md-search__options{left:.8rem}.md-search__options{top:.6rem}}[dir=ltr] .md-search__options>*{margin-left:.2rem}[dir=rtl] .md-search__options>*{margin-right:.2rem}.md-search__options>*{color:var(--md-default-fg-color--light);opacity:0;transform:scale(.75);transition:transform .15s cubic-bezier(.1,.7,.1,1),opacity .15s}.md-search__options>:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__options>*{opacity:1;pointer-events:auto;transform:scale(1)}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__options>:hover{opacity:.7}[dir=ltr] .md-search__suggest{padding-left:3.6rem;padding-right:2.2rem}[dir=rtl] .md-search__suggest{padding-left:2.2rem;padding-right:3.6rem}.md-search__suggest{align-items:center;color:var(--md-default-fg-color--lighter);display:flex;font-size:.9rem;height:100%;opacity:0;position:absolute;top:0;transition:opacity 50ms;white-space:nowrap;width:100%}@media screen and (min-width:60em){[dir=ltr] .md-search__suggest{padding-left:2.2rem}[dir=rtl] .md-search__suggest{padding-right:2.2rem}.md-search__suggest{font-size:.8rem}}[data-md-toggle=search]:checked~.md-header .md-search__suggest{opacity:1;transition:opacity .3s .1s}[dir=ltr] .md-search__output{border-bottom-left-radius:.1rem}[dir=ltr] .md-search__output,[dir=rtl] .md-search__output{border-bottom-right-radius:.1rem}[dir=rtl] .md-search__output{border-bottom-left-radius:.1rem}.md-search__output{overflow:hidden;position:absolute;width:100%;z-index:1}@media screen and (max-width:59.9375em){.md-search__output{bottom:0;top:2.4rem}}@media screen and (min-width:60em){.md-search__output{opacity:0;top:1.9rem;transition:opacity .4s}[data-md-toggle=search]:checked~.md-header .md-search__output{box-shadow:var(--md-shadow-z3);opacity:1}}.md-search__scrollwrap{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:var(--md-default-bg-color);height:100%;overflow-y:auto;touch-action:pan-y}@media (-webkit-max-device-pixel-ratio:1),(max-resolution:1dppx){.md-search__scrollwrap{transform:translateZ(0)}}@media screen and (min-width:60em) and (max-width:76.1875em){.md-search__scrollwrap{width:23.4rem}}@media screen and (min-width:76.25em){.md-search__scrollwrap{width:34.4rem}}@media screen and (min-width:60em){.md-search__scrollwrap{max-height:0;scrollbar-color:var(--md-default-fg-color--lighter) transparent;scrollbar-width:thin}[data-md-toggle=search]:checked~.md-header .md-search__scrollwrap{max-height:75vh}.md-search__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-search__scrollwrap::-webkit-scrollbar{height:.2rem;width:.2rem}.md-search__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}}.md-search-result{color:var(--md-default-fg-color);word-break:break-word}.md-search-result__meta{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.8rem;padding:0 .8rem;scroll-snap-align:start}@media screen and (min-width:60em){[dir=ltr] .md-search-result__meta{padding-left:2.2rem}[dir=rtl] .md-search-result__meta{padding-right:2.2rem}}.md-search-result__list{list-style:none;margin:0;padding:0}.md-search-result__item{box-shadow:0 -.05rem var(--md-default-fg-color--lightest)}.md-search-result__item:first-child{box-shadow:none}.md-search-result__link{display:block;outline:none;scroll-snap-align:start;transition:background-color .25s}.md-search-result__link:-webkit-any(:focus,:hover){background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:-moz-any(:focus,:hover){background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:is(:focus,:hover){background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:last-child p:last-child{margin-bottom:.6rem}.md-search-result__more summary{color:var(--md-typeset-a-color);cursor:pointer;display:block;font-size:.64rem;outline:none;padding:.75em .8rem;scroll-snap-align:start;transition:color .25s,background-color .25s}@media screen and (min-width:60em){[dir=ltr] .md-search-result__more summary{padding-left:2.2rem}[dir=rtl] .md-search-result__more summary{padding-right:2.2rem}}.md-search-result__more summary:-webkit-any(:focus,:hover){background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-search-result__more summary:-moz-any(:focus,:hover){background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-search-result__more summary:is(:focus,:hover){background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-search-result__more summary::marker{display:none}.md-search-result__more summary::-webkit-details-marker{display:none}.md-search-result__more summary~*>*{opacity:.65}.md-search-result__article{overflow:hidden;padding:0 .8rem;position:relative}@media screen and (min-width:60em){[dir=ltr] .md-search-result__article{padding-left:2.2rem}[dir=rtl] .md-search-result__article{padding-right:2.2rem}}.md-search-result__article--document .md-search-result__title{font-size:.8rem;font-weight:400;line-height:1.4;margin:.55rem 0}[dir=ltr] .md-search-result__icon{left:0}[dir=rtl] .md-search-result__icon{right:0}.md-search-result__icon{color:var(--md-default-fg-color--light);height:1.2rem;margin:.5rem;position:absolute;width:1.2rem}@media screen and (max-width:59.9375em){.md-search-result__icon{display:none}}.md-search-result__icon:after{background-color:currentcolor;content:"";display:inline-block;height:100%;-webkit-mask-image:var(--md-search-result-icon);mask-image:var(--md-search-result-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}[dir=rtl] .md-search-result__icon:after{transform:scaleX(-1)}.md-search-result__title{font-size:.64rem;font-weight:700;line-height:1.6;margin:.5em 0}.md-search-result__teaser{-webkit-box-orient:vertical;-webkit-line-clamp:2;color:var(--md-default-fg-color--light);display:-webkit-box;font-size:.64rem;line-height:1.6;margin:.5em 0;max-height:2rem;overflow:hidden;text-overflow:ellipsis}@media screen and (max-width:44.9375em){.md-search-result__teaser{-webkit-line-clamp:3;max-height:3rem}}@media screen and (min-width:60em) and (max-width:76.1875em){.md-search-result__teaser{-webkit-line-clamp:3;max-height:3rem}}.md-search-result__teaser mark{background-color:initial;text-decoration:underline}.md-search-result__terms{font-size:.64rem;font-style:italic;margin:.5em 0}.md-search-result mark{background-color:initial;color:var(--md-accent-fg-color)}.md-select{position:relative;z-index:1}.md-select__inner{background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);left:50%;margin-top:.2rem;max-height:0;opacity:0;position:absolute;top:calc(100% - .2rem);transform:translate3d(-50%,.3rem,0);transition:transform .25s 375ms,opacity .25s .25s,max-height 0ms .5s}.md-select:-webkit-any(:focus-within,:hover) .md-select__inner{max-height:10rem;opacity:1;transform:translate3d(-50%,0,0);-webkit-transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms;transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms}.md-select:-moz-any(:focus-within,:hover) .md-select__inner{max-height:10rem;opacity:1;transform:translate3d(-50%,0,0);-moz-transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms;transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms}.md-select:is(:focus-within,:hover) .md-select__inner{max-height:10rem;opacity:1;transform:translate3d(-50%,0,0);transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms}.md-select__inner:after{border-bottom:.2rem solid transparent;border-bottom-color:var(--md-default-bg-color);border-left:.2rem solid transparent;border-right:.2rem solid transparent;border-top:0;content:"";height:0;left:50%;margin-left:-.2rem;margin-top:-.2rem;position:absolute;top:0;width:0}.md-select__list{border-radius:.1rem;font-size:.8rem;list-style-type:none;margin:0;max-height:inherit;overflow:auto;padding:0}.md-select__item{line-height:1.8rem}[dir=ltr] .md-select__link{padding-left:.6rem;padding-right:1.2rem}[dir=rtl] .md-select__link{padding-left:1.2rem;padding-right:.6rem}.md-select__link{cursor:pointer;display:block;outline:none;scroll-snap-align:start;transition:background-color .25s,color .25s;width:100%}.md-select__link:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-select__link:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-select__link:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-select__link:focus{background-color:var(--md-default-fg-color--lightest)}.md-sidebar{align-self:flex-start;flex-shrink:0;padding:1.2rem 0;position:-webkit-sticky;position:sticky;top:2.4rem;width:12.1rem}@media print{.md-sidebar{display:none}}@media screen and (max-width:76.1875em){[dir=ltr] .md-sidebar--primary{left:-12.1rem}[dir=rtl] .md-sidebar--primary{right:-12.1rem}.md-sidebar--primary{background-color:var(--md-default-bg-color);display:block;height:100%;position:fixed;top:0;transform:translateX(0);transition:transform .25s cubic-bezier(.4,0,.2,1),box-shadow .25s;width:12.1rem;z-index:5}[data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{box-shadow:var(--md-shadow-z3);transform:translateX(12.1rem)}[dir=rtl] [data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{transform:translateX(-12.1rem)}.md-sidebar--primary .md-sidebar__scrollwrap{bottom:0;left:0;margin:0;overflow:hidden;position:absolute;right:0;-ms-scroll-snap-type:none;scroll-snap-type:none;top:0}}@media screen and (min-width:76.25em){.md-sidebar{height:0}.no-js .md-sidebar{height:auto}}.md-sidebar--secondary{display:none;order:2}@media screen and (min-width:60em){.md-sidebar--secondary{height:0}.no-js .md-sidebar--secondary{height:auto}.md-sidebar--secondary:not([hidden]){display:block}.md-sidebar--secondary .md-sidebar__scrollwrap{touch-action:pan-y}}.md-sidebar__scrollwrap{-webkit-backface-visibility:hidden;backface-visibility:hidden;margin:0 .2rem;overflow-y:auto;scrollbar-color:var(--md-default-fg-color--lighter) transparent;scrollbar-width:thin}.md-sidebar__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-sidebar__scrollwrap::-webkit-scrollbar{height:.2rem;width:.2rem}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@media screen and (max-width:76.1875em){.md-overlay{background-color:rgba(0,0,0,.54);height:0;opacity:0;position:fixed;top:0;transition:width 0ms .25s,height 0ms .25s,opacity .25s;width:0;z-index:5}[data-md-toggle=drawer]:checked~.md-overlay{height:100%;opacity:1;transition:width 0ms,height 0ms,opacity .25s;width:100%}}@-webkit-keyframes facts{0%{height:0}to{height:.65rem}}@keyframes facts{0%{height:0}to{height:.65rem}}@-webkit-keyframes fact{0%{opacity:0;transform:translateY(100%)}50%{opacity:0}to{opacity:1;transform:translateY(0)}}@keyframes fact{0%{opacity:0;transform:translateY(100%)}50%{opacity:0}to{opacity:1;transform:translateY(0)}}:root{--md-source-forks-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-repositories-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-stars-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-version-icon:url('data:image/svg+xml;charset=utf-8,')}.md-source{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:block;font-size:.65rem;line-height:1.2;outline-color:var(--md-accent-fg-color);transition:opacity .25s;white-space:nowrap}.md-source:hover{opacity:.7}.md-source__icon{display:inline-block;height:2.4rem;vertical-align:middle;width:2rem}[dir=ltr] .md-source__icon svg{margin-left:.6rem}[dir=rtl] .md-source__icon svg{margin-right:.6rem}.md-source__icon svg{margin-top:.6rem}[dir=ltr] .md-source__icon+.md-source__repository{margin-left:-2rem}[dir=rtl] .md-source__icon+.md-source__repository{margin-right:-2rem}[dir=ltr] .md-source__icon+.md-source__repository{padding-left:2rem}[dir=rtl] .md-source__icon+.md-source__repository{padding-right:2rem}[dir=ltr] .md-source__repository{margin-left:.6rem}[dir=rtl] .md-source__repository{margin-right:.6rem}.md-source__repository{display:inline-block;max-width:calc(100% - 1.2rem);overflow:hidden;text-overflow:ellipsis;vertical-align:middle}.md-source__facts{font-size:.55rem;list-style-type:none;margin:.1rem 0 0;opacity:.75;overflow:hidden;padding:0}[data-md-state=done] .md-source__facts{-webkit-animation:facts .25s ease-in;animation:facts .25s ease-in}.md-source__fact{display:inline-block}[data-md-state=done] .md-source__fact{-webkit-animation:fact .4s ease-out;animation:fact .4s ease-out}[dir=ltr] .md-source__fact:before{margin-right:.1rem}[dir=rtl] .md-source__fact:before{margin-left:.1rem}.md-source__fact:before{background-color:currentcolor;content:"";display:inline-block;height:.6rem;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;vertical-align:text-top;width:.6rem}[dir=ltr] .md-source__fact:nth-child(1n+2):before{margin-left:.4rem}[dir=rtl] .md-source__fact:nth-child(1n+2):before{margin-right:.4rem}.md-source__fact--version:before{-webkit-mask-image:var(--md-source-version-icon);mask-image:var(--md-source-version-icon)}.md-source__fact--stars:before{-webkit-mask-image:var(--md-source-stars-icon);mask-image:var(--md-source-stars-icon)}.md-source__fact--forks:before{-webkit-mask-image:var(--md-source-forks-icon);mask-image:var(--md-source-forks-icon)}.md-source__fact--repositories:before{-webkit-mask-image:var(--md-source-repositories-icon);mask-image:var(--md-source-repositories-icon)}.md-tabs{background-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color);overflow:auto;width:100%}@media print{.md-tabs{display:none}}@media screen and (max-width:76.1875em){.md-tabs{display:none}}.md-tabs[data-md-state=hidden]{pointer-events:none}[dir=ltr] .md-tabs__list{margin-left:.2rem}[dir=rtl] .md-tabs__list{margin-right:.2rem}.md-tabs__list{contain:content;list-style:none;margin:0;padding:0;white-space:nowrap}.md-tabs__item{display:inline-block;height:2.4rem;padding-left:.6rem;padding-right:.6rem}.md-tabs__link{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:block;font-size:.7rem;margin-top:.8rem;opacity:.7;outline-color:var(--md-accent-fg-color);outline-offset:.2rem;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .25s}.md-tabs__link--active,.md-tabs__link:-webkit-any(:focus,:hover){color:inherit;opacity:1}.md-tabs__link--active,.md-tabs__link:-moz-any(:focus,:hover){color:inherit;opacity:1}.md-tabs__link--active,.md-tabs__link:is(:focus,:hover){color:inherit;opacity:1}.md-tabs__item:nth-child(2) .md-tabs__link{transition-delay:20ms}.md-tabs__item:nth-child(3) .md-tabs__link{transition-delay:40ms}.md-tabs__item:nth-child(4) .md-tabs__link{transition-delay:60ms}.md-tabs__item:nth-child(5) .md-tabs__link{transition-delay:80ms}.md-tabs__item:nth-child(6) .md-tabs__link{transition-delay:.1s}.md-tabs__item:nth-child(7) .md-tabs__link{transition-delay:.12s}.md-tabs__item:nth-child(8) .md-tabs__link{transition-delay:.14s}.md-tabs__item:nth-child(9) .md-tabs__link{transition-delay:.16s}.md-tabs__item:nth-child(10) .md-tabs__link{transition-delay:.18s}.md-tabs__item:nth-child(11) .md-tabs__link{transition-delay:.2s}.md-tabs__item:nth-child(12) .md-tabs__link{transition-delay:.22s}.md-tabs__item:nth-child(13) .md-tabs__link{transition-delay:.24s}.md-tabs__item:nth-child(14) .md-tabs__link{transition-delay:.26s}.md-tabs__item:nth-child(15) .md-tabs__link{transition-delay:.28s}.md-tabs__item:nth-child(16) .md-tabs__link{transition-delay:.3s}.md-tabs[data-md-state=hidden] .md-tabs__link{opacity:0;transform:translateY(50%);transition:transform 0ms .1s,opacity .1s}.md-tags{margin-bottom:.75em}[dir=ltr] .md-tag{margin-right:.5em}[dir=rtl] .md-tag{margin-left:.5em}.md-tag{background:var(--md-default-fg-color--lightest);border-radius:.4rem;display:inline-block;font-size:.64rem;font-weight:700;line-height:1.6;margin-bottom:.5em;padding:.3125em .9375em}.md-tag[href]{-webkit-tap-highlight-color:transparent;color:inherit;outline:none;transition:color 125ms,background-color 125ms}.md-tag[href]:focus,.md-tag[href]:hover{background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}[id]>.md-tag{vertical-align:text-top}@-webkit-keyframes pulse{0%{box-shadow:0 0 0 0 var(--md-default-fg-color--lightest)}75%{box-shadow:0 0 0 .625em transparent}to{box-shadow:0 0 0 0 transparent}}@keyframes pulse{0%{box-shadow:0 0 0 0 var(--md-default-fg-color--lightest)}75%{box-shadow:0 0 0 .625em transparent}to{box-shadow:0 0 0 0 transparent}}:root{--md-tooltip-width:20rem}.md-tooltip{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);left:clamp(var(--md-tooltip-0,0rem) + .8rem,var(--md-tooltip-x),(100vw + var(--md-tooltip-0,0rem) + .8rem - var(--md-tooltip-width) - 2 * .8rem));max-height:0;max-width:calc(100vw - 1.6rem);opacity:0;position:absolute;top:var(--md-tooltip-y);transform:translateY(-.4rem);transition:transform 0ms .25s,opacity .25s,max-height 0ms .25s,z-index .25s;width:var(--md-tooltip-width);z-index:0}:focus-within>.md-tooltip{max-height:1000%;opacity:1;transform:translateY(0);transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height .25s,z-index 0ms}.focus-visible>.md-tooltip{outline:var(--md-accent-fg-color) auto}.md-tooltip__inner{font-size:.64rem;padding:.8rem}.md-tooltip__inner.md-typeset>:first-child{margin-top:0}.md-tooltip__inner.md-typeset>:last-child{margin-bottom:0}.md-annotation{outline:none;white-space:normal}[dir=rtl] .md-annotation{direction:rtl}.md-annotation:not([hidden]){display:inline-block;line-height:1.325}.md-annotation:focus-within>*{z-index:2}.md-annotation__inner{font-family:var(--md-text-font-family);top:calc(var(--md-tooltip-y) + 1.2ch)}:not(:focus-within)>.md-annotation__inner{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.md-annotation__index{color:#fff;cursor:pointer;margin:0 1ch;position:relative;transition:z-index .25s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:0}.md-annotation__index:after{-webkit-animation:pulse 2s infinite;animation:pulse 2s infinite;background-color:var(--md-default-fg-color--lighter);border-radius:2ch;content:"";height:2.2ch;left:-.126em;margin:0 -.4ch;padding:0 .4ch;position:absolute;transition:color .25s,background-color .25s;width:calc(100% + 1.2ch);width:max(2.2ch,100% + 1.2ch);z-index:-1}@media (prefers-reduced-motion){.md-annotation__index:after{-webkit-animation:none;animation:none}}:-webkit-any(:focus-within,:hover)>.md-annotation__index:after{background-color:var(--md-accent-fg-color)}:-moz-any(:focus-within,:hover)>.md-annotation__index:after{background-color:var(--md-accent-fg-color)}:is(:focus-within,:hover)>.md-annotation__index:after{background-color:var(--md-accent-fg-color)}:focus-within>.md-annotation__index:after{-webkit-animation:none;animation:none;transition:color .25s,background-color .25s}.md-annotation__index [data-md-annotation-id]{display:inline-block;line-height:90%}.md-annotation__index [data-md-annotation-id]:before{content:attr(data-md-annotation-id);display:inline-block;padding-bottom:.1em;transform:scale(1.15);transition:transform .4s cubic-bezier(.1,.7,.1,1);vertical-align:.065em}@media not print{.md-annotation__index [data-md-annotation-id]:before{content:"+"}:focus-within>.md-annotation__index [data-md-annotation-id]:before{transform:scale(1.25) rotate(45deg)}}:-webkit-any(:focus-within,:hover)>.md-annotation__index{color:var(--md-accent-bg-color)}:-moz-any(:focus-within,:hover)>.md-annotation__index{color:var(--md-accent-bg-color)}:is(:focus-within,:hover)>.md-annotation__index{color:var(--md-accent-bg-color)}:focus-within>.md-annotation__index{-webkit-animation:none;animation:none;transition:none}[dir=ltr] .md-top{margin-left:50%}[dir=rtl] .md-top{margin-right:50%}.md-top{background-color:var(--md-default-bg-color);border-radius:1.6rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color--light);font-size:.7rem;outline:none;padding:.4rem .8rem;position:fixed;top:3.2rem;transform:translate(-50%);transition:color 125ms,background-color 125ms,transform 125ms cubic-bezier(.4,0,.2,1),opacity 125ms;z-index:2}@media print{.md-top{display:none}}[dir=rtl] .md-top{transform:translate(50%)}.md-top[data-md-state=hidden]{opacity:0;pointer-events:none;transform:translate(-50%,.2rem);transition-duration:0ms}[dir=rtl] .md-top[data-md-state=hidden]{transform:translate(50%,.2rem)}.md-top:-webkit-any(:focus,:hover){background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-top:-moz-any(:focus,:hover){background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-top:is(:focus,:hover){background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-top svg{display:inline-block;vertical-align:-.5em}@-webkit-keyframes hoverfix{0%{pointer-events:none}}@keyframes hoverfix{0%{pointer-events:none}}:root{--md-version-icon:url('data:image/svg+xml;charset=utf-8,')}.md-version{flex-shrink:0;font-size:.8rem;height:2.4rem}[dir=ltr] .md-version__current{margin-left:1.4rem;margin-right:.4rem}[dir=rtl] .md-version__current{margin-left:.4rem;margin-right:1.4rem}.md-version__current{color:inherit;cursor:pointer;outline:none;position:relative;top:.05rem}[dir=ltr] .md-version__current:after{margin-left:.4rem}[dir=rtl] .md-version__current:after{margin-right:.4rem}.md-version__current:after{background-color:currentcolor;content:"";display:inline-block;height:.6rem;-webkit-mask-image:var(--md-version-icon);mask-image:var(--md-version-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;width:.4rem}.md-version__list{background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);list-style-type:none;margin:.2rem .8rem;max-height:0;opacity:0;overflow:auto;padding:0;position:absolute;-ms-scroll-snap-type:y mandatory;scroll-snap-type:y mandatory;top:.15rem;transition:max-height 0ms .5s,opacity .25s .25s;z-index:3}.md-version:-webkit-any(:focus-within,:hover) .md-version__list{max-height:10rem;opacity:1;-webkit-transition:max-height 0ms,opacity .25s;transition:max-height 0ms,opacity .25s}.md-version:-moz-any(:focus-within,:hover) .md-version__list{max-height:10rem;opacity:1;-moz-transition:max-height 0ms,opacity .25s;transition:max-height 0ms,opacity .25s}.md-version:is(:focus-within,:hover) .md-version__list{max-height:10rem;opacity:1;transition:max-height 0ms,opacity .25s}@media (pointer:coarse){.md-version:hover .md-version__list{-webkit-animation:hoverfix .25s forwards;animation:hoverfix .25s forwards}.md-version:focus-within .md-version__list{-webkit-animation:none;animation:none}}.md-version__item{line-height:1.8rem}[dir=ltr] .md-version__link{padding-left:.6rem;padding-right:1.2rem}[dir=rtl] .md-version__link{padding-left:1.2rem;padding-right:.6rem}.md-version__link{cursor:pointer;display:block;outline:none;scroll-snap-align:start;transition:color .25s,background-color .25s;white-space:nowrap;width:100%}.md-version__link:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-version__link:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-version__link:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-version__link:focus{background-color:var(--md-default-fg-color--lightest)}:root{--md-admonition-icon--note:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--abstract:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--info:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--tip:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--success:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--question:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--warning:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--failure:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--danger:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--bug:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--example:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--quote:url('data:image/svg+xml;charset=utf-8,')}.md-typeset :-webkit-any(.admonition,details){background-color:var(--md-admonition-bg-color);border:0 solid #448aff;border-radius:.1rem;box-shadow:var(--md-shadow-z1);color:var(--md-admonition-fg-color);display:flow-root;font-size:.64rem;margin:1.5625em 0;padding:0 .6rem;page-break-inside:avoid}.md-typeset :-moz-any(.admonition,details){background-color:var(--md-admonition-bg-color);border:0 solid #448aff;border-radius:.1rem;box-shadow:var(--md-shadow-z1);color:var(--md-admonition-fg-color);display:flow-root;font-size:.64rem;margin:1.5625em 0;padding:0 .6rem;page-break-inside:avoid}[dir=ltr] .md-typeset :-webkit-any(.admonition,details){border-left-width:.2rem}[dir=ltr] .md-typeset :-moz-any(.admonition,details){border-left-width:.2rem}[dir=ltr] .md-typeset :is(.admonition,details){border-left-width:.2rem}[dir=rtl] .md-typeset :-webkit-any(.admonition,details){border-right-width:.2rem}[dir=rtl] .md-typeset :-moz-any(.admonition,details){border-right-width:.2rem}[dir=rtl] .md-typeset :is(.admonition,details){border-right-width:.2rem}.md-typeset :is(.admonition,details){background-color:var(--md-admonition-bg-color);border:0 solid #448aff;border-radius:.1rem;box-shadow:var(--md-shadow-z1);color:var(--md-admonition-fg-color);display:flow-root;font-size:.64rem;margin:1.5625em 0;padding:0 .6rem;page-break-inside:avoid}@media print{.md-typeset :-webkit-any(.admonition,details){box-shadow:none}.md-typeset :-moz-any(.admonition,details){box-shadow:none}.md-typeset :is(.admonition,details){box-shadow:none}}.md-typeset :-webkit-any(.admonition,details)>*{box-sizing:border-box}.md-typeset :-moz-any(.admonition,details)>*{box-sizing:border-box}.md-typeset :is(.admonition,details)>*{box-sizing:border-box}.md-typeset :-webkit-any(.admonition,details) :-webkit-any(.admonition,details){margin-bottom:1em;margin-top:1em}.md-typeset :-moz-any(.admonition,details) :-moz-any(.admonition,details){margin-bottom:1em;margin-top:1em}.md-typeset :is(.admonition,details) :is(.admonition,details){margin-bottom:1em;margin-top:1em}.md-typeset :-webkit-any(.admonition,details) .md-typeset__scrollwrap{margin:1em -.6rem}.md-typeset :-moz-any(.admonition,details) .md-typeset__scrollwrap{margin:1em -.6rem}.md-typeset :is(.admonition,details) .md-typeset__scrollwrap{margin:1em -.6rem}.md-typeset :-webkit-any(.admonition,details) .md-typeset__table{padding:0 .6rem}.md-typeset :-moz-any(.admonition,details) .md-typeset__table{padding:0 .6rem}.md-typeset :is(.admonition,details) .md-typeset__table{padding:0 .6rem}.md-typeset :-webkit-any(.admonition,details)>.tabbed-set:only-child{margin-top:0}.md-typeset :-moz-any(.admonition,details)>.tabbed-set:only-child{margin-top:0}.md-typeset :is(.admonition,details)>.tabbed-set:only-child{margin-top:0}html .md-typeset :-webkit-any(.admonition,details)>:last-child{margin-bottom:.6rem}html .md-typeset :-moz-any(.admonition,details)>:last-child{margin-bottom:.6rem}html .md-typeset :is(.admonition,details)>:last-child{margin-bottom:.6rem}.md-typeset :-webkit-any(.admonition-title,summary){background-color:rgba(68,138,255,.1);border:none;font-weight:700;margin-bottom:0;margin-top:0;padding-bottom:.4rem;padding-top:.4rem;position:relative}.md-typeset :-moz-any(.admonition-title,summary){background-color:rgba(68,138,255,.1);border:none;font-weight:700;margin-bottom:0;margin-top:0;padding-bottom:.4rem;padding-top:.4rem;position:relative}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary){margin-left:-.8rem;margin-right:-.6rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary){margin-left:-.8rem;margin-right:-.6rem}[dir=ltr] .md-typeset :is(.admonition-title,summary){margin-left:-.8rem;margin-right:-.6rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary){margin-left:-.6rem;margin-right:-.8rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary){margin-left:-.6rem;margin-right:-.8rem}[dir=rtl] .md-typeset :is(.admonition-title,summary){margin-left:-.6rem;margin-right:-.8rem}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary){padding-left:2.2rem;padding-right:.6rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary){padding-left:2.2rem;padding-right:.6rem}[dir=ltr] .md-typeset :is(.admonition-title,summary){padding-left:2.2rem;padding-right:.6rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary){padding-left:.6rem;padding-right:2.2rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary){padding-left:.6rem;padding-right:2.2rem}[dir=rtl] .md-typeset :is(.admonition-title,summary){padding-left:.6rem;padding-right:2.2rem}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary){border-left-width:.2rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary){border-left-width:.2rem}[dir=ltr] .md-typeset :is(.admonition-title,summary){border-left-width:.2rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary){border-right-width:.2rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary){border-right-width:.2rem}[dir=rtl] .md-typeset :is(.admonition-title,summary){border-right-width:.2rem}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary){border-top-left-radius:.1rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary){border-top-left-radius:.1rem}[dir=ltr] .md-typeset :is(.admonition-title,summary){border-top-left-radius:.1rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary){border-top-right-radius:.1rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary){border-top-right-radius:.1rem}[dir=rtl] .md-typeset :is(.admonition-title,summary){border-top-right-radius:.1rem}.md-typeset :is(.admonition-title,summary){background-color:rgba(68,138,255,.1);border:none;font-weight:700;margin-bottom:0;margin-top:0;padding-bottom:.4rem;padding-top:.4rem;position:relative}html .md-typeset :-webkit-any(.admonition-title,summary):last-child{margin-bottom:0}html .md-typeset :-moz-any(.admonition-title,summary):last-child{margin-bottom:0}html .md-typeset :is(.admonition-title,summary):last-child{margin-bottom:0}.md-typeset :-webkit-any(.admonition-title,summary):before{background-color:#448aff;content:"";height:1rem;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;width:1rem}.md-typeset :-moz-any(.admonition-title,summary):before{background-color:#448aff;content:"";height:1rem;mask-image:var(--md-admonition-icon--note);mask-repeat:no-repeat;mask-size:contain;position:absolute;top:.625em;width:1rem}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary):before{left:.8rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary):before{left:.8rem}[dir=ltr] .md-typeset :is(.admonition-title,summary):before{left:.8rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary):before{right:.8rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary):before{right:.8rem}[dir=rtl] .md-typeset :is(.admonition-title,summary):before{right:.8rem}.md-typeset :is(.admonition-title,summary):before{background-color:#448aff;content:"";height:1rem;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;width:1rem}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.note){border-color:#448aff}.md-typeset :-moz-any(.admonition,details):-moz-any(.note){border-color:#448aff}.md-typeset :is(.admonition,details):is(.note){border-color:#448aff}.md-typeset :-webkit-any(.note)>:-webkit-any(.admonition-title,summary){background-color:rgba(68,138,255,.1)}.md-typeset :-moz-any(.note)>:-moz-any(.admonition-title,summary){background-color:rgba(68,138,255,.1)}.md-typeset :is(.note)>:is(.admonition-title,summary){background-color:rgba(68,138,255,.1)}.md-typeset :-webkit-any(.note)>:-webkit-any(.admonition-title,summary):before{background-color:#448aff;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.note)>:-moz-any(.admonition-title,summary):before{background-color:#448aff;mask-image:var(--md-admonition-icon--note);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.note)>:is(.admonition-title,summary):before{background-color:#448aff;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.abstract,.summary,.tldr){border-color:#00b0ff}.md-typeset :-moz-any(.admonition,details):-moz-any(.abstract,.summary,.tldr){border-color:#00b0ff}.md-typeset :is(.admonition,details):is(.abstract,.summary,.tldr){border-color:#00b0ff}.md-typeset :-webkit-any(.abstract,.summary,.tldr)>:-webkit-any(.admonition-title,summary){background-color:rgba(0,176,255,.1)}.md-typeset :-moz-any(.abstract,.summary,.tldr)>:-moz-any(.admonition-title,summary){background-color:rgba(0,176,255,.1)}.md-typeset :is(.abstract,.summary,.tldr)>:is(.admonition-title,summary){background-color:rgba(0,176,255,.1)}.md-typeset :-webkit-any(.abstract,.summary,.tldr)>:-webkit-any(.admonition-title,summary):before{background-color:#00b0ff;-webkit-mask-image:var(--md-admonition-icon--abstract);mask-image:var(--md-admonition-icon--abstract);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.abstract,.summary,.tldr)>:-moz-any(.admonition-title,summary):before{background-color:#00b0ff;mask-image:var(--md-admonition-icon--abstract);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.abstract,.summary,.tldr)>:is(.admonition-title,summary):before{background-color:#00b0ff;-webkit-mask-image:var(--md-admonition-icon--abstract);mask-image:var(--md-admonition-icon--abstract);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.info,.todo){border-color:#00b8d4}.md-typeset :-moz-any(.admonition,details):-moz-any(.info,.todo){border-color:#00b8d4}.md-typeset :is(.admonition,details):is(.info,.todo){border-color:#00b8d4}.md-typeset :-webkit-any(.info,.todo)>:-webkit-any(.admonition-title,summary){background-color:rgba(0,184,212,.1)}.md-typeset :-moz-any(.info,.todo)>:-moz-any(.admonition-title,summary){background-color:rgba(0,184,212,.1)}.md-typeset :is(.info,.todo)>:is(.admonition-title,summary){background-color:rgba(0,184,212,.1)}.md-typeset :-webkit-any(.info,.todo)>:-webkit-any(.admonition-title,summary):before{background-color:#00b8d4;-webkit-mask-image:var(--md-admonition-icon--info);mask-image:var(--md-admonition-icon--info);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.info,.todo)>:-moz-any(.admonition-title,summary):before{background-color:#00b8d4;mask-image:var(--md-admonition-icon--info);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.info,.todo)>:is(.admonition-title,summary):before{background-color:#00b8d4;-webkit-mask-image:var(--md-admonition-icon--info);mask-image:var(--md-admonition-icon--info);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.tip,.hint,.important){border-color:#00bfa5}.md-typeset :-moz-any(.admonition,details):-moz-any(.tip,.hint,.important){border-color:#00bfa5}.md-typeset :is(.admonition,details):is(.tip,.hint,.important){border-color:#00bfa5}.md-typeset :-webkit-any(.tip,.hint,.important)>:-webkit-any(.admonition-title,summary){background-color:rgba(0,191,165,.1)}.md-typeset :-moz-any(.tip,.hint,.important)>:-moz-any(.admonition-title,summary){background-color:rgba(0,191,165,.1)}.md-typeset :is(.tip,.hint,.important)>:is(.admonition-title,summary){background-color:rgba(0,191,165,.1)}.md-typeset :-webkit-any(.tip,.hint,.important)>:-webkit-any(.admonition-title,summary):before{background-color:#00bfa5;-webkit-mask-image:var(--md-admonition-icon--tip);mask-image:var(--md-admonition-icon--tip);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.tip,.hint,.important)>:-moz-any(.admonition-title,summary):before{background-color:#00bfa5;mask-image:var(--md-admonition-icon--tip);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.tip,.hint,.important)>:is(.admonition-title,summary):before{background-color:#00bfa5;-webkit-mask-image:var(--md-admonition-icon--tip);mask-image:var(--md-admonition-icon--tip);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.success,.check,.done){border-color:#00c853}.md-typeset :-moz-any(.admonition,details):-moz-any(.success,.check,.done){border-color:#00c853}.md-typeset :is(.admonition,details):is(.success,.check,.done){border-color:#00c853}.md-typeset :-webkit-any(.success,.check,.done)>:-webkit-any(.admonition-title,summary){background-color:rgba(0,200,83,.1)}.md-typeset :-moz-any(.success,.check,.done)>:-moz-any(.admonition-title,summary){background-color:rgba(0,200,83,.1)}.md-typeset :is(.success,.check,.done)>:is(.admonition-title,summary){background-color:rgba(0,200,83,.1)}.md-typeset :-webkit-any(.success,.check,.done)>:-webkit-any(.admonition-title,summary):before{background-color:#00c853;-webkit-mask-image:var(--md-admonition-icon--success);mask-image:var(--md-admonition-icon--success);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.success,.check,.done)>:-moz-any(.admonition-title,summary):before{background-color:#00c853;mask-image:var(--md-admonition-icon--success);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.success,.check,.done)>:is(.admonition-title,summary):before{background-color:#00c853;-webkit-mask-image:var(--md-admonition-icon--success);mask-image:var(--md-admonition-icon--success);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.question,.help,.faq){border-color:#64dd17}.md-typeset :-moz-any(.admonition,details):-moz-any(.question,.help,.faq){border-color:#64dd17}.md-typeset :is(.admonition,details):is(.question,.help,.faq){border-color:#64dd17}.md-typeset :-webkit-any(.question,.help,.faq)>:-webkit-any(.admonition-title,summary){background-color:rgba(100,221,23,.1)}.md-typeset :-moz-any(.question,.help,.faq)>:-moz-any(.admonition-title,summary){background-color:rgba(100,221,23,.1)}.md-typeset :is(.question,.help,.faq)>:is(.admonition-title,summary){background-color:rgba(100,221,23,.1)}.md-typeset :-webkit-any(.question,.help,.faq)>:-webkit-any(.admonition-title,summary):before{background-color:#64dd17;-webkit-mask-image:var(--md-admonition-icon--question);mask-image:var(--md-admonition-icon--question);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.question,.help,.faq)>:-moz-any(.admonition-title,summary):before{background-color:#64dd17;mask-image:var(--md-admonition-icon--question);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.question,.help,.faq)>:is(.admonition-title,summary):before{background-color:#64dd17;-webkit-mask-image:var(--md-admonition-icon--question);mask-image:var(--md-admonition-icon--question);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.warning,.caution,.attention){border-color:#ff9100}.md-typeset :-moz-any(.admonition,details):-moz-any(.warning,.caution,.attention){border-color:#ff9100}.md-typeset :is(.admonition,details):is(.warning,.caution,.attention){border-color:#ff9100}.md-typeset :-webkit-any(.warning,.caution,.attention)>:-webkit-any(.admonition-title,summary){background-color:rgba(255,145,0,.1)}.md-typeset :-moz-any(.warning,.caution,.attention)>:-moz-any(.admonition-title,summary){background-color:rgba(255,145,0,.1)}.md-typeset :is(.warning,.caution,.attention)>:is(.admonition-title,summary){background-color:rgba(255,145,0,.1)}.md-typeset :-webkit-any(.warning,.caution,.attention)>:-webkit-any(.admonition-title,summary):before{background-color:#ff9100;-webkit-mask-image:var(--md-admonition-icon--warning);mask-image:var(--md-admonition-icon--warning);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.warning,.caution,.attention)>:-moz-any(.admonition-title,summary):before{background-color:#ff9100;mask-image:var(--md-admonition-icon--warning);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.warning,.caution,.attention)>:is(.admonition-title,summary):before{background-color:#ff9100;-webkit-mask-image:var(--md-admonition-icon--warning);mask-image:var(--md-admonition-icon--warning);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.failure,.fail,.missing){border-color:#ff5252}.md-typeset :-moz-any(.admonition,details):-moz-any(.failure,.fail,.missing){border-color:#ff5252}.md-typeset :is(.admonition,details):is(.failure,.fail,.missing){border-color:#ff5252}.md-typeset :-webkit-any(.failure,.fail,.missing)>:-webkit-any(.admonition-title,summary){background-color:rgba(255,82,82,.1)}.md-typeset :-moz-any(.failure,.fail,.missing)>:-moz-any(.admonition-title,summary){background-color:rgba(255,82,82,.1)}.md-typeset :is(.failure,.fail,.missing)>:is(.admonition-title,summary){background-color:rgba(255,82,82,.1)}.md-typeset :-webkit-any(.failure,.fail,.missing)>:-webkit-any(.admonition-title,summary):before{background-color:#ff5252;-webkit-mask-image:var(--md-admonition-icon--failure);mask-image:var(--md-admonition-icon--failure);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.failure,.fail,.missing)>:-moz-any(.admonition-title,summary):before{background-color:#ff5252;mask-image:var(--md-admonition-icon--failure);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.failure,.fail,.missing)>:is(.admonition-title,summary):before{background-color:#ff5252;-webkit-mask-image:var(--md-admonition-icon--failure);mask-image:var(--md-admonition-icon--failure);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.danger,.error){border-color:#ff1744}.md-typeset :-moz-any(.admonition,details):-moz-any(.danger,.error){border-color:#ff1744}.md-typeset :is(.admonition,details):is(.danger,.error){border-color:#ff1744}.md-typeset :-webkit-any(.danger,.error)>:-webkit-any(.admonition-title,summary){background-color:rgba(255,23,68,.1)}.md-typeset :-moz-any(.danger,.error)>:-moz-any(.admonition-title,summary){background-color:rgba(255,23,68,.1)}.md-typeset :is(.danger,.error)>:is(.admonition-title,summary){background-color:rgba(255,23,68,.1)}.md-typeset :-webkit-any(.danger,.error)>:-webkit-any(.admonition-title,summary):before{background-color:#ff1744;-webkit-mask-image:var(--md-admonition-icon--danger);mask-image:var(--md-admonition-icon--danger);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.danger,.error)>:-moz-any(.admonition-title,summary):before{background-color:#ff1744;mask-image:var(--md-admonition-icon--danger);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.danger,.error)>:is(.admonition-title,summary):before{background-color:#ff1744;-webkit-mask-image:var(--md-admonition-icon--danger);mask-image:var(--md-admonition-icon--danger);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.bug){border-color:#f50057}.md-typeset :-moz-any(.admonition,details):-moz-any(.bug){border-color:#f50057}.md-typeset :is(.admonition,details):is(.bug){border-color:#f50057}.md-typeset :-webkit-any(.bug)>:-webkit-any(.admonition-title,summary){background-color:rgba(245,0,87,.1)}.md-typeset :-moz-any(.bug)>:-moz-any(.admonition-title,summary){background-color:rgba(245,0,87,.1)}.md-typeset :is(.bug)>:is(.admonition-title,summary){background-color:rgba(245,0,87,.1)}.md-typeset :-webkit-any(.bug)>:-webkit-any(.admonition-title,summary):before{background-color:#f50057;-webkit-mask-image:var(--md-admonition-icon--bug);mask-image:var(--md-admonition-icon--bug);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.bug)>:-moz-any(.admonition-title,summary):before{background-color:#f50057;mask-image:var(--md-admonition-icon--bug);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.bug)>:is(.admonition-title,summary):before{background-color:#f50057;-webkit-mask-image:var(--md-admonition-icon--bug);mask-image:var(--md-admonition-icon--bug);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.example){border-color:#7c4dff}.md-typeset :-moz-any(.admonition,details):-moz-any(.example){border-color:#7c4dff}.md-typeset :is(.admonition,details):is(.example){border-color:#7c4dff}.md-typeset :-webkit-any(.example)>:-webkit-any(.admonition-title,summary){background-color:rgba(124,77,255,.1)}.md-typeset :-moz-any(.example)>:-moz-any(.admonition-title,summary){background-color:rgba(124,77,255,.1)}.md-typeset :is(.example)>:is(.admonition-title,summary){background-color:rgba(124,77,255,.1)}.md-typeset :-webkit-any(.example)>:-webkit-any(.admonition-title,summary):before{background-color:#7c4dff;-webkit-mask-image:var(--md-admonition-icon--example);mask-image:var(--md-admonition-icon--example);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.example)>:-moz-any(.admonition-title,summary):before{background-color:#7c4dff;mask-image:var(--md-admonition-icon--example);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.example)>:is(.admonition-title,summary):before{background-color:#7c4dff;-webkit-mask-image:var(--md-admonition-icon--example);mask-image:var(--md-admonition-icon--example);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.quote,.cite){border-color:#9e9e9e}.md-typeset :-moz-any(.admonition,details):-moz-any(.quote,.cite){border-color:#9e9e9e}.md-typeset :is(.admonition,details):is(.quote,.cite){border-color:#9e9e9e}.md-typeset :-webkit-any(.quote,.cite)>:-webkit-any(.admonition-title,summary){background-color:hsla(0,0%,62%,.1)}.md-typeset :-moz-any(.quote,.cite)>:-moz-any(.admonition-title,summary){background-color:hsla(0,0%,62%,.1)}.md-typeset :is(.quote,.cite)>:is(.admonition-title,summary){background-color:hsla(0,0%,62%,.1)}.md-typeset :-webkit-any(.quote,.cite)>:-webkit-any(.admonition-title,summary):before{background-color:#9e9e9e;-webkit-mask-image:var(--md-admonition-icon--quote);mask-image:var(--md-admonition-icon--quote);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset :-moz-any(.quote,.cite)>:-moz-any(.admonition-title,summary):before{background-color:#9e9e9e;mask-image:var(--md-admonition-icon--quote);mask-repeat:no-repeat;mask-size:contain}.md-typeset :is(.quote,.cite)>:is(.admonition-title,summary):before{background-color:#9e9e9e;-webkit-mask-image:var(--md-admonition-icon--quote);mask-image:var(--md-admonition-icon--quote);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}:root{--md-footnotes-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .footnote{color:var(--md-default-fg-color--light);font-size:.64rem}[dir=ltr] .md-typeset .footnote>ol{margin-left:0}[dir=rtl] .md-typeset .footnote>ol{margin-right:0}.md-typeset .footnote>ol>li{transition:color 125ms}.md-typeset .footnote>ol>li:target{color:var(--md-default-fg-color)}.md-typeset .footnote>ol>li:focus-within .footnote-backref{opacity:1;transform:translateX(0);transition:none}.md-typeset .footnote>ol>li:-webkit-any(:hover,:target) .footnote-backref{opacity:1;transform:translateX(0)}.md-typeset .footnote>ol>li:-moz-any(:hover,:target) .footnote-backref{opacity:1;transform:translateX(0)}.md-typeset .footnote>ol>li:is(:hover,:target) .footnote-backref{opacity:1;transform:translateX(0)}.md-typeset .footnote>ol>li>:first-child{margin-top:0}.md-typeset .footnote-ref{font-size:.75em;font-weight:700}html .md-typeset .footnote-ref{outline-offset:.1rem}.md-typeset [id^="fnref:"]:target>.footnote-ref{outline:auto}.md-typeset .footnote-backref{color:var(--md-typeset-a-color);display:inline-block;font-size:0;opacity:0;transform:translateX(.25rem);transition:color .25s,transform .25s .25s,opacity 125ms .25s;vertical-align:text-bottom}@media print{.md-typeset .footnote-backref{color:var(--md-typeset-a-color);opacity:1;transform:translateX(0)}}[dir=rtl] .md-typeset .footnote-backref{transform:translateX(-.25rem)}.md-typeset .footnote-backref:hover{color:var(--md-accent-fg-color)}.md-typeset .footnote-backref:before{background-color:currentcolor;content:"";display:inline-block;height:.8rem;-webkit-mask-image:var(--md-footnotes-icon);mask-image:var(--md-footnotes-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:.8rem}[dir=rtl] .md-typeset .footnote-backref:before svg{transform:scaleX(-1)}[dir=ltr] .md-typeset .headerlink{margin-left:.5rem}[dir=rtl] .md-typeset .headerlink{margin-right:.5rem}.md-typeset .headerlink{color:var(--md-default-fg-color--lighter);display:inline-block;opacity:0;transition:color .25s,opacity 125ms}@media print{.md-typeset .headerlink{display:none}}.md-typeset .headerlink:focus,.md-typeset :-webkit-any(:hover,:target)>.headerlink{opacity:1;-webkit-transition:color .25s,opacity 125ms;transition:color .25s,opacity 125ms}.md-typeset .headerlink:focus,.md-typeset :-moz-any(:hover,:target)>.headerlink{opacity:1;-moz-transition:color .25s,opacity 125ms;transition:color .25s,opacity 125ms}.md-typeset .headerlink:focus,.md-typeset :is(:hover,:target)>.headerlink{opacity:1;transition:color .25s,opacity 125ms}.md-typeset .headerlink:-webkit-any(:focus,:hover),.md-typeset :target>.headerlink{color:var(--md-accent-fg-color)}.md-typeset .headerlink:-moz-any(:focus,:hover),.md-typeset :target>.headerlink{color:var(--md-accent-fg-color)}.md-typeset .headerlink:is(:focus,:hover),.md-typeset :target>.headerlink{color:var(--md-accent-fg-color)}.md-typeset :target{--md-scroll-margin:3.6rem;--md-scroll-offset:0rem;scroll-margin-top:calc(var(--md-scroll-margin) - var(--md-scroll-offset))}@media screen and (min-width:76.25em){.md-header--lifted~.md-container .md-typeset :target{--md-scroll-margin:6rem}}.md-typeset :-webkit-any(h1,h2,h3):target{--md-scroll-offset:0.2rem}.md-typeset :-moz-any(h1,h2,h3):target{--md-scroll-offset:0.2rem}.md-typeset :is(h1,h2,h3):target{--md-scroll-offset:0.2rem}.md-typeset h4:target{--md-scroll-offset:0.15rem}.md-typeset div.arithmatex{overflow:auto}@media screen and (max-width:44.9375em){.md-typeset div.arithmatex{margin:0 -.8rem}}.md-typeset div.arithmatex>*{margin-left:auto!important;margin-right:auto!important;padding:0 .8rem;touch-action:auto;width:-webkit-min-content;width:-moz-min-content;width:min-content}.md-typeset div.arithmatex>* mjx-container{margin:0!important}.md-typeset :-webkit-any(del,ins,.comment).critic{-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset :-moz-any(del,ins,.comment).critic{box-decoration-break:clone}.md-typeset :is(del,ins,.comment).critic{-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset del.critic{background-color:var(--md-typeset-del-color)}.md-typeset ins.critic{background-color:var(--md-typeset-ins-color)}.md-typeset .critic.comment{color:var(--md-code-hl-comment-color)}.md-typeset .critic.comment:before{content:"/* "}.md-typeset .critic.comment:after{content:" */"}.md-typeset .critic.block{box-shadow:none;display:block;margin:1em 0;overflow:auto;padding-left:.8rem;padding-right:.8rem}.md-typeset .critic.block>:first-child{margin-top:.5em}.md-typeset .critic.block>:last-child{margin-bottom:.5em}:root{--md-details-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset details{display:flow-root;overflow:visible;padding-top:0}.md-typeset details[open]>summary:after{transform:rotate(90deg)}.md-typeset details:not([open]){box-shadow:none;padding-bottom:0}.md-typeset details:not([open])>summary{border-radius:.1rem}[dir=ltr] .md-typeset summary{padding-right:1.8rem}[dir=rtl] .md-typeset summary{padding-left:1.8rem}[dir=ltr] .md-typeset summary{border-top-left-radius:.1rem}[dir=ltr] .md-typeset summary,[dir=rtl] .md-typeset summary{border-top-right-radius:.1rem}[dir=rtl] .md-typeset summary{border-top-left-radius:.1rem}.md-typeset summary{cursor:pointer;display:block;min-height:1rem}.md-typeset summary.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-typeset summary:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}[dir=ltr] .md-typeset summary:after{right:.4rem}[dir=rtl] .md-typeset summary:after{left:.4rem}.md-typeset summary:after{background-color:currentcolor;content:"";height:1rem;-webkit-mask-image:var(--md-details-icon);mask-image:var(--md-details-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;transform:rotate(0deg);transition:transform .25s;width:1rem}[dir=rtl] .md-typeset summary:after{transform:rotate(180deg)}.md-typeset summary::marker{display:none}.md-typeset summary::-webkit-details-marker{display:none}.md-typeset :-webkit-any(.emojione,.twemoji,.gemoji){display:inline-flex;height:1.125em;vertical-align:text-top}.md-typeset :-moz-any(.emojione,.twemoji,.gemoji){display:inline-flex;height:1.125em;vertical-align:text-top}.md-typeset :is(.emojione,.twemoji,.gemoji){display:inline-flex;height:1.125em;vertical-align:text-top}.md-typeset :-webkit-any(.emojione,.twemoji,.gemoji) svg{fill:currentcolor;max-height:100%;width:1.125em}.md-typeset :-moz-any(.emojione,.twemoji,.gemoji) svg{fill:currentcolor;max-height:100%;width:1.125em}.md-typeset :is(.emojione,.twemoji,.gemoji) svg{fill:currentcolor;max-height:100%;width:1.125em}.highlight :-webkit-any(.o,.ow){color:var(--md-code-hl-operator-color)}.highlight :-moz-any(.o,.ow){color:var(--md-code-hl-operator-color)}.highlight :is(.o,.ow){color:var(--md-code-hl-operator-color)}.highlight .p{color:var(--md-code-hl-punctuation-color)}.highlight :-webkit-any(.cpf,.l,.s,.sb,.sc,.s2,.si,.s1,.ss){color:var(--md-code-hl-string-color)}.highlight :-moz-any(.cpf,.l,.s,.sb,.sc,.s2,.si,.s1,.ss){color:var(--md-code-hl-string-color)}.highlight :is(.cpf,.l,.s,.sb,.sc,.s2,.si,.s1,.ss){color:var(--md-code-hl-string-color)}.highlight :-webkit-any(.cp,.se,.sh,.sr,.sx){color:var(--md-code-hl-special-color)}.highlight :-moz-any(.cp,.se,.sh,.sr,.sx){color:var(--md-code-hl-special-color)}.highlight :is(.cp,.se,.sh,.sr,.sx){color:var(--md-code-hl-special-color)}.highlight :-webkit-any(.m,.mb,.mf,.mh,.mi,.il,.mo){color:var(--md-code-hl-number-color)}.highlight :-moz-any(.m,.mb,.mf,.mh,.mi,.il,.mo){color:var(--md-code-hl-number-color)}.highlight :is(.m,.mb,.mf,.mh,.mi,.il,.mo){color:var(--md-code-hl-number-color)}.highlight :-webkit-any(.k,.kd,.kn,.kp,.kr,.kt){color:var(--md-code-hl-keyword-color)}.highlight :-moz-any(.k,.kd,.kn,.kp,.kr,.kt){color:var(--md-code-hl-keyword-color)}.highlight :is(.k,.kd,.kn,.kp,.kr,.kt){color:var(--md-code-hl-keyword-color)}.highlight :-webkit-any(.kc,.n){color:var(--md-code-hl-name-color)}.highlight :-moz-any(.kc,.n){color:var(--md-code-hl-name-color)}.highlight :is(.kc,.n){color:var(--md-code-hl-name-color)}.highlight :-webkit-any(.no,.nb,.bp){color:var(--md-code-hl-constant-color)}.highlight :-moz-any(.no,.nb,.bp){color:var(--md-code-hl-constant-color)}.highlight :is(.no,.nb,.bp){color:var(--md-code-hl-constant-color)}.highlight :-webkit-any(.nc,.ne,.nf,.nn){color:var(--md-code-hl-function-color)}.highlight :-moz-any(.nc,.ne,.nf,.nn){color:var(--md-code-hl-function-color)}.highlight :is(.nc,.ne,.nf,.nn){color:var(--md-code-hl-function-color)}.highlight :-webkit-any(.nd,.ni,.nl,.nt){color:var(--md-code-hl-keyword-color)}.highlight :-moz-any(.nd,.ni,.nl,.nt){color:var(--md-code-hl-keyword-color)}.highlight :is(.nd,.ni,.nl,.nt){color:var(--md-code-hl-keyword-color)}.highlight :-webkit-any(.c,.cm,.c1,.ch,.cs,.sd){color:var(--md-code-hl-comment-color)}.highlight :-moz-any(.c,.cm,.c1,.ch,.cs,.sd){color:var(--md-code-hl-comment-color)}.highlight :is(.c,.cm,.c1,.ch,.cs,.sd){color:var(--md-code-hl-comment-color)}.highlight :-webkit-any(.na,.nv,.vc,.vg,.vi){color:var(--md-code-hl-variable-color)}.highlight :-moz-any(.na,.nv,.vc,.vg,.vi){color:var(--md-code-hl-variable-color)}.highlight :is(.na,.nv,.vc,.vg,.vi){color:var(--md-code-hl-variable-color)}.highlight :-webkit-any(.ge,.gr,.gh,.go,.gp,.gs,.gu,.gt){color:var(--md-code-hl-generic-color)}.highlight :-moz-any(.ge,.gr,.gh,.go,.gp,.gs,.gu,.gt){color:var(--md-code-hl-generic-color)}.highlight :is(.ge,.gr,.gh,.go,.gp,.gs,.gu,.gt){color:var(--md-code-hl-generic-color)}.highlight :-webkit-any(.gd,.gi){border-radius:.1rem;margin:0 -.125em;padding:0 .125em}.highlight :-moz-any(.gd,.gi){border-radius:.1rem;margin:0 -.125em;padding:0 .125em}.highlight :is(.gd,.gi){border-radius:.1rem;margin:0 -.125em;padding:0 .125em}.highlight .gd{background-color:var(--md-typeset-del-color)}.highlight .gi{background-color:var(--md-typeset-ins-color)}.highlight .hll{background-color:var(--md-code-hl-color);display:block;margin:0 -1.1764705882em;padding:0 1.1764705882em}.highlight span.filename{background-color:var(--md-code-bg-color);border-bottom:.05rem solid var(--md-default-fg-color--lightest);border-top-left-radius:.1rem;border-top-right-radius:.1rem;display:flow-root;font-size:.85em;font-weight:700;margin-top:1em;padding:.6617647059em 1.1764705882em;position:relative}.highlight span.filename+pre{margin-top:0}.highlight span.filename+pre>code{border-top-left-radius:0;border-top-right-radius:0}.highlight [data-linenos]:before{background-color:var(--md-code-bg-color);box-shadow:-.05rem 0 var(--md-default-fg-color--lightest) inset;color:var(--md-default-fg-color--light);content:attr(data-linenos);float:left;left:-1.1764705882em;margin-left:-1.1764705882em;margin-right:1.1764705882em;padding-left:1.1764705882em;position:-webkit-sticky;position:sticky;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:3}.highlight code a[id]{position:absolute;visibility:hidden}.highlight code[data-md-copying] .hll{display:contents}.highlight code[data-md-copying] .md-annotation{display:none}.highlighttable{display:flow-root}.highlighttable :-webkit-any(tbody,td){display:block;padding:0}.highlighttable :-moz-any(tbody,td){display:block;padding:0}.highlighttable :is(tbody,td){display:block;padding:0}.highlighttable tr{display:flex}.highlighttable pre{margin:0}.highlighttable th.filename{flex-grow:1;padding:0;text-align:left}.highlighttable th.filename span.filename{margin-top:0}.highlighttable .linenos{background-color:var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-top-left-radius:.1rem;font-size:.85em;padding:.7720588235em 0 .7720588235em 1.1764705882em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.highlighttable .linenodiv{box-shadow:-.05rem 0 var(--md-default-fg-color--lightest) inset;padding-right:.5882352941em}.highlighttable .linenodiv pre{color:var(--md-default-fg-color--light);text-align:right}.highlighttable .code{flex:1;min-width:0}.linenodiv a{color:inherit}.md-typeset .highlighttable{direction:ltr;margin:1em 0}.md-typeset .highlighttable code{border-bottom-left-radius:0;border-top-left-radius:0}.md-typeset :-webkit-any(.highlight,.highlighttable)+.result{border:.05rem solid var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-bottom-right-radius:.1rem;border-top-width:.1rem;margin-top:-1.125em;overflow:visible;padding:0 1em}.md-typeset :-moz-any(.highlight,.highlighttable)+.result{border:.05rem solid var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-bottom-right-radius:.1rem;border-top-width:.1rem;margin-top:-1.125em;overflow:visible;padding:0 1em}.md-typeset :is(.highlight,.highlighttable)+.result{border:.05rem solid var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-bottom-right-radius:.1rem;border-top-width:.1rem;margin-top:-1.125em;overflow:visible;padding:0 1em}.md-typeset :-webkit-any(.highlight,.highlighttable)+.result:after{clear:both;content:"";display:block}.md-typeset :-moz-any(.highlight,.highlighttable)+.result:after{clear:both;content:"";display:block}.md-typeset :is(.highlight,.highlighttable)+.result:after{clear:both;content:"";display:block}@media screen and (max-width:44.9375em){.md-content__inner>.highlight{margin:1em -.8rem}.md-content__inner>.highlight .hll{margin:0 -.8rem;padding:0 .8rem}.md-content__inner>.highlight code{border-radius:0}.md-content__inner>.highlight+.result{border-left-width:0;border-radius:0;border-right-width:0;margin-left:-.8rem;margin-right:-.8rem}.md-content__inner>.highlighttable{border-radius:0;margin:1em -.8rem}.md-content__inner>.highlighttable .hll{margin:0 -.8rem;padding:0 .8rem}}.md-typeset .keys kbd:-webkit-any(:before,:after){-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;color:inherit;margin:0;position:relative}.md-typeset .keys kbd:-moz-any(:before,:after){-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;color:inherit;margin:0;position:relative}.md-typeset .keys kbd:is(:before,:after){-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;color:inherit;margin:0;position:relative}.md-typeset .keys span{color:var(--md-default-fg-color--light);padding:0 .2em}.md-typeset .keys .key-alt:before,.md-typeset .keys .key-left-alt:before,.md-typeset .keys .key-right-alt:before{content:"⎇";padding-right:.4em}.md-typeset .keys .key-command:before,.md-typeset .keys .key-left-command:before,.md-typeset .keys .key-right-command:before{content:"⌘";padding-right:.4em}.md-typeset .keys .key-control:before,.md-typeset .keys .key-left-control:before,.md-typeset .keys .key-right-control:before{content:"⌃";padding-right:.4em}.md-typeset .keys .key-left-meta:before,.md-typeset .keys .key-meta:before,.md-typeset .keys .key-right-meta:before{content:"◆";padding-right:.4em}.md-typeset .keys .key-left-option:before,.md-typeset .keys .key-option:before,.md-typeset .keys .key-right-option:before{content:"⌥";padding-right:.4em}.md-typeset .keys .key-left-shift:before,.md-typeset .keys .key-right-shift:before,.md-typeset .keys .key-shift:before{content:"⇧";padding-right:.4em}.md-typeset .keys .key-left-super:before,.md-typeset .keys .key-right-super:before,.md-typeset .keys .key-super:before{content:"❖";padding-right:.4em}.md-typeset .keys .key-left-windows:before,.md-typeset .keys .key-right-windows:before,.md-typeset .keys .key-windows:before{content:"⊞";padding-right:.4em}.md-typeset .keys .key-arrow-down:before{content:"↓";padding-right:.4em}.md-typeset .keys .key-arrow-left:before{content:"←";padding-right:.4em}.md-typeset .keys .key-arrow-right:before{content:"→";padding-right:.4em}.md-typeset .keys .key-arrow-up:before{content:"↑";padding-right:.4em}.md-typeset .keys .key-backspace:before{content:"⌫";padding-right:.4em}.md-typeset .keys .key-backtab:before{content:"⇤";padding-right:.4em}.md-typeset .keys .key-caps-lock:before{content:"⇪";padding-right:.4em}.md-typeset .keys .key-clear:before{content:"⌧";padding-right:.4em}.md-typeset .keys .key-context-menu:before{content:"☰";padding-right:.4em}.md-typeset .keys .key-delete:before{content:"⌦";padding-right:.4em}.md-typeset .keys .key-eject:before{content:"⏏";padding-right:.4em}.md-typeset .keys .key-end:before{content:"⤓";padding-right:.4em}.md-typeset .keys .key-escape:before{content:"⎋";padding-right:.4em}.md-typeset .keys .key-home:before{content:"⤒";padding-right:.4em}.md-typeset .keys .key-insert:before{content:"⎀";padding-right:.4em}.md-typeset .keys .key-page-down:before{content:"⇟";padding-right:.4em}.md-typeset .keys .key-page-up:before{content:"⇞";padding-right:.4em}.md-typeset .keys .key-print-screen:before{content:"⎙";padding-right:.4em}.md-typeset .keys .key-tab:after{content:"⇥";padding-left:.4em}.md-typeset .keys .key-num-enter:after{content:"⌤";padding-left:.4em}.md-typeset .keys .key-enter:after{content:"⏎";padding-left:.4em}.md-typeset .tabbed-set{border-radius:.1rem;display:flex;flex-flow:column wrap;margin:1em 0;position:relative}.md-typeset .tabbed-set>input{height:0;opacity:0;position:absolute;width:0}.md-typeset .tabbed-set>input:target{--md-scroll-offset:0.625em}.md-typeset .tabbed-labels{-ms-overflow-style:none;box-shadow:0 -.05rem var(--md-default-fg-color--lightest) inset;display:flex;max-width:100%;overflow:auto;-ms-scroll-snap-type:x proximity;scroll-snap-type:x proximity;scrollbar-width:none}@media print{.md-typeset .tabbed-labels{display:contents}}@media screen{.js .md-typeset .tabbed-labels{position:relative}.js .md-typeset .tabbed-labels:before{background:var(--md-accent-fg-color);bottom:0;content:"";display:block;height:2px;left:0;position:absolute;transform:translateX(var(--md-indicator-x));transition:width 225ms,transform .25s;transition-timing-function:cubic-bezier(.4,0,.2,1);width:var(--md-indicator-width)}}.md-typeset .tabbed-labels::-webkit-scrollbar{display:none}.md-typeset .tabbed-labels>label{border-bottom:.1rem solid transparent;border-radius:.1rem .1rem 0 0;color:var(--md-default-fg-color--light);cursor:pointer;flex-shrink:0;font-size:.64rem;font-weight:700;padding:.78125em 1.25em .625em;scroll-snap-align:start;transition:background-color .25s,color .25s;white-space:nowrap;width:auto}@media print{.md-typeset .tabbed-labels>label:first-child{order:1}.md-typeset .tabbed-labels>label:nth-child(2){order:2}.md-typeset .tabbed-labels>label:nth-child(3){order:3}.md-typeset .tabbed-labels>label:nth-child(4){order:4}.md-typeset .tabbed-labels>label:nth-child(5){order:5}.md-typeset .tabbed-labels>label:nth-child(6){order:6}.md-typeset .tabbed-labels>label:nth-child(7){order:7}.md-typeset .tabbed-labels>label:nth-child(8){order:8}.md-typeset .tabbed-labels>label:nth-child(9){order:9}.md-typeset .tabbed-labels>label:nth-child(10){order:10}.md-typeset .tabbed-labels>label:nth-child(11){order:11}.md-typeset .tabbed-labels>label:nth-child(12){order:12}.md-typeset .tabbed-labels>label:nth-child(13){order:13}.md-typeset .tabbed-labels>label:nth-child(14){order:14}.md-typeset .tabbed-labels>label:nth-child(15){order:15}.md-typeset .tabbed-labels>label:nth-child(16){order:16}.md-typeset .tabbed-labels>label:nth-child(17){order:17}.md-typeset .tabbed-labels>label:nth-child(18){order:18}.md-typeset .tabbed-labels>label:nth-child(19){order:19}.md-typeset .tabbed-labels>label:nth-child(20){order:20}}.md-typeset .tabbed-labels>label:hover{color:var(--md-accent-fg-color)}.md-typeset .tabbed-content{width:100%}@media print{.md-typeset .tabbed-content{display:contents}}.md-typeset .tabbed-block{display:none}@media print{.md-typeset .tabbed-block{display:block}.md-typeset .tabbed-block:first-child{order:1}.md-typeset .tabbed-block:nth-child(2){order:2}.md-typeset .tabbed-block:nth-child(3){order:3}.md-typeset .tabbed-block:nth-child(4){order:4}.md-typeset .tabbed-block:nth-child(5){order:5}.md-typeset .tabbed-block:nth-child(6){order:6}.md-typeset .tabbed-block:nth-child(7){order:7}.md-typeset .tabbed-block:nth-child(8){order:8}.md-typeset .tabbed-block:nth-child(9){order:9}.md-typeset .tabbed-block:nth-child(10){order:10}.md-typeset .tabbed-block:nth-child(11){order:11}.md-typeset .tabbed-block:nth-child(12){order:12}.md-typeset .tabbed-block:nth-child(13){order:13}.md-typeset .tabbed-block:nth-child(14){order:14}.md-typeset .tabbed-block:nth-child(15){order:15}.md-typeset .tabbed-block:nth-child(16){order:16}.md-typeset .tabbed-block:nth-child(17){order:17}.md-typeset .tabbed-block:nth-child(18){order:18}.md-typeset .tabbed-block:nth-child(19){order:19}.md-typeset .tabbed-block:nth-child(20){order:20}}.md-typeset .tabbed-block>.highlight:first-child>pre:first-child,.md-typeset .tabbed-block>.highlighttable:first-child,.md-typeset .tabbed-block>pre:first-child{margin:0}[dir=ltr] .md-typeset .tabbed-block>.highlight:first-child>pre:first-child>code,[dir=ltr] .md-typeset .tabbed-block>.highlighttable:first-child>code,[dir=ltr] .md-typeset .tabbed-block>pre:first-child>code{border-top-left-radius:0}[dir=ltr] .md-typeset .tabbed-block>.highlight:first-child>pre:first-child>code,[dir=ltr] .md-typeset .tabbed-block>.highlighttable:first-child>code,[dir=ltr] .md-typeset .tabbed-block>pre:first-child>code,[dir=rtl] .md-typeset .tabbed-block>.highlight:first-child>pre:first-child>code,[dir=rtl] .md-typeset .tabbed-block>.highlighttable:first-child>code,[dir=rtl] .md-typeset .tabbed-block>pre:first-child>code{border-top-right-radius:0}[dir=ltr] .md-typeset .tabbed-block>.highlighttable:first-child .linenos,[dir=rtl] .md-typeset .tabbed-block>.highlight:first-child>pre:first-child>code,[dir=rtl] .md-typeset .tabbed-block>.highlighttable:first-child>code,[dir=rtl] .md-typeset .tabbed-block>pre:first-child>code{border-top-left-radius:0}[dir=ltr] .md-typeset .tabbed-block>.highlighttable:first-child .linenos,[dir=rtl] .md-typeset .tabbed-block>.highlighttable:first-child .linenos{border-top-right-radius:0}[dir=rtl] .md-typeset .tabbed-block>.highlighttable:first-child .linenos{border-top-left-radius:0}.md-typeset .tabbed-block>.tabbed-set{margin:0}@media screen and (max-width:44.9375em){[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels{padding-left:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels{padding-right:.8rem}.md-content__inner>.tabbed-set .tabbed-labels{margin:0 -.8rem;max-width:100vw;scroll-padding-inline-start:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels:after{padding-right:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels:after{padding-left:.8rem}.md-content__inner>.tabbed-set .tabbed-labels:after{content:""}}@media screen{.md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9){color:var(--md-accent-fg-color)}.md-typeset .no-js .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset .no-js .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset .no-js .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset .no-js .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset .no-js .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset .no-js .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset .no-js .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset .no-js .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset .no-js .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset .no-js .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset .no-js .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset .no-js .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset .no-js .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset .no-js .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset .no-js .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset .no-js .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset .no-js .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset .no-js .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset .no-js .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset .no-js .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9),.no-js .md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.no-js .md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.no-js .md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.no-js .md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.no-js .md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.no-js .md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.no-js .md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.no-js .md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.no-js .md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.no-js .md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.no-js .md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.no-js .md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.no-js .md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.no-js .md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.no-js .md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.no-js .md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.no-js .md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.no-js .md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.no-js .md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.no-js .md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9){border-color:var(--md-accent-fg-color)}}.md-typeset .tabbed-set>input:first-child.focus-visible~.tabbed-labels>:first-child,.md-typeset .tabbed-set>input:nth-child(10).focus-visible~.tabbed-labels>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11).focus-visible~.tabbed-labels>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12).focus-visible~.tabbed-labels>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13).focus-visible~.tabbed-labels>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14).focus-visible~.tabbed-labels>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15).focus-visible~.tabbed-labels>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16).focus-visible~.tabbed-labels>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17).focus-visible~.tabbed-labels>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18).focus-visible~.tabbed-labels>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19).focus-visible~.tabbed-labels>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2).focus-visible~.tabbed-labels>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20).focus-visible~.tabbed-labels>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3).focus-visible~.tabbed-labels>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4).focus-visible~.tabbed-labels>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5).focus-visible~.tabbed-labels>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6).focus-visible~.tabbed-labels>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7).focus-visible~.tabbed-labels>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8).focus-visible~.tabbed-labels>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9).focus-visible~.tabbed-labels>:nth-child(9){background-color:var(--md-accent-fg-color--transparent)}.md-typeset .tabbed-set>input:first-child:checked~.tabbed-content>:first-child,.md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-content>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-content>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-content>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-content>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-content>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-content>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-content>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-content>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-content>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-content>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-content>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-content>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-content>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-content>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-content>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-content>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-content>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-content>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-content>:nth-child(9){display:block}:root{--md-tasklist-icon:url('data:image/svg+xml;charset=utf-8,');--md-tasklist-icon--checked:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .task-list-item{list-style-type:none;position:relative}[dir=ltr] .md-typeset .task-list-item [type=checkbox]{left:-2em}[dir=rtl] .md-typeset .task-list-item [type=checkbox]{right:-2em}.md-typeset .task-list-item [type=checkbox]{position:absolute;top:.45em}.md-typeset .task-list-control [type=checkbox]{opacity:0;z-index:-1}[dir=ltr] .md-typeset .task-list-indicator:before{left:-1.5em}[dir=rtl] .md-typeset .task-list-indicator:before{right:-1.5em}.md-typeset .task-list-indicator:before{background-color:var(--md-default-fg-color--lightest);content:"";height:1.25em;-webkit-mask-image:var(--md-tasklist-icon);mask-image:var(--md-tasklist-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.15em;width:1.25em}.md-typeset [type=checkbox]:checked+.task-list-indicator:before{background-color:#00e676;-webkit-mask-image:var(--md-tasklist-icon--checked);mask-image:var(--md-tasklist-icon--checked)}:root>*{--md-mermaid-font-family:var(--md-text-font-family),sans-serif;--md-mermaid-edge-color:var(--md-code-fg-color);--md-mermaid-node-bg-color:var(--md-accent-fg-color--transparent);--md-mermaid-node-fg-color:var(--md-accent-fg-color);--md-mermaid-label-bg-color:var(--md-default-bg-color);--md-mermaid-label-fg-color:var(--md-code-fg-color)}.mermaid{line-height:normal;margin:1em 0}@media screen and (min-width:45em){[dir=ltr] .md-typeset .inline{margin-right:.8rem}[dir=rtl] .md-typeset .inline{margin-left:.8rem}.md-typeset .inline{float:left;margin-bottom:.8rem;margin-top:0;width:11.7rem}[dir=rtl] .md-typeset .inline{float:right}[dir=ltr] .md-typeset .inline.end{margin-left:.8rem;margin-right:0}[dir=rtl] .md-typeset .inline.end{margin-left:0;margin-right:.8rem}.md-typeset .inline.end{float:right}[dir=rtl] .md-typeset .inline.end{float:left}} \ No newline at end of file diff --git a/assets/stylesheets/main.df45aa19.min.css.map b/assets/stylesheets/main.8c5ef100.min.css.map similarity index 58% rename from assets/stylesheets/main.df45aa19.min.css.map rename to assets/stylesheets/main.8c5ef100.min.css.map index 9a91a79cb..51603b280 100644 --- a/assets/stylesheets/main.df45aa19.min.css.map +++ b/assets/stylesheets/main.8c5ef100.min.css.map @@ -1 +1 @@ -{"version":3,"sources":["src/assets/stylesheets/main/extensions/pymdownx/_keys.scss","../../../src/assets/stylesheets/main.scss","src/assets/stylesheets/main/_resets.scss","src/assets/stylesheets/main/_colors.scss","src/assets/stylesheets/main/_icons.scss","src/assets/stylesheets/main/_typeset.scss","src/assets/stylesheets/utilities/_break.scss","src/assets/stylesheets/main/layout/_banner.scss","src/assets/stylesheets/main/layout/_base.scss","src/assets/stylesheets/main/layout/_clipboard.scss","src/assets/stylesheets/main/layout/_content.scss","src/assets/stylesheets/main/layout/_dialog.scss","src/assets/stylesheets/main/layout/_footer.scss","src/assets/stylesheets/main/layout/_form.scss","src/assets/stylesheets/main/layout/_header.scss","src/assets/stylesheets/main/layout/_nav.scss","src/assets/stylesheets/main/layout/_search.scss","src/assets/stylesheets/main/layout/_select.scss","src/assets/stylesheets/main/layout/_sidebar.scss","src/assets/stylesheets/main/layout/_source.scss","src/assets/stylesheets/main/layout/_tabs.scss","src/assets/stylesheets/main/layout/_tag.scss","src/assets/stylesheets/main/layout/_tooltip.scss","src/assets/stylesheets/main/layout/_top.scss","src/assets/stylesheets/main/layout/_version.scss","src/assets/stylesheets/main/extensions/markdown/_admonition.scss","node_modules/material-design-color/material-color.scss","src/assets/stylesheets/main/extensions/markdown/_footnotes.scss","src/assets/stylesheets/main/extensions/markdown/_toc.scss","src/assets/stylesheets/main/extensions/pymdownx/_arithmatex.scss","src/assets/stylesheets/main/extensions/pymdownx/_critic.scss","src/assets/stylesheets/main/extensions/pymdownx/_details.scss","src/assets/stylesheets/main/extensions/pymdownx/_emoji.scss","src/assets/stylesheets/main/extensions/pymdownx/_highlight.scss","src/assets/stylesheets/main/extensions/pymdownx/_tabbed.scss","src/assets/stylesheets/main/extensions/pymdownx/_tasklist.scss","src/assets/stylesheets/main/integrations/_mermaid.scss","src/assets/stylesheets/main/_modifiers.scss"],"names":[],"mappings":"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8mGJ,CgC/mGE,uBACE,sChC8mGJ,CgC3mGE,cACE,yChC6mGJ,CgCjmGE,4DACE,oChCmmGJ,CgCpmGE,yDACE,oChCmmGJ,CgCpmGE,mDACE,oChCmmGJ,CgC3lGE,6CACE,qChC6lGJ,CgC9lGE,0CACE,qChC6lGJ,CgC9lGE,oCACE,qChC6lGJ,CgCnlGE,oDACE,oChCqlGJ,CgCtlGE,iDACE,oChCqlGJ,CgCtlGE,2CACE,oChCqlGJ,CgC5kGE,gDACE,qChC8kGJ,CgC/kGE,6CACE,qChC8kGJ,CgC/kGE,uCACE,qChC8kGJ,CgCzkGE,gCACE,kChC2kGJ,CgC5kGE,6BACE,kChC2kGJ,CgC5kGE,uBACE,kChC2kGJ,CgCrkGE,qCACE,sChCukGJ,CgCxkGE,kCACE,sChCukGJ,CgCxkGE,4BACE,sChCukGJ,CgChkGE,yCACE,sChCkkGJ,CgCnkGE,sCACE,sChCkkGJ,CgCnkGE,gCACE,sChCkkGJ,CgC3jGE,yCACE,qChC6jGJ,CgC9jGE,sCACE,qChC6jGJ,CgC9jGE,gCACE,qChC6jGJ,CgCpjGE,gDACE,qChCsjGJ,CgCvjGE,6CACE,qChCsjGJ,CgCvjGE,uCACE,qChCsjGJ,CgC9iGE,6CACE,sChCgjGJ,CgCjjGE,0CACE,sChCgjGJ,CgCjjGE,oCACE,sChCgjGJ,CgCriGE,yDACE,qChCuiGJ,CgCxiGE,sDACE,qChCuiGJ,CgCxiGE,gDACE,qChCuiGJ,CgCliGE,iCAGE,mBAAA,CAFA,gBAAA,CACA,gBhCqiGJ,CgCviGE,8BAGE,mBAAA,CAFA,gBAAA,CACA,gBhCqiGJ,CgCviGE,wBAGE,mBAAA,CAFA,gBAAA,CACA,gBhCqiGJ,CgCjiGE,eACE,4ChCmiGJ,CgChiGE,eACE,4ChCkiGJ,CgC9hGE,gBAIE,wCAAA,CAHA,aAAA,CACA,wBAAA,CACA,wBhCiiGJ,CgC5hGE,yBAOE,wCAAA,CACA,+DAAA,CACA,4BAAA,CACA,6BAAA,CARA,iBAAA,CAIA,eAAA,CADA,eAAA,CAFA,cAAA,CACA,oCAAA,CAHA,iBhCuiGJ,CgC3hGI,6BACE,YhC6hGN,CgC1hGM,kCACE,wBAAA,CACA,yBhC4hGR,CgCthGE,iCAWE,wCAAA,CACA,+DAAA,CAFA,uCAAA,CAGA,0BAAA,CAPA,UAAA,CAJA,oBAAA,CAMA,2BAAA,CADA,2BAAA,CAEA,2BAAA,CARA,uBAAA,CAAA,eAAA,CAaA,wBAAA,CAAA,qBAAA,CAAA,oBAAA,CAAA,gBAAA,CATA,ShC+hGJ,CgC7gGE,sBACE,iBAAA,CACA,iBhC+gGJ,CgCvgGI,sCACE,gBhCygGN,CgCrgGI,gDACE,YhCugGN,CgC7/FA,gBACE,iBhCggGF,CgC5/FE,uCACE,aAAA,CACA,ShC8/FJ,CgChgGE,oCACE,aAAA,CACA,ShC8/FJ,CgChgGE,8BACE,aAAA,CACA,ShC8/FJ,CgCz/FE,mBACE,YhC2/FJ,CgCt/FE,oBACE,QhCw/FJ,CgCp/FE,4BACE,WAAA,CACA,SAAA,CACA,ehCs/FJ,CgCn/FI,0CACE,YhCq/FN,CgC/+FE,yBAIE,wCAAA,CAEA,+BAAA,CADA,4BAAA,CAFA,eAAA,CADA,oDAAA,CAKA,wBAAA,CAAA,qBAAA,CAAA,oBAAA,CAAA,gBhCi/FJ,CgC7+FE,2BAEE,+DAAA,CADA,2BhCg/FJ,CgC5+FI,+BACE,uCAAA,CACA,gBhC8+FN,CgCz+FE,sBACE,MAAA,CACA,WhC2+FJ,CgCt+FA,aACE,ahCy+FF,CgCh+FE,4BAEE,aAAA,CADA,YhCo+FJ,CgCh+FI,iCAEE,2BAAA,CADA,wBhCm+FN,CgC79FE,6DAKE,2CAAA,CAEA,+BAAA,CADA,gCAAA,CADA,sBAAA,CAJA,mBAAA,CAEA,gBAAA,CADA,ahCo+FJ,CgCt+FE,0DAKE,2CAAA,CAEA,+BAAA,CADA,gCAAA,CADA,sBAAA,CAJA,mBAAA,CAEA,gBAAA,CADA,ahCo+FJ,CgCt+FE,oDAKE,2CAAA,CAEA,+BAAA,CADA,gCAAA,CADA,sBAAA,CAJA,mBAAA,CAEA,gBAAA,CADA,ahCo+FJ,CgC59FI,mEAEE,UAAA,CACA,UAAA,CAFA,ahCg+FN,CgCj+FI,gEAEE,UAAA,CACA,UAAA,CAFA,ahCg+FN,CgCj+FI,0DAEE,UAAA,CACA,UAAA,CAFA,ahCg+FN,CKhmGI,wC2B+IF,8BACE,iBhCq9FF,CgCl9FE,mCACE,eAAA,CACA,ehCo9FJ,CgCh9FE,mCACE,ehCk9FJ,CgC98FE,sCAEE,mBAAA,CACA,eAAA,CADA,oBAAA,CADA,kBAAA,CAAA,mBhCk9FJ,CgC38FA,mCAEE,eAAA,CADA,iBhC+8FF,CgC38FE,wCACE,eAAA,CACA,ehC68FJ,CACF,CD9yGI,kDAIE,+BAAA,CACA,8BAAA,CAFA,aAAA,CADA,QAAA,CADA,iBCozGN,CDrzGI,+CAIE,+BAAA,CACA,8BAAA,CAFA,aAAA,CADA,QAAA,CADA,iBCozGN,CDrzGI,yCAIE,+BAAA,CACA,8BAAA,CAFA,aAAA,CADA,QAAA,CADA,iBCozGN,CD5yGI,uBAEE,uCAAA,CADA,cC+yGN,CD1vGM,iHAEE,WAlDkB,CAiDlB,kBCqwGR,CDtwGM,6HAEE,WAlDkB,CAiDlB,kBCixGR,CDlxGM,6HAEE,WAlDkB,CAiDlB,kBC6xGR,CD9xGM,oHAEE,WAlDkB,CAiDlB,kBCyyGR,CD1yGM,0HAEE,WAlDkB,CAiDlB,kBCqzGR,CDtzGM,uHAEE,WAlDkB,CAiDlB,kBCi0GR,CDl0GM,uHAEE,WAlDkB,CAiDlB,kBC60GR,CD90GM,6HAEE,WAlDkB,CAiDlB,kBCy1GR,CD11GM,yCAEE,WAlDkB,CAiDlB,kBC61GR,CD91GM,yCAEE,WAlDkB,CAiDlB,kBCi2GR,CDl2GM,0CAEE,WAlDkB,CAiDlB,kBCq2GR,CDt2GM,uCAEE,WAlDkB,CAiDlB,kBCy2GR,CD12GM,wCAEE,WAlDkB,CAiDlB,kBC62GR,CD92GM,sCAEE,WAlDkB,CAiDlB,kBCi3GR,CDl3GM,wCAEE,WAlDkB,CAiDlB,kBCq3GR,CDt3GM,oCAEE,WAlDkB,CAiDlB,kBCy3GR,CD13GM,2CAEE,WAlDkB,CAiDlB,kBC63GR,CD93GM,qCAEE,WAlDkB,CAiDlB,kBCi4GR,CDl4GM,oCAEE,WAlDkB,CAiDlB,kBCq4GR,CDt4GM,kCAEE,WAlDkB,CAiDlB,kBCy4GR,CD14GM,qCAEE,WAlDkB,CAiDlB,kBC64GR,CD94GM,mCAEE,WAlDkB,CAiDlB,kBCi5GR,CDl5GM,qCAEE,WAlDkB,CAiDlB,kBCq5GR,CDt5GM,wCAEE,WAlDkB,CAiDlB,kBCy5GR,CD15GM,sCAEE,WAlDkB,CAiDlB,kBC65GR,CD95GM,2CAEE,WAlDkB,CAiDlB,kBCi6GR,CDt5GM,iCAEE,WAPkB,CAMlB,iBCy5GR,CD15GM,uCAEE,WAPkB,CAMlB,iBC65GR,CD95GM,mCAEE,WAPkB,CAMlB,iBCi6GR,CiCh/GE,wBAKE,mBAAA,CAHA,YAAA,CACA,qBAAA,CACA,YAAA,CAHA,iBjCu/GJ,CiC7+GI,8BAGE,QAAA,CACA,SAAA,CAHA,iBAAA,CACA,OjCi/GN,CiC5+GM,qCACE,0BjC8+GR,CiC/8GE,2BAME,uBAAA,CAFA,+DAAA,CAHA,YAAA,CACA,cAAA,CACA,aAAA,CAEA,gCAAA,CAAA,4BAAA,CAEA,oBjCi9GJ,CiC98GI,aAVF,2BAWI,gBjCi9GJ,CACF,CiC98GI,cAGE,+BACE,iBjC88GN,CiC38GM,sCAOE,oCAAA,CALA,QAAA,CAWA,UAAA,CATA,aAAA,CAEA,UAAA,CAHA,MAAA,CAFA,iBAAA,CAOA,2CAAA,CACA,qCACE,CAEF,kDAAA,CAPA,+BjCm9GR,CACF,CiCt8GI,8CACE,YjCw8GN,CiCp8GI,iCAQE,qCAAA,CAEA,6BAAA,CANA,uCAAA,CAOA,cAAA,CAVA,aAAA,CAKA,gBAAA,CADA,eAAA,CAFA,8BAAA,CAMA,uBAAA,CAGA,2CACE,CANF,kBAAA,CALA,UjCg9GN,CiCj8GM,aAII,6CACE,OjCg8GV,CiCj8GQ,8CACE,OjCm8GV,CiCp8GQ,8CACE,OjCs8GV,CiCv8GQ,8CACE,OjCy8GV,CiC18GQ,8CACE,OjC48GV,CiC78GQ,8CACE,OjC+8GV,CiCh9GQ,8CACE,OjCk9GV,CiCn9GQ,8CACE,OjCq9GV,CiCt9GQ,8CACE,OjCw9GV,CiCz9GQ,+CACE,QjC29GV,CiC59GQ,+CACE,QjC89GV,CiC/9GQ,+CACE,QjCi+GV,CiCl+GQ,+CACE,QjCo+GV,CiCr+GQ,+CACE,QjCu+GV,CiCx+GQ,+CACE,QjC0+GV,CiC3+GQ,+CACE,QjC6+GV,CiC9+GQ,+CACE,QjCg/GV,CiCj/GQ,+CACE,QjCm/GV,CiCp/GQ,+CACE,QjCs/GV,CiCv/GQ,+CACE,QjCy/GV,CACF,CiCp/GM,uCACE,+BjCs/GR,CiCh/GE,4BACE,UjCk/GJ,CiC/+GI,aAJF,4BAKI,gBjCk/GJ,CACF,CiC9+GE,0BACE,YjCg/GJ,CiC7+GI,aAJF,0BAKI,ajCg/GJ,CiC5+GM,sCACE,OjC8+GR,CiC/+GM,uCACE,OjCi/GR,CiCl/GM,uCACE,OjCo/GR,CiCr/GM,uCACE,OjCu/GR,CiCx/GM,uCACE,OjC0/GR,CiC3/GM,uCACE,OjC6/GR,CiC9/GM,uCACE,OjCggHR,CiCjgHM,uCACE,OjCmgHR,CiCpgHM,uCACE,OjCsgHR,CiCvgHM,wCACE,QjCygHR,CiC1gHM,wCACE,QjC4gHR,CiC7gHM,wCACE,QjC+gHR,CiChhHM,wCACE,QjCkhHR,CiCnhHM,wCACE,QjCqhHR,CiCthHM,wCACE,QjCwhHR,CiCzhHM,wCACE,QjC2hHR,CiC5hHM,wCACE,QjC8hHR,CiC/hHM,wCACE,QjCiiHR,CiCliHM,wCACE,QjCoiHR,CiCriHM,wCACE,QjCuiHR,CACF,CiCjiHI,iKAGE,QjCmiHN,CiChiHM,8MACE,wBjCqiHR,CiCtiHM,4ZAEE,yBjCoiHR,CiC/hHI,uRACE,wBjCkiHN,CiCniHI,kJAEE,yBjCiiHN,CiCniHI,yEAEE,wBjCiiHN,CiC7hHI,sCACE,QjC+hHN,CK3hHI,wC4BSF,wDAGE,kBjCuhHF,CiC1hHA,wDAGE,mBjCuhHF,CiC1hHA,8CAEE,eAAA,CADA,eAAA,CAGA,iCjCshHF,CiClhHE,8DACE,mBjCqhHJ,CiCthHE,8DACE,kBjCqhHJ,CiCthHE,oDAEE,UjCohHJ,CACF,CiCxgHE,cAHF,olDAII,+BjC2gHF,CiCxgHE,g8GACE,sCjC0gHJ,CACF,CiCrgHA,4sDACE,uDjCwgHF,CiCpgHA,wmDACE,ajCugHF,CkCjvHA,MACE,mVAAA,CAEA,4VlCqvHF,CkC3uHE,4BAEE,oBAAA,CADA,iBlC+uHJ,CkC1uHI,sDAGE,SlC4uHN,CkC/uHI,sDAGE,UlC4uHN,CkC/uHI,4CACE,iBAAA,CACA,SlC6uHN,CkCvuHE,+CAEE,SAAA,CADA,UlC0uHJ,CkCruHE,kDAGE,WlC8uHJ,CkCjvHE,kDAGE,YlC8uHJ,CkCjvHE,wCAME,qDAAA,CAIA,UAAA,CALA,aAAA,CAEA,0CAAA,CAAA,kCAAA,CACA,6BAAA,CAAA,qBAAA,CACA,yBAAA,CAAA,iBAAA,CARA,iBAAA,CACA,SAAA,CAEA,YlC6uHJ,CkCnuHE,gEACE,wBT0Wa,CSzWb,mDAAA,CAAA,2ClCquHJ,CmCtxHA,QACE,8DAAA,CAGA,+CAAA,CACA,iEAAA,CACA,oDAAA,CACA,sDAAA,CACA,mDnCuxHF,CmCnxHA,SAEE,kBAAA,CADA,YnCuxHF,CK9nHI,mC+BhKA,8BAIE,kBpCmyHJ,CoCvyHE,8BAIE,iBpCmyHJ,CoCvyHE,oBACE,UAAA,CAIA,mBAAA,CAFA,YAAA,CADA,apCqyHJ,CoC/xHI,8BACE,WpCiyHN,CoC7xHI,kCAEE,iBAAA,CAAA,cpC+xHN,CoCjyHI,kCAEE,aAAA,CAAA,kBpC+xHN,CoCjyHI,wBACE,WpCgyHN,CoC5xHM,kCACE,UpC8xHR,CACF","file":"main.css"} \ No newline at end of file +{"version":3,"sources":["src/assets/stylesheets/main/extensions/pymdownx/_keys.scss","../../../src/assets/stylesheets/main.scss","src/assets/stylesheets/main/_resets.scss","src/assets/stylesheets/main/_colors.scss","src/assets/stylesheets/main/_icons.scss","src/assets/stylesheets/main/_typeset.scss","src/assets/stylesheets/utilities/_break.scss","src/assets/stylesheets/main/layout/_banner.scss","src/assets/stylesheets/main/layout/_base.scss","src/assets/stylesheets/main/layout/_clipboard.scss","src/assets/stylesheets/main/layout/_content.scss","src/assets/stylesheets/main/layout/_dialog.scss","src/assets/stylesheets/main/layout/_footer.scss","src/assets/stylesheets/main/layout/_form.scss","src/assets/stylesheets/main/layout/_header.scss","src/assets/stylesheets/main/layout/_nav.scss","src/assets/stylesheets/main/layout/_search.scss","src/assets/stylesheets/main/layout/_select.scss","src/assets/stylesheets/main/layout/_sidebar.scss","src/assets/stylesheets/main/layout/_source.scss","src/assets/stylesheets/main/layout/_tabs.scss","src/assets/stylesheets/main/layout/_tag.scss","src/assets/stylesheets/main/layout/_tooltip.scss","src/assets/stylesheets/main/layout/_top.scss","src/assets/stylesheets/main/layout/_version.scss","src/assets/stylesheets/main/extensions/markdown/_admonition.scss","node_modules/material-design-color/material-color.scss","src/assets/stylesheets/main/extensions/markdown/_footnotes.scss","src/assets/stylesheets/main/extensions/markdown/_toc.scss","src/assets/stylesheets/main/extensions/pymdownx/_arithmatex.scss","src/assets/stylesheets/main/extensions/pymdownx/_critic.scss","src/assets/stylesheets/main/extensions/pymdownx/_details.scss","src/assets/stylesheets/main/extensions/pymdownx/_emoji.scss","src/assets/stylesheets/main/extensions/pymdownx/_highlight.scss","src/assets/stylesheets/main/extensions/pymdownx/_tabbed.scss","src/assets/stylesheets/main/extensions/pymdownx/_tasklist.scss","src/assets/stylesheets/main/integrations/_mermaid.scss","src/assets/stylesheets/main/_modifiers.scss"],"names":[],"mappings":"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,6BACE,sChC+mGJ,CgChnGE,uBACE,sChC+mGJ,CgC5mGE,cACE,yChC8mGJ,CgClmGE,4DACE,oChComGJ,CgCrmGE,yDACE,oChComGJ,CgCrmGE,mDACE,oChComGJ,CgC5lGE,6CACE,qChC8lGJ,CgC/lGE,0CACE,qChC8lGJ,CgC/lGE,oCACE,qChC8lGJ,CgCplGE,oDACE,oChCslGJ,CgCvlGE,iDACE,oChCslGJ,CgCvlGE,2CACE,oChCslGJ,CgC7kGE,gDACE,qChC+kGJ,CgChlGE,6CACE,qChC+kGJ,CgChlGE,uCACE,qChC+kGJ,CgC1kGE,gCACE,kChC4kGJ,CgC7kGE,6BACE,kChC4kGJ,CgC7kGE,uBACE,kChC4kGJ,CgCtkGE,qCACE,sChCwkGJ,CgCzkGE,kCACE,sChCwkGJ,CgCzkGE,4BACE,sChCwkGJ,CgCjkGE,yCACE,sChCmkGJ,CgCpkGE,sCACE,sChCmkGJ,CgCpkGE,gCACE,sChCmkGJ,CgC5jGE,yCACE,qChC8jGJ,CgC/jGE,sCACE,qChC8jGJ,CgC/jGE,gCACE,qChC8jGJ,CgCrjGE,gDACE,qChCujGJ,CgCxjGE,6CACE,qChCujGJ,CgCxjGE,uCACE,qChCujGJ,CgC/iGE,6CACE,sChCijGJ,CgCljGE,0CACE,sChCijGJ,CgCljGE,oCACE,sChCijGJ,CgCtiGE,yDACE,qChCwiGJ,CgCziGE,sDACE,qChCwiGJ,CgCziGE,gDACE,qChCwiGJ,CgCniGE,iCAGE,mBAAA,CAFA,gBAAA,CACA,gBhCsiGJ,CgCxiGE,8BAGE,mBAAA,CAFA,gBAAA,CACA,gBhCsiGJ,CgCxiGE,wBAGE,mBAAA,CAFA,gBAAA,CACA,gBhCsiGJ,CgCliGE,eACE,4ChCoiGJ,CgCjiGE,eACE,4ChCmiGJ,CgC/hGE,gBAIE,wCAAA,CAHA,aAAA,CACA,wBAAA,CACA,wBhCkiGJ,CgC7hGE,yBAOE,wCAAA,CACA,+DAAA,CACA,4BAAA,CACA,6BAAA,CARA,iBAAA,CAIA,eAAA,CADA,eAAA,CAFA,cAAA,CACA,oCAAA,CAHA,iBhCwiGJ,CgC5hGI,6BACE,YhC8hGN,CgC3h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jC8+GV,CiC/+GQ,+CACE,QjCi/GV,CiCl/GQ,+CACE,QjCo/GV,CiCr/GQ,+CACE,QjCu/GV,CiCx/GQ,+CACE,QjC0/GV,CACF,CiCr/GM,uCACE,+BjCu/GR,CiCj/GE,4BACE,UjCm/GJ,CiCh/GI,aAJF,4BAKI,gBjCm/GJ,CACF,CiC/+GE,0BACE,YjCi/GJ,CiC9+GI,aAJF,0BAKI,ajCi/GJ,CiC7+GM,sCACE,OjC++GR,CiCh/GM,uCACE,OjCk/GR,CiCn/GM,uCACE,OjCq/GR,CiCt/GM,uCACE,OjCw/GR,CiCz/GM,uCACE,OjC2/GR,CiC5/GM,uCACE,OjC8/GR,CiC//GM,uCACE,OjCigHR,CiClgHM,uCACE,OjCogHR,CiCrgHM,uCACE,OjCugHR,CiCxgHM,wCACE,QjC0gHR,CiC3gHM,wCACE,QjC6gHR,CiC9gHM,wCACE,QjCghHR,CiCjhHM,wCACE,QjCmhHR,CiCphHM,wCACE,QjCshHR,CiCvhHM,wCACE,QjCyhHR,CiC1hHM,wCACE,QjC4hHR,CiC7hHM,wCACE,QjC+hHR,CiChiHM,wCACE,QjCkiHR,CiCniHM,wCACE,QjCqiHR,CiCtiHM,wCACE,QjCwiHR,CACF,CiCliHI,iKAGE,QjCoiHN,CiCjiHM,8MACE,wBjCsiHR,CiCviHM,4ZAEE,yBjCqiHR,CiChiHI,uRACE,wBjCmiHN,CiCpiHI,kJAEE,yBjCkiHN,CiCpiHI,yEAEE,wBjCkiHN,CiC9hHI,sCACE,QjCgiHN,CK5hHI,wC4BSF,wDAGE,kBjCwhHF,CiC3hHA,wDAGE,mBjCwhHF,CiC3hHA,8CAEE,eAAA,CADA,eAAA,CAGA,iCjCuhHF,CiCnhHE,8DACE,mBjCshHJ,CiCvhHE,8DACE,kBjCshHJ,CiCvhHE,oDAEE,UjCqhHJ,CACF,CiCzgHE,cAHF,olDAII,+BjC4gHF,CiCzgHE,g8GACE,sCjC2gHJ,CACF,CiCtgHA,4sDACE,uDjCygHF,CiCrgHA,wmDACE,ajCwgHF,CkClvHA,MACE,mVAAA,CAEA,4VlCsvHF,CkC5uHE,4BAEE,oBAAA,CADA,iBlCgvHJ,CkC3uHI,sDAGE,SlC6uHN,CkChvHI,sDAGE,UlC6uHN,CkChvHI,4CACE,iBAAA,CACA,SlC8uHN,CkCxuHE,+CAEE,SAAA,CADA,UlC2uHJ,CkCtuHE,kDAGE,WlC+uHJ,CkClvHE,kDAGE,YlC+uHJ,CkClvHE,wCAME,qDAAA,CAIA,UAAA,CALA,aAAA,CAEA,0CAAA,CAAA,kCAAA,CACA,6BAAA,CAAA,qBAAA,CACA,yBAAA,CAAA,iBAAA,CARA,iBAAA,CACA,SAAA,CAEA,YlC8uHJ,CkCpuHE,gEACE,wBT0Wa,CSzWb,mDAAA,CAAA,2ClCsuHJ,CmCvxHA,QACE,8DAAA,CAGA,+CAAA,CACA,iEAAA,CACA,oDAAA,CACA,sDAAA,CACA,mDnCwxHF,CmCpxHA,SAEE,kBAAA,CADA,YnCwxHF,CK/nHI,mC+BhKA,8BAIE,kBpCoyHJ,CoCxyHE,8BAIE,iBpCoyHJ,CoCxyHE,oBACE,UAAA,CAIA,mBAAA,CAFA,YAAA,CADA,apCsyHJ,CoChyHI,8BACE,WpCkyHN,CoC9xHI,kCAEE,iBAAA,CAAA,cpCgyHN,CoClyHI,kCAEE,aAAA,CAAA,kBpCgyHN,CoClyHI,wBACE,WpCiyHN,CoC7xHM,kCACE,UpC+xHR,CACF","file":"main.css"} \ No newline at end of file diff --git a/backup_restore/b_n_r-accidental_deletion/index.html b/backup_restore/b_n_r-accidental_deletion/index.html index 83aed22d8..735d82829 100644 --- a/backup_restore/b_n_r-accidental_deletion/index.html +++ b/backup_restore/b_n_r-accidental_deletion/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2428,9 +2428,9 @@

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 force-resync -u restoreme@example.net '*'
 docker-compose exec dovecot-mailcow doveadm quota recalc -u restoreme@example.net
-
+

diff --git a/backup_restore/b_n_r-backup/index.html b/backup_restore/b_n_r-backup/index.html index 878202dea..f97af78e8 100644 --- a/backup_restore/b_n_r-backup/index.html +++ b/backup_restore/b_n_r-backup/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2454,7 +2454,7 @@

Please do not copy this script to another location.

To run a backup, write "backup" as first parameter and either one or more components to backup as following parameters. You can also use "all" as second parameter to backup all components. Append --delete-days n to delete backups older than n days.

-
# Syntax:
+
# Syntax:
 # ./helper-scripts/backup_and_restore.sh backup (vmail|crypt|redis|rspamd|postfix|mysql|all|--delete-days)
 
 # Backup all, delete backups older than 3 days
@@ -2465,19 +2465,19 @@ You can also use "all" as second parameter to backup all components. Append 
+

The script will ask you for a backup location. Inside of this location it will create folders in the format "mailcow_DATE". You should not rename those folders to not break the restore process.

To run a backup unattended, define MAILCOW_BACKUP_LOCATION as environment variable before starting the script:

-
MAILCOW_BACKUP_LOCATION=/opt/backup /opt/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup all
-
+
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
-
+
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
+
#!/bin/sh
 
 # Backup mailcow data
 # https://mailcow.github.io/mailcow-dockerized-docs/backup_restore/b_n_r-backup/
@@ -2502,17 +2502,17 @@ if [ $RESULT -ne 0 ]
             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
-

+
mkdir -p /external_share/backups/backup_script
+

Create cronjobs: -

25 1 * * * rsync -aH --delete /opt/mailcow-dockerized /external_share/backups/mailcow-dockerized
+
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.

diff --git a/backup_restore/b_n_r-backup_restore-maildir/index.html b/backup_restore/b_n_r-backup_restore-maildir/index.html index dbcbd50cf..fd47d3be3 100644 --- a/backup_restore/b_n_r-backup_restore-maildir/index.html +++ b/backup_restore/b_n_r-backup_restore-maildir/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2412,15 +2412,15 @@

Backup

This line backups the vmail directory to a file backup_vmail.tar.gz in the mailcow root directory: -

cd /path/to/mailcow-dockerized
+
cd /path/to/mailcow-dockerized
 docker run --rm -i -v $(docker inspect --format '{{ range .Mounts }}{{ if eq .Destination "/var/vmail" }}{{ .Name }}{{ end }}{{ end }}' $(docker-compose ps -q dovecot-mailcow)):/vmail -v ${PWD}:/backup debian:stretch-slim tar cvfz /backup/backup_vmail.tar.gz /vmail
-

+

You can change the path by adjusting ${PWD} (which equals to the current directory) to any path you have write-access to. Set the filename backup_vmail.tar.gz to any custom name, but leave the path as it is. Example: [...] tar cvfz /backup/my_own_filename_.tar.gz

Restore

-
cd /path/to/mailcow-dockerized
+
cd /path/to/mailcow-dockerized
 docker run --rm -it -v $(docker inspect --format '{{ range .Mounts }}{{ if eq .Destination "/var/vmail" }}{{ .Name }}{{ end }}{{ end }}' $(docker-compose ps -q dovecot-mailcow)):/vmail -v ${PWD}:/backup debian:stretch-slim tar xvfz /backup/backup_vmail.tar.gz
-
+

diff --git a/backup_restore/b_n_r-backup_restore-mysql/index.html b/backup_restore/b_n_r-backup_restore-mysql/index.html index b53f6f1c1..70b48a356 100644 --- a/backup_restore/b_n_r-backup_restore-mysql/index.html +++ b/backup_restore/b_n_r-backup_restore-mysql/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2411,20 +2411,20 @@

MySQL (mysqldump)

Backup

-
cd /path/to/mailcow-dockerized
+
cd /path/to/mailcow-dockerized
 source mailcow.conf
 DATE=$(date +"%Y%m%d_%H%M%S")
 docker-compose exec -T mysql-mailcow mysqldump --default-character-set=utf8mb4 -u${DBUSER} -p${DBPASS} ${DBNAME} > backup_${DBNAME}_${DATE}.sql
-
+

Restore

Warning

You should redirect the SQL dump without docker-compose to prevent parsing errors.

-
cd /path/to/mailcow-dockerized
+
cd /path/to/mailcow-dockerized
 source mailcow.conf
 docker exec -i $(docker-compose ps -q mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} < backup_file.sql
-
+

diff --git a/backup_restore/b_n_r-coldstandby/index.html b/backup_restore/b_n_r-coldstandby/index.html index 216c76aff..fae35be74 100644 --- a/backup_restore/b_n_r-coldstandby/index.html +++ b/backup_restore/b_n_r-coldstandby/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2459,10 +2459,10 @@

You will need a SSH-enabled destination and a keyfile to connect to said destination. The key should not be protected by a password for the script to work unattended.

In your mailcow base directory, e.g. /opt/mailcow-dockerized you will find a file create_cold_standby.sh.

Edit this file and change the exported variables:

-
export REMOTE_SSH_KEY=/path/to/keyfile
+
export REMOTE_SSH_KEY=/path/to/keyfile
 export REMOTE_SSH_PORT=22
 export REMOTE_SSH_HOST=mailcow-backup.host.name
-
+

The key must be owned and readable by root only.

Both the source and destination require rsync >= v3.1.0. The destination must have Docker and docker-compose v1 available.

@@ -2470,28 +2470,28 @@ The destination must have Docker and docker-compose v1 availabl

You may want to test the connection by running ssh mailcow-backup.host.name -p22 -i /path/to/keyfile.

Backup and refresh the cold-standby

Run the first backup, this may take a while depending on the connection:

-
bash /opt/mailcow-dockerized/create_cold_standby.sh
-
+
bash /opt/mailcow-dockerized/create_cold_standby.sh
+

That was easy, wasn't it?

Updating your cold-standby is just as easy:

-
bash /opt/mailcow-dockerized/create_cold_standby.sh
-
+
bash /opt/mailcow-dockerized/create_cold_standby.sh
+

It's the same command.

Automated backups with cron

First make sure that the cron service is enabled and running:

-
systemctl enable cron.service && systemctl start cron.service
-
+
systemctl enable cron.service && systemctl start cron.service
+

To automate the backups to the cold-standby server you can use a cron job. To edit the cron jobs for the root user run:

-
crontab -e
-
+
crontab -e
+

Add the following lines to synchronize the cold standby server daily at 03:00. In this example errors of the last execution are logged into a file.

-
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
 
 0 3 * * * bash /opt/mailcow-dockerized/create_cold_standby.sh 2> /var/log/mailcow-coldstandby-sync.log
-
+

If saved correctly, the cron job should be shown by typing:

-
crontab -l
-
+
crontab -l
+

diff --git a/backup_restore/b_n_r-restore/index.html b/backup_restore/b_n_r-restore/index.html index c48a313ba..bc8942836 100644 --- a/backup_restore/b_n_r-restore/index.html +++ b/backup_restore/b_n_r-restore/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2399,9 +2399,9 @@

Restore

Please do not copy this script to another location.

To run a restore, start mailcow, use the script with "restore" as first parameter.

-
# Syntax:
+
# Syntax:
 # ./helper-scripts/backup_and_restore.sh restore
-
+

The script will ask you for a backup location containing the mailcow_DATE folders.


diff --git a/client/client-android/index.html b/client/client-android/index.html index 9e8c6e335..1b6c269e8 100644 --- a/client/client-android/index.html +++ b/client/client-android/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/client/client-apple/index.html b/client/client-apple/index.html index 907749fca..da8bd1dd2 100644 --- a/client/client-apple/index.html +++ b/client/client-apple/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/client/client-emclient/index.html b/client/client-emclient/index.html index 8c284038c..9abdb3c28 100644 --- a/client/client-emclient/index.html +++ b/client/client-emclient/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/client/client-kontact/index.html b/client/client-kontact/index.html index 10fbc3bd8..88edf0f9d 100644 --- a/client/client-kontact/index.html +++ b/client/client-kontact/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/client/client-manual/index.html b/client/client-manual/index.html index b2cff4ae5..9fd33ace0 100644 --- a/client/client-manual/index.html +++ b/client/client-manual/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/client/client-outlook/index.html b/client/client-outlook/index.html index 6c54e24de..d666f4fd0 100644 --- a/client/client-outlook/index.html +++ b/client/client-outlook/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/client/client-thunderbird/index.html b/client/client-thunderbird/index.html index 655bb5b85..eadc175ab 100644 --- a/client/client-thunderbird/index.html +++ b/client/client-thunderbird/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/client/client-windows/index.html b/client/client-windows/index.html index d99e6ba10..30a9af223 100644 --- a/client/client-windows/index.html +++ b/client/client-windows/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/client/client/index.html b/client/client/index.html index eef32735d..422619e9d 100644 --- a/client/client/index.html +++ b/client/client/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/backup_restore/b_n_r-accidental_deletion/index.html b/de/backup_restore/b_n_r-accidental_deletion/index.html index 1e73c2139..9c218b846 100644 --- a/de/backup_restore/b_n_r-accidental_deletion/index.html +++ b/de/backup_restore/b_n_r-accidental_deletion/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2428,9 +2428,9 @@

Um die Mailbox wiederherzustellen, stellen Sie sicher, dass Sie tatsächlich auf die gleiche Mailcow wiederherstellen, von der sie gelÜscht wurde, oder Sie verwenden die gleichen Verschlßsselungsschlßssel in crypt-vol-1.

Stellen Sie sicher, dass der Benutzer, den Sie wiederherstellen wollen, in Ihrer Mailcow existiert. Legen Sie diesen neu an, wenn der Benutzer fehlt.

Kopieren Sie die Ordner von /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/_garbage/[timestamp]_[domain_sanitized][user_sanitized] zurĂźck nach /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/[domain]/[user] und synchronisieren Sie die Ordner neu und berechnen Sie die Quota (Speicherplatz) neu:

-
docker-compose exec dovecot-mailcow doveadm force-resync -u restoreme@example.net '*'
+
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/de/backup_restore/b_n_r-backup/index.html b/de/backup_restore/b_n_r-backup/index.html index 35c7f76ac..7a9824e05 100644 --- a/de/backup_restore/b_n_r-backup/index.html +++ b/de/backup_restore/b_n_r-backup/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2454,7 +2454,7 @@

Bitte kopieren Sie dieses Skript nicht an einen anderen Ort.

Um ein Backup zu starten, geben Sie "backup" als ersten Parameter an und entweder eine oder mehrere zu sichernde Komponenten als folgende Parameter. Sie kÜnnen auch "all" als zweiten Parameter verwenden, um alle Komponenten zu sichern. Fßgen Sie --delete-days n an, um Sicherungen zu lÜschen, die älter als n Tage sind.

-
# Syntax:
+
# Syntax:
 # ./helper-scripts/backup_and_restore.sh backup (vmail|crypt|redis|rspamd|postfix|mysql|all|--delete-days)
 
 # Alles sichern, Sicherungen älter als 3 Tage lÜschen
@@ -2465,19 +2465,19 @@ Sie kĂśnnen auch "all" als zweiten Parameter verwenden, um alle Komponenten zu s
 
 # vmail sichern
 ./helper-scripts/backup_and_restore.sh backup vmail
-
+

Das Skript wird Sie nach einem Speicherort fĂźr die Sicherung fragen. Innerhalb dieses Speicherortes wird es Ordner im Format "mailcow_DATE" erstellen. Sie sollten diese Ordner nicht umbenennen, um den Wiederherstellungsprozess nicht zu unterbrechen.

Um ein Backup unbeaufsichtigt durchzufĂźhren, definieren Sie MAILCOW_BACKUP_LOCATION als Umgebungsvariable bevor Sie das Skript starten:

-
MAILCOW_BACKUP_LOCATION=/opt/backup /opt/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup all
-
+
MAILCOW_BACKUP_LOCATION=/opt/backup /opt/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup all
+

Cronjob

Sie können das Backup-Skript regelmäßig über einen Cronjob laufen lassen. Stellen Sie sicher, dass BACKUP_LOCATION existiert:

-
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
-
+
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
+

Standardmäßig sendet Cron das komplette Ergebnis jeder Backup-Operation per E-Mail. Wenn Sie möchten, dass cron nur im Fehlerfall (Exit-Code ungleich Null) eine E-Mail sendet, können Sie den folgenden Ausschnitt verwenden. Die Pfade müssen entsprechend Ihrer Einrichtung angepasst werden (dieses Skript ist ein Beitrag des Benutzers).

Das folgende Skript kann in /etc/cron.daily/mailcow-backup platziert werden - vergessen Sie nicht, es mit chmod +x als ausfĂźhrbar zu markieren:

-
#!/bin/sh
+
#!/bin/sh
 
 # Backup mailcow data
 # https://mailcow.github.io/mailcow-dockerized-docs/b_n_r_backup/
@@ -2521,17 +2521,17 @@ if [ $RESULT -ne 0 ]
             echo "STDOUT / STDERR:"
             cat "$OUT"
 fi
-
+

Backup-Strategie mit rsync und mailcow Backup-Skript

Erstellen Sie das Zielverzeichnis fĂźr mailcows Hilfsskript: -

mkdir -p /external_share/backups/backup_script
-

+
mkdir -p /external_share/backups/backup_script
+

Cronjobs erstellen: -

25 1 * * * rsync -aH --delete /opt/mailcow-dockerized /external_share/backups/mailcow-dockerized
+
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
 # Wenn Sie wollen, benutzen Sie acl util, um die Berechtigungen einiger/aller Ordner/Dateien zu sichern: getfacl -Rn /path
-

+

Am Zielort (in diesem Fall /external_share/backups) mÜchten Sie vielleicht Snapshot-Fähigkeiten haben (ZFS, Btrfs usw.). Machen Sie täglich einen Snapshot und bewahren Sie ihn fßr n Tage auf, um ein konsistentes Backup zu erhalten. Fßhren Sie kein rsync auf eine Samba-Freigabe durch, Sie mßssen die richtigen Berechtigungen einhalten!

Zum Wiederherstellen mĂźssen Sie rsync einfach in umgekehrter Richtung ausfĂźhren und Docker neu starten, um die Volumes erneut zu lesen. FĂźhren Sie docker-compose pull und docker-compose up -d aus.

diff --git a/de/backup_restore/b_n_r-backup_restore-maildir/index.html b/de/backup_restore/b_n_r-backup_restore-maildir/index.html index dec056027..d9fb853a1 100644 --- a/de/backup_restore/b_n_r-backup_restore-maildir/index.html +++ b/de/backup_restore/b_n_r-backup_restore-maildir/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2412,15 +2412,15 @@

Sicherung

Diese Zeile sichert das vmail-Verzeichnis in eine Datei backup_vmail.tar.gz im mailcow-Root-Verzeichnis: -

cd /pfad/zu/mailcow-dockerized
+
cd /pfad/zu/mailcow-dockerized
 docker run --rm -i -v $(docker inspect --format '{{ range .Mounts }}{{ if eq .Destination "/var/vmail" }}{{ .Name }}{{ end }}{{{ end }}' $(docker-compose ps -q dovecot-mailcow)):/vmail -v ${PWD}:/backup debian:stretch-slim tar cvfz /backup/backup_vmail.tar.gz /vmail
-

+

Sie kÜnnen den Pfad ändern, indem Sie ${PWD} (das dem aktuellen Verzeichnis entspricht) an einen beliebigen Pfad anpassen, auf den Sie Schreibzugriff haben. Setzen Sie den Dateinamen backup_vmail.tar.gz auf einen beliebigen Namen, aber lassen Sie den Pfad so wie er ist. Beispiel: [...] tar cvfz /backup/mein_eigener_filename_.tar.gz

Wiederherstellen

-
cd /pfad/zu/mailcow-dockerized
+
cd /pfad/zu/mailcow-dockerized
 docker run --rm -it -v $(docker inspect --format '{{ range .Mounts }}{{ if eq .Destination "/var/vmail" }}{{ .Name }}{{ end }}{{ end }}' $(docker-compose ps -q dovecot-mailcow)):/vmail -v ${PWD}:/backup debian:stretch-slim tar xvfz /backup/backup_vmail.tar.gz
-
+

diff --git a/de/backup_restore/b_n_r-backup_restore-mysql/index.html b/de/backup_restore/b_n_r-backup_restore-mysql/index.html index a8e97879e..4f27bcc73 100644 --- a/de/backup_restore/b_n_r-backup_restore-mysql/index.html +++ b/de/backup_restore/b_n_r-backup_restore-mysql/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2411,20 +2411,20 @@

MySQL (mysqldump)

Sicherung

-
cd /pfad/zu/mailcow-dockerized
+
cd /pfad/zu/mailcow-dockerized
 source mailcow.conf
 DATE=$(Datum +"%Y%m%d_%H%M%S")
 docker-compose exec -T mysql-mailcow mysqldump --default-character-set=utf8mb4 -u${DBUSER} -p${DBPASS} ${DBNAME} > backup_${DBNAME}_${DATE}.sql
-
+

Wiederherstellen

Warning

Sie sollten den SQL-Dump ohne docker-compose umleiten, um Parsing-Fehler zu vermeiden.

-
cd /pfad/zu/mailcow-dockerized
+
cd /pfad/zu/mailcow-dockerized
 source mailcow.conf
 docker exec -i $(docker-compose ps -q mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} < backup_file.sql
-
+

diff --git a/de/backup_restore/b_n_r-coldstandby/index.html b/de/backup_restore/b_n_r-coldstandby/index.html index ac9fba846..b646f3db7 100644 --- a/de/backup_restore/b_n_r-coldstandby/index.html +++ b/de/backup_restore/b_n_r-coldstandby/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2459,10 +2459,10 @@

Sie benÜtigen ein SSH-fähiges Ziel und eine Schlßsseldatei, um sich mit diesem Ziel zu verbinden. Der Schlßssel sollte nicht durch ein Passwort geschßtzt sein, damit das Skript unbeaufsichtigt arbeiten kann.

In Ihrem mailcow-Basisverzeichnis, z.B. /opt/mailcow-dockerized, finden Sie eine Datei create_cold_standby.sh.

Bearbeiten Sie diese Datei und ändern Sie die exportierten Variablen:

-
export REMOTE_SSH_KEY=/pfad/zur/keyfile
+
export REMOTE_SSH_KEY=/pfad/zur/keyfile
 export REMOTE_SSH_PORT=22
 export REMOTE_SSH_HOST=mailcow-backup.host.name
-
+

Der SchlĂźssel muss im Besitz von root sein und darf nur von diesem gelesen werden kĂśnnen.

Sowohl die Quelle als auch das Ziel benĂśtigen rsync >= v3.1.0. Das Ziel muss Ăźber Docker und docker-compose v1 verfĂźgen.

@@ -2470,28 +2470,28 @@ Das Ziel muss Ăźber Docker und docker-compose v1 verfĂźgen.

Sie kĂśnnen die Verbindung testen, indem Sie ssh mailcow-backup.host.name -p22 -i /path/to/keyfile ausfĂźhren.

Backup und Aktualisierung des Cold-Standby

Starten Sie das erste Backup, dies kann je nach Verbindung eine Weile dauern:

-
bash /opt/mailcow-dockerized/create_cold_standby.sh
-
+
bash /opt/mailcow-dockerized/create_cold_standby.sh
+

Das war einfach, nicht wahr?

Das Aktualisieren des Cold-Standby ist genauso einfach:

-
bash /opt/mailcow-dockerized/create_cold_standby.sh
-
+
bash /opt/mailcow-dockerized/create_cold_standby.sh
+

Es ist derselbe Befehl.

Automatisierte Backups mit cron

Stellen Sie zunächst sicher, dass der cron Dienst aktiviert ist und läuft:

-
systemctl enable cron.service && systemctl start cron.service
-
+
systemctl enable cron.service && systemctl start cron.service
+

Um die Backups auf dem Cold-Standby-Server zu automatisieren, kĂśnnen Sie einen Cron-Job verwenden. Um die Cron-Jobs fĂźr den Root-Benutzer zu bearbeiten, fĂźhren Sie aus:

-
crontab -e
-
+
crontab -e
+

Fßgen Sie die folgenden Zeilen hinzu, um den Cold-Standby-Server täglich um 03:00 Uhr zu synchronisieren. In diesem Beispiel werden Fehler der letzten Ausfßhrung in einer Datei protokolliert.

-
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
 
 0 3 * * * bash /opt/mailcow-dockerized/create_cold_standby.sh 2> /var/log/mailcow-coldstandby-sync.log
-
+

Wenn korrekt gespeichert, sollte der Cron-Job durch Eingabe angezeigt werden:

-
crontab -l
-
+
crontab -l
+

diff --git a/de/backup_restore/b_n_r-restore/index.html b/de/backup_restore/b_n_r-restore/index.html index 28c255d25..84450690d 100644 --- a/de/backup_restore/b_n_r-restore/index.html +++ b/de/backup_restore/b_n_r-restore/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2399,9 +2399,9 @@

Wiederherstellung

Bitte kopieren Sie dieses Skript nicht an einen anderen Ort.

Um eine Wiederherstellung durchzufĂźhren, starten Sie mailcow, verwenden Sie das Skript mit "restore" als ersten Parameter.

-
# Syntax:
+
# Syntax:
 # ./helper-scripts/backup_and_restore.sh restore
-
+

Das Skript wird Sie nach einem Speicherort fĂźr die Sicherung der mailcow_DATE-Ordner fragen.


diff --git a/de/client/client-android/index.html b/de/client/client-android/index.html index 6c3604777..b143ab60d 100644 --- a/de/client/client-android/index.html +++ b/de/client/client-android/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/client/client-apple/index.html b/de/client/client-apple/index.html index 42b7e2828..9d5faf0df 100644 --- a/de/client/client-apple/index.html +++ b/de/client/client-apple/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/client/client-emclient/index.html b/de/client/client-emclient/index.html index 8adf273c2..e86b61214 100644 --- a/de/client/client-emclient/index.html +++ b/de/client/client-emclient/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/client/client-kontact/index.html b/de/client/client-kontact/index.html index 03908a7c9..a2b8d5947 100644 --- a/de/client/client-kontact/index.html +++ b/de/client/client-kontact/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/client/client-manual/index.html b/de/client/client-manual/index.html index 5517700eb..2a479f394 100644 --- a/de/client/client-manual/index.html +++ b/de/client/client-manual/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/client/client-outlook/index.html b/de/client/client-outlook/index.html index 346619777..1a03706df 100644 --- a/de/client/client-outlook/index.html +++ b/de/client/client-outlook/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/client/client-thunderbird/index.html b/de/client/client-thunderbird/index.html index 095f38b84..ee6ee6330 100644 --- a/de/client/client-thunderbird/index.html +++ b/de/client/client-thunderbird/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/client/client-windows/index.html b/de/client/client-windows/index.html index 9fe55bba9..40d752662 100644 --- a/de/client/client-windows/index.html +++ b/de/client/client-windows/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/client/client/index.html b/de/client/client/index.html index 6852dfda0..56cac1e4a 100644 --- a/de/client/client/index.html +++ b/de/client/client/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/i_u_m/i_u_m_deinstall/index.html b/de/i_u_m/i_u_m_deinstall/index.html index 003c482e8..5bb0819a6 100644 --- a/de/i_u_m/i_u_m_deinstall/index.html +++ b/de/i_u_m/i_u_m_deinstall/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2346,8 +2346,8 @@

Deinstallation

Um mailcow: dockerized mit all seinen Volumes, Images und Containern zu entfernen, tun Sie dies:

-
docker-compose down -v --rmi all --remove-orphans
-
+
docker-compose down -v --rmi all --remove-orphans
+

Info

    diff --git a/de/i_u_m/i_u_m_install/index.html b/de/i_u_m/i_u_m_install/index.html index b61c3367a..3d623b3d0 100644 --- a/de/i_u_m/i_u_m_install/index.html +++ b/de/i_u_m/i_u_m_install/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2351,10 +2351,10 @@
    • Docker -

      curl -sSL https://get.docker.com/ | CHANNEL=stable sh
      +
      curl -sSL https://get.docker.com/ | CHANNEL=stable sh
       # Nachdem der Installationsprozess abgeschlossen ist, mĂźssen Sie eventuell den Dienst aktivieren und sicherstellen, dass er gestartet ist (z. B. CentOS 7)
       systemctl enable --now docker
      -

      +

    • Docker-Compose

      @@ -2365,44 +2365,44 @@ systemctl enable --now docker

      mailcow benötigt die neueste Version von docker-compose v1. Es wird dringend empfohlen, die untenstehenden Befehle zu verwenden, um docker-compose zu installieren. Paket-Manager (z.B. apt, yum) werden wahrscheinlich nicht die richtige Version liefern. Hinweis: Dieser Befehl lädt docker-compose aus dem offiziellen Docker-Github-Repository herunter und ist eine sichere Methode. Das Snippet ermittelt die neueste unterstützte Version von mailcow. In fast allen Fällen ist dies die letzte verfügbare Version (Ausnahmen sind kaputte Versionen oder größere Änderungen, die noch nicht von mailcow unterstützt werden).

-
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
+
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
-
+

Bitte verwenden Sie die neueste verfĂźgbare Docker-Engine und nicht die Engine, die mit Ihrem Distros-Repository ausgeliefert wird.

1.1.1. Auf SELinux-aktivierten Systemen, z.B. CentOS 7:

  • PrĂźfen Sie, ob das Paket "container-selinux" auf Ihrem System vorhanden ist:
-
rpm -qa | grep container-selinux
-
+
rpm -qa | grep container-selinux
+

Wenn der obige Befehl eine leere oder keine Ausgabe liefert, sollten Sie es Ăźber Ihren Paketmanager installieren.

  • PrĂźfen Sie, ob Docker SELinux-UnterstĂźtzung aktiviert hat:
-
docker info | grep selinux
-
+
docker info | grep selinux
+

Wenn der obige Befehl eine leere oder keine Ausgabe liefert, erstellen oder bearbeiten Sie /etc/docker/daemon.json und fĂźgen Sie "selinux-enabled": true hinzu. Beispielhafter Inhalt der Datei:

-
{
+
{
   "selinux-enabled": true
 }
-
+

Starten Sie den Docker-Daemon neu und ĂźberprĂźfen Sie, ob SELinux nun aktiviert ist.

Dieser Schritt ist erforderlich, um sicherzustellen, dass die mailcows-Volumes richtig gekennzeichnet sind, wie in der Compose-Datei angegeben. Wenn Sie daran interessiert sind, wie das funktioniert, kĂśnnen Sie sich die Readme-Datei von https://github.com/containers/container-selinux ansehen, die auf viele nĂźtzliche Informationen zu diesem Thema verweist.

2. Klonen Sie den Master-Zweig des Repositorys und stellen Sie sicher, dass Ihre umask gleich 0022 ist. Bitte klonen Sie das Repository als root-Benutzer und kontrollieren Sie auch den Stack als root. Wir werden die Attribute - wenn nÜtig - ändern, während wir die Container automatisch bereitstellen und sicherstellen, dass alles gesichert ist. Das update.sh-Skript muss daher ebenfalls als root ausgefßhrt werden. Es kann notwendig sein, den Besitzer und andere Attribute von Dateien zu ändern, auf die Sie sonst keinen Zugriff haben. Wir geben die Berechtigungen fßr jede exponierte Anwendung auf und fßhren einen exponierten Dienst nicht als root aus! Wenn Sie den Docker-Daemon als Nicht-Root-Benutzer steuern, erhalten Sie keine zusätzliche Sicherheit. Der unprivilegierte Benutzer wird die Container ebenfalls als root spawnen. Das Verhalten des Stacks ist identisch.

-
$ su
+
$ su
 # umask
 0022 # <- Überprüfen, dass es 0022 ist
 # cd /opt
 # git clone https://github.com/mailcow/mailcow-dockerized
 # cd mailcow-dockerized
-
+

3. Erzeugen Sie eine Konfigurationsdatei. Verwenden Sie einen FQDN (host.domain.tld) als Hostname, wenn Sie gefragt werden. -

./generate_config.sh
-

+
./generate_config.sh
+

4. Ändern Sie die Konfiguration, wenn Sie das wollen oder müssen. -

nano mailcow.conf
-
+
nano mailcow.conf
+
Wenn Sie planen, einen Reverse Proxy zu verwenden, kĂśnnen Sie zum Beispiel HTTPS an 127.0.0.1 auf Port 8443 und HTTP an 127.0.0.1 auf Port 8080 binden.

MĂśglicherweise mĂźssen Sie einen vorinstallierten MTA stoppen, der Port 25/tcp blockiert. Siehe dieses Kapitel, um zu erfahren, wie man Postfix rekonfiguriert, um nach einer erfolgreichen Installation neben mailcow laufen zu lassen.

Einige Updates modifizieren mailcow.conf und fügen neue Parameter hinzu. Es ist schwer, in der Dokumentation den Überblick zu behalten. Bitte überprüfen Sie deren Beschreibung und fragen Sie, wenn Sie unsicher sind, in den bekannten Kanälen nach Rat.

@@ -2410,20 +2410,20 @@ Wenn Sie planen, einen Reverse Proxy zu verwenden, kĂśnnen Sie zum Beispiel HTTP

Wenn Sie auf Probleme und seltsame Phänomene stoßen, überprüfen Sie bitte Ihre MTU.

Bearbeiten Sie docker-compose.yml und ändern Sie die Netzwerkeinstellungen entsprechend Ihrer MTU. Fßgen Sie den neuen Parameter driver_opts wie folgt hinzu: -

networks:
+
networks:
   mailcow-network:
     ...
     driver_opts:
       com.docker.network.driver.mtu: 1450
     ...
-

+

4.2. Benutzer ohne ein IPv6-aktiviertes Netzwerk auf ihrem Hostsystem:

Einschalten von IPv6. Endlich.

Wenn Sie kein IPv6-fähiges Netzwerk auf Ihrem Host haben und Sie sich nicht um ein besseres Internet kßmmern (hehe), ist es empfehlenswert, IPv6 fßr das mailcow-Netzwerk zu deaktivieren, um unvorhergesehene Probleme zu vermeiden.

5. LAden Sie die Images herunter und fĂźhren Sie die Compose-Datei aus. Der Parameter -d wird mailcow: dockerized starten: -

docker-compose pull
+
docker-compose pull
 docker-compose up -d
-

+

Geschafft!

Sie kĂśnnen nun auf https://${MAILCOW_HOSTNAME} mit den Standard-Zugangsdaten admin + Passwort moohoo zugreifen.

diff --git a/de/i_u_m/i_u_m_migration/index.html b/de/i_u_m/i_u_m_migration/index.html index ff09b304f..a3efb612b 100644 --- a/de/i_u_m/i_u_m_migration/index.html +++ b/de/i_u_m/i_u_m_migration/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2359,43 +2359,43 @@ Installieren Sie Do
  • Docker -

    curl -sSL https://get.docker.com/ | CHANNEL=stable sh
    +
    curl -sSL https://get.docker.com/ | CHANNEL=stable sh
     # Nachdem der Installationsprozess abgeschlossen ist, mĂźssen Sie den Dienst aktivieren und sicherstellen, dass er gestartet ist (z. B. CentOS 7)
     systemctl enable docker.service
    -

    +

  • docker-compose -

    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
    +
    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
    -

    +

Bitte verwenden Sie die neueste verfĂźgbare Docker-Engine und nicht die Engine, die mit Ihrem Distros-Repository ausgeliefert wird.

2. Stoppen Sie Docker und stellen Sie sicher, dass Docker gestoppt wurde: -

systemctl stop docker.service
+
systemctl stop docker.service
 systemctl status docker.service
-

+

3. Führen Sie die folgenden Befehle auf dem Quellcomputer aus (achten Sie darauf, die abschließenden Schrägstriche im ersten Pfadparameter wie unten gezeigt hinzuzufügen!) - WARNUNG: Dieser Befehl löscht alles, was bereits unter /var/lib/docker/volumes auf dem Zielrechner existiert: -

rsync -aHhP --numeric-ids --delete /opt/mailcow-dockerized/ root@target-machine.example.com:/opt/mailcow-dockerized
+
rsync -aHhP --numeric-ids --delete /opt/mailcow-dockerized/ root@target-machine.example.com:/opt/mailcow-dockerized
 rsync -aHhP --numeric-ids --delete /var/lib/docker/volumes/ root@target-machine.example.com:/var/lib/docker/volumes
-

+

4. Schalten Sie mailcow ab und stoppen Sie Docker auf dem Quellrechner. -

cd /opt/mailcow-dockerized
+
cd /opt/mailcow-dockerized
 docker-compose herunterfahren
 systemctl stop docker.service
-

+

**Wiederholen Sie Schritt 3 mit denselben Befehlen. Dies wird viel schneller gehen als beim ersten Mal.

6. Wechseln Sie auf den Zielrechner und starten Sie Docker. -

systemctl start docker.service
-

+
systemctl start docker.service
+

7. Ziehen Sie nun die mailcow Docker-Images auf den Zielrechner. -

cd /opt/mailcow-dockerized
+
cd /opt/mailcow-dockerized
 docker-compose pull
-

+

8. Starten Sie den gesamten mailcow-Stack und alles sollte fertig sein! -

docker-compose up -d
-

+
docker-compose up -d
+

9. Zum Schluss ändern Sie Ihre DNS-Einstellungen so, dass sie auf den Zielserver zeigen.


diff --git a/de/i_u_m/i_u_m_update/index.html b/de/i_u_m/i_u_m_update/index.html index 2805d2bdc..7f5960065 100644 --- a/de/i_u_m/i_u_m_update/index.html +++ b/de/i_u_m/i_u_m_update/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2480,13 +2480,13 @@

Ein Update-Skript in Ihrem mailcow-dockerized Verzeichnis kĂźmmert sich um Updates.

Aber benutzen Sie es mit Bedacht! Wenn Sie denken, dass Sie viele Änderungen am mailcow-Code vorgenommen haben, sollten Sie die manuelle Update-Anleitung unten verwenden.

FĂźhren sie das Update-Skript aus: -

./update.sh
-

+
./update.sh
+

Wenn es nĂśtig ist, wird es Sie fragen, wie Sie fortfahren mĂśchten. Merge-Fehler werden gemeldet. Einige kleinere Konflikte werden automatisch korrigiert (zugunsten des mailcow: dockerized repository code).

Optionen

-
# Optionen kĂśnnen kombiniert werden
+
# Optionen kĂśnnen kombiniert werden
 
 # - Prüft auf Updates und zeigt Änderungen an
 ./update.sh --check
@@ -2509,22 +2509,22 @@ Einige kleinere Konflikte werden automatisch korrigiert (zugunsten des mailcow:
 
 # - Nicht aktualisieren, nur holen von Docker Images
 ./update.sh --prefetch
-
+

Ich habe vergessen, was ich vor dem Ausfßhren von update.sh geändert habe.

Siehe git log --pretty=oneline | grep -i "before update", Sie werden eine Ausgabe ähnlich dieser haben:

-
22cd00b5e28893ef9ddef3c2b5436453cc5223ab Before update on 2020-09-28_19_25_45
+
22cd00b5e28893ef9ddef3c2b5436453cc5223ab Before update on 2020-09-28_19_25_45
 dacd4fb9b51e9e1c8a37d84485b92ffaf6c59353 Before update on 2020-08-07_13_31_31
-
+

Fßhren Sie git diff 22cd00b5e28893ef9ddef3c2b5436453cc5223ab aus, um zu sehen, was sich geändert hat.

Kann ich ein Rollback durchfĂźhren?

Ja.

Siehe das obige Thema, anstelle eines Diffs fĂźhren Sie checkout aus:

-
docker-compose down
+
docker-compose down
 # Ersetzen Sie die Commit-ID 22cd00b5e28893ef9ddef3c2b5436453cc5223ab durch Ihre ID
 git checkout 22cd00b5e28893ef9ddef3c2b5436453cc5223ab
 docker-compose pull
 docker-compose up -d
-
+

Hooks

Sie kĂśnnen sich in den Update-Mechanismus einklinken, indem Sie Skripte namens pre_commit_hook.sh und post_commit_hook.sh zu Ihrem mailcows-Root-Verzeichnis hinzufĂźgen. Siehe hier fĂźr weitere Details.

Fußnoten

diff --git a/de/index.html b/de/index.html index 983e846e1..cd42d1fdf 100644 --- a/de/index.html +++ b/de/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/manual-guides/ClamAV/u_e-clamav-additional_dbs/index.html b/de/manual-guides/ClamAV/u_e-clamav-additional_dbs/index.html index d98442006..680d1dde9 100644 --- a/de/manual-guides/ClamAV/u_e-clamav-additional_dbs/index.html +++ b/de/manual-guides/ClamAV/u_e-clamav-additional_dbs/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2466,21 +2466,21 @@
  • Sie brauchen your_id von den Downloadlinks. Diese sind pro User individuell.
  • FĂźgen Sie diese wie folgt in die data/conf/clamav/freshclam.conf ein und ersetzen Sie den your_id Teil mit Ihrer ID: -

    DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfo.hdb
    +
    DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfo.hdb
     DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfo.ign2
     DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/javascript.ndb
     DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/spam_marketing.ndb
     DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfohtml.hdb
     DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfoascii.hdb
     DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfopdf.hdb
    -

    +

  • Bei den kostenlosen SecuriteInfo Datenbanken ist die Download-Geschwindigkeit auf 300 kB/s begrenzt. Ändern Sie in data/conf/clamav/freshclam.conf den Standardwert ReceiveTimeout 20 auf ReceiveTimeout 90 (Zeitangabe in Sekunden), da ansonsten einige der Datenbank-Downloads aufgrund ihrer Größe abbrechen kĂśnnen.

  • Passen Sie data/conf/clamav/clamd.conf mit den folgenden Einstellungen an: -

    DetectPUA yes
    +
    DetectPUA yes
     ExcludePUA PUA.Win.Packer
     ExcludePUA PUA.Win.Trojan.Packed
     ExcludePUA PUA.Win.Trojan.Molebox
    @@ -2493,11 +2493,11 @@ MaxEmbeddedPE 100M
     MaxHTMLNormalize 50M
     MaxScriptNormalize 50M
     MaxZipTypeRcg 50M
    -

    +

  • Starten Sie den ClamAV Container neu: -
    docker-compose restart clamd-mailcow
    -
  • +
    docker-compose restart clamd-mailcow
    +

    Bitte beachten Sie:

      @@ -2509,14 +2509,14 @@ MaxZipTypeRcg 50M

      InterServer Datenbanken aktivieren

      1. FĂźgen Sie folgendes in data/conf/clamav/freshclam.conf ein: -
        DatabaseCustomURL http://sigs.interserver.net/interserver256.hdb
        +
        DatabaseCustomURL http://sigs.interserver.net/interserver256.hdb
         DatabaseCustomURL http://sigs.interserver.net/interservertopline.db
         DatabaseCustomURL http://sigs.interserver.net/shell.ldb
         DatabaseCustomURL http://sigs.interserver.net/whitelist.fp
        -
      2. +
  • Starten Sie den ClamAV Container neu: -
    docker-compose restart clamd-mailcow
    -
  • +
    docker-compose restart clamd-mailcow
    +

    diff --git a/de/manual-guides/ClamAV/u_e-clamav-whitelist/index.html b/de/manual-guides/ClamAV/u_e-clamav-whitelist/index.html index e8fc0b105..0951c35dc 100644 --- a/de/manual-guides/ClamAV/u_e-clamav-whitelist/index.html +++ b/de/manual-guides/ClamAV/u_e-clamav-whitelist/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2398,22 +2398,22 @@

    Whitelist fĂźr bestimmte ClamAV-Signaturen

    Es kann vorkommen, dass legitime (saubere) Mails von ClamAV blockiert werden (Rspamd markiert die Mail mit VIRUS_FOUND). So werden beispielsweise interaktive PDF-Formularanhänge standardmäßig blockiert, da der eingebettete Javascript-Code für schädliche Zwecke verwendet werden könnte. Überprüfen Sie dies anhand der clamd-Protokolle, z.B.:

    -
    docker-compose logs clamd-mailcow | grep "FOUND"
    -
    +
    docker-compose logs clamd-mailcow | grep "FOUND"
    +

    Diese Zeile bestätigt, dass ein solcher identifiziert wurde:

    -
    clamd-mailcow_1 | Sat Sep 28 07:43:24 2019 -> instream(local): PUA.Pdf.Trojan.EmbeddedJavaScript-1(e887d2ac324ce90750768b86b63d0749:363325) FOUND
    -
    +
    clamd-mailcow_1 | Sat Sep 28 07:43:24 2019 -> instream(local): PUA.Pdf.Trojan.EmbeddedJavaScript-1(e887d2ac324ce90750768b86b63d0749:363325) FOUND
    +

    Um diese spezielle Signatur auf die Whitelist zu setzen (und den Versand dieses Dateityps im Anhang zu ermĂśglichen), fĂźgen Sie sie der ClamAV-Signatur-Whitelist-Datei hinzu:

    -
    echo 'PUA.Pdf.Trojan.EmbeddedJavaScript-1' >> data/conf/clamav/whitelist.ign2
    -
    +
    echo 'PUA.Pdf.Trojan.EmbeddedJavaScript-1' >> data/conf/clamav/whitelist.ign2
    +

    Dann starten Sie den clamd-mailcow Service Container in der mailcow UI oder mit docker-compose neu:

    -
    docker-compose restart clamd-mailcow
    -
    +
    docker-compose restart clamd-mailcow
    +

    Bereinigen Sie zwischengespeicherte ClamAV-Ergebnisse in Redis:

    -
    # docker-compose exec redis-mailcow /bin/sh
    +
    # docker-compose exec redis-mailcow /bin/sh
     /data # redis-cli KEYS rs_cl* | xargs redis-cli DEL
     /data # exit
    -
    +

    diff --git a/de/manual-guides/Docker/u_e-docker-cust_dockerfiles/index.html b/de/manual-guides/Docker/u_e-docker-cust_dockerfiles/index.html index e149f5b1d..4e8a4161a 100644 --- a/de/manual-guides/Docker/u_e-docker-cust_dockerfiles/index.html +++ b/de/manual-guides/Docker/u_e-docker-cust_dockerfiles/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,14 +2348,14 @@

    Dockerfiles anpassen

    Sie mĂźssen die Override-Datei mit den entsprechenden Build-Tags in den mailcow: dockerized Root-Ordner (d.h. /opt/mailcow-dockerized) kopieren:

    -
    cp helper-scripts/docker-compose.override.yml.d/BUILD_FLAGS/docker-compose.override.yml docker-compose.override.yml
    -
    +
    cp helper-scripts/docker-compose.override.yml.d/BUILD_FLAGS/docker-compose.override.yml docker-compose.override.yml
    +

    Nehmen Sie Ihre Änderungen in data/Dockerfiles/$service vor und erstellen Sie das Image lokal:

    -
    docker build data/Dockerfiles/service -t mailcow/$service
    -
    +
    docker build data/Dockerfiles/service -t mailcow/$service
    +

    Nun werden die geänderten Container automatisch neu erstellt:

    -
    docker-compose up -d
    -
    +
    docker-compose up -d
    +

    diff --git a/de/manual-guides/Docker/u_e-docker-dc_bash_compl/index.html b/de/manual-guides/Docker/u_e-docker-dc_bash_compl/index.html index 49142112c..98e01a2b7 100644 --- a/de/manual-guides/Docker/u_e-docker-dc_bash_compl/index.html +++ b/de/manual-guides/Docker/u_e-docker-dc_bash_compl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,8 +2348,8 @@

    Docker Compose Bash Completion

    Um eine schÜne Bash-Vervollständigung in Ihren Containern zu erhalten, fßhren Sie einfach das Folgende aus:

    -
    curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
    -
    +
    curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
    +

    diff --git a/de/manual-guides/Dovecot/u_e-dovecot-any_acl/index.html b/de/manual-guides/Dovecot/u_e-dovecot-any_acl/index.html index 83f9526d8..6c96f082e 100644 --- a/de/manual-guides/Dovecot/u_e-dovecot-any_acl/index.html +++ b/de/manual-guides/Dovecot/u_e-dovecot-any_acl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,8 +2349,8 @@

    Am 17. August haben wir die Möglichkeit, mit "jedem" oder "allen authentifizierten Benutzern" zu teilen, standardmäßig deaktiviert.

    Diese Funktion kann wieder aktiviert werden, indem ACL_ANYONE auf allow in mailcow.conf gesetzt wird:

    -
    ACL_ANYONE=allow
    -
    +
    ACL_ANYONE=allow
    +

    Wenden Sie die Änderungen an, indem Sie docker-compose up -d ausführen.


    diff --git a/de/manual-guides/Dovecot/u_e-dovecot-catchall_vacation/index.html b/de/manual-guides/Dovecot/u_e-dovecot-catchall_vacation/index.html index da35c52d0..b14f0e2e4 100644 --- a/de/manual-guides/Dovecot/u_e-dovecot-catchall_vacation/index.html +++ b/de/manual-guides/Dovecot/u_e-dovecot-catchall_vacation/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/manual-guides/Dovecot/u_e-dovecot-expunge/index.html b/de/manual-guides/Dovecot/u_e-dovecot-expunge/index.html index 150ac3f32..03d53fdd1 100644 --- a/de/manual-guides/Dovecot/u_e-dovecot-expunge/index.html +++ b/de/manual-guides/Dovecot/u_e-dovecot-expunge/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2454,17 +2454,17 @@

    Der manuelle Weg

    Dann wollen wir mal loslegen:

    LÜschen Sie die Mails eines Benutzers im Junk-Ordner, die gelesen und älter als 4 Stunden sind

    -
    docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'Junk' SEEN not SINCE 4h
    -
    +
    docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'Junk' SEEN not SINCE 4h
    +

    LÜsche alle Mails des Benutzers im Junk-Ordner, die älter als 7 Tage sind

    -
    docker-compose exec dovecot-mailcow doveadm expunge -A mailbox 'Junk' savedbefore 7d
    -
    +
    docker-compose exec dovecot-mailcow doveadm expunge -A mailbox 'Junk' savedbefore 7d
    +

    LÜscht alle Mails (aller Benutzer) in allen Ordnern, die älter als 52 Wochen sind (internes Datum der Mail, nicht das Datum, an dem sie auf dem System gespeichert wurde => before statt savedbefore). Nßtzlich zum LÜschen sehr alter Mails in allen Benutzern und Ordnern (daher besonders nßtzlich fßr GDPR-Compliance).

    -
    docker-compose exec dovecot-mailcow doveadm expunge -A mailbox % before 52w
    -
    +
    docker-compose exec dovecot-mailcow doveadm expunge -A mailbox % before 52w
    +

    LÜschen von Mails in einem benutzerdefinierten Ordner innerhalb des Posteingangs eines Benutzers, die nicht gekennzeichnet und älter als 2 Wochen sind

    -
    docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'INBOX/custom-folder' not FLAGGED not SINCE 2w
    -
    +
    docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'INBOX/custom-folder' not FLAGGED not SINCE 2w
    +

    Info

    FĂźr mĂśgliche Zeitspannen oder SearchQuery schauen Sie bitte in man doveadm-search-query

    @@ -2472,21 +2472,21 @@

    Job-Scheduler

    Ăźber das Host-System cron

    Wenn Sie eine solche Aufgabe automatisieren wollen, kĂśnnen Sie einen Cron-Job auf Ihrem Rechner erstellen, der ein Skript wie das folgende aufruft:

    -
    #!/bin/bash
    +
    #!/bin/bash
     # Pfad zu mailcow-dockerized, z.B. /opt/mailcow-dockerized
     cd /pfad/zu/ihrem/mailcow-dockerized
     
     /usr/local/bin/docker-compose exec -T dovecot-mailcow doveadm expunge -A mailbox 'Junk' savedbefore 2w
     /usr/local/bin/docker-compose exec -T dovecot-mailcow doveadm expunge -A mailbox 'Junk' SEEN not SINCE 12h
     [...]
    -
    +

    Um einen Cronjob zu erstellen, kĂśnnen Sie crontab -e ausfĂźhren und etwas wie das Folgende einfĂźgen, um ein Skript auszufĂźhren:

    -
    # Jeden Tag um 04:00 Uhr morgens ausfĂźhren.
    +
    # Jeden Tag um 04:00 Uhr morgens ausfĂźhren.
     0 4 * * * /pfad/zu/ihr/expunge_mailboxes.sh
    -
    +

    Ăźber Docker Job Scheduler

    Um dies mit einem Docker-Job-Scheduler zu archivieren, verwenden Sie diese docker-compose.override.yml mit Ihrer Mailcow:

    -
    version: '2.1'
    +
    version: '2.1'
     
     services:
     
    @@ -2504,12 +2504,12 @@ services:
           - "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"
    -
    +

    Der Job-Controller braucht nur Zugriff auf den Docker Control Socket, um das Verhalten von "exec" zu emulieren. Dann fßgen wir unserem Dovecot-Container ein paar Labels hinzu, um den Job-Scheduler zu aktivieren und ihm in einem Cron-kompatiblen Scheduling-Format mitzuteilen, wann er laufen soll. Wenn Sie Probleme mit dem Scheduling-String haben, kÜnnen Sie crontab guru verwenden. Diese docker-compose.override.yml lÜscht jeden Tag um 4 Uhr morgens alle Mails, die älter als 2 Wochen sind, aus dem Ordner "Junk". Um zu sehen, ob alles richtig gelaufen ist, kÜnnen Sie nicht nur in Ihrer Mailbox nachsehen, sondern auch im Docker-Log von Ofelia, ob es etwa so aussieht:

    -
    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)] 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,
    -
    +

    Wenn der Vorgang fehlgeschlagen ist, wird dies angegeben und die Ausgabe von doveadm im Protokoll aufgefĂźhrt, um Ihnen die Fehlersuche zu erleichtern.

    Falls Sie weitere Jobs hinzufßgen wollen, stellen Sie sicher, dass Sie den "dovecot-expunge-trash"-Teil nach "ofelia.job-exec." in etwas anderes ändern, er definiert den Namen des Jobs. Die Syntax der Labels finden Sie unter mcuadros/ofelia.

    diff --git a/de/manual-guides/Dovecot/u_e-dovecot-extra_conf/index.html b/de/manual-guides/Dovecot/u_e-dovecot-extra_conf/index.html index cd4509dd2..e4b4e3b7f 100644 --- a/de/manual-guides/Dovecot/u_e-dovecot-extra_conf/index.html +++ b/de/manual-guides/Dovecot/u_e-dovecot-extra_conf/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,8 +2349,8 @@

    Erstellen Sie eine Datei data/conf/dovecot/extra.conf - falls nicht vorhanden - und fßgen Sie Ihren zusätzlichen Inhalt hier ein.

    Starten Sie dovecot-mailcow neu, um Ihre Änderungen zu übernehmen:

    -
    docker-compose restart dovecot-mailcow
    -
    +
    docker-compose restart dovecot-mailcow
    +

    diff --git a/de/manual-guides/Dovecot/u_e-dovecot-fts/index.html b/de/manual-guides/Dovecot/u_e-dovecot-fts/index.html index 1c3c3b527..2290f508d 100644 --- a/de/manual-guides/Dovecot/u_e-dovecot-fts/index.html +++ b/de/manual-guides/Dovecot/u_e-dovecot-fts/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2443,19 +2443,19 @@

    Die Standard-Heap-Größe (1024 M) ist in mailcow.conf definiert.

    Da wir in Docker laufen und unsere Container mit dem "restart: always" Flag erstellen, wird eine oom Situation zumindest nur einen Neustart des Containers auslĂśsen.

    FTS-bezogene Dovecot-Befehle

    -

    # Einzelbenutzer
    +

    # Einzelbenutzer
     docker-compose exec dovecot-mailcow doveadm fts rescan -u user@domain
     # alle Benutzer
     docker-compose exec dovecot-mailcow doveadm fts rescan -A
    -
    +
    Dovecot Wiki: "Scannt, welche Mails im Volltextsuchindex vorhanden sind und vergleicht diese mit den tatsächlich in den Postfächern vorhandenen Mails. Dies entfernt Mails aus dem Index, die bereits gelÜscht wurden und stellt sicher, dass der nächste doveadm-Index alle fehlenden Mails (falls vorhanden) indiziert."

    Dies indiziert nicht eine Mailbox neu. Es repariert im Grunde einen gegebenen Index.

    Wenn Sie die Daten sofort neu indizieren wollen, kĂśnnen Sie den folgenden Befehl ausfĂźhren, wobei '*' auch eine Postfachmaske wie 'Sent' sein kann. Sie mĂźssen diese Befehle nicht ausfĂźhren, aber es wird die Dinge ein wenig beschleunigen:

    -
    # einzelner Benutzer
    +
    # einzelner Benutzer
     docker-compose exec dovecot-mailcow doveadm index -u user@domain '*'
     # alle Benutzer, aber offensichtlich langsamer und gefährlicher
     docker-compose exec dovecot-mailcow doveadm index -A '*'
    -
    +

    Dies wird einige Zeit in Anspruch nehmen, abhängig von Ihrer Maschine und Solr kann oom ausfßhren, ßberwachen Sie es!

    Da die Neuindizierung sehr sinnvoll ist, haben wir sie nicht in die mailcow UI integriert. Sie mĂźssen sich um eventuelle Fehler beim Re-Indizieren einer Mailbox kĂźmmern.

    LĂśschen der Mailbox-Daten

    diff --git a/de/manual-guides/Dovecot/u_e-dovecot-idle_interval/index.html b/de/manual-guides/Dovecot/u_e-dovecot-idle_interval/index.html index 0342e863b..e7683dca4 100644 --- a/de/manual-guides/Dovecot/u_e-dovecot-idle_interval/index.html +++ b/de/manual-guides/Dovecot/u_e-dovecot-idle_interval/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2462,8 +2462,8 @@

    Konfiguration ändern

    Erstellen Sie eine neue Datei data/conf/dovecot/extra.conf (oder bearbeiten Sie sie, falls sie bereits existiert). FĂźgen Sie die Einstellung ein, gefolgt von dem neuen Wert. Um zum Beispiel das Intervall auf 5 Minuten zu setzen, kĂśnnen Sie Folgendes eingeben:

    -
    imap_idle_notify_interval = 5 mins
    -
    +
    imap_idle_notify_interval = 5 mins
    +

    29 Minuten ist der maximale Wert, den der entsprechende RFC erlaubt.

    Warning

    @@ -2471,13 +2471,13 @@ FĂźgen Sie die Einstellung ein, gefolgt von dem neuen Wert. Um zum Beispiel das

    Dovecot neu laden

    Nun laden Sie Dovecot neu:

    -
    docker-compose exec dovecot-mailcow dovecot reload
    -
    +
    docker-compose exec dovecot-mailcow dovecot reload
    +

    Info

    Sie kĂśnnen den Wert dieser Einstellung ĂźberprĂźfen mit -

    docker-compose exec dovecot-mailcow dovecot -a | grep "imap_idle_notify_interval"
    -
    +
    docker-compose exec dovecot-mailcow dovecot -a | grep "imap_idle_notify_interval"
    +
    Wenn Sie den Wert nicht geändert haben, sollte er auf 2m stehen. Wenn Sie ihn geändert haben, sollten Sie den neuen Wert sehen.

    diff --git a/de/manual-guides/Dovecot/u_e-dovecot-mail-crypt/index.html b/de/manual-guides/Dovecot/u_e-dovecot-mail-crypt/index.html index a4ac82ed2..612230934 100644 --- a/de/manual-guides/Dovecot/u_e-dovecot-mail-crypt/index.html +++ b/de/manual-guides/Dovecot/u_e-dovecot-mail-crypt/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2350,7 +2350,7 @@

    Die Mails werden komprimiert (lz4) und verschlĂźsselt gespeichert. Das SchlĂźsselpaar ist in crypt-vol-1 zu finden.

    Wenn Sie vorhandene maildir-Dateien entschlĂźsseln/verschlĂźsseln wollen, kĂśnnen Sie das folgende Skript auf eigene Gefahr verwenden:

    Rufen Sie Dovecot auf, indem Sie docker-compose exec dovecot-mailcow /bin/bash im mailcow-dockerisierten Verzeichnis ausfĂźhren.

    -
    # EntschlĂźsseln Sie /var/vmail
    +
    # EntschlĂźsseln Sie /var/vmail
     find /var/vmail/ -type f -regextype egrep -regex '.*S=.*W=.*' | while read -r file; do
     if [[ $(head -c7 "$file") == "CRYPTED" ]]; then
     doveadm fs get compress lz4:0:crypt:private_key_path=/mail_crypt/ecprivkey.pem:public_key_path=/mail_crypt/ecpubkey.pem:posix:prefix=/ \
    @@ -2375,7 +2375,7 @@ doveadm fs put crypt private_key_path=/mail_crypt/ecprivkey.pem:public_key_path=
       chown 5000:5000 "$file"
     fi
     done
    -
    +

    diff --git a/de/manual-guides/Dovecot/u_e-dovecot-more/index.html b/de/manual-guides/Dovecot/u_e-dovecot-more/index.html index bb557fe52..6f07c61eb 100644 --- a/de/manual-guides/Dovecot/u_e-dovecot-more/index.html +++ b/de/manual-guides/Dovecot/u_e-dovecot-more/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2414,25 +2414,25 @@

    doveadm quota

    Die Befehle quota get und quota recalc1 werden verwendet, um die Quota-Nutzung des aktuellen Benutzers anzuzeigen oder neu zu berechnen. Die angezeigten Werte sind in Kilobytes.

    Um den aktuellen Quota-Status fĂźr einen Benutzer / eine Mailbox aufzulisten, tun Sie folgendes:

    -
    doveadm quota get -u 'mailbox@example.org'
    -
    +
    doveadm quota get -u 'mailbox@example.org'
    +

    Um den Quota-Speicherwert fĂźr alle Benutzer aufzulisten, tun Sie folgendes:

    -
    doveadm quota get -A |grep "STORAGE"
    -
    +
    doveadm quota get -A |grep "STORAGE"
    +

    Berechnen Sie die Quota-Nutzung eines einzelnen Benutzers neu:

    -
    doveadm quota recalc -u 'mailbox@example.org'
    -
    +
    doveadm quota recalc -u 'mailbox@example.org'
    +

    Der Befehl doveadm search2 wird verwendet, um Nachrichten zu finden, die Ihrer Anfrage entsprechen. Er kann den Benutzernamen, die Mailbox-GUID / -UID und die Nachrichten-GUIDs / -UIDs zurĂźckgeben.

    Um die Anzahl der Nachrichten im .Trash Ordner eines Benutzers zu sehen:

    -
    doveadm search -A mailbox 'Trash' | awk '{print $1}' | sort | uniq -c
    -
    +
    doveadm search -A mailbox 'Trash' | awk '{print $1}' | sort | uniq -c
    +

    Alle Nachrichten im Postfach eines Benutzers anzeigen, die älter als 90 Tage sind:

    -
    doveadm search -u 'mailbox@example.org' mailbox 'INBOX' savedbefore 90d
    -
    +
    doveadm search -u 'mailbox@example.org' mailbox 'INBOX' savedbefore 90d
    +

    Zeige alle Nachrichten in beliebigen Ordnern, die älter sind als 30 Tage fßr mailbox@example.org:

    -
    doveadm search -u 'mailbox@example.org' mailbox "*" savedbefore 30d
    -
    +
    doveadm search -u 'mailbox@example.org' mailbox "*" savedbefore 30d
    +

      diff --git a/de/manual-guides/Dovecot/u_e-dovecot-public_folder/index.html b/de/manual-guides/Dovecot/u_e-dovecot-public_folder/index.html index 62c383f74..0dc47de77 100644 --- a/de/manual-guides/Dovecot/u_e-dovecot-public_folder/index.html +++ b/de/manual-guides/Dovecot/u_e-dovecot-public_folder/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2398,7 +2398,7 @@

      Erstellen Sie einen neuen Ăśffentlichen Namespace "Public" und eine Mailbox "Develcow" innerhalb dieses Namespaces:

      Bearbeiten oder erstellen Sie data/conf/dovecot/extra.conf, fĂźgen Sie hinzu:

      -
      namespace {
      +
      namespace {
         type = public
         separator = /
         prefix = Public/
      @@ -2408,18 +2408,18 @@
           auto = subscribe
         }
       }
      -
      +

      :INDEXPVT=~/public kann weggelassen werden, wenn die Flags, die pro Benutzer gesehen werden, nicht gewĂźnscht sind.

      Die neue Mailbox im Ăśffentlichen Namensraum wird von den Benutzern automatisch abonniert.

      Um allen authentifizierten Benutzern vollen Zugriff auf das neue Postfach (nicht auf den gesamten Namespace) zu gewähren, fßhren Sie aus:

      -
      docker-compose exec dovecot-mailcow doveadm acl set -A "Public/Develcow" "authenticated" lookup read write write-seen write-deleted insert post delete expunge create
      -
      +
      docker-compose exec dovecot-mailcow doveadm acl set -A "Public/Develcow" "authenticated" lookup read write write-seen write-deleted insert post delete expunge create
      +

      Passen Sie den Befehl an Ihre BedĂźrfnisse an, wenn Sie detailliertere Rechte pro Benutzer vergeben mĂśchten (verwenden Sie z.B. -u user@domain anstelle von -A).

      Erlaube authentifizierten Benutzern den Zugriff auf den gesamten Ăśffentlichen Namespace

      Um allen authentifizierten Benutzern vollen Zugriff auf den gesamten Üffentlichen Namespace und seine Unterordner zu gewähren, erstellen Sie eine neue Datei dovecot-acl im Namespace-Stammverzeichnis:

      Öffnen/bearbeiten/erstellen Sie /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/public/dovecot-acl (passen Sie den Pfad entsprechend an), um die globale ACL-Datei mit dem folgenden Inhalt zu erstellen:

      -
      authenticated kxeilprwts
      -
      +
      authenticated kxeilprwts
      +

      kxeilprwts" ist gleichbedeutend mit "lookup read write write-seen write-deleted insert post delete expunge create".

      Sie kÜnnen doveadm acl set -u user@domain "Public/Develcow" user=user@domain lookup read verwenden, um den Zugriff fßr einen einzelnen Benutzer zu beschränken. Sie kÜnnen es auch umdrehen und den Zugriff fßr alle Benutzer auf "lr" beschränken und nur einigen Benutzern vollen Zugriff gewähren.

      Siehe Dovecot ACL fĂźr weitere Informationen Ăźber ACL.

      diff --git a/de/manual-guides/Dovecot/u_e-dovecot-static_master/index.html b/de/manual-guides/Dovecot/u_e-dovecot-static_master/index.html index 3c74408a3..2865c3f92 100644 --- a/de/manual-guides/Dovecot/u_e-dovecot-static_master/index.html +++ b/de/manual-guides/Dovecot/u_e-dovecot-static_master/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2351,9 +2351,9 @@

      Das wird empfohlen und sollte nicht geändert werden.

      Wenn der Benutzer trotzdem statisch sein soll, geben Sie bitte zwei Variablen in mailcow.conf an.

      Beide Parameter dĂźrfen nicht leer sein!

      -
      DOVECOT_MASTER_USER=mymasteruser
      +
      DOVECOT_MASTER_USER=mymasteruser
       DOVECOT_MASTER_PASS=mysecretpass
      -
      +

      Führen Sie docker-compose up -d aus, um Ihre Änderungen zu übernehmen.

      Der statische Master-Benutzername wird zu DOVECOT_MASTER_USER@mailcow.local erweitert.

      Um sich als test@example.org anzumelden, wĂźrde dies test@example.org*mymasteruser@mailcow.local mit dem oben angegebenen Passwort entsprechen.

      diff --git a/de/manual-guides/Dovecot/u_e-dovecot-vmail-volume/index.html b/de/manual-guides/Dovecot/u_e-dovecot-vmail-volume/index.html index df63172fb..1abf5abc6 100644 --- a/de/manual-guides/Dovecot/u_e-dovecot-vmail-volume/index.html +++ b/de/manual-guides/Dovecot/u_e-dovecot-vmail-volume/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2442,26 +2442,26 @@

      Neuere Docker-Versionen scheinen sich ßber bestehende Volumes zu beschweren. Man kann dies vorßbergehend beheben, indem man das bestehende Volume entfernt und mailcow mit der Override-Datei startet. Aber es scheint nach einem Neustart problematisch zu sein (muss bestätigt werden).

    Ein einfacher, schmutziger, aber stabiler Workaround ist es, mailcow zu stoppen (docker-compose down), /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data zu entfernen und einen neuen Link zu Ihrem entfernten Dateisystem zu erstellen, zum Beispiel:

    -
    mv /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data_backup
    +
    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
    -
    +

    Starten Sie anschließend mailcow.


    Der "alte" Weg

    Wenn man einen anderen Ordner fĂźr das vmail-Volume verwenden mĂśchte, kann man eine docker-compose.override.yml Datei erstellen und den folgenden Inhalt hinzufĂźgen:

    -
    version: '2.1'
    +
    version: '2.1'
     volumes:
       vmail-vol-1:
         driver_opts:
           type: none
           device: /data/mailcow/vmail   
           o: bind
    -
    +

    Verschieben eines bestehenden vmail-Ordners:

    • Finden Sie den aktuellen vmail-Ordner anhand seines "Mountpoint"-Attributs: docker volume inspect mailcowdockerized_vmail-vol-1
    -
    [
    +
    [
         {
             "CreatedAt": "2019-06-16T22:08:34+02:00",
             "Driver": "local",
    @@ -2476,7 +2476,7 @@ volumes:
             "Scope": "local"
         }
     ]
    -
    +
    • Kopieren Sie den Inhalt des Mountpoint-Ordners an den neuen Speicherort (z.B. /data/mailcow/vmail) mit cp -a, rsync -a oder einem ähnlichen, nicht strikten Kopierbefehl
    • Stoppen Sie mailcow durch AusfĂźhren von docker-compose down aus Ihrem mailcow-Stammverzeichnis (z.B. /opt/mailcow-dockerized)
    • diff --git a/de/manual-guides/Nginx/u_e-nginx_custom/index.html b/de/manual-guides/Nginx/u_e-nginx_custom/index.html index f5f9b7ec9..2c0419a1c 100644 --- a/de/manual-guides/Nginx/u_e-nginx_custom/index.html +++ b/de/manual-guides/Nginx/u_e-nginx_custom/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2444,9 +2444,9 @@

      Neue Website

      Um persistente (Ăźber Updates) Sites zu erstellen, die von mailcow: dockerized gehostet werden, muss eine neue Site-Konfiguration in data/conf/nginx/ platziert werden:

      Eine gute Vorlage, um damit zu beginnen:

      -
      nano data/conf/nginx/my_custom_site.conf
      -
      -
      server {
      +
      nano data/conf/nginx/my_custom_site.conf
      +
      +
      server {
         ssl_certificate /etc/ssl/mail/cert.pem;
         ssl_certificate_key /etc/ssl/mail/key.pem;
         ssl_protocols TLSv1.2 TLSv1.3;
      @@ -2478,12 +2478,12 @@
           return 301 https://$server_name$request_uri;
         }
       }
      -
      +

      Neue Website mit Proxy zu einem entfernten Location

      Ein weiteres Beispiel mit einer Reverse-Proxy-Konfiguration:

      -
      nano data/conf/nginx/my_custom_site.conf
      -
      -
      server {
      +
      nano data/conf/nginx/my_custom_site.conf
      +
      +
      server {
         ssl_certificate /etc/ssl/mail/cert.pem;
         ssl_certificate_key /etc/ssl/mail/key.pem;
         ssl_protocols TLSv1.2 TLSv1.3;
      @@ -2519,18 +2519,18 @@
           client_max_body_size 0;
         }
       }
      -
      +

      Konfig-Erweiterung in mailcows Nginx

      Der Dateiname, der fßr eine neue Site verwendet wird, ist nicht wichtig, solange der Dateiname eine .conf-Erweiterung trägt.

      Es ist auch mĂśglich, die Konfiguration der Standarddatei site.conf Datei zu erweitern:

      -
      nano data/conf/nginx/site.my_content.custom
      -
      +
      nano data/conf/nginx/site.my_content.custom
      +

      Dieser Dateiname muss keine ".conf"-Erweiterung haben, sondern folgt dem Muster site.*.custom, wobei * ein eigener Name ist.

      Wenn PHP in eine benutzerdefinierte Site eingebunden werden soll, verwenden Sie bitte den PHP-FPM-Listener auf phpfpm:9002 oder erstellen Sie einen neuen Listener in data/conf/phpfpm/php-fpm.d/pools.conf.

      Starten Sie Nginx neu (und PHP-FPM, falls ein neuer Listener erstellt wurde):

      -
      docker-compose restart nginx-mailcow
      +
      docker-compose restart nginx-mailcow
       docker-compose restart php-fpm-mailcow
      -
      +

      diff --git a/de/manual-guides/Nginx/u_e-nginx_webmail-site/index.html b/de/manual-guides/Nginx/u_e-nginx_webmail-site/index.html index e544857fb..c501f9e8e 100644 --- a/de/manual-guides/Nginx/u_e-nginx_webmail-site/index.html +++ b/de/manual-guides/Nginx/u_e-nginx_webmail-site/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2350,7 +2350,7 @@

      WICHTIG: Diese Anleitung gilt nur fĂźr Konfigurationen, bei denen SNI nicht aktiviert ist. Wenn SNI aktiviert ist, muss der Zertifikatspfad angepasst werden. Etwas wie ssl_certificate,key /etc/ssl/mail/webmail.example.org/cert.pem,key.pem; wird genĂźgen. Aber: Das Zertifikat sollte zuerst bezogen werden und erst wenn das Zertifikat existiert, sollte eine Site Config erstellt werden. Nginx wird nicht starten, wenn es das Zertifikat und den SchlĂźssel nicht finden kann.

      Um eine Subdomain webmail.example.org zu erstellen und sie auf SOGo umzuleiten, mĂźssen Sie eine neue Nginx-Site erstellen. Achten Sie dabei auf "CHANGE_TO_MAILCOW_HOSTNAME"!

      nano data/conf/nginx/webmail.conf

      -
      server {
      +
      server {
         ssl_certificate /etc/ssl/mail/cert.pem;
         ssl_certificate_key /etc/ssl/mail/key.pem;
         index index.php index.html;
      @@ -2369,12 +2369,12 @@
           return 301 https://CHANGE_TO_MAILCOW_HOSTNAME/SOGo;
         }
       }
      -
      +

      Speichern Sie und starten Sie Nginx neu: docker-compose restart nginx-mailcow.

      Öffnen Sie nun mailcow.conf und suchen Sie ADDITIONAL_SAN. Fügen Sie webmail.example.org zu diesem Array hinzu, verwenden Sie keine Anführungszeichen!

      -
      ADDITIONAL_SAN=webmail.example.org
      -
      +
      ADDITIONAL_SAN=webmail.example.org
      +

      Fßhren Sie docker-compose up -d aus. Siehe "acme-mailcow" und "nginx-mailcow" Logs, wenn etwas fehlschlägt.


      diff --git a/de/manual-guides/Postfix/u_e-postfix-attachment_size/index.html b/de/manual-guides/Postfix/u_e-postfix-attachment_size/index.html index 9f29dde26..9c82c2ebd 100644 --- a/de/manual-guides/Postfix/u_e-postfix-attachment_size/index.html +++ b/de/manual-guides/Postfix/u_e-postfix-attachment_size/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,8 +2349,8 @@

      Öffnen Sie data/conf/postfix/extra.cf und setzen Sie das message_size_limit entsprechend in Bytes. Siehe main.cf für den Standardwert.

      Starten Sie Postfix neu:

      -
      docker-compose restart postfix-mailcow
      -
      +
      docker-compose restart postfix-mailcow
      +

      diff --git a/de/manual-guides/Postfix/u_e-postfix-custom_transport/index.html b/de/manual-guides/Postfix/u_e-postfix-custom_transport/index.html index b99f58cf9..9d0ef9097 100644 --- a/de/manual-guides/Postfix/u_e-postfix-custom_transport/index.html +++ b/de/manual-guides/Postfix/u_e-postfix-custom_transport/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/manual-guides/Postfix/u_e-postfix-disable_sender_verification/index.html b/de/manual-guides/Postfix/u_e-postfix-disable_sender_verification/index.html index b70d27705..c013df469 100644 --- a/de/manual-guides/Postfix/u_e-postfix-disable_sender_verification/index.html +++ b/de/manual-guides/Postfix/u_e-postfix-disable_sender_verification/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2416,14 +2416,14 @@

      Veraltete Anleitung (NICHT FÜR NEUERE MAILCOWS VERWENDEN!)

      Diese Option ist keine Best-Practice und sollte nur verwendet werden, wenn es keine andere MĂśglichkeit gibt, das zu erreichen, was Sie erreichen wollen.

      Erstellen Sie einfach eine Datei data/conf/postfix/check_sasl_access und tragen Sie den folgenden Inhalt ein. Dieser Benutzer muss in Ihrer Installation existieren und muss sich vor dem Versenden von Mails authentifizieren. -

      user-to-allow-everything@example.com OK
      -

      +
      user-to-allow-everything@example.com OK
      +

      Öffnen Sie data/conf/postfix/main.cf und suchen Sie smtpd_sender_restrictions. Fügen Sie check_sasl_access hash:/opt/postfix/conf/check_sasl_access wie folgt ein: -

      smtpd_sender_restrictions = check_sasl_access hash:/opt/postfix/conf/check_sasl_access reject_authenticated_sender_login_mismatch [...]
      -

      +
      smtpd_sender_restrictions = check_sasl_access hash:/opt/postfix/conf/check_sasl_access reject_authenticated_sender_login_mismatch [...]
      +

      Postmap auf check_sasl_access ausfĂźhren:

      -
      docker-compose exec postfix-mailcow postmap /opt/postfix/conf/check_sasl_access
      -
      +
      docker-compose exec postfix-mailcow postmap /opt/postfix/conf/check_sasl_access
      +

      Starten Sie den Postfix-Container neu.


      diff --git a/de/manual-guides/Postfix/u_e-postfix-extra_cf/index.html b/de/manual-guides/Postfix/u_e-postfix-extra_cf/index.html index 7605a6534..e6be16918 100644 --- a/de/manual-guides/Postfix/u_e-postfix-extra_cf/index.html +++ b/de/manual-guides/Postfix/u_e-postfix-extra_cf/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2351,8 +2351,8 @@

      Postfix wird sich einmal nach dem Start von postfix-mailcow Ăźber doppelte Werte beschweren, dies ist beabsichtigt.

      Syslog-ng wurde so konfiguriert, dass es diese Warnungen ausblendet, während Postfix läuft, um die Log-Dateien nicht jedes Mal mit unnÜtigen Informationen zu spammen, wenn ein Dienst benutzt wird.

      Starten Sie postfix-mailcow neu, um Ihre Änderungen zu übernehmen:

      -
      docker-compose restart postfix-mailcow
      -
      +
      docker-compose restart postfix-mailcow
      +

      diff --git a/de/manual-guides/Postfix/u_e-postfix-pflogsumm/index.html b/de/manual-guides/Postfix/u_e-postfix-pflogsumm/index.html index f00897940..8b5ed132b 100644 --- a/de/manual-guides/Postfix/u_e-postfix-pflogsumm/index.html +++ b/de/manual-guides/Postfix/u_e-postfix-pflogsumm/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,13 +2348,13 @@

      Statistik mit pflogsumm

      Um pflogsumm mit dem Standard-Logging-Treiber zu verwenden, mĂźssen wir postfix-mailcow Ăźber docker logs abfragen und die Ausgabe zu pflogsumm leiten:

      -
      docker logs --since 24h $(docker ps -qf name=postfix-mailcow) | pflogsumm
      -
      +
      docker logs --since 24h $(docker ps -qf name=postfix-mailcow) | pflogsumm
      +

      Die obige Log-Ausgabe ist auf die letzten 24 Stunden beschränkt.

      Es ist auch mÜglich, einen täglichen pflogsumm-Bericht ßber cron zu erstellen. Erstellen Sie die Datei /etc/cron.d/pflogsumm mit dem folgenden Inhalt:

      -
      SHELL=/bin/bash
      +
      SHELL=/bin/bash
       59 23 * * * root docker logs --since 24h $(docker ps -qf name=postfix-mailcow) | /usr/sbin/pflogsumm -d today | mail -s "Postfix Report of $(date)" postmaster@example.net
      -
      +

      Um zu funktionieren muss ein lokaler Postfix auf dem Server installiert werden, welcher an den Postfix der mailcow relayed.

      Genauere Informationen lassen sich unter Sektion Post-Installationsaufgaben -> Lokaler MTA auf Dockerhost finden.

      Basierend auf den Postfix-Logs der letzten 24 Stunden sendet dieses Beispiel dann jeden Tag um 23:59:00 Uhr einen pflogsumm-Bericht an postmaster@example.net.

      diff --git a/de/manual-guides/Postfix/u_e-postfix-postscreen_whitelist/index.html b/de/manual-guides/Postfix/u_e-postfix-postscreen_whitelist/index.html index 668757dc1..fe581f7b3 100644 --- a/de/manual-guides/Postfix/u_e-postfix-postscreen_whitelist/index.html +++ b/de/manual-guides/Postfix/u_e-postfix-postscreen_whitelist/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2353,11 +2353,11 @@

      CIDR ACTION

      Dabei steht CIDR fĂźr eine einzelne IP-Adresse oder einen IP-Bereich in CIDR-Notation und action entweder fĂźr "permit" oder "reject".

      Beispiel:

      -
      # Regeln werden in der angegebenen Reihenfolge ausgewertet.
      +
      # Regeln werden in der angegebenen Reihenfolge ausgewertet.
       # Schwarze Liste 192.168.* außer 192.168.0.1.
       192.168.0.1 permit
       192.168.0.0/16 reject
      -
      +

      Die Datei wird spontan neu geladen, ein Neustart von Postfix ist nicht erforderlich.


      diff --git a/de/manual-guides/Postfix/u_e-postfix-relayhost/index.html b/de/manual-guides/Postfix/u_e-postfix-relayhost/index.html index a97f4cc91..aa2902c40 100644 --- a/de/manual-guides/Postfix/u_e-postfix-relayhost/index.html +++ b/de/manual-guides/Postfix/u_e-postfix-relayhost/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/manual-guides/Postfix/u_e-postfix-trust_networks/index.html b/de/manual-guides/Postfix/u_e-postfix-trust_networks/index.html index a1dac31db..287a099ac 100644 --- a/de/manual-guides/Postfix/u_e-postfix-trust_networks/index.html +++ b/de/manual-guides/Postfix/u_e-postfix-trust_networks/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2447,15 +2447,15 @@

      IPv4-Hosts/Subnetze

      Um das Subnetz 192.168.2.0/24 zu den vertrauenswßrdigen Netzwerken hinzuzufßgen, kÜnnen Sie die folgende Konfiguration verwenden, abhängig von Ihren IPV4_NETWORK und IPV6_NETWORK Bereichen:

      Bearbeiten Sie 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
      -
      +
      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
      +

      FĂźhren Sie docker-compose restart postfix-mailcow aus, um Ihre neuen Einstellungen zu Ăźbernehmen.

      IPv6-Hosts/Subnets

      Das Hinzufßgen von IPv6-Hosts erfolgt auf die gleiche Weise wie bei IPv4, allerdings muss das Subnetz in eckige Klammern [] gesetzt und die Netzmaske angehängt werden.

      Um das Subnetz 2001:db8::/32 zu den vertrauenswßrdigen Netzwerken hinzuzufßgen, kÜnnen Sie die folgende Konfiguration verwenden, abhängig von Ihren IPV4_NETWORK- und IPV6_NETWORK-Bereichen:

      Bearbeiten Sie 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
      -
      +
      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
      +

      FĂźhren Sie docker-compose restart postfix-mailcow aus, um Ihre neuen Einstellungen zu Ăźbernehmen.

      Info

      diff --git a/de/manual-guides/Redis/u_e-redis/index.html b/de/manual-guides/Redis/u_e-redis/index.html index a97126f05..48729a65a 100644 --- a/de/manual-guides/Redis/u_e-redis/index.html +++ b/de/manual-guides/Redis/u_e-redis/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2477,28 +2477,28 @@

      Redis wird als Key-Value-Speicher fĂźr die Einstellungen und Daten von rspamd und (einige von) mailcow verwendet. Wenn Sie mit Redis nicht vertraut sind, lesen Sie bitte die EinfĂźhrung in Redis und besuchen Sie gegebenenfalls diese wunderbare Anleitung, um zu erfahren, wie man Redis benutzt.

      Client

      Um sich mit dem redis cli zu verbinden, fĂźhren Sie aus:

      -
      docker-compose exec redis-mailcow redis-cli
      -
      +
      docker-compose exec redis-mailcow redis-cli
      +

      Fehlersuche

      Hier sind einige nĂźtzliche Befehle fĂźr den redis-cli zur Fehlersuche:

      MONITOR

      Überwacht alle vom Server empfangenen Anfragen in Echtzeit:

      -
      # docker-compose exec redis-mailcow redis-cli
      +
      # docker-compose exec redis-mailcow redis-cli
       127.0.0.1:6379> Ăźberwachen
       OK
       1494077286.401963 [0 172.22.1.253:41228] "SMEMBERS" "BAYES_SPAM_keys"
       1494077288.292970 [0 172.22.1.253:41229] "SMEMBERS" "BAYES_SPAM_keys"
       [...]
      -
      +
      SCHLÜSSEL (Keys)

      Ermittelt alle SchlĂźssel, die dem Muster entsprechen:

      -
      KEYS *
      -
      +
      KEYS *
      +
      PING

      Testen Sie eine Verbindung:

      -
      127.0.0.1:6379> PING
      +
      127.0.0.1:6379> PING
       PONG
      -
      +

      Wenn Sie mehr wissen wollen, hier ist ein Cheat-Sheet.


      diff --git a/de/manual-guides/Rspamd/u_e-rspamd/index.html b/de/manual-guides/Rspamd/u_e-rspamd/index.html index fff5a75a0..e5832a892 100644 --- a/de/manual-guides/Rspamd/u_e-rspamd/index.html +++ b/de/manual-guides/Rspamd/u_e-rspamd/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2528,15 +2528,15 @@ Dies wird durch die Verwendung des Sieve-Plugins "sieve_imapsieve" und Parser-Sk

      Sie kĂśnnen auch die Web-UI von Rspamd verwenden, um Ham und/oder Spam zu lernen oder bestimmte Einstellungen von Rspamd anzupassen.

      Spam oder Ham aus bestehendem Verzeichnis lernen

      Sie kĂśnnen einen Einzeiler verwenden, um Mails im Klartextformat (unkomprimiert) zu lernen:

      -
      # Ham
      -for file in /my/folder/cur/*; do docker exec -i $(docker-compose ps -q rspamd-mailcow) rspamc learn_ham < $file; done
      +
      # Ham
      +for file in /my/folder/cur/*; do docker exec -i $(docker-compose ps -q rspamd-mailcow) rspamc learn_ham < $file; done
       # Spam
      -for file in /my/folder/.Junk/cur/*; do docker exec -i $(docker-compose ps -q rspamd-mailcow) rspamc learn_spam < $file; done
      -
      +for file in /my/folder/.Junk/cur/*; do docker exec -i $(docker-compose ps -q rspamd-mailcow) rspamc learn_spam < $file; done +

      Erwägen Sie, einen lokalen Ordner als neues Volume an rspamd-mailcow in docker-compose.yml anzuhängen und die gegebenen Dateien innerhalb des Containers zu lernen. Dies kann als Workaround verwendet werden, um komprimierte Daten mit zcat zu parsen. Beispiel:

      ``bash for file in /data/old_mail/.Junk/cur/*; do rspamc learn_spam < zcat $file; done -

      ### Gelernte Daten zurĂźcksetzen (Bayes, Neural)
      +
      ### Gelernte Daten zurĂźcksetzen (Bayes, Neural)
       
       Sie mĂźssen die SchlĂźssel in Redis lĂśschen, um die gelernten Daten zurĂźckzusetzen, also erstellen Sie jetzt eine Kopie Ihrer Redis-Datenbank:
       
      @@ -2545,30 +2545,30 @@ Sie mĂźssen die SchlĂźssel in Redis lĂśschen, um die gelernten Daten zurĂźckzuse
       ```bash
       # Es ist besser, Redis zu stoppen, bevor Sie die Datei kopieren.
       cp /var/lib/docker/volumes/mailcowdockerized_redis-vol-1/_data/dump.rdb /root/
      -

      +

      Bayes-Daten zurĂźcksetzen

      -
      docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern BAYES_* | xargs redis-cli del'
      +
      docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern BAYES_* | xargs redis-cli del'
       docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern RS* | xargs redis-cli del'
      -
      +

      Neurale Daten zurĂźcksetzen

      -
      docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern rn_* | xargs redis-cli del'
      -
      +
      docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern rn_* | xargs redis-cli del'
      +

      Fuzzy-Daten zurĂźcksetzen

      -
      # Wir mĂźssen zuerst das redis-cli eingeben:
      +
      # Wir mĂźssen zuerst das redis-cli eingeben:
       docker-compose exec redis-mailcow redis-cli
       # In redis-cli:
       127.0.0.1:6379> EVAL "for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end" 0 fuzzy*
      -
      +

      Info

      Wenn redis-cli sich beschwert Ăźber...

      -
      (error) ERR wrong number of arguments for 'del' command
      -
      +
      (error) ERR wrong number of arguments for 'del' command
      +

      ...das SchlĂźsselmuster nicht gefunden wurde und somit keine Daten zum LĂśschen vorhanden sind - ist es in Ordnung.

      CLI-Werkzeuge

      ``bash docker-compose exec rspamd-mailcow rspamc --help docker-compose exec rspamd-mailcow rspamadm --help -

      ## Greylisting deaktivieren
      +
      ## Greylisting deaktivieren
       
       Nur Nachrichten mit einer hĂśheren Punktzahl werden als Greylisting betrachtet (soft rejected). Es ist schlechte Praxis, Greylisting zu deaktivieren.
       
      @@ -2580,26 +2580,26 @@ FĂźgen Sie die Zeile hinzu:
       
       ```cpp
       enabled = false;
      -

      +

      Speichern Sie die Datei und starten Sie "rspamd-mailcow" neu: docker-compose restart rspamd-mailcow

      Spamfilter-Schwellenwerte (global)

      Jeder Benutzer kann seine Spam-Bewertung individuell ändern. Um eine neue serverweite Grenze zu definieren, editieren Sie data/conf/rspamd/local.d/actions.conf:

      -
      reject = 15;
      -add_header = 8;
      -greylist = 7;
      -
      +
      reject = 15;
      +add_header = 8;
      +greylist = 7;
      +

      Speichern Sie die Datei und starten Sie "rspamd-mailcow" neu: docker-compose restart rspamd-mailcow

      Bestehende Einstellungen der Benutzer werden nicht Ăźberschrieben!

      Um benutzerdefinierte Schwellenwerte zurĂźckzusetzen, fĂźhren Sie aus:

      -
      source mailcow.conf
      +
      source mailcow.conf
       docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e "delete from filterconf where option = 'highspamlevel' or option = 'lowspamlevel';"
       # oder:
       # docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e "delete from filterconf where option = 'highspamlevel' or option = 'lowspamlevel' and object = 'only-this-mailbox@example.org';"
      -
      +

      Benutzerdefinierte Ablehnungsnachrichten

      Die Standard-Spam-Reject-Meldung kann durch Hinzufßgen einer neuen Datei data/conf/rspamd/override.d/worker-proxy.custom.inc mit dem folgenden Inhalt geändert werden:

      -
      reject_message = "Meine eigene Ablehnungsnachricht";
      -
      +
      reject_message = "Meine eigene Ablehnungsnachricht";
      +

      Speichern Sie die Datei und starten Sie Rspamd neu: docker-compose restart rspamd-mailcow.

      Waehrend das oben genannte fuer abgelehnte Mails mit einem hohen Spam-Score funktioniert, ignorieren Prefilter-Aktionen diese Einstellung. FĂźr diese Karten muss das Multimap-Modul in Rspamd angepasst werden:

        @@ -2610,7 +2610,7 @@ docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e "del

        FĂźgen Sie Ihre eigene Nachricht als neue Zeile hinzu:

      -
      GLOBAL_RCPT_BL {
      +
      GLOBAL_RCPT_BL {
         Typ = "rcpt";
         map = "${LOCAL_CONFDIR}/custom/global_rcpt_blacklist.map";
         regexp = true;
      @@ -2618,40 +2618,40 @@ docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e "del
         action = "reject";
         message = "Der Versand von E-Mails an diesen Empfänger ist durch postmaster@your.domain verboten";
       }
      -
      +
      1. Speichern Sie die Datei und starten Sie Rspamd neu: docker-compose restart rspamd-mailcow.

      Verwerfen statt zurĂźckweisen

      Wenn Sie eine Nachricht stillschweigend verwerfen wollen, erstellen oder bearbeiten Sie die Datei data/conf/rspamd/override.d/worker-proxy.custom.inc und fĂźgen Sie den folgenden Inhalt hinzu:

      -
      discard_on_reject = true;
      -
      +
      discard_on_reject = true;
      +

      Starten Sie Rspamd neu:

      -
      docker-compose restart rspamd-mailcow
      -
      +
      docker-compose restart rspamd-mailcow
      +

      LĂśsche alle Ratelimit-SchlĂźssel

      Wenn Sie das UI nicht verwenden wollen und stattdessen alle SchlĂźssel in der Redis-Datenbank lĂśschen wollen, kĂśnnen Sie redis-cli fĂźr diese Aufgabe verwenden:

      -
      docker-compose exec redis-mailcow sh
      +
      docker-compose exec redis-mailcow sh
       # Unlink (verfĂźgbar in Redis >=4.) lĂśscht im Hintergrund
       redis-cli --scan --pattern RL* | xargs redis-cli unlink
      -
      +

      Starten Sie Rspamd neu:

      -
      docker-compose exec redis-mailcow sh
      -
      +
      docker-compose exec redis-mailcow sh
      +

      Erneutes Senden von Quarantäne-Benachrichtigungen auslÜsen

      Sollte nur zur Fehlersuche verwendet werden!

      -
      docker-compose exec dovecot-mailcow bash
      +
      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
      -
      +

      Speicherung der Historie erhĂśhen

      Standardmäßig speichert Rspamd 1000 Elemente in der Historie.

      Die Historie wird komprimiert gespeichert.

      Es wird empfohlen, hier keinen unverhältnismäßig hohen Wert zu verwenden, probieren Sie etwas in der Größenordnung von 5000 oder 10000 und sehen Sie, wie Ihr Server damit umgeht:

      Bearbeiten Sie data/conf/rspamd/local.d/history_redis.conf:

      -
      nrows = 1000; # Ändern Sie diesen Wert
      -
      +
      nrows = 1000; # Ändern Sie diesen Wert
      +

      Starten Sie anschließend Rspamd neu: docker-compose restart rspamd-mailcow


      diff --git a/de/manual-guides/SOGo/u_e-sogo/index.html b/de/manual-guides/SOGo/u_e-sogo/index.html index 0ff6c2d37..f8f1cd1f4 100644 --- a/de/manual-guides/SOGo/u_e-sogo/index.html +++ b/de/manual-guides/SOGo/u_e-sogo/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2491,24 +2491,24 @@ Nachdem Sie data/conf/sogo/custom-theme.js modifiziert und Änderun
    • Ăśffnen Sie die Entwicklerkonsole des Browsers, normalerweise ist die Tastenkombination F12
    • nur wenn Sie Firefox benutzen: schreiben Sie mit der Hand in die Entwicklerkonsole allow pasting und drĂźcken Sie Enter
    • fĂźgen Sie den Java-Script-Schnipsel in die Entwicklungskonsole ein: -
      copy([].slice.call(document.styleSheets)
      +
      copy([].slice.call(document.styleSheets)
         .map(e => e.ownerNode)
         .filter(e => e.hasAttribute('md-theme-style'))
         .map(e => e.textInhalt)
         .join('\n')
       )
      -
    • +
    • Öffnen Sie den Texteditor und fĂźgen Sie die Daten aus der Zwischenablage ein (Strg+V), Sie sollten ein minimiertes CSS erhalten, speichern Sie es
    • kopieren Sie die CSS-Datei auf den Mailcow-Server data/conf/sogo/custom-theme.css
    • editiere data/conf/sogo/sogo.conf und setze SOGoUIxDebugEnabled = NO;
    • Anhängen/Erstellen von docker-compose.override.yml mit: -
      Version: '2.1'
      +
      Version: '2.1'
       
       Dienste:
         sogo-mailcow:
           volumes:
             - ./data/conf/sogo/custom-theme.css:/usr/lib/GNUstep/SOGo/WebServerResources/css/theme-default.css:z
      -
    • +
    • fĂźhren Sie docker-compose up -d aus
    • AusfĂźhren von docker-compose restart memcached-mailcow
    • @@ -2516,7 +2516,7 @@ Dienste:
      1. checken Sie data/conf/sogo/custom-theme.js aus, indem Sie git fetch ; git checkout origin/master data/conf/sogo/custom-theme.js data/conf/sogo/custom-theme.js ausfĂźhren
      2. Suchen Sie in data/conf/sogo/custom-theme.js: -
        // Neue Paletten auf das Standardthema anwenden, einige FarbtĂśne neu zuordnen
        +
        // Neue Paletten auf das Standardthema anwenden, einige FarbtĂśne neu zuordnen
             $mdThemingProvider.theme('default')
               .primaryPalette('green-cow', {
                 'default': '400', // Hintergrundfarbe der oberen Symbolleisten
        @@ -2531,13 +2531,13 @@ Dienste:
                 hue-3': 'A700'
               })
               .backgroundPalette('frost-grey');
        -
        +
        und ersetzen Sie es durch: -
            $mdThemingProvider.theme('default');
        -
      3. +
            $mdThemingProvider.theme('default');
        +
      4. Entfernen Sie aus docker-compose.override.yml Volume Mount in sogo-mailcow: -
        - ./data/conf/sogo/custom-theme.css:/usr/lib/GNUstep/SOGo/WebServerResources/css/theme-default.css:z
        -
      5. +
        - ./data/conf/sogo/custom-theme.css:/usr/lib/GNUstep/SOGo/WebServerResources/css/theme-default.css:z
        +
      6. fĂźhren Sie docker-compose up -d aus
      7. Starten Sie docker-compose restart memcached-mailcow.
      @@ -2553,16 +2553,16 @@ Nachdem Sie diese Datei ersetzt haben, mĂźssen Sie SOGo und Memcached Container

      Domains sind normalerweise voneinander isoliert.

      Sie kÜnnen das ändern, indem Sie data/conf/sogo/sogo.conf modifizieren:

      Suche... -

         // SOGoDomainsVisibility = (
      +
         // SOGoDomainsVisibility = (
           // (domain1.tld, domain5.tld),
           // (domain3.tld, domain2.tld)
           // );
      -
      +
      ...und ersetzen Sie diese durch - zum Beispiel:

      -
          SOGoDomainsVisibility = (
      +
          SOGoDomainsVisibility = (
             (beispiel.org, beispiel.com, beispiel.net)
           );
      -
      +

      SOGo neu starten: docker-compose restart sogo-mailcow

      Deaktivieren Sie die Passwortänderung

      Bearbeiten Sie data/conf/sogo/sogo.conf und ändern Sie SOGoPasswordChangeEnabled auf NO. Bitte fßgen Sie keinen neuen Parameter hinzu.

      diff --git a/de/manual-guides/Unbound/u_e-unbound-fwd/index.html b/de/manual-guides/Unbound/u_e-unbound-fwd/index.html index 9dfa07f90..bf6112901 100644 --- a/de/manual-guides/Unbound/u_e-unbound-fwd/index.html +++ b/de/manual-guides/Unbound/u_e-unbound-fwd/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2416,18 +2416,18 @@ Wichtig: Nur DNSSEC-validierende DNS-Dienste werden funktionieren.

      Methode A, Unbound

      Bearbeiten Sie data/conf/unbound/unbound.conf und fĂźgen Sie die folgenden Parameter hinzu:

      -
      forward-zone:
      +
      forward-zone:
         name: "."
         forward-addr: 8.8.8.8 # VERWENDEN SIE KEINE ÖFFENTLICHEN DNS-SERVER - NUR EIN BEISPIEL
         forward-addr: 8.8.4.4 # VERWENDET KEINE ÖFFENTLICHEN DNS-SERVER - NUR EIN BEISPIEL
      -
      +

      Unbound neu starten:

      -
      docker-compose restart unbound-mailcow
      -
      +
      docker-compose restart unbound-mailcow
      +

      Methode B, Überschreiben der Datei

      -
      cd /opt/mailcow-dockerized
      +
      cd /opt/mailcow-dockerized
       cp helper-scripts/docker-compose.override.yml.d/EXTERNAL_DNS/docker-compose.override.yml .
      -
      +

      Bearbeiten Sie docker-compose.override.yml und passen Sie die IP an.

      FĂźhren Sie docker-compose down ; docker-compose up -d aus.

      diff --git a/de/manual-guides/Watchdog/u_e-watchdog-thresholds/index.html b/de/manual-guides/Watchdog/u_e-watchdog-thresholds/index.html index 2c89184ba..d59e37aef 100644 --- a/de/manual-guides/Watchdog/u_e-watchdog-thresholds/index.html +++ b/de/manual-guides/Watchdog/u_e-watchdog-thresholds/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2649,7 +2649,7 @@

      Watchdog verwendet Standardwerte fĂźr alle in docker-compose.yml definierten Thresholde.

      Die Standardwerte sind fĂźr die meisten Konfigurationen geeignet. Beispiel: -

      - NGINX_THRESHOLD=${NGINX_THRESHOLD:-5}
      +
      - NGINX_THRESHOLD=${NGINX_THRESHOLD:-5}
       - UNBOUND_THRESHOLD=${UNBOUND_THRESHOLD:-5}
       - REDIS_THRESHOLD=${REDIS_THRESHOLD:-5}
       - MYSQL_THRESHOLD=${MYSQL_THRESHOLD:-5}
      @@ -2667,7 +2667,7 @@ Beispiel:
       - OLEFY_THRESHOLD=${OLEFY_THRESHOLD:-5}
       - MAILQ_THRESHOLD=${MAILQ_THRESHOLD:-20}
       - MAILQ_CRIT=${MAILQ_CRIT:-30}
      -

      +

      Um sie anzupassen, fĂźgen Sie einfach die notwendigen Threshold Variablen (z.B. MAILQ_THRESHOLD=10) zu mailcow.conf hinzu und fĂźhren docker-compose up -d aus.

      Threshold Beschreibungen

      NGINX_THRESHOLD

      diff --git a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-bl_wl/index.html b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-bl_wl/index.html index b2ad52577..4be991eb5 100644 --- a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-bl_wl/index.html +++ b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-bl_wl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-config/index.html b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-config/index.html index f98e2723b..9555851f5 100644 --- a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-config/index.html +++ b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-config/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-css/index.html b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-css/index.html index 72f683772..f38c66076 100644 --- a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-css/index.html +++ b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-css/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-fido/index.html b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-fido/index.html index 983daa698..92247666f 100644 --- a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-fido/index.html +++ b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-fido/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-pushover/index.html b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-pushover/index.html index b820ce1fc..4d25fd59f 100644 --- a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-pushover/index.html +++ b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-pushover/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-spamalias/index.html b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-spamalias/index.html index 697b1642b..5fb63e112 100644 --- a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-spamalias/index.html +++ b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-spamalias/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-spamfilter/index.html b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-spamfilter/index.html index 854098b37..92154299c 100644 --- a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-spamfilter/index.html +++ b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-spamfilter/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-tagging/index.html b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-tagging/index.html index a1cc6d0af..36e0ae06b 100644 --- a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-tagging/index.html +++ b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-tagging/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2403,7 +2403,7 @@

      1. Diese Nachricht in einen Unterordner "facebook" verschieben (wird in Kleinbuchstaben erstellt, falls nicht vorhanden)

      2. Den Tag dem Betreff voranstellen: "[facebook] Betreff"

      Bitte beachten Sie: Großgeschriebene Tags werden in Kleinbuchstaben umgewandelt, mit Ausnahme des ersten Buchstabens. Wenn Sie den Tag so lassen wollen, wie er ist, wenden Sie bitte den folgenden Diff an und starten Sie mailcow neu: -

      diff --git a/data/conf/dovecot/global_sieve_after b/data/conf/dovecot/global_sieve_after
      +
      diff --git a/data/conf/dovecot/global_sieve_after b/data/conf/dovecot/global_sieve_after
       index e047136e..933c4137 100644
       --- a/data/conf/dovecot/global_sieve_after
       +++ b/data/conf/dovecot/global_sieve_after
      @@ -2416,7 +2416,7 @@ index e047136e..933c4137 100644
          if mailboxexists "INBOX/${1}" {
            fileinto "INBOX/${1}";
          } else {
      -

      +


      diff --git a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-tfa/index.html b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-tfa/index.html index 378db204c..87102e4f5 100644 --- a/de/manual-guides/mailcow-UI/u_e-mailcow_ui-tfa/index.html +++ b/de/manual-guides/mailcow-UI/u_e-mailcow_ui-tfa/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/manual-guides/u_e-80_to_443/index.html b/de/manual-guides/u_e-80_to_443/index.html index 43ead7c9c..9aa7a1c35 100644 --- a/de/manual-guides/u_e-80_to_443/index.html +++ b/de/manual-guides/u_e-80_to_443/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,7 +2349,7 @@

      Verwenden Sie die untenstehende Konfiguration nicht fĂźr Reverse-Proxy-Setups, bitte lesen Sie dazu unsere Reverse-Proxy-Anleitung, die einen Redirect von HTTP zu HTTPS beinhaltet.

      Öffne mailcow.conf und setze HTTP_BIND= - falls nicht bereits gesetzt.

      Erstellen Sie eine neue Datei data/conf/nginx/redirect.conf und fĂźgen Sie die folgende Serverkonfiguration in die Datei ein:

      -
      server {
      +
      server {
         root /web;
         listen 80 default_server;
         listen [::]:80 default_server;
      @@ -2363,13 +2363,13 @@
           return 301 https://$host$uri$is_args$args;
         }
       }
      -
      +

      Falls Sie den Parameter HTTP_BIND geändert haben, erstellen Sie den Container neu:

      -
      docker-compose up -d
      -
      +
      docker-compose up -d
      +

      Andernfalls starten Sie Nginx neu:

      -
      docker-compose restart nginx-mailcow
      -
      +
      docker-compose restart nginx-mailcow
      +

      diff --git a/de/manual-guides/u_e-autodiscover_config/index.html b/de/manual-guides/u_e-autodiscover_config/index.html index d650833d7..e28cb89e4 100644 --- a/de/manual-guides/u_e-autodiscover_config/index.html +++ b/de/manual-guides/u_e-autodiscover_config/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2350,7 +2350,7 @@ Denken Sie daran, dass ActiveSync NICHT mit einem Desktop-Client verwendet werden sollte.

      Öffnen/erstellen Sie data/web/inc/vars.local.inc.php und fügen Sie Ihre Änderungen in das Konfigurationsfeld ein.

      Die Änderungen werden mit "$autodiscover_config" in data/web/inc/vars.inc.php zusammengeführt):

      -
      <?php
      +
      <?php
       $autodiscover_config = array(
         // General autodiscover service type: "activesync" or "imap"
         // emClient uses autodiscover, but does not support ActiveSync. mailcow excludes emClient from ActiveSync.
      @@ -2388,7 +2388,7 @@ $autodiscover_config = array(
           'port' => $https_port,
         ),
       );
      -
      +

      Um immer IMAP und SMTP anstelle von EAS zu verwenden, setzen Sie 'autodiscoverType' => 'imap'.

      Deaktivieren Sie ActiveSync fĂźr Outlook-Desktop-Clients, indem Sie "useEASforOutlook" auf "no" setzen.

      diff --git a/de/manual-guides/u_e-reeanble-weak-protocols/index.html b/de/manual-guides/u_e-reeanble-weak-protocols/index.html index 7fab04170..7254a5495 100644 --- a/de/manual-guides/u_e-reeanble-weak-protocols/index.html +++ b/de/manual-guides/u_e-reeanble-weak-protocols/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,15 +2349,15 @@

      Unauthentifizierte Mails Ăźber SMTP an Port 25/tcp akzeptieren weiterhin >= TLS 1.0 . Es ist besser, eine schwache VerschlĂźsselung zu akzeptieren als gar keine.

      Wie kann man schwache Protokolle wieder aktivieren?

      Bearbeiten Sie data/conf/postfix/extra.cf:

      -
      submission_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
      +
      submission_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
       smtps_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
      -
      +

      Bearbeiten Sie data/conf/dovecot/extra.conf:

      -
      ssl_min_protocol = TLSv1
      -
      +
      ssl_min_protocol = TLSv1
      +

      Starten Sie die betroffenen Dienste neu:

      -
      docker-compose restart postfix-mailcow dovecot-mailcow
      -
      +
      docker-compose restart postfix-mailcow dovecot-mailcow
      +

      Tipp: Sie kĂśnnen TLS 1.2 in Windows 7 aktivieren.


      diff --git a/de/manual-guides/u_e-update-hooks/index.html b/de/manual-guides/u_e-update-hooks/index.html index be5a1242e..1db05a925 100644 --- a/de/manual-guides/u_e-update-hooks/index.html +++ b/de/manual-guides/u_e-update-hooks/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/manual-guides/u_e-why_unbound/index.html b/de/manual-guides/u_e-why_unbound/index.html index 4f53e65f9..f97551e3e 100644 --- a/de/manual-guides/u_e-why_unbound/index.html +++ b/de/manual-guides/u_e-why_unbound/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/models/model-acl/index.html b/de/models/model-acl/index.html index 5af64a578..7d003a0ee 100644 --- a/de/models/model-acl/index.html +++ b/de/models/model-acl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/models/model-passwd/index.html b/de/models/model-passwd/index.html index 1ef534124..5d1c36f5e 100644 --- a/de/models/model-passwd/index.html +++ b/de/models/model-passwd/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/models/model-sender_rcv/index.html b/de/models/model-sender_rcv/index.html index 89016fb80..272c5e4a9 100644 --- a/de/models/model-sender_rcv/index.html +++ b/de/models/model-sender_rcv/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/post_installation/firststeps-disable_ipv6/index.html b/de/post_installation/firststeps-disable_ipv6/index.html index 2479bb00c..59f156f02 100644 --- a/de/post_installation/firststeps-disable_ipv6/index.html +++ b/de/post_installation/firststeps-disable_ipv6/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2353,49 +2353,49 @@ zu erstellen und Ihre Änderungen am Dienst dort zu implementieren. Leider schei

      Um IPv6 im mailcow-Netzwerk zu deaktivieren, Ăśffnen Sie docker-compose.yml mit Ihrem bevorzugten Texteditor und suchen Sie nach dem Netzwerk-Abschnitt (er befindet sich am Ende der Datei).

      1. Ändern Sie docker-compose.yml

      Ändern Sie enable_ipv6: true in enable_ipv6: false:

      -
      networks:
      +
      networks:
         mailcow-network:
           [...]
           enable_ipv6: true # <<< auf false setzen
           [...]
      -
      +

      2. ipv6nat-mailcow deaktivieren

      Um den ipv6nat-mailcow Container ebenfalls zu deaktivieren, gehen Sie in Ihr mailcow Verzeichnis und erstellen Sie eine neue Datei namens "docker-compose.override.yml":

      HINWEIS: Wenn Sie bereits eine Override-Datei haben, erstellen Sie diese natĂźrlich nicht neu, sondern fĂźgen Sie die untenstehenden Zeilen entsprechend in Ihre bestehende Datei ein!

      -
      # cd /opt/mailcow-dockerized
      +
      # cd /opt/mailcow-dockerized
       # touch docker-compose.override.yml
      -
      +

      Öffnen Sie die Datei in Ihrem bevorzugten Texteditor und tragen Sie folgendes ein:

      -
      version: '2.1'
      +
      version: '2.1'
       services:
       
           ipv6nat-mailcow:
             image: bash:latest
             restart: "no"
             entrypoint: ["echo", "ipv6nat disabled in compose.override.yml"]
      -
      +

      Damit diese Änderungen wirksam werden, müssen Sie den Stack vollständig stoppen und dann neu starten, damit Container und Netzwerke neu erstellt werden:

      -
      docker-compose down
      +
      docker-compose down
       docker-compose up -d
      -
      +

      3. Deaktivieren Sie IPv6 in unbound-mailcow

      Bearbeiten Sie data/conf/unbound/unbound.conf und setzen Sie do-ip6 auf "no":

      -
      Server:
      +
      Server:
         [...]
         do-ip6: no
         [...]
      -
      +

      unbound neu starten:

      -
      docker-compose restart unbound-mailcow
      -
      +
      docker-compose restart unbound-mailcow
      +

      4. Deaktivieren Sie IPv6 in postfix-mailcow

      Erstellen Sie data/conf/postfix/extra.cf und setzen Sie smtp_address_preference auf ipv4:

      -
      smtp_address_preference = ipv4
      +
      smtp_address_preference = ipv4
       inet_protocols = ipv4
      -
      +

      Starten Sie Postfix neu:

      -
      docker-compose restart postfix-mailcow
      -
      +
      docker-compose restart postfix-mailcow
      +

      diff --git a/de/post_installation/firststeps-dmarc_reporting/index.html b/de/post_installation/firststeps-dmarc_reporting/index.html index 57e5b636e..d8a6388ce 100644 --- a/de/post_installation/firststeps-dmarc_reporting/index.html +++ b/de/post_installation/firststeps-dmarc_reporting/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2473,7 +2473,7 @@

      Aktivieren Sie DMARC-Berichterstattung

      Erstellen Sie die Datei data/conf/rspamd/local.d/dmarc.conf und setzen Sie den folgenden Inhalt:

      -
      reporting {
      +
      reporting {
           enabled = true;
           email = 'noreply-dmarc@example.com';
           domain = 'example.com';
      @@ -2486,9 +2486,9 @@
           max_entries = 2k;
           keys_expire = 2d;
       }
      -
      +

      Erstellen oder ändern Sie docker-compose.override.yml im mailcow-dockerized Basisverzeichnis:

      -
      version: '2.1'
      +
      version: '2.1'
       
       services:
         rspamd-mailcow:
      @@ -2501,16 +2501,16 @@ services:
         ofelia-mailcow:
           depends_on:
             - rspamd-mailcow
      -
      +

      Starte docker-compose up -d

      Senden Sie eine Kopie der Berichte an sich selbst

      Um eine versteckte Kopie der von Rspamd erzeugten Berichte zu erhalten, kĂśnnen Sie eine bcc_addrs Liste im reporting Konfigurationsabschnitt von data/conf/rspamd/local.d/dmarc.conf setzen:

      -
      reporting {
      +
      reporting {
           enabled = true;
           email = 'noreply-dmarc@example.com';
           bcc_addrs = ["noreply-dmarc@example.com", "parsedmarc@example.com"];
       [...]
      -
      +

      Rspamd lädt Änderungen in Echtzeit, so dass Sie den Container zu diesem Zeitpunkt nicht neu starten müssen.

      Dies kann nĂźtzlich sein, wenn Sie...

        @@ -2519,18 +2519,18 @@ services:

      Fehlersuche

      PrĂźfen Sie, wann der Berichtsplan zuletzt ausgefĂźhrt wurde:

      -
      docker-compose exec rspamd-mailcow date -r /var/lib/rspamd/dmarc_reports_last_log
      -
      +
      docker-compose exec rspamd-mailcow date -r /var/lib/rspamd/dmarc_reports_last_log
      +

      Sehen Sie sich die letzte Berichtsausgabe an:

      -
      docker-compose exec rspamd-mailcow cat /var/lib/rspamd/dmarc_reports_last_log
      -
      +
      docker-compose exec rspamd-mailcow cat /var/lib/rspamd/dmarc_reports_last_log
      +

      Manuelles AuslĂśsen eines DMARC-Berichts:

      -
      docker-compose exec rspamd-mailcow rspamadm dmarc_report
      -
      +
      docker-compose exec rspamd-mailcow rspamadm dmarc_report
      +

      Bestätigen Sie, dass Rspamd Daten in Redis aufgezeichnet hat:

      -
      docker-compose exec redis-mailcow redis-cli KEYS 'dmarc;*'
      +
      docker-compose exec redis-mailcow redis-cli KEYS 'dmarc;*'
       docker-compose exec redis-mailcow redis-cli HGETALL "dmarc;example.com;20211231"
      -
      +

      Ändern Sie die Häufigkeit der DMARC-Berichte

      Im obigen Beispiel werden die Berichte einmal alle 24 Stunden gesendet.

      Der Olefia-Zeitplan hat die gleiche Implementierung wie cron in Go, die unterstĂźtzte Syntax ist beschrieben in cron Documentation

      diff --git a/de/post_installation/firststeps-ip_bindings/index.html b/de/post_installation/firststeps-ip_bindings/index.html index 226942f0a..1266cfa65 100644 --- a/de/post_installation/firststeps-ip_bindings/index.html +++ b/de/post_installation/firststeps-ip_bindings/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2414,7 +2414,7 @@

      IPv4-Binding

      Um eine oder mehrere IPv4-Bind(ings) anzupassen, Ăśffne mailcow.conf und editiere eine, mehrere oder alle Variablen nach deinen BedĂźrfnissen:

      -
      # Aus technischen GrĂźnden unterscheiden sich die http-Bindungen ein wenig von anderen Service-Bindungen.
      +
      # Aus technischen GrĂźnden unterscheiden sich die http-Bindungen ein wenig von anderen Service-Bindungen.
       # Sie werden die folgenden Variablen finden, getrennt durch eine Bindungsadresse und deren Port:
       # Beispiel: HTTP_BIND=1.2.3.4
       
      @@ -2439,14 +2439,14 @@ SIEVE_PORT=4190
       DOVEADM_PORT=127.0.0.1:19991
       SQL_PORT=127.0.0.1:13306
       SOLR_PORT=127.0.0.1:18983
      -
      +

      Um Ihre Änderungen zu übernehmen, führen Sie docker-compose down gefolgt von docker-compose up -d aus.

      IPv6-Binding

      Das Ändern von IPv6-Bindings ist anders als bei IPv4. Auch dies hat einen technischen Hintergrund.

      Eine docker-compose.override.yml Datei wird verwendet, anstatt die docker-compose.yml Datei direkt zu bearbeiten. Dies geschieht, um die Aktualisierbarkeit zu erhalten, da die Datei docker-compose.yml regelmäßig aktualisiert wird und Ihre Änderungen höchstwahrscheinlich überschrieben werden.

      Bearbeiten Sie die Datei "docker-compose.override.yml" und erstellen Sie sie mit dem folgenden Inhalt. Ihr Inhalt wird mit der produktiven Datei "docker-compose.yml" zusammengefĂźhrt.

      Es wird eine imaginäre IPv6 2a00:dead:beef::abc angegeben. Das erste Suffix :PORT1 definiert den externen Port, während das zweite Suffix :PORT2 zu dem entsprechenden Port innerhalb des Containers fßhrt und nicht verändert werden darf.

      -
      version: '2.1'
      +
      version: '2.1'
       services:
       
           dovecot-mailcow:
      @@ -2467,7 +2467,7 @@ services:
             ports:
               - '2a00:dead:beef::abc:80:80'
               - '2a00:dead:beef::abc:443:443'
      -
      +

      Um Ihre Änderungen zu übernehmen, führen Sie docker-compose down gefolgt von docker-compose up -d aus.


      diff --git a/de/post_installation/firststeps-local_mta/index.html b/de/post_installation/firststeps-local_mta/index.html index c83c2ae42..65486de36 100644 --- a/de/post_installation/firststeps-local_mta/index.html +++ b/de/post_installation/firststeps-local_mta/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2347,15 +2347,15 @@

      Die einfachste MÜglichkeit wäre, den Listener an Port 25/tcp zu deaktivieren.

      Postfix-Benutzer deaktivieren den Listener, indem sie die folgende Zeile (beginnend mit smtp oder 25) in /etc/postfix/master.cf auskommentieren: -

      #smtp      inet  n       -       -       -       -       smtpd
      -

      +
      #smtp      inet  n       -       -       -       -       smtpd
      +

      Außerdem, um über eine Dockerized mailcow weiterzuleiten, sollten Sie 172.22.1.1 als Relayhost hinzufügen und das Docker-Interface aus "inet_interfaces" entfernen:

      -
      postconf -e 'relayhost = 172.22.1.1'
      +
      postconf -e 'relayhost = 172.22.1.1'
       postconf -e "mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128"
       postconf -e "inet_interfaces = loopback-only"
       postconf -e "relay_transport = relay"
       postconf -e "default_transport = smtp"
      -
      +

      Jetzt ist es wichtig, dass Sie nicht denselben FQDN in myhostname haben, den Sie fĂźr Ihre mailcow verwenden. PrĂźfen Sie Ihre lokale (nicht-Docker) Postfix' main.cf auf myhostname und setzen Sie ihn auf etwas anderes, zum Beispiel local.my.fqdn.tld.

      "172.22.1.1" ist das von mailcow erstellte Netzwerk-Gateway in Docker. Das Relaying Ăźber diese Schnittstelle ist notwendig (anstatt - zum Beispiel - direkt Ăźber ${MAILCOW_HOSTNAME}), um Ăźber ein bekanntes internes Netzwerk weiterzuleiten.

      diff --git a/de/post_installation/firststeps-logging/index.html b/de/post_installation/firststeps-logging/index.html index b5ed8bcdd..cd2953ddb 100644 --- a/de/post_installation/firststeps-logging/index.html +++ b/de/post_installation/firststeps-logging/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2466,16 +2466,16 @@ ohne die Fähigkeit zu verlieren, Logs von der UI zu lesen oder verdächtige Cli

      Über docker-compose.override.yml

      Hier ist die gute Nachricht: Da Docker einige großartige Logging-Treiber hat, können Sie mailcow: dockerized mit Leichtigkeit in Ihre bestehende Logging-Umgebung integrieren.

      Erstellen Sie eine docker-compose.override.yml und fĂźgen Sie zum Beispiel diesen Block hinzu, um das "gelf" Logging-Plugin fĂźr postfix-mailcow zu verwenden:

      -
      version: '2.1'
      +
      version: '2.1'
       services:
         postfix-mailcow: # oder ein anderer
           logging:
             driver: "gelf"
             options:
               gelf-address: "udp://graylog:12201"
      -
      +

      Ein weiteres Beispiel fĂźr Syslog:

      -
      version: '2.1'
      +
      version: '2.1'
       services:
       
         postfix-mailcow: # oder ein anderer
      @@ -2506,10 +2506,10 @@ local3.* /var/log/mailcow.logs
       & ~
       
       # Danach rsyslog neu starten.
      -
      +

      Über daemon.json (global)

      Wenn Sie den Logging-Treiber global ändern wollen, editieren Sie die Konfigurationsdatei des Docker-Daemons /etc/docker/daemon.json und starten Sie den Docker-Dienst neu:

      -
      {
      +
      {
       ...
         "log-driver": "gelf",
         "log-opts": {
      @@ -2517,9 +2517,9 @@ local3.* /var/log/mailcow.logs
         }
       ...
       }
      -
      +

      FĂźr Syslog:

      -
      {
      +
      {
       ...
         "log-driver": "syslog",
         "log-opts": {
      @@ -2527,7 +2527,7 @@ local3.* /var/log/mailcow.logs
         }
       ...
       }
      -
      +

      Starten Sie den Docker-Daemon neu und fĂźhren Sie docker-compose down && docker-compose up -d aus, um die Container mit dem neuen Protokollierungstreiber neu zu erstellen.


      diff --git a/de/post_installation/firststeps-rp/index.html b/de/post_installation/firststeps-rp/index.html index dea812617..68a968f2b 100644 --- a/de/post_installation/firststeps-rp/index.html +++ b/de/post_installation/firststeps-rp/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2467,11 +2467,11 @@

      Sie mßssen die Nginx-Seite, die mit mailcow: dockerized geliefert wird, nicht ändern. mailcow: dockerized vertraut auf das Standard-Gateway IP 172.22.1.1 als Proxy.

      1. Stellen Sie sicher, dass Sie HTTP_BIND und HTTPS_BIND in mailcow.conf auf eine lokale Adresse ändern und die Ports entsprechend einstellen, zum Beispiel: -

      HTTP_BIND=127.0.0.1
      +
      HTTP_BIND=127.0.0.1
       HTTP_PORT=8080
       HTTPS_BIND=127.0.0.1
       HTTPS_PORT=8443
      -

      +

      Dadurch werden auch die Bindungen innerhalb des Nginx-Containers geändert! Dies ist wichtig, wenn Sie sich entscheiden, einen Proxy innerhalb von Docker zu verwenden.

      WICHTIG: Verwenden Sie nicht Port 8081, 9081 oder 65510!

      Erzeugen Sie die betroffenen Container neu, indem Sie docker-compose up -d ausfĂźhren.

      @@ -2500,56 +2500,56 @@ Auf vielen Servern wird logrotate den Webserver sowieso täglich neu laden.

      2. Konfigurieren Sie Ihren lokalen Webserver als Reverse Proxy:

      Apache 2.4

      Erforderliche Module: -

      a2enmod rewrite proxy proxy_http headers ssl
      -

      +
      a2enmod rewrite proxy proxy_http headers ssl
      +

      Let's Encrypt wird unserem Rewrite folgen, Zertifikatsanfragen in mailcow werden problemlos funktionieren.

      Die hervorgehobenen Zeilen mĂźssen beachtet werden.

      -
      <VirtualHost *:80>
      -  ServerName ZU MAILCOW HOSTNAMEN ÄNDERN
      -  ServerAlias autodiscover.*
      -  ServerAlias autoconfig.*
      -  RewriteEngine on
      +
      <VirtualHost *:80>
      +  ServerName ZU MAILCOW HOSTNAMEN ÄNDERN
      +  ServerAlias autodiscover.*
      +  ServerAlias autoconfig.*
      +  RewriteEngine on
       
      -  RewriteCond %{HTTPS} off
      -  RewriteRule ^/?(.*) https://%{HTTP_HOST}/$1 [R=301,L]
      +  RewriteCond %{HTTPS} off
      +  RewriteRule ^/?(.*) https://%{HTTP_HOST}/$1 [R=301,L]
       
      -  ProxyPass / http://127.0.0.1:8080/
      -  ProxyPassReverse / http://127.0.0.1:8080/
      -  ProxyPreserveHost On
      -  ProxyAddHeaders On
      -  RequestHeader set X-Forwarded-Proto "http"
      -</VirtualHost>
      -<VirtualHost *:443>
      -  ServerName ZU MAILCOW HOSTNAMEN ÄNDERN
      -  ServerAlias autodiscover.*
      -  ServerAlias autoconfig.*
      +  ProxyPass / http://127.0.0.1:8080/
      +  ProxyPassReverse / http://127.0.0.1:8080/
      +  ProxyPreserveHost On
      +  ProxyAddHeaders On
      +  RequestHeader set X-Forwarded-Proto "http"
      +</VirtualHost>
      +<VirtualHost *:443>
      +  ServerName ZU MAILCOW HOSTNAMEN ÄNDERN
      +  ServerAlias autodiscover.*
      +  ServerAlias autoconfig.*
       
      -  # You should proxy to a plain HTTP session to offload SSL processing
      -  ProxyPass /Microsoft-Server-ActiveSync http://127.0.0.1:8080/Microsoft-Server-ActiveSync connectiontimeout=4000
      -  ProxyPassReverse /Microsoft-Server-ActiveSync http://127.0.0.1:8080/Microsoft-Server-ActiveSync
      -  ProxyPass / http://127.0.0.1:8080/
      -  ProxyPassReverse / http://127.0.0.1:8080/
      -  ProxyPreserveHost On
      -  ProxyAddHeaders On
      -  RequestHeader set X-Forwarded-Proto "https"
      +  # You should proxy to a plain HTTP session to offload SSL processing
      +  ProxyPass /Microsoft-Server-ActiveSync http://127.0.0.1:8080/Microsoft-Server-ActiveSync connectiontimeout=4000
      +  ProxyPassReverse /Microsoft-Server-ActiveSync http://127.0.0.1:8080/Microsoft-Server-ActiveSync
      +  ProxyPass / http://127.0.0.1:8080/
      +  ProxyPassReverse / http://127.0.0.1:8080/
      +  ProxyPreserveHost On
      +  ProxyAddHeaders On
      +  RequestHeader set X-Forwarded-Proto "https"
       
      -  SSLCertificateFile MAILCOW_ORDNER/data/assets/ssl/cert.pem
      -  SSLCertificateKeyFile MAILCOW_ORDNER/data/assets/ssl/key.pem
      +  SSLCertificateFile MAILCOW_ORDNER/data/assets/ssl/cert.pem
      +  SSLCertificateKeyFile MAILCOW_ORDNER/data/assets/ssl/key.pem
       
      -  # Wenn Sie einen HTTPS-Host als Proxy verwenden mĂśchten:
      -  #SSLProxyEngine On
      +  # Wenn Sie einen HTTPS-Host als Proxy verwenden mĂśchten:
      +  #SSLProxyEngine On
       
      -  # Wenn Sie einen Proxy fĂźr einen nicht vertrauenswĂźrdigen HTTPS-Host einrichten wollen:
      -  #SSLProxyVerify none
      -  #SSLProxyCheckPeerCN off
      -  #SSLProxyCheckPeerName off
      -  #SSLProxyCheckPeerExpire off
      -</VirtualHost>
      -
      + # Wenn Sie einen Proxy fĂźr einen nicht vertrauenswĂźrdigen HTTPS-Host einrichten wollen: + #SSLProxyVerify none + #SSLProxyCheckPeerCN off + #SSLProxyCheckPeerName off + #SSLProxyCheckPeerExpire off +</VirtualHost> +

      Nginx

      Let's Encrypt folgt unserem Rewrite, Zertifikatsanfragen funktionieren problemlos.

      Achten Sie auf die hervorgehobenen Zeilen.

      -
      server {
      +
      server {
         listen 80 default_server;
         listen [::]:80 default_server;
         server_name ZU MAILCOW HOSTNAMEN ÄNDERN autodiscover.* autoconfig.*;
      @@ -2600,14 +2600,14 @@ server {
           proxy_busy_buffers_size 512k;
         }
       }
      -
      +

      HAProxy (von der Community unterstĂźtzt)

      Warning

      Dies ist ein nicht unterstĂźtzter Community Beitrag. Sie kĂśnnen gerne Korrekturen bereitstellen.

      Wichtig/Fix erwĂźnscht: Dieses Beispiel leitet nur HTTPS-Verkehr weiter und benutzt nicht den in mailcow eingebauten ACME-Client.

      -
      frontend https-in
      +
      frontend https-in
         bind :::443 v4v6 ssl crt mailcow.pem
         default_backend mailcow
       
      @@ -2616,7 +2616,7 @@ backend mailcow
         http-request set-header X-Forwarded-Proto https if { ssl_fc }
         http-request set-header X-Forwarded-Proto http if !{ ssl_fc }
         server mailcow 127.0.0.1:8080 check
      -
      +

      Traefik v2 (von der Community unterstĂźtzt)

      Warning

      @@ -2627,50 +2627,50 @@ backend mailcow

      Zuallererst werden wir den acme-mailcow-Container deaktivieren, da wir die von traefik bereitgestellten Zertifikate verwenden werden. Dazu müssen wir SKIP_LETS_ENCRYPT=y in unserer mailcow.conf setzen und docker-compose up -d ausführen, um die Änderungen zu übernehmen.

      Dann erstellen wir eine docker-compose.override.yml Datei, um die Hauptdatei docker-compose.yml zu Ăźberschreiben, die sich im Mailcow-Stammverzeichnis befindet.

      -
      version: '2.1'
      +
      version: '2.1'
       
      -services:
      -    nginx-mailcow:
      -      networks:
      -        # Traefiks Netzwerk hinzufĂźgen
      -        web:
      -      labels:
      -        - traefik.enable=true
      -        # Erstellt einen Router namens "moo" fĂźr den Container und richtet eine Regel ein, um den Container mit einer bestimmten Regel zu verknĂźpfen,
      -        # in diesem Fall eine Host-Regel mit unserer MAILCOW_HOSTNAME-Variable.
      -        - traefik.http.routers.moo.rule=Host(`${MAILCOW_HOSTNAME}`)
      -        # Aktiviert tls Ăźber den zuvor erstellten Router.
      -        - traefik.http.routers.moo.tls=true
      -        # Gibt an, welche Art von Cert-Resolver wir verwenden werden, in diesem Fall le (Lets Encrypt).
      -        - traefik.http.routers.moo.tls.certresolver=le
      -        # Erzeugt einen Dienst namens "moo" fĂźr den Container und gibt an, welchen internen Port des Containers
      -        # Traefik die eingehenden Daten weiterleiten soll.
      -        - traefik.http.services.moo.loadbalancer.server.port=${HTTP_PORT}
      -        # Gibt an, welchen Eingangspunkt (externer Port) traefik fĂźr diesen Container abhĂśren soll.
      -        # Websecure ist Port 443, siehe die Datei traefik.toml wie oben.
      -        - traefik.http.routers.moo.entrypoints=websecure
      -        # Stellen Sie sicher, dass traefik das Web-Netzwerk verwendet, nicht das mailcowdockerized_mailcow-network
      -        - traefik.docker.network=web
      +services:
      +    nginx-mailcow:
      +      networks:
      +        # Traefiks Netzwerk hinzufĂźgen
      +        web:
      +      labels:
      +        - traefik.enable=true
      +        # Erstellt einen Router namens "moo" fĂźr den Container und richtet eine Regel ein, um den Container mit einer bestimmten Regel zu verknĂźpfen,
      +        # in diesem Fall eine Host-Regel mit unserer MAILCOW_HOSTNAME-Variable.
      +        - traefik.http.routers.moo.rule=Host(`${MAILCOW_HOSTNAME}`)
      +        # Aktiviert tls Ăźber den zuvor erstellten Router.
      +        - traefik.http.routers.moo.tls=true
      +        # Gibt an, welche Art von Cert-Resolver wir verwenden werden, in diesem Fall le (Lets Encrypt).
      +        - traefik.http.routers.moo.tls.certresolver=le
      +        # Erzeugt einen Dienst namens "moo" fĂźr den Container und gibt an, welchen internen Port des Containers
      +        # Traefik die eingehenden Daten weiterleiten soll.
      +        - traefik.http.services.moo.loadbalancer.server.port=${HTTP_PORT}
      +        # Gibt an, welchen Eingangspunkt (externer Port) traefik fĂźr diesen Container abhĂśren soll.
      +        # Websecure ist Port 443, siehe die Datei traefik.toml wie oben.
      +        - traefik.http.routers.moo.entrypoints=websecure
      +        # Stellen Sie sicher, dass traefik das Web-Netzwerk verwendet, nicht das mailcowdockerized_mailcow-network
      +        - traefik.docker.network=web
       
      -    certdumper:
      -        image: humenius/traefik-certs-dumper
      -        container_name: traefik_certdumper
      -        network_mode: none
      -        volumes:
      -          # mounten Sie den Ordner, der Traefiks `acme.json' Datei enthält
      -          # in diesem Fall wird Traefik von seinem eigenen docker-compose in ../traefik gestartet
      -          - ../traefik/data:/traefik:ro
      -          # SSL-Ordner von mailcow einhängen
      -          - ./data/assets/ssl/:/output:rw
      -        restart: always
      -        environment:
      -          # Ändern Sie dies nur, wenn Sie eine andere Domain für Mailcows Web-Frontend verwenden als in der Standard-Konfiguration
      -          - DOMAIN=${MAILCOW_HOSTNAME}
      +    certdumper:
      +        image: humenius/traefik-certs-dumper
      +        container_name: traefik_certdumper
      +        network_mode: none
      +        volumes:
      +          # mounten Sie den Ordner, der Traefiks `acme.json' Datei enthält
      +          # in diesem Fall wird Traefik von seinem eigenen docker-compose in ../traefik gestartet
      +          - ../traefik/data:/traefik:ro
      +          # SSL-Ordner von mailcow einhängen
      +          - ./data/assets/ssl/:/output:rw
      +        restart: always
      +        environment:
      +          # Ändern Sie dies nur, wenn Sie eine andere Domain für Mailcows Web-Frontend verwenden als in der Standard-Konfiguration
      +          - DOMAIN=${MAILCOW_HOSTNAME}
       
      -networks:
      -  web:
      -    external: true
      -
      +networks: + web: + external: true +

      Starten Sie die neuen Container mit docker-compose up -d.

      Da Traefik 2 ein acme v2 Format verwendet, um ALLE Lizenzen von allen Domains zu speichern, mĂźssen wir einen Weg finden, die Zertifikate auszulagern. Zum GlĂźck haben wir [diesen kleinen Container] (https://hub.docker.com/r/humenius/traefik-certs-dumper), der die Datei acme.json Ăźber ein Volume und eine Variable DOMAIN=example. org, und damit wird der Container die cert.pem und key.pem Dateien ausgeben, dafĂźr lassen wir einfach den traefik-certs-dumper Container laufen, binden das /traefik Volume an den Ordner, in dem unsere acme.json gespeichert ist, binden das /output Volume an unseren mailcow data/assets/ssl/ Ordner, und setzen die DOMAIN=example.org Variable auf die Domain, von der wir die Zertifikate ausgeben wollen.

      Dieser Container überwacht die Datei acme.json auf Änderungen und generiert die Dateien cert.pem und key.pem direkt in data/assets/ssl/, wobei der Pfad mit dem /output-Pfad des Containers verbunden ist.

      @@ -2680,18 +2680,18 @@ Dazu mĂźssen wir SKIP_LETS_ENCRYPT=y in unserer mailcow.conf<

      Optional: Post-Hook-Skript fĂźr nicht-mailcow ACME-Clients

      Die Verwendung eines lokalen Certbots (oder eines anderen ACME-Clients) erfordert den Neustart einiger Container, was Sie mit einem Post-Hook-Skript erledigen kÜnnen. Stellen Sie sicher, dass Sie die Pfade entsprechend ändern: -

      #!/bin/bash
      +
      #!/bin/bash
       cp /etc/letsencrypt/live/my.domain.tld/fullchain.pem /opt/mailcow-dockerized/data/assets/ssl/cert.pem
       cp /etc/letsencrypt/live/my.domain.tld/privkey.pem /opt/mailcow-dockerized/data/assets/ssl/key.pem
       postfix_c=$(docker ps -qaf name=postfix-mailcow)
       dovecot_c=$(docker ps -qaf name=dovecot-mailcow)
       nginx_c=$(docker ps -qaf name=nginx-mailcow)
       docker restart ${postfix_c} ${dovecot_c} ${nginx_c}
      -

      +

      HinzufĂźgen weiterer Servernamen fĂźr mailcow UI

      Wenn Sie vorhaben, einen Servernamen zu verwenden, der nicht MAILCOW_HOSTNAME in Ihrem Reverse-Proxy ist, stellen Sie sicher, dass Sie diesen Namen zuerst in mailcow.conf Ăźber ADDITIONAL_SERVER_NAMES einpflegen. Die Namen mĂźssen durch Kommas getrennt werden und dĂźrfen keine Leerzeichen enthalten. Wenn Sie diesen Schritt Ăźberspringen, kann es sein, dass mailcow auf Ihren Reverse-Proxy mit einer falschen Seite antwortet.

      -
      ADDITIONAL_SERVER_NAMES=webmail.domain.tld,other.example.tld
      -
      +
      ADDITIONAL_SERVER_NAMES=webmail.domain.tld,other.example.tld
      +

      FĂźhren Sie docker-compose up -d zum Anwenden aus.


      diff --git a/de/post_installation/firststeps-rspamd_ui/index.html b/de/post_installation/firststeps-rspamd_ui/index.html index 61a00a3a5..906ae17cf 100644 --- a/de/post_installation/firststeps-rspamd_ui/index.html +++ b/de/post_installation/firststeps-rspamd_ui/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/post_installation/firststeps-snat/index.html b/de/post_installation/firststeps-snat/index.html index 1f57ddda9..d3a58d591 100644 --- a/de/post_installation/firststeps-snat/index.html +++ b/de/post_installation/firststeps-snat/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,12 +2348,12 @@

      SNAT wird verwendet, um die Quelladresse der von mailcow gesendeten Pakete zu ändern. Es kann verwendet werden, um die ausgehende IP-Adresse auf Systemen mit mehreren IP-Adressen zu ändern.

      Öffnen Sie mailcow.conf, setzen Sie einen oder beide der folgenden Parameter:

      -
      # Benutze diese IPv4 fĂźr ausgehende Verbindungen (SNAT)
      +
      # Benutze diese IPv4 fĂźr ausgehende Verbindungen (SNAT)
       SNAT_TO_SOURCE=1.2.3.4
       
       # Benutze dieses IPv6 fĂźr ausgehende Verbindungen (SNAT)
       SNAT6_TO_SOURCE=dead:beef
      -
      +

      FĂźhren Sie docker-compose up -d aus.

      Die Werte werden von netfilter-mailcow gelesen. netfilter-mailcow stellt sicher, dass die Post-Routing-Regeln auf Position 1 in der Netfilter-Tabelle stehen. Es lĂśscht sie automatisch und legt sie neu an, wenn sie an einer anderen Position als 1 gefunden werden.

      Überprüfen Sie die Ausgabe von docker-compose logs --tail=200 netfilter-mailcow, um sicherzustellen, dass die SNAT-Einstellungen angewendet wurden.

      diff --git a/de/post_installation/firststeps-ssl/index.html b/de/post_installation/firststeps-ssl/index.html index 8e470b30b..4fce209bf 100644 --- a/de/post_installation/firststeps-ssl/index.html +++ b/de/post_installation/firststeps-ssl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2586,8 +2586,8 @@

      Zusätzliche Domain-Namen

      Bearbeiten Sie "mailcow.conf" und fĂźgen Sie einen Parameter ADDITIONAL_SAN wie folgt hinzu:

      Verwenden Sie keine AnfĂźhrungszeichen (") und keine Leerzeichen zwischen den Namen!

      -
      ADDITIONAL_SAN=smtp.*,cert1.example.com,cert2.example.org,whatever.*
      -
      +
      ADDITIONAL_SAN=smtp.*,cert1.example.com,cert2.example.org,whatever.*
      +

      Jeder Name wird anhand seiner IPv6-Adresse oder - wenn IPv6 in Ihrer Domäne nicht konfiguriert ist - anhand seiner IPv4-Adresse ßberprßft.

      Ein Wildcard-Name wie smtp.* wird versuchen, ein smtp.DOMAIN_NAME SAN fĂźr jede zu mailcow hinzugefĂźgte Domain zu erhalten.

      FĂźhren Sie docker-compose up -d aus, um betroffene Container automatisch neu zu erstellen.

      @@ -2596,17 +2596,17 @@

      Die Verwendung anderer Namen als MAILCOW_HOSTNAME fĂźr den Zugriff auf das mailcow UI kann weitere Konfiguration erfordern.

      Wenn Sie planen, einen anderen Servernamen als MAILCOW_HOSTNAME fĂźr den Zugriff auf die mailcow UI zu verwenden (z.B. durch HinzufĂźgen von mail.* zu ADDITIONAL_SAN), stellen Sie sicher, dass Sie diesen Namen in mailcow.conf Ăźber ADDITIONAL_SERVER_NAMES eintragen. Die Namen mĂźssen durch Kommas getrennt sein und dĂźrfen keine Leerzeichen enthalten. Wenn Sie diesen Schritt auslassen, kann mailcow mit einer falschen Seite antworten.

      -
      ADDITIONAL_SERVER_NAMES=webmail.domain.tld,other.example.tld
      -
      +
      ADDITIONAL_SERVER_NAMES=webmail.domain.tld,other.example.tld
      +

      FĂźhren Sie docker-compose up -d aus, um es anzuwenden.

      Erneuerung erzwingen

      Um eine Erneuerung zu erzwingen, mĂźssen Sie eine Datei namens force_renew erstellen und den acme-mailcow Container neu starten:

      -
      cd /opt/mailcow-dockerized
      +
      cd /opt/mailcow-dockerized
       touch data/assets/ssl/force_renew
       docker-compose restart acme-mailcow
       # PrĂźfen Sie nun die Logs auf eine Erneuerung
       docker-compose logs --tail=200 -f acme-mailcow
      -
      +

      Die Datei wird automatisch gelĂśscht.

      Validierungsfehler und wie man die Validierung Ăźberspringt

      Sie können die IP-Überprüfung überspringen, indem Sie SKIP_IP_CHECK=y in mailcow.conf setzen (keine Anführungszeichen). Seien Sie gewarnt, dass eine Fehlkonfiguration dazu führt, dass Sie von Let's Encrypt eingeschränkt werden! Dies ist vor allem für Multi-IP-Setups nützlich, bei denen der IP-Check die falsche Quell-IP-Adresse zurückgeben würde. Aufgrund der Verwendung von dynamischen IPs für acme-mailcow ist Source-NAT bei Neustarts nicht konsistent.

      @@ -2653,35 +2653,35 @@ Sie sollten sicherstellen, dass diese Clients den MAILCOW_HOSTNAME

      Um Ihre eigenen Zertifikate zu verwenden, speichern Sie einfach das kombinierte Zertifikat (mit dem Zertifikat und der zwischengeschalteten CA/CA, falls vorhanden) unter data/assets/ssl/cert.pem und den entsprechenden SchlĂźssel unter data/assets/ssl/key.pem.

      WICHTIG: Verwenden Sie keine symbolischen Links! Stellen Sie sicher, dass Sie die Zertifikate kopieren und sie nicht mit data/assets/ssl verknĂźpfen.

      Starten Sie die betroffenen Dienste anschließend neu:

      -
      docker restart $(docker ps -qaf name=postfix-mailcow)
      +
      docker restart $(docker ps -qaf name=postfix-mailcow)
       docker neu starten $(docker ps -qaf name=nginx-mailcow)
       docker restart $(docker ps -qaf name=dovecot-mailcow)
      -
      +

      Siehe Post-Hook-Skript fßr Nicht-Mailcow-ACME-Clients fßr ein vollständiges Beispielskript.

      Test gegen das ACME-Verzeichnis

      Bearbeiten Sie mailcow.conf und fĂźgen Sie LE_STAGING=y hinzu.

      Führen Sie docker-compose up -d aus, um Ihre Änderungen zu aktivieren.

      Benutzerdefinierte Verzeichnis-URL

      Editieren Sie mailcow.conf und fĂźgen Sie die entsprechende Verzeichnis-URL in die neue Variable DIRECTORY_URL ein:

      -
      DIRECTORY_URL=https://acme-custom-v9000.api.letsencrypt.org/directory
      -
      +
      DIRECTORY_URL=https://acme-custom-v9000.api.letsencrypt.org/directory
      +

      Sie kĂśnnen LE_STAGING nicht mit DIRECTORY_URL verwenden. Wenn beide gesetzt sind, wird nur LE_STAGING verwendet.

      Führen Sie docker-compose up -d aus, um Ihre Änderungen zu aktivieren.

      Überprüfen Sie Ihre Konfiguration

      Fßhren Sie docker-compose logs acme-mailcow aus, um herauszufinden, warum eine Validierung fehlschlägt.

      Um zu ĂźberprĂźfen, ob nginx das richtige Zertifikat verwendet, benutzen Sie einfach einen Browser Ihrer Wahl und ĂźberprĂźfen Sie das angezeigte Zertifikat.

      Um das von Postfix, Dovecot und Nginx verwendete Zertifikat zu ĂźberprĂźfen, verwenden wir openssl:

      -
      # Verbindung Ăźber SMTP (587)
      +
      # Verbindung Ăźber SMTP (587)
       echo "Q" | openssl s_client -starttls smtp -crlf -connect mx.mailcow.email:587
       # Verbindung Ăźber IMAP (143)
       echo "Q" | openssl s_client -starttls imap -showcerts -connect mx.mailcow.email:143
       # Verbindung Ăźber HTTPS (443)
       echo "Q" | openssl s_client -connect mx.mailcow.email:443
      -
      +

      Um die von openssl zurĂźckgegebenen Verfallsdaten gegen MAILCOW_HOSTNAME zu validieren, kĂśnnen Sie unser Hilfsskript verwenden:

      -
      cd /opt/mailcow-dockerized
      +
      cd /opt/mailcow-dockerized
       bash helper-scripts/expiry-dates.sh
      -
      +

      diff --git a/de/post_installation/firststeps-sync_jobs_migration/index.html b/de/post_installation/firststeps-sync_jobs_migration/index.html index 264bbfa3a..619cbc405 100644 --- a/de/post_installation/firststeps-sync_jobs_migration/index.html +++ b/de/post_installation/firststeps-sync_jobs_migration/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/prerequisite/prerequisite-dns/index.html b/de/prerequisite/prerequisite-dns/index.html index 31c650e31..0001e7fe8 100644 --- a/de/prerequisite/prerequisite-dns/index.html +++ b/de/prerequisite/prerequisite-dns/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2548,28 +2548,28 @@

      Stellen Sie sicher, dass der PTR-Eintrag Ihrer IP-Adresse mit dem FQDN Ihres mailcow-Hosts Ăźbereinstimmt: ${MAILCOW_HOSTNAME} 1. Dieser Eintrag wird normalerweise bei dem Provider gesetzt, von dem Sie die IP-Adresse (Server) gemietet haben.

      Die minimale DNS-Konfiguration

      Dieses Beispiel zeigt Ihnen eine Reihe von Einträgen fßr eine von mailcow verwaltete Domain. Jede Domain, die zu mailcow hinzugefßgt wird, benÜtigt mindestens diesen Satz an Einträgen, um korrekt zu funktionieren.

      -
      # Name Typ Wert
      +
      # Name Typ Wert
       mail IN A 1.2.3.4
       autodiscover IN CNAME mail.example.org. (Ihr ${MAILCOW_HOSTNAME})
       autoconfig IN CNAME mail.example.org. (Ihr ${MAILCOW_HOSTNAME})
       @ IN MX 10 mail.example.org. (Ihr ${MAILCOW_HOSTNAME})
      -
      +

      DKIM, SPF und DMARC

      Im folgenden Beispiel fßr eine DNS-Zonendatei wird ein einfacher SPF TXT-Eintrag verwendet, um nur DIESEM Server (dem MX) zu erlauben, E-Mails fßr Ihre Domäne zu senden. Jeder andere Server ist nicht zugelassen, kann es aber tun ("~all"). Weitere Informationen finden Sie im SPF-Projekt.

      -
      # Name Typ Wert
      +
      # Name Typ Wert
       @ IN TXT "v=spf1 mx a -all"
      -
      +

      Es wird dringend empfohlen, einen DKIM TXT-Eintrag in Ihrer mailcow UI zu erstellen und den entsprechenden TXT-Eintrag in Ihren DNS-Einträgen zu setzen. Bitte lesen Sie OpenDKIM fßr weitere Informationen.

      -
      # Name Typ Wert
      +
      # Name Typ Wert
       dkim._domainkey IN TXT "v=DKIM1; k=rsa; t=s; s=email; p=..."
      -
      +

      Der letzte Schritt, um sich selbst und andere zu schĂźtzen, ist die Implementierung eines DMARC TXT-Datensatzes, zum Beispiel mit Hilfe des DMARC-Assistenten (check).

      -
      # Name Typ Wert
      +
      # Name Typ Wert
       _dmarc IN TXT "v=DMARC1; p=reject; rua=mailto:mailauth-reports@example.org"
      -
      +

      Die erweiterte DNS-Konfiguration

      SRV-Einträge geben den/die Server fßr ein bestimmtes Protokoll in Ihrer Domäne an. Wenn Sie einen Dienst explizit als nicht bereitgestellt ankßndigen wollen, geben Sie "." als Zieladresse an (statt "mail.example.org."). Bitte beachten Sie RFC 2782.

      -
      # Name Typ Priorität Gewicht Port Wert
      +
      # Name Typ Priorität Gewicht Port Wert
       _autodiscover._tcp IN SRV 0 1 443 mail.example.org. (Ihr ${MAILCOW_HOSTNAME})
       _caldavs._tcp IN SRV 0 1 443 mail.example.org. (Ihr ${MAILCOW_HOSTNAME})
       _caldavs._tcp IN TXT "path=/SOGo/dav/"
      @@ -2582,7 +2582,7 @@ _pop3s._tcp IN SRV 0 1 995 mail.example.org. (Ihr ${MAILCOW_HOSTNAME})
       _sieve._tcp IN SRV 0 1 4190 mail.example.org. (Ihr ${MAILCOW_HOSTNAME})
       _smtps._tcp IN SRV 0 1 465 mail.example.org. (Ihr ${MAILCOW_HOSTNAME})
       _submission._tcp IN SRV 0 1 587 mail.example.org. (Ihr ${MAILCOW_HOSTNAME})
      -
      +

      Testen

      Hier finden Sie einige Tools, mit denen Sie Ihre DNS-Konfiguration ĂźberprĂźfen kĂśnnen:

        @@ -2613,7 +2613,7 @@ _submission._tcp IN SRV 0 1 587 mail.example.org. (Ihr ${MAILCOW_HOSTNAME})

        Diese Dienste stellen Ihnen mÜglicherweise einen TXT-Eintrag zur Verfßgung, den Sie in Ihre DNS-Einträge einfßgen mßssen, so wie es der Anbieter vorschreibt. Bitte stellen Sie sicher, dass Sie die Dokumentation des Anbieters des von Ihnen gewählten Dienstes lesen, da dieser Prozess variieren kann.

        E-Mail-Test fĂźr SPF, DKIM und DMARC:

        Um eine rudimentäre E-Mail-Authentifizierungsprßfung durchzufßhren, senden Sie eine E-Mail an check-auth at verifier.port25.com und warten Sie auf eine Antwort. Sie werden einen Bericht ähnlich dem folgenden finden:

        -
        ==========================================================
        +
        ==========================================================
         Zusammenfassung der Ergebnisse
         ==========================================================
         SPF-PrĂźfung: bestanden
        @@ -2626,7 +2626,7 @@ SpamAssassin-PrĂźfung: ham
         Einzelheiten:
         ==========================================================
         ....
        -
        +

        Der vollständige Bericht enthält weitere technische Details.

        Fully Qualified Domain Name (FQDN)

        diff --git a/de/prerequisite/prerequisite-system/index.html b/de/prerequisite/prerequisite-system/index.html index 22f7f67a7..1d84a4b7c 100644 --- a/de/prerequisite/prerequisite-system/index.html +++ b/de/prerequisite/prerequisite-system/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2569,10 +2569,10 @@

        Im Rahmen unseres Supports kĂśnnen wir Ihnen bei der korrekten Planung Ihres Setups helfen.

        Firewall & Ports

        Bitte ĂźberprĂźfen Sie, ob alle Standard-Ports von mailcow offen sind und nicht von anderen Anwendungen genutzt werden:

        -
        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'
         # oder:
         netstat -tulpn | grep -E -w '25|80|110|143|443|465|587|993|995|4190'
        -
        +

        Warnung

        Es gibt einige Probleme mit dem Betrieb von mailcow auf einem Firewalld/ufw aktivierten System. Sie sollten es deaktivieren (wenn mÜglich) und stattdessen Ihren Regelsatz in die DOCKER-USER-Kette verschieben, die nicht durch einen Neustart des Docker-Dienstes gelÜscht wird. Siehe diese (blog.donnex.net) oder diese (unrouted.io) Anleitung fßr Informationen darßber, wie man iptables-persistent mit der DOCKER-USER Kette benutzt. @@ -2665,34 +2665,34 @@ Da mailcow im Docker-Modus läuft, haben INPUT-Regeln keinen Effekt auf die Besc

        Port 53 ist in diesem Fall fĂźr die Firewall-Konfiguration unwichtig. Laut Dokumentation verwendet unbound den Portbereich 1024-65535 fĂźr ausgehende Anfragen. Da es sich bei der Hetzner Robot Firewall um eine statische Firewall handelt (jedes eingehende Paket wird isoliert geprĂźft) - mĂźssen die folgenden Regeln angewendet werden:

        FĂźr TCP -

        SRC-IP: ---
        +
        SRC-IP: ---
         DST-IP: ---
         SRC-Port: ---
         DST-Port: 1024-65535
         Protokoll: tcp
         TCP-Flags: ack
         Aktion:      Akzeptieren
        -

        +

        FĂźr UDP -

        SRC-IP: ---
        +
        SRC-IP: ---
         DST-IP: ---
         SRC-Port: ---
         DST-Port: 1024-65535
         Protokoll: udp
         Aktion:      Akzeptieren
        -

        +

        Wenn man einen restriktiveren Portbereich anwenden will, muss man zuerst die Konfiguration von unbound ändern (nach der Installation):

        {mailcow-dockerized}/data/conf/unbound/unbound.conf: -

        ausgehender-Port-vermeiden: 0-32767
        -

        +
        ausgehender-Port-vermeiden: 0-32767
        +

        Nun kĂśnnen die Firewall-Regeln wie folgt angepasst werden:

        -
        [...]
        +
        [...]
         DST Port: 32768-65535
         [...]
        -
        +

        Datum und Uhrzeit

        Um sicherzustellen, dass Sie das richtige Datum und die richtige Zeit auf Ihrem System eingestellt haben, ĂźberprĂźfen Sie bitte die Ausgabe von timedatectl status:

        -
        $ timedatectl status
        +
        $ timedatectl status
               Lokale Zeit: Sat 2017-05-06 02:12:33 CEST
           Weltzeit: Sa 2017-05-06 00:12:33 UTC
                 RTC-Zeit: Sa 2017-05-06 00:12:32
        @@ -2707,22 +2707,22 @@ NTP synchronisiert: ja
          Nächste Sommerzeitänderung: Die Sommerzeit endet (die Uhr springt eine Stunde rßckwärts) am
                           Sun 2017-10-29 02:59:59 MESZ
                           Sun 2017-10-29 02:00:00 MEZ
        -
        +

        Die Zeilen NTP aktiviert: ja und NTP synchronisiert: ja zeigen an, ob Sie NTP aktiviert haben und ob es synchronisiert ist.

        Um NTP zu aktivieren, mĂźssen Sie den Befehl timedatectl set-ntp true ausfĂźhren. Sie mĂźssen auch Ihre /etc/systemd/timesyncd.conf bearbeiten:

        -
        # vim /etc/systemd/timesyncd.conf
        +
        # vim /etc/systemd/timesyncd.conf
         [Zeit]
         NTP=0.pool.ntp.org 1.pool.ntp.org 2.pool.ntp.org 3.pool.ntp.org
        -
        +

        Hetzner Cloud (und wahrscheinlich andere)

        Prßfen Sie /etc/network/interfaces.d/50-cloud-init.cfg und ändern Sie die IPv6-Schnittstelle von eth0:0 auf eth0:

        -
        # Falsch:
        +
        # Falsch:
         auto eth0:0
         iface eth0:0 inet6 static
         # Richtig:
         auto eth0
         iface eth0 inet6 static
        -
        +

        Starten Sie die Schnittstelle neu, um die Einstellungen zu übernehmen. Sie können außerdem die cloud-init Netzwerkänderungen deaktivieren.

        MTU

        diff --git a/de/third_party/third_party-borgmatic/index.html b/de/third_party/third_party-borgmatic/index.html index 41ef0f0b8..fdce30ec0 100644 --- a/de/third_party/third_party-borgmatic/index.html +++ b/de/third_party/third_party-borgmatic/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2659,43 +2659,43 @@ Diese Anleitung behandelt nur die Grundlagen.

        Erstellen oder ändern Sie docker-compose.override.yml

        Im mailcow-dockerized Stammverzeichnis erstellen oder bearbeiten Sie docker-compose.override.yml und fĂźgen Sie die folgende Konfiguration ein: -

        version: '2.1'
        +
        version: '2.1'
         
        -services:
        -  borgmatic-mailcow:
        -    image: b3vis/borgmatic
        -    hostname: mailcow
        -    restart: always
        -    dns: ${IPV4_NETWORK:-172.22.1}.254
        -    volumes:
        -      - vmail-vol-1:/mnt/source/vmail:ro
        -      - crypt-vol-1:/mnt/source/crypt:ro
        -      - redis-vol-1:/mnt/source/redis:ro,z
        -      - rspamd-vol-1:/mnt/source/rspamd:ro,z
        -      - postfix-vol-1:/mnt/source/postfix:ro,z
        -      - mysql-socket-vol-1:/var/run/mysqld/:z
        -      - borg-config-vol-1:/root/.config/borg:Z
        -      - borg-cache-vol-1:/root/.cache/borg:Z
        -      - ./data/conf/borgmatic/etc:/etc/borgmatic.d:Z
        -      - ./data/conf/borgmatic/ssh:/root/.ssh:Z
        -    environment:
        -      - TZ=${TZ}
        -      - BORG_PASSPHRASE=YouBetterPutSomethingRealGoodHere
        -    networks:
        -      mailcow-network:
        -        aliases:
        -          - borgmatic
        +services:
        +  borgmatic-mailcow:
        +    image: b3vis/borgmatic
        +    hostname: mailcow
        +    restart: always
        +    dns: ${IPV4_NETWORK:-172.22.1}.254
        +    volumes:
        +      - vmail-vol-1:/mnt/source/vmail:ro
        +      - crypt-vol-1:/mnt/source/crypt:ro
        +      - redis-vol-1:/mnt/source/redis:ro,z
        +      - rspamd-vol-1:/mnt/source/rspamd:ro,z
        +      - postfix-vol-1:/mnt/source/postfix:ro,z
        +      - mysql-socket-vol-1:/var/run/mysqld/:z
        +      - borg-config-vol-1:/root/.config/borg:Z
        +      - borg-cache-vol-1:/root/.cache/borg:Z
        +      - ./data/conf/borgmatic/etc:/etc/borgmatic.d:Z
        +      - ./data/conf/borgmatic/ssh:/root/.ssh:Z
        +    environment:
        +      - TZ=${TZ}
        +      - BORG_PASSPHRASE=YouBetterPutSomethingRealGoodHere
        +    networks:
        +      mailcow-network:
        +        aliases:
        +          - borgmatic
         
        -volumes:
        -  borg-cache-vol-1:
        -  borg-config-vol-1:
        -

        +volumes: + borg-cache-vol-1: + borg-config-vol-1: +

        Stellen Sie sicher, dass Sie die BORG_PASSPHRASE in eine sichere Passphrase Ihrer Wahl ändern.

        Aus Sicherheitsgrßnden mounten wir das maildir als schreibgeschßtzt. Wenn Sie später Daten wiederherstellen wollen, mßssen Sie das mßssen Sie das ro-Flag entfernen, bevor Sie die Daten wiederherstellen. Dies wird im Abschnitt ßber die Wiederherstellung von Backups beschrieben.

        Erstellen Sie data/conf/borgmatic/etc/config.yaml

        Als nächstes mßssen wir die borgmatic-Konfiguration erstellen.

        -
        source mailcow.conf
        +
        source mailcow.conf
         cat <<EOF > data/conf/borgmatic/etc/config.yaml
         location:
             source_directories:
        @@ -2721,7 +2721,7 @@ cat <<EOF > data/conf/borgmatic/etc/config.yaml
                   password: ${DBPASS}
                   options: --default-character-set=utf8mb4
         EOF
        -
        +

        Das Erstellen der Datei auf diese Weise stellt sicher, dass die korrekten MySQL-Zugangsdaten aus mailcow.conf Ăźbernommen werden.

        Diese Datei ist ein minimales Beispiel fĂźr die Verwendung von borgmatic mit einem Konto user beim Cloud-Speicheranbieter rsync.net fĂźr ein Repository namens mailcow (siehe repositories Einstellung). Es wird sowohl das maildir als auch die MySQL-Datenbank sichern, was alles ist @@ -2737,8 +2737,8 @@ Container einbinden. Der Container definiert zu diesem Zweck ein Volume namens <

        Erstellen Sie einen crontab

        Erstellen Sie eine neue Textdatei in data/conf/borgmatic/etc/crontab.txt mit folgendem Inhalt:

        -
        14 * * * * PATH=$PATH:/usr/bin /usr/bin/borgmatic --stats -v 0 2>&1
        -
        +
        14 * * * * PATH=$PATH:/usr/bin /usr/bin/borgmatic --stats -v 0 2>&1
        +

        Diese Datei erwartet eine crontab-Syntax. Das hier gezeigte Beispiel veranlasst das Backup, jede Stunde um 14 Minuten nach nach der vollen Stunde auszufĂźhren und am Ende einige nette Statistiken zu protokollieren.

        SSH-SchlĂźssel in Ordner ablegen

        @@ -2747,8 +2747,8 @@ nach der vollen Stunde auszufĂźhren und am Ende einige nette Statistiken zu prot oder OpenSSH wird sich weigern, den SSH-SchlĂźssel zu benutzen.

        Den Container hochfahren

        Fßr den nächsten Schritt mßssen wir den Container in einem konfigurierten Zustand hochfahren und laufen lassen. Um das zu tun, fßhren Sie aus:

        -
        docker-compose up -d
        -
        +
        docker-compose up -d
        +

        Wiederherstellung von einem Backup

        Das Wiederherstellen eines Backups setzt voraus, dass Sie mit einer neuen Installation von mailcow beginnen, und dass Sie derzeit keine keine benutzerdefinierten Daten in ihrem maildir oder ihrer mailcow Datenbank.

        @@ -2768,8 +2768,8 @@ dieses Volume zu schreiben.

        Bevor Sie eine Wiederherstellung durchfĂźhren, mĂźssen Sie das vmail-Volume in docker-compose.override.yml beschreibbar machen, indem Sie das das ro-Flag aus dem Volume entfernen. Dann kĂśnnen Sie den folgenden Befehl verwenden, um das Maildir aus einem Backup wiederherzustellen:

        -
        docker-compose exec borgmatic-mailcow borgmatic extract --path mnt/source --archive latest
        -
        +
        docker-compose exec borgmatic-mailcow borgmatic extract --path mnt/source --archive latest
        +

        Alternativ kĂśnnen Sie auch einen beliebigen Archivnamen aus der Liste der Archive angeben (siehe Auflistung aller verfĂźgbaren Archive)

        MySQL wiederherstellen

        @@ -2778,30 +2778,30 @@ Dann kĂśnnen Sie den folgenden Befehl verwenden, um das Maildir aus einem Backup

        Die AusfĂźhrung dieses Befehls lĂśscht und erstellt die mailcow-Datenbank neu! FĂźhren sie diesen Befehl nicht aus, es sei denn sie beabsichtigen, die mailcow-Datenbank von einem Backup wiederherzustellen.

        Um die MySQL-Datenbank aus dem letzten Archiv wiederherzustellen, verwenden Sie diesen Befehl:

        -
        docker-compose exec borgmatic-mailcow borgmatic restore --archive latest
        -
        +
        docker-compose exec borgmatic-mailcow borgmatic restore --archive latest
        +

        Alternativ kĂśnnen Sie auch einen beliebigen Archivnamen aus der Liste der Archive angeben (siehe Auflistung aller verfĂźgbaren Archive)

        Nach der Wiederherstellung

        Nach der Wiederherstellung mßssen Sie mailcow neu starten. Wenn Sie den SELinux-Erzwingungsmodus deaktiviert haben, wäre jetzt ein guter Zeitpunkt, um ihn wieder zu aktivieren.

        Um mailcow neu zu starten, verwenden Sie den folgenden Befehl:

        -
        docker-compose down && docker-compose up -d
        -
        +
        docker-compose down && docker-compose up -d
        +

        Wenn Sie SELinux verwenden, werden dadurch auch alle Dateien in Ihrem vmail-Volume neu benannt. Seien Sie geduldig, denn dies kann eine Weile dauern kann, wenn Sie viele Dateien haben.

        NĂźtzliche Befehle

        Manueller Archivierungslauf (mit Debugging-Ausgabe)

        -
        docker-compose exec borgmatic-mailcow borgmatic -v 2
        -
        +
        docker-compose exec borgmatic-mailcow borgmatic -v 2
        +

        Auflistung aller verfĂźgbaren Archive

        -
        docker-compose exec borgmatic-mailcow borgmatic list
        -
        +
        docker-compose exec borgmatic-mailcow borgmatic list
        +

        Sperre aufheben

        Wenn borg während eines Archivierungslaufs unterbrochen wird, hinterlässt es eine veraltete Sperre, die gelÜscht werden muss, bevor neue Operationen durchgefßhrt werden kÜnnen:

        -
        docker-compose exec borgmatic-mailcow borg break-lock user@rsync.net:mailcow
        -
        +
        docker-compose exec borgmatic-mailcow borg break-lock user@rsync.net:mailcow
        +

        Wobei user@rsync.net:mailcow die URI zu Ihrem Repository ist.

        Jetzt wäre ein guter Zeitpunkt, einen manuellen Archivierungslauf durchzufßhren, um sicherzustellen, dass er erfolgreich durchgefßhrt werden kann.

        Exportieren von SchlĂźsseln

        @@ -2810,8 +2810,8 @@ SchlĂźsseldateien werden erzeugt, wenn Sie das Repository initialisieren. Die

        Beachten Sie, dass Sie in beiden Fällen auch die Passphrase haben mßssen, um die Archive zu entschlßsseln.

        Um die keyfile zu holen, fĂźhren Sie aus:

        -
        docker-compose exec borgmatic-mailcow borg key export --paper user@rsync.net:mailcow
        -
        +
        docker-compose exec borgmatic-mailcow borg key export --paper user@rsync.net:mailcow
        +

        Wobei user@rsync.net:mailcow die URI zu Ihrem Repository ist.


        diff --git a/de/third_party/third_party-exchange_onprem/index.html b/de/third_party/third_party-exchange_onprem/index.html index 89287ebe1..56de44cf5 100644 --- a/de/third_party/third_party-exchange_onprem/index.html +++ b/de/third_party/third_party-exchange_onprem/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/third_party/third_party-gitea/index.html b/de/third_party/third_party-gitea/index.html index e551190a8..ea2db2d85 100644 --- a/de/third_party/third_party-gitea/index.html +++ b/de/third_party/third_party-gitea/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2347,7 +2347,7 @@

        Mit der Fähigkeit von Gitea, sich über SMTP zu authentifizieren, ist es trivial, es mit mailcow zu integrieren. Es sind nur wenige Änderungen erforderlich:

        1. Öffnen Sie docker-compose.override.yml und fügen Sie Gitea hinzu:

        -
        version: '2.1'
        +
        version: '2.1'
         services:
         
                 gitea-mailcow:
        @@ -2360,28 +2360,28 @@ services:
                                 - gitea
                     ports:
                         - "${GITEA_SSH_PORT:-127.0.0.1:4000}:22"
        -
        +

        2. Erstellen Sie data/conf/nginx/site.gitea.custom, fĂźgen Sie folgendes hinzu: -

        location /gitea/ {
        +
        location /gitea/ {
                 proxy_pass http://gitea:3000/;
         }
        -

        +

        3. Öffne mailcow.conf und definiere den Port Bind, den Gitea für SSH verwenden soll. Beispiel:

        -
        GITEA_SSH_PORT=127.0.0.1:4000
        -
        +
        GITEA_SSH_PORT=127.0.0.1:4000
        +

        5. Führen Sie docker-compose up -d aus, um den Gitea-Container hochzufahren und führen Sie anschließend docker-compose restart nginx-mailcow aus.

        6. Wenn Sie mailcow zu https gezwungen haben, fĂźhren Sie Schritt 9 aus und starten Sie gitea mit docker-compose restart gitea-mailcow neu. Fahren Sie mit Schritt 7 fort (Denken Sie daran, https anstelle von http zu verwenden, https://mx.example.org/gitea/

        7. Öffnen Sie http://${MAILCOW_HOSTNAME}/gitea/, zum Beispiel http://mx.example.org/gitea/. Für die Datenbankdetails stellen Sie mysql als Datenbankhost ein. Verwenden Sie den in mailcow.conf gefundenen Wert von DBNAME als Datenbankname, DBUSER als Datenbankbenutzer und DBPASS als Datenbankpasswort.

        8. Sobald die Installation abgeschlossen ist, loggen Sie sich als Administrator ein und setzen Sie "Einstellungen" -> "Autorisierung" -> "SMTP aktivieren". SMTP-Host sollte postfix mit Port 587 sein, setzen Sie Skip TLS Verify, da wir ein nicht gelistetes SAN verwenden ("postfix" ist hĂśchstwahrscheinlich nicht Teil Ihres Zertifikats).

        9. Erstellen Sie data/gitea/gitea/conf/app.ini und setzen Sie die folgenden Werte. Sie kĂśnnen gitea cheat sheet, leider bisher nur in Englisch verfĂźgbar fĂźr deren Bedeutung und andere mĂśgliche Werte konsultieren.

        -
        [server]
        +
        [server]
         SSH_LISTEN_PORT = 22
         # FĂźr GITEA_SSH_PORT=127.0.0.1:4000 in mailcow.conf, setzen:
         SSH_DOMAIN = 127.0.0.1
         SSH_PORT = 4000
         # FĂźr MAILCOW_HOSTNAME=mx.example.org in mailcow.conf (und Standard-Ports fĂźr HTTPS), setzen:
         ROOT_URL = https://mx.example.org/gitea/
        -
        +

        10. Starten Sie gitea neu mit docker-compose restart gitea-mailcow. Ihre Nutzer sollten in der Lage sein, sich mit von mailcow verwalteten Konten anzumelden.


        diff --git a/de/third_party/third_party-gogs/index.html b/de/third_party/third_party-gogs/index.html index 6317c991d..436b12ae5 100644 --- a/de/third_party/third_party-gogs/index.html +++ b/de/third_party/third_party-gogs/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2347,7 +2347,7 @@

        Mit Gogs' Fähigkeit, sich über SMTP zu authentifizieren, ist es einfach, es mit mailcow zu verbinden. Es sind nur wenige Änderungen erforderlich:

        1. Öffne docker-compose.override.yml und füge Gogs hinzu:

        -
        version: '2.1'
        +
        version: '2.1'
         services:
         
             gogs-mailcow:
        @@ -2360,27 +2360,27 @@ services:
                     - gogs
               ports:
                 - "${GOGS_SSH_PORT:-127.0.0.1:4000}:22"
        -
        +

        2. Erstelle data/conf/nginx/site.gogs.custom, fĂźge hinzu: -

        location /gogs/ {
        +
        location /gogs/ {
             proxy_pass http://gogs:3000/;
         }
        -

        +

        3. Öffne mailcow.conf und definiere die Bindung, die Gogs für SSH verwenden soll. Beispiel:

        -
        GOGS_SSH_PORT=127.0.0.1:4000
        -
        +
        GOGS_SSH_PORT=127.0.0.1:4000
        +

        5. Führen Sie docker-compose up -d aus, um den Gogs-Container hochzufahren und führen Sie anschließend docker-compose restart nginx-mailcow aus.

        6. Öffnen Sie http://${MAILCOW_HOSTNAME}/gogs/, zum Beispiel http://mx.example.org/gogs/. Für Datenbank-Details setzen Sie mysql als Datenbank-Host. Verwenden Sie den in mailcow.conf gefundenen Wert von DBNAME als Datenbankname, DBUSER als Datenbankbenutzer und DBPASS als Datenbankpasswort.

        7. Sobald die Installation abgeschlossen ist, loggen Sie sich als Administrator ein und setzen Sie "Einstellungen" -> "Autorisierung" -> "SMTP aktivieren". SMTP-Host sollte postfix mit Port 587 sein, setzen Sie Skip TLS Verify, da wir ein nicht gelistetes SAN verwenden ("postfix" ist hĂśchstwahrscheinlich nicht Teil Ihres Zertifikats).

        8. Erstellen Sie data/gogs/gogs/conf/app.ini und setzen Sie die folgenden Werte. Sie kĂśnnen Gogs cheat sheet fĂźr ihre Bedeutung und andere mĂśgliche Werte konsultieren.

        -
        [server]
        +
        [server]
         SSH_LISTEN_PORT = 22
         # FĂźr GOGS_SSH_PORT=127.0.0.1:4000 in mailcow.conf, setzen:
         SSH_DOMAIN = 127.0.0.1
         SSH_PORT = 4000
         # FĂźr MAILCOW_HOSTNAME=mx.example.org in mailcow.conf (und Standard-Ports fĂźr HTTPS), setzen:
         ROOT_URL = https://mx.example.org/gogs/
        -
        +

        9. Starten Sie Gogs neu mit docker-compose restart gogs-mailcow. Ihre Benutzer sollten in der Lage sein, sich mit von mailcow verwalteten Konten einzuloggen.


        diff --git a/de/third_party/third_party-mailman3/index.html b/de/third_party/third_party-mailman3/index.html index 336ec3f4b..574d14e85 100644 --- a/de/third_party/third_party-mailman3/index.html +++ b/de/third_party/third_party-mailman3/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2780,15 +2780,15 @@

        DNS-Einrichtung

        Der größte Teil der Konfiguration ist in mailcows DNS Konfiguration enthalten. Nachdem diese Einrichtung abgeschlossen ist, fügen Sie eine weitere Subdomain für Mailman hinzu, z.B. lists.example.org, die auf denselben Server zeigt:

        -
        # Name Typ Wert
        +
        # Name Typ Wert
         lists IN A 1.2.3.4
         lists IN AAAA dead:beef
        -
        +

        Installieren Sie Apache als Reverse Proxy

        Installieren Sie Apache, z.B. mit dieser Anleitung von Digital Ocean: How To Install the Apache Web Server on Ubuntu 20.04 (Englisch).

        Aktivieren Sie bestimmte Apache Module (als root oder sudo):

        -
        a2enmod rewrite proxy proxy_http headers ssl wsgi proxy_uwsgi http2
        -
        +
        a2enmod rewrite proxy proxy_http headers ssl wsgi proxy_uwsgi http2
        +

        Möglicherweise müssen Sie weitere Pakete installieren, um diese Module zu erhalten. Dieses PPA von Ondřej Surý könnte Ihnen helfen.

        vHost-Konfiguration

        Kopieren Sie die mailcow.conf und die mailman.conf in den Apache conf Ordner sites-available (z.B. unter /etc/apache2/sites-available).

        @@ -2806,18 +2806,18 @@ lists IN AAAA dead:beef
      • https://mxtoolbox.com/SuperTool.aspx?action=aaaa%3aMAILMAN_DOMAIN

      Installieren Sie certbot (als root oder sudo):

      -
      apt install certbot
      -
      +
      apt install certbot
      +

      Holen Sie sich die gewĂźnschten Zertifikate (als root oder sudo):

      -
      certbot certonly -d mailcow_HOSTNAME
      +
      certbot certonly -d mailcow_HOSTNAME
       certbot certonly -d MAILMAN_DOMAIN
      -
      +

      Installieren Sie mailcow mit Mailman Integration

      Installieren Sie mailcow

      Folgen Sie der mailcow installation. Schritt 5 auslassen und nicht mit docker-compose starten!

      Mailcow konfigurieren

      Dies ist auch Schritt 4 in der offiziellen mailcow-Installation (nano mailcow.conf). Passen Sie also Ihre Bedßrfnisse an und ändern Sie die folgenden Variablen:

      -
      HTTP_PORT=18080 # verwenden Sie nicht 8080, da mailman es braucht
      +
      HTTP_PORT=18080 # verwenden Sie nicht 8080, da mailman es braucht
       HTTP_BIND=127.0.0.1 #
       HTTPS_PORT=18443 # Sie kĂśnnen 8443 verwenden
       HTTPS_BIND=127.0.0.1 # # HTTPS_BIND=127.0.0.1
      @@ -2826,10 +2826,10 @@ SKIP_LETS_ENCRYPT=y # Der Reverse Proxy wird die SSL-Verifizierung durchfĂźhren
       
       SNAT_TO_SOURCE=1.2.3.4 # ändern Sie dies in Ihre IPv4
       SNAT6_TO_SOURCE=dead:beef # Ändern Sie dies in Ihre globale IPv6
      -
      +

      Mailman-Integration hinzufĂźgen

      Erstelle die Datei /opt/mailcow-dockerized/docker-compose.override.yml (z.B. mit nano) und fĂźge die folgenden Zeilen hinzu:

      -
      version: '2.1'
      +
      version: '2.1'
       
       services:
         postfix-mailcow:
      @@ -2841,10 +2841,10 @@ services:
       networks:
         docker-mailman_mailman:
           external: true
      -
      +

      Das zusätzliche Volume wird von Mailman verwendet, um zusätzliche Konfigurationsdateien fßr mailcow postfix zu generieren. Das externe Netzwerk wird von Mailman erstellt und verwendet. mailcow benÜtigt es, um eingehende Listenmails an Mailman zu liefern.

      Erstellen Sie die Datei /opt/mailcow-dockerized/data/conf/postfix/extra.cf (z.B. mit nano) und fĂźgen Sie die folgenden Zeilen hinzu:

      -
      # mailman
      +
      # mailman
       
       recipient_delimiter = +
       unknown_local_recipient_reject_code = 550
      @@ -2869,7 +2869,7 @@ relay_domains =
       relay_recipient_maps =
         proxy:mysql:/opt/postfix/conf/sql/mysql_relay_recipient_maps.cf,
         regexp:/opt/mailman/core/var/data/postfix_lmtp
      -
      +

      Da wir hier die mailcow postfix Konfiguration überschreiben, kann dieser Schritt Ihre normalen Mailtransporte unterbrechen. Überprüfen Sie die originalen Konfigurationsdateien, wenn sich etwas geändert hat.

      SSL-Zertifikate

      Da wir mailcow als Proxy verwenden, mĂźssen wir die SSL-Zertifikate in die mailcow-Dateistruktur kopieren. Diese Aufgabe wird das Skript renew-ssl.sh fĂźr uns erledigen:

      @@ -2880,26 +2880,26 @@ relay_recipient_maps =
    • Noch nicht ausfĂźhren, da wir zuerst Mailman benĂśtigen

    Sie mĂźssen einen cronjob erstellen, so dass neue Zertifikate kopiert werden. FĂźhren Sie ihn als root oder sudo aus:

    -
    crontab -e
    -
    +
    crontab -e
    +

    Um das Skript jeden Tag um 5 Uhr morgens laufen zu lassen, fĂźgen Sie hinzu:

    -
    0 5 * * * /opt/mailcow-dockerized/renew-ssl.sh
    -
    +
    0 5 * * * /opt/mailcow-dockerized/renew-ssl.sh
    +

    Installieren Sie Mailman.

    Befolgen Sie im Wesentlichen die Anweisungen unter docker-mailman. Da sie sehr umfangreich sind, ist hier in aller KĂźrze beschrieben, was zu tun ist:

    Als root oder sudo:

    -
    cd /opt
    +
    cd /opt
     mkdir -p mailman/core
     mkdir -p mailman/web
     git clone https://github.com/maxking/docker-mailman
     cd docker-mailman
    -
    +

    Mailman konfigurieren

    Erstellen Sie einen langen SchlĂźssel fĂźr Hyperkitty, z.B. mit dem Linux-Befehl cat /dev/urandom | tr -dc a-zA-Z0-9 | head -c30; echo. Speichern Sie diesen SchlĂźssel vorerst als HYPERKITTY_KEY.

    Erstellen Sie ein langes Passwort fßr die Datenbank, z. B. mit dem Linux-Befehl cat /dev/urandom | tr -dc a-zA-Z0-9 | head -c30; echo. Speichern Sie dieses Passwort zunächst als DBPASS.

    Erstellen Sie einen langen SchlĂźssel fĂźr Django, z. B. mit dem Linux-Befehl cat /dev/urandom | tr -dc a-zA-Z0-9 | head -c30; echo. Speichern Sie diesen SchlĂźssel fĂźr einen Moment als DJANGO_KEY.

    Erstellen Sie die Datei /opt/docker-mailman/docker-compose.override.yaml und ersetzen Sie HYPERKITTY_KEY, DBPASS und DJANGO_KEY durch die generierten Werte:

    -
    version: '2'
    +
    version: '2'
     
     services:
       mailman-core:
    @@ -2928,17 +2928,17 @@ services:
         environment:
         - POSTGRES_PASSWORD=DBPASS
         restart: always
    -
    +

    Bei mailman-web geben Sie die korrekten Werte fßr SERVE_FROM_DOMAIN (z.B. lists.example.org), MAILMAN_ADMIN_USER und MAILMAN_ADMIN_EMAIL ein. Sie benÜtigen die Admin-Zugangsdaten, um sich in der Web-Oberfläche (Pistorius) anzumelden. Um das Passwort zum ersten Mal zu setzen, verwenden Sie die Funktion Passwort vergessen im Webinterface.

    Über andere Konfigurationsoptionen lesen Sie die Dokumentationen Mailman-web und Mailman-core.

    Konfigurieren Sie Mailman core und Mailman web

    Erstellen Sie die Datei /opt/mailman/core/mailman-extra.cfg mit dem folgenden Inhalt. mailman@example.org sollte auf ein gĂźltiges Postfach oder eine Umleitung verweisen.

    -
    [mailman]
    +
    [mailman]
     default_language: de
     site_owner: mailman@example.org
    -
    +

    Erstellen Sie die Datei /opt/mailman/web/settings_local.py mit dem folgenden Inhalt. mailman@example.org sollte auf ein gĂźltiges Postfach oder eine Umleitung verweisen.

    -

    # Gebietsschema
    +

    # Gebietsschema
     LANGUAGE_CODE = 'de-de'
     
     # soziale Authentifizierung deaktivieren
    @@ -2948,11 +2948,11 @@ SOCIALACCOUNT_PROVIDERS = {}
     DEFAULT_FROM_EMAIL = 'mailman@example.org'
     
     DEBUG = False
    -
    +
    Sie kĂśnnen LANGUAGE_CODE und SOCIALACCOUNT_PROVIDERS an Ihre BedĂźrfnisse anpassen. Im Moment hat SOCIALACCOUNT_PROVIDERS keinen Effekt, siehe issue #2.

    🏃 Ausführen

    AusfĂźhren (als root oder sudo)

    -
    a2ensite mailcow.conf
    +
    a2ensite mailcow.conf
     a2ensite mailman.conf
     systemctl restart apache2
     
    @@ -2963,14 +2963,14 @@ docker-compose up -d
     cd /opt/mailcow-dockerized/
     docker-compose pull
     ./renew-ssl.sh
    -
    +

    Warten Sie ein paar Minuten! Die Container mĂźssen ihre Datenbanken und Konfigurationsdateien erstellen. Dies kann bis zu 1 Minute und mehr dauern.

    Bemerkungen

    Neue Listen werden von Postfix nicht sofort erkannt

    Wenn man eine neue Liste anlegt und versucht, sofort eine E-Mail zu versenden, antwortet postfix mit Benutzer existiert nicht, weil postfix die Liste noch nicht an Mailman Ăźbergeben hat. Die Konfiguration unter /opt/mailman/core/var/data/postfix_lmtp wird nicht sofort aktualisiert. Wenn Sie die Liste sofort benĂśtigen, starten Sie postifx manuell neu:

    -
    cd /opt/mailcow-dockerized
    +
    cd /opt/mailcow-dockerized
     docker-compose restart postfix-mailcow
    -
    +

    Update

    mailcow hat sein eigenes Update-Skript in /opt/mailcow-dockerized/update.sh, siehe die Dokumentation.

    FĂźr Mailman holen Sie sich einfach die neueste Version aus dem github repository.

    diff --git a/de/third_party/third_party-mailpiler_integration/index.html b/de/third_party/third_party-mailpiler_integration/index.html index 79cd95b05..d73416a27 100644 --- a/de/third_party/third_party-mailpiler_integration/index.html +++ b/de/third_party/third_party-mailpiler_integration/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2456,11 +2456,11 @@

    Das zu lĂśsende Problem

    mailpiler bietet die Authentifizierung auf Basis von IMAP an, zum Beispiel:

    -
    $config['ENABLE_IMAP_AUTH'] = 1;
    +
    $config['ENABLE_IMAP_AUTH'] = 1;
     $config['IMAP_HOST'] = 'mail.example.com';
     $config['IMAP_PORT'] = 993;
     $config['IMAP_SSL'] = true;
    -
    +
    • Wenn Sie sich also mit patrik@example.com anmelden, sehen Sie nur zugestellte E-Mails, die von oder an diese spezielle E-Mail-Adresse gesendet wurden.
    • Wenn zusätzliche Aliase in mailcow definiert werden, wie z.B. team@example.com, werden Sie keine Emails sehen, die an oder von dieser Email-Adresse gesendet wurden, auch wenn Sie ein Empfänger von Emails sind, die an diese Alias-Adresse gesendet wurden.
    • @@ -2487,19 +2487,19 @@
      1. Setzen Sie die benutzerdefinierte Abfragefunktion von mailpiler und fĂźgen Sie diese an /usr/local/etc/piler/config-site.php an:

        -
        $config['MAILCOW_API_KEY'] = 'YOUR_READONLY_API_KEY';
        +
        $config['MAILCOW_API_KEY'] = 'YOUR_READONLY_API_KEY';
         $config['MAILCOW_SET_REALNAME'] = true; // wenn nicht angegeben, dann ist der Standardwert false
         $config['CUSTOM_EMAIL_QUERY_FUNCTION'] = 'query_mailcow_for_email_access';
         include('auth-mailcow.php');
        -
        +

        Sie kÜnnen auch den mailcow-Hostnamen ändern, falls erforderlich: -

        $config['MAILCOW_HOST'] = 'mail.domain.tld'; // standardmäßig $config['IMAP_HOST']
        -

        +
        $config['MAILCOW_HOST'] = 'mail.domain.tld'; // standardmäßig $config['IMAP_HOST']
        +

      2. Laden Sie die PHP-Datei mit den Funktionen aus dem GitHub Repo herunter:

        -
        curl -o /usr/local/etc/piler/auth-mailcow.php https://raw.githubusercontent.com/patschi/mailpiler-mailcow-integration/master/auth-mailcow.php
        -
        +
        curl -o /usr/local/etc/piler/auth-mailcow.php https://raw.githubusercontent.com/patschi/mailpiler-mailcow-integration/master/auth-mailcow.php
        +
      3. Erledigt!

        diff --git a/de/third_party/third_party-nextcloud/index.html b/de/third_party/third_party-nextcloud/index.html index 2483a5bbc..90196bb07 100644 --- a/de/third_party/third_party-nextcloud/index.html +++ b/de/third_party/third_party-nextcloud/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2458,14 +2458,14 @@

        Hintergrund-Aufgaben

        Zur Verwendung der empfohlenen Einstellung (Cron) zur Verarbeitung der Hintergrund-Aufgaben mĂźssen in der docker-compose.override.yml folgende Zeilen hinzugefĂźgt werden:

        -
        version: '2.1'
        +
        version: '2.1'
         services:
           php-fpm-mailcow:
             labels:
               ofelia.enabled: "true"
               ofelia.job-exec.nextcloud-cron.schedule: "@every 5m"
               ofelia.job-exec.nextcloud-cron.command: "su www-data -s /bin/bash -c \"/usr/local/bin/php -f /web/nextcloud/cron.php\""
        -
        +

        Nachdem diese Zeilen hinzugefügt wurden muss docker-compose up -d ausgeführt werden, um das Docker Image mit den entsprechenden Labels zu versehen. Danach muss zudem der docker scheduler neu gestartet werden, um den neuen Job zu registrieren. Dazu wird docker-compose restart ofelia-mailcow ausgeführt. Zur Überprüfung, ob die ofelia Konfiguration korrekt ist geladen wurde, kann mittels docker-compose logs ofelia-mailcow nach einer Zeile mit dem Inhalt @@ -2518,14 +2518,14 @@ services:

        Wenn Sie bisher Nextcloud mit mailcow-Authentifizierung ßber user_external/IMAP verwendet haben, mßssen Sie einige zusätzliche Schritte durchfßhren, um Ihre bestehenden Benutzerkonten mit OAuth2 zu verknßpfen.

        1. Klicken Sie auf die Schaltfläche in der oberen rechten Ecke und wählen Sie Apps. Scrollen Sie nach unten zur App Externe Benutzerauthentifizierung und klicken Sie daneben auf Entfernen. 2. Fßhren Sie die folgenden Abfragen in Ihrer Nextcloud-Datenbank aus (wenn Sie Nextcloud mit dem Skript von mailcow einrichten, kÜnnen Sie source mailcow.conf && docker-compose exec mysql-mailcow mysql -u$DBUSER -p$DBPASS $DBNAME ausfßhren): -

        INSERT INTO nc_users (uid, uid_lower) SELECT DISTINCT uid, LOWER(uid) FROM nc_users_external;
        +
        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;
        -

        +


        Wenn Sie Nextcloud bisher ohne mailcow-Authentifizierung, aber mit den gleichen Benutzernamen wie mailcow genutzt haben, kĂśnnen Sie Ihre bestehenden Benutzerkonten auch mit OAuth2 verknĂźpfen.

        1. FĂźhren Sie die folgenden Abfragen in Ihrer Nextcloud-Datenbank aus (wenn Sie Nextcloud mit dem Skript von mailcow einrichten, kĂśnnen Sie source mailcow.conf && docker-compose exec mysql-mailcow mysql -u$DBUSER -p$DBPASS $DBNAME ausfĂźhren): -

        INSERT INTO nc_sociallogin_connect (uid, identifier) SELECT DISTINCT uid, CONCAT("Mailcow-", uid) FROM nc_users;
        -

        +
        INSERT INTO nc_sociallogin_connect (uid, identifier) SELECT DISTINCT uid, CONCAT("Mailcow-", uid) FROM nc_users;
        +


        Aktualisieren

        Die Nextcloud-Instanz kann einfach mit dem Web-Update-Mechanismus aktualisiert werden. Bei größeren Updates können nach dem Update weitere Änderungen vorgenommen werden. Nachdem die Nextcloud-Instanz geprüft wurde, werden Probleme angezeigt. Dies können z.B. fehlende Indizes in der DB oder ähnliches sein. @@ -2535,13 +2535,13 @@ Es wird angezeigt, welche Befehle ausgeführt werden müssen, diese müssen im p


        Fehlersuche und Fehlerbehebung

        Es kann vorkommen, dass Sie die Nextcloud-Instanz von Ihrem Netzwerk aus nicht erreichen können. Dies kann daran liegen, dass der Eintrag Ihres Subnetzes im Array 'trusted_proxies' fehlt. Sie können Änderungen in der Nextcloud config.php in data/web/nextcloud/config/* vornehmen.

        -
        'trusted_proxies' =>
        +
        'trusted_proxies' =>
           array (
             0 => 'fd4d:6169:6c63:6f77::/64',
             1 => '172.22.1.0/24',
             2 => 'NewSubnet/24',
           ),
        -
        +

        Nachdem die Änderungen vorgenommen wurden, muss der nginx-Container neu gestartet werden. docker-compose restart nginx-mailcow

        diff --git a/de/third_party/third_party-portainer/index.html b/de/third_party/third_party-portainer/index.html index cecdfe23c..c5aed8c43 100644 --- a/de/third_party/third_party-portainer/index.html +++ b/de/third_party/third_party-portainer/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2347,7 +2347,7 @@

        Um Portainer zu aktivieren, mßssen die docker-compose.yml und site.conf fßr Nginx geändert werden.

        1. Erstellen Sie eine neue Datei docker-compose.override.yml im mailcow-dockerized Stammverzeichnis und fĂźgen Sie die folgende Konfiguration ein -

        version: '2.1'
        +
        version: '2.1'
         services:
             portainer-mailcow:
               image: portainer/portainer-ce
        @@ -2362,9 +2362,9 @@ services:
                 mailcow-network:
                   aliases:
                     - portainer
        -
        +
        2a. Erstelle data/conf/nginx/portainer.conf: -
        upstream portainer {
        +
        upstream portainer {
           server portainer-mailcow:9000;
         }
         
        @@ -2372,9 +2372,9 @@ map $http_upgrade $connection_upgrade {
           default upgrade;
           '' close;
         }
        -

        +

        2b. FĂźgen Sie einen neuen Standort fĂźr die Standard-Mailcow-Site ein, indem Sie die Datei data/conf/nginx/site.portainer.custom erstellen: -

          location /portainer/ {
        +
          location /portainer/ {
             proxy_http_version 1.1;
             proxy_set_header Host              $http_host;   # required for docker client's sake
             proxy_set_header X-Real-IP         $remote_addr; # pass on real client's IP
        @@ -2393,10 +2393,10 @@ map $http_upgrade $connection_upgrade {
             proxy_set_header Connection $connection_upgrade;
             proxy_pass http://portainer/api/websocket/;
           }
        -

        +

        3. Übernehmen Sie Ihre Änderungen: -

        docker-compose up -d && docker-compose restart nginx-mailcow
        -

        +
        docker-compose up -d && docker-compose restart nginx-mailcow
        +

        Nun können Sie einfach zu https://${MAILCOW_HOSTNAME}/portainer/ navigieren, um Ihre Portainer-Container-Überwachungsseite anzuzeigen. Sie werden dann aufgefordert, ein neues Passwort für den admin Account anzugeben. Nachdem Sie Ihr Passwort eingegeben haben, können Sie sich mit der Portainer UI verbinden.


        diff --git a/de/third_party/third_party-roundcube/index.html b/de/third_party/third_party-roundcube/index.html index 90e8544c1..f80985915 100644 --- a/de/third_party/third_party-roundcube/index.html +++ b/de/third_party/third_party-roundcube/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2466,7 +2466,7 @@

        Installation von Roundcube

        Laden Sie Roundcube 1.5.x in das Web htdocs Verzeichnis herunter und entpacken Sie es (hier rc/): -

        # PrĂźfen Sie, ob eine neuere Version vorliegt!
        +
        # PrĂźfen Sie, ob eine neuere Version vorliegt!
         cd daten/web
         wget -O - https://github.com/roundcube/roundcubemail/releases/download/1.5.2/roundcubemail-1.5.2-complete.tar.gz | tar xfvz -
         
        @@ -2478,17 +2478,17 @@ chown -R root: rc/
         
         # Fix Allow remote resources (https://github.com/roundcube/roundcubemail/issues/8170) sollte in 1.6 nicht erforderlich sein
         sed -i "s/\$prefix = '\.\/';/\$prefix = preg_replace\('\/\[\?\&]\.\*\$\/', '', \$_SERVER\['REQUEST_URI'] \?\? ''\) \?: '\.\/';/g" rc/program/include/rcmail.php
        -

        +

        Wenn Sie eine RechtschreibprĂźfung benĂśtigen, erstellen Sie eine Datei data/hooks/phpfpm/aspell.sh mit folgendem Inhalt und geben Sie dann chmod +x data/hooks/phpfpm/aspell.sh ein. Dadurch wird eine lokale RechtschreibprĂźfung installiert. Beachten Sie, dass die meisten modernen Webbrowser eine eingebaute RechtschreibprĂźfung haben, so dass Sie diese vielleicht nicht benĂśtigen. -

        #!/bin/bash
        +
        #!/bin/bash
         apk update
         apk add aspell-de # oder jede andere Sprache
        -

        +

        Erstellen Sie eine Datei data/web/rc/config/config.inc.php mit dem folgenden Inhalt. - Ändern Sie den Parameter des_key auf einen Zufallswert. Er wird verwendet, um Ihr IMAP-Passwort vorübergehend zu speichern. - Der db_prefix ist optional, wird aber empfohlen. - Wenn Sie die Rechtschreibprüfung im obigen Schritt nicht installiert haben, entfernen Sie den Parameter spellcheck_engine und ersetzen ihn durch $config['enable_spellcheck'] = false;. -

        <?php
        +
        <?php
         error_reporting(0);
         if (!file_exists('/tmp/mime.types')) {
         file_put_contents("/tmp/mime.types", fopen("http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types", 'r'));
        @@ -2520,13 +2520,13 @@ $config['smtp_conn_options'] = array(
           'ssl' => array('verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true)
         );
         $config['db_prefix'] = 'mailcow_rc1';
        -

        +

        Richten Sie Ihren Browser auf https://myserver/rc/installer und folgen Sie den Anweisungen. Initialisiere die Datenbank und verlasse das Installationsprogramm.

        **LĂśschen Sie das Verzeichnis data/web/rc/installer nach einer erfolgreichen Installation!

        Konfigurieren Sie die ManageSieve-Filterung

        Öffnen Sie data/web/rc/plugins/managesieve/config.inc.php und ändern Sie die folgenden Parameter (oder fügen Sie sie am Ende der Datei hinzu): -

        $config['managesieve_port'] = 4190;
        +
        $config['managesieve_port'] = 4190;
         $config['managesieve_host'] = 'tls://dovecot';
         $config['managesieve_conn_options'] = array(
           ssl' => array('verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true)
        @@ -2536,37 +2536,37 @@ $config['managesieve_conn_options'] = array(
         // 1 - Abschnitt "Urlaub" hinzufĂźgen,
         // 2 - Abschnitt "Urlaub" hinzufĂźgen, aber Abschnitt "Filter" ausblenden
         $config['managesieve_vacation'] = 1;
        -

        +

        Aktivieren Sie die Funktion "Passwort ändern" in Roundcube

        Öffnen Sie data/web/rc/config/config.inc.php und aktivieren Sie das Passwort-Plugin:

        -
        [...]
        +
        [...]
         $config['plugins'] = array(
             'archive',
             'password',
         );
         [...]
        -
        +

        Öffnen Sie data/web/rc/plugins/password/password.php, suchen Sie nach case 'ssha': und fügen Sie oben hinzu:

        -
                case 'ssha256':
        +
                case 'ssha256':
                     $salt = rcube_utils::random_bytes(8);
                     $crypted = base64_encode( hash('sha256', $password . $salt, TRUE ) . $salt );
                     $prefix  = '{SSHA256}';
                     break;
        -
        +

        Öffnen Sie data/web/rc/plugins/password/config.inc.php und ändern Sie die folgenden Parameter (oder fügen Sie sie am Ende der Datei hinzu):

        -
        $config['password_driver'] = 'sql';
        +
        $config['password_driver'] = 'sql';
         $config['password_algorithm'] = 'ssha256';
         $config['password_algorithm_prefix'] = '{SSHA256}';
         $config['password_query'] = "UPDATE mailbox SET password = %P WHERE username = %u";
        -
        +

        CardDAV AdressbĂźcher in Roundcube einbinden

        Laden Sie die neueste Version von RCMCardDAV in das Roundcube Plugin Verzeichnis und entpacken Sie es (hier rc/plugins): -

        cd data/web/rc/plugins
        +
        cd data/web/rc/plugins
         wget -O - https://github.com/mstilkerich/rcmcarddav/releases/download/v4.3.0/carddav-v4.3.0.tar.gz | tar xfvz -
         chown -R root: carddav/
        -

        +

        Kopieren Sie die Datei config.inc.php.dist nach config.inc.php (hier in rc/plugins/carddav) und fĂźgen Sie die folgende Voreinstellung an das Ende der Datei an - vergessen Sie nicht, mx.example.org durch Ihren eigenen Hostnamen zu ersetzen: -

        $prefs['SOGo'] = array(
        +
        $prefs['SOGo'] = array(
             'name'         =>  'SOGo',
             'username'     =>  '%u',
             'password'     =>  '%p',
        @@ -2579,7 +2579,7 @@ chown -R root: carddav/
             'fixed'        =>  array( 'active', 'name', 'username', 'password', 'refresh_time' ),
             'hide'        =>  false,
         );
        -
        +
        Bitte beachten Sie, dass dieses Preset nur das Standard-Adressbuch integriert (dasjenige, das den Namen "PersÜnliches Adressbuch" trägt und nicht gelÜscht werden kann). Weitere Adressbßcher werden derzeit nicht automatisch erkannt, kÜnnen aber manuell in den Roundcube-Einstellungen hinzugefßgt werden.

        Aktivieren Sie das Plugin, indem Sie carddav zu $config['plugins'] in rc/config/config.inc.php hinzufĂźgen.

        Wenn Sie die Standard-Adressbßcher (die in der Roundcube-Datenbank gespeichert sind) entfernen mÜchten, so dass nur die CardDAV-Adressbßcher zugänglich sind, fßgen Sie $config['address_book_type'] = ''; in die Konfigurationsdatei data/web/rc/config/config.inc.php ein.

        @@ -2587,7 +2587,7 @@ Bitte beachten Sie, dass dieses Preset nur das Standard-Adressbuch integriert (d

        Optional kĂśnnen Sie Roundcube's Link zu der mailcow Apps Liste hinzufĂźgen. Um dies zu tun, Ăśffnen oder erstellen Sie data/web/inc/vars.local.inc.php und fĂźgen Sie den folgenden Code-Block hinzu:

        HINWEIS: Vergessen Sie nicht, das <?php Trennzeichen in der ersten Zeile einzufĂźgen

        -
        ...
        +
        ...
         $MAILCOW_APPS = array(
           array(
             'name' => 'SOGo',
        @@ -2599,10 +2599,10 @@ $MAILCOW_APPS = array(
            )
         );
         ...
        -
        +

        Aktualisierung von Roundcube

        Ein Upgrade von Roundcube ist recht einfach: Gehen Sie auf die Github releases Seite fßr Roundcube und holen Sie sich den Link fßr die "complete.tar.gz" Datei fßr die gewßnschte Version. Dann folgen Sie den untenstehenden Befehlen und ändern Sie die URL und den Namen des Roundcube-Ordners, falls nÜtig.

        -
        # Starten Sie eine Bash-Sitzung des mailcow PHP-Containers
        +
        # Starten Sie eine Bash-Sitzung des mailcow PHP-Containers
         docker exec -it mailcowdockerized_php-fpm-mailcow_1 bash
         
         # Installieren Sie die erforderliche Upgrade-Abhängigkeit, dann aktualisieren Sie Roundcube auf die gewßnschte Version
        @@ -2620,42 +2620,42 @@ rm -rf roundcube*
         
         # Fix Allow remote resources (https://github.com/roundcube/roundcubemail/issues/8170) sollte in 1.6 nicht benĂśtigt werden
         sed -i "s/\$prefix = '\.\/';/\$prefix = preg_replace\('\/\[\?\&]\.\*\$\/', '', \$_SERVER\['REQUEST_URI'] \?\? ''\) \?: '\.\/';/g" /web/rc/program/include/rcmail.php
        -
        +

        Administratoren ohne Passwort in Roundcube einloggen lassen

        Installieren Sie zunächst das Plugin [dovecot_impersonate] (https://github.com/corbosman/dovecot_impersonate/) und fßgen Sie Roundcube als App hinzu (siehe oben).

        Editieren Sie mailcow.conf und fĂźgen Sie folgendes hinzu:

        -
        # Erlaube Admins, sich in Roundcube als Email-Benutzer einzuloggen (ohne Passwort)
        +
        # Erlaube Admins, sich in Roundcube als Email-Benutzer einzuloggen (ohne Passwort)
         # Roundcube mit Plugin dovecot_impersonate muss zuerst installiert werden
         
         ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE=y
        -
        +

        Editieren Sie docker-compose.override.yml und verfassen/erweitern Sie den Abschnitt fĂźr php-fpm-mailcow:

        -
        version: '2.1'
        +
        version: '2.1'
         services:
           php-fpm-mailcow:
             environment:
               - ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE=${ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE:-n}
        -
        +

        Bearbeiten Sie data/web/js/site/mailbox.js und den folgenden Code nach if (ALLOW_ADMIN_EMAIL_LOGIN) { ... }

        -
        if (ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE) {
        -  item.action += '<a href="/rc-auth.php?login=' + encodeURIComponent(item.username) + '" class="login_as btn btn-xs ' + btnSize + ' btn-primary" target="_blank"><i class="bi bi-envelope-fill"></i> Roundcube</a>';
        -}
        -
        +
        if (ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE) {
        +  item.action += '<a href="/rc-auth.php?login=' + encodeURIComponent(item.username) + '" class="login_as btn btn-xs ' + btnSize + ' btn-primary" target="_blank"><i class="bi bi-envelope-fill"></i> Roundcube</a>';
        +}
        +

        Bearbeiten Sie data/web/mailbox.php und fĂźgen Sie diese Zeile zum Array $template_data hinzu:

        -
          'allow_admin_email_login_roundcube' => (preg_match("/^(yes|y)+$/i", $_ENV["ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE"])) ? 'true' : 'false',
        -
        +
          'allow_admin_email_login_roundcube' => (preg_match("/^(yes|y)+$/i", $_ENV["ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE"])) ? 'true' : 'false',
        +

        Bearbeiten Sie data/web/templates/mailbox.twig und fĂźgen Sie diesen Code am Ende des [javascript-Abschnitts] ein (https://github.com/mailcow/mailcow-dockerized/blob/2f9da5ae93d93bf62a8c2b7a5a6ae50a41170c48/data/web/templates/mailbox.twig#L49-L57):

        -
          var ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE = {{ allow_admin_email_login_roundcube }};
        -
        +
          var ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE = {{ allow_admin_email_login_roundcube }};
        +

        Kopieren Sie den Inhalt der folgenden Dateien aus diesem Snippet:

        • data/web/inc/lib/RoundcubeAutoLogin.php
        • data/web/rc-auth.php

        Starten Sie schließlich mailcow neu

        -
        docker-compose down
        +
        docker-compose down
         docker-compose up -d
        -
        +

        diff --git a/de/troubleshooting/debug-admin_login_sogo/index.html b/de/troubleshooting/debug-admin_login_sogo/index.html index cba2a9e48..3b26680a7 100644 --- a/de/troubleshooting/debug-admin_login_sogo/index.html +++ b/de/troubleshooting/debug-admin_login_sogo/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2427,11 +2427,11 @@ Dazu wird ein zusätzlicher Link zu SOGo in der Mailbox-Liste (mailcow UI) angez

        Auch mehrere gleichzeitige Admin-Logins auf verschiedene Postfächer sind mit dieser Funktion mÜglich.

        Aktivieren der Funktion

        Die Funktion ist standardmäßig deaktiviert. Es kann in der mailcow.conf durch Setzen aktiviert werden: -

        ALLOW_ADMIN_EMAIL_LOGIN=y
        -
        +
        ALLOW_ADMIN_EMAIL_LOGIN=y
        +
        und die betroffenen Container neu erstellen mit -
        docker-compose up -d
        -

        +
        docker-compose up -d
        +

        Nachteile bei Aktivierung

        • Jeder SOGo-Seiten-Load und jede Active-Sync-Anfrage verursacht eine zusätzliche AusfĂźhrung eines internen PHP-Skripts. diff --git a/de/troubleshooting/debug-attach_service/index.html b/de/troubleshooting/debug-attach_service/index.html index c57384c5f..d05ccd216 100644 --- a/de/troubleshooting/debug-attach_service/index.html +++ b/de/troubleshooting/debug-attach_service/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2476,17 +2476,17 @@

          Anhängen eines Containers an Ihre Shell

          Um einen Container an Ihre Shell anzuhängen, kÜnnen Sie einfach folgendes ausfßhren

          -
          docker-compose exec $Dienst_Name /bin/bash
          -
          +
          docker-compose exec $Dienst_Name /bin/bash
          +

          Verbindung zu Diensten herstellen

          Wenn Sie sich direkt mit einem Dienst / einer Anwendung verbinden wollen, ist es immer eine gute Idee, source mailcow.conf zu benutzen, um alle relevanten Variablen in Ihre Umgebung zu bekommen.

          MySQL

          -
          Quelle mailcow.conf
          +
          Quelle mailcow.conf
           docker-compose exec mysql-mailcow mysql -u${DBUSER} -p${DBPASS} ${DBNAME}
          -
          +

          Redis

          -
          docker-compose exec redis-mailcow redis-cli
          -
          +
          docker-compose exec redis-mailcow redis-cli
          +

          Dienstbeschreibungen

          Hier ist eine kurze Übersicht, welcher Container / Dienst was macht:

          diff --git a/de/troubleshooting/debug-common_problems/index.html b/de/troubleshooting/debug-common_problems/index.html index 0b7623599..0f292be1f 100644 --- a/de/troubleshooting/debug-common_problems/index.html +++ b/de/troubleshooting/debug-common_problems/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2516,11 +2516,11 @@
        • PrĂźfen Sie, ob Ihre IP-Adresse auf einer schwarzen Liste steht. Sie kĂśnnen dnsbl.info oder einen ähnlichen Dienst verwenden, um Ihre IP-Adresse zu ĂźberprĂźfen.
        • Es gibt einige ISP-Router, die Mail-Ports fĂźr nicht auf der Blacklist stehende Domains blockieren. Bitte ĂźberprĂźfen Sie, ob Sie Ihren Server Ăźber die Ports 465 oder 587 erreichen kĂśnnen:
        • -
          # telnet 74.125.133.27 465
          +
          # telnet 74.125.133.27 465
           Versucht 74.125.133.27...
           Verbunden mit 74.125.133.27.
           Escape-Zeichen ist '^]'.
          -
          +

          Meine Mails werden als Spam identifiziert

          Bitte lesen Sie unsere DNS-Konfiguration Anleitung.

          docker-compose wirft seltsame Fehler aus.

          @@ -2537,8 +2537,8 @@ Escape-Zeichen ist '^]'.

          Es kĂśnnte auch eine falsch verknĂźpfte Datei sein (z. B. ein SSL-Zertifikat), die den Start eines wichtigen Containers (nginx) verhindert. PrĂźfen Sie daher immer Ihre Protokolle, um herauszufinden, woher das Problem kommt.

          Adresse bereits in Gebrauch

          Wenn Sie eine Fehlermeldung erhalten wie:

          -
          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:25: bind: address already in use
          -
          +
          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:25: bind: address already in use
          +

          während Sie versuchen, mailcow: dockerized zu starten / zu installieren, stellen Sie sicher, dass Sie unseren Abschnitt ßber prerequisites befolgt haben.

          XYZ kann keine Verbindung zu ...

          Bitte ĂźberprĂźfen Sie Ihre lokale Firewall! @@ -2546,19 +2546,19 @@ Docker und iptables-basierte Firewalls erstellen manchmal widersprĂźchliche Rege

          Wenn Sie Verbindungsprobleme von zu Hause aus haben, ĂźberprĂźfen Sie bitte auch die Firewall Ihres ISP-Routers, da einige von ihnen den E-Mail-Verkehr Ăźber die Ports SMTP (587) oder SMTPS (465) blockieren. Es kĂśnnte auch sein, dass Ihr ISP die Ports fĂźr SUBMISSION (25) blockiert.

          Während Linux-Benutzer aus einer Vielzahl von Tools1 wählen können, um zu überprüfen, ob ein Port offen ist, steht Windows-Benutzern standardmäßig nur der PowerShell-Befehl Test-NetConnection -ComputerName host -Port port zur Verfügung.

          Um Telnet auf einem Windows nach Vista zu aktivieren, lesen Sie bitte diese Anleitung oder geben Sie den folgenden Befehl in einem Terminal mit Administratorrechten ein:

          -
          dism /online /Enable-Feature /FeatureName:TelnetClient
          -
          +
          dism /online /Enable-Feature /FeatureName:TelnetClient
          +

          Inotify-Instanz-Limit Ăźberschritten fĂźr Benutzer 5000 (UID vmail) (siehe #453).

          Docker-Container verwenden die inotify-Limits von Docker-Hosts. Wenn Sie sie auf Ihrem Docker-Host setzen, werden sie an den Container weitergegeben.

          Dovecot startet ständig neu (siehe #2672).

          Stellen Sie sicher, dass Sie mindestens die folgenden Dateien in data/assets/ssl haben:

          -
          cert.pem
          +
          cert.pem
           dhparams.pem
           key.pem
          -
          +

          Wenn dhparams.pem fehlt, kĂśnnen Sie es mit Bash

          -
          openssl dhparam -out data/assets/ssl/dhparams.pem 4096
          -
          +
          openssl dhparam -out data/assets/ssl/dhparams.pem 4096
          +

            diff --git a/de/troubleshooting/debug-logs/index.html b/de/troubleshooting/debug-logs/index.html index a89c491a2..9b6af1f50 100644 --- a/de/troubleshooting/debug-logs/index.html +++ b/de/troubleshooting/debug-logs/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/de/troubleshooting/debug-mysql_aria/index.html b/de/troubleshooting/debug-mysql_aria/index.html index 3a53237ca..645e23d01 100644 --- a/de/troubleshooting/debug-mysql_aria/index.html +++ b/de/troubleshooting/debug-mysql_aria/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2398,7 +2398,7 @@

            Wenn Ihr Server abgestßrzt ist und MariaDB eine Fehlermeldung ähnlich [ERROR] mysqld: Aria recovery failed. Please run aria_chk -r on all Aria tables (*.MAI) and delete all aria_log.######## files, kÜnnen Sie Folgendes versuchen, um die Datenbank in einen gesunden Zustand zu bringen:

            Starten Sie den Stack und warten Sie, bis mysql-mailcow beginnt, einen Neustart zu melden. Überprüfen Sie dies, indem Sie docker-compose ps ausführen.

            FĂźhren Sie nun die folgenden Befehle aus:

            -
            # Stoppe den Stack, fĂźhre nicht "down" aus
            +
            # Stoppe den Stack, fĂźhre nicht "down" aus
             docker-compose stop
             # FĂźhren Sie eine Bash in dem gestoppten Container als Benutzer mysql aus
             docker-compose run --rm --entrypoint '/bin/sh -c "gosu mysql bash"' mysql-mailcow
            @@ -2408,7 +2408,7 @@ cd /var/lib/mysql
             aria_chk --check --force */*.MAI
             # LĂśschen der aria-Logdateien
             rm aria_log.*
            -
            +

            FĂźhren Sie nun docker-compose down gefolgt von docker-compose up -d aus.


            diff --git a/de/troubleshooting/debug-mysql_upgrade/index.html b/de/troubleshooting/debug-mysql_upgrade/index.html index 43bf7aa28..d1494106d 100644 --- a/de/troubleshooting/debug-mysql_upgrade/index.html +++ b/de/troubleshooting/debug-mysql_upgrade/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2396,13 +2396,13 @@

            FĂźhren Sie ein manuelles mysql_upgrade durch.

            Dieser Schritt ist normalerweise nicht notwendig.

            -
            docker-compose stop mysql-mailcow watchdog-mailcow
            +
            docker-compose stop mysql-mailcow watchdog-mailcow
             docker-compose run --rm --entrypoint '/bin/sh -c "gosu mysql mysqld --skip-grant-tables & sleep 10 && bash && exit 0"' mysql-mailcow
            -
            +

            Sobald die SQL-Shell gestartet wurde, fĂźhren Sie mysql_upgrade aus und verlassen den Container:

            -
            mysql_upgrade
            +
            mysql_upgrade
             exit
            -
            +

            diff --git a/de/troubleshooting/debug-reset_pw/index.html b/de/troubleshooting/debug-reset_pw/index.html index e91278504..85b16c25d 100644 --- a/de/troubleshooting/debug-reset_pw/index.html +++ b/de/troubleshooting/debug-reset_pw/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2544,16 +2544,16 @@

            mailcow Admin-Konto

            Setzt den mailcow Admin Account auf ein zufälliges Passwort zurück. Ältere mailcow: dockerisierte Installationen können das mailcow-reset-admin.sh Skript in ihrem mailcow Stammverzeichnis (mailcow_path) finden.

            -
            cd mailcow_pfad
            +
            cd mailcow_pfad
             ./helper-scripts/mailcow-reset-admin.sh
            -
            +

            MySQL-PasswĂśrter zurĂźcksetzen

            Stoppen Sie den Stack, indem Sie docker-compose stop ausfĂźhren.

            Wenn die Container heruntergefahren sind, fĂźhren Sie diesen Befehl aus:

            -
            docker-compose run --rm --entrypoint '/bin/sh -c "gosu mysql mysqld --skip-grant-tables & sleep 10 && mysql -hlocalhost -uroot && exit 0"' mysql-mailcow
            -
            +
            docker-compose run --rm --entrypoint '/bin/sh -c "gosu mysql mysqld --skip-grant-tables & sleep 10 && mysql -hlocalhost -uroot && exit 0"' mysql-mailcow
            +

            1. Datenbank-Name finden

            -
            # source mailcow.conf
            +
            # source mailcow.conf
             # docker-compose exec mysql-mailcow mysql -u${DBUSER} -p${DBPASS} ${DBNAME}
             MariaDB [(none)]> show databases;
             +--------------------+
            @@ -2565,11 +2565,11 @@ MariaDB [(none)]> show databases;
             | performance_schema |
             +--------------------+
             4 rows in set (0.00 sec)
            -
            +

            2. Einen oder mehrere Benutzer zurĂźcksetzen

            2.1 Maria DB < 10.4 (ältere mailcow-Installationen)

            Sowohl "password" als auch "authentication_string" existieren. Derzeit wird "password" verwendet, aber besser ist es, beide zu setzen.

            -
            MariaDB [(none)]> SELECT user FROM mysql.user;
            +
            MariaDB [(none)]> SELECT user FROM mysql.user;
             +--------------+
             | user |
             +--------------+
            @@ -2582,9 +2582,9 @@ MariaDB [(none)]> FLUSH PRIVILEGES;
             MariaDB [(none)]> UPDATE mysql.user SET authentication_string = PASSWORD('gotr00t'), password = PASSWORD('gotr00t') WHERE User = 'root';
             MariaDB [(none)]> UPDATE mysql.user SET authentication_string = PASSWORD('mookuh'), password = PASSWORD('mookuh') WHERE User = 'mailcow' AND Host = '%';
             MariaDB [(none)]> FLUSH PRIVILEGES;
            -
            +

            2.2 Maria DB >= 10.4 (aktuelle mailcows)

            -
            MariaDB [(none)]> SELECT user FROM mysql.user;
            +
            MariaDB [(none)]> SELECT user FROM mysql.user;
             +--------------+
             | user |
             +--------------+
            @@ -2598,16 +2598,16 @@ MariaDB [(none)]> ALTER USER 'mailcow'@'%' IDENTIFIED BY '
             MariaDB [(none)]> ALTER USER 'root'@'%' IDENTIFIED BY 'gotr00t'; MariaDB [(none)]> ALTER USER 'root'@'%' IDENTIFIED BY 'gotr00t';
             MariaDB [(none)]> ALTER USER 'root'@'localhost' IDENTIFIED BY 'gotr00t'; MariaDB [(none)]> ALTER USER 'root'@'localhost' IDENTIFIED BY 'gotr00t';
             MariaDB [(none)]> FLUSH PRIVILEGES;
            -
            +

            Zwei-Faktor-Authentifizierung entfernen

            FĂźr mailcow WebUI:

            Dies funktioniert ähnlich wie das Zurßcksetzen eines MySQL-Passworts, jetzt machen wir es vom Host aus, ohne uns mit dem MySQL CLI zu verbinden:

            -
            Quelle mailcow.conf
            +
            Quelle mailcow.conf
             docker-compose exec mysql-mailcow mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM tfa WHERE username='YOUR_USERNAME';"
            -
            +

            FĂźr SOGo:

            -
            docker-compose exec -u sogo sogo-mailcow sogo-tool user-preferences set defaults user@example.com SOGoGoogleAuthenticatorEnabled '{"SOGoGoogleAuthenticatorEnabled":0}'
            -
            +
            docker-compose exec -u sogo sogo-mailcow sogo-tool user-preferences set defaults user@example.com SOGoGoogleAuthenticatorEnabled '{"SOGoGoogleAuthenticatorEnabled":0}'
            +

            diff --git a/de/troubleshooting/debug-reset_tls/index.html b/de/troubleshooting/debug-reset_tls/index.html index 62a0f00df..ebed2398b 100644 --- a/de/troubleshooting/debug-reset_tls/index.html +++ b/de/troubleshooting/debug-reset_tls/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2346,14 +2346,14 @@

            TLS-Zertifikate zurĂźcksetzen

            Sollten Sie Probleme mit Ihrem Zertifikat, SchlĂźssel oder Let's Encrypt-Konto haben, versuchen Sie bitte, die TLS-Assets zurĂźckzusetzen:

            -
            source mailcow.conf
            +
            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
            -
            +

            Dies wird mailcow stoppen, die benĂśtigten Variablen beschaffen, ein selbstsigniertes Zertifikat erstellen und mailcow starten.

            Wenn Sie Let's Encrypt verwenden, sollten Sie vorsichtig sein, da Sie ein neues Konto und einen neuen Satz von Zertifikaten erstellen werden. Sie werden früher oder später auf ein Ratelimit stoßen.

            Bitte beachten Sie auch, dass frßhere TLSA-Datensätze ungßltig werden.

            diff --git a/de/troubleshooting/debug-rm_volumes/index.html b/de/troubleshooting/debug-rm_volumes/index.html index 2eda14cad..4e3191598 100644 --- a/de/troubleshooting/debug-rm_volumes/index.html +++ b/de/troubleshooting/debug-rm_volumes/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,8 +2348,8 @@

            Es kann sein, dass Sie einen Satz persistenter Daten entfernen wollen, um einen Konflikt zu lĂśsen oder um neu zu beginnen.

            mailcowdockerized kann variieren und hängt von Ihrem Compose-Projektnamen ab (wenn er unverändert ist, ist mailcowdockerized der richtige Wert). Wenn Sie sich unsicher sind, fßhren Sie docker volume ls aus, um eine vollständige Liste zu erhalten.

            LĂśschen Sie ein einzelnes Volume:

            -
            docker volume rm mailcowdockerized_${VOLUME_NAME}
            -
            +
            docker volume rm mailcowdockerized_${VOLUME_NAME}
            +
            • Entfernen Sie Volume mysql-vol-1, um alle MySQL-Daten zu entfernen.
            • Entfernen Sie Volume redis-vol-1 um alle Redis Daten zu entfernen.
            • diff --git a/de/troubleshooting/debug-rspamd_memory_leaks/index.html b/de/troubleshooting/debug-rspamd_memory_leaks/index.html index 51e89ff86..1c3fe9bb0 100644 --- a/de/troubleshooting/debug-rspamd_memory_leaks/index.html +++ b/de/troubleshooting/debug-rspamd_memory_leaks/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2346,7 +2346,7 @@

              Fortgeschritten: Memory-Leaks in Rspamd finden

              Eine kurze Anleitung, um einen schlecht funktionierenden Rspamd tiefgehend zu analysieren.

              -
              docker-compose exec rspamd-mailcow bash
              +
              docker-compose exec rspamd-mailcow bash
               
               if ! grep -qi 'apt-stable-asan' /etc/apt/sources.list.d/rspamd.list; then
                 sed -i 's/apt-stabil/apt-stabil-asan/i' /etc/apt/sources.list.d/rspamd.list
              @@ -2360,7 +2360,7 @@ nano /docker-entrypoint.sh
               
               export G_SLICE=always-malloc
               export ASAN_OPTIONS=new_delete_type_mismatch=0:detect_leaks=1:detect_odr_violation=0:log_path=/tmp/rspamd-asan:quarantine_size_mb=2048:malloc_context_size=8:fast_unwind_on_malloc=0
              -
              +

              Starten Sie Rspamd neu: docker-compose restart rspamd-mailcow

              Ihr Speicherverbrauch wird stark ansteigen, er wird auch stetig wachsen, was nicht mit einem mÜglichen Memory Leak zusammenhängt, nach dem Sie suchen.

              Lassen Sie den Container fĂźr ein paar Minuten, Stunden oder Tage laufen (es sollte die Zeit sein, die Sie normalerweise warten, bis der Memory Leak "passiert") und starten Sie ihn neu: docker-compose restart rspamd-mailcow.

              diff --git a/de/troubleshooting/debug/index.html b/de/troubleshooting/debug/index.html index fa4509dad..538da69ae 100644 --- a/de/troubleshooting/debug/index.html +++ b/de/troubleshooting/debug/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/backup_restore/b_n_r-accidental_deletion/index.html b/en/backup_restore/b_n_r-accidental_deletion/index.html index 5c105a7cc..b207d5cb2 100644 --- a/en/backup_restore/b_n_r-accidental_deletion/index.html +++ b/en/backup_restore/b_n_r-accidental_deletion/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2428,9 +2428,9 @@

              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 force-resync -u restoreme@example.net '*'
               docker-compose exec dovecot-mailcow doveadm quota recalc -u restoreme@example.net
              -
              +

              diff --git a/en/backup_restore/b_n_r-backup/index.html b/en/backup_restore/b_n_r-backup/index.html index 9df5c0e38..8b512cc14 100644 --- a/en/backup_restore/b_n_r-backup/index.html +++ b/en/backup_restore/b_n_r-backup/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2454,7 +2454,7 @@

              Please do not copy this script to another location.

              To run a backup, write "backup" as first parameter and either one or more components to backup as following parameters. You can also use "all" as second parameter to backup all components. Append --delete-days n to delete backups older than n days.

              -
              # Syntax:
              +
              # Syntax:
               # ./helper-scripts/backup_and_restore.sh backup (vmail|crypt|redis|rspamd|postfix|mysql|all|--delete-days)
               
               # Backup all, delete backups older than 3 days
              @@ -2465,19 +2465,19 @@ You can also use "all" as second parameter to backup all components. Append 
              +

              The script will ask you for a backup location. Inside of this location it will create folders in the format "mailcow_DATE". You should not rename those folders to not break the restore process.

              To run a backup unattended, define MAILCOW_BACKUP_LOCATION as environment variable before starting the script:

              -
              MAILCOW_BACKUP_LOCATION=/opt/backup /opt/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup all
              -
              +
              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
              -
              +
              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
              +
              #!/bin/sh
               
               # Backup mailcow data
               # https://mailcow.github.io/mailcow-dockerized-docs/backup_restore/b_n_r-backup/
              @@ -2502,17 +2502,17 @@ if [ $RESULT -ne 0 ]
                           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
              -

              +
              mkdir -p /external_share/backups/backup_script
              +

              Create cronjobs: -

              25 1 * * * rsync -aH --delete /opt/mailcow-dockerized /external_share/backups/mailcow-dockerized
              +
              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.

              diff --git a/en/backup_restore/b_n_r-backup_restore-maildir/index.html b/en/backup_restore/b_n_r-backup_restore-maildir/index.html index d7775ee1a..926e65c54 100644 --- a/en/backup_restore/b_n_r-backup_restore-maildir/index.html +++ b/en/backup_restore/b_n_r-backup_restore-maildir/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2412,15 +2412,15 @@

              Backup

              This line backups the vmail directory to a file backup_vmail.tar.gz in the mailcow root directory: -

              cd /path/to/mailcow-dockerized
              +
              cd /path/to/mailcow-dockerized
               docker run --rm -i -v $(docker inspect --format '{{ range .Mounts }}{{ if eq .Destination "/var/vmail" }}{{ .Name }}{{ end }}{{ end }}' $(docker-compose ps -q dovecot-mailcow)):/vmail -v ${PWD}:/backup debian:stretch-slim tar cvfz /backup/backup_vmail.tar.gz /vmail
              -

              +

              You can change the path by adjusting ${PWD} (which equals to the current directory) to any path you have write-access to. Set the filename backup_vmail.tar.gz to any custom name, but leave the path as it is. Example: [...] tar cvfz /backup/my_own_filename_.tar.gz

              Restore

              -
              cd /path/to/mailcow-dockerized
              +
              cd /path/to/mailcow-dockerized
               docker run --rm -it -v $(docker inspect --format '{{ range .Mounts }}{{ if eq .Destination "/var/vmail" }}{{ .Name }}{{ end }}{{ end }}' $(docker-compose ps -q dovecot-mailcow)):/vmail -v ${PWD}:/backup debian:stretch-slim tar xvfz /backup/backup_vmail.tar.gz
              -
              +

              diff --git a/en/backup_restore/b_n_r-backup_restore-mysql/index.html b/en/backup_restore/b_n_r-backup_restore-mysql/index.html index 66c02ddd8..eaed07a59 100644 --- a/en/backup_restore/b_n_r-backup_restore-mysql/index.html +++ b/en/backup_restore/b_n_r-backup_restore-mysql/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2411,20 +2411,20 @@

              MySQL (mysqldump)

              Backup

              -
              cd /path/to/mailcow-dockerized
              +
              cd /path/to/mailcow-dockerized
               source mailcow.conf
               DATE=$(date +"%Y%m%d_%H%M%S")
               docker-compose exec -T mysql-mailcow mysqldump --default-character-set=utf8mb4 -u${DBUSER} -p${DBPASS} ${DBNAME} > backup_${DBNAME}_${DATE}.sql
              -
              +

              Restore

              Warning

              You should redirect the SQL dump without docker-compose to prevent parsing errors.

              -
              cd /path/to/mailcow-dockerized
              +
              cd /path/to/mailcow-dockerized
               source mailcow.conf
               docker exec -i $(docker-compose ps -q mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} < backup_file.sql
              -
              +

              diff --git a/en/backup_restore/b_n_r-coldstandby/index.html b/en/backup_restore/b_n_r-coldstandby/index.html index a2346e61e..97f60cee6 100644 --- a/en/backup_restore/b_n_r-coldstandby/index.html +++ b/en/backup_restore/b_n_r-coldstandby/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2459,10 +2459,10 @@

              You will need a SSH-enabled destination and a keyfile to connect to said destination. The key should not be protected by a password for the script to work unattended.

              In your mailcow base directory, e.g. /opt/mailcow-dockerized you will find a file create_cold_standby.sh.

              Edit this file and change the exported variables:

              -
              export REMOTE_SSH_KEY=/path/to/keyfile
              +
              export REMOTE_SSH_KEY=/path/to/keyfile
               export REMOTE_SSH_PORT=22
               export REMOTE_SSH_HOST=mailcow-backup.host.name
              -
              +

              The key must be owned and readable by root only.

              Both the source and destination require rsync >= v3.1.0. The destination must have Docker and docker-compose v1 available.

              @@ -2470,28 +2470,28 @@ The destination must have Docker and docker-compose v1 availabl

              You may want to test the connection by running ssh mailcow-backup.host.name -p22 -i /path/to/keyfile.

              Backup and refresh the cold-standby

              Run the first backup, this may take a while depending on the connection:

              -
              bash /opt/mailcow-dockerized/create_cold_standby.sh
              -
              +
              bash /opt/mailcow-dockerized/create_cold_standby.sh
              +

              That was easy, wasn't it?

              Updating your cold-standby is just as easy:

              -
              bash /opt/mailcow-dockerized/create_cold_standby.sh
              -
              +
              bash /opt/mailcow-dockerized/create_cold_standby.sh
              +

              It's the same command.

              Automated backups with cron

              First make sure that the cron service is enabled and running:

              -
              systemctl enable cron.service && systemctl start cron.service
              -
              +
              systemctl enable cron.service && systemctl start cron.service
              +

              To automate the backups to the cold-standby server you can use a cron job. To edit the cron jobs for the root user run:

              -
              crontab -e
              -
              +
              crontab -e
              +

              Add the following lines to synchronize the cold standby server daily at 03:00. In this example errors of the last execution are logged into a file.

              -
              PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
              +
              PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
               
               0 3 * * * bash /opt/mailcow-dockerized/create_cold_standby.sh 2> /var/log/mailcow-coldstandby-sync.log
              -
              +

              If saved correctly, the cron job should be shown by typing:

              -
              crontab -l
              -
              +
              crontab -l
              +

              diff --git a/en/backup_restore/b_n_r-restore/index.html b/en/backup_restore/b_n_r-restore/index.html index f71b8eb3b..5a0f3bfd0 100644 --- a/en/backup_restore/b_n_r-restore/index.html +++ b/en/backup_restore/b_n_r-restore/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2399,9 +2399,9 @@

              Restore

              Please do not copy this script to another location.

              To run a restore, start mailcow, use the script with "restore" as first parameter.

              -
              # Syntax:
              +
              # Syntax:
               # ./helper-scripts/backup_and_restore.sh restore
              -
              +

              The script will ask you for a backup location containing the mailcow_DATE folders.


              diff --git a/en/client/client-android/index.html b/en/client/client-android/index.html index 6cd131f86..94faf4332 100644 --- a/en/client/client-android/index.html +++ b/en/client/client-android/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/client/client-apple/index.html b/en/client/client-apple/index.html index 0d3868fc7..7a3b70f42 100644 --- a/en/client/client-apple/index.html +++ b/en/client/client-apple/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/client/client-emclient/index.html b/en/client/client-emclient/index.html index ae1296159..20bec9461 100644 --- a/en/client/client-emclient/index.html +++ b/en/client/client-emclient/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/client/client-kontact/index.html b/en/client/client-kontact/index.html index c1b9cdf3b..dfd7a7232 100644 --- a/en/client/client-kontact/index.html +++ b/en/client/client-kontact/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/client/client-manual/index.html b/en/client/client-manual/index.html index 5ea21952f..36630e09c 100644 --- a/en/client/client-manual/index.html +++ b/en/client/client-manual/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/client/client-outlook/index.html b/en/client/client-outlook/index.html index 4103918e7..a5575b0d8 100644 --- a/en/client/client-outlook/index.html +++ b/en/client/client-outlook/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/client/client-thunderbird/index.html b/en/client/client-thunderbird/index.html index 91b7b5ae7..30e57da06 100644 --- a/en/client/client-thunderbird/index.html +++ b/en/client/client-thunderbird/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/client/client-windows/index.html b/en/client/client-windows/index.html index 93eadea57..b97dfa181 100644 --- a/en/client/client-windows/index.html +++ b/en/client/client-windows/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/client/client/index.html b/en/client/client/index.html index 159ff5e9e..e38471b14 100644 --- a/en/client/client/index.html +++ b/en/client/client/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/i_u_m/i_u_m_deinstall/index.html b/en/i_u_m/i_u_m_deinstall/index.html index 5315f3b8c..adc94c7ff 100644 --- a/en/i_u_m/i_u_m_deinstall/index.html +++ b/en/i_u_m/i_u_m_deinstall/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2346,8 +2346,8 @@

              Deinstallation

              To remove mailcow: dockerized with all it's volumes, images and containers do:

              -
              docker-compose down -v --rmi all --remove-orphans
              -
              +
              docker-compose down -v --rmi all --remove-orphans
              +

              Info

                diff --git a/en/i_u_m/i_u_m_install/index.html b/en/i_u_m/i_u_m_install/index.html index 39ca5a652..002337086 100644 --- a/en/i_u_m/i_u_m_install/index.html +++ b/en/i_u_m/i_u_m_install/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2351,10 +2351,10 @@
                • Docker -

                  curl -sSL https://get.docker.com/ | CHANNEL=stable sh
                  +
                  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 --now docker
                  -

                  +

                • Docker-Compose

                  @@ -2365,44 +2365,44 @@ systemctl enable --now docker

                  mailcow requires the latest version of docker-compose v1. 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 correct 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
              +
              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
              -
              +

              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
              -
              +
              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
              -
              +
              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 bootstrapping 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.

              -
              $ su
              +
              $ su
               # umask
               0022 # <- Verify it is 0022
               # cd /opt
               # git clone https://github.com/mailcow/mailcow-dockerized
               # cd mailcow-dockerized
              -
              +

              3. Generate a configuration file. Use a FQDN (host.domain.tld) as hostname when asked. -

              ./generate_config.sh
              -

              +
              ./generate_config.sh
              +

              4. Change configuration if you want or need to. -

              nano mailcow.conf
              -
              +
              nano mailcow.conf
              +
              If you plan to use a reverse proxy, you can, for example, bind HTTPS to 127.0.0.1 on port 8443 and HTTP to 127.0.0.1 on port 8080.

              You may need to stop an existing pre-installed MTA which blocks port 25/tcp. See this chapter to learn how to reconfigure Postfix to run besides mailcow after a successful installation.

              Some updates modify mailcow.conf and add new parameters. It is hard to keep track of them in the documentation. Please check their description and, if unsure, ask at the known channels for advise.

              @@ -2410,20 +2410,20 @@ If you plan to use a reverse proxy, you can, for example, bind HTTPS to 127.0.0.

              Whenever you run into trouble and strange phenomena, please check your MTU.

              Edit docker-compose.yml and change the network settings according to your MTU. Add the new driver_opts parameter like this: -

              networks:
              +
              networks:
                 mailcow-network:
                   ...
                   driver_opts:
                     com.docker.network.driver.mtu: 1450
                   ...
              -

              +

              4.2. Users without an IPv6 enabled network on their host system:

              Enable IPv6. Finally.

              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 for the mailcow network to prevent unforeseen issues.

              5. Pull the images and run the compose file. The parameter -d will start mailcow: dockerized detached: -

              docker-compose pull
              +
              docker-compose pull
               docker-compose up -d
              -

              +

              Done!

              You can now access https://${MAILCOW_HOSTNAME} with the default credentials admin + password moohoo.

              diff --git a/en/i_u_m/i_u_m_migration/index.html b/en/i_u_m/i_u_m_migration/index.html index a73d9ea0b..213339b53 100644 --- a/en/i_u_m/i_u_m_migration/index.html +++ b/en/i_u_m/i_u_m_migration/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2359,43 +2359,43 @@ Install Docker
              • Docker -

                curl -sSL https://get.docker.com/ | CHANNEL=stable sh
                +
                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
                -

                +

              • docker-compose -

                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
                +
                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
                -

                +

              Please use the latest Docker engine available and do not use the engine that ships with your distros repository.

              2. Stop Docker and assure Docker has stopped: -

              systemctl stop docker.service
              +
              systemctl stop docker.service
               systemctl status docker.service
              -

              +

              3. Run the following commands on the source machine (take care of adding the trailing slashes in the first path parameter as shown below!) - WARNING: This command will erase anything that may already exist under /var/lib/docker/volumes on the target machine: -

              rsync -aHhP --numeric-ids --delete /opt/mailcow-dockerized/ root@target-machine.example.com:/opt/mailcow-dockerized
              +
              rsync -aHhP --numeric-ids --delete /opt/mailcow-dockerized/ root@target-machine.example.com:/opt/mailcow-dockerized
               rsync -aHhP --numeric-ids --delete /var/lib/docker/volumes/ root@target-machine.example.com:/var/lib/docker/volumes
              -

              +

              4. Shut down mailcow and stop Docker on the source machine. -

              cd /opt/mailcow-dockerized
              +
              cd /opt/mailcow-dockerized
               docker-compose down
               systemctl stop docker.service
              -

              +

              5. Repeat step 3 with the same commands. This will be much quicker than the first time.

              6. Switch over to the target machine and start Docker. -

              systemctl start docker.service
              -

              +
              systemctl start docker.service
              +

              7. Now pull the mailcow Docker images on the target machine. -

              cd /opt/mailcow-dockerized
              +
              cd /opt/mailcow-dockerized
               docker-compose pull
              -

              +

              8. Start the whole mailcow stack and everything should be done! -

              docker-compose up -d
              -

              +
              docker-compose up -d
              +

              9. Finally, change your DNS settings to point to the target server.


              diff --git a/en/i_u_m/i_u_m_update/index.html b/en/i_u_m/i_u_m_update/index.html index a741457be..854164a1f 100644 --- a/en/i_u_m/i_u_m_update/index.html +++ b/en/i_u_m/i_u_m_update/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2480,13 +2480,13 @@

              An update script in your mailcow-dockerized directory will take care of updates.

              But use it with caution! If you think you made a lot of changes to the mailcow code, you should use the manual update guide below.

              Run the update script: -

              ./update.sh
              -

              +
              ./update.sh
              +

              If it needs to, it will ask you how you wish to proceed. Merge errors will be reported. Some minor conflicts will be auto-corrected (in favour for the mailcow: dockerized repository code).

              Options

              -
              # Options can be combined
              +
              # Options can be combined
               
               # - Check for updates and show changes
               ./update.sh --check
              @@ -2509,22 +2509,22 @@ Some minor conflicts will be auto-corrected (in favour for the mailcow: dockeriz
               
               # - Don't update, but prefetch images and exit
               ./update.sh --prefetch
              -
              +

              I forgot what I changed before running update.sh

              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
              +
              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
              +
              docker-compose down
               # Replace commit ID 22cd00b5e28893ef9ddef3c2b5436453cc5223ab by your ID
               git checkout 22cd00b5e28893ef9ddef3c2b5436453cc5223ab
               docker-compose pull
               docker-compose up -d
              -
              +

              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 for more details.

              Footnotes

              diff --git a/en/index.html b/en/index.html index af897fb55..fc168cabb 100644 --- a/en/index.html +++ b/en/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/manual-guides/ClamAV/u_e-clamav-additional_dbs/index.html b/en/manual-guides/ClamAV/u_e-clamav-additional_dbs/index.html index bec8f54d7..836cd1060 100644 --- a/en/manual-guides/ClamAV/u_e-clamav-additional_dbs/index.html +++ b/en/manual-guides/ClamAV/u_e-clamav-additional_dbs/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2466,21 +2466,21 @@
            • You will need to get your_id from one of the download links, they are individual for every user
            • Add to data/conf/clamav/freshclam.conf with replaced your_id part: -

              DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfo.hdb
              +
              DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfo.hdb
               DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfo.ign2
               DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/javascript.ndb
               DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/spam_marketing.ndb
               DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfohtml.hdb
               DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfoascii.hdb
               DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfopdf.hdb
              -

              +

            • For free SecuriteInfo databases, download speed is limited to 300 kB/s. In data/conf/clamav/freshclam.conf, increase the default ReceiveTimeout 20 value to ReceiveTimeout 90 (time in seconds), otherwise some of the database downloads could fail because of their size.

            • Adjust data/conf/clamav/clamd.conf to align with next settings: -

              DetectPUA yes
              +
              DetectPUA yes
               ExcludePUA PUA.Win.Packer
               ExcludePUA PUA.Win.Trojan.Packed
               ExcludePUA PUA.Win.Trojan.Molebox
              @@ -2493,11 +2493,11 @@ MaxEmbeddedPE 100M
               MaxHTMLNormalize 50M
               MaxScriptNormalize 50M
               MaxZipTypeRcg 50M
              -

              +

            • Restart ClamAV container: -
              docker-compose restart clamd-mailcow
              -
            • +
              docker-compose restart clamd-mailcow
              +

          Please note:

            @@ -2509,14 +2509,14 @@ MaxZipTypeRcg 50M

            Enable InterServer databases

            1. Add to data/conf/clamav/freshclam.conf: -
              DatabaseCustomURL http://sigs.interserver.net/interserver256.hdb
              +
              DatabaseCustomURL http://sigs.interserver.net/interserver256.hdb
               DatabaseCustomURL http://sigs.interserver.net/interservertopline.db
               DatabaseCustomURL http://sigs.interserver.net/shell.ldb
               DatabaseCustomURL http://sigs.interserver.net/whitelist.fp
              -
            2. +
        • Restart ClamAV container: -
          docker-compose restart clamd-mailcow
          -
        • +
          docker-compose restart clamd-mailcow
          +

          diff --git a/en/manual-guides/ClamAV/u_e-clamav-whitelist/index.html b/en/manual-guides/ClamAV/u_e-clamav-whitelist/index.html index 799fb7635..efd22c212 100644 --- a/en/manual-guides/ClamAV/u_e-clamav-whitelist/index.html +++ b/en/manual-guides/ClamAV/u_e-clamav-whitelist/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2398,22 +2398,22 @@

          Whitelist specific ClamAV signatures

          You may find that legitimate (clean) mail is being blocked by ClamAV (Rspamd will flag the mail with VIRUS_FOUND). For instance, interactive PDF form attachments are blocked by default because the embedded Javascript code may be used for nefarious purposes. Confirm by looking at the clamd logs, e.g.:

          -
          docker-compose logs clamd-mailcow | grep "FOUND"
          -
          +
          docker-compose logs clamd-mailcow | grep "FOUND"
          +

          This line confirms that such was identified:

          -
          clamd-mailcow_1      | Sat Sep 28 07:43:24 2019 -> instream(local): PUA.Pdf.Trojan.EmbeddedJavaScript-1(e887d2ac324ce90750768b86b63d0749:363325) FOUND
          -
          +
          clamd-mailcow_1      | Sat Sep 28 07:43:24 2019 -> instream(local): PUA.Pdf.Trojan.EmbeddedJavaScript-1(e887d2ac324ce90750768b86b63d0749:363325) FOUND
          +

          To whitelist this particular signature (and enable sending this type of file attached), add it to the ClamAV signature whitelist file:

          -
          echo 'PUA.Pdf.Trojan.EmbeddedJavaScript-1' >> data/conf/clamav/whitelist.ign2
          -
          +
          echo 'PUA.Pdf.Trojan.EmbeddedJavaScript-1' >> data/conf/clamav/whitelist.ign2
          +

          Then restart the clamd-mailcow service container in the mailcow UI or using docker-compose:

          -
          docker-compose restart clamd-mailcow
          -
          +
          docker-compose restart clamd-mailcow
          +

          Cleanup cached ClamAV results in Redis:

          -
          # docker-compose exec redis-mailcow  /bin/sh
          +
          # docker-compose exec redis-mailcow  /bin/sh
           /data # redis-cli KEYS rs_cl* | xargs redis-cli DEL
           /data # exit
          -
          +

          diff --git a/en/manual-guides/Docker/u_e-docker-cust_dockerfiles/index.html b/en/manual-guides/Docker/u_e-docker-cust_dockerfiles/index.html index 7d9808bd2..cfa8ef675 100644 --- a/en/manual-guides/Docker/u_e-docker-cust_dockerfiles/index.html +++ b/en/manual-guides/Docker/u_e-docker-cust_dockerfiles/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,14 +2348,14 @@

          Customize Dockerfiles

          You need to copy the override file with corresponding build tags to the mailcow: dockerized root folder (i.e. /opt/mailcow-dockerized):

          -
          cp helper-scripts/docker-compose.override.yml.d/BUILD_FLAGS/docker-compose.override.yml docker-compose.override.yml
          -
          +
          cp helper-scripts/docker-compose.override.yml.d/BUILD_FLAGS/docker-compose.override.yml docker-compose.override.yml
          +

          Make your changes in data/Dockerfiles/$service and build the image locally:

          -
          docker build data/Dockerfiles/service -t mailcow/$service
          -
          +
          docker build data/Dockerfiles/service -t mailcow/$service
          +

          Now auto-recreate modified containers:

          -
          docker-compose up -d
          -
          +
          docker-compose up -d
          +

          diff --git a/en/manual-guides/Docker/u_e-docker-dc_bash_compl/index.html b/en/manual-guides/Docker/u_e-docker-dc_bash_compl/index.html index 82ee7adf3..3404a09c2 100644 --- a/en/manual-guides/Docker/u_e-docker-dc_bash_compl/index.html +++ b/en/manual-guides/Docker/u_e-docker-dc_bash_compl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,8 +2348,8 @@

          Docker Compose Bash Completion

          To get some sexy bash completion inside your containers simply execute the following:

          -
          curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
          -
          +
          curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
          +

          diff --git a/en/manual-guides/Dovecot/u_e-dovecot-any_acl/index.html b/en/manual-guides/Dovecot/u_e-dovecot-any_acl/index.html index 44aa33bf8..b2eb32914 100644 --- a/en/manual-guides/Dovecot/u_e-dovecot-any_acl/index.html +++ b/en/manual-guides/Dovecot/u_e-dovecot-any_acl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,8 +2349,8 @@

          On August the 17th, we disabled the possibility to share with "any" or "all authenticated users" by default.

          This function can be re-enabled by setting ACL_ANYONE to allow in mailcow.conf:

          -
          ACL_ANYONE=allow
          -
          +
          ACL_ANYONE=allow
          +

          Apply the changes by running docker-compose up -d.


          diff --git a/en/manual-guides/Dovecot/u_e-dovecot-catchall_vacation/index.html b/en/manual-guides/Dovecot/u_e-dovecot-catchall_vacation/index.html index 097dcced2..e71a976da 100644 --- a/en/manual-guides/Dovecot/u_e-dovecot-catchall_vacation/index.html +++ b/en/manual-guides/Dovecot/u_e-dovecot-catchall_vacation/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/manual-guides/Dovecot/u_e-dovecot-expunge/index.html b/en/manual-guides/Dovecot/u_e-dovecot-expunge/index.html index 884d1bd2f..1beefec86 100644 --- a/en/manual-guides/Dovecot/u_e-dovecot-expunge/index.html +++ b/en/manual-guides/Dovecot/u_e-dovecot-expunge/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2454,17 +2454,17 @@

          The manual way

          That said, let's dive in:

          Delete a user's mails inside the junk folder that are read and older than 4 hours

          -
          docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'Junk' SEEN not SINCE 4h
          -
          +
          docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'Junk' SEEN not SINCE 4h
          +

          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
          -
          +
          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
          -
          +
          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

          -
          docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'INBOX/custom-folder' not FLAGGED not SINCE 2w
          -
          +
          docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'INBOX/custom-folder' not FLAGGED not SINCE 2w
          +

          Info

          For possible time spans or search keys have a look at man doveadm-search-query

          @@ -2472,21 +2472,21 @@

          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:

          -
          #!/bin/bash
          +
          #!/bin/bash
           # Path to mailcow-dockerized, e.g. /opt/mailcow-dockerized
           cd /path/to/your/mailcow-dockerized
           
           /usr/local/bin/docker-compose exec -T dovecot-mailcow doveadm expunge -A mailbox 'Junk' savedbefore 2w
           /usr/local/bin/docker-compose exec -T dovecot-mailcow doveadm expunge -A mailbox 'Junk' SEEN not SINCE 12h
           [...]
          -
          +

          To create a cron job you may execute crontab -e and insert something like the following to execute a script:

          -
          # Execute everyday at 04:00 A.M.
          +
          # 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'
          +
          version: '2.1'
           
           services:
           
          @@ -2504,12 +2504,12 @@ services:
                 - "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. 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)] 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.

          diff --git a/en/manual-guides/Dovecot/u_e-dovecot-extra_conf/index.html b/en/manual-guides/Dovecot/u_e-dovecot-extra_conf/index.html index 8361e9cc6..108ac39d3 100644 --- a/en/manual-guides/Dovecot/u_e-dovecot-extra_conf/index.html +++ b/en/manual-guides/Dovecot/u_e-dovecot-extra_conf/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,8 +2349,8 @@

          Create a file data/conf/dovecot/extra.conf - if missing - and add your additional content here.

          Restart dovecot-mailcow to apply your changes:

          -
          docker-compose restart dovecot-mailcow
          -
          +
          docker-compose restart dovecot-mailcow
          +

          diff --git a/en/manual-guides/Dovecot/u_e-dovecot-fts/index.html b/en/manual-guides/Dovecot/u_e-dovecot-fts/index.html index 6ee05db2a..76281c276 100644 --- a/en/manual-guides/Dovecot/u_e-dovecot-fts/index.html +++ b/en/manual-guides/Dovecot/u_e-dovecot-fts/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2443,19 +2443,19 @@

          The default heap size (1024 M) is defined in mailcow.conf.

          Since we run in Docker and create our containers with the "restart: always" flag, a oom situation will at least only trigger a restart of the container.

          -
          # single user
          +
          # single user
           docker-compose exec dovecot-mailcow doveadm fts rescan -u user@domain
           # all users
           docker-compose exec dovecot-mailcow doveadm fts rescan -A
          -
          +

          Dovecot Wiki: "Scan what mails exist in the full text search index and compare those to what actually exist in mailboxes. This removes mails from the index that have already been expunged and makes sure that the next doveadm index will index all the missing mails (if any)."

          This does not re-index a mailbox. It basically repairs a given index.

          If you want to re-index data immediately, you can run the followig command, where '*' can also be a mailbox mask like 'Sent'. You do not need to run these commands, but it will speed things up a bit:

          -
          # single user
          +
          # single user
           docker-compose exec dovecot-mailcow doveadm index -u user@domain '*'
           # all users, but obviously slower and more dangerous
           docker-compose exec dovecot-mailcow doveadm index -A '*'
          -
          +

          This will take some time depending on your machine and Solr can run oom, monitor it!

          Because re-indexing is very sensible, we did not include it to mailcow UI. You will need to take care of any errors while re-indexing a mailbox.

          Delete mailbox data

          diff --git a/en/manual-guides/Dovecot/u_e-dovecot-idle_interval/index.html b/en/manual-guides/Dovecot/u_e-dovecot-idle_interval/index.html index 5c69ad7d2..49f3cb48e 100644 --- a/en/manual-guides/Dovecot/u_e-dovecot-idle_interval/index.html +++ b/en/manual-guides/Dovecot/u_e-dovecot-idle_interval/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2462,8 +2462,8 @@

          Change configuration

          Create a new file data/conf/dovecot/extra.conf (or edit it if it already exists). Insert the setting followed by the new value. For example, to set the interval to 5 minutes you could type:

          -
          imap_idle_notify_interval = 5 mins
          -
          +
          imap_idle_notify_interval = 5 mins
          +

          29 minutes is the maximum value allowed by the corresponding RFC.

          Warning

          @@ -2471,13 +2471,13 @@ Insert the setting followed by the new value. For example, to set the interval t

          Reload Dovecot

          Now reload Dovecot: -

          docker-compose exec dovecot-mailcow dovecot reload
          -

          +
          docker-compose exec dovecot-mailcow dovecot reload
          +

          Info

          You can check the value of this setting with -

          docker-compose exec dovecot-mailcow dovecot -a | grep "imap_idle_notify_interval"
          -
          +
          docker-compose exec dovecot-mailcow dovecot -a | grep "imap_idle_notify_interval"
          +
          If you didn't change it, it should be at 2m. If you did change it, you should see your new value.

          diff --git a/en/manual-guides/Dovecot/u_e-dovecot-mail-crypt/index.html b/en/manual-guides/Dovecot/u_e-dovecot-mail-crypt/index.html index d793a2f47..acc38ea93 100644 --- a/en/manual-guides/Dovecot/u_e-dovecot-mail-crypt/index.html +++ b/en/manual-guides/Dovecot/u_e-dovecot-mail-crypt/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2350,7 +2350,7 @@

          Mails are stored compressed (lz4) and encrypted. The key pair can be found in crypt-vol-1.

          If you want to decode/encode existing maildir files, you can use the following script at your own risk:

          Enter Dovecot by running docker-compose exec dovecot-mailcow /bin/bash in the mailcow-dockerized location.

          -
          # Decrypt /var/vmail
          +
          # Decrypt /var/vmail
           find /var/vmail/ -type f -regextype egrep -regex '.*S=.*W=.*' | while read -r file; do
           if [[ $(head -c7 "$file") == "CRYPTED" ]]; then
           doveadm fs get compress lz4:0:crypt:private_key_path=/mail_crypt/ecprivkey.pem:public_key_path=/mail_crypt/ecpubkey.pem:posix:prefix=/ \
          @@ -2374,7 +2374,7 @@ doveadm fs put crypt private_key_path=/mail_crypt/ecprivkey.pem:public_key_path=
             chown 5000:5000 "$file"
           fi
           done
          -
          +

          diff --git a/en/manual-guides/Dovecot/u_e-dovecot-more/index.html b/en/manual-guides/Dovecot/u_e-dovecot-more/index.html index 27b20d7e8..8c0174c86 100644 --- a/en/manual-guides/Dovecot/u_e-dovecot-more/index.html +++ b/en/manual-guides/Dovecot/u_e-dovecot-more/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2414,25 +2414,25 @@

          doveadm quota

          The quota get and quota recalc1 commands are used to display or recalculate the current user's quota usage. The reported values are in kilobytes.

          To list the current quota status for a user / mailbox, do:

          -
          doveadm quota get -u 'mailbox@example.org'
          -
          +
          doveadm quota get -u 'mailbox@example.org'
          +

          To list the quota storage value for all users, do:

          -
          doveadm quota get -A |grep "STORAGE"
          -
          +
          doveadm quota get -A |grep "STORAGE"
          +

          Recalculate a single user's quota usage:

          -
          doveadm quota recalc -u 'mailbox@example.org'
          -
          +
          doveadm quota recalc -u 'mailbox@example.org'
          +

          The doveadm search2 command is used to find messages matching your query. It can return the username, mailbox-GUID / -UID and message-GUIDs / -UIDs.

          To view the number of messages, by user, in their .Trash folder:

          -
          doveadm search -A mailbox 'Trash' | awk '{print $1}' | sort | uniq -c
          -
          +
          doveadm search -A mailbox 'Trash' | awk '{print $1}' | sort | uniq -c
          +

          Show all messages in a user's inbox older then 90 days:

          -
          doveadm search -u 'mailbox@example.org' mailbox 'INBOX' savedbefore 90d
          -
          +
          doveadm search -u 'mailbox@example.org' mailbox 'INBOX' savedbefore 90d
          +

          Show all messages in any folder that are older then 30 days for mailbox@example.org:

          -
          doveadm search -u 'mailbox@example.org' mailbox "*" savedbefore 30d
          -
          +
          doveadm search -u 'mailbox@example.org' mailbox "*" savedbefore 30d
          +

            diff --git a/en/manual-guides/Dovecot/u_e-dovecot-public_folder/index.html b/en/manual-guides/Dovecot/u_e-dovecot-public_folder/index.html index 98c04732e..856ca167e 100644 --- a/en/manual-guides/Dovecot/u_e-dovecot-public_folder/index.html +++ b/en/manual-guides/Dovecot/u_e-dovecot-public_folder/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2398,7 +2398,7 @@

            Create a new public namespace "Public" and a mailbox "Develcow" inside that namespace:

            Edit or create data/conf/dovecot/extra.conf, add:

            -
            namespace {
            +
            namespace {
               type = public
               separator = /
               prefix = Public/
            @@ -2408,18 +2408,18 @@
                 auto = subscribe
               }
             }
            -
            +

            :INDEXPVT=~/public can be omitted if per-user seen flags are not wanted.

            The new mailbox in the public namespace will be auto-subscribed by users.

            To allow all authenticated users access full to that new mailbox (not the whole namespace), run:

            -
            docker-compose exec dovecot-mailcow doveadm acl set -A "Public/Develcow" "authenticated" lookup read write write-seen write-deleted insert post delete expunge create
            -
            +
            docker-compose exec dovecot-mailcow doveadm acl set -A "Public/Develcow" "authenticated" lookup read write write-seen write-deleted insert post delete expunge create
            +

            Adjust the command to your needs if you like to assign more granular rights per user (use -u user@domain instead of -A for example).

            Allow authenticated users access to the whole public namespace

            To allow all authenticated users access full access to the whole public namespace and its subfolders, create a new dovecot-acl file in the namespace root directory:

            Open/edit/create /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/public/dovecot-acl (adjust the path accordingly) to create the global ACL file with the following content:

            -
            authenticated kxeilprwts
            -
            +
            authenticated kxeilprwts
            +

            kxeilprwts equals to lookup read write write-seen write-deleted insert post delete expunge create.

            You can use doveadm acl set -u user@domain "Public/Develcow" user=user@domain lookup read to limit access for a single user. You may also turn it around to limit access for all users to "lr" and grant only some users full access.

            See Dovecot ACL for further information about ACL.

            diff --git a/en/manual-guides/Dovecot/u_e-dovecot-static_master/index.html b/en/manual-guides/Dovecot/u_e-dovecot-static_master/index.html index 002e8c592..43215acfe 100644 --- a/en/manual-guides/Dovecot/u_e-dovecot-static_master/index.html +++ b/en/manual-guides/Dovecot/u_e-dovecot-static_master/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2351,9 +2351,9 @@

            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_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.

            diff --git a/en/manual-guides/Dovecot/u_e-dovecot-vmail-volume/index.html b/en/manual-guides/Dovecot/u_e-dovecot-vmail-volume/index.html index 9bddba1b8..294356bc6 100644 --- a/en/manual-guides/Dovecot/u_e-dovecot-vmail-volume/index.html +++ b/en/manual-guides/Dovecot/u_e-dovecot-vmail-volume/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2442,26 +2442,26 @@

            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
          +
          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'
          +
          version: '2.1'
           volumes:
             vmail-vol-1:
               driver_opts:
                 type: none
                 device: /data/mailcow/vmail   
                 o: bind
          -
          +

          Moving an existing vmail folder:

          • Locate the current vmail folder by its "Mountpoint" attribute: docker volume inspect mailcowdockerized_vmail-vol-1
          -
          [
          +
          [
               {
                   "CreatedAt": "2019-06-16T22:08:34+02:00",
                   "Driver": "local",
          @@ -2476,7 +2476,7 @@ volumes:
                   "Scope": "local"
               }
           ]
          -
          +
          • Copy the content of the Mountpoint folder to the new location (e.g. /data/mailcow/vmail) using cp -a, rsync -a or a similar non strcuture breaking copy command
          • Stop mailcow by executing docker-compose down from within your mailcow root folder (e.g. /opt/mailcow-dockerized)
          • diff --git a/en/manual-guides/Nginx/u_e-nginx_custom/index.html b/en/manual-guides/Nginx/u_e-nginx_custom/index.html index fdb1c4603..d0b453e42 100644 --- a/en/manual-guides/Nginx/u_e-nginx_custom/index.html +++ b/en/manual-guides/Nginx/u_e-nginx_custom/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2444,9 +2444,9 @@

            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
            -
            -
            server {
            +
            nano data/conf/nginx/my_custom_site.conf
            +
            +
            server {
               ssl_certificate /etc/ssl/mail/cert.pem;
               ssl_certificate_key /etc/ssl/mail/key.pem;
               ssl_protocols TLSv1.2 TLSv1.3;
            @@ -2478,12 +2478,12 @@
                 return 301 https://$server_name$request_uri;
               }
             }
            -
            +

            New site with proxy to a remote location

            Another example with a reverse proxy configuration:

            -
            nano data/conf/nginx/my_custom_site.conf
            -
            -
            server {
            +
            nano data/conf/nginx/my_custom_site.conf
            +
            +
            server {
               ssl_certificate /etc/ssl/mail/cert.pem;
               ssl_certificate_key /etc/ssl/mail/key.pem;
               ssl_protocols TLSv1.2 TLSv1.3;
            @@ -2519,18 +2519,18 @@
                 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:

            -
            nano data/conf/nginx/site.my_content.custom
            -
            +
            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.

            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.

            Restart Nginx (and PHP-FPM, if a new listener was created):

            -
            docker-compose restart nginx-mailcow
            +
            docker-compose restart nginx-mailcow
             docker-compose restart php-fpm-mailcow
            -
            +

            diff --git a/en/manual-guides/Nginx/u_e-nginx_webmail-site/index.html b/en/manual-guides/Nginx/u_e-nginx_webmail-site/index.html index f91864d53..0504223d3 100644 --- a/en/manual-guides/Nginx/u_e-nginx_webmail-site/index.html +++ b/en/manual-guides/Nginx/u_e-nginx_webmail-site/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2350,7 +2350,7 @@

            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"!

            nano data/conf/nginx/webmail.conf

            -
            server {
            +
            server {
               ssl_certificate /etc/ssl/mail/cert.pem;
               ssl_certificate_key /etc/ssl/mail/key.pem;
               index index.php index.html;
            @@ -2369,12 +2369,12 @@
                 return 301 https://CHANGE_TO_MAILCOW_HOSTNAME/SOGo;
               }
             }
            -
            +

            Save and restart Nginx: docker-compose restart nginx-mailcow.

            Now open mailcow.conf and find ADDITIONAL_SAN. Add webmail.example.org to this array, don't use quotes!

            -
            ADDITIONAL_SAN=webmail.example.org
            -
            +
            ADDITIONAL_SAN=webmail.example.org
            +

            Run docker-compose up -d. See "acme-mailcow" and "nginx-mailcow" logs if anything fails.


            diff --git a/en/manual-guides/Postfix/u_e-postfix-attachment_size/index.html b/en/manual-guides/Postfix/u_e-postfix-attachment_size/index.html index ad184d7cd..70dd921da 100644 --- a/en/manual-guides/Postfix/u_e-postfix-attachment_size/index.html +++ b/en/manual-guides/Postfix/u_e-postfix-attachment_size/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,8 +2349,8 @@

            Open data/conf/postfix/extra.cf and set the message_size_limit accordingly in bytes. See main.cf for the default value.

            Restart Postfix:

            -
            docker-compose restart postfix-mailcow
            -
            +
            docker-compose restart postfix-mailcow
            +

            diff --git a/en/manual-guides/Postfix/u_e-postfix-custom_transport/index.html b/en/manual-guides/Postfix/u_e-postfix-custom_transport/index.html index 39c385a81..4c8e66d45 100644 --- a/en/manual-guides/Postfix/u_e-postfix-custom_transport/index.html +++ b/en/manual-guides/Postfix/u_e-postfix-custom_transport/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/manual-guides/Postfix/u_e-postfix-disable_sender_verification/index.html b/en/manual-guides/Postfix/u_e-postfix-disable_sender_verification/index.html index c7df4b478..74110d613 100644 --- a/en/manual-guides/Postfix/u_e-postfix-disable_sender_verification/index.html +++ b/en/manual-guides/Postfix/u_e-postfix-disable_sender_verification/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2416,14 +2416,14 @@

            Deprecated guide (DO NOT USE ON NEWER MAILCOWS!)

            This option is not best-practice and should only be implemented when there is no other option available to achieve whatever you are trying to do.

            Simply create a file data/conf/postfix/check_sasl_access and enter the following content. This user must exist in your installation and needs to authenticate before sending mail. -

            user-to-allow-everything@example.com OK
            -

            +
            user-to-allow-everything@example.com OK
            +

            Open data/conf/postfix/main.cf and find smtpd_sender_restrictions. Prepend check_sasl_access hash:/opt/postfix/conf/check_sasl_access like this: -

            smtpd_sender_restrictions = check_sasl_access hash:/opt/postfix/conf/check_sasl_access reject_authenticated_sender_login_mismatch [...]
            -

            +
            smtpd_sender_restrictions = check_sasl_access hash:/opt/postfix/conf/check_sasl_access reject_authenticated_sender_login_mismatch [...]
            +

            Run postmap on check_sasl_access:

            -
            docker-compose exec postfix-mailcow postmap /opt/postfix/conf/check_sasl_access
            -
            +
            docker-compose exec postfix-mailcow postmap /opt/postfix/conf/check_sasl_access
            +

            Restart the Postfix container.


            diff --git a/en/manual-guides/Postfix/u_e-postfix-extra_cf/index.html b/en/manual-guides/Postfix/u_e-postfix-extra_cf/index.html index 0a89dbc22..04e878bdc 100644 --- a/en/manual-guides/Postfix/u_e-postfix-extra_cf/index.html +++ b/en/manual-guides/Postfix/u_e-postfix-extra_cf/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2351,8 +2351,8 @@

            Postfix will complain about duplicate values once after starting postfix-mailcow, this is intended.

            Syslog-ng was configured to hide those warnings while Postfix is running, to not spam the log files with unnecessary information every time a service is used.

            Restart postfix-mailcow to apply your changes:

            -
            docker-compose restart postfix-mailcow
            -
            +
            docker-compose restart postfix-mailcow
            +

            diff --git a/en/manual-guides/Postfix/u_e-postfix-pflogsumm/index.html b/en/manual-guides/Postfix/u_e-postfix-pflogsumm/index.html index a369af940..e342474d5 100644 --- a/en/manual-guides/Postfix/u_e-postfix-pflogsumm/index.html +++ b/en/manual-guides/Postfix/u_e-postfix-pflogsumm/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,13 +2348,13 @@

            Statistics with pflogsumm

            To use pflogsumm with the default logging driver, we need to query postfix-mailcow via docker logs and direct the output to pflogsumm:

            -
            docker logs --since 24h $(docker ps -qf name=postfix-mailcow) | pflogsumm
            -
            +
            docker logs --since 24h $(docker ps -qf name=postfix-mailcow) | pflogsumm
            +

            The above log output is limited to the last 24 hours.

            It is also possible to create a daily pflogsumm report via cron. Create the /etc/cron.d/pflogsumm file with the following content:

            -
            SHELL=/bin/bash
            +
            SHELL=/bin/bash
             59 23 * * root docker logs --since 24h $(docker ps -qf name=postfix-mailcow) | /usr/sbin/pflogsumm -d today | mail -s "Postfix Report of $(date)" postmaster@example.net
            -
            +

            To work, a local postfix must be installed on the server, which relays to the mailcow postfix.

            More detailed information can be found in section Post installation tasks -> Local MTA on Dockerhost.

            Based on the postfix logs of the last 24 hours, this example then sends a pflogsumm report to postmaster@example.net every day at 23:59:00.

            diff --git a/en/manual-guides/Postfix/u_e-postfix-postscreen_whitelist/index.html b/en/manual-guides/Postfix/u_e-postfix-postscreen_whitelist/index.html index 186130d0e..dc46f2166 100644 --- a/en/manual-guides/Postfix/u_e-postfix-postscreen_whitelist/index.html +++ b/en/manual-guides/Postfix/u_e-postfix-postscreen_whitelist/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2353,11 +2353,11 @@

            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.
            +
            # 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.


            diff --git a/en/manual-guides/Postfix/u_e-postfix-relayhost/index.html b/en/manual-guides/Postfix/u_e-postfix-relayhost/index.html index 16e1dc120..ae2aa53d4 100644 --- a/en/manual-guides/Postfix/u_e-postfix-relayhost/index.html +++ b/en/manual-guides/Postfix/u_e-postfix-relayhost/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/manual-guides/Postfix/u_e-postfix-trust_networks/index.html b/en/manual-guides/Postfix/u_e-postfix-trust_networks/index.html index ece707e37..3e5db7433 100644 --- a/en/manual-guides/Postfix/u_e-postfix-trust_networks/index.html +++ b/en/manual-guides/Postfix/u_e-postfix-trust_networks/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2447,15 +2447,15 @@

            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
            -
            +
            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
            -
            +
            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

            diff --git a/en/manual-guides/Redis/u_e-redis/index.html b/en/manual-guides/Redis/u_e-redis/index.html index d91c74ee2..2747c54f6 100644 --- a/en/manual-guides/Redis/u_e-redis/index.html +++ b/en/manual-guides/Redis/u_e-redis/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2477,28 +2477,28 @@

            Redis is used as a key-value store for rspamd's and (some of) mailcow's settings and data. If you are unfamiliar with redis please read the introduction to redis and maybe visit this wonderful guide on how to use it.

            Client

            To connect to the redis cli execute:

            -
            docker-compose exec redis-mailcow redis-cli
            -
            +
            docker-compose exec redis-mailcow redis-cli
            +

            Debugging

            Here are some useful commands for the redis-cli for debugging:

            MONITOR

            Listens for all requests received by the server in real time:

            -
            # docker-compose exec redis-mailcow redis-cli
            +
            # docker-compose exec redis-mailcow redis-cli
             127.0.0.1:6379> monitor
             OK
             1494077286.401963 [0 172.22.1.253:41228] "SMEMBERS" "BAYES_SPAM_keys"
             1494077288.292970 [0 172.22.1.253:41229] "SMEMBERS" "BAYES_SPAM_keys"
             [...]
            -
            +
            KEYS

            Get all keys matching your pattern:

            -
            KEYS *
            -
            +
            KEYS *
            +
            PING

            Test a connection:

            -
            127.0.0.1:6379> PING
            +
            127.0.0.1:6379> PING
             PONG
            -
            +

            If you want to know more, here is a cheat sheet.


            diff --git a/en/manual-guides/Rspamd/u_e-rspamd/index.html b/en/manual-guides/Rspamd/u_e-rspamd/index.html index 4d7f44e91..6ba85c637 100644 --- a/en/manual-guides/Rspamd/u_e-rspamd/index.html +++ b/en/manual-guides/Rspamd/u_e-rspamd/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2556,68 +2556,68 @@ This is achieved by using the Sieve plugin "sieve_imapsieve" and parser scripts.

            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

            You can use a one-liner to learn mail in plain-text (uncompressed) format:

            -
            # Ham
            -for file in /my/folder/cur/*; do docker exec -i $(docker-compose ps -q rspamd-mailcow) rspamc learn_ham < $file; done
            +
            # Ham
            +for file in /my/folder/cur/*; do docker exec -i $(docker-compose ps -q rspamd-mailcow) rspamc learn_ham < $file; done
             # Spam
            -for file in /my/folder/.Junk/cur/*; do docker exec -i $(docker-compose ps -q rspamd-mailcow) rspamc learn_spam < $file; done
            -
            +for file in /my/folder/.Junk/cur/*; do docker exec -i $(docker-compose ps -q rspamd-mailcow) rspamc learn_spam < $file; done +

            Consider attaching a local folder as new volume to rspamd-mailcow in docker-compose.yml and learn given files inside the container. This can be used as workaround to parse compressed data with zcat. Example:

            -
            for file in /data/old_mail/.Junk/cur/*; do rspamc learn_spam < zcat $file; done
            -
            +
            for file in /data/old_mail/.Junk/cur/*; do rspamc learn_spam < zcat $file; done
            +

            Reset learned data (Bayes, Neural)

            You need to delete keys in Redis to reset learned data, so create a copy of your Redis database now:

            Backup database

            -
            # It is better to stop Redis before you copy the file.
            +
            # It is better to stop Redis before you copy the file.
             cp /var/lib/docker/volumes/mailcowdockerized_redis-vol-1/_data/dump.rdb /root/
            -
            +

            Reset Bayes data

            -
            docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern BAYES_* | xargs redis-cli del'
            +
            docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern BAYES_* | xargs redis-cli del'
             docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern RS* | xargs redis-cli del'
            -
            +

            Reset Neural data

            -
            docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern rn_* | xargs redis-cli del'
            -
            +
            docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern rn_* | xargs redis-cli del'
            +

            Reset Fuzzy data

            -
            # We need to enter the redis-cli first:
            +
            # We need to enter the redis-cli first:
             docker-compose exec redis-mailcow redis-cli
             # In redis-cli:
             127.0.0.1:6379> EVAL "for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end" 0 fuzzy*
            -
            +

            Info

            If redis-cli complains about...

            -
            (error) ERR wrong number of arguments for 'del' command
            -
            +
            (error) ERR wrong number of arguments for 'del' command
            +

            ...the key pattern was not found and thus no data is available to delete - it is fine.

            CLI tools

            -
            docker-compose exec rspamd-mailcow rspamc --help
            +
            docker-compose exec rspamd-mailcow rspamc --help
             docker-compose exec rspamd-mailcow rspamadm --help
            -
            +

            Disable Greylisting

            Only messages with a higher score will be considered to be greylisted (soft rejected). It is bad practice to disable greylisting.

            You can disable greylisting server-wide by editing:

            {mailcow-dir}/data/conf/rspamd/local.d/greylist.conf

            Add the line:

            -
            enabled = false;
            -
            +
            enabled = false;
            +

            Save the file and restart "rspamd-mailcow": docker-compose restart rspamd-mailcow

            Spam filter thresholds (global)

            Each user is able to change their spam rating individually. To define a new server-wide limit, edit data/conf/rspamd/local.d/actions.conf:

            -
            reject = 15;
            -add_header = 8;
            -greylist = 7;
            -
            +
            reject = 15;
            +add_header = 8;
            +greylist = 7;
            +

            Save the file and restart "rspamd-mailcow": docker-compose restart rspamd-mailcow

            Existing settings of users will not be overwritten!

            To reset custom defined thresholds, run:

            -
            source mailcow.conf
            +
            source mailcow.conf
             docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e "delete from filterconf where option = 'highspamlevel' or option = 'lowspamlevel';"
             # or:
             # docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e "delete from filterconf where option = 'highspamlevel' or option = 'lowspamlevel' and object = 'only-this-mailbox@example.org';"
            -
            +

            Custom reject messages

            The default spam reject message can be changed by adding a new file data/conf/rspamd/override.d/worker-proxy.custom.inc with the following content:

            -
            reject_message = "My custom reject message";
            -
            +
            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, prefilter reject actions will ignore this setting. For these maps, the multimap module in Rspamd needs to be adjusted:

              @@ -2628,7 +2628,7 @@ docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e "del

              Add your custom message as new line:

            -
            GLOBAL_RCPT_BL {
            +
            GLOBAL_RCPT_BL {
               type = "rcpt";
               map = "${LOCAL_CONFDIR}/custom/global_rcpt_blacklist.map";
               regexp = true;
            @@ -2636,40 +2636,40 @@ docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e "del
               action = "reject";
               message = "Sending mail to this recipient is prohibited by postmaster@your.domain";
             }
            -
            +
            1. Save the file and restart Rspamd: docker-compose restart rspamd-mailcow.

            Discard instead of reject

            If you want to silently drop a message, create or edit the file data/conf/rspamd/override.d/worker-proxy.custom.inc and add the following content:

            -
            discard_on_reject = true;
            -
            +
            discard_on_reject = true;
            +

            Restart Rspamd:

            -
            docker-compose restart rspamd-mailcow
            -
            +
            docker-compose restart rspamd-mailcow
            +

            Wipe all ratelimit keys

            If you don't want to use the UI and instead wipe all keys in the Redis database, you can use redis-cli for that task:

            -
            docker-compose exec redis-mailcow sh
            +
            docker-compose exec redis-mailcow sh
             # Unlink (available in Redis >=4.) will delete in the backgronud
             redis-cli --scan --pattern RL* | xargs redis-cli unlink
            -
            +

            Restart Rspamd:

            -
            docker-compose exec redis-mailcow sh
            -
            +
            docker-compose exec redis-mailcow sh
            +

            Trigger a resend of quarantine notifications

            Should be used for debugging only!

            -
            docker-compose exec dovecot-mailcow bash
            +
            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
            -
            +
            nrows = 1000; # change this value
            +

            Restart Rspamd afterwards: docker-compose restart rspamd-mailcow


            diff --git a/en/manual-guides/SOGo/u_e-sogo/index.html b/en/manual-guides/SOGo/u_e-sogo/index.html index a1fa9de0e..5f85cb267 100644 --- a/en/manual-guides/SOGo/u_e-sogo/index.html +++ b/en/manual-guides/SOGo/u_e-sogo/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2491,24 +2491,24 @@ After you modified data/conf/sogo/custom-theme.js and made changes
          • open browser developer console, usually shortcut is F12
          • only if you use Firefox: write by hands in dev console allow pasting and press enter
          • paste java script snipet in dev console: -
            copy([].slice.call(document.styleSheets)
            +
            copy([].slice.call(document.styleSheets)
               .map(e => e.ownerNode)
               .filter(e => e.hasAttribute('md-theme-style'))
               .map(e => e.textContent)
               .join('\n')
             )
            -
          • +
          • open text editor and paste data from clipboard (Ctrl+V), you should get minified CSS, save it
          • copy CSS file to mailcow server data/conf/sogo/custom-theme.css
          • edit data/conf/sogo/sogo.conf and set SOGoUIxDebugEnabled = NO;
          • append/create docker-compose.override.yml with: -
            version: '2.1'
            +
            version: '2.1'
             
             services:
               sogo-mailcow:
                 volumes:
                   - ./data/conf/sogo/custom-theme.css:/usr/lib/GNUstep/SOGo/WebServerResources/css/theme-default.css:z
            -
          • +
          • run docker-compose up -d
          • run docker-compose restart memcached-mailcow
          • @@ -2516,7 +2516,7 @@ services:
            1. 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
            2. find in data/conf/sogo/custom-theme.js: -
              // Apply new palettes to the default theme, remap some of the hues
              +
              // 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
              @@ -2531,13 +2531,13 @@ services:
                       'hue-3': 'A700'
                     })
                     .backgroundPalette('frost-grey');
              -
              +
              and replace it with: -
                  $mdThemingProvider.theme('default');
              -
            3. +
                  $mdThemingProvider.theme('default');
              +
            4. remove from docker-compose.override.yml volume mount in sogo-mailcow: -
              - ./data/conf/sogo/custom-theme.css:/usr/lib/GNUstep/SOGo/WebServerResources/css/theme-default.css:z
              -
            5. +
              - ./data/conf/sogo/custom-theme.css:/usr/lib/GNUstep/SOGo/WebServerResources/css/theme-default.css:z
              +
            6. run docker-compose up -d
            7. run docker-compose restart memcached-mailcow
            @@ -2553,16 +2553,16 @@ After you replaced said file you need to restart SOGo and Memcached containers b

            Domains are usually isolated from eachother.

            You can change that by modifying data/conf/sogo/sogo.conf:

            Search... -

               // SOGoDomainsVisibility = (
            +
               // SOGoDomainsVisibility = (
                 //  (domain1.tld, domain5.tld),
                 //  (domain3.tld, domain2.tld)
                 // );
            -
            +
            ...and replace it by - for example:

            -
                SOGoDomainsVisibility = (
            +
                SOGoDomainsVisibility = (
                   (example.org, example.com, example.net)
                 );
            -
            +

            Restart SOGo: docker-compose restart sogo-mailcow

            Disable password changing

            Edit data/conf/sogo/sogo.conf and change SOGoPasswordChangeEnabled to NO. Please do not add a new parameter.

            diff --git a/en/manual-guides/Unbound/u_e-unbound-fwd/index.html b/en/manual-guides/Unbound/u_e-unbound-fwd/index.html index b7a216e49..7bca36dd5 100644 --- a/en/manual-guides/Unbound/u_e-unbound-fwd/index.html +++ b/en/manual-guides/Unbound/u_e-unbound-fwd/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2416,18 +2416,18 @@ Important: Only DNSSEC validating DNS services will work.

            Method A, Unbound

            Edit data/conf/unbound/unbound.conf and append the following parameters:

            -
            forward-zone:
            +
            forward-zone:
               name: "."
               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:

            -
            docker-compose restart unbound-mailcow
            -
            +
            docker-compose restart unbound-mailcow
            +

            Method B, Override file

            -
            cd /opt/mailcow-dockerized
            +
            cd /opt/mailcow-dockerized
             cp helper-scripts/docker-compose.override.yml.d/EXTERNAL_DNS/docker-compose.override.yml .
            -
            +

            Edit docker-compose.override.yml and adjust the IP.

            Run docker-compose down ; docker-compose up -d.

            diff --git a/en/manual-guides/Watchdog/u_e-watchdog-thresholds/index.html b/en/manual-guides/Watchdog/u_e-watchdog-thresholds/index.html index 42b44f3dd..b6aeff15e 100644 --- a/en/manual-guides/Watchdog/u_e-watchdog-thresholds/index.html +++ b/en/manual-guides/Watchdog/u_e-watchdog-thresholds/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2649,7 +2649,7 @@

            Watchdog uses default values for all thresholds defined in docker-compose.yml.

            The default values will work for most setups. Example: -

            - NGINX_THRESHOLD=${NGINX_THRESHOLD:-5}
            +
            - NGINX_THRESHOLD=${NGINX_THRESHOLD:-5}
             - UNBOUND_THRESHOLD=${UNBOUND_THRESHOLD:-5}
             - REDIS_THRESHOLD=${REDIS_THRESHOLD:-5}
             - MYSQL_THRESHOLD=${MYSQL_THRESHOLD:-5}
            @@ -2667,7 +2667,7 @@ Example:
             - OLEFY_THRESHOLD=${OLEFY_THRESHOLD:-5}
             - MAILQ_THRESHOLD=${MAILQ_THRESHOLD:-20}
             - MAILQ_CRIT=${MAILQ_CRIT:-30}
            -

            +

            To adjust them just add necessary threshold variables (e.g. MAILQ_THRESHOLD=10) to mailcow.conf and run docker-compose up -d.

            Thresholds descriptions

            NGINX_THRESHOLD

            diff --git a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-bl_wl/index.html b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-bl_wl/index.html index 7cf312626..ab3c640e1 100644 --- a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-bl_wl/index.html +++ b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-bl_wl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-config/index.html b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-config/index.html index 278971d70..69d2bc566 100644 --- a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-config/index.html +++ b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-config/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-css/index.html b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-css/index.html index dfd2bf84d..0e15ff677 100644 --- a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-css/index.html +++ b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-css/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-fido/index.html b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-fido/index.html index 4f1ccfd16..c01b0a812 100644 --- a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-fido/index.html +++ b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-fido/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-pushover/index.html b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-pushover/index.html index 26a63654c..d1647cfce 100644 --- a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-pushover/index.html +++ b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-pushover/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-spamalias/index.html b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-spamalias/index.html index 23374af4e..65a2a359b 100644 --- a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-spamalias/index.html +++ b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-spamalias/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-spamfilter/index.html b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-spamfilter/index.html index b22968ddd..5ff28a355 100644 --- a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-spamfilter/index.html +++ b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-spamfilter/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-tagging/index.html b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-tagging/index.html index 93fe47c8b..806cb05d5 100644 --- a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-tagging/index.html +++ b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-tagging/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2403,7 +2403,7 @@

            1. Move this message to a sub folder "facebook" (will be created lower case if not existing)

            2. Prepend the tag to the subject: "[facebook] Subject"

            Please note: Uppercase tags are converted to lowercase except for the first letter. If you want to keep the tag as it is, please apply the following diff and restart mailcow: -

            diff --git a/data/conf/dovecot/global_sieve_after b/data/conf/dovecot/global_sieve_after
            +
            diff --git a/data/conf/dovecot/global_sieve_after b/data/conf/dovecot/global_sieve_after
             index e047136e..933c4137 100644
             --- a/data/conf/dovecot/global_sieve_after
             +++ b/data/conf/dovecot/global_sieve_after
            @@ -2416,7 +2416,7 @@ index e047136e..933c4137 100644
                if mailboxexists "INBOX/${1}" {
                  fileinto "INBOX/${1}";
                } else {
            -

            +


            diff --git a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-tfa/index.html b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-tfa/index.html index e1406bc38..ca0d687ad 100644 --- a/en/manual-guides/mailcow-UI/u_e-mailcow_ui-tfa/index.html +++ b/en/manual-guides/mailcow-UI/u_e-mailcow_ui-tfa/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/manual-guides/u_e-80_to_443/index.html b/en/manual-guides/u_e-80_to_443/index.html index d23f0f973..33a00f6c7 100644 --- a/en/manual-guides/u_e-80_to_443/index.html +++ b/en/manual-guides/u_e-80_to_443/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,7 +2349,7 @@

            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= - if not already set.

            Create a new file data/conf/nginx/redirect.conf and add the following server config to the file:

            -
            server {
            +
            server {
               root /web;
               listen 80 default_server;
               listen [::]:80 default_server;
            @@ -2363,13 +2363,13 @@
                 return 301 https://$host$uri$is_args$args;
               }
             }
            -
            +

            In case you changed the HTTP_BIND parameter, recreate the container:

            -
            docker-compose up -d
            -
            +
            docker-compose up -d
            +

            Otherwise restart Nginx:

            -
            docker-compose restart nginx-mailcow
            -
            +
            docker-compose restart nginx-mailcow
            +

            diff --git a/en/manual-guides/u_e-autodiscover_config/index.html b/en/manual-guides/u_e-autodiscover_config/index.html index 3f9f1d721..842247929 100644 --- a/en/manual-guides/u_e-autodiscover_config/index.html +++ b/en/manual-guides/u_e-autodiscover_config/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2350,7 +2350,7 @@ Keep in mind, that ActiveSync should NOT be used with a desktop client.

            Open/create data/web/inc/vars.local.inc.php and add your changes to the configuration array.

            Changes will be merged with "$autodiscover_config" in data/web/inc/vars.inc.php):

            -
            <?php
            +
            <?php
             $autodiscover_config = array(
               // General autodiscover service type: "activesync" or "imap"
               // emClient uses autodiscover, but does not support ActiveSync. mailcow excludes emClient from ActiveSync.
            @@ -2388,7 +2388,7 @@ $autodiscover_config = array(
                 'port' => $https_port,
               ),
             );
            -
            +

            To always use IMAP and SMTP instead of EAS, set 'autodiscoverType' => 'imap'.

            Disable ActiveSync for Outlook desktop clients by setting "useEASforOutlook" to "no".

            diff --git a/en/manual-guides/u_e-reeanble-weak-protocols/index.html b/en/manual-guides/u_e-reeanble-weak-protocols/index.html index dfe130d99..64ac8cb9d 100644 --- a/en/manual-guides/u_e-reeanble-weak-protocols/index.html +++ b/en/manual-guides/u_e-reeanble-weak-protocols/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,15 +2349,15 @@

            Unauthenticated mail via SMTP on port 25/tcp does still accept >= TLS 1.0 . It is better to accept a weak encryption than none at all.

            How to re-enable weak protocols?

            Edit data/conf/postfix/extra.cf:

            -
            submission_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
            +
            submission_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
             smtps_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
            -
            +

            Edit data/conf/dovecot/extra.conf:

            -
            ssl_min_protocol = TLSv1
            -
            +
            ssl_min_protocol = TLSv1
            +

            Restart the affected services:

            -
            docker-compose restart postfix-mailcow dovecot-mailcow
            -
            +
            docker-compose restart postfix-mailcow dovecot-mailcow
            +

            Hint: You can enable TLS 1.2 in Windows 7.


            diff --git a/en/manual-guides/u_e-update-hooks/index.html b/en/manual-guides/u_e-update-hooks/index.html index afd515d8e..360fafee4 100644 --- a/en/manual-guides/u_e-update-hooks/index.html +++ b/en/manual-guides/u_e-update-hooks/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/manual-guides/u_e-why_unbound/index.html b/en/manual-guides/u_e-why_unbound/index.html index d6a46457b..820b96dc5 100644 --- a/en/manual-guides/u_e-why_unbound/index.html +++ b/en/manual-guides/u_e-why_unbound/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/models/model-acl/index.html b/en/models/model-acl/index.html index 69c1c99db..f2cb7e0ab 100644 --- a/en/models/model-acl/index.html +++ b/en/models/model-acl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/models/model-passwd/index.html b/en/models/model-passwd/index.html index 0dd6b0aa1..c4b3d40ea 100644 --- a/en/models/model-passwd/index.html +++ b/en/models/model-passwd/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/models/model-sender_rcv/index.html b/en/models/model-sender_rcv/index.html index b4d5bfbdf..7dd0b244e 100644 --- a/en/models/model-sender_rcv/index.html +++ b/en/models/model-sender_rcv/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/post_installation/firststeps-disable_ipv6/index.html b/en/post_installation/firststeps-disable_ipv6/index.html index 84c4a947d..0878c47ee 100644 --- a/en/post_installation/firststeps-disable_ipv6/index.html +++ b/en/post_installation/firststeps-disable_ipv6/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2353,49 +2353,49 @@ and implement your changes to the service there. Unfortunately, this right now o

            To disable IPv6 on the mailcow network, open docker-compose.yml with your favourite text editor and search for the network section (it's near the bottom of the file).

            1. Modify docker-compose.yml

            Change enable_ipv6: true to enable_ipv6: false:

            -
            networks:
            +
            networks:
               mailcow-network:
                 [...]
                 enable_ipv6: true # <<< set to false
                 [...]
            -
            +

            2. Disable ipv6nat-mailcow

            To disable the ipv6nat-mailcow container as well, go to your mailcow directory and create a new file called "docker-compose.override.yml":

            NOTE: If you already have an override file, of course don't recreate it, but merge the lines below into your existing one accordingly!

            -
            # cd /opt/mailcow-dockerized
            +
            # cd /opt/mailcow-dockerized
             # touch docker-compose.override.yml
            -
            +

            Open the file in your favourite text editor and fill in the following:

            -
            version: '2.1'
            +
            version: '2.1'
             services:
             
                 ipv6nat-mailcow:
                   image: bash:latest
                   restart: "no"
                   entrypoint: ["echo", "ipv6nat disabled in compose.override.yml"]
            -
            +

            For these changes to be effective, you need to fully stop and then restart the stack, so containers and networks are recreated:

            -
            docker-compose down
            +
            docker-compose down
             docker-compose up -d
            -
            +

            3. Disable IPv6 in unbound-mailcow

            Edit data/conf/unbound/unbound.conf and set do-ip6 to "no":

            -
            server:
            +
            server:
               [...]
               do-ip6: no
               [...]
            -
            +

            Restart Unbound:

            -
            docker-compose restart unbound-mailcow
            -
            +
            docker-compose restart unbound-mailcow
            +

            4. Disable IPv6 in postfix-mailcow

            Create data/conf/postfix/extra.cf and set smtp_address_preference to ipv4:

            -
            smtp_address_preference = ipv4
            +
            smtp_address_preference = ipv4
             inet_protocols = ipv4
            -
            +

            Restart Postfix:

            -
            docker-compose restart postfix-mailcow
            -
            +
            docker-compose restart postfix-mailcow
            +

            diff --git a/en/post_installation/firststeps-dmarc_reporting/index.html b/en/post_installation/firststeps-dmarc_reporting/index.html index 2965bfa27..d7f5f2657 100644 --- a/en/post_installation/firststeps-dmarc_reporting/index.html +++ b/en/post_installation/firststeps-dmarc_reporting/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2473,7 +2473,7 @@

            Enable DMARC reporting

            Create the file data/conf/rspamd/local.d/dmarc.conf and set the following content:

            -
            reporting {
            +
            reporting {
                 enabled = true;
                 email = 'noreply-dmarc@example.com';
                 domain = 'example.com';
            @@ -2486,9 +2486,9 @@
                 max_entries = 2k;
                 keys_expire = 2d;
             }
            -
            +

            Create or modify docker-compose.override.yml in the mailcow-dockerized base directory:

            -
            version: '2.1'
            +
            version: '2.1'
             
             services:
               rspamd-mailcow:
            @@ -2501,16 +2501,16 @@ services:
               ofelia-mailcow:
                 depends_on:
                   - rspamd-mailcow
            -
            +

            Run docker-compose up -d

            Send a copy reports to yourself

            To receive a hidden copy of reports generated by Rspamd you can set a bcc_addrs list in the reporting config section of data/conf/rspamd/local.d/dmarc.conf:

            -
            reporting {
            +
            reporting {
                 enabled = true;
                 email = 'noreply-dmarc@example.com';
                 bcc_addrs = ["noreply-dmarc@example.com","parsedmarc@example.com"];
             [...]
            -
            +

            Rspamd will load changes in real time, so you won't need to restart the container at this point.

            This can be useful if you...

              @@ -2519,18 +2519,18 @@ services:

            Troubleshooting

            Check when the report schedule last ran:

            -
            docker-compose exec rspamd-mailcow date -r /var/lib/rspamd/dmarc_reports_last_log
            -
            +
            docker-compose exec rspamd-mailcow date -r /var/lib/rspamd/dmarc_reports_last_log
            +

            See the latest report output:

            -
            docker-compose exec rspamd-mailcow cat /var/lib/rspamd/dmarc_reports_last_log
            -
            +
            docker-compose exec rspamd-mailcow cat /var/lib/rspamd/dmarc_reports_last_log
            +

            Manually trigger a DMARC report:

            -
            docker-compose exec rspamd-mailcow rspamadm dmarc_report
            -
            +
            docker-compose exec rspamd-mailcow rspamadm dmarc_report
            +

            Validate that Rspamd has recorded data in Redis:

            -
            docker-compose exec redis-mailcow redis-cli KEYS 'dmarc;*'
            +
            docker-compose exec redis-mailcow redis-cli KEYS 'dmarc;*'
             docker-compose exec redis-mailcow redis-cli HGETALL "dmarc;example.com;20211231"
            -
            +

            Change DMARC reporting frequency

            In the example above reports are sent once every 24 hours.

            Olefia schedule has same implementation as cron in Go, supported syntax described at cron Documentation

            diff --git a/en/post_installation/firststeps-ip_bindings/index.html b/en/post_installation/firststeps-ip_bindings/index.html index 8d97ece46..aa0ddc0c0 100644 --- a/en/post_installation/firststeps-ip_bindings/index.html +++ b/en/post_installation/firststeps-ip_bindings/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2414,7 +2414,7 @@

            IPv4 binding

            To adjust one or multiple IPv4 bindings, open mailcow.conf and edit one, multiple or all variables as per your needs:

            -
            # For technical reasons, http bindings are a bit different from other service bindings.
            +
            # 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
             
            @@ -2439,14 +2439,14 @@ SIEVE_PORT=4190
             DOVEADM_PORT=127.0.0.1:19991
             SQL_PORT=127.0.0.1:13306
             SOLR_PORT=127.0.0.1:18983
            -
            +

            To apply your changes, run docker-compose down followed by docker-compose up -d.

            IPv6 binding

            Changing IPv6 bindings is different from IPv4. Again, this has a technical background.

            A docker-compose.override.yml file will be used instead of editing the docker-compose.yml file directly. This is to maintain updatability, as the docker-compose.yml file gets updated regularly and your changes will most likely be overwritten.

            Edit to create a file docker-compose.override.yml with the following content. Its content will be merged with the productive docker-compose.yml file.

            An imaginary IPv6 2a00:dead:beef::abc is given. The first suffix :PORT1 defines the external port, while the second suffix :PORT2 routes to the corresponding port inside the container and must not be changed.

            -
            version: '2.1'
            +
            version: '2.1'
             services:
             
                 dovecot-mailcow:
            @@ -2467,7 +2467,7 @@ services:
                   ports:
                     - '2a00:dead:beef::abc:80:80'
                     - '2a00:dead:beef::abc:443:443'
            -
            +

            To apply your changes, run docker-compose down followed by docker-compose up -d.


            diff --git a/en/post_installation/firststeps-local_mta/index.html b/en/post_installation/firststeps-local_mta/index.html index 39bd7e66f..05b07bca0 100644 --- a/en/post_installation/firststeps-local_mta/index.html +++ b/en/post_installation/firststeps-local_mta/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2347,15 +2347,15 @@

            The easiest option would be to disable the listener on port 25/tcp.

            Postfix users disable the listener by commenting the following line (starting with smtp or 25) in /etc/postfix/master.cf: -

            #smtp      inet  n       -       -       -       -       smtpd
            -

            +
            #smtp      inet  n       -       -       -       -       smtpd
            +

            Furthermore, to relay over a dockerized mailcow, you may want to add 172.22.1.1 as relayhost and remove the Docker interface from "inet_interfaces":

            -
            postconf -e 'relayhost = 172.22.1.1'
            +
            postconf -e 'relayhost = 172.22.1.1'
             postconf -e "mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128"
             postconf -e "inet_interfaces = loopback-only"
             postconf -e "relay_transport = relay"
             postconf -e "default_transport = smtp"
            -
            +

            Now it is important to not have the same FQDN in myhostname as you use for your dockerized mailcow. Check your local (non-Docker) Postfix' main.cf for myhostname and set it to something different, for example local.my.fqdn.tld.

            "172.22.1.1" is the mailcow created network gateway in Docker. Relaying over this interface is necessary (instead of - for example - relaying directly over ${MAILCOW_HOSTNAME}) to relay over a known internal network.

            diff --git a/en/post_installation/firststeps-logging/index.html b/en/post_installation/firststeps-logging/index.html index f99e402ee..86dec2589 100644 --- a/en/post_installation/firststeps-logging/index.html +++ b/en/post_installation/firststeps-logging/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2466,16 +2466,16 @@ the ability to read logs from the UI or ban suspicious clients with netfilter-ma

            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:

            -
            version: '2.1'
            +
            version: '2.1'
             services:
               postfix-mailcow: # or any other
                 logging:
                   driver: "gelf"
                   options:
                     gelf-address: "udp://graylog:12201"
            -
            +

            Another example for Syslog:

            -
            version: '2.1'
            +
            version: '2.1'
             services:
             
               postfix-mailcow: # or any other
            @@ -2506,10 +2506,10 @@ 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:

            -
            {
            +
            {
             ...
               "log-driver": "gelf",
               "log-opts": {
            @@ -2517,9 +2517,9 @@ local3.*        /var/log/mailcow.logs
               }
             ...
             }
            -
            +

            For Syslog:

            -
            {
            +
            {
             ...
               "log-driver": "syslog",
               "log-opts": {
            @@ -2527,7 +2527,7 @@ local3.*        /var/log/mailcow.logs
               }
             ...
             }
            -
            +

            Restart the Docker daemon and run docker-compose down && docker-compose up -d to recreate the containers with the new logging driver.


            diff --git a/en/post_installation/firststeps-rp/index.html b/en/post_installation/firststeps-rp/index.html index 18f18f722..e4f7eecb4 100644 --- a/en/post_installation/firststeps-rp/index.html +++ b/en/post_installation/firststeps-rp/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2467,11 +2467,11 @@

            You don't need to change the Nginx site that comes with mailcow: dockerized. mailcow: dockerized trusts the default gateway IP 172.22.1.1 as proxy.

            1. Make sure you change HTTP_BIND and HTTPS_BIND in mailcow.conf to a local address and set the ports accordingly, for example: -

            HTTP_BIND=127.0.0.1
            +
            HTTP_BIND=127.0.0.1
             HTTP_PORT=8080
             HTTPS_BIND=127.0.0.1
             HTTPS_PORT=8443
            -

            +

            This will also change the bindings inside the Nginx container! This is important, if you decide to use a proxy within Docker.

            IMPORTANT: Do not use port 8081, 9081 or 65510!

            Recreate affected containers by running docker-compose up -d.

            @@ -2500,56 +2500,56 @@ On many servers logrotate will reload the webserver daily anyway.

            2. Configure your local webserver as reverse proxy:

            Apache 2.4

            Required modules: -

            a2enmod rewrite proxy proxy_http headers ssl
            -

            +
            a2enmod rewrite proxy proxy_http headers ssl
            +

            Let's Encrypt will follow our rewrite, certificate requests in mailcow will work fine.

            Take care of highlighted lines.

            -
            <VirtualHost *:80>
            -  ServerName CHANGE_TO_MAILCOW_HOSTNAME
            -  ServerAlias autodiscover.*
            -  ServerAlias autoconfig.*
            -  RewriteEngine on
            +
            <VirtualHost *:80>
            +  ServerName CHANGE_TO_MAILCOW_HOSTNAME
            +  ServerAlias autodiscover.*
            +  ServerAlias autoconfig.*
            +  RewriteEngine on
             
            -  RewriteCond %{HTTPS} off
            -  RewriteRule ^/?(.*) https://%{HTTP_HOST}/$1 [R=301,L]
            +  RewriteCond %{HTTPS} off
            +  RewriteRule ^/?(.*) https://%{HTTP_HOST}/$1 [R=301,L]
             
            -  ProxyPass / http://127.0.0.1:8080/
            -  ProxyPassReverse / http://127.0.0.1:8080/
            -  ProxyPreserveHost On
            -  ProxyAddHeaders On
            -  RequestHeader set X-Forwarded-Proto "http"
            -</VirtualHost>
            -<VirtualHost *:443>
            -  ServerName CHANGE_TO_MAILCOW_HOSTNAME
            -  ServerAlias autodiscover.*
            -  ServerAlias autoconfig.*
            +  ProxyPass / http://127.0.0.1:8080/
            +  ProxyPassReverse / http://127.0.0.1:8080/
            +  ProxyPreserveHost On
            +  ProxyAddHeaders On
            +  RequestHeader set X-Forwarded-Proto "http"
            +</VirtualHost>
            +<VirtualHost *:443>
            +  ServerName CHANGE_TO_MAILCOW_HOSTNAME
            +  ServerAlias autodiscover.*
            +  ServerAlias autoconfig.*
             
            -  # You should proxy to a plain HTTP session to offload SSL processing
            -  ProxyPass /Microsoft-Server-ActiveSync http://127.0.0.1:8080/Microsoft-Server-ActiveSync connectiontimeout=4000
            -  ProxyPassReverse /Microsoft-Server-ActiveSync http://127.0.0.1:8080/Microsoft-Server-ActiveSync
            -  ProxyPass / http://127.0.0.1:8080/
            -  ProxyPassReverse / http://127.0.0.1:8080/
            -  ProxyPreserveHost On
            -  ProxyAddHeaders On
            -  RequestHeader set X-Forwarded-Proto "https"
            +  # You should proxy to a plain HTTP session to offload SSL processing
            +  ProxyPass /Microsoft-Server-ActiveSync http://127.0.0.1:8080/Microsoft-Server-ActiveSync connectiontimeout=4000
            +  ProxyPassReverse /Microsoft-Server-ActiveSync http://127.0.0.1:8080/Microsoft-Server-ActiveSync
            +  ProxyPass / http://127.0.0.1:8080/
            +  ProxyPassReverse / http://127.0.0.1:8080/
            +  ProxyPreserveHost On
            +  ProxyAddHeaders On
            +  RequestHeader set X-Forwarded-Proto "https"
             
            -  SSLCertificateFile MAILCOW_PATH/data/assets/ssl/cert.pem
            -  SSLCertificateKeyFile MAILCOW_PATH/data/assets/ssl/key.pem
            +  SSLCertificateFile MAILCOW_PATH/data/assets/ssl/cert.pem
            +  SSLCertificateKeyFile MAILCOW_PATH/data/assets/ssl/key.pem
             
            -  # If you plan to proxy to a HTTPS host:
            -  #SSLProxyEngine On
            +  # If you plan to proxy to a HTTPS host:
            +  #SSLProxyEngine On
             
            -  # If you plan to proxy to an untrusted HTTPS host:
            -  #SSLProxyVerify none
            -  #SSLProxyCheckPeerCN off
            -  #SSLProxyCheckPeerName off
            -  #SSLProxyCheckPeerExpire off
            -</VirtualHost>
            -
            + # If you plan to proxy to an untrusted HTTPS host: + #SSLProxyVerify none + #SSLProxyCheckPeerCN off + #SSLProxyCheckPeerName off + #SSLProxyCheckPeerExpire off +</VirtualHost> +

            Nginx

            Let's Encrypt will follow our rewrite, certificate requests will work fine.

            Take care of highlighted lines.

            -
            server {
            +
            server {
               listen 80 default_server;
               listen [::]:80 default_server;
               server_name CHANGE_TO_MAILCOW_HOSTNAME autodiscover.* autoconfig.*;
            @@ -2600,14 +2600,14 @@ server {
                 proxy_busy_buffers_size 512k;
               }
             }
            -
            +

            HAProxy (community supported)

            Warning

            This is an unsupported community contribution. Feel free to provide fixes.

            Important/Fixme: This example only forwards HTTPS traffic and does not use mailcows built-in ACME client.

            -
            frontend https-in
            +
            frontend https-in
               bind :::443 v4v6 ssl crt mailcow.pem
               default_backend mailcow
             
            @@ -2616,7 +2616,7 @@ backend mailcow
               http-request set-header X-Forwarded-Proto https if { ssl_fc }
               http-request set-header X-Forwarded-Proto http if !{ ssl_fc }
               server mailcow 127.0.0.1:8080 check
            -
            +

            Traefik v2 (community supported)

            Warning

            @@ -2627,50 +2627,50 @@ backend mailcow

            So, first of all, we are going to disable the acme-mailcow container since we'll use the certs that traefik will provide us. For this we'll have to set SKIP_LETS_ENCRYPT=y on our mailcow.conf, and run docker-compose up -d to apply the changes.

            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.

            -
            version: '2.1'
            +
            version: '2.1'
             
            -services:
            -    nginx-mailcow:
            -      networks:
            -        # add Traefik's network
            -        web:
            -      labels:
            -        - traefik.enable=true
            -        # Creates a router called "moo" for the container, and sets up a rule to link the container to certain rule,
            -        #   in this case, a Host rule with our MAILCOW_HOSTNAME var.
            -        - traefik.http.routers.moo.rule=Host(`${MAILCOW_HOSTNAME}`)
            -        # Enables tls over the router we created before.
            -        - traefik.http.routers.moo.tls=true
            -        # Specifies which kind of cert resolver we'll use, in this case le (Lets Encrypt).
            -        - 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=${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=websecure
            -        # Make sure traefik uses the web network, not the mailcowdockerized_mailcow-network
            -        - traefik.docker.network=web
            +services:
            +    nginx-mailcow:
            +      networks:
            +        # add Traefik's network
            +        web:
            +      labels:
            +        - traefik.enable=true
            +        # Creates a router called "moo" for the container, and sets up a rule to link the container to certain rule,
            +        #   in this case, a Host rule with our MAILCOW_HOSTNAME var.
            +        - traefik.http.routers.moo.rule=Host(`${MAILCOW_HOSTNAME}`)
            +        # Enables tls over the router we created before.
            +        - traefik.http.routers.moo.tls=true
            +        # Specifies which kind of cert resolver we'll use, in this case le (Lets Encrypt).
            +        - 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=${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=websecure
            +        # Make sure traefik uses the web network, not the mailcowdockerized_mailcow-network
            +        - traefik.docker.network=web
             
            -    certdumper:
            -        image: humenius/traefik-certs-dumper
            -        container_name: traefik_certdumper
            -        network_mode: none
            -        volumes:
            -          # mount the folder which contains Traefik's `acme.json' file
            -          #   in this case Traefik is started from its own docker-compose in ../traefik
            -          - ../traefik/data:/traefik:ro
            -          # mount mailcow's SSL folder
            -          - ./data/assets/ssl/:/output:rw
            -        restart: always
            -        environment:
            -          # only change this, if you're using another domain for mailcow's web frontend compared to the standard config
            -          - DOMAIN=${MAILCOW_HOSTNAME}
            +    certdumper:
            +        image: humenius/traefik-certs-dumper
            +        container_name: traefik_certdumper
            +        network_mode: none
            +        volumes:
            +          # mount the folder which contains Traefik's `acme.json' file
            +          #   in this case Traefik is started from its own docker-compose in ../traefik
            +          - ../traefik/data:/traefik:ro
            +          # mount mailcow's SSL folder
            +          - ./data/assets/ssl/:/output:rw
            +        restart: always
            +        environment:
            +          # only change this, if you're using another domain for mailcow's web frontend compared to the standard config
            +          - DOMAIN=${MAILCOW_HOSTNAME}
             
            -networks:
            -  web:
            -    external: true
            -
            +networks: + web: + external: true +

            Start the new containers with docker-compose up -d.

            Now, there's only one thing left to do, which is setup the certs so that the mail services can use them as well, since Traefik 2 uses an acme v2 format to save ALL the license from all the domains we have, we'll need to find a way to dump the certs, lucky we have this tiny container which grabs the acme.json file trough a volume, and a variable DOMAIN=example.org, and with these, the container will output the cert.pem and key.pem files, for this we'll simply run the traefik-certs-dumper container binding the /traefik volume to the folder where our acme.json is saved, bind the /output volume to our mailcow data/assets/ssl/ folder, and set up the DOMAIN=example.org variable to the domain we want the certs dumped from.

            This container will watch over the acme.json file for any changes, and regenerate the cert.pem and key.pem files directly into data/assets/ssl/ being the path binded to the container's /output path.

            @@ -2680,18 +2680,18 @@ For this we'll have to set SKIP_LETS_ENCRYPT=y on our mailcow

            Optional: Post-hook script for non-mailcow ACME clients

            Using a local certbot (or any other ACME client) requires to restart some containers, you can do this with a post-hook script. Make sure you change the paths accordingly: -

            #!/bin/bash
            +
            #!/bin/bash
             cp /etc/letsencrypt/live/my.domain.tld/fullchain.pem /opt/mailcow-dockerized/data/assets/ssl/cert.pem
             cp /etc/letsencrypt/live/my.domain.tld/privkey.pem /opt/mailcow-dockerized/data/assets/ssl/key.pem
             postfix_c=$(docker ps -qaf name=postfix-mailcow)
             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
            -
            +
            ADDITIONAL_SERVER_NAMES=webmail.domain.tld,other.example.tld
            +

            Run docker-compose up -d to apply.


            diff --git a/en/post_installation/firststeps-rspamd_ui/index.html b/en/post_installation/firststeps-rspamd_ui/index.html index 782b8d486..6c6a54bbe 100644 --- a/en/post_installation/firststeps-rspamd_ui/index.html +++ b/en/post_installation/firststeps-rspamd_ui/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/post_installation/firststeps-snat/index.html b/en/post_installation/firststeps-snat/index.html index e4dbc4f2a..f477dea31 100644 --- a/en/post_installation/firststeps-snat/index.html +++ b/en/post_installation/firststeps-snat/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,12 +2348,12 @@

            SNAT is used to change the source address of the packets sent by mailcow. 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:

            -
            # Use this IPv4 for outgoing connections (SNAT)
            +
            # Use this IPv4 for outgoing connections (SNAT)
             SNAT_TO_SOURCE=1.2.3.4
             
             # Use this IPv6 for outgoing connections (SNAT)
             SNAT6_TO_SOURCE=dead:beef
            -
            +

            Run docker-compose up -d.

            The values are read by netfilter-mailcow. netfilter-mailcow will make sure, the post-routing rules are on position 1 in the netfilter table. It does automatically delete and re-create them if they are found on another position than 1.

            Check the output of docker-compose logs --tail=200 netfilter-mailcow to ensure the SNAT settings have been applied.

            diff --git a/en/post_installation/firststeps-ssl/index.html b/en/post_installation/firststeps-ssl/index.html index 8d57d572d..b8d6294f7 100644 --- a/en/post_installation/firststeps-ssl/index.html +++ b/en/post_installation/firststeps-ssl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2586,8 +2586,8 @@

            Additional domain names

            Edit "mailcow.conf" and add a parameter ADDITIONAL_SAN like this:

            Do not use quotes (") and do not use spaces between the names!

            -
            ADDITIONAL_SAN=smtp.*,cert1.example.com,cert2.example.org,whatever.*
            -
            +
            ADDITIONAL_SAN=smtp.*,cert1.example.com,cert2.example.org,whatever.*
            +

            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.

            @@ -2596,17 +2596,17 @@

            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
            -
            +
            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:

            -
            cd /opt/mailcow-dockerized
            +
            cd /opt/mailcow-dockerized
             touch data/assets/ssl/force_renew
             docker-compose restart acme-mailcow
             # Now check the logs for a renewal
             docker-compose logs --tail=200 -f acme-mailcow
            -
            +

            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 address. Due to using dynamic IPs for acme-mailcow, source NAT is not consistent over restarts.

            @@ -2653,35 +2653,35 @@ You should make sure these clients use the MAILCOW_HOSTNAME for sec

            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:

            -
            docker restart $(docker ps -qaf name=postfix-mailcow)
            +
            docker restart $(docker ps -qaf name=postfix-mailcow)
             docker restart $(docker ps -qaf name=nginx-mailcow)
             docker restart $(docker ps -qaf name=dovecot-mailcow)
            -
            +

            See Post-hook script for non-mailcow ACME clients for a full example script.

            Test against staging ACME directory

            Edit mailcow.conf and add LE_STAGING=y.

            Run docker-compose up -d to activate your changes.

            Custom directory URL

            Edit mailcow.conf and add the corresponding directory URL to the new variable DIRECTORY_URL:

            -
            DIRECTORY_URL=https://acme-custom-v9000.api.letsencrypt.org/directory
            -
            +
            DIRECTORY_URL=https://acme-custom-v9000.api.letsencrypt.org/directory
            +

            You cannot use LE_STAGING with DIRECTORY_URL. If both are set, only LE_STAGING is used.

            Run docker-compose up -d to activate your changes.

            Check your configuration

            Run docker-compose logs acme-mailcow to find out why a validation fails.

            To check if nginx serves the correct certificate, simply use a browser of your choice and check the displayed certificate.

            To check the certificate served by Postfix, Dovecot and Nginx we will use openssl:

            -
            # Connect via SMTP (587)
            +
            # Connect via SMTP (587)
             echo "Q" | openssl s_client -starttls smtp -crlf -connect mx.mailcow.email:587
             # Connect via IMAP (143)
             echo "Q" | openssl s_client -starttls imap -showcerts -connect mx.mailcow.email:143
             # Connect via HTTPS (443)
             echo "Q" | openssl s_client -connect mx.mailcow.email:443
            -
            +

            To validate the expiry dates as returned by openssl against MAILCOW_HOSTNAME, you are able to use our helper script:

            -
            cd /opt/mailcow-dockerized
            +
            cd /opt/mailcow-dockerized
             bash helper-scripts/expiry-dates.sh
            -
            +

            diff --git a/en/post_installation/firststeps-sync_jobs_migration/index.html b/en/post_installation/firststeps-sync_jobs_migration/index.html index 06fca30f9..065a8a562 100644 --- a/en/post_installation/firststeps-sync_jobs_migration/index.html +++ b/en/post_installation/firststeps-sync_jobs_migration/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/prerequisite/prerequisite-dns/index.html b/en/prerequisite/prerequisite-dns/index.html index c54d54a53..5cd408c5f 100644 --- a/en/prerequisite/prerequisite-dns/index.html +++ b/en/prerequisite/prerequisite-dns/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2548,28 +2548,28 @@

            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

            This example shows you a set of records for one domain managed by mailcow. Each domain that is added to mailcow needs at least this set of records to function correctly.

            -
            # Name              Type       Value
            +
            # Name              Type       Value
             mail                IN A       1.2.3.4
             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

            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 for further reading.

            -
            # Name              Type       Value
            +
            # 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 for further reading.

            -
            # Name              Type       Value
            +
            # 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 (check).

            -
            # Name              Type       Value
            +
            # Name              Type       Value
             _dmarc              IN TXT     "v=DMARC1; p=reject; rua=mailto:mailauth-reports@example.org"
            -
            +

            The advanced DNS configuration

            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.

            -
            # Name              Type       Priority Weight Port    Value
            +
            # 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/"
            @@ -2582,7 +2582,7 @@ _pop3s._tcp         IN SRV     0        1      995      mail.example.org. (your
             _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

            Here are some tools you can use to verify your DNS configuration:

              @@ -2613,7 +2613,7 @@ _submission._tcp IN SRV 0 1 587 mail.example.org. (your

              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:

              -
              ==========================================================
              +
              ==========================================================
               Summary of Results
               ==========================================================
               SPF check:          pass
              @@ -2626,7 +2626,7 @@ SpamAssassin check: ham
               Details:
               ==========================================================
               ....
              -
              +

              The full report will contain more technical details.

              Fully Qualified Domain Name (FQDN)

              diff --git a/en/prerequisite/prerequisite-system/index.html b/en/prerequisite/prerequisite-system/index.html index e159e2efb..b03597f6b 100644 --- a/en/prerequisite/prerequisite-system/index.html +++ b/en/prerequisite/prerequisite-system/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2569,10 +2569,10 @@

              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'
               # or:
               netstat -tulpn | grep -E -w '25|80|110|143|443|465|587|993|995|4190'
              -
              +

              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.donnex.net) or this (unrouted.io) guide for information about how to use iptables-persistent with the DOCKER-USER chain. @@ -2665,34 +2665,34 @@ As mailcow runs dockerized, INPUT rules have no effect on restricting access to

              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:       ---
              +
              SRC-IP:       ---
               DST IP:       ---
               SRC Port:    ---
               DST Port:    1024-65535
               Protocol:    tcp
               TCP flags:   ack
               Action:      Accept
              -

              +

              For UDP -

              SRC-IP:       ---
              +
              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
              -

              +
              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:

              -
              $ timedatectl status
              +
              $ timedatectl status
                     Local time: Sat 2017-05-06 02:12:33 CEST
                 Universal time: Sat 2017-05-06 00:12:33 UTC
                       RTC time: Sat 2017-05-06 00:12:32
              @@ -2707,22 +2707,22 @@ NTP synchronized: yes
                Next DST change: DST ends (the clock jumps one hour backwards) at
                                 Sun 2017-10-29 02:59:59 CEST
                                 Sun 2017-10-29 02:00:00 CET
              -
              +

              The lines NTP enabled: yes and NTP synchronized: yes indicate whether you have NTP enabled and if it's synchronized.

              To enable NTP you need to run the command timedatectl set-ntp true. You also need to edit your /etc/systemd/timesyncd.conf:

              -
              # vim /etc/systemd/timesyncd.conf
              +
              # vim /etc/systemd/timesyncd.conf
               [Time]
               NTP=0.pool.ntp.org 1.pool.ntp.org 2.pool.ntp.org 3.pool.ntp.org
              -
              +

              Hetzner Cloud (and probably others)

              Check /etc/network/interfaces.d/50-cloud-init.cfg and change the IPv6 interface from eth0:0 to eth0:

              -
              # Wrong:
              +
              # Wrong:
               auto eth0:0
               iface eth0:0 inet6 static
               # Right:
               auto eth0
               iface eth0 inet6 static
              -
              +

              Reboot or restart the interface. You may want to disable cloud-init network changes.

              MTU

              diff --git a/en/third_party/third_party-borgmatic/index.html b/en/third_party/third_party-borgmatic/index.html index e5eff1b40..da0add0ca 100644 --- a/en/third_party/third_party-borgmatic/index.html +++ b/en/third_party/third_party-borgmatic/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2687,43 +2687,43 @@ This guide only covers the basics.

              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:

              -
              version: '2.1'
              +
              version: '2.1'
               
              -services:
              -  borgmatic-mailcow:
              -    image: b3vis/borgmatic
              -    hostname: mailcow
              -    restart: always
              -    dns: ${IPV4_NETWORK:-172.22.1}.254
              -    volumes:
              -      - vmail-vol-1:/mnt/source/vmail:ro
              -      - crypt-vol-1:/mnt/source/crypt:ro
              -      - redis-vol-1:/mnt/source/redis:ro,z
              -      - rspamd-vol-1:/mnt/source/rspamd:ro,z
              -      - postfix-vol-1:/mnt/source/postfix:ro,z
              -      - mysql-socket-vol-1:/var/run/mysqld/:z
              -      - borg-config-vol-1:/root/.config/borg:Z
              -      - borg-cache-vol-1:/root/.cache/borg:Z
              -      - ./data/conf/borgmatic/etc:/etc/borgmatic.d:Z
              -      - ./data/conf/borgmatic/ssh:/root/.ssh:Z
              -    environment:
              -      - TZ=${TZ}
              -      - BORG_PASSPHRASE=YouBetterPutSomethingRealGoodHere
              -    networks:
              -      mailcow-network:
              -        aliases:
              -          - borgmatic
              +services:
              +  borgmatic-mailcow:
              +    image: b3vis/borgmatic
              +    hostname: mailcow
              +    restart: always
              +    dns: ${IPV4_NETWORK:-172.22.1}.254
              +    volumes:
              +      - vmail-vol-1:/mnt/source/vmail:ro
              +      - crypt-vol-1:/mnt/source/crypt:ro
              +      - redis-vol-1:/mnt/source/redis:ro,z
              +      - rspamd-vol-1:/mnt/source/rspamd:ro,z
              +      - postfix-vol-1:/mnt/source/postfix:ro,z
              +      - mysql-socket-vol-1:/var/run/mysqld/:z
              +      - borg-config-vol-1:/root/.config/borg:Z
              +      - borg-cache-vol-1:/root/.cache/borg:Z
              +      - ./data/conf/borgmatic/etc:/etc/borgmatic.d:Z
              +      - ./data/conf/borgmatic/ssh:/root/.ssh:Z
              +    environment:
              +      - TZ=${TZ}
              +      - BORG_PASSPHRASE=YouBetterPutSomethingRealGoodHere
              +    networks:
              +      mailcow-network:
              +        aliases:
              +          - borgmatic
               
              -volumes:
              -  borg-cache-vol-1:
              -  borg-config-vol-1:
              -
              +volumes: + borg-cache-vol-1: + borg-config-vol-1: +

              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.

              -
              source mailcow.conf
              +
              source mailcow.conf
               cat <<EOF > data/conf/borgmatic/etc/config.yaml
               location:
                   source_directories:
              @@ -2749,7 +2749,7 @@ cat <<EOF > data/conf/borgmatic/etc/config.yaml
                         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 @@ -2765,8 +2765,8 @@ container. The container defines a volume called /mnt/borg-repository

              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
              -
              +
              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

              @@ -2775,14 +2775,14 @@ usual id_rsa, id_ed25519 or similar to be in this dire 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:

              -
              docker-compose up -d
              -
              +
              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:

              -
              docker-compose exec borgmatic-mailcow borgmatic init --encryption repokey-blake2
              -
              +
              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.

              @@ -2793,8 +2793,8 @@ 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:

              -
              docker-compose restart borgmatic-mailcow
              -
              +
              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.

              @@ -2814,8 +2814,8 @@ 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:

              -
              docker-compose exec borgmatic-mailcow borgmatic extract --path mnt/source --archive latest
              -
              +
              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)

              Restore MySQL

              @@ -2825,30 +2825,30 @@ Then you can use the following command to restore the maildir from a backup:

              intend to recover the mailcow database from a backup.

              To restore the MySQL database from the latest archive use this command:

              -
              docker-compose exec borgmatic-mailcow borgmatic restore --archive latest
              -
              +
              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)

              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:

              -
              docker-compose down && docker-compose up -d
              -
              +
              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)

              -
              docker-compose exec borgmatic-mailcow borgmatic -v 2
              -
              +
              docker-compose exec borgmatic-mailcow borgmatic -v 2
              +

              Listing all available archives

              -
              docker-compose exec borgmatic-mailcow borgmatic list
              -
              +
              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:

              -
              docker-compose exec borgmatic-mailcow borg break-lock user@rsync.net:mailcow
              -
              +
              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

              @@ -2857,8 +2857,8 @@ key files are generated when you initialize the repository. The repokey

              Note that in either case you also must have the passphrase to decrypt any archives.

              To fetch the keyfile run:

              -
              docker-compose exec borgmatic-mailcow borg key export --paper user@rsync.net:mailcow
              -
              +
              docker-compose exec borgmatic-mailcow borg key export --paper user@rsync.net:mailcow
              +

              Where user@rsync.net:mailcow is the URI to your repository.


              diff --git a/en/third_party/third_party-exchange_onprem/index.html b/en/third_party/third_party-exchange_onprem/index.html index fe74ecd5b..581f07dfa 100644 --- a/en/third_party/third_party-exchange_onprem/index.html +++ b/en/third_party/third_party-exchange_onprem/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/third_party/third_party-gitea/index.html b/en/third_party/third_party-gitea/index.html index d6e78d802..d9021788d 100644 --- a/en/third_party/third_party-gitea/index.html +++ b/en/third_party/third_party-gitea/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2347,7 +2347,7 @@

              With Gitea' ability to authenticate over SMTP it is trivial to integrate it with mailcow. Few changes are needed:

              1. Open docker-compose.override.yml and add gitea:

              -
              version: '2.1'
              +
              version: '2.1'
               services:
               
                       gitea-mailcow:
              @@ -2360,28 +2360,28 @@ services:
                                       - gitea
                           ports:
                               - "${GITEA_SSH_PORT:-127.0.0.1:4000}:22"
              -
              +

              2. Create data/conf/nginx/site.gitea.custom, add: -

              location /gitea/ {
              +
              location /gitea/ {
                       proxy_pass http://gitea:3000/;
               }
              -

              +

              3. Open mailcow.conf and define the binding you want gitea to use for SSH. Example:

              -
              GITEA_SSH_PORT=127.0.0.1:4000
              -
              +
              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. 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. 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. 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 for their meaning and other possible values.

              -
              [server]
              +
              [server]
               SSH_LISTEN_PORT = 22
               # For GITEA_SSH_PORT=127.0.0.1:4000 in mailcow.conf, set:
               SSH_DOMAIN = 127.0.0.1
               SSH_PORT = 4000
               # For MAILCOW_HOSTNAME=mx.example.org in mailcow.conf (and default ports for HTTPS), set:
               ROOT_URL = https://mx.example.org/gitea/
              -
              +

              10. Restart gitea with docker-compose restart gitea-mailcow. Your users should be able to login with mailcow managed accounts.


              diff --git a/en/third_party/third_party-gogs/index.html b/en/third_party/third_party-gogs/index.html index ec12e3a40..146ebecfc 100644 --- a/en/third_party/third_party-gogs/index.html +++ b/en/third_party/third_party-gogs/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2347,7 +2347,7 @@

              With Gogs' ability to authenticate over SMTP it is trivial to integrate it with mailcow. Few changes are needed:

              1. Open docker-compose.override.yml and add Gogs:

              -
              version: '2.1'
              +
              version: '2.1'
               services:
               
                   gogs-mailcow:
              @@ -2360,27 +2360,27 @@ services:
                           - gogs
                     ports:
                       - "${GOGS_SSH_PORT:-127.0.0.1:4000}:22"
              -
              +

              2. Create data/conf/nginx/site.gogs.custom, add: -

              location /gogs/ {
              +
              location /gogs/ {
                   proxy_pass http://gogs:3000/;
               }
              -

              +

              3. Open mailcow.conf and define the binding you want Gogs to use for SSH. Example:

              -
              GOGS_SSH_PORT=127.0.0.1:4000
              -
              +
              GOGS_SSH_PORT=127.0.0.1:4000
              +

              5. Run docker-compose up -d to bring up the Gogs container and run docker-compose restart nginx-mailcow afterwards.

              6. Open http://${MAILCOW_HOSTNAME}/gogs/, for example http://mx.example.org/gogs/. 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.

              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).

              8. Create data/gogs/gogs/conf/app.ini and set following values. You can consult Gogs cheat sheet for their meaning and other possible values.

              -
              [server]
              +
              [server]
               SSH_LISTEN_PORT = 22
               # For GOGS_SSH_PORT=127.0.0.1:4000 in mailcow.conf, set:
               SSH_DOMAIN = 127.0.0.1
               SSH_PORT = 4000
               # For MAILCOW_HOSTNAME=mx.example.org in mailcow.conf (and default ports for HTTPS), set:
               ROOT_URL = https://mx.example.org/gogs/
              -
              +

              9. Restart Gogs with docker-compose restart gogs-mailcow. Your users should be able to login with mailcow managed accounts.


              diff --git a/en/third_party/third_party-mailman3/index.html b/en/third_party/third_party-mailman3/index.html index b9c10765f..e8a396cc6 100644 --- a/en/third_party/third_party-mailman3/index.html +++ b/en/third_party/third_party-mailman3/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2780,15 +2780,15 @@

              DNS setup

              Most of the configuration is covered by mailcows DNS setup. After finishing this setup add another subdomain for Mailman, e.g. lists.example.org that points to the same server:

              -
              # Name    Type       Value
              +
              # Name    Type       Value
               lists     IN A       1.2.3.4
               lists     IN AAAA    dead:beef
              -
              +

              Install Apache as a reverse proxy

              Install Apache, e.g. with this guide from Digital Ocean: How To Install the Apache Web Server on Ubuntu 20.04.

              Activate certain Apache modules (as root or sudo):

              -
              a2enmod rewrite proxy proxy_http headers ssl wsgi proxy_uwsgi http2
              -
              +
              a2enmod rewrite proxy proxy_http headers ssl wsgi proxy_uwsgi http2
              +

              Maybe you have to install further packages to get these modules. This PPA by Ondřej Surý may help you.

              vHost configuration

              Copy the mailcow.conf and the mailman.conf in the Apache conf folder sites-available (e.g. under /etc/apache2/sites-available).

              @@ -2806,18 +2806,18 @@ lists IN AAAA dead:beef
            • https://mxtoolbox.com/SuperTool.aspx?action=aaaa%3aMAILMAN_DOMAIN

            Install certbot (as root or sudo):

            -
            apt install certbot
            -
            +
            apt install certbot
            +

            Get the desired certificates (as root or sudo):

            -
            certbot certonly -d mailcow_HOSTNAME
            +
            certbot certonly -d mailcow_HOSTNAME
             certbot certonly -d MAILMAN_DOMAIN
            -
            +

            Install mailcow with Mailman integration

            Install mailcow

            Follow the mailcow installation. Omit step 5 and do not pull and up with docker-compose!

            Configure mailcow

            This is also Step 4 in the official mailcow installation (nano mailcow.conf). So change to your needs and alter the following variables:

            -
            HTTP_PORT=18080            # don't use 8080 as mailman needs it
            +
            HTTP_PORT=18080            # don't use 8080 as mailman needs it
             HTTP_BIND=127.0.0.1        #
             HTTPS_PORT=18443           # you may use 8443
             HTTPS_BIND=127.0.0.1       #
            @@ -2826,10 +2826,10 @@ SKIP_LETS_ENCRYPT=y        # reverse proxy will do the SSL termination
             
             SNAT_TO_SOURCE=1.2.3.4     # change this to your IPv4
             SNAT6_TO_SOURCE=dead:beef  # change this to your global IPv6
            -
            +

            Add Mailman integration

            Create the file /opt/mailcow-dockerized/docker-compose.override.yml (e.g. with nano) and add the following lines:

            -

            version: '2.1'
            +

            version: '2.1'
             
             services:
               postfix-mailcow:
            @@ -2841,10 +2841,10 @@ services:
             networks:
               docker-mailman_mailman:
                 external: true
            -
            +
            The additional volume is used by Mailman to generate additional config files for mailcow postfix. The external network is build and used by Mailman. mailcow needs it to deliver incoming list mails to Mailman.

            Create the file /opt/mailcow-dockerized/data/conf/postfix/extra.cf (e.g. with nano) and add the following lines:

            -

            # mailman
            +

            # mailman
             
             recipient_delimiter = +
             unknown_local_recipient_reject_code = 550
            @@ -2869,7 +2869,7 @@ relay_domains =
             relay_recipient_maps =
               proxy:mysql:/opt/postfix/conf/sql/mysql_relay_recipient_maps.cf,
               regexp:/opt/mailman/core/var/data/postfix_lmtp
            -
            +
            As we overwrite mailcow postfix configuration here, this step may break your normal mail transports. Check the original configuration files if anything changed.

            SSL certificates

            As we proxying mailcow, we need to copy the SSL certificates into the mailcow file structure. This task will do the script renew-ssl.sh for us:

            @@ -2880,26 +2880,26 @@ As we overwrite mailcow postfix configuration here, this step may break
          • Do not run it yet, as we first need Mailman

          You have to create a cronjob, so that new certificates will be copied. Execute as root or sudo:

          -
          crontab -e
          -
          +
          crontab -e
          +

          To run the script every day at 5am, add:

          -
          0   5  *   *   *     /opt/mailcow-dockerized/renew-ssl.sh
          -
          +
          0   5  *   *   *     /opt/mailcow-dockerized/renew-ssl.sh
          +

          Install Mailman

          Basicly follow the instructions at docker-mailman. As they are a lot, here is in a nuthshell what to do:

          As root or sudo:

          -
          cd /opt
          +
          cd /opt
           mkdir -p mailman/core
           mkdir -p mailman/web
           git clone https://github.com/maxking/docker-mailman
           cd docker-mailman
          -
          +

          Configure Mailman

          Create a long key for Hyperkitty, e.g. with the linux command cat /dev/urandom | tr -dc a-zA-Z0-9 | head -c30; echo. Save this key for a moment as HYPERKITTY_KEY.

          Create a long password for the database, e.g. with the linux command cat /dev/urandom | tr -dc a-zA-Z0-9 | head -c30; echo. Save this password for a moment as DBPASS.

          Create a long key for Django, e.g. with the linux command cat /dev/urandom | tr -dc a-zA-Z0-9 | head -c30; echo. Save this key for a moment as DJANGO_KEY.

          Create the file /opt/docker-mailman/docker-compose.override.yaml and replace HYPERKITTY_KEY, DBPASS and DJANGO_KEY with the generated values:

          -
          version: '2'
          +
          version: '2'
           
           services:
             mailman-core:
          @@ -2928,17 +2928,17 @@ services:
               environment:
               - POSTGRES_PASSWORD=DBPASS
               restart: always
          -
          +

          At mailman-web fill in correct values for SERVE_FROM_DOMAIN (e.g. lists.example.org), MAILMAN_ADMIN_USER and MAILMAN_ADMIN_EMAIL. You need the admin credentials to log into the web interface (Pistorius). For setting the password for the first time use the Forgot password function in the web interface.

          About other configuration options read Mailman-web and Mailman-core documentation.

          Configure Mailman core and Mailman web

          Create the file /opt/mailman/core/mailman-extra.cfg with the following content. mailman@example.org should be pointing to a valid mail box or redirection.

          -
          [mailman]
          +
          [mailman]
           default_language: de
           site_owner: mailman@example.org
          -
          +

          Create the file /opt/mailman/web/settings_local.py with the following content. mailman@example.org should be pointing to a valid mail box or redirection.

          -

          # locale
          +

          # locale
           LANGUAGE_CODE = 'de-de'
           
           # disable social authentication
          @@ -2948,11 +2948,11 @@ SOCIALACCOUNT_PROVIDERS = {}
           DEFAULT_FROM_EMAIL = 'mailman@example.org'
           
           DEBUG = False
          -
          +
          You can change LANGUAGE_CODE and SOCIALACCOUNT_PROVIDERS to your needs. At the moment SOCIALACCOUNT_PROVIDERS has no effect, see issue #2.

          🏃 Run

          Run (as root or sudo)

          -
          a2ensite mailcow.conf
          +
          a2ensite mailcow.conf
           a2ensite mailman.conf
           systemctl restart apache2
           
          @@ -2963,14 +2963,14 @@ docker-compose up -d
           cd /opt/mailcow-dockerized/
           docker-compose pull
           ./renew-ssl.sh
          -
          +

          Wait a few minutes! The containers have to create there databases and config files. This can last up to 1 minute and more.

          Remarks

          New lists aren't recognized by postfix instantly

          When you create a new list and try to immediately send an e-mail, postfix responses with User doesn't exist, because postfix won't deliver it to Mailman yet. The configuration at /opt/mailman/core/var/data/postfix_lmtp is not instantly updated. If you need the list instantly, restart postifx manually:

          -
          cd /opt/mailcow-dockerized
          +
          cd /opt/mailcow-dockerized
           docker-compose restart postfix-mailcow
          -
          +

          Update

          mailcow has it's own update script in /opt/mailcow-dockerized/update.sh, see the docs.

          For Mailman just fetch the newest version from the github repository.

          diff --git a/en/third_party/third_party-mailpiler_integration/index.html b/en/third_party/third_party-mailpiler_integration/index.html index 97646ea88..95c8c7ae1 100644 --- a/en/third_party/third_party-mailpiler_integration/index.html +++ b/en/third_party/third_party-mailpiler_integration/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2456,11 +2456,11 @@

          The problem to solve

          mailpiler offers the authentication based on IMAP, for example:

          -
          $config['ENABLE_IMAP_AUTH'] = 1;
          +
          $config['ENABLE_IMAP_AUTH'] = 1;
           $config['IMAP_HOST'] = 'mail.example.com';
           $config['IMAP_PORT'] =  993;
           $config['IMAP_SSL'] = true;
          -
          +
          • So when you log in using patrik@example.com, you will only see delivered emails sent from or to this specific email address.
          • When additional aliases are defined in mailcow, like team@example.com, you won't see emails sent to or from this email address even the fact you're a recipient of mails sent to this alias address.
          • @@ -2487,19 +2487,19 @@
            1. Set the custom query function of mailpiler and append this to /usr/local/etc/piler/config-site.php:

              -
              $config['MAILCOW_API_KEY'] = 'YOUR_READONLY_API_KEY';
              +
              $config['MAILCOW_API_KEY'] = 'YOUR_READONLY_API_KEY';
               $config['MAILCOW_SET_REALNAME'] = true; // when not specified, then default is false
               $config['CUSTOM_EMAIL_QUERY_FUNCTION'] = 'query_mailcow_for_email_access';
               include('auth-mailcow.php');
              -
              +

              You can also change the mailcow hostname, if required: -

              $config['MAILCOW_HOST'] = 'mail.domain.tld'; // defaults to $config['IMAP_HOST']
              -

              +
              $config['MAILCOW_HOST'] = 'mail.domain.tld'; // defaults to $config['IMAP_HOST']
              +

            2. Download the PHP file with the functions from the GitHub repo:

              -
              curl -o /usr/local/etc/piler/auth-mailcow.php https://raw.githubusercontent.com/patschi/mailpiler-mailcow-integration/master/auth-mailcow.php
              -
              +
              curl -o /usr/local/etc/piler/auth-mailcow.php https://raw.githubusercontent.com/patschi/mailpiler-mailcow-integration/master/auth-mailcow.php
              +
            3. Done!

              diff --git a/en/third_party/third_party-nextcloud/index.html b/en/third_party/third_party-nextcloud/index.html index 50abfd05c..b2416e985 100644 --- a/en/third_party/third_party-nextcloud/index.html +++ b/en/third_party/third_party-nextcloud/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2457,14 +2457,14 @@

              In order for mailcow to generate a a certificate for the nextcloud domain you need to add "nextcloud.domain.tld" to ADDITIONAL_SAN in mailcow.conf and run docker-compose up -d to apply. For more informaton refer to: Advanced SSL.

              Background jobs

              To use the recommended setting (cron) to execute the background jobs following lines need to be added to the docker-compose.override.yml:

              -
              version: '2.1'
              +
              version: '2.1'
               services:
                 php-fpm-mailcow:
                   labels:
                     ofelia.enabled: "true"
                     ofelia.job-exec.nextcloud-cron.schedule: "@every 5m"
                     ofelia.job-exec.nextcloud-cron.command: "su www-data -s /bin/bash -c \"/usr/local/bin/php -f /web/nextcloud/cron.php\""
              -
              +

              After adding these lines the docker-compose up -d command must be executed to update the docker image and also the docker scheduler image must be restarted to pick up the new job definition by executing docker-compose restart ofelia-mailcow. To check if the job was successfully picked up by ofelia the command docker-compose logs ofelia-mailcow will contain a line similar to New job registered "nextcloud-cron" - ....

              @@ -2516,14 +2516,14 @@ services:

              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_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): -

              INSERT INTO nc_sociallogin_connect (uid, identifier) SELECT DISTINCT uid, CONCAT("Mailcow-", uid) FROM nc_users;
              -

              +
              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. @@ -2533,13 +2533,13 @@ It shows which commands have to be executed, these have to be placed in the php-


              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' =>
              +
              '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/en/third_party/third_party-portainer/index.html b/en/third_party/third_party-portainer/index.html index 4193cc181..36b4b74f6 100644 --- a/en/third_party/third_party-portainer/index.html +++ b/en/third_party/third_party-portainer/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2347,7 +2347,7 @@

              In order to enable Portainer, the docker-compose.yml and site.conf for Nginx must be modified.

              1. Create a new file docker-compose.override.yml in the mailcow-dockerized root folder and insert the following configuration -

              version: '2.1'
              +
              version: '2.1'
               services:
                   portainer-mailcow:
                     image: portainer/portainer-ce
              @@ -2362,9 +2362,9 @@ services:
                       mailcow-network:
                         aliases:
                           - portainer
              -
              +
              2a. Create data/conf/nginx/portainer.conf: -
              upstream portainer {
              +
              upstream portainer {
                 server portainer-mailcow:9000;
               }
               
              @@ -2372,9 +2372,9 @@ map $http_upgrade $connection_upgrade {
                 default upgrade;
                 '' close;
               }
              -

              +

              2b. Insert a new location to the default mailcow site by creating the file data/conf/nginx/site.portainer.custom: -

                location /portainer/ {
              +
                location /portainer/ {
                   proxy_http_version 1.1;
                   proxy_set_header Host              $http_host;   # required for docker client's sake
                   proxy_set_header X-Real-IP         $remote_addr; # pass on real client's IP
              @@ -2393,10 +2393,10 @@ map $http_upgrade $connection_upgrade {
                   proxy_set_header Connection $connection_upgrade;
                   proxy_pass http://portainer/api/websocket/;
                 }
              -

              +

              3. Apply your changes: -

              docker-compose up -d && docker-compose restart nginx-mailcow
              -

              +
              docker-compose up -d && docker-compose restart nginx-mailcow
              +

              Now you can simply navigate to https://${MAILCOW_HOSTNAME}/portainer/ to view your Portainer container monitoring page. You’ll then be prompted to specify a new password for the admin account. After specifying your password, you’ll then be able to connect to the Portainer UI.


              diff --git a/en/third_party/third_party-roundcube/index.html b/en/third_party/third_party-roundcube/index.html index 8b29622ea..bc33dfb41 100644 --- a/en/third_party/third_party-roundcube/index.html +++ b/en/third_party/third_party-roundcube/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2466,7 +2466,7 @@

              Installing Roundcube

              Download Roundcube 1.5.x to the web htdocs directory and extract it (here rc/): -

              # Check for a newer release!
              +
              # Check for a newer release!
               cd data/web
               wget -O - https://github.com/roundcube/roundcubemail/releases/download/1.5.2/roundcubemail-1.5.2-complete.tar.gz | tar xfvz -
               
              @@ -2478,17 +2478,17 @@ chown -R root: rc/
               
               # Fix Allow remote resources (https://github.com/roundcube/roundcubemail/issues/8170) should not be required in 1.6
               sed -i "s/\$prefix = '\.\/';/\$prefix = preg_replace\('\/\[\?\&]\.\*\$\/', '', \$_SERVER\['REQUEST_URI'] \?\? ''\) \?: '\.\/';/g" rc/program/include/rcmail.php
              -

              +

              If you need spell check features, create a file data/hooks/phpfpm/aspell.sh with the following content, then chmod +x data/hooks/phpfpm/aspell.sh. This installs a local spell check engine. Note, most modern web browsers have built in spell check, so you may not want/need this. -

              #!/bin/bash
              +
              #!/bin/bash
               apk update
               apk add aspell-en # or any other language
              -

              +

              Create a file data/web/rc/config/config.inc.php with the following content. - Change the des_key parameter to a random value. It is used to temporarily store your IMAP password. - The db_prefix is optional but recommended. - If you didn't install spell check in the above step, remove spellcheck_engine parameter and replace it with $config['enable_spellcheck'] = false;. -

              <?php
              +
              <?php
               error_reporting(0);
               if (!file_exists('/tmp/mime.types')) {
               file_put_contents("/tmp/mime.types", fopen("http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types", 'r'));
              @@ -2520,13 +2520,13 @@ $config['smtp_conn_options'] = array(
                 'ssl' => array('verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true)
               );
               $config['db_prefix'] = 'mailcow_rc1';
              -

              +

              Point your browser to https://myserver/rc/installer and follow the instructions. Initialize the database and leave the installer.

              Delete the directory data/web/rc/installer after a successful installation!

              Configure ManageSieve filtering

              Open data/web/rc/plugins/managesieve/config.inc.php and change the following parameters (or add them at the bottom of that file): -

              $config['managesieve_port'] = 4190;
              +
              $config['managesieve_port'] = 4190;
               $config['managesieve_host'] = 'tls://dovecot';
               $config['managesieve_conn_options'] = array(
                 'ssl' => array('verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true)
              @@ -2536,37 +2536,37 @@ $config['managesieve_conn_options'] = array(
               // 1 - add Vacation section,
               // 2 - add Vacation section, but hide Filters section
               $config['managesieve_vacation'] = 1;
              -

              +

              Enable change password function in Roundcube

              Open data/web/rc/config/config.inc.php and enable the password plugin:

              -
              ...
              +
              ...
               $config['plugins'] = array(
                   'archive',
                   'password',
               );
               ...
              -
              +

              Open data/web/rc/plugins/password/password.php, search for case 'ssha': and add above:

              -
                      case 'ssha256':
              +
                      case 'ssha256':
                           $salt = rcube_utils::random_bytes(8);
                           $crypted = base64_encode( hash('sha256', $password . $salt, TRUE ) . $salt );
                           $prefix  = '{SSHA256}';
                           break;
              -
              +

              Open data/web/rc/plugins/password/config.inc.php and change the following parameters (or add them at the bottom of that file):

              -
              $config['password_driver'] = 'sql';
              +
              $config['password_driver'] = 'sql';
               $config['password_algorithm'] = 'ssha256';
               $config['password_algorithm_prefix'] = '{SSHA256}';
               $config['password_query'] = "UPDATE mailbox SET password = %P WHERE username = %u";
              -
              +

              Integrate CardDAV addressbooks in Roundcube

              Download the latest release of RCMCardDAV to the Roundcube plugin directory and extract it (here rc/plugins): -

              cd data/web/rc/plugins
              +
              cd data/web/rc/plugins
               wget -O - https://github.com/mstilkerich/rcmcarddav/releases/download/v4.3.0/carddav-v4.3.0.tar.gz  | tar xfvz -
               chown -R root: carddav/
              -

              +

              Copy the file config.inc.php.dist to config.inc.php (here in rc/plugins/carddav) and append the following preset to the end of the file - don't forget to replace mx.example.org with your own hostname: -

              $prefs['SOGo'] = array(
              +
              $prefs['SOGo'] = array(
                   'name'         =>  'SOGo',
                   'username'     =>  '%u',
                   'password'     =>  '%p',
              @@ -2579,7 +2579,7 @@ chown -R root: carddav/
                   'fixed'        =>  array( 'active', 'name', 'username', 'password', 'refresh_time' ),
                   'hide'        =>  false,
               );
              -
              +
              Please note, that this preset only integrates the default addressbook (the one that's named "Personal Address Book" and can't be deleted). Additional addressbooks are currently not automatically detected but can be manually added within the roundecube settings.

              Enable the plugin by adding carddav to $config['plugins'] in rc/config/config.inc.php.

              If you want to remove the default addressbooks (stored in the Roundcube database), so that only the CardDAV addressbooks are accessible, append $config['address_book_type'] = ''; to the config file data/web/rc/config/config.inc.php.

              @@ -2587,7 +2587,7 @@ Please note, that this preset only integrates the default addressbook (the one t

              Optionally, you can add Roundcube's link to the mailcow Apps list. To do this, open or create data/web/inc/vars.local.inc.php and add the following code-block:

              NOTE: Don't forget to add the <?php delimiter on the first line

              -
              ...
              +
              ...
               $MAILCOW_APPS = array(
                 array(
                   'name' => 'SOGo',
              @@ -2599,10 +2599,10 @@ $MAILCOW_APPS = array(
                  )
               );
               ...
              -
              +

              Upgrading Roundcube

              Upgrading Roundcube is rather simple, go to the Github releases page for Roundcube and get the link for the "complete.tar.gz" file for the wanted release. Then follow the below commands and change the URL and Roundcube folder name if needed.

              -
              # Enter a bash session of the mailcow PHP container
              +
              # Enter a bash session of the mailcow PHP container
               docker exec -it mailcowdockerized_php-fpm-mailcow_1 bash
               
               # Install required upgrade dependency, then upgrade Roundcube to wanted release
              @@ -2620,42 +2620,42 @@ rm -rf roundcube*
               
               # Fix Allow remote resources (https://github.com/roundcube/roundcubemail/issues/8170) should not be required in 1.6
               sed -i "s/\$prefix = '\.\/';/\$prefix = preg_replace\('\/\[\?\&]\.\*\$\/', '', \$_SERVER\['REQUEST_URI'] \?\? ''\) \?: '\.\/';/g" /web/rc/program/include/rcmail.php
              -
              +

              Let admins log into Roundcube without password

              First, install plugin dovecot_impersonate and add Roundcube as an app (see above).

              Edit mailcow.conf and add the following:

              -
              # Allow admins to log into Roundcube as email user (without any password)
              +
              # Allow admins to log into Roundcube as email user (without any password)
               # Roundcube with plugin dovecot_impersonate must be installed first
               
               ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE=y
              -
              +

              Edit docker-compose.override.yml and crate/extend the section for php-fpm-mailcow:

              -
              version: '2.1'
              +
              version: '2.1'
               services:
                 php-fpm-mailcow:
                   environment:
                     - ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE=${ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE:-n}
              -
              +

              Edit data/web/js/site/mailbox.js and the following code after if (ALLOW_ADMIN_EMAIL_LOGIN) { ... }

              -
              if (ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE) {
              -  item.action += '<a href="/rc-auth.php?login=' + encodeURIComponent(item.username) + '" class="login_as btn btn-xs ' + btnSize + ' btn-primary" target="_blank"><i class="bi bi-envelope-fill"></i> Roundcube</a>';
              -}
              -
              +
              if (ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE) {
              +  item.action += '<a href="/rc-auth.php?login=' + encodeURIComponent(item.username) + '" class="login_as btn btn-xs ' + btnSize + ' btn-primary" target="_blank"><i class="bi bi-envelope-fill"></i> Roundcube</a>';
              +}
              +

              Edit data/web/mailbox.php and add this line to array $template_data:

              -
                'allow_admin_email_login_roundcube' => (preg_match("/^(yes|y)+$/i", $_ENV["ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE"])) ? 'true' : 'false',
              -
              +
                'allow_admin_email_login_roundcube' => (preg_match("/^(yes|y)+$/i", $_ENV["ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE"])) ? 'true' : 'false',
              +

              Edit data/web/templates/mailbox.twig and add this code to the bottom of the javascript section:

              -
                var ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE = {{ allow_admin_email_login_roundcube }};
              -
              +
                var ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE = {{ allow_admin_email_login_roundcube }};
              +

              Copy the contents of the following files from this Snippet:

              • data/web/inc/lib/RoundcubeAutoLogin.php
              • data/web/rc-auth.php

              Finally, restart mailcow

              -
              docker-compose down
              +
              docker-compose down
               docker-compose up -d
              -
              +

              diff --git a/en/troubleshooting/debug-admin_login_sogo/index.html b/en/troubleshooting/debug-admin_login_sogo/index.html index e59fbdbb8..c3f5199dc 100644 --- a/en/troubleshooting/debug-admin_login_sogo/index.html +++ b/en/troubleshooting/debug-admin_login_sogo/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2428,11 +2428,11 @@ log into SOGo as a mailbox user, without knowing the users password.

              Multiple concurrent admin-logins to different mailboxes are also possible when using this feature.

              Enabling the feature

              The feature is disabled by default. It can be enabled in the mailcow.conf by setting: -

              ALLOW_ADMIN_EMAIL_LOGIN=y
              -
              +
              ALLOW_ADMIN_EMAIL_LOGIN=y
              +
              and recreating the affected containers with -
              docker-compose up -d
              -

              +
              docker-compose up -d
              +

              Drawbacks when enabled

              • Each SOGo page-load and each Active-Sync request will cause an additional execution of an internal PHP script. diff --git a/en/troubleshooting/debug-attach_service/index.html b/en/troubleshooting/debug-attach_service/index.html index 7b9d815f5..816617af8 100644 --- a/en/troubleshooting/debug-attach_service/index.html +++ b/en/troubleshooting/debug-attach_service/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2476,17 +2476,17 @@

                Attaching a Container to your Shell

                To attach a container to your shell you can simply run

                -
                docker-compose exec $Service_Name /bin/bash
                -
                +
                docker-compose exec $Service_Name /bin/bash
                +

                Connecting to Services

                If you want to connect to a service / application directly it is always a good idea to source mailcow.conf to get all relevant variables into your environment.

                MySQL

                -
                source mailcow.conf
                +
                source mailcow.conf
                 docker-compose exec mysql-mailcow mysql -u${DBUSER} -p${DBPASS} ${DBNAME}
                -
                +

                Redis

                -
                docker-compose exec redis-mailcow redis-cli
                -
                +
                docker-compose exec redis-mailcow redis-cli
                +

                Service Descriptions

                Here is a brief overview of what container / service does what:

          diff --git a/en/troubleshooting/debug-common_problems/index.html b/en/troubleshooting/debug-common_problems/index.html index 6afcc1f66..c38562215 100644 --- a/en/troubleshooting/debug-common_problems/index.html +++ b/en/troubleshooting/debug-common_problems/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2516,11 +2516,11 @@
        • Check if your IP address is on any blacklists. You could use 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:
        • -
          # telnet 74.125.133.27 465
          +
          # telnet 74.125.133.27 465
           Trying 74.125.133.27...
           Connected to 74.125.133.27.
           Escape character is '^]'.
          -
          +

          My mails are identified as Spam

          Please read our guide on DNS configuration.

          docker-compose throws weird errors

          @@ -2537,8 +2537,8 @@ Escape character is '^]'.

          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

          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
          -
          +
          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.

          XYZ can't connect to ...

          Please check your local firewall! @@ -2546,19 +2546,19 @@ Docker and iptables-based firewalls sometimes create conflicting rules, so disab

          If you experience connection problems from home, please check your ISP router's firewall too, some of them block mail traffic on the SMTP (587) or SMTPS (465) ports. It could also be, that your ISP is blocking the ports for SUBMISSION (25).

          While Linux users can chose from a variety of tools1 to check if a port is open, the Windows user has only the PowerShell command Test-NetConnection -ComputerName host -Port port available by default.

          To enable telnet on a Windows after Vista please check this guide or enter the following command in an terminal with administrator privileges:

          -
          dism /online /Enable-Feature /FeatureName:TelnetClient
          -
          +
          dism /online /Enable-Feature /FeatureName:TelnetClient
          +

          Inotify instance limit for user 5000 (UID vmail) exceeded (see #453)

          Docker containers use the Docker hosts inotify limits. Setting them on your Docker host will pass them to the container.

          Dovecot keeps restarting (see #2672)

          Check that you have at least the following files in data/assets/ssl:

          -
          cert.pem
          +
          cert.pem
           dhparams.pem
           key.pem
          -
          +

          If dhparams.pem is missing, you can generate it with

          -
          openssl dhparam -out data/assets/ssl/dhparams.pem 4096
          -
          +
          openssl dhparam -out data/assets/ssl/dhparams.pem 4096
          +

            diff --git a/en/troubleshooting/debug-logs/index.html b/en/troubleshooting/debug-logs/index.html index f8ac8e83b..709ed0662 100644 --- a/en/troubleshooting/debug-logs/index.html +++ b/en/troubleshooting/debug-logs/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/en/troubleshooting/debug-mysql_aria/index.html b/en/troubleshooting/debug-mysql_aria/index.html index 94ec39d03..d5af4af53 100644 --- a/en/troubleshooting/debug-mysql_aria/index.html +++ b/en/troubleshooting/debug-mysql_aria/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2398,7 +2398,7 @@

            If your server crashed and MariaDB logs an error similar to [ERROR] mysqld: Aria recovery failed. Please run aria_chk -r on all Aria tables (*.MAI) and delete all aria_log.######## files you may want to try the following to recover the database to a healthy state:

            Start the stack and wait until mysql-mailcow begins to report a restarting state. Check by running docker-compose ps.

            Now run the following commands:

            -
            # Stop the stack, don't run "down"
            +
            # Stop the stack, don't run "down"
             docker-compose stop
             # Run a bash in the stopped container as user mysql
             docker-compose run --rm --entrypoint '/bin/sh -c "gosu mysql bash"' mysql-mailcow
            @@ -2408,7 +2408,7 @@ cd /var/lib/mysql
             aria_chk --check --force */*.MAI
             # Delete aria log files
             rm aria_log.*
            -
            +

            Now run docker-compose down followed by docker-compose up -d.


            diff --git a/en/troubleshooting/debug-mysql_upgrade/index.html b/en/troubleshooting/debug-mysql_upgrade/index.html index 862f2e6d9..6c52e09bb 100644 --- a/en/troubleshooting/debug-mysql_upgrade/index.html +++ b/en/troubleshooting/debug-mysql_upgrade/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2396,13 +2396,13 @@

            Run a manual mysql_upgrade

            This step is usually not necessary.

            -
            docker-compose stop mysql-mailcow watchdog-mailcow
            +
            docker-compose stop mysql-mailcow watchdog-mailcow
             docker-compose run --rm --entrypoint '/bin/sh -c "gosu mysql mysqld --skip-grant-tables & sleep 10 && bash && exit 0"' mysql-mailcow
            -
            +

            As soon as the SQL shell spawned, run mysql_upgrade and exit the container:

            -
            mysql_upgrade
            +
            mysql_upgrade
             exit
            -
            +

            diff --git a/en/troubleshooting/debug-reset_pw/index.html b/en/troubleshooting/debug-reset_pw/index.html index 28c8bfbfe..f8f46ffb5 100644 --- a/en/troubleshooting/debug-reset_pw/index.html +++ b/en/troubleshooting/debug-reset_pw/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2544,16 +2544,16 @@

            mailcow Admin Account

            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
            +
            cd mailcow_path
             ./helper-scripts/mailcow-reset-admin.sh
            -
            +

            Reset MySQL Passwords

            Stop the stack by running docker-compose stop.

            When the containers came to a stop, run this command:

            -
            docker-compose run --rm --entrypoint '/bin/sh -c "gosu mysql mysqld --skip-grant-tables & sleep 10 && mysql -hlocalhost -uroot && exit 0"' mysql-mailcow
            -
            +
            docker-compose run --rm --entrypoint '/bin/sh -c "gosu mysql mysqld --skip-grant-tables & sleep 10 && mysql -hlocalhost -uroot && exit 0"' mysql-mailcow
            +

            1. Find database name

            -
            # source mailcow.conf
            +
            # source mailcow.conf
             # docker-compose exec mysql-mailcow mysql -u${DBUSER} -p${DBPASS} ${DBNAME}
             MariaDB [(none)]> show databases;
             +--------------------+
            @@ -2565,11 +2565,11 @@ MariaDB [(none)]> show databases;
             | performance_schema |
             +--------------------+
             4 rows in set (0.00 sec)
            -
            +

            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.

            -
            MariaDB [(none)]> SELECT user FROM mysql.user;
            +
            MariaDB [(none)]> SELECT user FROM mysql.user;
             +--------------+
             | user         |
             +--------------+
            @@ -2582,9 +2582,9 @@ MariaDB [(none)]> FLUSH PRIVILEGES;
             MariaDB [(none)]> UPDATE mysql.user SET authentication_string = PASSWORD('gotr00t'), password = PASSWORD('gotr00t') WHERE User = 'root';
             MariaDB [(none)]> UPDATE mysql.user SET authentication_string = PASSWORD('mookuh'), password = PASSWORD('mookuh') WHERE User = 'mailcow' AND Host = '%';
             MariaDB [(none)]> FLUSH PRIVILEGES;
            -
            +

            2.2 Maria DB >= 10.4 (current mailcows)

            -
            MariaDB [(none)]> SELECT user FROM mysql.user;
            +
            MariaDB [(none)]> SELECT user FROM mysql.user;
             +--------------+
             | user         |
             +--------------+
            @@ -2598,16 +2598,16 @@ MariaDB [(none)]> ALTER USER 'mailcow'@'%' IDENTIFIED BY '
             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
            +
            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}'
            -
            +
            docker-compose exec -u sogo sogo-mailcow sogo-tool user-preferences set defaults user@example.com SOGoGoogleAuthenticatorEnabled '{"SOGoGoogleAuthenticatorEnabled":0}'
            +

            diff --git a/en/troubleshooting/debug-reset_tls/index.html b/en/troubleshooting/debug-reset_tls/index.html index 0c254e14e..bdb72abfa 100644 --- a/en/troubleshooting/debug-reset_tls/index.html +++ b/en/troubleshooting/debug-reset_tls/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2346,14 +2346,14 @@

            Reset TLS certificates

            In case you encounter problems with your certificate, key or Let's Encrypt account, please try to reset the TLS assets:

            -
            source mailcow.conf
            +
            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/en/troubleshooting/debug-rm_volumes/index.html b/en/troubleshooting/debug-rm_volumes/index.html index b4426b837..6cb731740 100644 --- a/en/troubleshooting/debug-rm_volumes/index.html +++ b/en/troubleshooting/debug-rm_volumes/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,8 +2348,8 @@

            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 volume ls for a full list.

            Delete a single volume:

            -
            docker volume rm mailcowdockerized_${VOLUME_NAME}
            -
            +
            docker volume rm mailcowdockerized_${VOLUME_NAME}
            +
            • Remove volume mysql-vol-1 to remove all MySQL data.
            • Remove volume redis-vol-1 to remove all Redis data.
            • diff --git a/en/troubleshooting/debug-rspamd_memory_leaks/index.html b/en/troubleshooting/debug-rspamd_memory_leaks/index.html index 495fd7c6a..f420b6191 100644 --- a/en/troubleshooting/debug-rspamd_memory_leaks/index.html +++ b/en/troubleshooting/debug-rspamd_memory_leaks/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2346,7 +2346,7 @@

              Advanced: Find memory leaks in Rspamd

              A quick guide to deeply analyze a malfunctioning Rspamd.

              -
              docker-compose exec rspamd-mailcow bash
              +
              docker-compose exec rspamd-mailcow bash
               
               if ! grep -qi 'apt-stable-asan' /etc/apt/sources.list.d/rspamd.list; then
                 sed -i 's/apt-stable/apt-stable-asan/i' /etc/apt/sources.list.d/rspamd.list
              @@ -2360,7 +2360,7 @@ nano /docker-entrypoint.sh
               
               export G_SLICE=always-malloc
               export ASAN_OPTIONS=new_delete_type_mismatch=0:detect_leaks=1:detect_odr_violation=0:log_path=/tmp/rspamd-asan:quarantine_size_mb=2048:malloc_context_size=8:fast_unwind_on_malloc=0
              -
              +

              Restart Rspamd: docker-compose restart rspamd-mailcow

              Your memory consumption will increase by a lot, it will also steadily grow, which is not related to a possible memory leak you are looking for.

              Leave the container running for a few minutes, hours or days (it should match the time you usually wait for the leak to "happen") and restart it: docker-compose restart rspamd-mailcow.

              diff --git a/en/troubleshooting/debug/index.html b/en/troubleshooting/debug/index.html index aecbdcbee..abbc14a27 100644 --- a/en/troubleshooting/debug/index.html +++ b/en/troubleshooting/debug/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/i_u_m/i_u_m_deinstall/index.html b/i_u_m/i_u_m_deinstall/index.html index 67ab0b152..90aeeee73 100644 --- a/i_u_m/i_u_m_deinstall/index.html +++ b/i_u_m/i_u_m_deinstall/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2346,8 +2346,8 @@

              Deinstallation

              To remove mailcow: dockerized with all it's volumes, images and containers do:

              -
              docker-compose down -v --rmi all --remove-orphans
              -
              +
              docker-compose down -v --rmi all --remove-orphans
              +

              Info

                diff --git a/i_u_m/i_u_m_install/index.html b/i_u_m/i_u_m_install/index.html index 73c97c438..cc2bdc167 100644 --- a/i_u_m/i_u_m_install/index.html +++ b/i_u_m/i_u_m_install/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2351,10 +2351,10 @@
                • Docker -

                  curl -sSL https://get.docker.com/ | CHANNEL=stable sh
                  +
                  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 --now docker
                  -

                  +

                • Docker-Compose

                  @@ -2365,44 +2365,44 @@ systemctl enable --now docker

                  mailcow requires the latest version of docker-compose v1. 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 correct 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
              +
              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
              -
              +

              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
              -
              +
              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
              -
              +
              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 bootstrapping 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.

              -
              $ su
              +
              $ su
               # umask
               0022 # <- Verify it is 0022
               # cd /opt
               # git clone https://github.com/mailcow/mailcow-dockerized
               # cd mailcow-dockerized
              -
              +

              3. Generate a configuration file. Use a FQDN (host.domain.tld) as hostname when asked. -

              ./generate_config.sh
              -

              +
              ./generate_config.sh
              +

              4. Change configuration if you want or need to. -

              nano mailcow.conf
              -
              +
              nano mailcow.conf
              +
              If you plan to use a reverse proxy, you can, for example, bind HTTPS to 127.0.0.1 on port 8443 and HTTP to 127.0.0.1 on port 8080.

              You may need to stop an existing pre-installed MTA which blocks port 25/tcp. See this chapter to learn how to reconfigure Postfix to run besides mailcow after a successful installation.

              Some updates modify mailcow.conf and add new parameters. It is hard to keep track of them in the documentation. Please check their description and, if unsure, ask at the known channels for advise.

              @@ -2410,20 +2410,20 @@ If you plan to use a reverse proxy, you can, for example, bind HTTPS to 127.0.0.

              Whenever you run into trouble and strange phenomena, please check your MTU.

              Edit docker-compose.yml and change the network settings according to your MTU. Add the new driver_opts parameter like this: -

              networks:
              +
              networks:
                 mailcow-network:
                   ...
                   driver_opts:
                     com.docker.network.driver.mtu: 1450
                   ...
              -

              +

              4.2. Users without an IPv6 enabled network on their host system:

              Enable IPv6. Finally.

              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 for the mailcow network to prevent unforeseen issues.

              5. Pull the images and run the compose file. The parameter -d will start mailcow: dockerized detached: -

              docker-compose pull
              +
              docker-compose pull
               docker-compose up -d
              -

              +

              Done!

              You can now access https://${MAILCOW_HOSTNAME} with the default credentials admin + password moohoo.

              diff --git a/i_u_m/i_u_m_migration/index.html b/i_u_m/i_u_m_migration/index.html index 047b4300f..614e6cecb 100644 --- a/i_u_m/i_u_m_migration/index.html +++ b/i_u_m/i_u_m_migration/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2359,43 +2359,43 @@ Install Docker
              • Docker -

                curl -sSL https://get.docker.com/ | CHANNEL=stable sh
                +
                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
                -

                +

              • docker-compose -

                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
                +
                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
                -

                +

              Please use the latest Docker engine available and do not use the engine that ships with your distros repository.

              2. Stop Docker and assure Docker has stopped: -

              systemctl stop docker.service
              +
              systemctl stop docker.service
               systemctl status docker.service
              -

              +

              3. Run the following commands on the source machine (take care of adding the trailing slashes in the first path parameter as shown below!) - WARNING: This command will erase anything that may already exist under /var/lib/docker/volumes on the target machine: -

              rsync -aHhP --numeric-ids --delete /opt/mailcow-dockerized/ root@target-machine.example.com:/opt/mailcow-dockerized
              +
              rsync -aHhP --numeric-ids --delete /opt/mailcow-dockerized/ root@target-machine.example.com:/opt/mailcow-dockerized
               rsync -aHhP --numeric-ids --delete /var/lib/docker/volumes/ root@target-machine.example.com:/var/lib/docker/volumes
              -

              +

              4. Shut down mailcow and stop Docker on the source machine. -

              cd /opt/mailcow-dockerized
              +
              cd /opt/mailcow-dockerized
               docker-compose down
               systemctl stop docker.service
              -

              +

              5. Repeat step 3 with the same commands. This will be much quicker than the first time.

              6. Switch over to the target machine and start Docker. -

              systemctl start docker.service
              -

              +
              systemctl start docker.service
              +

              7. Now pull the mailcow Docker images on the target machine. -

              cd /opt/mailcow-dockerized
              +
              cd /opt/mailcow-dockerized
               docker-compose pull
              -

              +

              8. Start the whole mailcow stack and everything should be done! -

              docker-compose up -d
              -

              +
              docker-compose up -d
              +

              9. Finally, change your DNS settings to point to the target server.


              diff --git a/i_u_m/i_u_m_update/index.html b/i_u_m/i_u_m_update/index.html index 7216b9e85..079ca5d64 100644 --- a/i_u_m/i_u_m_update/index.html +++ b/i_u_m/i_u_m_update/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2480,13 +2480,13 @@

              An update script in your mailcow-dockerized directory will take care of updates.

              But use it with caution! If you think you made a lot of changes to the mailcow code, you should use the manual update guide below.

              Run the update script: -

              ./update.sh
              -

              +
              ./update.sh
              +

              If it needs to, it will ask you how you wish to proceed. Merge errors will be reported. Some minor conflicts will be auto-corrected (in favour for the mailcow: dockerized repository code).

              Options

              -
              # Options can be combined
              +
              # Options can be combined
               
               # - Check for updates and show changes
               ./update.sh --check
              @@ -2509,22 +2509,22 @@ Some minor conflicts will be auto-corrected (in favour for the mailcow: dockeriz
               
               # - Don't update, but prefetch images and exit
               ./update.sh --prefetch
              -
              +

              I forgot what I changed before running update.sh

              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
              +
              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
              +
              docker-compose down
               # Replace commit ID 22cd00b5e28893ef9ddef3c2b5436453cc5223ab by your ID
               git checkout 22cd00b5e28893ef9ddef3c2b5436453cc5223ab
               docker-compose pull
               docker-compose up -d
              -
              +

              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 for more details.

              Footnotes

              diff --git a/index.html b/index.html index f75d1fb41..2fbe08ebe 100644 --- a/index.html +++ b/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/manual-guides/ClamAV/u_e-clamav-additional_dbs/index.html b/manual-guides/ClamAV/u_e-clamav-additional_dbs/index.html index 2c5d3f040..070d0bf0b 100644 --- a/manual-guides/ClamAV/u_e-clamav-additional_dbs/index.html +++ b/manual-guides/ClamAV/u_e-clamav-additional_dbs/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2466,21 +2466,21 @@
            • You will need to get your_id from one of the download links, they are individual for every user
            • Add to data/conf/clamav/freshclam.conf with replaced your_id part: -

              DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfo.hdb
              +
              DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfo.hdb
               DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfo.ign2
               DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/javascript.ndb
               DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/spam_marketing.ndb
               DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfohtml.hdb
               DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfoascii.hdb
               DatabaseCustomURL https://www.securiteinfo.com/get/signatures/your_id/securiteinfopdf.hdb
              -

              +

            • For free SecuriteInfo databases, download speed is limited to 300 kB/s. In data/conf/clamav/freshclam.conf, increase the default ReceiveTimeout 20 value to ReceiveTimeout 90 (time in seconds), otherwise some of the database downloads could fail because of their size.

            • Adjust data/conf/clamav/clamd.conf to align with next settings: -

              DetectPUA yes
              +
              DetectPUA yes
               ExcludePUA PUA.Win.Packer
               ExcludePUA PUA.Win.Trojan.Packed
               ExcludePUA PUA.Win.Trojan.Molebox
              @@ -2493,11 +2493,11 @@ MaxEmbeddedPE 100M
               MaxHTMLNormalize 50M
               MaxScriptNormalize 50M
               MaxZipTypeRcg 50M
              -

              +

            • Restart ClamAV container: -
              docker-compose restart clamd-mailcow
              -
            • +
              docker-compose restart clamd-mailcow
              +

          Please note:

            @@ -2509,14 +2509,14 @@ MaxZipTypeRcg 50M

            Enable InterServer databases

            1. Add to data/conf/clamav/freshclam.conf: -
              DatabaseCustomURL http://sigs.interserver.net/interserver256.hdb
              +
              DatabaseCustomURL http://sigs.interserver.net/interserver256.hdb
               DatabaseCustomURL http://sigs.interserver.net/interservertopline.db
               DatabaseCustomURL http://sigs.interserver.net/shell.ldb
               DatabaseCustomURL http://sigs.interserver.net/whitelist.fp
              -
            2. +
        • Restart ClamAV container: -
          docker-compose restart clamd-mailcow
          -
        • +
          docker-compose restart clamd-mailcow
          +

          diff --git a/manual-guides/ClamAV/u_e-clamav-whitelist/index.html b/manual-guides/ClamAV/u_e-clamav-whitelist/index.html index 5227654a2..c7ad2cdfe 100644 --- a/manual-guides/ClamAV/u_e-clamav-whitelist/index.html +++ b/manual-guides/ClamAV/u_e-clamav-whitelist/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2398,22 +2398,22 @@

          Whitelist specific ClamAV signatures

          You may find that legitimate (clean) mail is being blocked by ClamAV (Rspamd will flag the mail with VIRUS_FOUND). For instance, interactive PDF form attachments are blocked by default because the embedded Javascript code may be used for nefarious purposes. Confirm by looking at the clamd logs, e.g.:

          -
          docker-compose logs clamd-mailcow | grep "FOUND"
          -
          +
          docker-compose logs clamd-mailcow | grep "FOUND"
          +

          This line confirms that such was identified:

          -
          clamd-mailcow_1      | Sat Sep 28 07:43:24 2019 -> instream(local): PUA.Pdf.Trojan.EmbeddedJavaScript-1(e887d2ac324ce90750768b86b63d0749:363325) FOUND
          -
          +
          clamd-mailcow_1      | Sat Sep 28 07:43:24 2019 -> instream(local): PUA.Pdf.Trojan.EmbeddedJavaScript-1(e887d2ac324ce90750768b86b63d0749:363325) FOUND
          +

          To whitelist this particular signature (and enable sending this type of file attached), add it to the ClamAV signature whitelist file:

          -
          echo 'PUA.Pdf.Trojan.EmbeddedJavaScript-1' >> data/conf/clamav/whitelist.ign2
          -
          +
          echo 'PUA.Pdf.Trojan.EmbeddedJavaScript-1' >> data/conf/clamav/whitelist.ign2
          +

          Then restart the clamd-mailcow service container in the mailcow UI or using docker-compose:

          -
          docker-compose restart clamd-mailcow
          -
          +
          docker-compose restart clamd-mailcow
          +

          Cleanup cached ClamAV results in Redis:

          -
          # docker-compose exec redis-mailcow  /bin/sh
          +
          # docker-compose exec redis-mailcow  /bin/sh
           /data # redis-cli KEYS rs_cl* | xargs redis-cli DEL
           /data # exit
          -
          +

          diff --git a/manual-guides/Docker/u_e-docker-cust_dockerfiles/index.html b/manual-guides/Docker/u_e-docker-cust_dockerfiles/index.html index 5bd19481d..489e3e897 100644 --- a/manual-guides/Docker/u_e-docker-cust_dockerfiles/index.html +++ b/manual-guides/Docker/u_e-docker-cust_dockerfiles/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,14 +2348,14 @@

          Customize Dockerfiles

          You need to copy the override file with corresponding build tags to the mailcow: dockerized root folder (i.e. /opt/mailcow-dockerized):

          -
          cp helper-scripts/docker-compose.override.yml.d/BUILD_FLAGS/docker-compose.override.yml docker-compose.override.yml
          -
          +
          cp helper-scripts/docker-compose.override.yml.d/BUILD_FLAGS/docker-compose.override.yml docker-compose.override.yml
          +

          Make your changes in data/Dockerfiles/$service and build the image locally:

          -
          docker build data/Dockerfiles/service -t mailcow/$service
          -
          +
          docker build data/Dockerfiles/service -t mailcow/$service
          +

          Now auto-recreate modified containers:

          -
          docker-compose up -d
          -
          +
          docker-compose up -d
          +

          diff --git a/manual-guides/Docker/u_e-docker-dc_bash_compl/index.html b/manual-guides/Docker/u_e-docker-dc_bash_compl/index.html index 909a8ce9e..2f1844e1d 100644 --- a/manual-guides/Docker/u_e-docker-dc_bash_compl/index.html +++ b/manual-guides/Docker/u_e-docker-dc_bash_compl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,8 +2348,8 @@

          Docker Compose Bash Completion

          To get some sexy bash completion inside your containers simply execute the following:

          -
          curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
          -
          +
          curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
          +

          diff --git a/manual-guides/Dovecot/u_e-dovecot-any_acl/index.html b/manual-guides/Dovecot/u_e-dovecot-any_acl/index.html index 5e99fc0d7..ac4fe7bdb 100644 --- a/manual-guides/Dovecot/u_e-dovecot-any_acl/index.html +++ b/manual-guides/Dovecot/u_e-dovecot-any_acl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,8 +2349,8 @@

          On August the 17th, we disabled the possibility to share with "any" or "all authenticated users" by default.

          This function can be re-enabled by setting ACL_ANYONE to allow in mailcow.conf:

          -
          ACL_ANYONE=allow
          -
          +
          ACL_ANYONE=allow
          +

          Apply the changes by running docker-compose up -d.


          diff --git a/manual-guides/Dovecot/u_e-dovecot-catchall_vacation/index.html b/manual-guides/Dovecot/u_e-dovecot-catchall_vacation/index.html index 42336653f..60313af4d 100644 --- a/manual-guides/Dovecot/u_e-dovecot-catchall_vacation/index.html +++ b/manual-guides/Dovecot/u_e-dovecot-catchall_vacation/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/manual-guides/Dovecot/u_e-dovecot-expunge/index.html b/manual-guides/Dovecot/u_e-dovecot-expunge/index.html index 65fe574be..60120f585 100644 --- a/manual-guides/Dovecot/u_e-dovecot-expunge/index.html +++ b/manual-guides/Dovecot/u_e-dovecot-expunge/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2454,17 +2454,17 @@

          The manual way

          That said, let's dive in:

          Delete a user's mails inside the junk folder that are read and older than 4 hours

          -
          docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'Junk' SEEN not SINCE 4h
          -
          +
          docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'Junk' SEEN not SINCE 4h
          +

          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
          -
          +
          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
          -
          +
          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

          -
          docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'INBOX/custom-folder' not FLAGGED not SINCE 2w
          -
          +
          docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'INBOX/custom-folder' not FLAGGED not SINCE 2w
          +

          Info

          For possible time spans or search keys have a look at man doveadm-search-query

          @@ -2472,21 +2472,21 @@

          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:

          -
          #!/bin/bash
          +
          #!/bin/bash
           # Path to mailcow-dockerized, e.g. /opt/mailcow-dockerized
           cd /path/to/your/mailcow-dockerized
           
           /usr/local/bin/docker-compose exec -T dovecot-mailcow doveadm expunge -A mailbox 'Junk' savedbefore 2w
           /usr/local/bin/docker-compose exec -T dovecot-mailcow doveadm expunge -A mailbox 'Junk' SEEN not SINCE 12h
           [...]
          -
          +

          To create a cron job you may execute crontab -e and insert something like the following to execute a script:

          -
          # Execute everyday at 04:00 A.M.
          +
          # 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'
          +
          version: '2.1'
           
           services:
           
          @@ -2504,12 +2504,12 @@ services:
                 - "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. 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)] 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.

          diff --git a/manual-guides/Dovecot/u_e-dovecot-extra_conf/index.html b/manual-guides/Dovecot/u_e-dovecot-extra_conf/index.html index 674268362..b7621383b 100644 --- a/manual-guides/Dovecot/u_e-dovecot-extra_conf/index.html +++ b/manual-guides/Dovecot/u_e-dovecot-extra_conf/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,8 +2349,8 @@

          Create a file data/conf/dovecot/extra.conf - if missing - and add your additional content here.

          Restart dovecot-mailcow to apply your changes:

          -
          docker-compose restart dovecot-mailcow
          -
          +
          docker-compose restart dovecot-mailcow
          +

          diff --git a/manual-guides/Dovecot/u_e-dovecot-fts/index.html b/manual-guides/Dovecot/u_e-dovecot-fts/index.html index e77afdd8b..28db77ad1 100644 --- a/manual-guides/Dovecot/u_e-dovecot-fts/index.html +++ b/manual-guides/Dovecot/u_e-dovecot-fts/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2443,19 +2443,19 @@

          The default heap size (1024 M) is defined in mailcow.conf.

          Since we run in Docker and create our containers with the "restart: always" flag, a oom situation will at least only trigger a restart of the container.

          -
          # single user
          +
          # single user
           docker-compose exec dovecot-mailcow doveadm fts rescan -u user@domain
           # all users
           docker-compose exec dovecot-mailcow doveadm fts rescan -A
          -
          +

          Dovecot Wiki: "Scan what mails exist in the full text search index and compare those to what actually exist in mailboxes. This removes mails from the index that have already been expunged and makes sure that the next doveadm index will index all the missing mails (if any)."

          This does not re-index a mailbox. It basically repairs a given index.

          If you want to re-index data immediately, you can run the followig command, where '*' can also be a mailbox mask like 'Sent'. You do not need to run these commands, but it will speed things up a bit:

          -
          # single user
          +
          # single user
           docker-compose exec dovecot-mailcow doveadm index -u user@domain '*'
           # all users, but obviously slower and more dangerous
           docker-compose exec dovecot-mailcow doveadm index -A '*'
          -
          +

          This will take some time depending on your machine and Solr can run oom, monitor it!

          Because re-indexing is very sensible, we did not include it to mailcow UI. You will need to take care of any errors while re-indexing a mailbox.

          Delete mailbox data

          diff --git a/manual-guides/Dovecot/u_e-dovecot-idle_interval/index.html b/manual-guides/Dovecot/u_e-dovecot-idle_interval/index.html index 9a741dd83..e8908614e 100644 --- a/manual-guides/Dovecot/u_e-dovecot-idle_interval/index.html +++ b/manual-guides/Dovecot/u_e-dovecot-idle_interval/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2462,8 +2462,8 @@

          Change configuration

          Create a new file data/conf/dovecot/extra.conf (or edit it if it already exists). Insert the setting followed by the new value. For example, to set the interval to 5 minutes you could type:

          -
          imap_idle_notify_interval = 5 mins
          -
          +
          imap_idle_notify_interval = 5 mins
          +

          29 minutes is the maximum value allowed by the corresponding RFC.

          Warning

          @@ -2471,13 +2471,13 @@ Insert the setting followed by the new value. For example, to set the interval t

          Reload Dovecot

          Now reload Dovecot: -

          docker-compose exec dovecot-mailcow dovecot reload
          -

          +
          docker-compose exec dovecot-mailcow dovecot reload
          +

          Info

          You can check the value of this setting with -

          docker-compose exec dovecot-mailcow dovecot -a | grep "imap_idle_notify_interval"
          -
          +
          docker-compose exec dovecot-mailcow dovecot -a | grep "imap_idle_notify_interval"
          +
          If you didn't change it, it should be at 2m. If you did change it, you should see your new value.

          diff --git a/manual-guides/Dovecot/u_e-dovecot-mail-crypt/index.html b/manual-guides/Dovecot/u_e-dovecot-mail-crypt/index.html index 9b748c9b5..dd4cfe587 100644 --- a/manual-guides/Dovecot/u_e-dovecot-mail-crypt/index.html +++ b/manual-guides/Dovecot/u_e-dovecot-mail-crypt/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2350,7 +2350,7 @@

          Mails are stored compressed (lz4) and encrypted. The key pair can be found in crypt-vol-1.

          If you want to decode/encode existing maildir files, you can use the following script at your own risk:

          Enter Dovecot by running docker-compose exec dovecot-mailcow /bin/bash in the mailcow-dockerized location.

          -
          # Decrypt /var/vmail
          +
          # Decrypt /var/vmail
           find /var/vmail/ -type f -regextype egrep -regex '.*S=.*W=.*' | while read -r file; do
           if [[ $(head -c7 "$file") == "CRYPTED" ]]; then
           doveadm fs get compress lz4:0:crypt:private_key_path=/mail_crypt/ecprivkey.pem:public_key_path=/mail_crypt/ecpubkey.pem:posix:prefix=/ \
          @@ -2374,7 +2374,7 @@ doveadm fs put crypt private_key_path=/mail_crypt/ecprivkey.pem:public_key_path=
             chown 5000:5000 "$file"
           fi
           done
          -
          +

          diff --git a/manual-guides/Dovecot/u_e-dovecot-more/index.html b/manual-guides/Dovecot/u_e-dovecot-more/index.html index 89b4daaed..1c4baf636 100644 --- a/manual-guides/Dovecot/u_e-dovecot-more/index.html +++ b/manual-guides/Dovecot/u_e-dovecot-more/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2414,25 +2414,25 @@

          doveadm quota

          The quota get and quota recalc1 commands are used to display or recalculate the current user's quota usage. The reported values are in kilobytes.

          To list the current quota status for a user / mailbox, do:

          -
          doveadm quota get -u 'mailbox@example.org'
          -
          +
          doveadm quota get -u 'mailbox@example.org'
          +

          To list the quota storage value for all users, do:

          -
          doveadm quota get -A |grep "STORAGE"
          -
          +
          doveadm quota get -A |grep "STORAGE"
          +

          Recalculate a single user's quota usage:

          -
          doveadm quota recalc -u 'mailbox@example.org'
          -
          +
          doveadm quota recalc -u 'mailbox@example.org'
          +

          The doveadm search2 command is used to find messages matching your query. It can return the username, mailbox-GUID / -UID and message-GUIDs / -UIDs.

          To view the number of messages, by user, in their .Trash folder:

          -
          doveadm search -A mailbox 'Trash' | awk '{print $1}' | sort | uniq -c
          -
          +
          doveadm search -A mailbox 'Trash' | awk '{print $1}' | sort | uniq -c
          +

          Show all messages in a user's inbox older then 90 days:

          -
          doveadm search -u 'mailbox@example.org' mailbox 'INBOX' savedbefore 90d
          -
          +
          doveadm search -u 'mailbox@example.org' mailbox 'INBOX' savedbefore 90d
          +

          Show all messages in any folder that are older then 30 days for mailbox@example.org:

          -
          doveadm search -u 'mailbox@example.org' mailbox "*" savedbefore 30d
          -
          +
          doveadm search -u 'mailbox@example.org' mailbox "*" savedbefore 30d
          +

            diff --git a/manual-guides/Dovecot/u_e-dovecot-public_folder/index.html b/manual-guides/Dovecot/u_e-dovecot-public_folder/index.html index b24121c3f..87d15de04 100644 --- a/manual-guides/Dovecot/u_e-dovecot-public_folder/index.html +++ b/manual-guides/Dovecot/u_e-dovecot-public_folder/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2398,7 +2398,7 @@

            Create a new public namespace "Public" and a mailbox "Develcow" inside that namespace:

            Edit or create data/conf/dovecot/extra.conf, add:

            -
            namespace {
            +
            namespace {
               type = public
               separator = /
               prefix = Public/
            @@ -2408,18 +2408,18 @@
                 auto = subscribe
               }
             }
            -
            +

            :INDEXPVT=~/public can be omitted if per-user seen flags are not wanted.

            The new mailbox in the public namespace will be auto-subscribed by users.

            To allow all authenticated users access full to that new mailbox (not the whole namespace), run:

            -
            docker-compose exec dovecot-mailcow doveadm acl set -A "Public/Develcow" "authenticated" lookup read write write-seen write-deleted insert post delete expunge create
            -
            +
            docker-compose exec dovecot-mailcow doveadm acl set -A "Public/Develcow" "authenticated" lookup read write write-seen write-deleted insert post delete expunge create
            +

            Adjust the command to your needs if you like to assign more granular rights per user (use -u user@domain instead of -A for example).

            Allow authenticated users access to the whole public namespace

            To allow all authenticated users access full access to the whole public namespace and its subfolders, create a new dovecot-acl file in the namespace root directory:

            Open/edit/create /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/public/dovecot-acl (adjust the path accordingly) to create the global ACL file with the following content:

            -
            authenticated kxeilprwts
            -
            +
            authenticated kxeilprwts
            +

            kxeilprwts equals to lookup read write write-seen write-deleted insert post delete expunge create.

            You can use doveadm acl set -u user@domain "Public/Develcow" user=user@domain lookup read to limit access for a single user. You may also turn it around to limit access for all users to "lr" and grant only some users full access.

            See Dovecot ACL for further information about ACL.

            diff --git a/manual-guides/Dovecot/u_e-dovecot-static_master/index.html b/manual-guides/Dovecot/u_e-dovecot-static_master/index.html index 4387d62f6..9733aad82 100644 --- a/manual-guides/Dovecot/u_e-dovecot-static_master/index.html +++ b/manual-guides/Dovecot/u_e-dovecot-static_master/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2351,9 +2351,9 @@

            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_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.

            diff --git a/manual-guides/Dovecot/u_e-dovecot-vmail-volume/index.html b/manual-guides/Dovecot/u_e-dovecot-vmail-volume/index.html index 8a4d7f797..3ea807e78 100644 --- a/manual-guides/Dovecot/u_e-dovecot-vmail-volume/index.html +++ b/manual-guides/Dovecot/u_e-dovecot-vmail-volume/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2442,26 +2442,26 @@

            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
          +
          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'
          +
          version: '2.1'
           volumes:
             vmail-vol-1:
               driver_opts:
                 type: none
                 device: /data/mailcow/vmail   
                 o: bind
          -
          +

          Moving an existing vmail folder:

          • Locate the current vmail folder by its "Mountpoint" attribute: docker volume inspect mailcowdockerized_vmail-vol-1
          -
          [
          +
          [
               {
                   "CreatedAt": "2019-06-16T22:08:34+02:00",
                   "Driver": "local",
          @@ -2476,7 +2476,7 @@ volumes:
                   "Scope": "local"
               }
           ]
          -
          +
          • Copy the content of the Mountpoint folder to the new location (e.g. /data/mailcow/vmail) using cp -a, rsync -a or a similar non strcuture breaking copy command
          • Stop mailcow by executing docker-compose down from within your mailcow root folder (e.g. /opt/mailcow-dockerized)
          • diff --git a/manual-guides/Nginx/u_e-nginx_custom/index.html b/manual-guides/Nginx/u_e-nginx_custom/index.html index 19d709f2a..2ef69a8f0 100644 --- a/manual-guides/Nginx/u_e-nginx_custom/index.html +++ b/manual-guides/Nginx/u_e-nginx_custom/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2444,9 +2444,9 @@

            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
            -
            -
            server {
            +
            nano data/conf/nginx/my_custom_site.conf
            +
            +
            server {
               ssl_certificate /etc/ssl/mail/cert.pem;
               ssl_certificate_key /etc/ssl/mail/key.pem;
               ssl_protocols TLSv1.2 TLSv1.3;
            @@ -2478,12 +2478,12 @@
                 return 301 https://$server_name$request_uri;
               }
             }
            -
            +

            New site with proxy to a remote location

            Another example with a reverse proxy configuration:

            -
            nano data/conf/nginx/my_custom_site.conf
            -
            -
            server {
            +
            nano data/conf/nginx/my_custom_site.conf
            +
            +
            server {
               ssl_certificate /etc/ssl/mail/cert.pem;
               ssl_certificate_key /etc/ssl/mail/key.pem;
               ssl_protocols TLSv1.2 TLSv1.3;
            @@ -2519,18 +2519,18 @@
                 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:

            -
            nano data/conf/nginx/site.my_content.custom
            -
            +
            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.

            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.

            Restart Nginx (and PHP-FPM, if a new listener was created):

            -
            docker-compose restart nginx-mailcow
            +
            docker-compose restart nginx-mailcow
             docker-compose restart php-fpm-mailcow
            -
            +

            diff --git a/manual-guides/Nginx/u_e-nginx_webmail-site/index.html b/manual-guides/Nginx/u_e-nginx_webmail-site/index.html index 1fe800e27..334d4a8be 100644 --- a/manual-guides/Nginx/u_e-nginx_webmail-site/index.html +++ b/manual-guides/Nginx/u_e-nginx_webmail-site/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2350,7 +2350,7 @@

            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"!

            nano data/conf/nginx/webmail.conf

            -
            server {
            +
            server {
               ssl_certificate /etc/ssl/mail/cert.pem;
               ssl_certificate_key /etc/ssl/mail/key.pem;
               index index.php index.html;
            @@ -2369,12 +2369,12 @@
                 return 301 https://CHANGE_TO_MAILCOW_HOSTNAME/SOGo;
               }
             }
            -
            +

            Save and restart Nginx: docker-compose restart nginx-mailcow.

            Now open mailcow.conf and find ADDITIONAL_SAN. Add webmail.example.org to this array, don't use quotes!

            -
            ADDITIONAL_SAN=webmail.example.org
            -
            +
            ADDITIONAL_SAN=webmail.example.org
            +

            Run docker-compose up -d. See "acme-mailcow" and "nginx-mailcow" logs if anything fails.


            diff --git a/manual-guides/Postfix/u_e-postfix-attachment_size/index.html b/manual-guides/Postfix/u_e-postfix-attachment_size/index.html index ebfa2995b..324bd9b30 100644 --- a/manual-guides/Postfix/u_e-postfix-attachment_size/index.html +++ b/manual-guides/Postfix/u_e-postfix-attachment_size/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,8 +2349,8 @@

            Open data/conf/postfix/extra.cf and set the message_size_limit accordingly in bytes. See main.cf for the default value.

            Restart Postfix:

            -
            docker-compose restart postfix-mailcow
            -
            +
            docker-compose restart postfix-mailcow
            +

            diff --git a/manual-guides/Postfix/u_e-postfix-custom_transport/index.html b/manual-guides/Postfix/u_e-postfix-custom_transport/index.html index 46800a2d9..7618d1410 100644 --- a/manual-guides/Postfix/u_e-postfix-custom_transport/index.html +++ b/manual-guides/Postfix/u_e-postfix-custom_transport/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/manual-guides/Postfix/u_e-postfix-disable_sender_verification/index.html b/manual-guides/Postfix/u_e-postfix-disable_sender_verification/index.html index f2201c3ce..7b88f6b0d 100644 --- a/manual-guides/Postfix/u_e-postfix-disable_sender_verification/index.html +++ b/manual-guides/Postfix/u_e-postfix-disable_sender_verification/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2416,14 +2416,14 @@

            Deprecated guide (DO NOT USE ON NEWER MAILCOWS!)

            This option is not best-practice and should only be implemented when there is no other option available to achieve whatever you are trying to do.

            Simply create a file data/conf/postfix/check_sasl_access and enter the following content. This user must exist in your installation and needs to authenticate before sending mail. -

            user-to-allow-everything@example.com OK
            -

            +
            user-to-allow-everything@example.com OK
            +

            Open data/conf/postfix/main.cf and find smtpd_sender_restrictions. Prepend check_sasl_access hash:/opt/postfix/conf/check_sasl_access like this: -

            smtpd_sender_restrictions = check_sasl_access hash:/opt/postfix/conf/check_sasl_access reject_authenticated_sender_login_mismatch [...]
            -

            +
            smtpd_sender_restrictions = check_sasl_access hash:/opt/postfix/conf/check_sasl_access reject_authenticated_sender_login_mismatch [...]
            +

            Run postmap on check_sasl_access:

            -
            docker-compose exec postfix-mailcow postmap /opt/postfix/conf/check_sasl_access
            -
            +
            docker-compose exec postfix-mailcow postmap /opt/postfix/conf/check_sasl_access
            +

            Restart the Postfix container.


            diff --git a/manual-guides/Postfix/u_e-postfix-extra_cf/index.html b/manual-guides/Postfix/u_e-postfix-extra_cf/index.html index 3c8e0c566..31c2d294d 100644 --- a/manual-guides/Postfix/u_e-postfix-extra_cf/index.html +++ b/manual-guides/Postfix/u_e-postfix-extra_cf/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2351,8 +2351,8 @@

            Postfix will complain about duplicate values once after starting postfix-mailcow, this is intended.

            Syslog-ng was configured to hide those warnings while Postfix is running, to not spam the log files with unnecessary information every time a service is used.

            Restart postfix-mailcow to apply your changes:

            -
            docker-compose restart postfix-mailcow
            -
            +
            docker-compose restart postfix-mailcow
            +

            diff --git a/manual-guides/Postfix/u_e-postfix-pflogsumm/index.html b/manual-guides/Postfix/u_e-postfix-pflogsumm/index.html index 04e02c09d..d01dc3afb 100644 --- a/manual-guides/Postfix/u_e-postfix-pflogsumm/index.html +++ b/manual-guides/Postfix/u_e-postfix-pflogsumm/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,13 +2348,13 @@

            Statistics with pflogsumm

            To use pflogsumm with the default logging driver, we need to query postfix-mailcow via docker logs and direct the output to pflogsumm:

            -
            docker logs --since 24h $(docker ps -qf name=postfix-mailcow) | pflogsumm
            -
            +
            docker logs --since 24h $(docker ps -qf name=postfix-mailcow) | pflogsumm
            +

            The above log output is limited to the last 24 hours.

            It is also possible to create a daily pflogsumm report via cron. Create the /etc/cron.d/pflogsumm file with the following content:

            -
            SHELL=/bin/bash
            +
            SHELL=/bin/bash
             59 23 * * root docker logs --since 24h $(docker ps -qf name=postfix-mailcow) | /usr/sbin/pflogsumm -d today | mail -s "Postfix Report of $(date)" postmaster@example.net
            -
            +

            To work, a local postfix must be installed on the server, which relays to the mailcow postfix.

            More detailed information can be found in section Post installation tasks -> Local MTA on Dockerhost.

            Based on the postfix logs of the last 24 hours, this example then sends a pflogsumm report to postmaster@example.net every day at 23:59:00.

            diff --git a/manual-guides/Postfix/u_e-postfix-postscreen_whitelist/index.html b/manual-guides/Postfix/u_e-postfix-postscreen_whitelist/index.html index 3ce108730..1948c26d7 100644 --- a/manual-guides/Postfix/u_e-postfix-postscreen_whitelist/index.html +++ b/manual-guides/Postfix/u_e-postfix-postscreen_whitelist/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2353,11 +2353,11 @@

            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.
            +
            # 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.


            diff --git a/manual-guides/Postfix/u_e-postfix-relayhost/index.html b/manual-guides/Postfix/u_e-postfix-relayhost/index.html index 443c8a869..1ad8620e6 100644 --- a/manual-guides/Postfix/u_e-postfix-relayhost/index.html +++ b/manual-guides/Postfix/u_e-postfix-relayhost/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/manual-guides/Postfix/u_e-postfix-trust_networks/index.html b/manual-guides/Postfix/u_e-postfix-trust_networks/index.html index 37f4a454f..3990356de 100644 --- a/manual-guides/Postfix/u_e-postfix-trust_networks/index.html +++ b/manual-guides/Postfix/u_e-postfix-trust_networks/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2447,15 +2447,15 @@

            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
            -
            +
            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
            -
            +
            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

            diff --git a/manual-guides/Redis/u_e-redis/index.html b/manual-guides/Redis/u_e-redis/index.html index 62ecc8f77..617eae16c 100644 --- a/manual-guides/Redis/u_e-redis/index.html +++ b/manual-guides/Redis/u_e-redis/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2477,28 +2477,28 @@

            Redis is used as a key-value store for rspamd's and (some of) mailcow's settings and data. If you are unfamiliar with redis please read the introduction to redis and maybe visit this wonderful guide on how to use it.

            Client

            To connect to the redis cli execute:

            -
            docker-compose exec redis-mailcow redis-cli
            -
            +
            docker-compose exec redis-mailcow redis-cli
            +

            Debugging

            Here are some useful commands for the redis-cli for debugging:

            MONITOR

            Listens for all requests received by the server in real time:

            -
            # docker-compose exec redis-mailcow redis-cli
            +
            # docker-compose exec redis-mailcow redis-cli
             127.0.0.1:6379> monitor
             OK
             1494077286.401963 [0 172.22.1.253:41228] "SMEMBERS" "BAYES_SPAM_keys"
             1494077288.292970 [0 172.22.1.253:41229] "SMEMBERS" "BAYES_SPAM_keys"
             [...]
            -
            +
            KEYS

            Get all keys matching your pattern:

            -
            KEYS *
            -
            +
            KEYS *
            +
            PING

            Test a connection:

            -
            127.0.0.1:6379> PING
            +
            127.0.0.1:6379> PING
             PONG
            -
            +

            If you want to know more, here is a cheat sheet.


            diff --git a/manual-guides/Rspamd/u_e-rspamd/index.html b/manual-guides/Rspamd/u_e-rspamd/index.html index a5a126877..c35d15f7e 100644 --- a/manual-guides/Rspamd/u_e-rspamd/index.html +++ b/manual-guides/Rspamd/u_e-rspamd/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2556,68 +2556,68 @@ This is achieved by using the Sieve plugin "sieve_imapsieve" and parser scripts.

            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

            You can use a one-liner to learn mail in plain-text (uncompressed) format:

            -
            # Ham
            -for file in /my/folder/cur/*; do docker exec -i $(docker-compose ps -q rspamd-mailcow) rspamc learn_ham < $file; done
            +
            # Ham
            +for file in /my/folder/cur/*; do docker exec -i $(docker-compose ps -q rspamd-mailcow) rspamc learn_ham < $file; done
             # Spam
            -for file in /my/folder/.Junk/cur/*; do docker exec -i $(docker-compose ps -q rspamd-mailcow) rspamc learn_spam < $file; done
            -
            +for file in /my/folder/.Junk/cur/*; do docker exec -i $(docker-compose ps -q rspamd-mailcow) rspamc learn_spam < $file; done +

            Consider attaching a local folder as new volume to rspamd-mailcow in docker-compose.yml and learn given files inside the container. This can be used as workaround to parse compressed data with zcat. Example:

            -
            for file in /data/old_mail/.Junk/cur/*; do rspamc learn_spam < zcat $file; done
            -
            +
            for file in /data/old_mail/.Junk/cur/*; do rspamc learn_spam < zcat $file; done
            +

            Reset learned data (Bayes, Neural)

            You need to delete keys in Redis to reset learned data, so create a copy of your Redis database now:

            Backup database

            -
            # It is better to stop Redis before you copy the file.
            +
            # It is better to stop Redis before you copy the file.
             cp /var/lib/docker/volumes/mailcowdockerized_redis-vol-1/_data/dump.rdb /root/
            -
            +

            Reset Bayes data

            -
            docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern BAYES_* | xargs redis-cli del'
            +
            docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern BAYES_* | xargs redis-cli del'
             docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern RS* | xargs redis-cli del'
            -
            +

            Reset Neural data

            -
            docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern rn_* | xargs redis-cli del'
            -
            +
            docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern rn_* | xargs redis-cli del'
            +

            Reset Fuzzy data

            -
            # We need to enter the redis-cli first:
            +
            # We need to enter the redis-cli first:
             docker-compose exec redis-mailcow redis-cli
             # In redis-cli:
             127.0.0.1:6379> EVAL "for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end" 0 fuzzy*
            -
            +

            Info

            If redis-cli complains about...

            -
            (error) ERR wrong number of arguments for 'del' command
            -
            +
            (error) ERR wrong number of arguments for 'del' command
            +

            ...the key pattern was not found and thus no data is available to delete - it is fine.

            CLI tools

            -
            docker-compose exec rspamd-mailcow rspamc --help
            +
            docker-compose exec rspamd-mailcow rspamc --help
             docker-compose exec rspamd-mailcow rspamadm --help
            -
            +

            Disable Greylisting

            Only messages with a higher score will be considered to be greylisted (soft rejected). It is bad practice to disable greylisting.

            You can disable greylisting server-wide by editing:

            {mailcow-dir}/data/conf/rspamd/local.d/greylist.conf

            Add the line:

            -
            enabled = false;
            -
            +
            enabled = false;
            +

            Save the file and restart "rspamd-mailcow": docker-compose restart rspamd-mailcow

            Spam filter thresholds (global)

            Each user is able to change their spam rating individually. To define a new server-wide limit, edit data/conf/rspamd/local.d/actions.conf:

            -
            reject = 15;
            -add_header = 8;
            -greylist = 7;
            -
            +
            reject = 15;
            +add_header = 8;
            +greylist = 7;
            +

            Save the file and restart "rspamd-mailcow": docker-compose restart rspamd-mailcow

            Existing settings of users will not be overwritten!

            To reset custom defined thresholds, run:

            -
            source mailcow.conf
            +
            source mailcow.conf
             docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e "delete from filterconf where option = 'highspamlevel' or option = 'lowspamlevel';"
             # or:
             # docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e "delete from filterconf where option = 'highspamlevel' or option = 'lowspamlevel' and object = 'only-this-mailbox@example.org';"
            -
            +

            Custom reject messages

            The default spam reject message can be changed by adding a new file data/conf/rspamd/override.d/worker-proxy.custom.inc with the following content:

            -
            reject_message = "My custom reject message";
            -
            +
            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, prefilter reject actions will ignore this setting. For these maps, the multimap module in Rspamd needs to be adjusted:

              @@ -2628,7 +2628,7 @@ docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e "del

              Add your custom message as new line:

            -
            GLOBAL_RCPT_BL {
            +
            GLOBAL_RCPT_BL {
               type = "rcpt";
               map = "${LOCAL_CONFDIR}/custom/global_rcpt_blacklist.map";
               regexp = true;
            @@ -2636,40 +2636,40 @@ docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e "del
               action = "reject";
               message = "Sending mail to this recipient is prohibited by postmaster@your.domain";
             }
            -
            +
            1. Save the file and restart Rspamd: docker-compose restart rspamd-mailcow.

            Discard instead of reject

            If you want to silently drop a message, create or edit the file data/conf/rspamd/override.d/worker-proxy.custom.inc and add the following content:

            -
            discard_on_reject = true;
            -
            +
            discard_on_reject = true;
            +

            Restart Rspamd:

            -
            docker-compose restart rspamd-mailcow
            -
            +
            docker-compose restart rspamd-mailcow
            +

            Wipe all ratelimit keys

            If you don't want to use the UI and instead wipe all keys in the Redis database, you can use redis-cli for that task:

            -
            docker-compose exec redis-mailcow sh
            +
            docker-compose exec redis-mailcow sh
             # Unlink (available in Redis >=4.) will delete in the backgronud
             redis-cli --scan --pattern RL* | xargs redis-cli unlink
            -
            +

            Restart Rspamd:

            -
            docker-compose exec redis-mailcow sh
            -
            +
            docker-compose exec redis-mailcow sh
            +

            Trigger a resend of quarantine notifications

            Should be used for debugging only!

            -
            docker-compose exec dovecot-mailcow bash
            +
            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
            -
            +
            nrows = 1000; # change this value
            +

            Restart Rspamd afterwards: docker-compose restart rspamd-mailcow


            diff --git a/manual-guides/SOGo/u_e-sogo/index.html b/manual-guides/SOGo/u_e-sogo/index.html index ef4dc6534..9ae1232d8 100644 --- a/manual-guides/SOGo/u_e-sogo/index.html +++ b/manual-guides/SOGo/u_e-sogo/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2491,24 +2491,24 @@ After you modified data/conf/sogo/custom-theme.js and made changes
          • open browser developer console, usually shortcut is F12
          • only if you use Firefox: write by hands in dev console allow pasting and press enter
          • paste java script snipet in dev console: -
            copy([].slice.call(document.styleSheets)
            +
            copy([].slice.call(document.styleSheets)
               .map(e => e.ownerNode)
               .filter(e => e.hasAttribute('md-theme-style'))
               .map(e => e.textContent)
               .join('\n')
             )
            -
          • +
          • open text editor and paste data from clipboard (Ctrl+V), you should get minified CSS, save it
          • copy CSS file to mailcow server data/conf/sogo/custom-theme.css
          • edit data/conf/sogo/sogo.conf and set SOGoUIxDebugEnabled = NO;
          • append/create docker-compose.override.yml with: -
            version: '2.1'
            +
            version: '2.1'
             
             services:
               sogo-mailcow:
                 volumes:
                   - ./data/conf/sogo/custom-theme.css:/usr/lib/GNUstep/SOGo/WebServerResources/css/theme-default.css:z
            -
          • +
          • run docker-compose up -d
          • run docker-compose restart memcached-mailcow
          • @@ -2516,7 +2516,7 @@ services:
            1. 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
            2. find in data/conf/sogo/custom-theme.js: -
              // Apply new palettes to the default theme, remap some of the hues
              +
              // 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
              @@ -2531,13 +2531,13 @@ services:
                       'hue-3': 'A700'
                     })
                     .backgroundPalette('frost-grey');
              -
              +
              and replace it with: -
                  $mdThemingProvider.theme('default');
              -
            3. +
                  $mdThemingProvider.theme('default');
              +
            4. remove from docker-compose.override.yml volume mount in sogo-mailcow: -
              - ./data/conf/sogo/custom-theme.css:/usr/lib/GNUstep/SOGo/WebServerResources/css/theme-default.css:z
              -
            5. +
              - ./data/conf/sogo/custom-theme.css:/usr/lib/GNUstep/SOGo/WebServerResources/css/theme-default.css:z
              +
            6. run docker-compose up -d
            7. run docker-compose restart memcached-mailcow
            @@ -2553,16 +2553,16 @@ After you replaced said file you need to restart SOGo and Memcached containers b

            Domains are usually isolated from eachother.

            You can change that by modifying data/conf/sogo/sogo.conf:

            Search... -

               // SOGoDomainsVisibility = (
            +
               // SOGoDomainsVisibility = (
                 //  (domain1.tld, domain5.tld),
                 //  (domain3.tld, domain2.tld)
                 // );
            -
            +
            ...and replace it by - for example:

            -
                SOGoDomainsVisibility = (
            +
                SOGoDomainsVisibility = (
                   (example.org, example.com, example.net)
                 );
            -
            +

            Restart SOGo: docker-compose restart sogo-mailcow

            Disable password changing

            Edit data/conf/sogo/sogo.conf and change SOGoPasswordChangeEnabled to NO. Please do not add a new parameter.

            diff --git a/manual-guides/Unbound/u_e-unbound-fwd/index.html b/manual-guides/Unbound/u_e-unbound-fwd/index.html index 0bf5ac7d7..1ac343167 100644 --- a/manual-guides/Unbound/u_e-unbound-fwd/index.html +++ b/manual-guides/Unbound/u_e-unbound-fwd/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2416,18 +2416,18 @@ Important: Only DNSSEC validating DNS services will work.

            Method A, Unbound

            Edit data/conf/unbound/unbound.conf and append the following parameters:

            -
            forward-zone:
            +
            forward-zone:
               name: "."
               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:

            -
            docker-compose restart unbound-mailcow
            -
            +
            docker-compose restart unbound-mailcow
            +

            Method B, Override file

            -
            cd /opt/mailcow-dockerized
            +
            cd /opt/mailcow-dockerized
             cp helper-scripts/docker-compose.override.yml.d/EXTERNAL_DNS/docker-compose.override.yml .
            -
            +

            Edit docker-compose.override.yml and adjust the IP.

            Run docker-compose down ; docker-compose up -d.

            diff --git a/manual-guides/Watchdog/u_e-watchdog-thresholds/index.html b/manual-guides/Watchdog/u_e-watchdog-thresholds/index.html index c732ca90d..8b354f76b 100644 --- a/manual-guides/Watchdog/u_e-watchdog-thresholds/index.html +++ b/manual-guides/Watchdog/u_e-watchdog-thresholds/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2649,7 +2649,7 @@

            Watchdog uses default values for all thresholds defined in docker-compose.yml.

            The default values will work for most setups. Example: -

            - NGINX_THRESHOLD=${NGINX_THRESHOLD:-5}
            +
            - NGINX_THRESHOLD=${NGINX_THRESHOLD:-5}
             - UNBOUND_THRESHOLD=${UNBOUND_THRESHOLD:-5}
             - REDIS_THRESHOLD=${REDIS_THRESHOLD:-5}
             - MYSQL_THRESHOLD=${MYSQL_THRESHOLD:-5}
            @@ -2667,7 +2667,7 @@ Example:
             - OLEFY_THRESHOLD=${OLEFY_THRESHOLD:-5}
             - MAILQ_THRESHOLD=${MAILQ_THRESHOLD:-20}
             - MAILQ_CRIT=${MAILQ_CRIT:-30}
            -

            +

            To adjust them just add necessary threshold variables (e.g. MAILQ_THRESHOLD=10) to mailcow.conf and run docker-compose up -d.

            Thresholds descriptions

            NGINX_THRESHOLD

            diff --git a/manual-guides/mailcow-UI/u_e-mailcow_ui-bl_wl/index.html b/manual-guides/mailcow-UI/u_e-mailcow_ui-bl_wl/index.html index aa465f771..8705bd1c1 100644 --- a/manual-guides/mailcow-UI/u_e-mailcow_ui-bl_wl/index.html +++ b/manual-guides/mailcow-UI/u_e-mailcow_ui-bl_wl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/manual-guides/mailcow-UI/u_e-mailcow_ui-config/index.html b/manual-guides/mailcow-UI/u_e-mailcow_ui-config/index.html index 811479b2c..2a3398c91 100644 --- a/manual-guides/mailcow-UI/u_e-mailcow_ui-config/index.html +++ b/manual-guides/mailcow-UI/u_e-mailcow_ui-config/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/manual-guides/mailcow-UI/u_e-mailcow_ui-css/index.html b/manual-guides/mailcow-UI/u_e-mailcow_ui-css/index.html index 584d5f0b5..7827338d8 100644 --- a/manual-guides/mailcow-UI/u_e-mailcow_ui-css/index.html +++ b/manual-guides/mailcow-UI/u_e-mailcow_ui-css/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/manual-guides/mailcow-UI/u_e-mailcow_ui-fido/index.html b/manual-guides/mailcow-UI/u_e-mailcow_ui-fido/index.html index 8ca805268..c16c7afa8 100644 --- a/manual-guides/mailcow-UI/u_e-mailcow_ui-fido/index.html +++ b/manual-guides/mailcow-UI/u_e-mailcow_ui-fido/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/manual-guides/mailcow-UI/u_e-mailcow_ui-pushover/index.html b/manual-guides/mailcow-UI/u_e-mailcow_ui-pushover/index.html index 461eee771..f2e85e1ae 100644 --- a/manual-guides/mailcow-UI/u_e-mailcow_ui-pushover/index.html +++ b/manual-guides/mailcow-UI/u_e-mailcow_ui-pushover/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/manual-guides/mailcow-UI/u_e-mailcow_ui-spamalias/index.html b/manual-guides/mailcow-UI/u_e-mailcow_ui-spamalias/index.html index 22c0cd0a7..53db3b8be 100644 --- a/manual-guides/mailcow-UI/u_e-mailcow_ui-spamalias/index.html +++ b/manual-guides/mailcow-UI/u_e-mailcow_ui-spamalias/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/manual-guides/mailcow-UI/u_e-mailcow_ui-spamfilter/index.html b/manual-guides/mailcow-UI/u_e-mailcow_ui-spamfilter/index.html index 1493c45cf..3cb71a380 100644 --- a/manual-guides/mailcow-UI/u_e-mailcow_ui-spamfilter/index.html +++ b/manual-guides/mailcow-UI/u_e-mailcow_ui-spamfilter/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/manual-guides/mailcow-UI/u_e-mailcow_ui-tagging/index.html b/manual-guides/mailcow-UI/u_e-mailcow_ui-tagging/index.html index 2e5b2bab0..f14ac7803 100644 --- a/manual-guides/mailcow-UI/u_e-mailcow_ui-tagging/index.html +++ b/manual-guides/mailcow-UI/u_e-mailcow_ui-tagging/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2403,7 +2403,7 @@

            1. Move this message to a sub folder "facebook" (will be created lower case if not existing)

            2. Prepend the tag to the subject: "[facebook] Subject"

            Please note: Uppercase tags are converted to lowercase except for the first letter. If you want to keep the tag as it is, please apply the following diff and restart mailcow: -

            diff --git a/data/conf/dovecot/global_sieve_after b/data/conf/dovecot/global_sieve_after
            +
            diff --git a/data/conf/dovecot/global_sieve_after b/data/conf/dovecot/global_sieve_after
             index e047136e..933c4137 100644
             --- a/data/conf/dovecot/global_sieve_after
             +++ b/data/conf/dovecot/global_sieve_after
            @@ -2416,7 +2416,7 @@ index e047136e..933c4137 100644
                if mailboxexists "INBOX/${1}" {
                  fileinto "INBOX/${1}";
                } else {
            -

            +


            diff --git a/manual-guides/mailcow-UI/u_e-mailcow_ui-tfa/index.html b/manual-guides/mailcow-UI/u_e-mailcow_ui-tfa/index.html index ee5b6ad60..10af4a3bd 100644 --- a/manual-guides/mailcow-UI/u_e-mailcow_ui-tfa/index.html +++ b/manual-guides/mailcow-UI/u_e-mailcow_ui-tfa/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/manual-guides/u_e-80_to_443/index.html b/manual-guides/u_e-80_to_443/index.html index fac048bd9..9279d4ad0 100644 --- a/manual-guides/u_e-80_to_443/index.html +++ b/manual-guides/u_e-80_to_443/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,7 +2349,7 @@

            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= - if not already set.

            Create a new file data/conf/nginx/redirect.conf and add the following server config to the file:

            -
            server {
            +
            server {
               root /web;
               listen 80 default_server;
               listen [::]:80 default_server;
            @@ -2363,13 +2363,13 @@
                 return 301 https://$host$uri$is_args$args;
               }
             }
            -
            +

            In case you changed the HTTP_BIND parameter, recreate the container:

            -
            docker-compose up -d
            -
            +
            docker-compose up -d
            +

            Otherwise restart Nginx:

            -
            docker-compose restart nginx-mailcow
            -
            +
            docker-compose restart nginx-mailcow
            +

            diff --git a/manual-guides/u_e-autodiscover_config/index.html b/manual-guides/u_e-autodiscover_config/index.html index 7f63d14f9..2799dc3ae 100644 --- a/manual-guides/u_e-autodiscover_config/index.html +++ b/manual-guides/u_e-autodiscover_config/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2350,7 +2350,7 @@ Keep in mind, that ActiveSync should NOT be used with a desktop client.

            Open/create data/web/inc/vars.local.inc.php and add your changes to the configuration array.

            Changes will be merged with "$autodiscover_config" in data/web/inc/vars.inc.php):

            -
            <?php
            +
            <?php
             $autodiscover_config = array(
               // General autodiscover service type: "activesync" or "imap"
               // emClient uses autodiscover, but does not support ActiveSync. mailcow excludes emClient from ActiveSync.
            @@ -2388,7 +2388,7 @@ $autodiscover_config = array(
                 'port' => $https_port,
               ),
             );
            -
            +

            To always use IMAP and SMTP instead of EAS, set 'autodiscoverType' => 'imap'.

            Disable ActiveSync for Outlook desktop clients by setting "useEASforOutlook" to "no".

            diff --git a/manual-guides/u_e-reeanble-weak-protocols/index.html b/manual-guides/u_e-reeanble-weak-protocols/index.html index 3e73d6b4f..c88ac999b 100644 --- a/manual-guides/u_e-reeanble-weak-protocols/index.html +++ b/manual-guides/u_e-reeanble-weak-protocols/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2349,15 +2349,15 @@

            Unauthenticated mail via SMTP on port 25/tcp does still accept >= TLS 1.0 . It is better to accept a weak encryption than none at all.

            How to re-enable weak protocols?

            Edit data/conf/postfix/extra.cf:

            -
            submission_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
            +
            submission_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
             smtps_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
            -
            +

            Edit data/conf/dovecot/extra.conf:

            -
            ssl_min_protocol = TLSv1
            -
            +
            ssl_min_protocol = TLSv1
            +

            Restart the affected services:

            -
            docker-compose restart postfix-mailcow dovecot-mailcow
            -
            +
            docker-compose restart postfix-mailcow dovecot-mailcow
            +

            Hint: You can enable TLS 1.2 in Windows 7.


            diff --git a/manual-guides/u_e-update-hooks/index.html b/manual-guides/u_e-update-hooks/index.html index e6d7acbef..06681f616 100644 --- a/manual-guides/u_e-update-hooks/index.html +++ b/manual-guides/u_e-update-hooks/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/manual-guides/u_e-why_unbound/index.html b/manual-guides/u_e-why_unbound/index.html index fcf414313..9d4a5b3bf 100644 --- a/manual-guides/u_e-why_unbound/index.html +++ b/manual-guides/u_e-why_unbound/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/models/model-acl/index.html b/models/model-acl/index.html index 86d5e86cc..c3763c893 100644 --- a/models/model-acl/index.html +++ b/models/model-acl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/models/model-passwd/index.html b/models/model-passwd/index.html index 64f1c985d..e75e094bf 100644 --- a/models/model-passwd/index.html +++ b/models/model-passwd/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/models/model-sender_rcv/index.html b/models/model-sender_rcv/index.html index 26fbb6537..fed867232 100644 --- a/models/model-sender_rcv/index.html +++ b/models/model-sender_rcv/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/post_installation/firststeps-disable_ipv6/index.html b/post_installation/firststeps-disable_ipv6/index.html index 1b226de74..0a3100467 100644 --- a/post_installation/firststeps-disable_ipv6/index.html +++ b/post_installation/firststeps-disable_ipv6/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2353,49 +2353,49 @@ and implement your changes to the service there. Unfortunately, this right now o

            To disable IPv6 on the mailcow network, open docker-compose.yml with your favourite text editor and search for the network section (it's near the bottom of the file).

            1. Modify docker-compose.yml

            Change enable_ipv6: true to enable_ipv6: false:

            -
            networks:
            +
            networks:
               mailcow-network:
                 [...]
                 enable_ipv6: true # <<< set to false
                 [...]
            -
            +

            2. Disable ipv6nat-mailcow

            To disable the ipv6nat-mailcow container as well, go to your mailcow directory and create a new file called "docker-compose.override.yml":

            NOTE: If you already have an override file, of course don't recreate it, but merge the lines below into your existing one accordingly!

            -
            # cd /opt/mailcow-dockerized
            +
            # cd /opt/mailcow-dockerized
             # touch docker-compose.override.yml
            -
            +

            Open the file in your favourite text editor and fill in the following:

            -
            version: '2.1'
            +
            version: '2.1'
             services:
             
                 ipv6nat-mailcow:
                   image: bash:latest
                   restart: "no"
                   entrypoint: ["echo", "ipv6nat disabled in compose.override.yml"]
            -
            +

            For these changes to be effective, you need to fully stop and then restart the stack, so containers and networks are recreated:

            -
            docker-compose down
            +
            docker-compose down
             docker-compose up -d
            -
            +

            3. Disable IPv6 in unbound-mailcow

            Edit data/conf/unbound/unbound.conf and set do-ip6 to "no":

            -
            server:
            +
            server:
               [...]
               do-ip6: no
               [...]
            -
            +

            Restart Unbound:

            -
            docker-compose restart unbound-mailcow
            -
            +
            docker-compose restart unbound-mailcow
            +

            4. Disable IPv6 in postfix-mailcow

            Create data/conf/postfix/extra.cf and set smtp_address_preference to ipv4:

            -
            smtp_address_preference = ipv4
            +
            smtp_address_preference = ipv4
             inet_protocols = ipv4
            -
            +

            Restart Postfix:

            -
            docker-compose restart postfix-mailcow
            -
            +
            docker-compose restart postfix-mailcow
            +

            diff --git a/post_installation/firststeps-dmarc_reporting/index.html b/post_installation/firststeps-dmarc_reporting/index.html index c0266494c..9ddd9d0e1 100644 --- a/post_installation/firststeps-dmarc_reporting/index.html +++ b/post_installation/firststeps-dmarc_reporting/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2473,7 +2473,7 @@

            Enable DMARC reporting

            Create the file data/conf/rspamd/local.d/dmarc.conf and set the following content:

            -
            reporting {
            +
            reporting {
                 enabled = true;
                 email = 'noreply-dmarc@example.com';
                 domain = 'example.com';
            @@ -2486,9 +2486,9 @@
                 max_entries = 2k;
                 keys_expire = 2d;
             }
            -
            +

            Create or modify docker-compose.override.yml in the mailcow-dockerized base directory:

            -
            version: '2.1'
            +
            version: '2.1'
             
             services:
               rspamd-mailcow:
            @@ -2501,16 +2501,16 @@ services:
               ofelia-mailcow:
                 depends_on:
                   - rspamd-mailcow
            -
            +

            Run docker-compose up -d

            Send a copy reports to yourself

            To receive a hidden copy of reports generated by Rspamd you can set a bcc_addrs list in the reporting config section of data/conf/rspamd/local.d/dmarc.conf:

            -
            reporting {
            +
            reporting {
                 enabled = true;
                 email = 'noreply-dmarc@example.com';
                 bcc_addrs = ["noreply-dmarc@example.com","parsedmarc@example.com"];
             [...]
            -
            +

            Rspamd will load changes in real time, so you won't need to restart the container at this point.

            This can be useful if you...

              @@ -2519,18 +2519,18 @@ services:

            Troubleshooting

            Check when the report schedule last ran:

            -
            docker-compose exec rspamd-mailcow date -r /var/lib/rspamd/dmarc_reports_last_log
            -
            +
            docker-compose exec rspamd-mailcow date -r /var/lib/rspamd/dmarc_reports_last_log
            +

            See the latest report output:

            -
            docker-compose exec rspamd-mailcow cat /var/lib/rspamd/dmarc_reports_last_log
            -
            +
            docker-compose exec rspamd-mailcow cat /var/lib/rspamd/dmarc_reports_last_log
            +

            Manually trigger a DMARC report:

            -
            docker-compose exec rspamd-mailcow rspamadm dmarc_report
            -
            +
            docker-compose exec rspamd-mailcow rspamadm dmarc_report
            +

            Validate that Rspamd has recorded data in Redis:

            -
            docker-compose exec redis-mailcow redis-cli KEYS 'dmarc;*'
            +
            docker-compose exec redis-mailcow redis-cli KEYS 'dmarc;*'
             docker-compose exec redis-mailcow redis-cli HGETALL "dmarc;example.com;20211231"
            -
            +

            Change DMARC reporting frequency

            In the example above reports are sent once every 24 hours.

            Olefia schedule has same implementation as cron in Go, supported syntax described at cron Documentation

            diff --git a/post_installation/firststeps-ip_bindings/index.html b/post_installation/firststeps-ip_bindings/index.html index 94d28ccce..6a11ebd6a 100644 --- a/post_installation/firststeps-ip_bindings/index.html +++ b/post_installation/firststeps-ip_bindings/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2414,7 +2414,7 @@

            IPv4 binding

            To adjust one or multiple IPv4 bindings, open mailcow.conf and edit one, multiple or all variables as per your needs:

            -
            # For technical reasons, http bindings are a bit different from other service bindings.
            +
            # 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
             
            @@ -2439,14 +2439,14 @@ SIEVE_PORT=4190
             DOVEADM_PORT=127.0.0.1:19991
             SQL_PORT=127.0.0.1:13306
             SOLR_PORT=127.0.0.1:18983
            -
            +

            To apply your changes, run docker-compose down followed by docker-compose up -d.

            IPv6 binding

            Changing IPv6 bindings is different from IPv4. Again, this has a technical background.

            A docker-compose.override.yml file will be used instead of editing the docker-compose.yml file directly. This is to maintain updatability, as the docker-compose.yml file gets updated regularly and your changes will most likely be overwritten.

            Edit to create a file docker-compose.override.yml with the following content. Its content will be merged with the productive docker-compose.yml file.

            An imaginary IPv6 2a00:dead:beef::abc is given. The first suffix :PORT1 defines the external port, while the second suffix :PORT2 routes to the corresponding port inside the container and must not be changed.

            -
            version: '2.1'
            +
            version: '2.1'
             services:
             
                 dovecot-mailcow:
            @@ -2467,7 +2467,7 @@ services:
                   ports:
                     - '2a00:dead:beef::abc:80:80'
                     - '2a00:dead:beef::abc:443:443'
            -
            +

            To apply your changes, run docker-compose down followed by docker-compose up -d.


            diff --git a/post_installation/firststeps-local_mta/index.html b/post_installation/firststeps-local_mta/index.html index 4df30d8c1..5d35217b9 100644 --- a/post_installation/firststeps-local_mta/index.html +++ b/post_installation/firststeps-local_mta/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2347,15 +2347,15 @@

            The easiest option would be to disable the listener on port 25/tcp.

            Postfix users disable the listener by commenting the following line (starting with smtp or 25) in /etc/postfix/master.cf: -

            #smtp      inet  n       -       -       -       -       smtpd
            -

            +
            #smtp      inet  n       -       -       -       -       smtpd
            +

            Furthermore, to relay over a dockerized mailcow, you may want to add 172.22.1.1 as relayhost and remove the Docker interface from "inet_interfaces":

            -
            postconf -e 'relayhost = 172.22.1.1'
            +
            postconf -e 'relayhost = 172.22.1.1'
             postconf -e "mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128"
             postconf -e "inet_interfaces = loopback-only"
             postconf -e "relay_transport = relay"
             postconf -e "default_transport = smtp"
            -
            +

            Now it is important to not have the same FQDN in myhostname as you use for your dockerized mailcow. Check your local (non-Docker) Postfix' main.cf for myhostname and set it to something different, for example local.my.fqdn.tld.

            "172.22.1.1" is the mailcow created network gateway in Docker. Relaying over this interface is necessary (instead of - for example - relaying directly over ${MAILCOW_HOSTNAME}) to relay over a known internal network.

            diff --git a/post_installation/firststeps-logging/index.html b/post_installation/firststeps-logging/index.html index 4880fe618..7ad887e90 100644 --- a/post_installation/firststeps-logging/index.html +++ b/post_installation/firststeps-logging/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2466,16 +2466,16 @@ the ability to read logs from the UI or ban suspicious clients with netfilter-ma

            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:

            -
            version: '2.1'
            +
            version: '2.1'
             services:
               postfix-mailcow: # or any other
                 logging:
                   driver: "gelf"
                   options:
                     gelf-address: "udp://graylog:12201"
            -
            +

            Another example for Syslog:

            -
            version: '2.1'
            +
            version: '2.1'
             services:
             
               postfix-mailcow: # or any other
            @@ -2506,10 +2506,10 @@ 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:

            -
            {
            +
            {
             ...
               "log-driver": "gelf",
               "log-opts": {
            @@ -2517,9 +2517,9 @@ local3.*        /var/log/mailcow.logs
               }
             ...
             }
            -
            +

            For Syslog:

            -
            {
            +
            {
             ...
               "log-driver": "syslog",
               "log-opts": {
            @@ -2527,7 +2527,7 @@ local3.*        /var/log/mailcow.logs
               }
             ...
             }
            -
            +

            Restart the Docker daemon and run docker-compose down && docker-compose up -d to recreate the containers with the new logging driver.


            diff --git a/post_installation/firststeps-rp/index.html b/post_installation/firststeps-rp/index.html index 81ea1ea6e..e9d0c189d 100644 --- a/post_installation/firststeps-rp/index.html +++ b/post_installation/firststeps-rp/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2467,11 +2467,11 @@

            You don't need to change the Nginx site that comes with mailcow: dockerized. mailcow: dockerized trusts the default gateway IP 172.22.1.1 as proxy.

            1. Make sure you change HTTP_BIND and HTTPS_BIND in mailcow.conf to a local address and set the ports accordingly, for example: -

            HTTP_BIND=127.0.0.1
            +
            HTTP_BIND=127.0.0.1
             HTTP_PORT=8080
             HTTPS_BIND=127.0.0.1
             HTTPS_PORT=8443
            -

            +

            This will also change the bindings inside the Nginx container! This is important, if you decide to use a proxy within Docker.

            IMPORTANT: Do not use port 8081, 9081 or 65510!

            Recreate affected containers by running docker-compose up -d.

            @@ -2500,56 +2500,56 @@ On many servers logrotate will reload the webserver daily anyway.

            2. Configure your local webserver as reverse proxy:

            Apache 2.4

            Required modules: -

            a2enmod rewrite proxy proxy_http headers ssl
            -

            +
            a2enmod rewrite proxy proxy_http headers ssl
            +

            Let's Encrypt will follow our rewrite, certificate requests in mailcow will work fine.

            Take care of highlighted lines.

            -
            <VirtualHost *:80>
            -  ServerName CHANGE_TO_MAILCOW_HOSTNAME
            -  ServerAlias autodiscover.*
            -  ServerAlias autoconfig.*
            -  RewriteEngine on
            +
            <VirtualHost *:80>
            +  ServerName CHANGE_TO_MAILCOW_HOSTNAME
            +  ServerAlias autodiscover.*
            +  ServerAlias autoconfig.*
            +  RewriteEngine on
             
            -  RewriteCond %{HTTPS} off
            -  RewriteRule ^/?(.*) https://%{HTTP_HOST}/$1 [R=301,L]
            +  RewriteCond %{HTTPS} off
            +  RewriteRule ^/?(.*) https://%{HTTP_HOST}/$1 [R=301,L]
             
            -  ProxyPass / http://127.0.0.1:8080/
            -  ProxyPassReverse / http://127.0.0.1:8080/
            -  ProxyPreserveHost On
            -  ProxyAddHeaders On
            -  RequestHeader set X-Forwarded-Proto "http"
            -</VirtualHost>
            -<VirtualHost *:443>
            -  ServerName CHANGE_TO_MAILCOW_HOSTNAME
            -  ServerAlias autodiscover.*
            -  ServerAlias autoconfig.*
            +  ProxyPass / http://127.0.0.1:8080/
            +  ProxyPassReverse / http://127.0.0.1:8080/
            +  ProxyPreserveHost On
            +  ProxyAddHeaders On
            +  RequestHeader set X-Forwarded-Proto "http"
            +</VirtualHost>
            +<VirtualHost *:443>
            +  ServerName CHANGE_TO_MAILCOW_HOSTNAME
            +  ServerAlias autodiscover.*
            +  ServerAlias autoconfig.*
             
            -  # You should proxy to a plain HTTP session to offload SSL processing
            -  ProxyPass /Microsoft-Server-ActiveSync http://127.0.0.1:8080/Microsoft-Server-ActiveSync connectiontimeout=4000
            -  ProxyPassReverse /Microsoft-Server-ActiveSync http://127.0.0.1:8080/Microsoft-Server-ActiveSync
            -  ProxyPass / http://127.0.0.1:8080/
            -  ProxyPassReverse / http://127.0.0.1:8080/
            -  ProxyPreserveHost On
            -  ProxyAddHeaders On
            -  RequestHeader set X-Forwarded-Proto "https"
            +  # You should proxy to a plain HTTP session to offload SSL processing
            +  ProxyPass /Microsoft-Server-ActiveSync http://127.0.0.1:8080/Microsoft-Server-ActiveSync connectiontimeout=4000
            +  ProxyPassReverse /Microsoft-Server-ActiveSync http://127.0.0.1:8080/Microsoft-Server-ActiveSync
            +  ProxyPass / http://127.0.0.1:8080/
            +  ProxyPassReverse / http://127.0.0.1:8080/
            +  ProxyPreserveHost On
            +  ProxyAddHeaders On
            +  RequestHeader set X-Forwarded-Proto "https"
             
            -  SSLCertificateFile MAILCOW_PATH/data/assets/ssl/cert.pem
            -  SSLCertificateKeyFile MAILCOW_PATH/data/assets/ssl/key.pem
            +  SSLCertificateFile MAILCOW_PATH/data/assets/ssl/cert.pem
            +  SSLCertificateKeyFile MAILCOW_PATH/data/assets/ssl/key.pem
             
            -  # If you plan to proxy to a HTTPS host:
            -  #SSLProxyEngine On
            +  # If you plan to proxy to a HTTPS host:
            +  #SSLProxyEngine On
             
            -  # If you plan to proxy to an untrusted HTTPS host:
            -  #SSLProxyVerify none
            -  #SSLProxyCheckPeerCN off
            -  #SSLProxyCheckPeerName off
            -  #SSLProxyCheckPeerExpire off
            -</VirtualHost>
            -
            + # If you plan to proxy to an untrusted HTTPS host: + #SSLProxyVerify none + #SSLProxyCheckPeerCN off + #SSLProxyCheckPeerName off + #SSLProxyCheckPeerExpire off +</VirtualHost> +

            Nginx

            Let's Encrypt will follow our rewrite, certificate requests will work fine.

            Take care of highlighted lines.

            -
            server {
            +
            server {
               listen 80 default_server;
               listen [::]:80 default_server;
               server_name CHANGE_TO_MAILCOW_HOSTNAME autodiscover.* autoconfig.*;
            @@ -2600,14 +2600,14 @@ server {
                 proxy_busy_buffers_size 512k;
               }
             }
            -
            +

            HAProxy (community supported)

            Warning

            This is an unsupported community contribution. Feel free to provide fixes.

            Important/Fixme: This example only forwards HTTPS traffic and does not use mailcows built-in ACME client.

            -
            frontend https-in
            +
            frontend https-in
               bind :::443 v4v6 ssl crt mailcow.pem
               default_backend mailcow
             
            @@ -2616,7 +2616,7 @@ backend mailcow
               http-request set-header X-Forwarded-Proto https if { ssl_fc }
               http-request set-header X-Forwarded-Proto http if !{ ssl_fc }
               server mailcow 127.0.0.1:8080 check
            -
            +

            Traefik v2 (community supported)

            Warning

            @@ -2627,50 +2627,50 @@ backend mailcow

            So, first of all, we are going to disable the acme-mailcow container since we'll use the certs that traefik will provide us. For this we'll have to set SKIP_LETS_ENCRYPT=y on our mailcow.conf, and run docker-compose up -d to apply the changes.

            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.

            -
            version: '2.1'
            +
            version: '2.1'
             
            -services:
            -    nginx-mailcow:
            -      networks:
            -        # add Traefik's network
            -        web:
            -      labels:
            -        - traefik.enable=true
            -        # Creates a router called "moo" for the container, and sets up a rule to link the container to certain rule,
            -        #   in this case, a Host rule with our MAILCOW_HOSTNAME var.
            -        - traefik.http.routers.moo.rule=Host(`${MAILCOW_HOSTNAME}`)
            -        # Enables tls over the router we created before.
            -        - traefik.http.routers.moo.tls=true
            -        # Specifies which kind of cert resolver we'll use, in this case le (Lets Encrypt).
            -        - 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=${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=websecure
            -        # Make sure traefik uses the web network, not the mailcowdockerized_mailcow-network
            -        - traefik.docker.network=web
            +services:
            +    nginx-mailcow:
            +      networks:
            +        # add Traefik's network
            +        web:
            +      labels:
            +        - traefik.enable=true
            +        # Creates a router called "moo" for the container, and sets up a rule to link the container to certain rule,
            +        #   in this case, a Host rule with our MAILCOW_HOSTNAME var.
            +        - traefik.http.routers.moo.rule=Host(`${MAILCOW_HOSTNAME}`)
            +        # Enables tls over the router we created before.
            +        - traefik.http.routers.moo.tls=true
            +        # Specifies which kind of cert resolver we'll use, in this case le (Lets Encrypt).
            +        - 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=${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=websecure
            +        # Make sure traefik uses the web network, not the mailcowdockerized_mailcow-network
            +        - traefik.docker.network=web
             
            -    certdumper:
            -        image: humenius/traefik-certs-dumper
            -        container_name: traefik_certdumper
            -        network_mode: none
            -        volumes:
            -          # mount the folder which contains Traefik's `acme.json' file
            -          #   in this case Traefik is started from its own docker-compose in ../traefik
            -          - ../traefik/data:/traefik:ro
            -          # mount mailcow's SSL folder
            -          - ./data/assets/ssl/:/output:rw
            -        restart: always
            -        environment:
            -          # only change this, if you're using another domain for mailcow's web frontend compared to the standard config
            -          - DOMAIN=${MAILCOW_HOSTNAME}
            +    certdumper:
            +        image: humenius/traefik-certs-dumper
            +        container_name: traefik_certdumper
            +        network_mode: none
            +        volumes:
            +          # mount the folder which contains Traefik's `acme.json' file
            +          #   in this case Traefik is started from its own docker-compose in ../traefik
            +          - ../traefik/data:/traefik:ro
            +          # mount mailcow's SSL folder
            +          - ./data/assets/ssl/:/output:rw
            +        restart: always
            +        environment:
            +          # only change this, if you're using another domain for mailcow's web frontend compared to the standard config
            +          - DOMAIN=${MAILCOW_HOSTNAME}
             
            -networks:
            -  web:
            -    external: true
            -
            +networks: + web: + external: true +

            Start the new containers with docker-compose up -d.

            Now, there's only one thing left to do, which is setup the certs so that the mail services can use them as well, since Traefik 2 uses an acme v2 format to save ALL the license from all the domains we have, we'll need to find a way to dump the certs, lucky we have this tiny container which grabs the acme.json file trough a volume, and a variable DOMAIN=example.org, and with these, the container will output the cert.pem and key.pem files, for this we'll simply run the traefik-certs-dumper container binding the /traefik volume to the folder where our acme.json is saved, bind the /output volume to our mailcow data/assets/ssl/ folder, and set up the DOMAIN=example.org variable to the domain we want the certs dumped from.

            This container will watch over the acme.json file for any changes, and regenerate the cert.pem and key.pem files directly into data/assets/ssl/ being the path binded to the container's /output path.

            @@ -2680,18 +2680,18 @@ For this we'll have to set SKIP_LETS_ENCRYPT=y on our mailcow

            Optional: Post-hook script for non-mailcow ACME clients

            Using a local certbot (or any other ACME client) requires to restart some containers, you can do this with a post-hook script. Make sure you change the paths accordingly: -

            #!/bin/bash
            +
            #!/bin/bash
             cp /etc/letsencrypt/live/my.domain.tld/fullchain.pem /opt/mailcow-dockerized/data/assets/ssl/cert.pem
             cp /etc/letsencrypt/live/my.domain.tld/privkey.pem /opt/mailcow-dockerized/data/assets/ssl/key.pem
             postfix_c=$(docker ps -qaf name=postfix-mailcow)
             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
            -
            +
            ADDITIONAL_SERVER_NAMES=webmail.domain.tld,other.example.tld
            +

            Run docker-compose up -d to apply.


            diff --git a/post_installation/firststeps-rspamd_ui/index.html b/post_installation/firststeps-rspamd_ui/index.html index 414e2208b..7306b6dbc 100644 --- a/post_installation/firststeps-rspamd_ui/index.html +++ b/post_installation/firststeps-rspamd_ui/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/post_installation/firststeps-snat/index.html b/post_installation/firststeps-snat/index.html index b51ddabb5..c85462620 100644 --- a/post_installation/firststeps-snat/index.html +++ b/post_installation/firststeps-snat/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,12 +2348,12 @@

            SNAT is used to change the source address of the packets sent by mailcow. 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:

            -
            # Use this IPv4 for outgoing connections (SNAT)
            +
            # Use this IPv4 for outgoing connections (SNAT)
             SNAT_TO_SOURCE=1.2.3.4
             
             # Use this IPv6 for outgoing connections (SNAT)
             SNAT6_TO_SOURCE=dead:beef
            -
            +

            Run docker-compose up -d.

            The values are read by netfilter-mailcow. netfilter-mailcow will make sure, the post-routing rules are on position 1 in the netfilter table. It does automatically delete and re-create them if they are found on another position than 1.

            Check the output of docker-compose logs --tail=200 netfilter-mailcow to ensure the SNAT settings have been applied.

            diff --git a/post_installation/firststeps-ssl/index.html b/post_installation/firststeps-ssl/index.html index cbb465ac4..d85d48555 100644 --- a/post_installation/firststeps-ssl/index.html +++ b/post_installation/firststeps-ssl/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2586,8 +2586,8 @@

            Additional domain names

            Edit "mailcow.conf" and add a parameter ADDITIONAL_SAN like this:

            Do not use quotes (") and do not use spaces between the names!

            -
            ADDITIONAL_SAN=smtp.*,cert1.example.com,cert2.example.org,whatever.*
            -
            +
            ADDITIONAL_SAN=smtp.*,cert1.example.com,cert2.example.org,whatever.*
            +

            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.

            @@ -2596,17 +2596,17 @@

            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
            -
            +
            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:

            -
            cd /opt/mailcow-dockerized
            +
            cd /opt/mailcow-dockerized
             touch data/assets/ssl/force_renew
             docker-compose restart acme-mailcow
             # Now check the logs for a renewal
             docker-compose logs --tail=200 -f acme-mailcow
            -
            +

            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 address. Due to using dynamic IPs for acme-mailcow, source NAT is not consistent over restarts.

            @@ -2653,35 +2653,35 @@ You should make sure these clients use the MAILCOW_HOSTNAME for sec

            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:

            -
            docker restart $(docker ps -qaf name=postfix-mailcow)
            +
            docker restart $(docker ps -qaf name=postfix-mailcow)
             docker restart $(docker ps -qaf name=nginx-mailcow)
             docker restart $(docker ps -qaf name=dovecot-mailcow)
            -
            +

            See Post-hook script for non-mailcow ACME clients for a full example script.

            Test against staging ACME directory

            Edit mailcow.conf and add LE_STAGING=y.

            Run docker-compose up -d to activate your changes.

            Custom directory URL

            Edit mailcow.conf and add the corresponding directory URL to the new variable DIRECTORY_URL:

            -
            DIRECTORY_URL=https://acme-custom-v9000.api.letsencrypt.org/directory
            -
            +
            DIRECTORY_URL=https://acme-custom-v9000.api.letsencrypt.org/directory
            +

            You cannot use LE_STAGING with DIRECTORY_URL. If both are set, only LE_STAGING is used.

            Run docker-compose up -d to activate your changes.

            Check your configuration

            Run docker-compose logs acme-mailcow to find out why a validation fails.

            To check if nginx serves the correct certificate, simply use a browser of your choice and check the displayed certificate.

            To check the certificate served by Postfix, Dovecot and Nginx we will use openssl:

            -
            # Connect via SMTP (587)
            +
            # Connect via SMTP (587)
             echo "Q" | openssl s_client -starttls smtp -crlf -connect mx.mailcow.email:587
             # Connect via IMAP (143)
             echo "Q" | openssl s_client -starttls imap -showcerts -connect mx.mailcow.email:143
             # Connect via HTTPS (443)
             echo "Q" | openssl s_client -connect mx.mailcow.email:443
            -
            +

            To validate the expiry dates as returned by openssl against MAILCOW_HOSTNAME, you are able to use our helper script:

            -
            cd /opt/mailcow-dockerized
            +
            cd /opt/mailcow-dockerized
             bash helper-scripts/expiry-dates.sh
            -
            +

            diff --git a/post_installation/firststeps-sync_jobs_migration/index.html b/post_installation/firststeps-sync_jobs_migration/index.html index 05feec65a..4d25d76a7 100644 --- a/post_installation/firststeps-sync_jobs_migration/index.html +++ b/post_installation/firststeps-sync_jobs_migration/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/prerequisite/prerequisite-dns/index.html b/prerequisite/prerequisite-dns/index.html index f70e833b3..191afbe52 100644 --- a/prerequisite/prerequisite-dns/index.html +++ b/prerequisite/prerequisite-dns/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2548,28 +2548,28 @@

            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

            This example shows you a set of records for one domain managed by mailcow. Each domain that is added to mailcow needs at least this set of records to function correctly.

            -
            # Name              Type       Value
            +
            # Name              Type       Value
             mail                IN A       1.2.3.4
             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

            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 for further reading.

            -
            # Name              Type       Value
            +
            # 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 for further reading.

            -
            # Name              Type       Value
            +
            # 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 (check).

            -
            # Name              Type       Value
            +
            # Name              Type       Value
             _dmarc              IN TXT     "v=DMARC1; p=reject; rua=mailto:mailauth-reports@example.org"
            -
            +

            The advanced DNS configuration

            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.

            -
            # Name              Type       Priority Weight Port    Value
            +
            # 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/"
            @@ -2582,7 +2582,7 @@ _pop3s._tcp         IN SRV     0        1      995      mail.example.org. (your
             _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

            Here are some tools you can use to verify your DNS configuration:

              @@ -2613,7 +2613,7 @@ _submission._tcp IN SRV 0 1 587 mail.example.org. (your

              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:

              -
              ==========================================================
              +
              ==========================================================
               Summary of Results
               ==========================================================
               SPF check:          pass
              @@ -2626,7 +2626,7 @@ SpamAssassin check: ham
               Details:
               ==========================================================
               ....
              -
              +

              The full report will contain more technical details.

              Fully Qualified Domain Name (FQDN)

              diff --git a/prerequisite/prerequisite-system/index.html b/prerequisite/prerequisite-system/index.html index 5c863e66f..e016a8b8f 100644 --- a/prerequisite/prerequisite-system/index.html +++ b/prerequisite/prerequisite-system/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2569,10 +2569,10 @@

              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'
               # or:
               netstat -tulpn | grep -E -w '25|80|110|143|443|465|587|993|995|4190'
              -
              +

              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.donnex.net) or this (unrouted.io) guide for information about how to use iptables-persistent with the DOCKER-USER chain. @@ -2665,34 +2665,34 @@ As mailcow runs dockerized, INPUT rules have no effect on restricting access to

              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:       ---
              +
              SRC-IP:       ---
               DST IP:       ---
               SRC Port:    ---
               DST Port:    1024-65535
               Protocol:    tcp
               TCP flags:   ack
               Action:      Accept
              -

              +

              For UDP -

              SRC-IP:       ---
              +
              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
              -

              +
              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:

              -
              $ timedatectl status
              +
              $ timedatectl status
                     Local time: Sat 2017-05-06 02:12:33 CEST
                 Universal time: Sat 2017-05-06 00:12:33 UTC
                       RTC time: Sat 2017-05-06 00:12:32
              @@ -2707,22 +2707,22 @@ NTP synchronized: yes
                Next DST change: DST ends (the clock jumps one hour backwards) at
                                 Sun 2017-10-29 02:59:59 CEST
                                 Sun 2017-10-29 02:00:00 CET
              -
              +

              The lines NTP enabled: yes and NTP synchronized: yes indicate whether you have NTP enabled and if it's synchronized.

              To enable NTP you need to run the command timedatectl set-ntp true. You also need to edit your /etc/systemd/timesyncd.conf:

              -
              # vim /etc/systemd/timesyncd.conf
              +
              # vim /etc/systemd/timesyncd.conf
               [Time]
               NTP=0.pool.ntp.org 1.pool.ntp.org 2.pool.ntp.org 3.pool.ntp.org
              -
              +

              Hetzner Cloud (and probably others)

              Check /etc/network/interfaces.d/50-cloud-init.cfg and change the IPv6 interface from eth0:0 to eth0:

              -
              # Wrong:
              +
              # Wrong:
               auto eth0:0
               iface eth0:0 inet6 static
               # Right:
               auto eth0
               iface eth0 inet6 static
              -
              +

              Reboot or restart the interface. You may want to disable cloud-init network changes.

              MTU

              diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 68b651cb0fb683308775f47cbbb917fe2bfa25df..64f0281250e0bfac10da71bc9e71189907fbbcdb 100644 GIT binary patch delta 15 WcmZn>Y!PIW@8;n6ziT5~9R~m;f&}3J delta 15 WcmZn>Y!PIW@8;kL+_{mhjspN7X#_F= diff --git a/third_party/third_party-borgmatic/index.html b/third_party/third_party-borgmatic/index.html index 068c371b7..ebff48b37 100644 --- a/third_party/third_party-borgmatic/index.html +++ b/third_party/third_party-borgmatic/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2687,43 +2687,43 @@ This guide only covers the basics.

              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:

              -
              version: '2.1'
              +
              version: '2.1'
               
              -services:
              -  borgmatic-mailcow:
              -    image: b3vis/borgmatic
              -    hostname: mailcow
              -    restart: always
              -    dns: ${IPV4_NETWORK:-172.22.1}.254
              -    volumes:
              -      - vmail-vol-1:/mnt/source/vmail:ro
              -      - crypt-vol-1:/mnt/source/crypt:ro
              -      - redis-vol-1:/mnt/source/redis:ro,z
              -      - rspamd-vol-1:/mnt/source/rspamd:ro,z
              -      - postfix-vol-1:/mnt/source/postfix:ro,z
              -      - mysql-socket-vol-1:/var/run/mysqld/:z
              -      - borg-config-vol-1:/root/.config/borg:Z
              -      - borg-cache-vol-1:/root/.cache/borg:Z
              -      - ./data/conf/borgmatic/etc:/etc/borgmatic.d:Z
              -      - ./data/conf/borgmatic/ssh:/root/.ssh:Z
              -    environment:
              -      - TZ=${TZ}
              -      - BORG_PASSPHRASE=YouBetterPutSomethingRealGoodHere
              -    networks:
              -      mailcow-network:
              -        aliases:
              -          - borgmatic
              +services:
              +  borgmatic-mailcow:
              +    image: b3vis/borgmatic
              +    hostname: mailcow
              +    restart: always
              +    dns: ${IPV4_NETWORK:-172.22.1}.254
              +    volumes:
              +      - vmail-vol-1:/mnt/source/vmail:ro
              +      - crypt-vol-1:/mnt/source/crypt:ro
              +      - redis-vol-1:/mnt/source/redis:ro,z
              +      - rspamd-vol-1:/mnt/source/rspamd:ro,z
              +      - postfix-vol-1:/mnt/source/postfix:ro,z
              +      - mysql-socket-vol-1:/var/run/mysqld/:z
              +      - borg-config-vol-1:/root/.config/borg:Z
              +      - borg-cache-vol-1:/root/.cache/borg:Z
              +      - ./data/conf/borgmatic/etc:/etc/borgmatic.d:Z
              +      - ./data/conf/borgmatic/ssh:/root/.ssh:Z
              +    environment:
              +      - TZ=${TZ}
              +      - BORG_PASSPHRASE=YouBetterPutSomethingRealGoodHere
              +    networks:
              +      mailcow-network:
              +        aliases:
              +          - borgmatic
               
              -volumes:
              -  borg-cache-vol-1:
              -  borg-config-vol-1:
              -
              +volumes: + borg-cache-vol-1: + borg-config-vol-1: +

              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.

              -
              source mailcow.conf
              +
              source mailcow.conf
               cat <<EOF > data/conf/borgmatic/etc/config.yaml
               location:
                   source_directories:
              @@ -2749,7 +2749,7 @@ cat <<EOF > data/conf/borgmatic/etc/config.yaml
                         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 @@ -2765,8 +2765,8 @@ container. The container defines a volume called /mnt/borg-repository

              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
              -
              +
              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

              @@ -2775,14 +2775,14 @@ usual id_rsa, id_ed25519 or similar to be in this dire 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:

              -
              docker-compose up -d
              -
              +
              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:

              -
              docker-compose exec borgmatic-mailcow borgmatic init --encryption repokey-blake2
              -
              +
              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.

              @@ -2793,8 +2793,8 @@ 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:

              -
              docker-compose restart borgmatic-mailcow
              -
              +
              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.

              @@ -2814,8 +2814,8 @@ 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:

              -
              docker-compose exec borgmatic-mailcow borgmatic extract --path mnt/source --archive latest
              -
              +
              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)

              Restore MySQL

              @@ -2825,30 +2825,30 @@ Then you can use the following command to restore the maildir from a backup:

              intend to recover the mailcow database from a backup.

              To restore the MySQL database from the latest archive use this command:

              -
              docker-compose exec borgmatic-mailcow borgmatic restore --archive latest
              -
              +
              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)

              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:

              -
              docker-compose down && docker-compose up -d
              -
              +
              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)

              -
              docker-compose exec borgmatic-mailcow borgmatic -v 2
              -
              +
              docker-compose exec borgmatic-mailcow borgmatic -v 2
              +

              Listing all available archives

              -
              docker-compose exec borgmatic-mailcow borgmatic list
              -
              +
              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:

              -
              docker-compose exec borgmatic-mailcow borg break-lock user@rsync.net:mailcow
              -
              +
              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

              @@ -2857,8 +2857,8 @@ key files are generated when you initialize the repository. The repokey

              Note that in either case you also must have the passphrase to decrypt any archives.

              To fetch the keyfile run:

              -
              docker-compose exec borgmatic-mailcow borg key export --paper user@rsync.net:mailcow
              -
              +
              docker-compose exec borgmatic-mailcow borg key export --paper user@rsync.net:mailcow
              +

              Where user@rsync.net:mailcow is the URI to your repository.


              diff --git a/third_party/third_party-exchange_onprem/index.html b/third_party/third_party-exchange_onprem/index.html index fc477ea14..a8157872e 100644 --- a/third_party/third_party-exchange_onprem/index.html +++ b/third_party/third_party-exchange_onprem/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/third_party/third_party-gitea/index.html b/third_party/third_party-gitea/index.html index cc16f34be..5480ca6ff 100644 --- a/third_party/third_party-gitea/index.html +++ b/third_party/third_party-gitea/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2347,7 +2347,7 @@

              With Gitea' ability to authenticate over SMTP it is trivial to integrate it with mailcow. Few changes are needed:

              1. Open docker-compose.override.yml and add gitea:

              -
              version: '2.1'
              +
              version: '2.1'
               services:
               
                       gitea-mailcow:
              @@ -2360,28 +2360,28 @@ services:
                                       - gitea
                           ports:
                               - "${GITEA_SSH_PORT:-127.0.0.1:4000}:22"
              -
              +

              2. Create data/conf/nginx/site.gitea.custom, add: -

              location /gitea/ {
              +
              location /gitea/ {
                       proxy_pass http://gitea:3000/;
               }
              -

              +

              3. Open mailcow.conf and define the binding you want gitea to use for SSH. Example:

              -
              GITEA_SSH_PORT=127.0.0.1:4000
              -
              +
              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. 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. 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. 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 for their meaning and other possible values.

              -
              [server]
              +
              [server]
               SSH_LISTEN_PORT = 22
               # For GITEA_SSH_PORT=127.0.0.1:4000 in mailcow.conf, set:
               SSH_DOMAIN = 127.0.0.1
               SSH_PORT = 4000
               # For MAILCOW_HOSTNAME=mx.example.org in mailcow.conf (and default ports for HTTPS), set:
               ROOT_URL = https://mx.example.org/gitea/
              -
              +

              10. Restart gitea with docker-compose restart gitea-mailcow. Your users should be able to login with mailcow managed accounts.


              diff --git a/third_party/third_party-gogs/index.html b/third_party/third_party-gogs/index.html index 4060a2509..8527c9c57 100644 --- a/third_party/third_party-gogs/index.html +++ b/third_party/third_party-gogs/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2347,7 +2347,7 @@

              With Gogs' ability to authenticate over SMTP it is trivial to integrate it with mailcow. Few changes are needed:

              1. Open docker-compose.override.yml and add Gogs:

              -
              version: '2.1'
              +
              version: '2.1'
               services:
               
                   gogs-mailcow:
              @@ -2360,27 +2360,27 @@ services:
                           - gogs
                     ports:
                       - "${GOGS_SSH_PORT:-127.0.0.1:4000}:22"
              -
              +

              2. Create data/conf/nginx/site.gogs.custom, add: -

              location /gogs/ {
              +
              location /gogs/ {
                   proxy_pass http://gogs:3000/;
               }
              -

              +

              3. Open mailcow.conf and define the binding you want Gogs to use for SSH. Example:

              -
              GOGS_SSH_PORT=127.0.0.1:4000
              -
              +
              GOGS_SSH_PORT=127.0.0.1:4000
              +

              5. Run docker-compose up -d to bring up the Gogs container and run docker-compose restart nginx-mailcow afterwards.

              6. Open http://${MAILCOW_HOSTNAME}/gogs/, for example http://mx.example.org/gogs/. 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.

              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).

              8. Create data/gogs/gogs/conf/app.ini and set following values. You can consult Gogs cheat sheet for their meaning and other possible values.

              -
              [server]
              +
              [server]
               SSH_LISTEN_PORT = 22
               # For GOGS_SSH_PORT=127.0.0.1:4000 in mailcow.conf, set:
               SSH_DOMAIN = 127.0.0.1
               SSH_PORT = 4000
               # For MAILCOW_HOSTNAME=mx.example.org in mailcow.conf (and default ports for HTTPS), set:
               ROOT_URL = https://mx.example.org/gogs/
              -
              +

              9. Restart Gogs with docker-compose restart gogs-mailcow. Your users should be able to login with mailcow managed accounts.


              diff --git a/third_party/third_party-mailman3/index.html b/third_party/third_party-mailman3/index.html index 5957e6df3..b0499bb6c 100644 --- a/third_party/third_party-mailman3/index.html +++ b/third_party/third_party-mailman3/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2780,15 +2780,15 @@

              DNS setup

              Most of the configuration is covered by mailcows DNS setup. After finishing this setup add another subdomain for Mailman, e.g. lists.example.org that points to the same server:

              -
              # Name    Type       Value
              +
              # Name    Type       Value
               lists     IN A       1.2.3.4
               lists     IN AAAA    dead:beef
              -
              +

              Install Apache as a reverse proxy

              Install Apache, e.g. with this guide from Digital Ocean: How To Install the Apache Web Server on Ubuntu 20.04.

              Activate certain Apache modules (as root or sudo):

              -
              a2enmod rewrite proxy proxy_http headers ssl wsgi proxy_uwsgi http2
              -
              +
              a2enmod rewrite proxy proxy_http headers ssl wsgi proxy_uwsgi http2
              +

              Maybe you have to install further packages to get these modules. This PPA by Ondřej Surý may help you.

              vHost configuration

              Copy the mailcow.conf and the mailman.conf in the Apache conf folder sites-available (e.g. under /etc/apache2/sites-available).

              @@ -2806,18 +2806,18 @@ lists IN AAAA dead:beef
            • https://mxtoolbox.com/SuperTool.aspx?action=aaaa%3aMAILMAN_DOMAIN

            Install certbot (as root or sudo):

            -
            apt install certbot
            -
            +
            apt install certbot
            +

            Get the desired certificates (as root or sudo):

            -
            certbot certonly -d mailcow_HOSTNAME
            +
            certbot certonly -d mailcow_HOSTNAME
             certbot certonly -d MAILMAN_DOMAIN
            -
            +

            Install mailcow with Mailman integration

            Install mailcow

            Follow the mailcow installation. Omit step 5 and do not pull and up with docker-compose!

            Configure mailcow

            This is also Step 4 in the official mailcow installation (nano mailcow.conf). So change to your needs and alter the following variables:

            -
            HTTP_PORT=18080            # don't use 8080 as mailman needs it
            +
            HTTP_PORT=18080            # don't use 8080 as mailman needs it
             HTTP_BIND=127.0.0.1        #
             HTTPS_PORT=18443           # you may use 8443
             HTTPS_BIND=127.0.0.1       #
            @@ -2826,10 +2826,10 @@ SKIP_LETS_ENCRYPT=y        # reverse proxy will do the SSL termination
             
             SNAT_TO_SOURCE=1.2.3.4     # change this to your IPv4
             SNAT6_TO_SOURCE=dead:beef  # change this to your global IPv6
            -
            +

            Add Mailman integration

            Create the file /opt/mailcow-dockerized/docker-compose.override.yml (e.g. with nano) and add the following lines:

            -

            version: '2.1'
            +

            version: '2.1'
             
             services:
               postfix-mailcow:
            @@ -2841,10 +2841,10 @@ services:
             networks:
               docker-mailman_mailman:
                 external: true
            -
            +
            The additional volume is used by Mailman to generate additional config files for mailcow postfix. The external network is build and used by Mailman. mailcow needs it to deliver incoming list mails to Mailman.

            Create the file /opt/mailcow-dockerized/data/conf/postfix/extra.cf (e.g. with nano) and add the following lines:

            -

            # mailman
            +

            # mailman
             
             recipient_delimiter = +
             unknown_local_recipient_reject_code = 550
            @@ -2869,7 +2869,7 @@ relay_domains =
             relay_recipient_maps =
               proxy:mysql:/opt/postfix/conf/sql/mysql_relay_recipient_maps.cf,
               regexp:/opt/mailman/core/var/data/postfix_lmtp
            -
            +
            As we overwrite mailcow postfix configuration here, this step may break your normal mail transports. Check the original configuration files if anything changed.

            SSL certificates

            As we proxying mailcow, we need to copy the SSL certificates into the mailcow file structure. This task will do the script renew-ssl.sh for us:

            @@ -2880,26 +2880,26 @@ As we overwrite mailcow postfix configuration here, this step may break
          • Do not run it yet, as we first need Mailman

          You have to create a cronjob, so that new certificates will be copied. Execute as root or sudo:

          -
          crontab -e
          -
          +
          crontab -e
          +

          To run the script every day at 5am, add:

          -
          0   5  *   *   *     /opt/mailcow-dockerized/renew-ssl.sh
          -
          +
          0   5  *   *   *     /opt/mailcow-dockerized/renew-ssl.sh
          +

          Install Mailman

          Basicly follow the instructions at docker-mailman. As they are a lot, here is in a nuthshell what to do:

          As root or sudo:

          -
          cd /opt
          +
          cd /opt
           mkdir -p mailman/core
           mkdir -p mailman/web
           git clone https://github.com/maxking/docker-mailman
           cd docker-mailman
          -
          +

          Configure Mailman

          Create a long key for Hyperkitty, e.g. with the linux command cat /dev/urandom | tr -dc a-zA-Z0-9 | head -c30; echo. Save this key for a moment as HYPERKITTY_KEY.

          Create a long password for the database, e.g. with the linux command cat /dev/urandom | tr -dc a-zA-Z0-9 | head -c30; echo. Save this password for a moment as DBPASS.

          Create a long key for Django, e.g. with the linux command cat /dev/urandom | tr -dc a-zA-Z0-9 | head -c30; echo. Save this key for a moment as DJANGO_KEY.

          Create the file /opt/docker-mailman/docker-compose.override.yaml and replace HYPERKITTY_KEY, DBPASS and DJANGO_KEY with the generated values:

          -
          version: '2'
          +
          version: '2'
           
           services:
             mailman-core:
          @@ -2928,17 +2928,17 @@ services:
               environment:
               - POSTGRES_PASSWORD=DBPASS
               restart: always
          -
          +

          At mailman-web fill in correct values for SERVE_FROM_DOMAIN (e.g. lists.example.org), MAILMAN_ADMIN_USER and MAILMAN_ADMIN_EMAIL. You need the admin credentials to log into the web interface (Pistorius). For setting the password for the first time use the Forgot password function in the web interface.

          About other configuration options read Mailman-web and Mailman-core documentation.

          Configure Mailman core and Mailman web

          Create the file /opt/mailman/core/mailman-extra.cfg with the following content. mailman@example.org should be pointing to a valid mail box or redirection.

          -
          [mailman]
          +
          [mailman]
           default_language: de
           site_owner: mailman@example.org
          -
          +

          Create the file /opt/mailman/web/settings_local.py with the following content. mailman@example.org should be pointing to a valid mail box or redirection.

          -

          # locale
          +

          # locale
           LANGUAGE_CODE = 'de-de'
           
           # disable social authentication
          @@ -2948,11 +2948,11 @@ SOCIALACCOUNT_PROVIDERS = {}
           DEFAULT_FROM_EMAIL = 'mailman@example.org'
           
           DEBUG = False
          -
          +
          You can change LANGUAGE_CODE and SOCIALACCOUNT_PROVIDERS to your needs. At the moment SOCIALACCOUNT_PROVIDERS has no effect, see issue #2.

          🏃 Run

          Run (as root or sudo)

          -
          a2ensite mailcow.conf
          +
          a2ensite mailcow.conf
           a2ensite mailman.conf
           systemctl restart apache2
           
          @@ -2963,14 +2963,14 @@ docker-compose up -d
           cd /opt/mailcow-dockerized/
           docker-compose pull
           ./renew-ssl.sh
          -
          +

          Wait a few minutes! The containers have to create there databases and config files. This can last up to 1 minute and more.

          Remarks

          New lists aren't recognized by postfix instantly

          When you create a new list and try to immediately send an e-mail, postfix responses with User doesn't exist, because postfix won't deliver it to Mailman yet. The configuration at /opt/mailman/core/var/data/postfix_lmtp is not instantly updated. If you need the list instantly, restart postifx manually:

          -
          cd /opt/mailcow-dockerized
          +
          cd /opt/mailcow-dockerized
           docker-compose restart postfix-mailcow
          -
          +

          Update

          mailcow has it's own update script in /opt/mailcow-dockerized/update.sh, see the docs.

          For Mailman just fetch the newest version from the github repository.

          diff --git a/third_party/third_party-mailpiler_integration/index.html b/third_party/third_party-mailpiler_integration/index.html index b46200c8f..713eac413 100644 --- a/third_party/third_party-mailpiler_integration/index.html +++ b/third_party/third_party-mailpiler_integration/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2456,11 +2456,11 @@

          The problem to solve

          mailpiler offers the authentication based on IMAP, for example:

          -
          $config['ENABLE_IMAP_AUTH'] = 1;
          +
          $config['ENABLE_IMAP_AUTH'] = 1;
           $config['IMAP_HOST'] = 'mail.example.com';
           $config['IMAP_PORT'] =  993;
           $config['IMAP_SSL'] = true;
          -
          +
          • So when you log in using patrik@example.com, you will only see delivered emails sent from or to this specific email address.
          • When additional aliases are defined in mailcow, like team@example.com, you won't see emails sent to or from this email address even the fact you're a recipient of mails sent to this alias address.
          • @@ -2487,19 +2487,19 @@
            1. Set the custom query function of mailpiler and append this to /usr/local/etc/piler/config-site.php:

              -
              $config['MAILCOW_API_KEY'] = 'YOUR_READONLY_API_KEY';
              +
              $config['MAILCOW_API_KEY'] = 'YOUR_READONLY_API_KEY';
               $config['MAILCOW_SET_REALNAME'] = true; // when not specified, then default is false
               $config['CUSTOM_EMAIL_QUERY_FUNCTION'] = 'query_mailcow_for_email_access';
               include('auth-mailcow.php');
              -
              +

              You can also change the mailcow hostname, if required: -

              $config['MAILCOW_HOST'] = 'mail.domain.tld'; // defaults to $config['IMAP_HOST']
              -

              +
              $config['MAILCOW_HOST'] = 'mail.domain.tld'; // defaults to $config['IMAP_HOST']
              +

            2. Download the PHP file with the functions from the GitHub repo:

              -
              curl -o /usr/local/etc/piler/auth-mailcow.php https://raw.githubusercontent.com/patschi/mailpiler-mailcow-integration/master/auth-mailcow.php
              -
              +
              curl -o /usr/local/etc/piler/auth-mailcow.php https://raw.githubusercontent.com/patschi/mailpiler-mailcow-integration/master/auth-mailcow.php
              +
            3. Done!

              diff --git a/third_party/third_party-nextcloud/index.html b/third_party/third_party-nextcloud/index.html index e02263d61..dbb723b75 100644 --- a/third_party/third_party-nextcloud/index.html +++ b/third_party/third_party-nextcloud/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2457,14 +2457,14 @@

              In order for mailcow to generate a a certificate for the nextcloud domain you need to add "nextcloud.domain.tld" to ADDITIONAL_SAN in mailcow.conf and run docker-compose up -d to apply. For more informaton refer to: Advanced SSL.

              Background jobs

              To use the recommended setting (cron) to execute the background jobs following lines need to be added to the docker-compose.override.yml:

              -
              version: '2.1'
              +
              version: '2.1'
               services:
                 php-fpm-mailcow:
                   labels:
                     ofelia.enabled: "true"
                     ofelia.job-exec.nextcloud-cron.schedule: "@every 5m"
                     ofelia.job-exec.nextcloud-cron.command: "su www-data -s /bin/bash -c \"/usr/local/bin/php -f /web/nextcloud/cron.php\""
              -
              +

              After adding these lines the docker-compose up -d command must be executed to update the docker image and also the docker scheduler image must be restarted to pick up the new job definition by executing docker-compose restart ofelia-mailcow. To check if the job was successfully picked up by ofelia the command docker-compose logs ofelia-mailcow will contain a line similar to New job registered "nextcloud-cron" - ....

              @@ -2516,14 +2516,14 @@ services:

              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_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): -

              INSERT INTO nc_sociallogin_connect (uid, identifier) SELECT DISTINCT uid, CONCAT("Mailcow-", uid) FROM nc_users;
              -

              +
              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. @@ -2533,13 +2533,13 @@ It shows which commands have to be executed, these have to be placed in the php-


              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' =>
              +
              '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/third_party/third_party-portainer/index.html b/third_party/third_party-portainer/index.html index 150640eb5..7e2d9c827 100644 --- a/third_party/third_party-portainer/index.html +++ b/third_party/third_party-portainer/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2347,7 +2347,7 @@

              In order to enable Portainer, the docker-compose.yml and site.conf for Nginx must be modified.

              1. Create a new file docker-compose.override.yml in the mailcow-dockerized root folder and insert the following configuration -

              version: '2.1'
              +
              version: '2.1'
               services:
                   portainer-mailcow:
                     image: portainer/portainer-ce
              @@ -2362,9 +2362,9 @@ services:
                       mailcow-network:
                         aliases:
                           - portainer
              -
              +
              2a. Create data/conf/nginx/portainer.conf: -
              upstream portainer {
              +
              upstream portainer {
                 server portainer-mailcow:9000;
               }
               
              @@ -2372,9 +2372,9 @@ map $http_upgrade $connection_upgrade {
                 default upgrade;
                 '' close;
               }
              -

              +

              2b. Insert a new location to the default mailcow site by creating the file data/conf/nginx/site.portainer.custom: -

                location /portainer/ {
              +
                location /portainer/ {
                   proxy_http_version 1.1;
                   proxy_set_header Host              $http_host;   # required for docker client's sake
                   proxy_set_header X-Real-IP         $remote_addr; # pass on real client's IP
              @@ -2393,10 +2393,10 @@ map $http_upgrade $connection_upgrade {
                   proxy_set_header Connection $connection_upgrade;
                   proxy_pass http://portainer/api/websocket/;
                 }
              -

              +

              3. Apply your changes: -

              docker-compose up -d && docker-compose restart nginx-mailcow
              -

              +
              docker-compose up -d && docker-compose restart nginx-mailcow
              +

              Now you can simply navigate to https://${MAILCOW_HOSTNAME}/portainer/ to view your Portainer container monitoring page. You’ll then be prompted to specify a new password for the admin account. After specifying your password, you’ll then be able to connect to the Portainer UI.


              diff --git a/third_party/third_party-roundcube/index.html b/third_party/third_party-roundcube/index.html index 187fcb5e9..7b685ce8a 100644 --- a/third_party/third_party-roundcube/index.html +++ b/third_party/third_party-roundcube/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2466,7 +2466,7 @@

              Installing Roundcube

              Download Roundcube 1.5.x to the web htdocs directory and extract it (here rc/): -

              # Check for a newer release!
              +
              # Check for a newer release!
               cd data/web
               wget -O - https://github.com/roundcube/roundcubemail/releases/download/1.5.2/roundcubemail-1.5.2-complete.tar.gz | tar xfvz -
               
              @@ -2478,17 +2478,17 @@ chown -R root: rc/
               
               # Fix Allow remote resources (https://github.com/roundcube/roundcubemail/issues/8170) should not be required in 1.6
               sed -i "s/\$prefix = '\.\/';/\$prefix = preg_replace\('\/\[\?\&]\.\*\$\/', '', \$_SERVER\['REQUEST_URI'] \?\? ''\) \?: '\.\/';/g" rc/program/include/rcmail.php
              -

              +

              If you need spell check features, create a file data/hooks/phpfpm/aspell.sh with the following content, then chmod +x data/hooks/phpfpm/aspell.sh. This installs a local spell check engine. Note, most modern web browsers have built in spell check, so you may not want/need this. -

              #!/bin/bash
              +
              #!/bin/bash
               apk update
               apk add aspell-en # or any other language
              -

              +

              Create a file data/web/rc/config/config.inc.php with the following content. - Change the des_key parameter to a random value. It is used to temporarily store your IMAP password. - The db_prefix is optional but recommended. - If you didn't install spell check in the above step, remove spellcheck_engine parameter and replace it with $config['enable_spellcheck'] = false;. -

              <?php
              +
              <?php
               error_reporting(0);
               if (!file_exists('/tmp/mime.types')) {
               file_put_contents("/tmp/mime.types", fopen("http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types", 'r'));
              @@ -2520,13 +2520,13 @@ $config['smtp_conn_options'] = array(
                 'ssl' => array('verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true)
               );
               $config['db_prefix'] = 'mailcow_rc1';
              -

              +

              Point your browser to https://myserver/rc/installer and follow the instructions. Initialize the database and leave the installer.

              Delete the directory data/web/rc/installer after a successful installation!

              Configure ManageSieve filtering

              Open data/web/rc/plugins/managesieve/config.inc.php and change the following parameters (or add them at the bottom of that file): -

              $config['managesieve_port'] = 4190;
              +
              $config['managesieve_port'] = 4190;
               $config['managesieve_host'] = 'tls://dovecot';
               $config['managesieve_conn_options'] = array(
                 'ssl' => array('verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true)
              @@ -2536,37 +2536,37 @@ $config['managesieve_conn_options'] = array(
               // 1 - add Vacation section,
               // 2 - add Vacation section, but hide Filters section
               $config['managesieve_vacation'] = 1;
              -

              +

              Enable change password function in Roundcube

              Open data/web/rc/config/config.inc.php and enable the password plugin:

              -
              ...
              +
              ...
               $config['plugins'] = array(
                   'archive',
                   'password',
               );
               ...
              -
              +

              Open data/web/rc/plugins/password/password.php, search for case 'ssha': and add above:

              -
                      case 'ssha256':
              +
                      case 'ssha256':
                           $salt = rcube_utils::random_bytes(8);
                           $crypted = base64_encode( hash('sha256', $password . $salt, TRUE ) . $salt );
                           $prefix  = '{SSHA256}';
                           break;
              -
              +

              Open data/web/rc/plugins/password/config.inc.php and change the following parameters (or add them at the bottom of that file):

              -
              $config['password_driver'] = 'sql';
              +
              $config['password_driver'] = 'sql';
               $config['password_algorithm'] = 'ssha256';
               $config['password_algorithm_prefix'] = '{SSHA256}';
               $config['password_query'] = "UPDATE mailbox SET password = %P WHERE username = %u";
              -
              +

              Integrate CardDAV addressbooks in Roundcube

              Download the latest release of RCMCardDAV to the Roundcube plugin directory and extract it (here rc/plugins): -

              cd data/web/rc/plugins
              +
              cd data/web/rc/plugins
               wget -O - https://github.com/mstilkerich/rcmcarddav/releases/download/v4.3.0/carddav-v4.3.0.tar.gz  | tar xfvz -
               chown -R root: carddav/
              -

              +

              Copy the file config.inc.php.dist to config.inc.php (here in rc/plugins/carddav) and append the following preset to the end of the file - don't forget to replace mx.example.org with your own hostname: -

              $prefs['SOGo'] = array(
              +
              $prefs['SOGo'] = array(
                   'name'         =>  'SOGo',
                   'username'     =>  '%u',
                   'password'     =>  '%p',
              @@ -2579,7 +2579,7 @@ chown -R root: carddav/
                   'fixed'        =>  array( 'active', 'name', 'username', 'password', 'refresh_time' ),
                   'hide'        =>  false,
               );
              -
              +
              Please note, that this preset only integrates the default addressbook (the one that's named "Personal Address Book" and can't be deleted). Additional addressbooks are currently not automatically detected but can be manually added within the roundecube settings.

              Enable the plugin by adding carddav to $config['plugins'] in rc/config/config.inc.php.

              If you want to remove the default addressbooks (stored in the Roundcube database), so that only the CardDAV addressbooks are accessible, append $config['address_book_type'] = ''; to the config file data/web/rc/config/config.inc.php.

              @@ -2587,7 +2587,7 @@ Please note, that this preset only integrates the default addressbook (the one t

              Optionally, you can add Roundcube's link to the mailcow Apps list. To do this, open or create data/web/inc/vars.local.inc.php and add the following code-block:

              NOTE: Don't forget to add the <?php delimiter on the first line

              -
              ...
              +
              ...
               $MAILCOW_APPS = array(
                 array(
                   'name' => 'SOGo',
              @@ -2599,10 +2599,10 @@ $MAILCOW_APPS = array(
                  )
               );
               ...
              -
              +

              Upgrading Roundcube

              Upgrading Roundcube is rather simple, go to the Github releases page for Roundcube and get the link for the "complete.tar.gz" file for the wanted release. Then follow the below commands and change the URL and Roundcube folder name if needed.

              -
              # Enter a bash session of the mailcow PHP container
              +
              # Enter a bash session of the mailcow PHP container
               docker exec -it mailcowdockerized_php-fpm-mailcow_1 bash
               
               # Install required upgrade dependency, then upgrade Roundcube to wanted release
              @@ -2620,42 +2620,42 @@ rm -rf roundcube*
               
               # Fix Allow remote resources (https://github.com/roundcube/roundcubemail/issues/8170) should not be required in 1.6
               sed -i "s/\$prefix = '\.\/';/\$prefix = preg_replace\('\/\[\?\&]\.\*\$\/', '', \$_SERVER\['REQUEST_URI'] \?\? ''\) \?: '\.\/';/g" /web/rc/program/include/rcmail.php
              -
              +

              Let admins log into Roundcube without password

              First, install plugin dovecot_impersonate and add Roundcube as an app (see above).

              Edit mailcow.conf and add the following:

              -
              # Allow admins to log into Roundcube as email user (without any password)
              +
              # Allow admins to log into Roundcube as email user (without any password)
               # Roundcube with plugin dovecot_impersonate must be installed first
               
               ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE=y
              -
              +

              Edit docker-compose.override.yml and crate/extend the section for php-fpm-mailcow:

              -
              version: '2.1'
              +
              version: '2.1'
               services:
                 php-fpm-mailcow:
                   environment:
                     - ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE=${ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE:-n}
              -
              +

              Edit data/web/js/site/mailbox.js and the following code after if (ALLOW_ADMIN_EMAIL_LOGIN) { ... }

              -
              if (ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE) {
              -  item.action += '<a href="/rc-auth.php?login=' + encodeURIComponent(item.username) + '" class="login_as btn btn-xs ' + btnSize + ' btn-primary" target="_blank"><i class="bi bi-envelope-fill"></i> Roundcube</a>';
              -}
              -
              +
              if (ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE) {
              +  item.action += '<a href="/rc-auth.php?login=' + encodeURIComponent(item.username) + '" class="login_as btn btn-xs ' + btnSize + ' btn-primary" target="_blank"><i class="bi bi-envelope-fill"></i> Roundcube</a>';
              +}
              +

              Edit data/web/mailbox.php and add this line to array $template_data:

              -
                'allow_admin_email_login_roundcube' => (preg_match("/^(yes|y)+$/i", $_ENV["ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE"])) ? 'true' : 'false',
              -
              +
                'allow_admin_email_login_roundcube' => (preg_match("/^(yes|y)+$/i", $_ENV["ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE"])) ? 'true' : 'false',
              +

              Edit data/web/templates/mailbox.twig and add this code to the bottom of the javascript section:

              -
                var ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE = {{ allow_admin_email_login_roundcube }};
              -
              +
                var ALLOW_ADMIN_EMAIL_LOGIN_ROUNDCUBE = {{ allow_admin_email_login_roundcube }};
              +

              Copy the contents of the following files from this Snippet:

              • data/web/inc/lib/RoundcubeAutoLogin.php
              • data/web/rc-auth.php

              Finally, restart mailcow

              -
              docker-compose down
              +
              docker-compose down
               docker-compose up -d
              -
              +

              diff --git a/troubleshooting/debug-admin_login_sogo/index.html b/troubleshooting/debug-admin_login_sogo/index.html index 40c9ced3f..b5588d662 100644 --- a/troubleshooting/debug-admin_login_sogo/index.html +++ b/troubleshooting/debug-admin_login_sogo/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2428,11 +2428,11 @@ log into SOGo as a mailbox user, without knowing the users password.

              Multiple concurrent admin-logins to different mailboxes are also possible when using this feature.

              Enabling the feature

              The feature is disabled by default. It can be enabled in the mailcow.conf by setting: -

              ALLOW_ADMIN_EMAIL_LOGIN=y
              -
              +
              ALLOW_ADMIN_EMAIL_LOGIN=y
              +
              and recreating the affected containers with -
              docker-compose up -d
              -

              +
              docker-compose up -d
              +

              Drawbacks when enabled

              • Each SOGo page-load and each Active-Sync request will cause an additional execution of an internal PHP script. diff --git a/troubleshooting/debug-attach_service/index.html b/troubleshooting/debug-attach_service/index.html index 6c8a5822b..901026958 100644 --- a/troubleshooting/debug-attach_service/index.html +++ b/troubleshooting/debug-attach_service/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2476,17 +2476,17 @@

                Attaching a Container to your Shell

                To attach a container to your shell you can simply run

                -
                docker-compose exec $Service_Name /bin/bash
                -
                +
                docker-compose exec $Service_Name /bin/bash
                +

                Connecting to Services

                If you want to connect to a service / application directly it is always a good idea to source mailcow.conf to get all relevant variables into your environment.

                MySQL

                -
                source mailcow.conf
                +
                source mailcow.conf
                 docker-compose exec mysql-mailcow mysql -u${DBUSER} -p${DBPASS} ${DBNAME}
                -
                +

                Redis

                -
                docker-compose exec redis-mailcow redis-cli
                -
                +
                docker-compose exec redis-mailcow redis-cli
                +

                Service Descriptions

                Here is a brief overview of what container / service does what:

          diff --git a/troubleshooting/debug-common_problems/index.html b/troubleshooting/debug-common_problems/index.html index 90edfaacc..d7c9e346d 100644 --- a/troubleshooting/debug-common_problems/index.html +++ b/troubleshooting/debug-common_problems/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2516,11 +2516,11 @@
        • Check if your IP address is on any blacklists. You could use 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:
        • -
          # telnet 74.125.133.27 465
          +
          # telnet 74.125.133.27 465
           Trying 74.125.133.27...
           Connected to 74.125.133.27.
           Escape character is '^]'.
          -
          +

          My mails are identified as Spam

          Please read our guide on DNS configuration.

          docker-compose throws weird errors

          @@ -2537,8 +2537,8 @@ Escape character is '^]'.

          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

          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
          -
          +
          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.

          XYZ can't connect to ...

          Please check your local firewall! @@ -2546,19 +2546,19 @@ Docker and iptables-based firewalls sometimes create conflicting rules, so disab

          If you experience connection problems from home, please check your ISP router's firewall too, some of them block mail traffic on the SMTP (587) or SMTPS (465) ports. It could also be, that your ISP is blocking the ports for SUBMISSION (25).

          While Linux users can chose from a variety of tools1 to check if a port is open, the Windows user has only the PowerShell command Test-NetConnection -ComputerName host -Port port available by default.

          To enable telnet on a Windows after Vista please check this guide or enter the following command in an terminal with administrator privileges:

          -
          dism /online /Enable-Feature /FeatureName:TelnetClient
          -
          +
          dism /online /Enable-Feature /FeatureName:TelnetClient
          +

          Inotify instance limit for user 5000 (UID vmail) exceeded (see #453)

          Docker containers use the Docker hosts inotify limits. Setting them on your Docker host will pass them to the container.

          Dovecot keeps restarting (see #2672)

          Check that you have at least the following files in data/assets/ssl:

          -
          cert.pem
          +
          cert.pem
           dhparams.pem
           key.pem
          -
          +

          If dhparams.pem is missing, you can generate it with

          -
          openssl dhparam -out data/assets/ssl/dhparams.pem 4096
          -
          +
          openssl dhparam -out data/assets/ssl/dhparams.pem 4096
          +

            diff --git a/troubleshooting/debug-logs/index.html b/troubleshooting/debug-logs/index.html index 4d5b1fc03..6dcefe60d 100644 --- a/troubleshooting/debug-logs/index.html +++ b/troubleshooting/debug-logs/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/troubleshooting/debug-mysql_aria/index.html b/troubleshooting/debug-mysql_aria/index.html index 71f79f5bc..ab1c1b307 100644 --- a/troubleshooting/debug-mysql_aria/index.html +++ b/troubleshooting/debug-mysql_aria/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2398,7 +2398,7 @@

            If your server crashed and MariaDB logs an error similar to [ERROR] mysqld: Aria recovery failed. Please run aria_chk -r on all Aria tables (*.MAI) and delete all aria_log.######## files you may want to try the following to recover the database to a healthy state:

            Start the stack and wait until mysql-mailcow begins to report a restarting state. Check by running docker-compose ps.

            Now run the following commands:

            -
            # Stop the stack, don't run "down"
            +
            # Stop the stack, don't run "down"
             docker-compose stop
             # Run a bash in the stopped container as user mysql
             docker-compose run --rm --entrypoint '/bin/sh -c "gosu mysql bash"' mysql-mailcow
            @@ -2408,7 +2408,7 @@ cd /var/lib/mysql
             aria_chk --check --force */*.MAI
             # Delete aria log files
             rm aria_log.*
            -
            +

            Now run docker-compose down followed by docker-compose up -d.


            diff --git a/troubleshooting/debug-mysql_upgrade/index.html b/troubleshooting/debug-mysql_upgrade/index.html index 19fa5f1a2..c3e1e32f0 100644 --- a/troubleshooting/debug-mysql_upgrade/index.html +++ b/troubleshooting/debug-mysql_upgrade/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2396,13 +2396,13 @@

            Run a manual mysql_upgrade

            This step is usually not necessary.

            -
            docker-compose stop mysql-mailcow watchdog-mailcow
            +
            docker-compose stop mysql-mailcow watchdog-mailcow
             docker-compose run --rm --entrypoint '/bin/sh -c "gosu mysql mysqld --skip-grant-tables & sleep 10 && bash && exit 0"' mysql-mailcow
            -
            +

            As soon as the SQL shell spawned, run mysql_upgrade and exit the container:

            -
            mysql_upgrade
            +
            mysql_upgrade
             exit
            -
            +

            diff --git a/troubleshooting/debug-reset_pw/index.html b/troubleshooting/debug-reset_pw/index.html index a5febf520..3e28cc0a3 100644 --- a/troubleshooting/debug-reset_pw/index.html +++ b/troubleshooting/debug-reset_pw/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2544,16 +2544,16 @@

            mailcow Admin Account

            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
            +
            cd mailcow_path
             ./helper-scripts/mailcow-reset-admin.sh
            -
            +

            Reset MySQL Passwords

            Stop the stack by running docker-compose stop.

            When the containers came to a stop, run this command:

            -
            docker-compose run --rm --entrypoint '/bin/sh -c "gosu mysql mysqld --skip-grant-tables & sleep 10 && mysql -hlocalhost -uroot && exit 0"' mysql-mailcow
            -
            +
            docker-compose run --rm --entrypoint '/bin/sh -c "gosu mysql mysqld --skip-grant-tables & sleep 10 && mysql -hlocalhost -uroot && exit 0"' mysql-mailcow
            +

            1. Find database name

            -
            # source mailcow.conf
            +
            # source mailcow.conf
             # docker-compose exec mysql-mailcow mysql -u${DBUSER} -p${DBPASS} ${DBNAME}
             MariaDB [(none)]> show databases;
             +--------------------+
            @@ -2565,11 +2565,11 @@ MariaDB [(none)]> show databases;
             | performance_schema |
             +--------------------+
             4 rows in set (0.00 sec)
            -
            +

            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.

            -
            MariaDB [(none)]> SELECT user FROM mysql.user;
            +
            MariaDB [(none)]> SELECT user FROM mysql.user;
             +--------------+
             | user         |
             +--------------+
            @@ -2582,9 +2582,9 @@ MariaDB [(none)]> FLUSH PRIVILEGES;
             MariaDB [(none)]> UPDATE mysql.user SET authentication_string = PASSWORD('gotr00t'), password = PASSWORD('gotr00t') WHERE User = 'root';
             MariaDB [(none)]> UPDATE mysql.user SET authentication_string = PASSWORD('mookuh'), password = PASSWORD('mookuh') WHERE User = 'mailcow' AND Host = '%';
             MariaDB [(none)]> FLUSH PRIVILEGES;
            -
            +

            2.2 Maria DB >= 10.4 (current mailcows)

            -
            MariaDB [(none)]> SELECT user FROM mysql.user;
            +
            MariaDB [(none)]> SELECT user FROM mysql.user;
             +--------------+
             | user         |
             +--------------+
            @@ -2598,16 +2598,16 @@ MariaDB [(none)]> ALTER USER 'mailcow'@'%' IDENTIFIED BY '
             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
            +
            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}'
            -
            +
            docker-compose exec -u sogo sogo-mailcow sogo-tool user-preferences set defaults user@example.com SOGoGoogleAuthenticatorEnabled '{"SOGoGoogleAuthenticatorEnabled":0}'
            +

            diff --git a/troubleshooting/debug-reset_tls/index.html b/troubleshooting/debug-reset_tls/index.html index db8481e85..580d073ff 100644 --- a/troubleshooting/debug-reset_tls/index.html +++ b/troubleshooting/debug-reset_tls/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2346,14 +2346,14 @@

            Reset TLS certificates

            In case you encounter problems with your certificate, key or Let's Encrypt account, please try to reset the TLS assets:

            -
            source mailcow.conf
            +
            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/troubleshooting/debug-rm_volumes/index.html b/troubleshooting/debug-rm_volumes/index.html index 34bed26ff..b1ba7d5b6 100644 --- a/troubleshooting/debug-rm_volumes/index.html +++ b/troubleshooting/debug-rm_volumes/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2348,8 +2348,8 @@

            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 volume ls for a full list.

            Delete a single volume:

            -
            docker volume rm mailcowdockerized_${VOLUME_NAME}
            -
            +
            docker volume rm mailcowdockerized_${VOLUME_NAME}
            +
            • Remove volume mysql-vol-1 to remove all MySQL data.
            • Remove volume redis-vol-1 to remove all Redis data.
            • diff --git a/troubleshooting/debug-rspamd_memory_leaks/index.html b/troubleshooting/debug-rspamd_memory_leaks/index.html index 6772d9c22..3935a46d2 100644 --- a/troubleshooting/debug-rspamd_memory_leaks/index.html +++ b/troubleshooting/debug-rspamd_memory_leaks/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -2346,7 +2346,7 @@

              Advanced: Find memory leaks in Rspamd

              A quick guide to deeply analyze a malfunctioning Rspamd.

              -
              docker-compose exec rspamd-mailcow bash
              +
              docker-compose exec rspamd-mailcow bash
               
               if ! grep -qi 'apt-stable-asan' /etc/apt/sources.list.d/rspamd.list; then
                 sed -i 's/apt-stable/apt-stable-asan/i' /etc/apt/sources.list.d/rspamd.list
              @@ -2360,7 +2360,7 @@ nano /docker-entrypoint.sh
               
               export G_SLICE=always-malloc
               export ASAN_OPTIONS=new_delete_type_mismatch=0:detect_leaks=1:detect_odr_violation=0:log_path=/tmp/rspamd-asan:quarantine_size_mb=2048:malloc_context_size=8:fast_unwind_on_malloc=0
              -
              +

              Restart Rspamd: docker-compose restart rspamd-mailcow

              Your memory consumption will increase by a lot, it will also steadily grow, which is not related to a possible memory leak you are looking for.

              Leave the container running for a few minutes, hours or days (it should match the time you usually wait for the leak to "happen") and restart it: docker-compose restart rspamd-mailcow.

              diff --git a/troubleshooting/debug/index.html b/troubleshooting/debug/index.html index f7179dc55..3ed821864 100644 --- a/troubleshooting/debug/index.html +++ b/troubleshooting/debug/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - +