Adding WebSocket Without Sacrificing Security

I have a Traefik YAML file that’s running perfectly, with no errors in the logs – everything looks smooth and harmonious. However, when I try running applications that rely on WebSocket, like Chatwoot, it's like the WebSocket has gone on vacation. Messages don’t update in real-time, which makes me think the WebSocket isn’t being routed correctly.

Does anyone have tips on how to get the WebSocket back to work without messing up the pristine logs? Any help is appreciated!

version: "3.8"

services:

  traefik:
    image: traefik/traefik:v3.1.2
    container_name: traefik
    command:
      - "--api.dashboard=false"
      - "--providers.docker.endpoint=unix:///var/run/docker.sock"
      - "--providers.docker.exposedByDefault=false"
      - "--providers.docker.network=network_swarm_public"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
      - "--entrypoints.web.http.redirections.entryPoint.scheme=https"
      - "--entrypoints.web.http.redirections.entrypoint.permanent=true"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.letsencryptresolver.acme.httpchallenge=true"
      - "--certificatesresolvers.letsencryptresolver.acme.httpchallenge.entrypoint=web"
      - "--certificatesresolvers.letsencryptresolver.acme.email=example@example.com"
      - "--certificatesresolvers.letsencryptresolver.acme.storage=/etc/traefik/letsencrypt/acme.json"
      - "--log.level=DEBUG"
      - "--log.format=common"
      #- "--log.filePath=/var/log/traefik/traefik.log"
      - "--accesslog=true"
      #- "--accesslog.filepath=/var/log/traefik/access-log"
    deploy:
      placement:
        constraints:
          - node.role == manager
      labels:
        - traefik.enable=true
        - traefik.http.middlewares.gzip.compress=true
        - traefik.http.services.http-catchall.loadbalancer.server.port=80
        - traefik.http.middlewares.redirect-https.redirectscheme.scheme=https
        - traefik.http.middlewares.redirect-https.redirectscheme.permanent=true
        - traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)
        - traefik.http.routers.http-catchall.entrypoints=web
        - traefik.http.routers.http-catchall.middlewares=redirect-https@docker
        - traefik.http.routers.http-catchall.priority=1
        # Suport WebSocket
        # - traefik.http.middlewares.websocket-header.headers.customrequestheaders.Upgrade=websocket
        # - traefik.http.middlewares.websocket-header.headers.customrequestheaders.Connection=Upgrade
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "vol_certificates:/etc/traefik/letsencrypt"
    networks:
      - network_swarm_public
    ports:
      - target: 80
        published: 80
        mode: host
      - target: 443
        published: 443
        mode: host

volumes:
  vol_certificates:
    external: true
    name: volume_swarm_certificates

networks:
  network_swarm_public:
    external: true
    name: network_swarm_public

Usually WebSockets run without an issue over http.

With Traefik v3, late in v2, some timeouts were introduced to improve security, not keeping connections open forever by default.

Might that be an issue? Check browsers developer tools network tab for connections and if they get closed after a timeout.

Thank you so much for your help, @bluepuma77 ! Although I have experience in technology, I’m relatively new to configuring WebSockets with Traefik, so I’m probably overlooking some important detail. From what I can tell, the WebSockets aren’t connecting properly. I suspect the issue might be with the labels I’ve configured, but as a beginner in this area, I’m not sure what exactly I’m doing wrong.

The labels need to go on the target service.

Usually you need nothing special for WSS, as the regular target web app will do http and WSS. The upgrade headers come from browser/client.

If it’s not too much trouble, could you provide me with an example? When I tried setting it up with nothing beyond what I would typically use for HTTPS, the messages didn’t update automatically, and I had to refresh the page to see them.

Check simple Traefik example.