Docker compose works fine until I add traefik

Docker: 20.10.22
Docker Compose: 2.15.1
mariadb: 10.10
Passbolt: 3.10.0-1-ce
traefik: 2.9

I have the firewall rules and public DNS entries configured properly, so I can hit the website by FQDN (internal/external).
If I remove the traefik module from the docker-compose-ce.yaml (and move the port config to the passbolt container settings) everything works fine. (Of course then I get SSL certificate errors).

Pretty much using the instructions from the docker templates from passbolt. Also followed a well done youtube video by Christian Lempa

When I run

docker-compose -f docker-compose-ce.yaml up

it seems to launch fine - I don’t see any errors. All 3 containers launch. The last entry by traefik is as follows:
time="2023-02-21T17:44:53Z" level=info msg="Testing certificate renew..." providerName=letsencrypt.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory"

But when I browse to it the browser returns:

This page isnt working
pb.mydomain.com redirected you too many times
Try cleaning your cookies
ERR_TOO_MANY_REDIRECTS

docker-compose-ce.yaml:

version: '3.9'
services:
  db:
    image: mariadb:10.10
    restart: unless-stopped
    environment:
      - MYSQL_RANDOM_ROOT_PASSWORD=true
      - MYSQL_DATABASE=passbolt
      - MYSQL_USER=passbolt
      - MYSQL_PASSWORD=P4ssb0lt
    volumes:
      - database_volume:/var/lib/mysql

  passbolt:
    image: passbolt/passbolt:3.10.0-1-ce
    #Alternatively you can use rootless:
    #image: passbolt/passbolt:latest-ce-non-root
    restart: unless-stopped
    depends_on:
      - db
    environment:
      - APP_FULL_BASE_URL=https://pb.mydomain.com
      - DATASOURCES_DEFAULT_HOST=db
      - DATASOURCES_DEFAULT_USERNAME=passbolt
      - DATASOURCES_DEFAULT_PASSWORD=P4ssb0lt
      - DATASOURCES_DEFAULT_DATABASE=passbolt
      - EMAIL_TRANSPORT_DEFAULT_HOST=smtp.office365.com
      - EMAIL_TRANSPORT_DEFAULT_PORT=587
      - EMAIL_TRANSPORT_DEFAULT_USERNAME=$EMAIL_TRANSPORT_DEFAULT_USERNAME
      - EMAIL_TRANSPORT_DEFAULT_PASSWORD=$EMAIL_TRANSPORT_DEFAULT_PASSWORD
      - EMAIL_TRANSPORT_DEFAULT_TLS=true
      - EMAIL_DEFAULT_FROM_NAME=admin@mydomain.com
    
    volumes:
      - gpg_volume:/etc/passbolt/gpg
      - jwt_volume:/etc/passbolt/jwt
    command: ["/usr/bin/wait-for.sh", "-t", "15", "db:3306", "--", "/docker-entrypoint.sh"]
   
  traefik:
    image: traefik:2.9
    container_name: "traefik"
    restart: always
    ports:
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik.yaml:/traefik.yaml:ro
      - ./conf/:/etc/traefik/conf
      - ./shared/:/shared

    labels:
      traefik.enable: "true"
      traefik.http.routers.passbolt-http.entrypoints: "web"
      traefik.http.routers.passbolt-http.rule: "Host(`pb.mydomain.com`)"
      traefik.http.routers.passbolt-http.middlewares: "SslHeader@file"
      traefik.http.routers.passbolt-https.middlewares: "SslHeader@file"
      traefik.http.routers.passbolt-https.entrypoints: "websecure"
      traefik.http.routers.passbolt-https.rule: "Host(`pb.mydomain.com`)"
      traefik.http.routers.passbolt-https.tls: "true"
      traefik.http.routers.passbolt-https.tls.certresolver: "letsencrypt"


volumes:
  database_volume:
  gpg_volume:
  jwt_volume:

traefik.yaml:

global:
  sendAnonymousUsage: false
log:
  level: INFO
  format: common
providers:
  docker:
    endpoint: 'unix:///var/run/docker.sock'
    watch: true
    exposedByDefault: false
    swarmMode: false
  file:
    directory: /etc/traefik/conf/
    watch: true
api:
  dashboard: false
  debug: false
  insecure: false
entryPoints:
  web:
    address: ':80'
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true
  websecure:
    address: ':443'
certificatesResolvers:
  letsencrypt:
    acme:
      email: 'admin@mydomain.com'
      storage: /shared/acme.json
      caServer: 'https://acme-v02.api.letsencrypt.org/directory'
      keyType: EC256
      httpChallenge:
        entryPoint: web
      tlsChallenge: {}

tls.yaml and headers.yaml are unchanged from the passbolt template versions

Hi :wave:

Are you using Cloudflare ? Maybe this can help: Traefik/Portainer - ERR_TOO_MANY_REDIRECTS - Stack Overflow ?

Best,

No, however the DNS is a smaller domain registrar, so I’m not sure about how sophisticated their DNS configuration is. I’ve been looking to move the domain to a more standard registrar that will probably have a more up-to-date DNS interface, so maybe I should do that first before trying to troubleshoot further.

Thanks for the tip

It was just a guess, I don’t think changing the DNS will solve the problem.

Did you try to clean your cookies as suggested in the output ?

Yeah - also tried from a new (external) browser - same message…

Tried it again - I’m new to traefik.

I built a new deployment on a different domain on a photon OS:
Set the traefik log level to DEBUG (I suspect that’s the problem, and not sure what PROPER logs should look like).

Now when I test it says:
ERR_SSL_UNRECOGNIZED_NAME_ALERT

Here’s the tail of the log for traefik:


time="2023-02-22T20:57:31Z" level=debug msg="No default certificate, fallback to the internal generated certificate" tlsStoreName=default
time="2023-02-22T20:57:31Z" level=debug msg="Added outgoing tracing middleware acme-http@internal" entryPointName=web routerName=acme-http@internal middlewareName=tracing middlewareType=TracingForwarder
time="2023-02-22T20:57:31Z" level=debug msg="Added outgoing tracing middleware noop@internal" middlewareType=TracingForwarder entryPointName=web routerName=web-to-websecure@internal middlewareName=tracing
time="2023-02-22T20:57:31Z" level=debug msg="Creating middleware" middlewareType=RedirectScheme entryPointName=web routerName=web-to-websecure@internal middlewareName=redirect-web-to-websecure@internal
time="2023-02-22T20:57:31Z" level=debug msg="Setting up redirection to https 443" routerName=web-to-websecure@internal middlewareName=redirect-web-to-websecure@internal middlewareType=RedirectScheme entryPointName=web
time="2023-02-22T20:57:31Z" level=debug msg="Creating middleware" entryPointName=web middlewareName=traefik-internal-recovery middlewareType=Recovery
time="2023-02-22T20:57:31Z" level=debug msg="Adding certificate for domain(s) pb.mydomain.com"
time="2023-02-22T20:57:32Z" level=debug msg="No default certificate, fallback to the internal generated certificate" tlsStoreName=default
time="2023-02-22T20:57:32Z" level=debug msg="Added outgoing tracing middleware acme-http@internal" middlewareType=TracingForwarder entryPointName=web routerName=acme-http@internal middlewareName=tracing
time="2023-02-22T20:57:32Z" level=debug msg="Added outgoing tracing middleware noop@internal" entryPointName=web routerName=web-to-websecure@internal middlewareName=tracing middlewareType=TracingForwarder
time="2023-02-22T20:57:32Z" level=debug msg="Creating middleware" entryPointName=web routerName=web-to-websecure@internal middlewareName=redirect-web-to-websecure@internal middlewareType=RedirectScheme
time="2023-02-22T20:57:32Z" level=debug msg="Setting up redirection to https 443" middlewareName=redirect-web-to-websecure@internal middlewareType=RedirectScheme entryPointName=web routerName=web-to-websecure@internal
time="2023-02-22T20:57:32Z" level=debug msg="Creating middleware" entryPointName=web routerName=passbolt-http@docker serviceName=passbolt-passbolt middlewareName=pipelining middlewareType=Pipelining
time="2023-02-22T20:57:32Z" level=debug msg="Creating load-balancer" serviceName=passbolt-passbolt entryPointName=web routerName=passbolt-http@docker
time="2023-02-22T20:57:32Z" level=debug msg="Creating server 0 http://172.20.0.4:80" entryPointName=web routerName=passbolt-http@docker serverName=0 serviceName=passbolt-passbolt
time="2023-02-22T20:57:32Z" level=debug msg="child http://172.20.0.4:80 now UP"
time="2023-02-22T20:57:32Z" level=debug msg="Propagating new UP status"
time="2023-02-22T20:57:32Z" level=debug msg="Added outgoing tracing middleware passbolt-passbolt" middlewareType=TracingForwarder entryPointName=web routerName=passbolt-http@docker middlewareName=tracing
time="2023-02-22T20:57:32Z" level=debug msg="Creating middleware" routerName=passbolt-http@docker middlewareName=SslHeader@file middlewareType=Headers entryPointName=web
time="2023-02-22T20:57:32Z" level=debug msg="Setting up secureHeaders from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" middlewareType=Headers entryPointName=web routerName=passbolt-http@docker middlewareName=SslHeader@file
time="2023-02-22T20:57:32Z" level=debug msg="Setting up customHeaders/Cors from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" middlewareType=Headers entryPointName=web routerName=passbolt-http@docker middlewareName=SslHeader@file
time="2023-02-22T20:57:32Z" level=debug msg="Adding tracing to middleware" middlewareName=SslHeader@file entryPointName=web routerName=passbolt-http@docker
time="2023-02-22T20:57:32Z" level=debug msg="Creating middleware" middlewareType=Recovery entryPointName=web middlewareName=traefik-internal-recovery
time="2023-02-22T20:57:32Z" level=debug msg="Creating middleware" entryPointName=websecure routerName=passbolt-https@docker serviceName=passbolt-passbolt middlewareName=pipelining middlewareType=Pipelining
time="2023-02-22T20:57:32Z" level=debug msg="Creating load-balancer" entryPointName=websecure routerName=passbolt-https@docker serviceName=passbolt-passbolt
time="2023-02-22T20:57:32Z" level=debug msg="Creating server 0 http://172.20.0.4:80" serverName=0 entryPointName=websecure routerName=passbolt-https@docker serviceName=passbolt-passbolt
time="2023-02-22T20:57:32Z" level=debug msg="child http://172.20.0.4:80 now UP"
time="2023-02-22T20:57:32Z" level=debug msg="Propagating new UP status"
time="2023-02-22T20:57:32Z" level=debug msg="Added outgoing tracing middleware passbolt-passbolt" middlewareType=TracingForwarder entryPointName=websecure routerName=passbolt-https@docker middlewareName=tracing
time="2023-02-22T20:57:32Z" level=debug msg="Creating middleware" routerName=passbolt-https@docker middlewareName=SslHeader@file middlewareType=Headers entryPointName=websecure
time="2023-02-22T20:57:32Z" level=debug msg="Setting up secureHeaders from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" middlewareType=Headers entryPointName=websecure routerName=passbolt-https@docker middlewareName=SslHeader@file
time="2023-02-22T20:57:32Z" level=debug msg="Setting up customHeaders/Cors from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" entryPointName=websecure routerName=passbolt-https@docker middlewareName=SslHeader@file middlewareType=Headers
time="2023-02-22T20:57:32Z" level=debug msg="Adding tracing to middleware" routerName=passbolt-https@docker middlewareName=SslHeader@file entryPointName=websecure
time="2023-02-22T20:57:32Z" level=debug msg="Creating middleware" middlewareName=traefik-internal-recovery middlewareType=Recovery entryPointName=websecure
time="2023-02-22T20:57:32Z" level=debug msg="Adding route for pb.mydomain.com with TLS options default" entryPointName=websecure
time="2023-02-22T20:57:32Z" level=debug msg="Trying to challenge certificate for domain [pb.mydomain.com] found in HostSNI rule" routerName=passbolt-https@docker rule="Host(`pb.mydomain.com`)" ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=letsencrypt.acme
time="2023-02-22T20:57:32Z" level=debug msg="Looking for provided certificate(s) to validate [\"pb.mydomain.com\"]..." ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=letsencrypt.acme routerName=passbolt-https@docker rule="Host(`pb.mydomain.com`)"
time="2023-02-22T20:57:32Z" level=debug msg="No ACME certificate generation required for domains [\"pb.mydomain.com\"]." rule="Host(`pb.mydomain.com`)" ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=letsencrypt.acme routerName=passbolt-https@docker
time="2023-02-22T21:08:11Z" level=debug msg="TLS: strict SNI enabled - No certificate found for domain: \"\", closing connection"
time="2023-02-22T21:08:11Z" level=debug msg="http: TLS handshake error from 185.180.143.79:45044: tls: no certificates configured"

Looks like it is downloading the certificate, but then fails some strict SNI check - and gets a TLS handshake error. Not sure where to look next

Have you looked at the configurations found in this post for reference? Docker installation: Various problems with traefik container (SOLVED)

I did. It appears his issue was that the traefik container was failing to launch.

Unfortunately the fix for his solution was that he rebuilt it from scratch, and the problem didn’t come back.
I’ve configured this on a couple docker servers, using 2 different domains. I think I got much closer - but it does look like a traefik (or a traefik/passbolt integration) issue.

Hi,

Can you confirm you obfuscated your real passbolt domain name with pb.mydomain.com? Do you have port 80 opened? It is needed to let let’s encrypt generate the certificate.

I just had a closer look to the logs you provided.

Here, Traefik is checking your certificate status (does it exist? is it needed to proceed to a renewal?):

time="2023-02-22T20:57:32Z" level=debug msg="Trying to challenge certificate for domain [pb.mydomain.com] found in HostSNI rule" routerName=passbolt-https@docker rule="Host(`pb.mydomain.com`)" ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=letsencrypt.acme
time="2023-02-22T20:57:32Z" level=debug msg="Looking for provided certificate(s) to validate [\"pb.mydomain.com\"]..." ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=letsencrypt.acme routerName=passbolt-https@docker rule="Host(`pb.mydomain.com`)"

It seems Traefik has found the certificate because of the No ACME certificate generation required:

time="2023-02-22T20:57:32Z" level=debug msg="No ACME certificate generation required for domains [\"pb.mydomain.com\"]." rule="Host(`pb.mydomain.com`)" ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=letsencrypt.acme routerName=passbolt-https@docker

On the other hand, there is another explanation: maybe Traefik assume generating a certificate is not possible/needed, as “pb.mydomain.com” domain name doesn’t exist, that’s why I asked if you obfuscated your real domain with pb.mydomain.com :

nslookup pb.mydomain.com
Server:         94.140.14.14
Address:        94.140.14.14#53

** server can't find pb.mydomain.com: NXDOMAIN

Is your real domain name in******-***sus.org ? If yes, pb.in******-***sus.orgdoesn’t exists so maybe it is the reason why Let’s Encrypt is not able to generate a certificate.

The last log is weird: No certificate found for domain: "" (domain is empty).

time="2023-02-22T21:08:11Z" level=debug msg="TLS: strict SNI enabled - No certificate found for domain: \"\", closing connection"

Traefik stores the generated certificates in the /shared/acme.json file. Can you check the content of this file if it contains certificates?

As an example, here is mine:

{
  "letsencrypt": {
    "Account": {
      "Email": "user@domain.tld",
      "Registration": {
        "body": {
          "status": "valid",
          "contact": [
            "mailto:user@domain.tld"
          ]
        },
        "uri": "https://acme-v02.api.letsencrypt.org/acme/acct/obfuscated"
      },
      "PrivateKey": "**obfuscated**",
      "KeyType": "P256"
    },    "Certificates": [
      {
        "domain": {
          "main": "mydomain.tld"
        },
        "certificate": "**obfuscated**",
        "key": "**obfuscated**",
        "Store": "default"
      },
(...)

Hope this help,

Best regards,

That is indeed helpful.
I am forwarding port 80 and port 443, and yes - I obfuscated my domain, and the acme.json DID contain my certificate. But I think you are getting me pointed in the right direction. I had to sudo cat acme.json otherwise it didn’t have permissions.

My first test was on my windows machine (had problems there too, but let’s not muddy the waters)…
When I decided to rebuild this - I decided to run it on a Photon-OS VM running docker on my lab ESXi server.

Since I’m relatively new to docker - I followed instructions I found on setting up remote dev with vscode. Of course they followed best practice, and setup a non-root user which was then granted SUDO permissions.

I completely forgot that the passbolt image has a specific root and non-root image (and I think traefik needs some other configuration changes as well to run as non-root correct?)

I purged the contrainer and tried running this from the photon-os as root, but I still had no luck.

This project is a stepping stone for me to understand getting passbolt running properly in a multi-container setup, as my end-goal is to host this in Azure Web app for containers. I don’t think you can run as root in that environment, so as much as it will add complexity - I think I have to push through this to get it working as non-root user.

To run the passbolt non-root image with traefik, you have to add this label:

traefik.http.services.passbolt-https.loadbalancer.server.port: 8080

As explained in the documentation: Passbolt Help | Auto configure HTTPS with Let's Encrypt on Docker

1 Like

Uggg - how did I miss that?
That has seemed to help, but now I’m rate-limited on letsencrypt.

I’ll try again later - thanks so much for sticking with me. My goal when complete here is to draft a how-to guide on hosting passbolt within Azure web app for containers - so hopefully this effort will help some other folks if I can push through all this.

Your help is much appreciated! I’ll give you an update later when I can try again.

2 Likes

I’m continuing to have the same problem. The acme.json file DOES generate and appears to have the correct data including a private key. It shows status as “valid”

I verified in my external firewall that the 80 and 443 access and NAT rules are getting hit and forwarding web (80/443) traffic to the internal IP of the docker host (Photon OS) (this works and the site loads if I run passbolt docker WITHOUT traefik from an external machine)

Heres my traefik logs:

passbolt-traefik-1   | time="2023-03-12T17:57:18Z" level=debug msg="Setting up secureHeaders from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" routerName=passbolt-https@docker middlewareType=Headers middlewareName=SslHeader@file entryPointName=websecure
passbolt-traefik-1   | time="2023-03-12T17:57:18Z" level=debug msg="Setting up customHeaders/Cors from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" entryPointName=websecure routerName=passbolt-https@docker middlewareType=Headers middlewareName=SslHeader@file
passbolt-traefik-1   | time="2023-03-12T17:57:18Z" level=debug msg="Adding tracing to middleware" entryPointName=websecure routerName=passbolt-https@docker middlewareName=SslHeader@file
passbolt-traefik-1   | time="2023-03-12T17:57:18Z" level=debug msg="Creating middleware" middlewareName=traefik-internal-recovery middlewareType=Recovery entryPointName=websecure
passbolt-traefik-1   | time="2023-03-12T17:57:18Z" level=debug msg="Adding route for pb.mydomain.com with TLS options default" entryPointName=websecure
passbolt-traefik-1   | time="2023-03-12T17:57:18Z" level=debug msg="Trying to challenge certificate for domain [pb.mydomain.com] found in HostSNI rule" routerName=passbolt-https@docker rule="Host(`pb.mydomain.com`)" ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=letsencrypt.acme
passbolt-traefik-1   | time="2023-03-12T17:57:18Z" level=debug msg="Looking for provided certificate(s) to validate [\"pb.mydomain.com\"]..." ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=letsencrypt.acme routerName=passbolt-https@docker rule="Host(`pb.mydomain.com`)"
passbolt-traefik-1   | time="2023-03-12T17:57:18Z" level=debug msg="Domains [\"pb.mydomain.com\"] need ACME certificates generation for domains \"pb.mydomain.com\"." providerName=letsencrypt.acme routerName=passbolt-https@docker rule="Host(`pb.mydomain.com`)" ACME CA="https://acme-v02.api.letsencrypt.org/directory"
passbolt-traefik-1   | time="2023-03-12T17:57:18Z" level=debug msg="Loading ACME certificates [pb.mydomain.com]..." rule="Host(`pb.mydomain.com`)" ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=letsencrypt.acme routerName=passbolt-https@docker
passbolt-traefik-1   | time="2023-03-12T17:57:18Z" level=debug msg="legolog: [INFO] [pb.mydomain.com] acme: Obtaining bundled SAN certificate"
passbolt-traefik-1   | time="2023-03-12T17:57:18Z" level=debug msg="legolog: [INFO] [pb.mydomain.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/210307310337"
passbolt-traefik-1   | time="2023-03-12T17:57:18Z" level=debug msg="legolog: [INFO] [pb.mydomain.com] acme: use tls-alpn-01 solver"
passbolt-traefik-1   | time="2023-03-12T17:57:18Z" level=debug msg="legolog: [INFO] [pb.mydomain.com] acme: Trying to solve TLS-ALPN-01"
passbolt-traefik-1   | time="2023-03-12T17:57:18Z" level=debug msg="TLS Challenge Present temp certificate for pb.mydomain.com" providerName=tlsalpn.acme
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Configuration received: {\"http\":{},\"tcp\":{},\"udp\":{},\"tls\":{}}" providerName=tlsalpn.acme
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Adding certificate for domain(s) acme challenge temp,pb.mydomain.com"
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="No default certificate, fallback to the internal generated certificate" tlsStoreName=default
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Added outgoing tracing middleware noop@internal" entryPointName=web routerName=web-to-websecure@internal middlewareName=tracing middlewareType=TracingForwarder
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Creating middleware" entryPointName=web routerName=web-to-websecure@internal middlewareName=redirect-web-to-websecure@internal middlewareType=RedirectScheme
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Setting up redirection to https 443" middlewareName=redirect-web-to-websecure@internal middlewareType=RedirectScheme entryPointName=web routerName=web-to-websecure@internal
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Creating middleware" serviceName=passbolt-https middlewareName=pipelining middlewareType=Pipelining entryPointName=web routerName=passbolt-http@docker
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Creating load-balancer" serviceName=passbolt-https entryPointName=web routerName=passbolt-http@docker
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Creating server 0 http://172.28.0.4:8080" routerName=passbolt-http@docker serviceName=passbolt-https serverName=0 entryPointName=web
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="child http://172.28.0.4:8080 now UP"
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Propagating new UP status"
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Added outgoing tracing middleware passbolt-https" routerName=passbolt-http@docker entryPointName=web middlewareName=tracing middlewareType=TracingForwarder
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Creating middleware" middlewareType=Headers entryPointName=web routerName=passbolt-http@docker middlewareName=SslHeader@file
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Setting up secureHeaders from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" middlewareType=Headers entryPointName=web routerName=passbolt-http@docker middlewareName=SslHeader@file
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Setting up customHeaders/Cors from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" routerName=passbolt-http@docker middlewareName=SslHeader@file middlewareType=Headers entryPointName=web
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Adding tracing to middleware" routerName=passbolt-http@docker middlewareName=SslHeader@file entryPointName=web
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Added outgoing tracing middleware acme-http@internal" middlewareName=tracing middlewareType=TracingForwarder routerName=acme-http@internal entryPointName=web
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Creating middleware" middlewareName=traefik-internal-recovery middlewareType=Recovery entryPointName=web
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Creating middleware" middlewareType=Pipelining routerName=passbolt-https@docker serviceName=passbolt-https entryPointName=websecure middlewareName=pipelining
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Creating load-balancer" serviceName=passbolt-https entryPointName=websecure routerName=passbolt-https@docker
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Creating server 0 http://172.28.0.4:8080" serverName=0 entryPointName=websecure routerName=passbolt-https@docker serviceName=passbolt-https
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="child http://172.28.0.4:8080 now UP"
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Propagating new UP status"
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Added outgoing tracing middleware passbolt-https" middlewareName=tracing middlewareType=TracingForwarder entryPointName=websecure routerName=passbolt-https@docker
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Creating middleware" entryPointName=websecure routerName=passbolt-https@docker middlewareName=SslHeader@file middlewareType=Headers
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Setting up secureHeaders from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" entryPointName=websecure routerName=passbolt-https@docker middlewareName=SslHeader@file middlewareType=Headers
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Setting up customHeaders/Cors from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" entryPointName=websecure routerName=passbolt-https@docker middlewareName=SslHeader@file middlewareType=Headers
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Adding tracing to middleware" routerName=passbolt-https@docker middlewareName=SslHeader@file entryPointName=websecure
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Creating middleware" middlewareName=traefik-internal-recovery middlewareType=Recovery entryPointName=websecure
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Adding route for pb.mydomain.com with TLS options default" entryPointName=websecure
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Trying to challenge certificate for domain [pb.mydomain.com] found in HostSNI rule" ACME CA="https://acme-v02.api.letsencrypt.org/directory" routerName=passbolt-https@docker rule="Host(`pb.mydomain.com`)" providerName=letsencrypt.acme
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="Looking for provided certificate(s) to validate [\"pb.mydomain.com\"]..." ACME CA="https://acme-v02.api.letsencrypt.org/directory" routerName=passbolt-https@docker rule="Host(`pb.mydomain.com`)" providerName=letsencrypt.acme
passbolt-traefik-1   | time="2023-03-12T17:57:19Z" level=debug msg="No ACME certificate generation required for domains [\"pb.mydomain.com\"]." rule="Host(`pb.mydomain.com`)" providerName=letsencrypt.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory" routerName=passbolt-https@docker
passbolt-traefik-1   | time="2023-03-12T17:57:26Z" level=debug msg="TLS Challenge CleanUp temp certificate for pb.mydomain.com" providerName=tlsalpn.acme
passbolt-traefik-1   | time="2023-03-12T17:57:26Z" level=debug msg="Configuration received: {\"http\":{},\"tcp\":{},\"udp\":{},\"tls\":{}}" providerName=tlsalpn.acme
passbolt-traefik-1   | time="2023-03-12T17:57:26Z" level=debug msg="legolog: [INFO] Deactivating auth: https://acme-v02.api.letsencrypt.org/acme/authz-v3/210307310337"
passbolt-traefik-1   | time="2023-03-12T17:57:26Z" level=error msg="Unable to obtain ACME certificate for domains \"pb.mydomain.com\": unable to generate a certificate for the domains [pb.mydomain.com]: error: one or more domains had a problem:\n[pb.mydomain.com] acme: error: 400 :: urn:ietf:params:acme:error:connection :: 47.12.26.235: Connection refused\n" ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=letsencrypt.acme routerName=passbolt-https@docker rule="Host(`pb.mydomain.com`)"
passbolt-traefik-1   | time="2023-03-12T17:57:26Z" level=debug msg="No default certificate, fallback to the internal generated certificate" tlsStoreName=default

The error is related to firewall settings and/or port bindings.

I think port forwarding should go to traefik and not to the container, as traefik is in front of the container and passing traffic back to port 8080 for non-root.

The documentation doesn’t mention alternative bindings on the passbolt container when using traefik so I’m not clear on this, but if you are binding 80 and 443 to your passbolt container first, it may prevent traefik from doing so. Passbolt container port bindings for non-root:

 - 8080:80
 - 4433:433

Do you have traefik and passbolt reversed with regards to ports?

I have them set (as I understood) per the passbolt documentation.

Maybe I’m not reading it clearly.
I followed the non-root instructions for passbolt (8080 and 4433 instead of 80/443) And the only instructions for traefik config is to add the loadbalancer.server.port label and set it to 8080

docker-compose-ce.yaml:

version: '3.9'
services:
  db:
    image: mariadb:10.3
    restart: unless-stopped
    environment:
      MYSQL_RANDOM_ROOT_PASSWORD: "true"
      MYSQL_DATABASE: "passbolt"
      MYSQL_USER: "passbolt"
      MYSQL_PASSWORD: "P4ssb0lt"
    volumes:
      - database_volume:/var/lib/mysql

  passbolt:
    image: passbolt/passbolt:3.10.0-1-ce-non-root
    #Alternatively you can use rootless:
    #image: passbolt/passbolt:latest-ce-non-root
    restart: unless-stopped
    depends_on:
      - db
    environment:
      APP_FULL_BASE_URL: https://pb.cuyunalakesmtb.com
      DATASOURCES_DEFAULT_HOST: "db"
      DATASOURCES_DEFAULT_USERNAME: "passbolt"
      DATASOURCES_DEFAULT_PASSWORD: "P4ssb0lt"
      DATASOURCES_DEFAULT_DATABASE: "passbolt"
    volumes:
      - gpg_volume:/etc/passbolt/gpg
      - jwt_volume:/etc/passbolt/jwt
    command: ["/usr/bin/wait-for.sh", "-t", "0", "db:3306", "--", "/docker-entrypoint.sh"]
    labels:
      traefik.enable: "true"
      traefik.http.routers.passbolt-http.entrypoints: "web"
      traefik.http.routers.passbolt-http.rule: "Host(`pb.cuyunalakesmtb.com`)"
      traefik.http.routers.passbolt-http.middlewares: "SslHeader@file"
      traefik.http.routers.passbolt-https.middlewares: "SslHeader@file"
      traefik.http.routers.passbolt-https.entrypoints: "websecure"
      traefik.http.routers.passbolt-https.rule: "Host(`pb.cuyunalakesmtb.com`)"
      traefik.http.routers.passbolt-https.tls: "true"
      traefik.http.routers.passbolt-https.tls.certresolver: "letsencrypt"
      traefik.http.services.passbolt-https.loadbalancer.server.port: '8080'

  traefik:
    image: traefik:2.9.8
    restart: always
    ports:
    # - 80:80
    # - 443:443
      - 8080:80
      - 4433:433
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik.yaml:/traefik.yaml:ro
      - ./conf/:/etc/traefik/conf
      - ./letsencrypt:/letsencrypt/
      #- ./shared/:/shared
      #Alternatively for non-root images:
    # - 8080:80
    # - 4433:433

volumes:
  database_volume:
  gpg_volume:
  jwt_volume:

traefik.yaml:

global:
  sendAnonymousUsage: false
log:
  level: DEBUG
  format: common
providers:
  docker:
    endpoint: 'unix:///var/run/docker.sock'
    watch: true
    exposedByDefault: false
    swarmMode: false
  file:
    directory: /etc/traefik/conf/
    watch: true
api:
  dashboard: false
  debug: false
  insecure: false
entryPoints:
  web:
    address: ':80'
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true
  websecure:
    address: ':443'
certificatesResolvers:
  letsencrypt:
    acme:
      email: paul@mydomain.com
      #storage: /shared/acme.json
      storage: /letsencrypt/acme.json
      caServer: 'https://acme-v02.api.letsencrypt.org/directory'
      keyType: EC256
      httpChallenge:
        entryPoint: web
      tlsChallenge: {}

I’ve tried the ports configured several ways - and it always seems traefik gets the initial cert, but then cannot validate it:

passbolt-traefik-1   | time="2023-03-13T12:24:55Z" level=debug msg="Creating middleware" entryPointName=websecure routerName=passbolt-https@docker middlewareName=SslHeader@file middlewareType=Headers
passbolt-traefik-1   | time="2023-03-13T12:24:55Z" level=debug msg="Setting up secureHeaders from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" entryPointName=websecure routerName=passbolt-https@docker middlewareName=SslHeader@file middlewareType=Headers
passbolt-traefik-1   | time="2023-03-13T12:24:55Z" level=debug msg="Setting up customHeaders/Cors from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" middlewareName=SslHeader@file middlewareType=Headers entryPointName=websecure routerName=passbolt-https@docker
passbolt-traefik-1   | time="2023-03-13T12:24:55Z" level=debug msg="Adding tracing to middleware" middlewareName=SslHeader@file entryPointName=websecure routerName=passbolt-https@docker
passbolt-traefik-1   | time="2023-03-13T12:24:55Z" level=debug msg="Creating middleware" entryPointName=websecure middlewareName=traefik-internal-recovery middlewareType=Recovery
passbolt-traefik-1   | time="2023-03-13T12:24:55Z" level=debug msg="Adding route for pb.obscureddomain.com with TLS options default" entryPointName=websecure
passbolt-traefik-1   | time="2023-03-13T12:24:55Z" level=debug msg="Trying to challenge certificate for domain [pb.obscureddomain.com] found in HostSNI rule" routerName=passbolt-https@docker rule="Host(`pb.obscureddomain.com`)" providerName=letsencrypt.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory"
passbolt-traefik-1   | time="2023-03-13T12:24:55Z" level=debug msg="Looking for provided certificate(s) to validate [\"pb.obscureddomain.com\"]..." rule="Host(`pb.obscureddomain.com`)" providerName=letsencrypt.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory" routerName=passbolt-https@docker
passbolt-traefik-1   | time="2023-03-13T12:24:55Z" level=debug msg="No ACME certificate generation required for domains [\"pb.obscureddomain.com\"]." routerName=passbolt-https@docker rule="Host(`pb.obscureddomain.com`)" providerName=letsencrypt.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory"
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="TLS Challenge CleanUp temp certificate for pb.obscureddomain.com" providerName=tlsalpn.acme
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Configuration received: {\"http\":{},\"tcp\":{},\"udp\":{},\"tls\":{}}" providerName=tlsalpn.acme
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="legolog: [INFO] Deactivating auth: https://acme-v02.api.letsencrypt.org/acme/authz-v3/210511387867"
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="No default certificate, fallback to the internal generated certificate" tlsStoreName=default
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Creating middleware" middlewareName=pipelining entryPointName=web routerName=passbolt-http@docker serviceName=passbolt-https middlewareType=Pipelining
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Creating load-balancer" entryPointName=web routerName=passbolt-http@docker serviceName=passbolt-https
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Creating server 0 http://172.29.0.4:8080" serviceName=passbolt-https serverName=0 entryPointName=web routerName=passbolt-http@docker
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="child http://172.29.0.4:8080 now UP"
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Propagating new UP status"
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Added outgoing tracing middleware passbolt-https" entryPointName=web middlewareName=tracing middlewareType=TracingForwarder routerName=passbolt-http@docker
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Creating middleware" middlewareType=Headers entryPointName=web routerName=passbolt-http@docker middlewareName=SslHeader@file
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Setting up secureHeaders from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" entryPointName=web routerName=passbolt-http@docker middlewareName=SslHeader@file middlewareType=Headers
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Setting up customHeaders/Cors from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" entryPointName=web routerName=passbolt-http@docker middlewareName=SslHeader@file middlewareType=Headers
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Adding tracing to middleware" entryPointName=web routerName=passbolt-http@docker middlewareName=SslHeader@file
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Added outgoing tracing middleware noop@internal" routerName=web-to-websecure@internal middlewareName=tracing middlewareType=TracingForwarder entryPointName=web
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Creating middleware" middlewareName=redirect-web-to-websecure@internal middlewareType=RedirectScheme entryPointName=web routerName=web-to-websecure@internal
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Setting up redirection to https 443" entryPointName=web routerName=web-to-websecure@internal middlewareName=redirect-web-to-websecure@internal middlewareType=RedirectScheme
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Added outgoing tracing middleware acme-http@internal" entryPointName=web routerName=acme-http@internal middlewareName=tracing middlewareType=TracingForwarder
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Creating middleware" middlewareType=Recovery entryPointName=web middlewareName=traefik-internal-recovery
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Creating middleware" middlewareType=Pipelining entryPointName=websecure routerName=passbolt-https@docker serviceName=passbolt-https middlewareName=pipelining
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Creating load-balancer" entryPointName=websecure routerName=passbolt-https@docker serviceName=passbolt-https
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Creating server 0 http://172.29.0.4:8080" routerName=passbolt-https@docker serviceName=passbolt-https serverName=0 entryPointName=websecure
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="child http://172.29.0.4:8080 now UP"
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Propagating new UP status"
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Added outgoing tracing middleware passbolt-https" entryPointName=websecure routerName=passbolt-https@docker middlewareName=tracing middlewareType=TracingForwarder
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Creating middleware" middlewareName=SslHeader@file middlewareType=Headers routerName=passbolt-https@docker entryPointName=websecure
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Setting up secureHeaders from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" routerName=passbolt-https@docker entryPointName=websecure middlewareName=SslHeader@file middlewareType=Headers
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Setting up customHeaders/Cors from {map[] map[] false [] [GET OPTIONS PUT] [origin-list-or-null] [] [] 100 true [] [] false false  map[] false 315360000 true true true true SAMEORIGIN true true  default-src 'self' 'unsafe-inline'  same-origin  vibrate 'self' false}" entryPointName=websecure middlewareName=SslHeader@file middlewareType=Headers routerName=passbolt-https@docker
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Adding tracing to middleware" middlewareName=SslHeader@file entryPointName=websecure routerName=passbolt-https@docker
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Creating middleware" entryPointName=websecure middlewareName=traefik-internal-recovery middlewareType=Recovery
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Adding route for pb.obscureddomain.com with TLS options default" entryPointName=websecure
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Trying to challenge certificate for domain [pb.obscureddomain.com] found in HostSNI rule" rule="Host(`pb.obscureddomain.com`)" providerName=letsencrypt.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory" routerName=passbolt-https@docker
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="Looking for provided certificate(s) to validate [\"pb.obscureddomain.com\"]..." providerName=letsencrypt.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory" routerName=passbolt-https@docker rule="Host(`pb.obscureddomain.com`)"
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=debug msg="No ACME certificate generation required for domains [\"pb.obscureddomain.com\"]." rule="Host(`pb.obscureddomain.com`)" providerName=letsencrypt.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory" routerName=passbolt-https@docker
passbolt-traefik-1   | time="2023-03-13T12:25:07Z" level=error msg="Unable to obtain ACME certificate for domains \"pb.obscureddomain.com\": unable to generate a certificate for the domains [pb.obscureddomain.com]: error: one or more domains had a problem:\n[pb.obscureddomain.com] acme: error: 400 :: urn:ietf:params:acme:error:connection :: 47.12.26.235: Timeout during connect (likely firewall problem)\n" rule="Host(`pb.obscureddomain.com`)" providerName=letsencrypt.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory" routerName=passbolt-https@docker

@pdrangeid1 Thanks for posting, very helpful.

In the compose file, passbolt should have what I showed above (seems they are missing) and traefik should have this in the ports:

 - 80:80
 - 443:443