From a03ff8ff7c4ecef502e56aa4d79b67c32a999772 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:18:51 +0100 Subject: [PATCH 01/80] chore(deps): Bump docker/setup-buildx-action from 3.7.1 to 3.8.0 (#4293) --- .github/workflows/generic_build.yml | 2 +- .github/workflows/generic_publish.yml | 2 +- .github/workflows/generic_test.yml | 2 +- .github/workflows/generic_vulnerability-scan.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/generic_build.yml b/.github/workflows/generic_build.yml index 70b5d256..0f1b308e 100644 --- a/.github/workflows/generic_build.yml +++ b/.github/workflows/generic_build.yml @@ -79,7 +79,7 @@ jobs: platforms: arm64 - name: 'Set up Docker Buildx' - uses: docker/setup-buildx-action@v3.7.1 + uses: docker/setup-buildx-action@v3.8.0 # NOTE: AMD64 can build within 2 minutes - name: 'Build images' diff --git a/.github/workflows/generic_publish.yml b/.github/workflows/generic_publish.yml index a6d76a11..119809d0 100644 --- a/.github/workflows/generic_publish.yml +++ b/.github/workflows/generic_publish.yml @@ -40,7 +40,7 @@ jobs: platforms: arm64 - name: 'Set up Docker Buildx' - uses: docker/setup-buildx-action@v3.7.1 + uses: docker/setup-buildx-action@v3.8.0 # Try get the cached build layers from a prior `generic_build.yml` job. # NOTE: Until adopting `type=gha` scoped cache exporter (in `docker/build-push-action`), diff --git a/.github/workflows/generic_test.yml b/.github/workflows/generic_test.yml index 3f1053da..31ec6165 100644 --- a/.github/workflows/generic_test.yml +++ b/.github/workflows/generic_test.yml @@ -38,7 +38,7 @@ jobs: # Ensures consistent BuildKit version (not coupled to Docker Engine), # and increased compatibility of the build cache vs mixing buildx drivers. - name: 'Set up Docker Buildx' - uses: docker/setup-buildx-action@v3.7.1 + uses: docker/setup-buildx-action@v3.8.0 # Importing from the cache should create the image within approx 30 seconds: # NOTE: `qemu` step is not needed as we only test for AMD64. diff --git a/.github/workflows/generic_vulnerability-scan.yml b/.github/workflows/generic_vulnerability-scan.yml index 9cad4293..1405df73 100644 --- a/.github/workflows/generic_vulnerability-scan.yml +++ b/.github/workflows/generic_vulnerability-scan.yml @@ -37,7 +37,7 @@ jobs: # Ensures consistent BuildKit version (not coupled to Docker Engine), # and increased compatibility of the build cache vs mixing buildx drivers. - name: 'Set up Docker Buildx' - uses: docker/setup-buildx-action@v3.7.1 + uses: docker/setup-buildx-action@v3.8.0 # Importing from the cache should create the image within approx 30 seconds: # NOTE: `qemu` step is not needed as we only test for AMD64. From 02415b03dce763a717747bb737e4698ddcd7aefd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 08:26:14 +0100 Subject: [PATCH 02/80] chore(deps): Bump anchore/scan-action from 5.3.0 to 6.0.0 (#4292) --- .github/workflows/generic_vulnerability-scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generic_vulnerability-scan.yml b/.github/workflows/generic_vulnerability-scan.yml index 1405df73..86246f2c 100644 --- a/.github/workflows/generic_vulnerability-scan.yml +++ b/.github/workflows/generic_vulnerability-scan.yml @@ -55,7 +55,7 @@ jobs: provenance: false - name: 'Run the Anchore Grype scan action' - uses: anchore/scan-action@v5.3.0 + uses: anchore/scan-action@v6.0.0 id: scan with: image: mailserver-testing:ci From 259f2031fca6ee8b2f55386cec8c55d30176cfd2 Mon Sep 17 00:00:00 2001 From: Pooyan Khanjankhani Date: Mon, 23 Dec 2024 05:08:46 +0330 Subject: [PATCH 03/80] docs: Fix typo on usage page (#4294) Co-authored-by: Casper --- docs/content/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/usage.md b/docs/content/usage.md index ca4e8dfe..1c31aa17 100644 --- a/docs/content/usage.md +++ b/docs/content/usage.md @@ -48,7 +48,7 @@ We will later dig into DKIM, DMARC & SPF, but for now, these are the records tha - The **MX record** tells everyone which (DNS) name is responsible for e-mails on your domain. Because you want to keep the option of running another service on the domain name itself, you run your mail server on `mail.example.com`. This does not imply your e-mails will look like `test@mail.example.com`, the DNS name of your mail server is decoupled of the domain it serves e-mails for. - In theory, you mail server could even serve e-mails for `test@some-other-domain.com`, if the MX record for `some-other-domain.com` points to `mail.example.com`. + Your mail server could also handle emails for `test@some-other-domain.com`, if the MX record for `some-other-domain.com` points to `mail.example.com`. - The **A record** tells everyone which IP address the DNS name `mail.example.com` resolves to. - The **PTR record** is the counterpart of the A record, telling everyone what name the IP address `11.22.33.44` resolves to. From 24fb65ce7b638b342c1c9f427912756a0e53ed3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Wo=C5=BAniak?= <92504295+zespere@users.noreply.github.com> Date: Sat, 28 Dec 2024 06:00:27 +0100 Subject: [PATCH 04/80] docs: Environment - Update Dovecot docs URL (#4296) Co-authored-by: Casper --- docs/content/config/environment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/config/environment.md b/docs/content/config/environment.md index b7231b10..a16f6bcb 100644 --- a/docs/content/config/environment.md +++ b/docs/content/config/environment.md @@ -295,7 +295,7 @@ Customize the update check interval. Number + Suffix. Suffix must be 's' for sec - sdbox => (experimental) uses Dovecot high-performance mailbox format, one file contains one message - mdbox ==> (experimental) uses Dovecot high-performance mailbox format, multiple messages per file and multiple files per box -This option has been added in November 2019. Using other format than Maildir is considered as experimental in docker-mailserver and should only be used for testing purpose. For more details, please refer to [Dovecot Documentation](https://wiki2.dovecot.org/MailboxFormat). +This option has been added in November 2019. Using other format than Maildir is considered as experimental in docker-mailserver and should only be used for testing purpose. For more details, please refer to [Dovecot Documentation](https://doc.dovecot.org/admin_manual/mailbox_formats/#mailbox-formats). ##### POSTFIX_REJECT_UNKNOWN_CLIENT_HOSTNAME From e6d519b6f82f1d3a1fada4b24edaed6f64f5d3f0 Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Mon, 6 Jan 2025 09:02:02 +1300 Subject: [PATCH 05/80] docs: TLS (Caddy) - Revise advice on `tls internal` (#4305) --- docs/content/config/security/ssl.md | 36 ++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/docs/content/config/security/ssl.md b/docs/content/config/security/ssl.md index 96f4a717..9b1fd8f7 100644 --- a/docs/content/config/security/ssl.md +++ b/docs/content/config/security/ssl.md @@ -485,6 +485,8 @@ DSM-generated letsencrypt certificates get auto-renewed every three months. !!! example + While DMS does not need a webserver to work, this workaround will provision a TLS certificate for DMS to use by adding a dummy site block to trigger cert provisioning. + ```yaml title="compose.yaml" services: # Basic Caddy service to provision certs: @@ -510,9 +512,12 @@ DSM-generated letsencrypt certificates get auto-renewed every three months. - ${CADDY_DATA_DIR}/certificates/acme-v02.api.letsencrypt.org-directory/mail.example.com/mail.example.com.key:/etc/letsencrypt/live/mail.example.com/privkey.pem ``` + An explicit entry in your `Caddyfile` config will have Caddy provision and renew a certificate for your DMS FQDN: + ```caddyfile title="Caddyfile" mail.example.com { - tls internal { + # Optionally provision RSA 2048-bit certificate instead of ECDSA P-256: + tls { key_type rsa2048 } @@ -522,10 +527,12 @@ DSM-generated letsencrypt certificates get auto-renewed every three months. } ``` - While DMS does not need a webserver to work, this workaround will provision a TLS certificate for DMS to use. + !!! info - - [`tls internal`][caddy-docs::tls-internal] will create a local self-signed cert for testing. This targets only the site-address, unlike the global `local_certs` option. - - [`key_type`][caddy-docs::key-type] can be used in the `tls` block if you need to enforce RSA as the key type for certificates provisioned. The default is currently ECDSA (P-256). + An explicit `tls` directive affects only the site-address block it's used in: + + - Use [`tls internal { ... }`][caddy-docs::tls-internal] if wanting to create a local self-signed cert, which may be useful for testing. This allows opt-in to use self-signed certs unlike the global `local_certs` option. + - [`key_type`][caddy-docs::key-type] can be used in the `tls` block if you need to enforce RSA as the key type for certificates provisioned. The default is currently ECDSA (P-256). This may improve compatibility with legacy clients. ??? example "With `caddy-docker-proxy`" @@ -558,9 +565,9 @@ DSM-generated letsencrypt certificates get auto-renewed every three months. labels: # Set your DMS FQDN here to add the site-address into the generated Caddyfile: caddy_0: mail.example.com - # Add a dummy directive is required: + # Adding a dummy directive is required: caddy_0.respond: "Hello DMS" - # Uncomment to make a proxy for Rspamd + # Uncomment to make a proxy for Rspamd: # caddy_1: rspamd.example.com # caddy_1.reverse_proxy: "{{upstreams 11334}}" ``` @@ -571,6 +578,23 @@ DSM-generated letsencrypt certificates get auto-renewed every three months. This can make the volume mounting for DMS to find the certificates non-deterministic, but you can [restrict provisioning to single service via the `acme_ca` setting][caddy::restrict-acme-provisioner]. + --- + + **NOTE:** Bind mounting a file directly instead of a directory will mount by inode. If the file is updated at renewal and this modifies the inode on the host system, then the container will still point to the old certificate. + + If this happens, consider using our manual TLS type instead: + + ```yaml title="compose.yaml" + services: + mailserver: + environment: + SSL_TYPE: manual + SSL_CERT_PATH: /srv/tls/mail.example.com/mail.example.com.crt + SSL_KEY_PATH: /srv/tls/mail.example.com/mail.example.com.key + volumes: + - ${CADDY_DATA_DIR}/certificates/acme-v02.api.letsencrypt.org-directory/mail.example.com/:/srv/tls/mail.example.com/:ro + ``` + ### Traefik [Traefik][traefik::github] is an open-source application proxy using the [ACME protocol][ietf::rfc::acme]. Traefik can request certificates for domains and subdomains, and it will take care of renewals, challenge negotiations, etc. From a302bd79e3c76c2b501628cfbcee77fee03b9511 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 12:36:44 +1300 Subject: [PATCH 06/80] chore(deps): Bump docker/setup-qemu-action from 3.2.0 to 3.3.0 (#4309) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/v3.2.0...v3.3.0) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/generic_build.yml | 2 +- .github/workflows/generic_publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/generic_build.yml b/.github/workflows/generic_build.yml index 0f1b308e..c3dce52c 100644 --- a/.github/workflows/generic_build.yml +++ b/.github/workflows/generic_build.yml @@ -74,7 +74,7 @@ jobs: cache-buildx- - name: 'Set up QEMU' - uses: docker/setup-qemu-action@v3.2.0 + uses: docker/setup-qemu-action@v3.3.0 with: platforms: arm64 diff --git a/.github/workflows/generic_publish.yml b/.github/workflows/generic_publish.yml index 119809d0..2520aade 100644 --- a/.github/workflows/generic_publish.yml +++ b/.github/workflows/generic_publish.yml @@ -35,7 +35,7 @@ jobs: type=semver,pattern={{major}}.{{minor}}.{{patch}} - name: 'Set up QEMU' - uses: docker/setup-qemu-action@v3.2.0 + uses: docker/setup-qemu-action@v3.3.0 with: platforms: arm64 From 8df1fba96e1efb1c28317f6e162323bf781918be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 12:38:15 +1300 Subject: [PATCH 07/80] chore(deps): Bump docker/build-push-action from 6.10.0 to 6.11.0 (#4310) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.10.0 to 6.11.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.10.0...v6.11.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com> --- .github/workflows/generic_build.yml | 2 +- .github/workflows/generic_publish.yml | 2 +- .github/workflows/generic_test.yml | 2 +- .github/workflows/generic_vulnerability-scan.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/generic_build.yml b/.github/workflows/generic_build.yml index c3dce52c..0561587f 100644 --- a/.github/workflows/generic_build.yml +++ b/.github/workflows/generic_build.yml @@ -83,7 +83,7 @@ jobs: # NOTE: AMD64 can build within 2 minutes - name: 'Build images' - uses: docker/build-push-action@v6.10.0 + uses: docker/build-push-action@v6.11.0 with: context: . # Build at least the AMD64 image (which runs against the test suite). diff --git a/.github/workflows/generic_publish.yml b/.github/workflows/generic_publish.yml index 2520aade..835e2a81 100644 --- a/.github/workflows/generic_publish.yml +++ b/.github/workflows/generic_publish.yml @@ -67,7 +67,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: 'Build and publish images' - uses: docker/build-push-action@v6.10.0 + uses: docker/build-push-action@v6.11.0 with: context: . build-args: | diff --git a/.github/workflows/generic_test.yml b/.github/workflows/generic_test.yml index 31ec6165..19324f0a 100644 --- a/.github/workflows/generic_test.yml +++ b/.github/workflows/generic_test.yml @@ -43,7 +43,7 @@ jobs: # Importing from the cache should create the image within approx 30 seconds: # NOTE: `qemu` step is not needed as we only test for AMD64. - name: 'Build AMD64 image from cache' - uses: docker/build-push-action@v6.10.0 + uses: docker/build-push-action@v6.11.0 with: context: . tags: mailserver-testing:ci diff --git a/.github/workflows/generic_vulnerability-scan.yml b/.github/workflows/generic_vulnerability-scan.yml index 86246f2c..bf700139 100644 --- a/.github/workflows/generic_vulnerability-scan.yml +++ b/.github/workflows/generic_vulnerability-scan.yml @@ -42,7 +42,7 @@ jobs: # Importing from the cache should create the image within approx 30 seconds: # NOTE: `qemu` step is not needed as we only test for AMD64. - name: 'Build AMD64 image from cache' - uses: docker/build-push-action@v6.10.0 + uses: docker/build-push-action@v6.11.0 with: context: . tags: mailserver-testing:ci From 3ebca5dabaea1469f482d22912e08ec33c16cfed Mon Sep 17 00:00:00 2001 From: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> Date: Sat, 18 Jan 2025 21:26:07 +0100 Subject: [PATCH 08/80] Revert "fix: fix incorrect link in README.md (#4184)" (#4322) This reverts commit 84180f879e5eaaa15930509d4154248c3248d765. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6e1d2735..e4dbf44a 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ A production-ready fullstack but simple containerized mail server (SMTP, IMAP, L ## :package: Included Services - [Postfix](http://www.postfix.org) with SMTP or LDAP authentication and support for [extension delimiters](https://docker-mailserver.github.io/docker-mailserver/latest/config/account-management/overview/#aliases) -- [Dovecot](https://www.dovecot.org) with SASL, IMAP, POP3, LDAP, [basic Sieve support](https://docker-mailserver.github.io/docker-mailserver/latest/config/advanced/mail-sieve) and [quotas](https://docker-mailserver.github.io/docker-mailserver/latest/config/user-management/#quotas) +- [Dovecot](https://www.dovecot.org) with SASL, IMAP, POP3, LDAP, [basic Sieve support](https://docker-mailserver.github.io/docker-mailserver/latest/config/advanced/mail-sieve) and [quotas](https://docker-mailserver.github.io/docker-mailserver/latest/config/account-management/overview/#quotas) - [Rspamd](https://rspamd.com/) - [Amavis](https://www.amavis.org/) - [SpamAssassin](http://spamassassin.apache.org/) supporting custom rules From f0daa1c8abff606bd3fa6f5212b7e77c1e7b38a2 Mon Sep 17 00:00:00 2001 From: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> Date: Sun, 19 Jan 2025 01:27:07 +0100 Subject: [PATCH 09/80] chore: remove `VERSION` file (#4321) --- .dockerignore | 1 - .github/workflows/generic_build.yml | 7 ++----- CHANGELOG.md | 1 + VERSION | 1 - 4 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 VERSION diff --git a/.dockerignore b/.dockerignore index b6eef669..50365994 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,2 @@ * !target -!VERSION diff --git a/.github/workflows/generic_build.yml b/.github/workflows/generic_build.yml index 0561587f..b81c94de 100644 --- a/.github/workflows/generic_build.yml +++ b/.github/workflows/generic_build.yml @@ -32,7 +32,7 @@ jobs: with: submodules: recursive - # Can potentially be replaced by: `${{ hashFiles('target/**', 'Dockerfile', 'VERSION') }}` + # Can potentially be replaced by: `${{ hashFiles('target/**', 'Dockerfile') }}` # Must not be affected by file metadata changes and have a consistent sort order: # https://docs.github.com/en/actions/learn-github-actions/expressions#hashfiles # Keying by the relevant build context is more re-usable than a commit SHA. @@ -40,10 +40,7 @@ jobs: id: derive-image-cache-key shell: bash run: | - ADDITIONAL_FILES=( - 'Dockerfile' - 'VERSION' - ) + ADDITIONAL_FILES=( 'Dockerfile' ) # Recursively collect file paths from `target/` and pipe a list of # checksums to be sorted (by hash value) and finally generate a checksum diff --git a/CHANGELOG.md b/CHANGELOG.md index b0409511..8ca4bdcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file. The format - DMS v14 mistakenly relocated the _getmail state directory_ to the _DMS Config Volume_ as a `getmail/` subdirectory. - This has been corrected to `/var/lib/getmail` (_if you have mounted a DMS State Volume to `/var/mail-state`, `/var/lib/getmail` will be symlinked to `/var/mail-state/lib-getmail`_). - To preserve this state when upgrading to DMS v15, **you must manually migrate `getmail/` from the _DMS Config Volume_ to `lib-getmail/` in the _DMS State Volume_.** +- **removed `VERSION`** file that was used for checking version updates ([#3677](https://github.com/docker-mailserver/docker-mailserver/issues/3677),[#4321](https://github.com/docker-mailserver/docker-mailserver/pull/4321)) ### Security diff --git a/VERSION b/VERSION deleted file mode 100644 index 4b964e96..00000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -14.0.0 From 2d56210c522410a29d15d0c890667fad2fee1c75 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Jan 2025 21:42:25 +0100 Subject: [PATCH 10/80] chore(deps): Bump docker/build-push-action from 6.11.0 to 6.12.0 (#4324) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.11.0 to 6.12.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.11.0...v6.12.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/generic_build.yml | 2 +- .github/workflows/generic_publish.yml | 2 +- .github/workflows/generic_test.yml | 2 +- .github/workflows/generic_vulnerability-scan.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/generic_build.yml b/.github/workflows/generic_build.yml index b81c94de..5c819637 100644 --- a/.github/workflows/generic_build.yml +++ b/.github/workflows/generic_build.yml @@ -80,7 +80,7 @@ jobs: # NOTE: AMD64 can build within 2 minutes - name: 'Build images' - uses: docker/build-push-action@v6.11.0 + uses: docker/build-push-action@v6.12.0 with: context: . # Build at least the AMD64 image (which runs against the test suite). diff --git a/.github/workflows/generic_publish.yml b/.github/workflows/generic_publish.yml index 835e2a81..edd642fb 100644 --- a/.github/workflows/generic_publish.yml +++ b/.github/workflows/generic_publish.yml @@ -67,7 +67,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: 'Build and publish images' - uses: docker/build-push-action@v6.11.0 + uses: docker/build-push-action@v6.12.0 with: context: . build-args: | diff --git a/.github/workflows/generic_test.yml b/.github/workflows/generic_test.yml index 19324f0a..190f1f89 100644 --- a/.github/workflows/generic_test.yml +++ b/.github/workflows/generic_test.yml @@ -43,7 +43,7 @@ jobs: # Importing from the cache should create the image within approx 30 seconds: # NOTE: `qemu` step is not needed as we only test for AMD64. - name: 'Build AMD64 image from cache' - uses: docker/build-push-action@v6.11.0 + uses: docker/build-push-action@v6.12.0 with: context: . tags: mailserver-testing:ci diff --git a/.github/workflows/generic_vulnerability-scan.yml b/.github/workflows/generic_vulnerability-scan.yml index bf700139..a74c9827 100644 --- a/.github/workflows/generic_vulnerability-scan.yml +++ b/.github/workflows/generic_vulnerability-scan.yml @@ -42,7 +42,7 @@ jobs: # Importing from the cache should create the image within approx 30 seconds: # NOTE: `qemu` step is not needed as we only test for AMD64. - name: 'Build AMD64 image from cache' - uses: docker/build-push-action@v6.11.0 + uses: docker/build-push-action@v6.12.0 with: context: . tags: mailserver-testing:ci From 7cb2fc788f67a90319e2d7ecdd5422bc9cd33afc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Jan 2025 10:56:37 +0100 Subject: [PATCH 11/80] chore(deps): Bump anchore/scan-action from 6.0.0 to 6.1.0 (#4332) Bumps [anchore/scan-action](https://github.com/anchore/scan-action) from 6.0.0 to 6.1.0. - [Release notes](https://github.com/anchore/scan-action/releases) - [Changelog](https://github.com/anchore/scan-action/blob/main/RELEASE.md) - [Commits](https://github.com/anchore/scan-action/compare/v6.0.0...v6.1.0) --- updated-dependencies: - dependency-name: anchore/scan-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/generic_vulnerability-scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generic_vulnerability-scan.yml b/.github/workflows/generic_vulnerability-scan.yml index a74c9827..2e73e0f2 100644 --- a/.github/workflows/generic_vulnerability-scan.yml +++ b/.github/workflows/generic_vulnerability-scan.yml @@ -55,7 +55,7 @@ jobs: provenance: false - name: 'Run the Anchore Grype scan action' - uses: anchore/scan-action@v6.0.0 + uses: anchore/scan-action@v6.1.0 id: scan with: image: mailserver-testing:ci From 4d8a56072a88cbacea373be88aa1d805e1eacc59 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Jan 2025 11:02:25 +0100 Subject: [PATCH 12/80] chore(deps): Bump docker/build-push-action from 6.12.0 to 6.13.0 (#4331) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.12.0 to 6.13.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.12.0...v6.13.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> --- .github/workflows/generic_build.yml | 2 +- .github/workflows/generic_publish.yml | 2 +- .github/workflows/generic_test.yml | 2 +- .github/workflows/generic_vulnerability-scan.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/generic_build.yml b/.github/workflows/generic_build.yml index 5c819637..6000f5ff 100644 --- a/.github/workflows/generic_build.yml +++ b/.github/workflows/generic_build.yml @@ -80,7 +80,7 @@ jobs: # NOTE: AMD64 can build within 2 minutes - name: 'Build images' - uses: docker/build-push-action@v6.12.0 + uses: docker/build-push-action@v6.13.0 with: context: . # Build at least the AMD64 image (which runs against the test suite). diff --git a/.github/workflows/generic_publish.yml b/.github/workflows/generic_publish.yml index edd642fb..42cde7ea 100644 --- a/.github/workflows/generic_publish.yml +++ b/.github/workflows/generic_publish.yml @@ -67,7 +67,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: 'Build and publish images' - uses: docker/build-push-action@v6.12.0 + uses: docker/build-push-action@v6.13.0 with: context: . build-args: | diff --git a/.github/workflows/generic_test.yml b/.github/workflows/generic_test.yml index 190f1f89..f28dbc9b 100644 --- a/.github/workflows/generic_test.yml +++ b/.github/workflows/generic_test.yml @@ -43,7 +43,7 @@ jobs: # Importing from the cache should create the image within approx 30 seconds: # NOTE: `qemu` step is not needed as we only test for AMD64. - name: 'Build AMD64 image from cache' - uses: docker/build-push-action@v6.12.0 + uses: docker/build-push-action@v6.13.0 with: context: . tags: mailserver-testing:ci diff --git a/.github/workflows/generic_vulnerability-scan.yml b/.github/workflows/generic_vulnerability-scan.yml index 2e73e0f2..3b20b2ed 100644 --- a/.github/workflows/generic_vulnerability-scan.yml +++ b/.github/workflows/generic_vulnerability-scan.yml @@ -42,7 +42,7 @@ jobs: # Importing from the cache should create the image within approx 30 seconds: # NOTE: `qemu` step is not needed as we only test for AMD64. - name: 'Build AMD64 image from cache' - uses: docker/build-push-action@v6.12.0 + uses: docker/build-push-action@v6.13.0 with: context: . tags: mailserver-testing:ci From 3faa40bfb5442e4fd6638aa5878fe807feb7e94f Mon Sep 17 00:00:00 2001 From: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> Date: Sun, 2 Feb 2025 22:35:50 +0100 Subject: [PATCH 13/80] docs: add ARC example to Rspamd documentation (#4328) Signed-off-by: georglauterbach <44545919+georglauterbach@users.noreply.github.com> --- docs/content/config/security/rspamd.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/content/config/security/rspamd.md b/docs/content/config/security/rspamd.md index 8705262c..c49baea6 100644 --- a/docs/content/config/security/rspamd.md +++ b/docs/content/config/security/rspamd.md @@ -247,6 +247,24 @@ Rspamd is running, but you want or need to adjust it? First, create a file named There is a dedicated [section for setting up DKIM with Rspamd in our documentation][docs::dkim-with-rspamd]. +### ARC (Authenticated Received Chain) + +ARC is not set up by default, but you can easily enable it by adding a file called `arc.conf` to `docker-data/dms/config/rspamd/override.d/`. ARC can use DKIM keys that you should have already created. The configuration file could then contain the following: + +```conf +sign_local = true; +sign_authenticated = true; + +domain { + { + # Change the path here to your actual private key + path = "/tmp/docker-mailserver/rspamd/dkim/rsa-2048-mail-.private.txt"; + # Changhe the selected if you chose a non-default one + selector = "mail"; + } +} +``` + ### _Abusix_ Integration This subsection provides information about the integration of [Abusix][abusix-web], "a set of blocklists that work as an additional email security layer for your existing mail environment". The setup is straight-forward and well documented: From 0e61f170fd552077e797483310a7d61500bbe020 Mon Sep 17 00:00:00 2001 From: Zlatibor Veljkovic Date: Tue, 4 Feb 2025 00:45:43 +0100 Subject: [PATCH 14/80] docs: `bind-smtp-network-interface.md` - Add bridge network config advice (#4330) Co-authored-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com> --- .../use-cases/bind-smtp-network-interface.md | 50 ++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/docs/content/examples/use-cases/bind-smtp-network-interface.md b/docs/content/examples/use-cases/bind-smtp-network-interface.md index b12e21de..0da33b19 100644 --- a/docs/content/examples/use-cases/bind-smtp-network-interface.md +++ b/docs/content/examples/use-cases/bind-smtp-network-interface.md @@ -21,10 +21,6 @@ This can be configured by [overriding the default Postfix configurations][docs:: In `postfix-main.cf` you'll have to set the [`smtp_bind_address`][postfix-docs::smtp-bind-address-ipv4] and [`smtp_bind_address6`][postfix-docs::smtp-bind-address-ipv6] to the respective IP-address on the server you want to use. -[docs::overrides-postfix]: ../../config/advanced/override-defaults/postfix.md -[postfix-docs::smtp-bind-address-ipv4]: https://www.postfix.org/postconf.5.html#smtp_bind_address -[postfix-docs::smtp-bind-address-ipv6]: https://www.postfix.org/postconf.5.html#smtp_bind_address6 - !!! example === "Contributed solution" @@ -55,14 +51,56 @@ to the respective IP-address on the server you want to use. ``` If that avoids the concern with `smtp-amavis`, you may still need to additionally override for the [`relay` transport][gh-src::postfix-master-cf::relay-transport] as well if you have configured DMS to relay mail. + + === "Bridged Networks" + + When your DMS container is using a bridge network, you'll instead need to restrict which IP address inbound and outbound traffic is routed through via the bridged interface. + + For **inbound** traffic, you may configure this at whatever scope is most appropriate for you: + + - **Daemon:** Change the [default bind address][inbound-ip::docker-docs::daemon] configured in `/etc/docker/daemon.json` (default `0.0.0.0`) + - **Network:** Assign the [`host_binding_ipv4` bridge driver option][inbound-ip::docker-docs::network] as shown in the below `compose.yaml` snippet. + - **Container:** Provide an explicit host IP address when [publishing a port][inbound-ip::docker-docs::container]. + + For **outbound** traffic, the bridge network will use the default route. You can change this by either: + + - [Manually routing networks][outbound-ip::route-manually] on the host. + - Use the [`host_ipv4` driver option][outbind-ip::host-ipv4] for Docker networks to force the SNAT (source IP) that the bridged network will route outbound traffic through. + - This IP address must belong to a network interface to be routed through it. + - IPv6 support via `host_ipv6` [requires at least Docker v25][outbind-ip::host-ipv6]. + + --- + + Here is a `compose.yaml` snippet that applies the inbound + outbound settings to the default bridge network Docker Compose creates (_if it already exists, you will need to ensure it's re-created to apply the updated settings_): + + ```yaml title="compose.yaml" + networks: + default: + driver_opts: + # Inbound IP (sets the host IP that published ports receive traffic from): + com.docker.network.bridge.host_binding_ipv4: 198.51.100.42 + # Outbound IP (sets the host IP that external hosts will receive connections from): + com.docker.network.host_ipv4: 198.51.100.42 + ``` !!! note "IP addresses for documentation" - IP addresses shown in above examples are placeholders, they are IP addresses reserved for documentation by IANA (_[RFC-5737 (IPv4)][rfc-5737] and [RFC-3849 (IPv6)][rfc-3849]_). Replace them with the IP addresses you want DMS to send mail through. - + IP addresses shown in above examples (`198.51.100.42` + `2001:DB8::42`) are placeholders, they are IP addresses reserved for documentation by IANA (_[RFC-5737 (IPv4)][rfc-5737] and [RFC-3849 (IPv6)][rfc-3849]_). Replace them with the IP addresses you want DMS to send mail through. + +[docs::overrides-postfix]: ../../config/advanced/override-defaults/postfix.md +[postfix-docs::smtp-bind-address-ipv4]: https://www.postfix.org/postconf.5.html#smtp_bind_address +[postfix-docs::smtp-bind-address-ipv6]: https://www.postfix.org/postconf.5.html#smtp_bind_address6 + [rfc-5737]: https://datatracker.ietf.org/doc/html/rfc5737 [rfc-3849]: https://datatracker.ietf.org/doc/html/rfc3849 [gh-pr::3465::comment-restrictions]: https://github.com/docker-mailserver/docker-mailserver/pull/3465#discussion_r1458114528 [gh-pr::3465::alternative-solution]: https://github.com/docker-mailserver/docker-mailserver/pull/3465#issuecomment-1678107233 [gh-src::postfix-master-cf::relay-transport]: https://github.com/docker-mailserver/docker-mailserver/blob/9cdbef2b369fb4fb0f1b4e534da8703daf92abc9/target/postfix/master.cf#L65 + +[inbound-ip::docker-docs::daemon]: https://docs.docker.com/reference/cli/dockerd/#default-network-options +[inbound-ip::docker-docs::network]: https://docs.docker.com/engine/network/drivers/bridge/#default-host-binding-address +[inbound-ip::docker-docs::container]: https://docs.docker.com/reference/compose-file/services/#ports +[outbound-ip::route-manually]: https://github.com/moby/moby/issues/30053#issuecomment-1077041045 +[outbind-ip::host-ipv4]: https://github.com/moby/libnetwork/pull/2454 +[outbind-ip::host-ipv6]: https://github.com/moby/moby/issues/46469 From e116920f4df64cd55c9cd91e8783180b3fa2aae0 Mon Sep 17 00:00:00 2001 From: Casper Date: Wed, 5 Feb 2025 23:10:57 +0100 Subject: [PATCH 15/80] Add missing "setup debug getmail" command and documentation (#4346) --- CHANGELOG.md | 1 + docs/content/config/advanced/mail-getmail.md | 8 ++++++++ target/bin/setup | 2 ++ 3 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ca4bdcb..781ef3e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file. The format - DMS v14 mistakenly relocated the _getmail state directory_ to the _DMS Config Volume_ as a `getmail/` subdirectory. - This has been corrected to `/var/lib/getmail` (_if you have mounted a DMS State Volume to `/var/mail-state`, `/var/lib/getmail` will be symlinked to `/var/mail-state/lib-getmail`_). - To preserve this state when upgrading to DMS v15, **you must manually migrate `getmail/` from the _DMS Config Volume_ to `lib-getmail/` in the _DMS State Volume_.** + - Added missing `debug getmail` subcommand to `setup` ([#4346](https://github.com/docker-mailserver/docker-mailserver/pull/4346)) - **removed `VERSION`** file that was used for checking version updates ([#3677](https://github.com/docker-mailserver/docker-mailserver/issues/3677),[#4321](https://github.com/docker-mailserver/docker-mailserver/pull/4321)) ### Security diff --git a/docs/content/config/advanced/mail-getmail.md b/docs/content/config/advanced/mail-getmail.md index d423b4f0..f4ce7e63 100644 --- a/docs/content/config/advanced/mail-getmail.md +++ b/docs/content/config/advanced/mail-getmail.md @@ -108,3 +108,11 @@ It is possible to utilize the `getmail-gmail-xoauth-tokens` helper to provide au [getmail-docs]: https://getmail6.org/configuration.html [getmail-docs-xoauth-12]: https://github.com/getmail6/getmail6/blob/1f95606156231f1e074ba62a9baa64f892a92ef8/docs/getmailrc-examples#L286 [getmail-docs-xoauth-13]: https://github.com/getmail6/getmail6/blob/1f95606156231f1e074ba62a9baa64f892a92ef8/docs/getmailrc-examples#L351 + +## Debugging + +To debug your `getmail` configurations, run this `setup debug` command: + +```sh +docker exec -it dms-container-name setup debug getmail +``` diff --git a/target/bin/setup b/target/bin/setup index ac0d6328..c05f59a7 100755 --- a/target/bin/setup +++ b/target/bin/setup @@ -64,6 +64,7 @@ ${RED}[${ORANGE}SUB${RED}]${ORANGE}COMMANDS${RESET} ${LBLUE}COMMAND${RESET} debug ${RED}:=${RESET} setup debug ${CYAN}fetchmail${RESET} + setup debug ${CYAN}getmail${RESET} setup debug ${CYAN}login${RESET} setup debug ${CYAN}show-mail-logs${RESET} @@ -150,6 +151,7 @@ function _main() { ( debug ) case ${2:-} in ( fetchmail ) debug-fetchmail ;; + ( getmail ) debug-getmail ;; ( show-mail-logs ) cat /var/log/mail/mail.log ;; ( login ) shift 2 From 85793988d6d81ec21e19ccab96070fcd1f3d6208 Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Fri, 7 Feb 2025 10:10:37 +1300 Subject: [PATCH 16/80] chore: `demo-setups/relay-compose.yaml` should use network alias (#4347) --- demo-setups/relay-compose.yaml | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/demo-setups/relay-compose.yaml b/demo-setups/relay-compose.yaml index f4df2de0..cb4f0846 100644 --- a/demo-setups/relay-compose.yaml +++ b/demo-setups/relay-compose.yaml @@ -41,17 +41,13 @@ services: hostname: smtp.relay-service.test environment: # WORKAROUND: Bypass security checks from the mail-client (dms-sender container) - # (avoids needing valid DNS for this example) + # (avoids needing expected DNS records to run this example) - PERMIT_DOCKER=connected-networks # TLS is required when relaying to dms-relay via ports 587 / 465 # (dms-relay will then relay the mail to dms-destination over port 25) - SSL_TYPE=manual - SSL_KEY_PATH=/tmp/tls/key.pem - SSL_CERT_PATH=/tmp/tls/cert.pem - # WORKAROUND: `links` is required due to lack of properly configured DNS. - # (resolves destination.test to the IP of the dms-destination container) - links: - - "dms-destination:destination.test" configs: - source: dms-accounts-relay target: /tmp/docker-mailserver/postfix-accounts.cf @@ -64,8 +60,14 @@ services: dms-destination: image: mailserver/docker-mailserver:latest # :14.0 hostname: mail.destination.test - # Same workaround for purposes of the example, with the target recipient provisioned to accept mail + # WORKAROUND: dms-relay must be able to resolve DNS for `@destination.test` to the IP of this container: + # Normally a MX record would direct mail to the MTA (eg: `mail.destination.test`) + networks: + default: + aliases: + - destination.test environment: + # WORKAROUND: Same workaround as needed for dms-relay - PERMIT_DOCKER=connected-networks configs: - source: dms-accounts-destination @@ -75,6 +77,13 @@ services: # NOTE: This feature requires Docker Compose v2.23.1 (Nov 2023) or newer: # https://github.com/compose-spec/compose-spec/pull/446 configs: + # `postfix-main.cf`, a single line change to make all outbound SMTP connections over implicit TLS instead of the default explicit TLS (StartTLS). + # NOTE: If you need to only selectively relay mail, you would need to instead adjust this on the relay service in `/etc/postfix/master.cf`, + # However DMS presently modifies this when using the DMS Relay Host feature support, which may override `postfix-master.cf` or `user-patches.sh` due to `check-for-changes.sh`. + dms-main: + content: | + smtp_tls_wrappermode=yes + # DMS expects an account to be configured to run, this example provides accounts already created. # Login credentials: # user: "john.doe@example.test" password: "secret" @@ -94,13 +103,6 @@ configs: content: | jane.doe@destination.test|{SHA512-CRYPT}$$6$$o65y1ZXC4ooOPLwZ$$7TF1nYowEtNJpH6BwJBgdj2pPAxaCvhIKQA6ww5zdHm/AA7aemY9eoHC91DOgYNaKj1HLxSeWNDdvrp6mbtUY. - # This is `postfix-main.cf`, single line change to make all outbound SMTP connections over port 465 instead of 25 (default) - # If you selectively relay mail, you would need to adjust this on the relay service in `/etc/postfix/master.cf`, - # However DMS presently modifies this when using the DMS Relay Host feature support, which may override `postfix-master.cf` or `user-patches.sh` due to `check-for-changes.sh`. - dms-main: - content: | - smtp_tls_wrappermode=yes - # TLS files: # - Use an ECDSA cert that's been signed by a self-signed CA for TLS cert verification. # - This cert is only valid for mail.example.test, mail.destination.test, smtp.relay-service.test From 59a379aed781d8e66b9388491aed245a9f5d9af1 Mon Sep 17 00:00:00 2001 From: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> Date: Sat, 8 Feb 2025 22:23:06 +0100 Subject: [PATCH 17/80] scripts: restructure container restart behavior (#4323) Signed-off-by: georglauterbach <44545919+georglauterbach@users.noreply.github.com> Signed-off-by: dependabot[bot] Co-authored-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- CHANGELOG.md | 9 +- target/scripts/start-mailserver.sh | 54 ++--- target/scripts/startup/check-stack.sh | 18 -- target/scripts/startup/setup-stack.sh | 4 +- target/scripts/startup/setup.d/mail_state.sh | 242 ++++++++++--------- target/scripts/startup/variables-stack.sh | 54 ++++- 6 files changed, 202 insertions(+), 179 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 781ef3e4..379992c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,8 +19,6 @@ All notable changes to this project will be documented in this file. The format - DMS v14 mistakenly relocated the _getmail state directory_ to the _DMS Config Volume_ as a `getmail/` subdirectory. - This has been corrected to `/var/lib/getmail` (_if you have mounted a DMS State Volume to `/var/mail-state`, `/var/lib/getmail` will be symlinked to `/var/mail-state/lib-getmail`_). - To preserve this state when upgrading to DMS v15, **you must manually migrate `getmail/` from the _DMS Config Volume_ to `lib-getmail/` in the _DMS State Volume_.** - - Added missing `debug getmail` subcommand to `setup` ([#4346](https://github.com/docker-mailserver/docker-mailserver/pull/4346)) -- **removed `VERSION`** file that was used for checking version updates ([#3677](https://github.com/docker-mailserver/docker-mailserver/issues/3677),[#4321](https://github.com/docker-mailserver/docker-mailserver/pull/4321)) ### Security @@ -31,9 +29,11 @@ All notable changes to this project will be documented in this file. The format - **Internal:** - Add password confirmation to several `setup` CLI subcommands ([#4072](https://github.com/docker-mailserver/docker-mailserver/pull/4072)) + - Added a `debug getmail` subcommand to `setup` ([#4346](https://github.com/docker-mailserver/docker-mailserver/pull/4346)) ### Updates +- **Removed `VERSION` file** from the repo that releases of DMS prior to v13 (Nov 2023) would check to detect new releases ([#3677](https://github.com/docker-mailserver/docker-mailserver/issues/3677), [#4321](https://github.com/docker-mailserver/docker-mailserver/pull/4321)) - **Fail2ban:** - Updated to version [`1.1.0`](https://github.com/fail2ban/fail2ban/releases/tag/1.1.0) ([#4045](https://github.com/docker-mailserver/docker-mailserver/pull/4045)) - **Documentation:** @@ -54,11 +54,12 @@ All notable changes to this project will be documented in this file. The format - Correctly apply a compatibility fix for OAuth2 introduced in DMS v13.3.1 which had not been applied to the actual LDAP config changes ([#4175](https://github.com/docker-mailserver/docker-mailserver/pull/4175)) - **Internal:** - The main `mail.log` (_which is piped to stdout via `tail`_) now correctly begins from the first log line of the active container run. Previously some daemon logs and potential warnings/errors were omitted ([#4146](https://github.com/docker-mailserver/docker-mailserver/pull/4146)) - - Fixed a regression introduced in v14 where `postfix-main.cf` appended `stderr` output into `/etc/postfix/main.cf`, causing Postfix startup to fail ([#4147](https://github.com/docker-mailserver/docker-mailserver/pull/4147)) - `start-mailserver.sh` removed unused `shopt -s inherit_errexit` ([#4161](https://github.com/docker-mailserver/docker-mailserver/pull/4161)) + - Fixed a regression introduced in v14 where `postfix-main.cf` appended `stderr` output into `/etc/postfix/main.cf`, causing Postfix startup to fail ([#4147](https://github.com/docker-mailserver/docker-mailserver/pull/4147)) + - Fixed a regression introduced in v14 to better support running `start-mailserver.sh` with container restarts, which now only skip calling `_setup()` ([#4323](https://github.com/docker-mailserver/docker-mailserver/pull/4323#issuecomment-2629559254)) + - The command `swaks --help` is now functional ([#4282](https://github.com/docker-mailserver/docker-mailserver/pull/4282)) - **Rspamd:** - DKIM private key path checking is now performed only on paths that do not contain `$` ([#4201](https://github.com/docker-mailserver/docker-mailserver/pull/4201)) -- The command `swaks --help` is now functional ([#4282](https://github.com/docker-mailserver/docker-mailserver/pull/4282)) ### CI diff --git a/target/scripts/start-mailserver.sh b/target/scripts/start-mailserver.sh index f6ceadf5..e820f746 100755 --- a/target/scripts/start-mailserver.sh +++ b/target/scripts/start-mailserver.sh @@ -38,7 +38,6 @@ function _register_functions() { # ? >> Checks _register_check_function '_check_hostname' - _register_check_function '_check_log_level' _register_check_function '_check_spam_prefix' # ? >> Setup @@ -63,7 +62,6 @@ function _register_functions() { ;; ( 'LDAP' ) - _environment_variables_ldap _register_setup_function '_setup_ldap' ;; @@ -76,15 +74,8 @@ function _register_functions() { ;; esac - if [[ ${ENABLE_OAUTH2} -eq 1 ]]; then - _environment_variables_oauth2 - _register_setup_function '_setup_oauth2' - fi - - if [[ ${ENABLE_SASLAUTHD} -eq 1 ]]; then - _environment_variables_saslauthd - _register_setup_function '_setup_saslauthd' - fi + [[ ${ENABLE_OAUTH2} -eq 1 ]] && _register_setup_function '_setup_oauth2' + [[ ${ENABLE_SASLAUTHD} -eq 1 ]] && _register_setup_function '_setup_saslauthd' _register_setup_function '_setup_dovecot_inet_protocols' @@ -122,20 +113,23 @@ function _register_functions() { _register_setup_function '_setup_logwatch' _register_setup_function '_setup_save_states' - _register_setup_function '_setup_apply_fixes_after_configuration' - _register_setup_function '_environment_variables_export' + _register_setup_function '_setup_adjust_state_permissions' if [[ ${ENABLE_MTA_STS} -eq 1 ]]; then _register_setup_function '_setup_mta_sts' _register_start_daemon '_start_daemon_mta_sts_daemon' fi + # ! The following functions must be executed after all other setup functions + _register_setup_function '_setup_directory_and_file_permissions' + _register_setup_function '_setup_run_user_patches' + # ? >> Daemons _register_start_daemon '_start_daemon_cron' _register_start_daemon '_start_daemon_rsyslog' - [[ ${SMTP_ONLY} -ne 1 ]] && _register_start_daemon '_start_daemon_dovecot' + [[ ${SMTP_ONLY} -ne 1 ]] && _register_start_daemon '_start_daemon_dovecot' if [[ ${ENABLE_UPDATE_CHECK} -eq 1 ]]; then if [[ ${DMS_RELEASE} != 'edge' ]]; then @@ -174,26 +168,24 @@ function _register_functions() { # ? >> Executing all stacks / actual start of DMS # ------------------------------------------------------------ +_early_supervisor_setup +_early_variables_setup + +_log 'info' "Welcome to docker-mailserver ${DMS_RELEASE}" + +_register_functions +_check + # Ensure DMS only adjusts config files for a new container. # Container restarts should skip as they retain the modified config. -if [[ ! -f /CONTAINER_START ]]; then - _early_supervisor_setup - _early_variables_setup - - _log 'info' "Welcome to docker-mailserver ${DMS_RELEASE}" - - _register_functions - _check - _setup - _run_user_patches +if [[ -f /CONTAINER_START ]]; then + _log 'info' 'Container was restarted. Skipping most setup routines.' + # We cannot skip all setup routines because some need to run _after_ + # the initial setup (and hence, they cannot be moved to the check stack). + _setup_directory_and_file_permissions + _setup_adjust_state_permissions else - # container was restarted - _early_variables_setup - - _log 'info' 'Container was restarted. Skipping setup routines.' - _log 'info' "Welcome to docker-mailserver ${DMS_RELEASE}" - - _register_functions + _setup fi # marker to check if container was restarted diff --git a/target/scripts/startup/check-stack.sh b/target/scripts/startup/check-stack.sh index 766fcccf..52d83ad4 100644 --- a/target/scripts/startup/check-stack.sh +++ b/target/scripts/startup/check-stack.sh @@ -26,24 +26,6 @@ function _check_hostname() { fi } -function _check_log_level() { - if [[ ${LOG_LEVEL} == 'trace' ]] \ - || [[ ${LOG_LEVEL} == 'debug' ]] \ - || [[ ${LOG_LEVEL} == 'info' ]] \ - || [[ ${LOG_LEVEL} == 'warn' ]] \ - || [[ ${LOG_LEVEL} == 'error' ]] - then - return 0 - else - local DEFAULT_LOG_LEVEL='info' - _log 'warn' "Log level '${LOG_LEVEL}' is invalid (falling back to default '${DEFAULT_LOG_LEVEL}')" - - # shellcheck disable=SC2034 - VARS[LOG_LEVEL]="${DEFAULT_LOG_LEVEL}" - LOG_LEVEL="${DEFAULT_LOG_LEVEL}" - fi -} - function _check_spam_prefix() { # This check should be independent of ENABLE_POP3 and ENABLE_IMAP if [[ ${MOVE_SPAM_TO_JUNK} -eq 0 ]] \ diff --git a/target/scripts/startup/setup-stack.sh b/target/scripts/startup/setup-stack.sh index 8c8e6461..789dc0c7 100644 --- a/target/scripts/startup/setup-stack.sh +++ b/target/scripts/startup/setup-stack.sh @@ -82,7 +82,7 @@ function _setup_timezone() { fi } -function _setup_apply_fixes_after_configuration() { +function _setup_directory_and_file_permissions() { _log 'trace' 'Removing leftover PID files from a stop/start' find /var/run/ -not -name 'supervisord.pid' -name '*.pid' -delete touch /dev/shm/supervisor.sock @@ -103,7 +103,7 @@ function _setup_apply_fixes_after_configuration() { fi } -function _run_user_patches() { +function _setup_run_user_patches() { local USER_PATCHES='/tmp/docker-mailserver/user-patches.sh' if [[ -f ${USER_PATCHES} ]]; then diff --git a/target/scripts/startup/setup.d/mail_state.sh b/target/scripts/startup/setup.d/mail_state.sh index e819c138..931e3c05 100644 --- a/target/scripts/startup/setup.d/mail_state.sh +++ b/target/scripts/startup/setup.d/mail_state.sh @@ -3,123 +3,129 @@ # Consolidate all states into a single directory # (/var/mail-state) to allow persistence using docker volumes function _setup_save_states() { - local DEST DESTDIR STATEDIR SERVICEDIR SERVICEDIRS SERVICEFILE SERVICEFILES - - STATEDIR='/var/mail-state' - - if [[ -d ${STATEDIR} ]]; then - _log 'debug' "Consolidating all state onto ${STATEDIR}" - - # Always enabled features: - SERVICEDIRS=( - lib/logrotate - lib/postfix - spool/postfix - ) - - # Only consolidate state for services that are enabled - # Notably avoids copying over 200MB for the ClamAV database - [[ ${ENABLE_AMAVIS} -eq 1 ]] && SERVICEDIRS+=('lib/amavis') - [[ ${ENABLE_CLAMAV} -eq 1 ]] && SERVICEDIRS+=('lib/clamav') - [[ ${ENABLE_FAIL2BAN} -eq 1 ]] && SERVICEDIRS+=('lib/fail2ban') - [[ ${ENABLE_FETCHMAIL} -eq 1 ]] && SERVICEDIRS+=('lib/fetchmail') - [[ ${ENABLE_GETMAIL} -eq 1 ]] && SERVICEDIRS+=('lib/getmail') - [[ ${ENABLE_MTA_STS} -eq 1 ]] && SERVICEDIRS+=('lib/mta-sts') - [[ ${ENABLE_POSTGREY} -eq 1 ]] && SERVICEDIRS+=('lib/postgrey') - [[ ${ENABLE_RSPAMD} -eq 1 ]] && SERVICEDIRS+=('lib/rspamd') - [[ ${ENABLE_RSPAMD_REDIS} -eq 1 ]] && SERVICEDIRS+=('lib/redis') - [[ ${ENABLE_SPAMASSASSIN} -eq 1 ]] && SERVICEDIRS+=('lib/spamassassin') - [[ ${ENABLE_SRS} -eq 1 ]] && SERVICEDIRS+=('lib/postsrsd') - [[ ${SMTP_ONLY} -ne 1 ]] && SERVICEDIRS+=('lib/dovecot') - - # Single service files - [[ ${ENABLE_SRS} -eq 1 ]] && SERVICEFILES+=('/etc/postsrsd.secret') - - for SERVICEFILE in "${SERVICEFILES[@]}"; do - DEST="${STATEDIR}/${SERVICEFILE}" - DESTDIR="${DEST%/*}" - - mkdir -p "${DESTDIR}" - if [[ -f ${DEST} ]]; then - _log 'trace' "Destination ${DEST} exists, linking ${SERVICEFILE} to it" - # Original content from image no longer relevant, remove it: - rm -f "${SERVICEFILE}" - elif [[ -f "${SERVICEFILE}" ]]; then - _log 'trace' "Moving ${SERVICEFILE} to ${DEST}" - # Empty volume was mounted, or new content from enabling a feature ENV: - mv "${SERVICEFILE}" "${DEST}" - # Apply SELinux security context to match the state directory, so access - # is not restricted to the current running container: - chcon -R --reference="${STATEDIR}" "${DEST}" 2>/dev/null || true - fi - - # Symlink the original file in the container ($SERVICEFILE) to be - # sourced from assocaiated path in /var/mail-state/ ($DEST): - ln -s "${DEST}" "${SERVICEFILE}" - done - - for SERVICEDIR in "${SERVICEDIRS[@]}"; do - DEST="${STATEDIR}/${SERVICEDIR//\//-}" - SERVICEDIR="/var/${SERVICEDIR}" - - # If relevant content is found in /var/mail-state (presumably a volume mount), - # use it instead. Otherwise copy over any missing directories checked. - if [[ -d ${DEST} ]]; then - _log 'trace' "Destination ${DEST} exists, linking ${SERVICEDIR} to it" - # Original content from image no longer relevant, remove it: - rm -rf "${SERVICEDIR}" - elif [[ -d ${SERVICEDIR} ]]; then - _log 'trace' "Moving contents of ${SERVICEDIR} to ${DEST}" - # An empty volume was mounted, or new content dir now exists from enabling a feature ENV: - mv "${SERVICEDIR}" "${DEST}" - # Apply SELinux security context to match the state directory, so access - # is not restricted to the current running container: - chcon -R --reference="${STATEDIR}" "${DEST}" 2>/dev/null || true - else - _log 'error' "${SERVICEDIR} should exist but is missing" - fi - - # Symlink the original path in the container ($SERVICEDIR) to be - # sourced from assocaiated path in /var/mail-state/ ($DEST): - ln -s "${DEST}" "${SERVICEDIR}" - done - - # This ensures the user and group of the files from the external mount have their - # numeric ID values in sync. New releases where the installed packages order changes - # can change the values in the Docker image, causing an ownership mismatch. - # NOTE: More details about users and groups added during image builds are documented here: - # https://github.com/docker-mailserver/docker-mailserver/pull/3011#issuecomment-1399120252 - _log 'trace' "Fixing ${STATEDIR}/* permissions" - [[ ${ENABLE_AMAVIS} -eq 1 ]] && chown -R amavis:amavis "${STATEDIR}/lib-amavis" - [[ ${ENABLE_CLAMAV} -eq 1 ]] && chown -R clamav:clamav "${STATEDIR}/lib-clamav" - [[ ${ENABLE_FETCHMAIL} -eq 1 ]] && chown -R fetchmail:nogroup "${STATEDIR}/lib-fetchmail" - [[ ${ENABLE_MTA_STS} -eq 1 ]] && chown -R _mta-sts:_mta-sts "${STATEDIR}/lib-mta-sts" - [[ ${ENABLE_POSTGREY} -eq 1 ]] && chown -R postgrey:postgrey "${STATEDIR}/lib-postgrey" - [[ ${ENABLE_RSPAMD} -eq 1 ]] && chown -R _rspamd:_rspamd "${STATEDIR}/lib-rspamd" - [[ ${ENABLE_RSPAMD_REDIS} -eq 1 ]] && chown -R redis:redis "${STATEDIR}/lib-redis" - [[ ${ENABLE_SPAMASSASSIN} -eq 1 ]] && chown -R debian-spamd:debian-spamd "${STATEDIR}/lib-spamassassin" - - chown -R root:root "${STATEDIR}/lib-logrotate" - chown -R postfix:postfix "${STATEDIR}/lib-postfix" - - # NOTE: The Postfix spool location has mixed owner/groups to take into account: - # UID = postfix(101): active, bounce, corrupt, defer, deferred, flush, hold, incoming, maildrop, private, public, saved, trace - # UID = root(0): dev, etc, lib, pid, usr - # GID = postdrop(103): maildrop, public - # GID for all other directories is root(0) - # NOTE: `spool-postfix/private/` will be set to `postfix:postfix` when Postfix starts / restarts - # Set most common ownership: - chown -R postfix:root "${STATEDIR}/spool-postfix" - chown root:root "${STATEDIR}/spool-postfix" - - # These two require the postdrop(103) group: - chgrp -R postdrop "${STATEDIR}"/spool-postfix/{maildrop,public} - - # These permissions rely on the `postdrop` binary having the SGID bit set. - # Ref: https://github.com/docker-mailserver/docker-mailserver/pull/3625 - chmod 730 "${STATEDIR}/spool-postfix/maildrop" - chmod 710 "${STATEDIR}/spool-postfix/public" - else - _log 'debug' "'${STATEDIR}' is not present; Not consolidating state" + if [[ ! -d ${DMS_STATE_DIR:?DMS_STATE_DIR is not set} ]]; then + _log 'debug' "'${DMS_STATE_DIR}' is not present - not consolidating state" + return 0 fi + + _log 'debug' "Consolidating all state onto ${DMS_STATE_DIR}" + + local DEST SERVICEDIR SERVICEDIRS SERVICEFILE SERVICEFILES + + # Always enabled features: + SERVICEDIRS=( + 'lib/logrotate' + 'lib/postfix' + 'spool/postfix' + ) + + # Only consolidate state for services that are enabled + # Notably avoids copying over 200MB for the ClamAV database + [[ ${ENABLE_AMAVIS} -eq 1 ]] && SERVICEDIRS+=('lib/amavis') + [[ ${ENABLE_CLAMAV} -eq 1 ]] && SERVICEDIRS+=('lib/clamav') + [[ ${ENABLE_FAIL2BAN} -eq 1 ]] && SERVICEDIRS+=('lib/fail2ban') + [[ ${ENABLE_FETCHMAIL} -eq 1 ]] && SERVICEDIRS+=('lib/fetchmail') + [[ ${ENABLE_GETMAIL} -eq 1 ]] && SERVICEDIRS+=('lib/getmail') + [[ ${ENABLE_MTA_STS} -eq 1 ]] && SERVICEDIRS+=('lib/mta-sts') + [[ ${ENABLE_POSTGREY} -eq 1 ]] && SERVICEDIRS+=('lib/postgrey') + [[ ${ENABLE_RSPAMD} -eq 1 ]] && SERVICEDIRS+=('lib/rspamd') + [[ ${ENABLE_RSPAMD_REDIS} -eq 1 ]] && SERVICEDIRS+=('lib/redis') + [[ ${ENABLE_SPAMASSASSIN} -eq 1 ]] && SERVICEDIRS+=('lib/spamassassin') + [[ ${ENABLE_SRS} -eq 1 ]] && SERVICEDIRS+=('lib/postsrsd') + [[ ${SMTP_ONLY} -ne 1 ]] && SERVICEDIRS+=('lib/dovecot') + + # Single service files + [[ ${ENABLE_SRS} -eq 1 ]] && SERVICEFILES+=('/etc/postsrsd.secret') + + for SERVICEFILE in "${SERVICEFILES[@]}"; do + DEST="${DMS_STATE_DIR}/${SERVICEFILE}" + + # Append service parent dir(s) path to the state dir and ensure it exists: + mkdir -p "${DEST%/*}" + if [[ -f ${DEST} ]]; then + _log 'trace' "Destination ${DEST} exists, linking ${SERVICEFILE} to it" + # Original content from image no longer relevant, remove it: + rm -f "${SERVICEFILE}" + elif [[ -f "${SERVICEFILE}" ]]; then + _log 'trace' "Moving ${SERVICEFILE} to ${DEST}" + # Empty volume was mounted, or new content from enabling a feature ENV: + mv "${SERVICEFILE}" "${DEST}" + # Apply SELinux security context to match the state directory, so access + # is not restricted to the current running container: + chcon -R --reference="${DMS_STATE_DIR}" "${DEST}" 2>/dev/null || true + fi + + # Symlink the original file in the container ($SERVICEFILE) to be + # sourced from assocaiated path in /var/mail-state/ ($DEST): + ln -s "${DEST}" "${SERVICEFILE}" + done + + for SERVICEDIR in "${SERVICEDIRS[@]}"; do + DEST="${DMS_STATE_DIR}/${SERVICEDIR//\//-}" + SERVICEDIR="/var/${SERVICEDIR}" + + # If relevant content is found in /var/mail-state (presumably a volume mount), + # use it instead. Otherwise copy over any missing directories checked. + if [[ -d ${DEST} ]]; then + _log 'trace' "Destination ${DEST} exists, linking ${SERVICEDIR} to it" + # Original content from image no longer relevant, remove it: + rm -rf "${SERVICEDIR}" + elif [[ -d ${SERVICEDIR} ]]; then + _log 'trace' "Moving contents of ${SERVICEDIR} to ${DEST}" + # An empty volume was mounted, or new content dir now exists from enabling a feature ENV: + mv "${SERVICEDIR}" "${DEST}" + # Apply SELinux security context to match the state directory, so access + # is not restricted to the current running container: + # https://github.com/docker-mailserver/docker-mailserver/pull/3890 + chcon -R --reference="${DMS_STATE_DIR}" "${DEST}" 2>/dev/null || true + else + _log 'error' "${SERVICEDIR} should exist but is missing" + fi + + # Symlink the original path in the container ($SERVICEDIR) to be + # sourced from associated path in /var/mail-state/ ($DEST): + ln -s "${DEST}" "${SERVICEDIR}" + done +} + +# These corrections are to fix changes to UID/GID values between upgrades, +# or when ownership/permissions were altered externally on the host (eg: migration or system scripts) +function _setup_adjust_state_permissions() { + [[ ! -d ${DMS_STATE_DIR:?DMS_STATE_DIR is not set} ]] && return 0 + + # This ensures the user and group of the files from the external mount have their + # numeric ID values in sync. New releases where the installed packages order changes + # can change the values in the Docker image, causing an ownership mismatch. + # NOTE: More details about users and groups added during image builds are documented here: + # https://github.com/docker-mailserver/docker-mailserver/pull/3011#issuecomment-1399120252 + _log 'trace' "Ensuring correct ownership + permissions for DMS state dir: '${DMS_STATE_DIR}'" + [[ ${ENABLE_AMAVIS} -eq 1 ]] && chown -R amavis:amavis "${DMS_STATE_DIR}/lib-amavis" + [[ ${ENABLE_CLAMAV} -eq 1 ]] && chown -R clamav:clamav "${DMS_STATE_DIR}/lib-clamav" + [[ ${ENABLE_FETCHMAIL} -eq 1 ]] && chown -R fetchmail:nogroup "${DMS_STATE_DIR}/lib-fetchmail" + [[ ${ENABLE_MTA_STS} -eq 1 ]] && chown -R _mta-sts:_mta-sts "${DMS_STATE_DIR}/lib-mta-sts" + [[ ${ENABLE_POSTGREY} -eq 1 ]] && chown -R postgrey:postgrey "${DMS_STATE_DIR}/lib-postgrey" + [[ ${ENABLE_RSPAMD} -eq 1 ]] && chown -R _rspamd:_rspamd "${DMS_STATE_DIR}/lib-rspamd" + [[ ${ENABLE_RSPAMD_REDIS} -eq 1 ]] && chown -R redis:redis "${DMS_STATE_DIR}/lib-redis" + [[ ${ENABLE_SPAMASSASSIN} -eq 1 ]] && chown -R debian-spamd:debian-spamd "${DMS_STATE_DIR}/lib-spamassassin" + + chown -R root:root "${DMS_STATE_DIR}/lib-logrotate" + chown -R postfix:postfix "${DMS_STATE_DIR}/lib-postfix" + + # NOTE: The Postfix spool location has mixed owner/groups to take into account: + # UID = postfix(101): active, bounce, corrupt, defer, deferred, flush, hold, incoming, maildrop, private, public, saved, trace + # UID = root(0): dev, etc, lib, pid, usr + # GID = postdrop(103): maildrop, public + # GID for all other directories is root(0) + # NOTE: `spool-postfix/private/` will be set to `postfix:postfix` when Postfix starts / restarts + # Set most common ownership: + chown -R postfix:root "${DMS_STATE_DIR}/spool-postfix" + chown root:root "${DMS_STATE_DIR}/spool-postfix" + + # These two require the postdrop(103) group: + chgrp -R postdrop "${DMS_STATE_DIR}"/spool-postfix/{maildrop,public} + + # These permissions rely on the `postdrop` binary having the SGID bit set. + # Ref: https://github.com/docker-mailserver/docker-mailserver/pull/3625 + chmod 730 "${DMS_STATE_DIR}/spool-postfix/maildrop" + chmod 710 "${DMS_STATE_DIR}/spool-postfix/public" } diff --git a/target/scripts/startup/variables-stack.sh b/target/scripts/startup/variables-stack.sh index 3fa4d761..f8f5af5e 100644 --- a/target/scripts/startup/variables-stack.sh +++ b/target/scripts/startup/variables-stack.sh @@ -4,9 +4,27 @@ declare -A VARS function _early_variables_setup() { + __environment_variables_log_level _obtain_hostname_and_domainname __environment_variables_backwards_compatibility __environment_variables_general_setup + + [[ ${ACCOUNT_PROVISIONER} == 'LDAP' ]] && __environment_variables_ldap + [[ ${ENABLE_OAUTH2} -eq 1 ]] && __environment_variables_oauth2 + [[ ${ENABLE_SASLAUTHD} -eq 1 ]] && __environment_variables_saslauthd + + __environment_variables_export +} + +# Declare a variable as readonly if it is not already set. +function __declare_readonly() { + local VARIABLE_NAME=${1:?Variable name required when declaring a variable as readonly} + local VARIABLE_VALUE=${2:?Variable value required when declaring a variable as readonly} + + if [[ ! -v ${VARIABLE_NAME} ]]; then + readonly "${VARIABLE_NAME}=${VARIABLE_VALUE}" + VARS[${VARIABLE_NAME}]="${VARIABLE_VALUE}" + fi } # This function handles variables that are deprecated. This allows a @@ -55,6 +73,12 @@ function __environment_variables_general_setup() { VARS[DMS_VMAIL_UID]="${DMS_VMAIL_UID:=5000}" VARS[DMS_VMAIL_GID]="${DMS_VMAIL_GID:=5000}" + # internal variables are next + + __declare_readonly 'DMS_STATE_DIR' '/var/mail-state' + + # user-customizable are last + _log 'trace' 'Setting anti-spam & anti-virus environment variables' VARS[AMAVIS_LOGLEVEL]="${AMAVIS_LOGLEVEL:=0}" @@ -159,15 +183,27 @@ function __environment_variables_general_setup() { VARS[UPDATE_CHECK_INTERVAL]="${UPDATE_CHECK_INTERVAL:=1d}" } -function _environment_variables_oauth2() { - _log 'debug' 'Setting OAUTH2-related environment variables now' +function __environment_variables_log_level() { + if [[ ${LOG_LEVEL} == 'trace' ]] \ + || [[ ${LOG_LEVEL} == 'debug' ]] \ + || [[ ${LOG_LEVEL} == 'info' ]] \ + || [[ ${LOG_LEVEL} == 'warn' ]] \ + || [[ ${LOG_LEVEL} == 'error' ]] + then + return 0 + else + local DEFAULT_LOG_LEVEL='info' + _log 'warn' "Log level '${LOG_LEVEL}' is invalid (falling back to default '${DEFAULT_LOG_LEVEL}')" - VARS[OAUTH2_INTROSPECTION_URL]="${OAUTH2_INTROSPECTION_URL:=}" + # shellcheck disable=SC2034 + VARS[LOG_LEVEL]="${DEFAULT_LOG_LEVEL}" + LOG_LEVEL="${DEFAULT_LOG_LEVEL}" + fi } # This function handles environment variables related to LDAP. # NOTE: SASLAuthd and Dovecot LDAP support inherit these common ENV. -function _environment_variables_ldap() { +function __environment_variables_ldap() { _log 'debug' 'Setting LDAP-related environment variables now' VARS[LDAP_BIND_DN]="${LDAP_BIND_DN:=}" @@ -177,9 +213,15 @@ function _environment_variables_ldap() { VARS[LDAP_START_TLS]="${LDAP_START_TLS:=no}" } +function __environment_variables_oauth2() { + _log 'debug' 'Setting OAUTH2-related environment variables now' + + VARS[OAUTH2_INTROSPECTION_URL]="${OAUTH2_INTROSPECTION_URL:=}" +} + # This function handles environment variables related to SASLAUTHD # LDAP specific ENV handled in: `startup/setup.d/saslauthd.sh:_setup_saslauthd()` -function _environment_variables_saslauthd() { +function __environment_variables_saslauthd() { _log 'debug' 'Setting SASLAUTHD-related environment variables now' # This ENV is only used by the supervisor service config `saslauth.conf`: @@ -190,7 +232,7 @@ function _environment_variables_saslauthd() { # This function Writes the contents of the `VARS` map (associative array) # to locations where they can be sourced from (e.g. `/etc/dms-settings`) # or where they can be used by Bash directly (e.g. `/root/.bashrc`). -function _environment_variables_export() { +function __environment_variables_export() { _log 'debug' "Exporting environment variables now (creating '/etc/dms-settings')" : >/root/.bashrc # make DMS variables available in login shells and their subprocesses From c66d8ce40b705f7ce9d67e12e48a26ca1a67be9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 10:36:20 +0100 Subject: [PATCH 18/80] chore(deps): Bump docker/setup-qemu-action from 3.3.0 to 3.4.0 (#4353) --- .github/workflows/generic_build.yml | 2 +- .github/workflows/generic_publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/generic_build.yml b/.github/workflows/generic_build.yml index 6000f5ff..53cb6893 100644 --- a/.github/workflows/generic_build.yml +++ b/.github/workflows/generic_build.yml @@ -71,7 +71,7 @@ jobs: cache-buildx- - name: 'Set up QEMU' - uses: docker/setup-qemu-action@v3.3.0 + uses: docker/setup-qemu-action@v3.4.0 with: platforms: arm64 diff --git a/.github/workflows/generic_publish.yml b/.github/workflows/generic_publish.yml index 42cde7ea..d5966a2b 100644 --- a/.github/workflows/generic_publish.yml +++ b/.github/workflows/generic_publish.yml @@ -35,7 +35,7 @@ jobs: type=semver,pattern={{major}}.{{minor}}.{{patch}} - name: 'Set up QEMU' - uses: docker/setup-qemu-action@v3.3.0 + uses: docker/setup-qemu-action@v3.4.0 with: platforms: arm64 From 83bfe72d489beda875717130eba9b348218f3bda Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Wed, 12 Feb 2025 11:56:51 +1300 Subject: [PATCH 19/80] chore: Migrate dovecot config from Dockerfile (#4350) --- Dockerfile | 10 ---- target/scripts/start-mailserver.sh | 1 - target/scripts/startup/setup.d/dovecot.sh | 59 ++++++++++++++++++++--- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/Dockerfile b/Dockerfile index 09295a22..32ac9ae8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -88,16 +88,6 @@ RUN dpkg -i /dovecot-fts-xapian-*.deb && rm /dovecot-fts-xapian-*.deb COPY target/dovecot/*.inc target/dovecot/*.conf /etc/dovecot/conf.d/ COPY target/dovecot/dovecot-purge.cron /etc/cron.d/dovecot-purge.disabled RUN chmod 0 /etc/cron.d/dovecot-purge.disabled -WORKDIR /usr/share/dovecot - -# hadolint ignore=SC2016,SC2086,SC2069 -RUN < Date: Wed, 12 Feb 2025 20:34:22 +0100 Subject: [PATCH 20/80] docs: Fix typo in DKIM and utils.sh (#4358) --- docs/content/config/best-practices/dkim_dmarc_spf.md | 4 ++-- target/scripts/helpers/utils.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/config/best-practices/dkim_dmarc_spf.md b/docs/content/config/best-practices/dkim_dmarc_spf.md index 2ef8e902..c04d4b7e 100644 --- a/docs/content/config/best-practices/dkim_dmarc_spf.md +++ b/docs/content/config/best-practices/dkim_dmarc_spf.md @@ -29,7 +29,7 @@ Cloudflare has written an [article about DKIM, DMARC and SPF][cloudflare-dkim-dm When DKIM is enabled: 1. Inbound mail will verify any included DKIM signatures -2. Outbound mail is signed (_when you're sending domain has a configured DKIM key_) +2. Outbound mail is signed (_when your sending domain has a configured DKIM key_) DKIM requires a public/private key pair to enable **signing (_via private key_)** your outgoing mail, while the receiving end must query DNS to **verify (_via public key_)** that the signature is trustworthy. @@ -76,7 +76,7 @@ You should have: ??? info "Changing the key size" The keypair generated for using with DKIM presently defaults to RSA-2048. This is a good size but you can lower the security to `1024-bit`, or increase it to `4096-bit` (_discouraged as that is excessive_). - + To generate a key with different size (_for RSA 1024-bit_) run: ```sh diff --git a/target/scripts/helpers/utils.sh b/target/scripts/helpers/utils.sh index c848e13e..90fd8f9b 100644 --- a/target/scripts/helpers/utils.sh +++ b/target/scripts/helpers/utils.sh @@ -122,7 +122,7 @@ function _reload_postfix() { # you can set the environment variable `POSTFIX_README_DIRECTORY='/new/dir/'` # (`POSTFIX_` is an arbitrary prefix, you can choose the one you like), # and then call this function: -# `_replace_by_env_in_file 'POSTFIX_' 'PATH TO POSTFIX's main.cf>` +# `_replace_by_env_in_file 'POSTFIX_' '` # # ## Panics # From 425d1162aeeeb532e12eeccd9548d31213c9f07f Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Fri, 14 Feb 2025 01:16:31 +1300 Subject: [PATCH 21/80] chore: `packages.sh` - Bump versions + housekeeping (#4357) --- CHANGELOG.md | 38 ++++++++++--------- target/scripts/build/compile.sh | 51 +++++++++++++++---------- target/scripts/build/packages.sh | 64 +++++++++++++++++++------------- 3 files changed, 90 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 379992c3..794c2e64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,20 +11,12 @@ All notable changes to this project will be documented in this file. The format - **saslauthd** mechanism support via ENV `SASLAUTHD_MECHANISMS` with `pam`, `shadow`, `mysql` values has been removed. Only `ldap` and `rimap` remain supported ([#4259](https://github.com/docker-mailserver/docker-mailserver/pull/4259)) - **getmail6** has been refactored: ([#4156](https://github.com/docker-mailserver/docker-mailserver/pull/4156)) - The [DMS config volume](https://docker-mailserver.github.io/docker-mailserver/v15.0/config/advanced/optional-config/#volumes) now has support for `getmailrc_general.cf` for overriding [common default settings](https://docker-mailserver.github.io/docker-mailserver/v15.0/config/advanced/mail-getmail/#common-options). If you previously mounted this config file directly to `/etc/getmailrc_general` you should switch to our config volume support. - - IMAP/POP3 example configs added to our [`config-examples`](https://github.com/docker-mailserver/docker-mailserver/tree/v15.0.0/config-examples/getmail). - - ENV [`GETMAIL_POLL`](https://docker-mailserver.github.io/docker-mailserver/v15.0/config/environment/#getmail_poll) now supports values above 30 minutes. - - Added `getmail` as a new service for `supervisor` to manage, replacing cron for periodic polling. - Generated getmail configuration files no longer set the `message_log` option. Instead of individual log files per config, the [default base settings DMS configures](https://github.com/docker-mailserver/docker-mailserver/tree/v15.0.0/target/getmail/getmailrc_general) now enables `message_log_syslog`. This aligns with how other services in DMS log to syslog where it is captured in `mail.log`. - Getmail configurations have changed location from the base of the DMS Config Volume, to the `getmail/` subdirectory. Any existing configurations **must be migrated manually.** - - DMS v14 mistakenly relocated the _getmail state directory_ to the _DMS Config Volume_ as a `getmail/` subdirectory. + - **DMS v14 mistakenly** relocated the _getmail state directory_ to the _DMS Config Volume_ as a `getmail/` subdirectory. - This has been corrected to `/var/lib/getmail` (_if you have mounted a DMS State Volume to `/var/mail-state`, `/var/lib/getmail` will be symlinked to `/var/mail-state/lib-getmail`_). - To preserve this state when upgrading to DMS v15, **you must manually migrate `getmail/` from the _DMS Config Volume_ to `lib-getmail/` in the _DMS State Volume_.** -### Security - -- **Fail2ban:** - - Ensure a secure connection, when downloading the fail2ban package ([#4080](https://github.com/docker-mailserver/docker-mailserver/pull/4080)) - ### Added - **Internal:** @@ -33,30 +25,40 @@ All notable changes to this project will be documented in this file. The format ### Updates -- **Removed `VERSION` file** from the repo that releases of DMS prior to v13 (Nov 2023) would check to detect new releases ([#3677](https://github.com/docker-mailserver/docker-mailserver/issues/3677), [#4321](https://github.com/docker-mailserver/docker-mailserver/pull/4321)) -- **Fail2ban:** - - Updated to version [`1.1.0`](https://github.com/fail2ban/fail2ban/releases/tag/1.1.0) ([#4045](https://github.com/docker-mailserver/docker-mailserver/pull/4045)) +**Internal:** + - **Removed `VERSION` file** from the repo. Releases of DMS prior to v13 (Nov 2023) would check this to detect new releases ([#3677](https://github.com/docker-mailserver/docker-mailserver/issues/3677), [#4321](https://github.com/docker-mailserver/docker-mailserver/pull/4321)) + - During image build, ensure a secure connection when downloading the `fail2ban` package ([#4080](https://github.com/docker-mailserver/docker-mailserver/pull/4080)) - **Documentation:** - Account Management and Authentication pages have been rewritten and better organized ([#4122](https://github.com/docker-mailserver/docker-mailserver/pull/4122)) - Add a caveat for `DMS_VMAIL_UID` not being compatible with `0` / root ([#4143](https://github.com/docker-mailserver/docker-mailserver/pull/4143)) +- **Getmail:** ([#4156](https://github.com/docker-mailserver/docker-mailserver/pull/4156)) + - Added `getmail` as a new service for `supervisor` to manage, replacing cron for periodic polling. + - IMAP/POP3 example configs added to our [`config-examples`](https://github.com/docker-mailserver/docker-mailserver/tree/v15.0.0/config-examples/getmail). + - ENV [`GETMAIL_POLL`](https://docker-mailserver.github.io/docker-mailserver/v15.0/config/environment/#getmail_poll) now supports values above 30 minutes. - **Postfix:** - By default opt-out from _Microsoft reactions_ for outbound mail ([#4120](https://github.com/docker-mailserver/docker-mailserver/pull/4120)) -- Updated `jaq` version from `1.3.0` to `2.0.0` ([#4190](https://github.com/docker-mailserver/docker-mailserver/pull/4190)) -- Updated Rspamd GTube settings and tests ([#4191](https://github.com/docker-mailserver/docker-mailserver/pull/4191)) +- **Rspamd:** + - Updated GTube settings and tests ([#4191](https://github.com/docker-mailserver/docker-mailserver/pull/4191)) +- Updated externally installed software ([#4357](https://github.com/docker-mailserver/docker-mailserver/pull/4357)): + - `DOVECOT_COMMUNITY_REPO=1` custom image build ARG now supports the latest Dovecot [`2.4.x`](https://github.com/dovecot/core/releases/tag/2.4.0) (_DMS provides Dovecot `2.3.19` by default_) + - Dovecot FTS Xapian module (`1.7.12` => [`1.9.0`](https://github.com/grosjo/fts-xapian/releases/tag/1.9)) + - `jaq` (`1.3.0` => [`2.1.0`](https://github.com/01mf02/jaq/releases/tag/v2.1.0)) + - Fail2Ban (`1.0.2-2` => [`1.1.0`](https://github.com/fail2ban/fail2ban/releases/tag/1.1.0)) ([#4045](https://github.com/docker-mailserver/docker-mailserver/pull/4045)) + - Rspamd (`3.8.4` => [`3.11.0`](https://github.com/rspamd/rspamd/releases/tag/3.11.0)) - Implicitly upgraded during image build, as the third-party repo lacks version pinning support. ### Fixes - **Dovecot:** - The logwatch `ignore.conf` now also excludes Xapian messages about pending documents ([#4060](https://github.com/docker-mailserver/docker-mailserver/pull/4060)) - - `dovecot-fts-xapian` plugin was updated to `1.7.13`, fixing a regression with indexing ([#4095](https://github.com/docker-mailserver/docker-mailserver/pull/4095)) + - `dovecot-fts-xapian` plugin was updated, fixing a regression with indexing ([#4095](https://github.com/docker-mailserver/docker-mailserver/pull/4095)) - The "dummy account" workaround for _Dovecot Quota_ feature support no longer treats the alias as a regex when checking the Dovecot UserDB ([#4222](https://github.com/docker-mailserver/docker-mailserver/pull/4222)) - **LDAP:** - - Correctly apply a compatibility fix for OAuth2 introduced in DMS v13.3.1 which had not been applied to the actual LDAP config changes ([#4175](https://github.com/docker-mailserver/docker-mailserver/pull/4175)) + - Correctly apply a compatibility fix for OAuth2 introduced in DMS `v13.3.1` which had not been applied to the actual LDAP config changes ([#4175](https://github.com/docker-mailserver/docker-mailserver/pull/4175)) - **Internal:** - The main `mail.log` (_which is piped to stdout via `tail`_) now correctly begins from the first log line of the active container run. Previously some daemon logs and potential warnings/errors were omitted ([#4146](https://github.com/docker-mailserver/docker-mailserver/pull/4146)) - `start-mailserver.sh` removed unused `shopt -s inherit_errexit` ([#4161](https://github.com/docker-mailserver/docker-mailserver/pull/4161)) - - Fixed a regression introduced in v14 where `postfix-main.cf` appended `stderr` output into `/etc/postfix/main.cf`, causing Postfix startup to fail ([#4147](https://github.com/docker-mailserver/docker-mailserver/pull/4147)) - - Fixed a regression introduced in v14 to better support running `start-mailserver.sh` with container restarts, which now only skip calling `_setup()` ([#4323](https://github.com/docker-mailserver/docker-mailserver/pull/4323#issuecomment-2629559254)) + - Fixed a regression introduced in DMS v14 where `postfix-main.cf` appended `stderr` output into `/etc/postfix/main.cf`, causing Postfix startup to fail ([#4147](https://github.com/docker-mailserver/docker-mailserver/pull/4147)) + - Fixed a regression introduced in DMS v14 to better support running `start-mailserver.sh` with container restarts, which now only skip calling `_setup()` ([#4323](https://github.com/docker-mailserver/docker-mailserver/pull/4323#issuecomment-2629559254)) - The command `swaks --help` is now functional ([#4282](https://github.com/docker-mailserver/docker-mailserver/pull/4282)) - **Rspamd:** - DKIM private key path checking is now performed only on paths that do not contain `$` ([#4201](https://github.com/docker-mailserver/docker-mailserver/pull/4201)) diff --git a/target/scripts/build/compile.sh b/target/scripts/build/compile.sh index c34a8833..bad84f23 100644 --- a/target/scripts/build/compile.sh +++ b/target/scripts/build/compile.sh @@ -11,28 +11,39 @@ source /usr/local/bin/helpers/log.sh # shellcheck disable=SC2310 _log_level_is 'trace' && QUIET='-y' || QUIET='-qq' -function _compile_dovecot_fts_xapian() { +function _install_build_deps() { apt-get "${QUIET}" update apt-get "${QUIET}" install --no-install-recommends \ automake libtool pkg-config libicu-dev libsqlite3-dev libxapian-dev make build-essential dh-make devscripts dovecot-dev - - local XAPIAN_VERSION='1.7.13' - curl -sSfL -o dovecot-fts-xapian.tar.gz \ - "https://github.com/grosjo/fts-xapian/releases/download/${XAPIAN_VERSION}/dovecot-fts-xapian-${XAPIAN_VERSION}.tar.gz" - tar xf dovecot-fts-xapian.tar.gz - - cd "fts-xapian-${XAPIAN_VERSION}" - USER=root dh_make -p "dovecot-fts-xapian-${XAPIAN_VERSION}" --single --native --copyright gpl2 -y - - rm debian/*.ex - cp PACKAGES/DEB/control debian/ - cp PACKAGES/DEB/changelog debian/ - cp PACKAGES/DEB/compat debian/ - - sed -i -E "s|(dovecot-fts-xapian)-[1-9\.-]+|\1-${XAPIAN_VERSION}|g" debian/control - sed -i -E "s|(dovecot-fts-xapian)-[1-9\.-]+ \(.*\)(.*)|\1-${XAPIAN_VERSION} (${XAPIAN_VERSION})\2|g" debian/changelog - - debuild -us -uc -B | tee /tmp/debuild.log 2>&1 } -_compile_dovecot_fts_xapian +function _build_package() { + local XAPIAN_VERSION='1.9' + curl -fsSL "https://github.com/grosjo/fts-xapian/releases/download/${XAPIAN_VERSION}/dovecot-fts-xapian-${XAPIAN_VERSION}.tar.gz" \ + | tar -xz + cd "fts-xapian-${XAPIAN_VERSION}" + + # Prepare for building DEB source package: + # https://manpages.debian.org/bookworm/dh-make/dh_make.1.en.html + # License LGPL 2.1: https://github.com/grosjo/fts-xapian/issues/174#issuecomment-2422404568 + USER=root dh_make --packagename "dovecot-fts-xapian-${XAPIAN_VERSION}" --single --native --copyright lgpl2 -y + # Remove generated example files: + rm debian/*.ex + # Add required package metadata: + # https://www.debian.org/doc/manuals/maint-guide/dreq.en.html#control + curl -fsSL https://raw.githubusercontent.com/grosjo/fts-xapian/refs/tags/1.7.16/PACKAGES/DEB/control > debian/control + # Replace version number: + sed -i -E "s|(dovecot-fts-xapian)-[1-9\.-]+|\1-${XAPIAN_VERSION}|g" debian/control + # Required to proceed with debuild: + # https://www.debian.org/doc/manuals/maint-guide/dother.en.html#compat + # (13 is the default debhelper version from the original `dh_make` generated `debian/control`): + echo '13' > debian/compat + + # Build arch specific binary package via debuild: + # https://manpages.debian.org/bookworm/devscripts/debuild.1.en.html + # https://manpages.debian.org/bookworm/dpkg-dev/dpkg-buildpackage.1.en.html + debuild --no-sign --build=any | tee /tmp/debuild.log 2>&1 +} + +_install_build_deps +_build_package diff --git a/target/scripts/build/packages.sh b/target/scripts/build/packages.sh index 787c84ac..bcfdcbcb 100644 --- a/target/scripts/build/packages.sh +++ b/target/scripts/build/packages.sh @@ -24,13 +24,14 @@ function _pre_installation_steps() { apt-get "${QUIET}" upgrade _log 'trace' 'Installing packages that are needed early' - # add packages usually required by apt to - # - not log unnecessary warnings - # - be able to add PPAs early (e.g., Rspamd) + # Add packages usually required by apt to: local EARLY_PACKAGES=( - apt-utils # avoid useless warnings - apt-transport-https ca-certificates curl gnupg # required for adding PPAs - systemd-standalone-sysusers # avoid problems with SA / Amavis (https://github.com/docker-mailserver/docker-mailserver/pull/3403#pullrequestreview-1596689953) + # Avoid logging unnecessary warnings: + apt-utils + # Required for adding third-party repos (/etc/apt/sources.list.d) as alternative package sources (eg: Dovecot CE and Rspamd): + apt-transport-https ca-certificates curl gnupg + # Avoid problems with SA / Amavis (https://github.com/docker-mailserver/docker-mailserver/pull/3403#pullrequestreview-1596689953): + systemd-standalone-sysusers ) apt-get "${QUIET}" install --no-install-recommends "${EARLY_PACKAGES[@]}" 2>/dev/null } @@ -38,7 +39,7 @@ function _pre_installation_steps() { function _install_utils() { _log 'debug' 'Installing utils sourced from Github' _log 'trace' 'Installing jaq' - local JAQ_TAG='v2.0.0' + local JAQ_TAG='v2.1.0' curl -sSfL "https://github.com/01mf02/jaq/releases/download/${JAQ_TAG}/jaq-$(uname -m)-unknown-linux-gnu" -o /usr/bin/jaq chmod +x /usr/bin/jaq @@ -136,43 +137,56 @@ function _install_dovecot() { dovecot-pop3d dovecot-sieve ) - # Dovecot packages for community supported features. + # Additional Dovecot packages for supporting the DMS community (docs-only guide contributions). DOVECOT_PACKAGES+=(dovecot-auth-lua) - # Dovecot's deb community repository only provides x86_64 packages, so do not include it - # when building for another architecture. + # (Opt-in via ENV) Change repo source for dovecot packages to a third-party repo maintained by Dovecot. + # NOTE: AMD64 / x86_64 is the only supported arch from the Dovecot CE repo (thus noDMS built for ARM64 / aarch64) + # Repo: https://repo.dovecot.org/ce-2.4-latest/debian/bookworm/dists/bookworm/main/ + # Docs: https://repo.dovecot.org/#debian if [[ ${DOVECOT_COMMUNITY_REPO} -eq 1 ]] && [[ "$(uname --machine)" == "x86_64" ]]; then - _log 'trace' 'Using Dovecot community repository' - curl -sSfL https://repo.dovecot.org/DOVECOT-REPO-GPG | gpg --import - gpg --export ED409DA1 > /etc/apt/trusted.gpg.d/dovecot.gpg - echo "deb https://repo.dovecot.org/ce-2.3-latest/debian/${VERSION_CODENAME} ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/dovecot.list + # WARNING: Repo only provides Debian Bookworm package support for Dovecot CE 2.4+. + # As Debian Bookworm only packages Dovecot 2.3.x, building DMS with this alternative package repo may not yet be compatible with DMS: + # - 2.3.19: https://salsa.debian.org/debian/dovecot/-/tree/stable/bookworm + # - 2.3.21: https://salsa.debian.org/debian/dovecot/-/tree/stable/bookworm-backports - _log 'trace' 'Updating Dovecot package signatures' + _log 'trace' 'Adding third-party package repository (Dovecot)' + curl -fsSL https://repo.dovecot.org/DOVECOT-REPO-GPG-2.4 | gpg --dearmor > /usr/share/keyrings/upstream-dovecot.gpg + echo \ + "deb [signed-by=/usr/share/keyrings/upstream-dovecot.gpg] https://repo.dovecot.org/ce-2.4-latest/debian/${VERSION_CODENAME} ${VERSION_CODENAME} main" \ + > /etc/apt/sources.list.d/upstream-dovecot.list + + # Refresh package index: apt-get "${QUIET}" update - # Additional community package needed for Lua support if the Dovecot community repository is used. + # This repo instead provides `dovecot-auth-lua` as a transitional package to `dovecot-lua`, + # thus this extra package is required to retain lua support: DOVECOT_PACKAGES+=(dovecot-lua) fi _log 'debug' 'Installing Dovecot' apt-get "${QUIET}" install --no-install-recommends "${DOVECOT_PACKAGES[@]}" - # dependency for fts_xapian + # Runtime dependency for fts_xapian (built via `compile.sh`): apt-get "${QUIET}" install --no-install-recommends libxapian30 } function _install_rspamd() { - _log 'debug' 'Installing Rspamd' - _log 'trace' 'Adding Rspamd PPA' - curl -sSfL https://rspamd.com/apt-stable/gpg.key | gpg --dearmor >/etc/apt/trusted.gpg.d/rspamd.gpg - echo \ - "deb [signed-by=/etc/apt/trusted.gpg.d/rspamd.gpg] http://rspamd.com/apt-stable/ ${VERSION_CODENAME} main" \ - >/etc/apt/sources.list.d/rspamd.list + # NOTE: DMS only supports the rspamd package via using the third-party repo maintained by Rspamd (AMD64 + ARM64): + # Repo: https://rspamd.com/apt-stable/dists/bookworm/main/ + # Docs: https://rspamd.com/downloads.html#debian-and-ubuntu-linux + # NOTE: Debian 12 provides Rspamd 3.4 (too old) and Rspamd discourages it's use - _log 'trace' 'Updating package index after adding PPAs' + _log 'trace' 'Adding third-party package repository (Rspamd)' + curl -fsSL https://rspamd.com/apt-stable/gpg.key | gpg --dearmor > /usr/share/keyrings/upstream-rspamd.gpg + echo \ + "deb [signed-by=/usr/share/keyrings/upstream-rspamd.gpg] https://rspamd.com/apt-stable/ ${VERSION_CODENAME} main" \ + > /etc/apt/sources.list.d/upstream-rspamd.list + + # Refresh package index: apt-get "${QUIET}" update - _log 'trace' 'Installing actual package' + _log 'debug' 'Installing Rspamd' apt-get "${QUIET}" install rspamd redis-server } From f2fedff251a91da3bfc1f780a17b30e1346a53a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Feb 2025 21:46:09 +0100 Subject: [PATCH 22/80] chore(deps): Bump docker/setup-buildx-action from 3.8.0 to 3.9.0 (#4352) --- .github/workflows/generic_build.yml | 2 +- .github/workflows/generic_publish.yml | 2 +- .github/workflows/generic_test.yml | 2 +- .github/workflows/generic_vulnerability-scan.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/generic_build.yml b/.github/workflows/generic_build.yml index 53cb6893..30d8df46 100644 --- a/.github/workflows/generic_build.yml +++ b/.github/workflows/generic_build.yml @@ -76,7 +76,7 @@ jobs: platforms: arm64 - name: 'Set up Docker Buildx' - uses: docker/setup-buildx-action@v3.8.0 + uses: docker/setup-buildx-action@v3.9.0 # NOTE: AMD64 can build within 2 minutes - name: 'Build images' diff --git a/.github/workflows/generic_publish.yml b/.github/workflows/generic_publish.yml index d5966a2b..72228d51 100644 --- a/.github/workflows/generic_publish.yml +++ b/.github/workflows/generic_publish.yml @@ -40,7 +40,7 @@ jobs: platforms: arm64 - name: 'Set up Docker Buildx' - uses: docker/setup-buildx-action@v3.8.0 + uses: docker/setup-buildx-action@v3.9.0 # Try get the cached build layers from a prior `generic_build.yml` job. # NOTE: Until adopting `type=gha` scoped cache exporter (in `docker/build-push-action`), diff --git a/.github/workflows/generic_test.yml b/.github/workflows/generic_test.yml index f28dbc9b..1303c8ad 100644 --- a/.github/workflows/generic_test.yml +++ b/.github/workflows/generic_test.yml @@ -38,7 +38,7 @@ jobs: # Ensures consistent BuildKit version (not coupled to Docker Engine), # and increased compatibility of the build cache vs mixing buildx drivers. - name: 'Set up Docker Buildx' - uses: docker/setup-buildx-action@v3.8.0 + uses: docker/setup-buildx-action@v3.9.0 # Importing from the cache should create the image within approx 30 seconds: # NOTE: `qemu` step is not needed as we only test for AMD64. diff --git a/.github/workflows/generic_vulnerability-scan.yml b/.github/workflows/generic_vulnerability-scan.yml index 3b20b2ed..511ade7a 100644 --- a/.github/workflows/generic_vulnerability-scan.yml +++ b/.github/workflows/generic_vulnerability-scan.yml @@ -37,7 +37,7 @@ jobs: # Ensures consistent BuildKit version (not coupled to Docker Engine), # and increased compatibility of the build cache vs mixing buildx drivers. - name: 'Set up Docker Buildx' - uses: docker/setup-buildx-action@v3.8.0 + uses: docker/setup-buildx-action@v3.9.0 # Importing from the cache should create the image within approx 30 seconds: # NOTE: `qemu` step is not needed as we only test for AMD64. From aba92b7bb83929fab296a4c5340133d3f5dadaeb Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Sun, 16 Feb 2025 21:53:01 +1300 Subject: [PATCH 23/80] ci: Upgrade `mkdocs-material` to 9.6 (#4368) --- .github/workflows/scripts/docs/build-docs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scripts/docs/build-docs.sh b/.github/workflows/scripts/docs/build-docs.sh index d4384b5e..4eac8c4d 100755 --- a/.github/workflows/scripts/docs/build-docs.sh +++ b/.github/workflows/scripts/docs/build-docs.sh @@ -11,7 +11,7 @@ docker run \ --user "$(id -u):$(id -g)" \ --volume "./:/docs" \ --name "build-docs" \ - squidfunk/mkdocs-material:9.5 build --strict + squidfunk/mkdocs-material:9.6 build --strict # Remove unnecessary build artifacts: https://github.com/squidfunk/mkdocs-material/issues/2519 # site/ is the build output folder. From 07e558e4bee524262c8ab18ad04e685b941e782d Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Sun, 16 Feb 2025 22:22:40 +1300 Subject: [PATCH 24/80] docs: Fix broken ref links (#4366) --- docs/content/config/best-practices/dkim_dmarc_spf.md | 2 +- docs/content/config/debugging.md | 2 +- docs/content/contributing/general.md | 11 +++++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/content/config/best-practices/dkim_dmarc_spf.md b/docs/content/config/best-practices/dkim_dmarc_spf.md index c04d4b7e..daea09d3 100644 --- a/docs/content/config/best-practices/dkim_dmarc_spf.md +++ b/docs/content/config/best-practices/dkim_dmarc_spf.md @@ -54,7 +54,7 @@ You'll need to repeat this process if you add any new domains. You should have: -- At least one [email account setup][docs-accounts-add] +- At least one [email account setup][docs-accounts] - Attached a [volume for config][docs-volumes-config] to persist the generated files to local storage !!! example "Creating DKIM Keys" diff --git a/docs/content/config/debugging.md b/docs/content/config/debugging.md index 30fee383..fca962f1 100644 --- a/docs/content/config/debugging.md +++ b/docs/content/config/debugging.md @@ -111,7 +111,7 @@ This could be from outdated software, or running a system that isn't able to pro - **Container runtime:** Docker and Podman for example have subtle differences. DMS docs are primarily focused on Docker, but we try to document known issues where relevant. - **Rootless containers:** Introduces additional differences in behavior or requirements: - cgroup v2 is required for supporting rootless containers. - - Differences such as for container networking which may further affect support for IPv6 and preserving the client IP (Remote address). Example with Docker rootless are [binding a port to a specific interface][docker-rootless-interface] and the choice of [port forwarding driver][docs-rootless-portdriver]. + - Differences such as for container networking which may further affect support for IPv6 and preserving the client IP (Remote address). Example with Docker rootless are [binding a port to a specific interface][docker-rootless-interface] and the choice of [port forwarding driver][docs::fail2ban::rootless-portdriver]. [network::docker-userlandproxy]: https://github.com/moby/moby/issues/44721 [network::docker-nftables]: https://github.com/moby/moby/issues/26824 diff --git a/docs/content/contributing/general.md b/docs/content/contributing/general.md index ea88dc85..a540f257 100644 --- a/docs/content/contributing/general.md +++ b/docs/content/contributing/general.md @@ -15,13 +15,20 @@ When refactoring, writing or altering scripts or other files, adhere to these ru Make sure to select `edge` in the dropdown menu at the top. Navigate to the page you would like to edit and click the edit button in the top right. This allows you to make changes and create a pull-request. -Alternatively you can make the changes locally. For that you'll need to have Docker installed. Navigate into the `docs/` directory. Then run: +Alternatively you can make the changes locally. For that you'll need to have Docker installed and run: ```sh -docker run --rm -it -p 8000:8000 -v "${PWD}:/docs" squidfunk/mkdocs-material +# From the root directory of the git clone: +docker run --rm -it -p 8000:8000 -v "./docs:/docs" squidfunk/mkdocs-material ``` This serves the documentation on your local machine on port `8000`. Each change will be hot-reloaded onto the page you view, just edit, save and look at the result. +!!! note + + The container logs will inform you of invalid links detected, but a [few are false-positives][gh-dms::mkdocs-link-error-false-positives] due to our usage of linking to specific [content tabs][mkdocs::content-tabs]. + [get-docker]: https://docs.docker.com/get-docker/ [docs-bats-parallel]: https://bats-core.readthedocs.io/en/v1.8.2/usage.html#parallel-execution +[gh-dms::mkdocs-link-error-false-positives]: https://github.com/docker-mailserver/docker-mailserver/pull/4366 +[mkdocs::content-tabs]: https://squidfunk.github.io/mkdocs-material/reference/content-tabs/#anchor-links From 0ebf820b00fcc7c634229c5df50d5c36cb2a9c8f Mon Sep 17 00:00:00 2001 From: Casper Date: Sun, 16 Feb 2025 10:46:49 +0100 Subject: [PATCH 25/80] Make deletion of mailbox data opt-in (#4365) Co-authored-by: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> --- CHANGELOG.md | 1 + target/bin/delmailuser | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 794c2e64..36e51e41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file. The format - **DMS v14 mistakenly** relocated the _getmail state directory_ to the _DMS Config Volume_ as a `getmail/` subdirectory. - This has been corrected to `/var/lib/getmail` (_if you have mounted a DMS State Volume to `/var/mail-state`, `/var/lib/getmail` will be symlinked to `/var/mail-state/lib-getmail`_). - To preserve this state when upgrading to DMS v15, **you must manually migrate `getmail/` from the _DMS Config Volume_ to `lib-getmail/` in the _DMS State Volume_.** + - `setup email delete ` now requires explicit confirmation if the mailbox data should be deleted ([#4365](https://github.com/docker-mailserver/docker-mailserver/pull/4365)). ### Added diff --git a/target/bin/delmailuser b/target/bin/delmailuser index c4b68ff3..9488953e 100755 --- a/target/bin/delmailuser +++ b/target/bin/delmailuser @@ -19,7 +19,11 @@ function _main() { for MAIL_ACCOUNT in "${@}"; do _account_should_already_exist - [[ ${MAILDEL} -eq 1 ]] && _remove_maildir "${MAIL_ACCOUNT}" + if [[ ${MAILDEL} -eq 1 ]]; then + _remove_maildir "${MAIL_ACCOUNT}" + else + _log 'info' "The mailbox data will not be deleted." + fi _manage_virtual_aliases_delete '_' "${MAIL_ACCOUNT}" \ || _exit_with_error "Aliases for '${MAIL_ACCOUNT}' could not be deleted" @@ -31,7 +35,7 @@ function _main() { _manage_accounts_delete "${MAIL_ACCOUNT}" \ || _exit_with_error "'${MAIL_ACCOUNT}' could not be deleted" - _log 'info' "'${MAIL_ACCOUNT}' and associated data deleted" + _log 'info' "'${MAIL_ACCOUNT}' and associated data (aliases, quotas) deleted" done } @@ -43,14 +47,14 @@ ${ORANGE}USAGE${RESET} ${ORANGE}OPTIONS${RESET} -y - Skip prompt by approving to ${LWHITE}delete all mail storage${RESET} for the account(s). + Skip prompt by approving to ${LWHITE}delete all mail data${RESET} for the account(s). ${BLUE}Generic Program Information${RESET} help Print the usage information. ${ORANGE}DESCRIPTION${RESET} Delete a mail account, including associated data (aliases, quotas) and - optionally the mailbox storage for that account. + optionally the mailbox data for that account. ${ORANGE}EXAMPLES${RESET} ${LWHITE}./setup.sh email del user@example.com${RESET} @@ -87,12 +91,10 @@ function _parse_options() { function _maildel_request_if_missing() { if [[ ${MAILDEL} -eq 0 ]]; then local MAILDEL_CHOSEN - read -r -p "Do you want to delete the mailbox as well (removing all mails)? [Y/n] " MAILDEL_CHOSEN + read -r -p "Do you want to delete the mailbox data as well (removing all mails)? [y/N] " MAILDEL_CHOSEN - # TODO: Why would MAILDEL be set to true if MAILDEL_CHOSEN is empty? - if [[ ${MAILDEL_CHOSEN} =~ (y|Y|yes|Yes) ]] || [[ -z ${MAILDEL_CHOSEN} ]]; then - MAILDEL=1 - fi + # Delete mailbox data only if the user provides explicit confirmation. + [[ ${MAILDEL_CHOSEN,,} == "y" ]] && MAILDEL=1 fi } @@ -103,10 +105,10 @@ function _remove_maildir() { local DOMAIN_PART="${MAIL_ACCOUNT#*@}" local MAIL_ACCOUNT_STORAGE_DIR="/var/mail/${DOMAIN_PART}/${LOCAL_PART}" - [[ ! -d ${MAIL_ACCOUNT_STORAGE_DIR} ]] && _exit_with_error "Mailbox directory '${MAIL_ACCOUNT_STORAGE_DIR}' does not exist" + [[ ! -d ${MAIL_ACCOUNT_STORAGE_DIR} ]] && _exit_with_error "Mailbox data directory '${MAIL_ACCOUNT_STORAGE_DIR}' does not exist" - _log 'info' "Deleting Mailbox: '${MAIL_ACCOUNT_STORAGE_DIR}'" - rm -R "${MAIL_ACCOUNT_STORAGE_DIR}" || _exit_with_error 'Mailbox could not be deleted' + _log 'info' "Deleting mailbox data: '${MAIL_ACCOUNT_STORAGE_DIR}'" + rm -R "${MAIL_ACCOUNT_STORAGE_DIR}" || _exit_with_error 'Mailbox data could not be deleted' # Remove parent directory too if it's empty: rmdir "/var/mail/${DOMAIN_PART}" &>/dev/null } From bcee78e2c1c310c4815b3e03c5e9278ad8ef1343 Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Mon, 17 Feb 2025 11:17:29 +1300 Subject: [PATCH 26/80] docs: Revise Rspamd page (#4360) --- docs/content/config/security/rspamd.md | 257 +++++++++++++++---------- 1 file changed, 159 insertions(+), 98 deletions(-) diff --git a/docs/content/config/security/rspamd.md b/docs/content/config/security/rspamd.md index c49baea6..45f94c65 100644 --- a/docs/content/config/security/rspamd.md +++ b/docs/content/config/security/rspamd.md @@ -6,34 +6,60 @@ title: 'Security | Rspamd' Rspamd is a ["fast, free and open-source spam filtering system"][rspamd-web]. DMS integrates Rspamd like any other service. We provide a basic but easy to maintain setup of Rspamd. -If you want to take a look at the default configuration files for Rspamd that DMS packs, navigate to [`target/rspamd/` inside the repository][dms-repo::default-rspamd-configuration]. Please consult the [section "The Default Configuration"](#the-default-configuration) section down below for a written overview. +If you want to take a look at the default configuration files for Rspamd that DMS adds, navigate to [`target/rspamd/` inside the repository][dms-repo::default-rspamd-configuration]. Please consult the [section "The Default Configuration"](#the-default-configuration) section down below for a written overview. -## Related Environment Variables +### Enable Rspamd -The following environment variables are related to Rspamd: +Rspamd is presently opt-in for DMS, but intended to become the default anti-spam service in a future release. -1. [`ENABLE_RSPAMD`](../environment.md#enable_rspamd) -2. [`ENABLE_RSPAMD_REDIS`](../environment.md#enable_rspamd_redis) -3. [`RSPAMD_CHECK_AUTHENTICATED`](../environment.md#rspamd_check_authenticated) -4. [`RSPAMD_GREYLISTING`](../environment.md#rspamd_greylisting) -5. [`RSPAMD_HFILTER`](../environment.md#rspamd_hfilter) -6. [`RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE`](../environment.md#rspamd_hfilter_hostname_unknown_score) -7. [`RSPAMD_LEARN`](../environment.md#rspamd_learn) -8. [`SPAM_SUBJECT`](../environment.md#spam_subject) -9. [`MOVE_SPAM_TO_JUNK`][docs::spam-to-junk] -10. [`MARK_SPAM_AS_READ`](../environment.md#mark_spam_as_read) +DMS offers two anti-spam solutions: -With these variables, you can enable Rspamd itself, and you can enable / disable certain features related to Rspamd. +- Legacy (_Amavis, SpamAssassin, OpenDKIM, OpenDMARC_) +- Rspamd (_Provides equivalent features of software from the legacy solution_) -## The Default Configuration +While you could configure Rspamd to only replace some of the legacy services, it is advised to only use Rspamd with the legacy services disabled. -### Other Anti-Spam-Services +!!! example "Switch to Rspamd" -DMS packs other anti-spam services, like SpamAssassin or Amavis, next to Rspamd. There exist services, like ClamAV (`ENABLE_CLAMAV`), that Rspamd can utilize to improve the scanning. Except for ClamAV, we recommend disabling **all other** anti-spam services when using Rspamd. The [basic configuration shown below](#a-very-basic-configuration) provides a good starting point. + To use Rspamd add the following ENV config changes: + + ```env + ENABLE_RSPAMD=1 + + # Rspamd replaces the functionality of all these anti-spam services, disable them: + ENABLE_OPENDKIM=0 + ENABLE_OPENDMARC=0 + ENABLE_POLICYD_SPF=0 + ENABLE_AMAVIS=0 + ENABLE_SPAMASSASSIN=0 + # Greylisting is opt-in, if you had enabled Postgrey switch to the Rspamd equivalent: + ENABLE_POSTGREY=0 + RSPAMD_GREYLISTING=1 + + # Optional: Add anti-virus support with ClamAV (compatible with Rspamd): + ENABLE_CLAMAV=1 + ``` + +!!! info "Relevant Environment Variables" + + The following environment variables are related to Rspamd: + + 1. [`ENABLE_RSPAMD`](../environment.md#enable_rspamd) + 2. [`ENABLE_RSPAMD_REDIS`](../environment.md#enable_rspamd_redis) + 3. [`RSPAMD_CHECK_AUTHENTICATED`](../environment.md#rspamd_check_authenticated) + 4. [`RSPAMD_GREYLISTING`](../environment.md#rspamd_greylisting) + 5. [`RSPAMD_HFILTER`](../environment.md#rspamd_hfilter) + 6. [`RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE`](../environment.md#rspamd_hfilter_hostname_unknown_score) + 7. [`RSPAMD_LEARN`](../environment.md#rspamd_learn) + 8. [`SPAM_SUBJECT`](../environment.md#spam_subject) + 9. [`MOVE_SPAM_TO_JUNK`][docs::spam-to-junk] + 10. [`MARK_SPAM_AS_READ`](../environment.md#mark_spam_as_read) + +## Overview of Rspamd support ### Mode of Operation -!!! tip "Attention" +!!! note "Attention" Read this section carefully if you want to understand how Rspamd is integrated into DMS and how it works (on a surface level). @@ -79,13 +105,16 @@ DMS does not set a default password for the controller worker. You may want to d When Rspamd is enabled, we implicitly also start an instance of Redis in the container: - Redis is configured to persist its data via RDB snapshots to disk in the directory `/var/lib/redis` (_or the [`/var/mail-state/`][docs::dms-volumes-state] volume when present_). -- With the volume mount, the snapshot will restore the Redis data across container restarts, and provide a way to keep backup. +- With the volume mount, the snapshot will restore the Redis data across container updates, and provide a way to keep a backup. +- Without a volume mount a containers internal state will persist across restarts until the container is recreated due to changes like ENV or upgrading the image for the container. Redis uses `/etc/redis/redis.conf` for configuration: - We adjust this file when enabling the internal Redis service. - If you have an external instance of Redis to use, the internal Redis service can be opt-out via setting the ENV [`ENABLE_RSPAMD_REDIS=0`][docs::env::enable-redis] (_link also details required changes to the DMS Rspamd config_). +If you are interested in using Valkey instead of Redis, please refer to [this guidance][gh-dms::guide::valkey]. + ### Web Interface Rspamd provides a [web interface][rspamd-docs::web-ui], which contains statistics and data Rspamd collects. The interface is enabled by default and reachable on port 11334. @@ -96,7 +125,7 @@ To use the web interface you will need to configure a password, [otherwise you w ??? example "Set a custom password" - Add this line to [your rspamd `custom-commands.conf` config](#with-the-help-of-a-custom-file) which sets the `password` option of the _controller worker_: + Add this line to [your Rspamd `custom-commands.conf` config](#with-the-help-of-a-custom-file) which sets the `password` option of the _controller worker_: ``` set-option-for-controller password "your hashed password here" @@ -108,9 +137,13 @@ To use the web interface you will need to configure a password, [otherwise you w docker exec -it rspamadm pw ``` + --- + + **Related:** A minimal Rspamd `compose.yaml` [example with a reverse-proxy for web access][gh-dms:guide::rspamd-web]. + ### DNS -DMS does not supply custom values for DNS servers (to Rspamd). If you need to use custom DNS servers, which could be required when using [DNS-based deny/allowlists](#rbls-real-time-blacklists-dnsbls-dns-based-blacklists), you need to adjust [`options.inc`][rspamd-docs::basic-options] yourself. Make sure to also read our [FAQ page on DNS servers][docs::faq::dns-servers]. +DMS does not supply custom values for DNS servers (to Rspamd). If you need to use custom DNS servers, which could be required when using [DNS-based deny/allowlists](#rbls-real-time-blacklists-dnsbls-dns-based-blacklists), you need to adjust [`options.inc`][rspamd-docs::config::global] yourself. Make sure to also read our [FAQ page on DNS servers][docs::faq::dns-servers]. !!! warning @@ -142,7 +175,7 @@ You can choose to enable ClamAV, and Rspamd will then use it to check for viruse #### RBLs (Real-time Blacklists) / DNSBLs (DNS-based Blacklists) -The [RBL module][rspamd-docs::modules::rbl] is enabled by default. As a consequence, Rspamd will perform DNS lookups to various blacklists. Whether an RBL or a DNSBL is queried depends on where the domain name was obtained: RBL servers are queried with IP addresses extracted from message headers, DNSBL server are queried with domains and IP addresses extracted from the message body \[[source][www::rbl-vs-dnsbl]\]. +The [RBL module][rspamd-docs::modules::rbl] is enabled by default. As a consequence, Rspamd will perform DNS lookups to various blacklists. Whether an RBL or a DNSBL is queried depends on where the domain name was obtained: RBL servers are queried with IP addresses extracted from message headers, DNSBL server are queried with domains and IP addresses extracted from the message body ([source][www::rbl-vs-dnsbl]). !!! danger "Rspamd and DNS Block Lists" @@ -152,124 +185,141 @@ The [RBL module][rspamd-docs::modules::rbl] is enabled by default. As a conseque ## Providing Custom Settings & Overriding Settings -DMS brings sane default settings for Rspamd. They are located at `/etc/rspamd/local.d/` inside the container (or `target/rspamd/local.d/` in the repository). +!!! info "Rspamd config overriding precedence" -### Manually + Rspamd has a layered approach for configuration with [`local.d` and `override.d` config directories][rspamd-docs::config-directories]. -!!! question "What is [`docker-data/dms/config/`][docs::dms-volumes-config]?" + - DMS [extends the Rspamd default configs via `/etc/rspamd/local.d/`][dms-repo::default-rspamd-configuration]. + - User config changes should be handled separately as overrides via the [DMS Config Volume][docs::dms-volumes-config] (`docker-data/dms/config/`) with either: + - `./rspamd/override.d/` - Config files placed here are copied to `/etc/rspamd/override.d/` during container startup. + - [`./rspamd/custom-commands.conf`](#with-the-help-of-a-custom-file) - Applied after copying any provided configs from `rspamd/override.d/` (DMS Config volume) to `/etc/rspamd/override.d/`. -If you want to overwrite the default settings or provide your settings, you can place files at `docker-data/dms/config/rspamd/override.d/`. Files from this directory are copied to `/etc/rspamd/override.d/` during startup. These files [forcibly override][rspamd-docs::override-dir] Rspamd and DMS default settings. +!!! abstract "Reference docs for Rspamd config" -!!! question "What is the [`local.d` directory and how does it compare to `override.d`][rspamd-docs::config-directories]?" + - [Config Overview][rspamd-docs::config::overview], [Quickstart guide][rspamd-docs::config::quickstart], and [Config Syntax (UCL)][rspamd-docs::config::ucl-syntax] + - Global Options ([`options.inc`][rspamd-docs::config::global]) + - [Workers][rspamd-docs::config::workers] ([`worker-controller.inc`][rspamd-docs::config::worker-controller], [`worker-proxy.inc`][rspamd-docs::config::worker-proxy]) + - [Modules][rspamd-docs::modules] (_view each module page for their specific config options_) -!!! warning "Clashing Overrides" +!!! tip "View rendered config" - Note that when also [using the `custom-commands.conf` file](#with-the-help-of-a-custom-file), files in `override.d` may be overwritten in case you adjust them manually and with the help of the file. + `rspamadm configdump` will output the full rspamd configuration that is used should you need it for troubleshooting / inspection. -### With the Help of a Custom File + - You can also see which modules are enabled / disabled via `rspamadm configdump --modules-state` + - Specific config sections like `dkim` or `worker` can also be used to filter the output to just those sections: `rspamadm configdump dkim worker` + - Use `--show-help` to include inline documentation for many settings. -DMS provides the ability to do simple adjustments to Rspamd modules with the help of a single file. Just place a file called `custom-commands.conf` into `docker-data/dms/config/rspamd/`. If this file is present, DMS will evaluate it. The structure is simple, as each line in the file looks like this: +### Using `custom-commands.conf` { #with-the-help-of-a-custom-file } -```txt -COMMAND ARGUMENT1 ARGUMENT2 ARGUMENT3 -``` +For convenience DMS provides a single config file that will directly create or modify multiple configs at `/etc/rspamd/override.d/`. This is handled as the final rspamd configuration step during container startup. -where `COMMAND` can be: +DMS will apply this config when you provide `rspamd/custom-commands.conf` in your DMS Config volume. Configure it with directive lines as documented below. -1. `disable-module`: disables the module with name `ARGUMENT1` -2. `enable-module`: explicitly enables the module with name `ARGUMENT1` -3. `set-option-for-module`: sets the value for option `ARGUMENT2` to `ARGUMENT3` inside module `ARGUMENT1` -4. `set-option-for-controller`: set the value of option `ARGUMENT1` to `ARGUMENT2` for the controller worker -5. `set-option-for-proxy`: set the value of option `ARGUMENT1` to `ARGUMENT2` for the proxy worker -6. `set-common-option`: set the option `ARGUMENT1` that [defines basic Rspamd behavior][rspamd-docs::basic-options] to value `ARGUMENT2` -7. `add-line`: this will add the complete line after `ARGUMENT1` (with all characters) to the file `/etc/rspamd/override.d/` +!!! note "Only use this feature for `option = value` changes" -!!! example "An Example Is [Shown Down Below](#adjusting-and-extending-the-very-basic-configuration)" + `custom-commands.conf` is only suitable for adding or replacing simple `option = value` settings for configs at `/etc/rspamd/override.d/`. + + - New settings are appended to the associated config file. + - When replacing an existing setting in an override config, that setting may be any matching line (_allowing for nested scopes, instead of only top-level keys_). + + Any changes involving more advanced [UCL config syntax][rspamd-docs::config::ucl-syntax] should instead add UCL config files directly to `rspamd/override.d/` (_in the DMS Config volume_). -!!! note "File Names & Extensions" +!!! info "`custom-commands.conf` syntax" - For command 1 - 3, we append the `.conf` suffix to the module name to get the correct file name automatically. For commands 4 - 6, the file name is fixed (you don't even need to provide it). For command 7, you will need to provide the whole file name (including the suffix) yourself! + There are 7 directives available to manage custom Rspamd configurations. Add these directive lines into `custom-commands.conf`, they will be processed sequentially. -You can also have comments (the line starts with `#`) and blank lines in `custom-commands.conf` - they are properly handled and not evaluated. + **Directives:** -!!! tip "Adjusting Modules This Way" + ```txt + # For /etc/rspamd/override.d/{options.inc,worker-controller.inc,worker-proxy}.inc + set-common-option