Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 22 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ Thank you very much.
- [A converted example](#a-converted-example)
- [Checking the result](#checking-the-result)
- [Clearing the rspamd hyperscan cache after an rspamd upgrade](#clearing-the-rspamd-hyperscan-cache-after-an-rspamd-upgrade)
- [Migration from Traefik 2 to 3](#migration-from-traefik-2-to-3)
- [Migration from Traefik 1 to 2](#migration-from-traefik-1-to-2)
- [Migration from 1.0 to 1.1](#migration-from-10-to-11)
- [Migration from hardware/mailserver to mailserver2/mailserver](#migration-from-hardwaremailserver-to-mailserver2mailserver)
Expand Down Expand Up @@ -264,12 +265,11 @@ At first launch, the container takes few minutes to generate SSL certificates (i

| Service | URI |
| --------------------- | -------------------------------- |
| **Traefik dashboard** | https://mail.domain.tld/ |
| **Rspamd dashboard** | https://spam.domain.tld/ |
| **Administration** | https://postfixadmin.domain.tld/ |
| **Webmail** | https://webmail.domain.tld/ |

Traefik dashboard use a basic authentication (user:admin, password:12345), the password can be encoded in MD5, SHA1 and BCrypt. You can use [htpasswd ](https://httpd.apache.org/docs/2.4/programs/htpasswd.html) to generate those ones. Users can be specified directly in the `traefik.toml` file. Rspamd dashboard use the password defined in your `docker-compose.yml`.
The Traefik dashboard is not exposed by this configuration, see the [Traefik documentation](https://doc.traefik.io/traefik/operations/dashboard/) to enable it. Rspamd dashboard use the password defined in your `docker-compose.yml`.

You can check the startup logs with this command:

Expand Down Expand Up @@ -495,7 +495,7 @@ You can use this variable to allow other local containers to relay via the mails

#### Let's Encrypt certificates generated by Traefik

To use Let's Encrypt certificates generated by Traefik, mount a new docker volume like this:
To use Let's Encrypt certificates generated by Traefik, mount the Traefik `acme` folder in the mailserver container:

```yml
mailserver:
Expand All @@ -505,80 +505,37 @@ mailserver:
...
```

The startup script read the `acme.json`* file generated by Traefik and split into pem files all appropriate certificates (CN = mail.domain.tld).
:bulb: On a host running SELinux in enforcing mode, append `:z` to that mount, so that both containers are allowed to access the folder.

:bulb: *Compatible with both Traefik `>=1.5.0` and `1.6+` ACME json format, with **SAN** and **wildcard** certificates support.
The startup script reads `acme.json`, extracts the certificate issued for your mailserver FQDN (default: `mail.domain.tld`) and reloads Postfix and Dovecot every time Traefik renews it. A wildcard certificate for your domain (`*.domain.tld`) is used as well, when `acme.json` contains one.

```
docker logs -f mailserver

[INFO] Search for SSL certificates generated by Traefik
[INFO] acme.json found with ACME v2 format, dumping into pem files
[INFO] Let's encrypt live directory found
[INFO] Using /etc/letsencrypt/live/mail.domain.tld folder
```

Don't forget to add a new Traefik frontend rule somewhere in your docker-compose.yml to generate a certificate for your mailserver FQDN (default: mail.domain.tld) subdomain.
Traefik only requests certificates for the domains it serves, so your FQDN has to appear in the labels of one of your containers. In [docker-compose.sample.yml](docker-compose.sample.yml) the Rspamd router does this, by requesting a certificate whose main domain is the mailserver FQDN:

```yml
# docker-compose.yml

labels:
- traefik.frontend.rule=Host:mail.${DOMAIN}
- "traefik.http.routers.spam.rule=Host(`spam.${MAILSERVER_DOMAIN}`)"
- "traefik.http.routers.spam.tls.certresolver=letsencrypt"
- "traefik.http.routers.spam.tls.domains[0].main=${MAILSERVER_HOSTNAME}.${MAILSERVER_DOMAIN}"
- "traefik.http.routers.spam.tls.domains[0].sans=spam.${MAILSERVER_DOMAIN}"
```

Alternatively, you can specify your domains in the `traefik.toml` to generate a SAN certificate:
:warning: A wildcard certificate can only be issued through a `DNS-01` challenge. To use one, replace the `tlsChallenge` section of `traefik.toml` with your [DNS provider](https://doc.traefik.io/traefik/https/acme/#dnschallenge):

```toml
[acme]
onHostRule = false

[[acme.domains]]
main = "domain.tld"
sans = ["mail.domain.tld", "spam.domain.tld", "postfixadmin.domain.tld", "webmail.domain.tld"]
```

Or a wildcard certificate:

:warning: ACME wildcard certificates can only be generated thanks to a `DNS-01` challenge.

```toml
[acme]
onHostRule = false

# https://docs.traefik.io/v1.6/configuration/acme/#dnschallenge
[acme.dnsChallenge]
# traefik.toml
[certificatesResolvers.letsencrypt.acme.dnsChallenge]
provider = "your_dns_provider"
delayBeforeCheck = 0

[[acme.domains]]
main = "*.domain.tld"
```

If the startup script does not find the appropriate SSL certificate and private key, look at the Traefik logs to see what's going on.
If the mailserver does not find a certificate, it logs:

```
docker logs -f mailserver

[INFO] Search for SSL certificates generated by Traefik
[INFO] ...
[INFO] ...
[INFO] acme.json found with ACME v2 format, dumping into pem files
[ERROR] The certificate for mail.domain.tld or the private key was not found !
[INFO] Don't forget to add a new traefik frontend rule to generate a certificate for mail.domain.tld subdomain
[INFO] Look /mnt/docker/traefik/acme/dump.log and 'docker logs traefik' for more information
```

```toml
# traefik.toml

[acme]
acmeLogging = true
```
Check that Traefik actually issued it with `docker logs traefik`, after setting `level = "DEBUG"` in the `[log]` section of `traefik.toml`. When the extraction itself fails, its output is kept in `/mnt/docker/mail/ssl/acme_dump.log`.

```
docker-compose restart traefik && docker logs -f traefik
```
:bulb: `acme.json` has the same format in Traefik 2 and 3. Files written by Traefik 1.x are still supported, their configuration is described in the [Traefik 1.7 documentation](https://doc.traefik.io/traefik/v1.7/configuration/acme/).

#### Custom certificates

Expand Down Expand Up @@ -1325,6 +1282,12 @@ docker compose exec mailserver ls /var/log/mail.err

<p align="right"><a href="#summary">Back to table of contents :arrow_up_small:</a></p>

### Migration from Traefik 2 to 3

Migrating from Traefik 2 to 3 only changes the version of the Traefik image. The labels in [docker-compose.sample.yml](docker-compose.sample.yml), [traefik.sample.toml](traefik.sample.toml) and [file.sample.toml](file.sample.toml) are accepted by Traefik 3 unchanged, and `acme.json` keeps the same format, so your existing certificates are kept. If you added routers of your own, check the [Traefik v3 migration guide](https://doc.traefik.io/traefik/migrate/v2-to-v3/): the router rule syntax changed in v3.

<p align="right"><a href="#summary">Back to table of contents :arrow_up_small:</a></p>

### Migration from Traefik 1 to 2

Migrating from traefik 1 to 2 does not change any mailserver images that are used, only the traefik image version. You do need to update traefik labels on all containers as per [docker-compose.sample.yml](docker-compose.sample.yml). When you do this, either delete your acme.json and let traefik request the new certificate, or use the [tool](https://github.com/traefik/traefik-migration-tool) to convert from v1 to v2.
Expand Down
2 changes: 1 addition & 1 deletion sample.env
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ POSTFIXADMIN_DOCKER_TAG=3.2.4

RAINLOOP_DOCKER_TAG=1.14.0

TRAEFIK_DOCKER_TAG=2.2.11
TRAEFIK_DOCKER_TAG=3.7

# Docker volumes parent folder
VOLUMES_ROOT_PATH=/mnt/docker
Expand Down
Loading