[GH-ISSUE #286] Configure a Traefik proxy #192

Closed
opened 2026-03-15 13:07:01 +03:00 by kerem · 6 comments
Owner

Originally created by @SimoSca on GitHub (Apr 25, 2024).
Original GitHub issue: https://github.com/axllent/mailpit/issues/286

First of all, thanks for your work!

As requested in https://mailpit.axllent.org/docs/configuration/proxy/, I'll share my custom notes about usage of Traefik Proxy via docker containers.

I have a "global" traefik instance running over the machine, and single docker-compose.yml files with dns services exposed via Traefik, and that's why I'll use the network_mode: bridge.

Traefik tls

Before using traefik, you must have a traefik service running and configured with the smtp entrypoint,
which simply could listen for example on port 25.

You can use traefik to manage the smtp traffic via tls on smtp entrypoint:

services:
  joomla:
    depends_on:
      - mailpit
    extra_hosts:
      - "my-project-dns-smtp.example.invalid:host-gateway"
  mailpit:
    image: axllent/mailpit:latest
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      # WEB GUI
      - "traefik.tcp.routers.my-project_gui.entrypoints=web-secure"
      - "traefik.http.routers.my-project_gui.rule=Host(`my-project-dns.example.invalid`)"
      - "traefik.http.routers.my-project_gui.service=svc_my-project_gui"
      - "traefik.http.services.svc_my-project_gui.loadbalancer.server.port=8025"
      # SMTP SERVER
      # tls true is needed to use HostSNI
      - "traefik.tcp.routers.my-project_smtp.tls=true"
      # You must specify HostSNI, if "*" or specific hostname, depends on your needs
      #- "traefik.tcp.routers.my-project_smtp.rule=HostSNI(`*`)"
      - "traefik.tcp.routers.my-project_smtp.rule=HostSNI(`my-project-dns-smtp.example.invalid`)"
      - "traefik.tcp.routers.my-project_smtp.entrypoints=smtp"
      - "traefik.tcp.routers.my-project_smtp.service=my-project_smtp"
      - "traefik.tcp.services.my-project_smtp.loadbalancer.server.port=1025"
    hostname: 'mailpit-host'
    network_mode: "bridge"

in this case, you MUST set the smtp port to 25 (that is the traefik entrypoint for smtp) and the hostname
to my-project-dns-smtp.example.invalid plus the ssl/tls directive.

NOTE:

  • the HostSNI(...) is mandatory and over tls, so tls directive/setup (both traefik and smtp client) is mandatory
  • in this case traefik manages tls (certificates) on port smpt, then pass the traffic to the service without tls, so the service don't need to manage certificates
  • the starttls connection doesn't work with traefik, so you must use tls directive or no secure connection (tested also in passthrough mode)

As another case, you can use traefik simply as passthrough, so the service manages the certificates:

services:
  joomla:
    depends_on:
      - mailpit
    extra_hosts:
      - "my-project-dns-smtp.example.invalid:host-gateway"
  mailpit:
    image: axllent/mailpit:latest
    restart: unless-stopped
    volumes:
      - ./wildcard.fullchain.pem:/etc/ssl/certs/wildcard.fullchain.pem
      - ./wildcard.privkey.pem:/etc/ssl/private/wildcard.privkey.pem
    environment:
      # If you use letsencrypt certificates, set the "fullchain" cert and related private key
      MP_SMTP_TLS_CERT: /etc/ssl/certs/wildcard.fullchain.pem
      MP_SMTP_TLS_KEY: /etc/ssl/private/wildcard.privkey.pem
      MP_SMTP_REQUIRE_TLS: true
      # MP_SMTP_REQUIRE_STARTTLS: true
    labels:
      - "traefik.enable=true"
      # WEB GUI
      - "traefik.tcp.routers.my-project_gui.entrypoints=web-secure"
      - "traefik.http.routers.my-project_gui.rule=Host(`my-project-dns.example.invalid`)"
      - "traefik.http.routers.my-project_gui.service=svc_my-project_gui"
      - "traefik.http.services.svc_my-project_gui.loadbalancer.server.port=8025"
      # SMTP SERVER
      # tls true is needed to use HostSNI
      - "traefik.tcp.routers.my-project_smtp.tls=true"
      #- "traefik.tcp.routers.my-project_smtp.rule=HostSNI(`*`)"
      - "traefik.tcp.routers.my-project_smtp.rule=HostSNI(`my-project-dns-smtp.example.invalid`)"
      - "traefik.tcp.routers.my-project_smtp.entrypoints=smtp" # opzionale, ma meglio specificarlo
      - "traefik.tcp.routers.my-project_smtp.service=my-project_smtp"
      - "traefik.tcp.routers.my-project_smtp.tls.passthrough=true"
      - "traefik.tcp.services.my-project_smtp.loadbalancer.server.port=1025"
    hostname: 'mailpit-host'
    network_mode: "bridge"

as you can see, with passthrough directive, we moved the effort to the "mailpit" service, so the service must manage the certificates.

STARTTLS

If you want to use starttls to secure your connection, you must exclude traefik, and contact directly the service:

services:
  joomla:
    depends_on:
      - mailpit
    extra_hosts:
      - "my-project-dns-smtp.example.invalid:host-gateway"
  mailpit:
    image: axllent/mailpit:latest
    restart: unless-stopped
    volumes:
      - ./wildcard.fullchain.pem:/etc/ssl/certs/wildcard.fullchain.pem
      - ./wildcard.privkey.pem:/etc/ssl/private/wildcard.privkey.pem
    environment:
      MP_SMTP_TLS_CERT: /etc/ssl/certs/wildcard.fullchain.pem
      MP_SMTP_TLS_KEY: /etc/ssl/private/wildcard.privkey.pem
      MP_SMTP_AUTH: "user1:pass1" # example of auth
      # MP_SMTP_REQUIRE_TLS: true
      MP_SMTP_REQUIRE_STARTTLS: true
    # It's important to expose the port:
    ports:
      - "1025:1025"
    labels:
      - "traefik.enable=true"
      # WEB GUI
      - "traefik.tcp.routers.jmy-project_gui.entrypoints=web-secure"
      - "traefik.http.routers.my-project_gui.rule=Host(`my-project-dns.example.invalid`)"
      - "traefik.http.routers.my-project_gui.service=svc_my-project_gui"
      - "traefik.http.services.svc_my-project_gui.loadbalancer.server.port=8025"
    hostname: 'mailpit-host'
    network_mode: "bridge"

In this case you must configure the client to work with starttls, point to port 1025 and hostname my-project-dns-smtp.example.invalid.

IMPORTANT

Alternatively to explicit mount, you could create a custom private image with the certificates inside, and with default environment variables
MP_SMTP_TLS_CERT and MP_SMTP_TLS_KEY pointing to the certificates inside the image.

Originally created by @SimoSca on GitHub (Apr 25, 2024). Original GitHub issue: https://github.com/axllent/mailpit/issues/286 First of all, thanks for your work! As requested in https://mailpit.axllent.org/docs/configuration/proxy/, I'll share my custom notes about usage of Traefik Proxy via docker containers. I have a "global" traefik instance running over the machine, and single docker-compose.yml files with dns services exposed via Traefik, and that's why I'll use the `network_mode: bridge`. ### Traefik tls > Before using traefik, you must have a traefik service running and configured with the `smtp` entrypoint, > which simply could listen for example on port 25. You can use traefik to manage the smtp traffic via `tls` on `smtp` entrypoint: ````yaml services: joomla: depends_on: - mailpit extra_hosts: - "my-project-dns-smtp.example.invalid:host-gateway" mailpit: image: axllent/mailpit:latest restart: unless-stopped labels: - "traefik.enable=true" # WEB GUI - "traefik.tcp.routers.my-project_gui.entrypoints=web-secure" - "traefik.http.routers.my-project_gui.rule=Host(`my-project-dns.example.invalid`)" - "traefik.http.routers.my-project_gui.service=svc_my-project_gui" - "traefik.http.services.svc_my-project_gui.loadbalancer.server.port=8025" # SMTP SERVER # tls true is needed to use HostSNI - "traefik.tcp.routers.my-project_smtp.tls=true" # You must specify HostSNI, if "*" or specific hostname, depends on your needs #- "traefik.tcp.routers.my-project_smtp.rule=HostSNI(`*`)" - "traefik.tcp.routers.my-project_smtp.rule=HostSNI(`my-project-dns-smtp.example.invalid`)" - "traefik.tcp.routers.my-project_smtp.entrypoints=smtp" - "traefik.tcp.routers.my-project_smtp.service=my-project_smtp" - "traefik.tcp.services.my-project_smtp.loadbalancer.server.port=1025" hostname: 'mailpit-host' network_mode: "bridge" ```` in this case, you MUST set the smtp port to 25 (that is the traefik entrypoint for smtp) and the hostname to `my-project-dns-smtp.example.invalid` plus the `ssl/tls` directive. NOTE: - the `HostSNI(...)` is mandatory and over tls, so `tls` directive/setup (both traefik and smtp client) is mandatory - in this case traefik manages `tls` (certificates) on port `smpt`, then pass the traffic to the service without `tls`, so the service don't need to manage certificates - the `starttls` connection doesn't work with traefik, so you must use `tls` directive or no secure connection (tested also in `passthrough` mode) As another case, you can use traefik simply as passthrough, so the service manages the certificates: ````yaml services: joomla: depends_on: - mailpit extra_hosts: - "my-project-dns-smtp.example.invalid:host-gateway" mailpit: image: axllent/mailpit:latest restart: unless-stopped volumes: - ./wildcard.fullchain.pem:/etc/ssl/certs/wildcard.fullchain.pem - ./wildcard.privkey.pem:/etc/ssl/private/wildcard.privkey.pem environment: # If you use letsencrypt certificates, set the "fullchain" cert and related private key MP_SMTP_TLS_CERT: /etc/ssl/certs/wildcard.fullchain.pem MP_SMTP_TLS_KEY: /etc/ssl/private/wildcard.privkey.pem MP_SMTP_REQUIRE_TLS: true # MP_SMTP_REQUIRE_STARTTLS: true labels: - "traefik.enable=true" # WEB GUI - "traefik.tcp.routers.my-project_gui.entrypoints=web-secure" - "traefik.http.routers.my-project_gui.rule=Host(`my-project-dns.example.invalid`)" - "traefik.http.routers.my-project_gui.service=svc_my-project_gui" - "traefik.http.services.svc_my-project_gui.loadbalancer.server.port=8025" # SMTP SERVER # tls true is needed to use HostSNI - "traefik.tcp.routers.my-project_smtp.tls=true" #- "traefik.tcp.routers.my-project_smtp.rule=HostSNI(`*`)" - "traefik.tcp.routers.my-project_smtp.rule=HostSNI(`my-project-dns-smtp.example.invalid`)" - "traefik.tcp.routers.my-project_smtp.entrypoints=smtp" # opzionale, ma meglio specificarlo - "traefik.tcp.routers.my-project_smtp.service=my-project_smtp" - "traefik.tcp.routers.my-project_smtp.tls.passthrough=true" - "traefik.tcp.services.my-project_smtp.loadbalancer.server.port=1025" hostname: 'mailpit-host' network_mode: "bridge" ```` as you can see, with `passthrough` directive, we moved the effort to the "mailpit" service, so the service must manage the certificates. ### STARTTLS If you want to use `starttls` to secure your connection, you must exclude traefik, and contact directly the service: ````yaml services: joomla: depends_on: - mailpit extra_hosts: - "my-project-dns-smtp.example.invalid:host-gateway" mailpit: image: axllent/mailpit:latest restart: unless-stopped volumes: - ./wildcard.fullchain.pem:/etc/ssl/certs/wildcard.fullchain.pem - ./wildcard.privkey.pem:/etc/ssl/private/wildcard.privkey.pem environment: MP_SMTP_TLS_CERT: /etc/ssl/certs/wildcard.fullchain.pem MP_SMTP_TLS_KEY: /etc/ssl/private/wildcard.privkey.pem MP_SMTP_AUTH: "user1:pass1" # example of auth # MP_SMTP_REQUIRE_TLS: true MP_SMTP_REQUIRE_STARTTLS: true # It's important to expose the port: ports: - "1025:1025" labels: - "traefik.enable=true" # WEB GUI - "traefik.tcp.routers.jmy-project_gui.entrypoints=web-secure" - "traefik.http.routers.my-project_gui.rule=Host(`my-project-dns.example.invalid`)" - "traefik.http.routers.my-project_gui.service=svc_my-project_gui" - "traefik.http.services.svc_my-project_gui.loadbalancer.server.port=8025" hostname: 'mailpit-host' network_mode: "bridge" ```` In this case you must configure the client to work with `starttls`, point to port `1025` and hostname `my-project-dns-smtp.example.invalid`. **IMPORTANT** Alternatively to explicit mount, you could create a custom private image with the certificates inside, and with default environment variables `MP_SMTP_TLS_CERT` and `MP_SMTP_TLS_KEY` pointing to the certificates inside the image.
kerem 2026-03-15 13:07:01 +03:00
Author
Owner

@axllent commented on GitHub (Apr 25, 2024):

Thanks @SimoSca! Can you please confirm for me that the websocket connections works with this setup? The easy way to tell is whether the icon to the left of "Inbox" (in the side navigation) is an envelope, or a reload (circle with an arrow).

<!-- gh-comment-id:2078230380 --> @axllent commented on GitHub (Apr 25, 2024): Thanks @SimoSca! Can you please confirm for me that the websocket connections works with this setup? The easy way to tell is whether the icon to the left of "Inbox" (in the side navigation) is an envelope, or a reload (circle with an arrow).
Author
Owner

@SimoSca commented on GitHub (Apr 26, 2024):

Hi @axllent , yes, I confirm that websocket works with this setup.

<!-- gh-comment-id:2079029929 --> @SimoSca commented on GitHub (Apr 26, 2024): Hi @axllent , yes, I confirm that websocket works with this setup.
Author
Owner

@axllent commented on GitHub (Apr 26, 2024):

Awesome, thanks so much for the notes and confirmation. I have added this to the website so others can reference it 👍

<!-- gh-comment-id:2079040286 --> @axllent commented on GitHub (Apr 26, 2024): Awesome, thanks so much for the notes and confirmation. I have added this to the website so others can reference it :+1:
Author
Owner

@jortizbs commented on GitHub (Jun 10, 2024):

Hello @axllent and @SimoSca.

I have tried following @SimonSca's documentation, but I have not managed to make it work.

I have configured it using Traefik as TLS handler.
So the Mailpit service does not handle certificates.

I have tried to test it in the following ways:

Without TLS
/mailpit sendmail < email.txt -> works as the documentation states

With TLS
/mailpit sendmail -S “my-domain-name”:“my-traefik-port” < email.txt -> shows error

error sending mail
FATA[2024/06/10 11:15:11] EOF

Using sendmail command directly
sendmail -H 'openssl s_client -host “my-domain-name” -port “my-traefik-port -msg” < email.txt -> shows error

Connecting to 20.0.0.2
sendmail: SMTP init failed

Using openssl command directly
openssl s_client -host “my-domain-name” -port “my-traefik-port -msg

In this case, it seems to connect and Traefik resolves the certificates

<<< TLS 1.2, RecordHeader [length 0005]
    17 03 03 00 46
220 e764e14bf7b9 Mailpit ESMTP Service ready

The problem is that I can't close the message

mail from: <f@test.com>
>>> TLS 1.2, RecordHeader [length 0005]
    17 03 03 00 30
<<< TLS 1.2, RecordHeader [length 0005]
    17 03 03 00 26
250 2.1.0 Ok
rcpt to: <t@test.com>
>>> TLS 1.2, RecordHeader [length 0005]
    17 03 03 00 2e
<<< TLS 1.2, RecordHeader [length 0005]
    17 03 03 00 26
250 2.1.5 Ok
data
>>> TLS 1.2, RecordHeader [length 0005] 17 03 03 00 1d
    17 03 03 00 1d
<<< TLS 1.2, RecordHeader [length 0005] 17 03 03 00 1d
    17 03 03 00 4a
354 Begin mail entry; ends with <CR><LF>.<CR><LF>.
This is an email test.
>>> TLS 1.2, RecordHeader [length 0005].
    17 03 03 00 30
.
>>> TLS 1.2, RecordHeader [length 0005]
    17 03 03 00 1a

>>> TLS 1.2, RecordHeader [length 0005] 17 03 03 00 19 .
    17 03 03 00 19

Could you please tell me how to test it to verify that it works.

I don't know if I am doing something wrong.

Thank you very much.

<!-- gh-comment-id:2158112513 --> @jortizbs commented on GitHub (Jun 10, 2024): Hello @axllent and @SimoSca. I have tried following @SimonSca's documentation, but I have not managed to make it work. I have configured it using Traefik as TLS handler. So the Mailpit service does not handle certificates. I have tried to test it in the following ways: **Without TLS** `/mailpit sendmail < email.txt` -> works as the documentation states **With TLS** `/mailpit sendmail -S “my-domain-name”:“my-traefik-port” < email.txt` -> shows error ``` error sending mail FATA[2024/06/10 11:15:11] EOF ``` **Using sendmail command directly** `sendmail -H 'openssl s_client -host “my-domain-name” -port “my-traefik-port -msg” < email.txt` -> shows error ``` Connecting to 20.0.0.2 sendmail: SMTP init failed ``` **Using openssl command directly** `openssl s_client -host “my-domain-name” -port “my-traefik-port -msg` In this case, it seems to connect and Traefik resolves the certificates ``` <<< TLS 1.2, RecordHeader [length 0005] 17 03 03 00 46 220 e764e14bf7b9 Mailpit ESMTP Service ready ``` The problem is that I can't close the message ``` mail from: <f@test.com> >>> TLS 1.2, RecordHeader [length 0005] 17 03 03 00 30 <<< TLS 1.2, RecordHeader [length 0005] 17 03 03 00 26 250 2.1.0 Ok rcpt to: <t@test.com> >>> TLS 1.2, RecordHeader [length 0005] 17 03 03 00 2e <<< TLS 1.2, RecordHeader [length 0005] 17 03 03 00 26 250 2.1.5 Ok data >>> TLS 1.2, RecordHeader [length 0005] 17 03 03 00 1d 17 03 03 00 1d <<< TLS 1.2, RecordHeader [length 0005] 17 03 03 00 1d 17 03 03 00 4a 354 Begin mail entry; ends with <CR><LF>.<CR><LF>. This is an email test. >>> TLS 1.2, RecordHeader [length 0005]. 17 03 03 00 30 . >>> TLS 1.2, RecordHeader [length 0005] 17 03 03 00 1a >>> TLS 1.2, RecordHeader [length 0005] 17 03 03 00 19 . 17 03 03 00 19 ``` Could you please tell me how to test it to verify that it works. I don't know if I am doing something wrong. Thank you very much.
Author
Owner

@jortizbs commented on GitHub (Jun 10, 2024):

Hi, I have seen what was the problem with openssl, I had to add the Input/Output -crlf option.

That way it allowed me to close the message to send it.

<!-- gh-comment-id:2158497870 --> @jortizbs commented on GitHub (Jun 10, 2024): Hi, I have seen what was the problem with openssl, I had to add the Input/Output -crlf option. That way it allowed me to close the message to send it.
Author
Owner

@anasmirza534 commented on GitHub (Dec 17, 2024):

Above config not worked for me on Traefik v3. Lots of trial and error, then finally worked. Sharing reference for others.

label for smtp

labels:
  - "traefik.tcp.routers.mailpit_smtp.tls=false"
  - "traefik.tcp.routers.mailpit_smtp.entrypoints=smtp"
  - "traefik.tcp.routers.mailpit_smtp.service=mailpit_smtp"
  - "traefik.tcp.services.mailpit_smtp.loadbalancer.server.port=1025"
  - "traefik.tcp.routers.mailpit_smtp.rule=HostSNI(`*`)"
  - "traefik.tcp.routers.mailpit_smtp.tls.domains[0].main=mailpit-smtp.example.com"
  - "traefik.tcp.routers.mailpit_smtp.tls.domains[0].sans="
  - "traefik.tcp.routers.mailpit_smtp.tls.passthrough=true"

need to add smtp entry point into traefik static config, I have added port 1025 both in static config and bound port in docker compose for traefik.

<!-- gh-comment-id:2547185088 --> @anasmirza534 commented on GitHub (Dec 17, 2024): Above config not worked for me on Traefik v3. Lots of trial and error, then finally worked. Sharing reference for others. label for smtp ```yml labels: - "traefik.tcp.routers.mailpit_smtp.tls=false" - "traefik.tcp.routers.mailpit_smtp.entrypoints=smtp" - "traefik.tcp.routers.mailpit_smtp.service=mailpit_smtp" - "traefik.tcp.services.mailpit_smtp.loadbalancer.server.port=1025" - "traefik.tcp.routers.mailpit_smtp.rule=HostSNI(`*`)" - "traefik.tcp.routers.mailpit_smtp.tls.domains[0].main=mailpit-smtp.example.com" - "traefik.tcp.routers.mailpit_smtp.tls.domains[0].sans=" - "traefik.tcp.routers.mailpit_smtp.tls.passthrough=true" ``` need to add smtp entry point into traefik static config, I have added port 1025 both in static config and bound port in docker compose for traefik.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/mailpit#192
No description provided.