Configuring Mumble with Traefik and Docker Compose

I tried to make the minimum viable configuration to get up and running with Traefik, without the web UI.
My configuration looks a little something like this:

services:
  reverse-proxy:
    image: traefik:v3.0
    command:
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"

    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"

  web:
    image: httpd:2.4
    volumes:
      - "./web:/usr/local/apache2/htdocs/"
    labels:
      - "traefik.http.routers.web.rule=Host(`example.dev`)"
      - "traefik.http.services.web.loadbalancer.server.port=80"

  whoami:
    image: containous/whoami
    labels:
      - "traefik.http.routers.whoami.rule=Host(`whoami.example.dev`)"
      - "traefik.http.services.whoami.loadbalancer.server.port=80"

How could I have a Mumble server accessible at example.dev? I tried adding a Mumble server to my Docker Compose config, but it only was accessible at the direct IP and not the domain as I thought it would be able to. Mumble requires port 64738 on both TCP and UDP, I believe.

You want to run Mumble through Traefik?

Even a Traefik maintainer is running Mumble without (link).

UDP does not allow sending of the domain info, so you can’t match with HTTP (Host()) or TLS (HostSNI()). You can only run a single server per port.

For real time coms an extra hop will always add latency. I would only use Traefik if the Mumble server can not get its own public IP (can not be reached from Internet), if you really need to proxy all connections.

Good day.
Since your question was “HOW to do this” and not “should I do this” or “is this a good idea”, I will tell you how I got it working with Docker Swarm (docker engine 28.3.3) and Traefik reverse proxy (3.3.7)

First, please be aware there are some differences between “docker” and “docker-swarm” in terms of Traefik.
I will try to highlight some of those here, but best refer to the official documentation for details

  command:
      # Enable Docker in Traefik, so that it reads labels from Docker services
      - --providers.docker
      # Add a constraint to only use services with the label "traefik.constraint-label=traefik-public"
      - --providers.docker.constraints=Label(`traefik.constraint-label`, `traefik-public`)
      # Do not expose all Docker services, only the ones explicitly exposed
      - --providers.docker.exposedbydefault=false
      # Enable Docker Swarm mode
      - --providers.swarm.endpoint=unix:///var/run/docker.sock

Next, also part of the “command” key, you define some entry points:

      # Mumble entrypoint ports
      - --entrypoints.mumbletcp.address=:64738
      - --entrypoints.mumbleudp.address=:64738/udp
      - --entrypoints.mumbleice.address=:6502

Next, as part of your mumble service definition, you must add these as part of the “deploy.labels” key. Again, note, there is a difference between docker and docker swarm. this works for swarm.

deploy:
  labels:
    - traefik.tcp.routers.mumbletcp.entrypoints=mumbletcp
    - traefik.tcp.routers.mumbletcp.rule=HostSNI(`*`)
    - traefik.tcp.services.mumbletcp-svc.loadbalancer.server.port=64738
    - traefik.udp.routers.mumbleudp.entrypoints=mumbleudp
    - traefik.udp.services.mumbleudp-svc.loadbalancer.server.port=64738

I have not added the ICE entrypoint I have defined previously, since I had enough trouble to get this working, and I don’t yet know if I actually want the ICE port open.

Note: I am also very new to mumble.

Text chat was working fine the whole time.

BUT, I struggled with voice chat.
Voice chat only start working after I “registered” all my test users, AND forced all clients to use TCP only. Then I went to bed. I need to test some more since I’m not sure, but I THINK UDP is not working correctly.

If I’m correct about the UDP issue, and since mumble itself does not expose a web interface (?), AND it force the use of certificate-based encryption in anyway, I’m having some doubts about the sense of placing it behind a reverse proxy.
The only pro I can think of, is if I want to expose to the internet - then having a single entrypoint might be helpful, security wise. But how much… idk.

Edit to add: this tool tests the UDP ping all-good for me, so I’ll check the TCP vs UDP situation again with real clients.

The providers docker and swarm have been separated, I think with v3. The reason was to be able to auto-configure local containers (not in swarm) and swarm services in parallel. This means that you need to set all desired attributes like constraints on swarm, too.