I have setup Traefik using docker and I'm trying to put my Network Video Recorder (Unifi NVR) behind reverse proxy. My current setup seems to work for the most part, except when the NVR tries to reach WebSocket through a different port. This is the docker compose for the Traefik setup:
traefik:
image: traefik:2.3.2
container_name: traefik
environment:
- NAMECHEAP_API_USER=${NAMECHEAP_API_USER}
- NAMECHEAP_API_KEY=${NAMECHEAP_API_KEY}
command:
#### CLI commands that will configure Traefik (static) ####
## API Settings ##
- --api.insecure=true # <== Enables insecure api
- --api.dashboard=true # <== Enables the dashboard to view services, middlewares, routers, etc...
- --api.debug=true # <== Enables additional endpoints for debugging and profiling
## Log Settings ##
- --log.level=DEBUG # <== Setting the level of the logs
## Provider Settings ##
- --providers.docker=true # <== Enables docker as a provider
- --providers.docker.exposedbydefault=false # <== Don't expose every container to traefik, only expose enabled ones
- --providers.file.filename=/etc/traefik/dynamic.yml # <== Reference to the dynamic configuration file
## Entrypoints Settings ##
- --entrypoints.web.address=:80 # <== Defining an entrypoint for port :80 named web
- --entrypoints.web.http.redirections.entryPoint.to=websecure # <== Redirect web to websecure (http > https)
- --entrypoints.web.http.redirections.entryPoint.scheme=https # <== Set HTTPS as redirection scheme
- --entrypoints.websecure.address=:443 # <== Defining an entrypoint for https on port :443 named websecure
## Certificate Settings (Let's Encrypt) ##
- --certificatesresolvers.default.acme.email=${EMAIL} # <== Setting email for certs
- --certificatesresolvers.default.acme.storage=/etc/traefik/acme/acme.json # <== Defining acme file to store cert information
- --certificatesresolvers.default.acme.dnschallenge=true # <== Enable DNS-01 ACME challenge to generate and renew ACME certs
- --certificatesresolvers.default.acme.dnschallenge.provider=namecheap # <== Set DNS-01 challenge provider
- --certificatesresolvers.default.acme.dnschallenge.delayBeforeCheck=32 # <== Wait 32 seconds before checking propagation.
- --certificatesresolvers.default.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53 # <== Use these to check for propagation.
- --serversTransport.insecureSkipVerify=true # <== Disables SSL certificate verification between traefik and backend. Certificate does not need to be valid!
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ${DATADIR}/appdata/traefik/dynamic.yml:/etc/traefik/dynamic.yml
- ${DATADIR}/appdata/traefik/acme.json:/etc/traefik/acme/acme.json
labels:
- "traefik.enable=true" # <== Enable traefik on itself to view dashboard and assign subdomain to view it
- "traefik.http.routers.traefik.rule=Host(`traefik.example.com`)" # <== Setting the domain for the dashboard
- "traefik.http.routers.traefik.service=api@internal" # <== Enabling the api to be a service to access
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.traefik.tls.certresolver=default"
- "traefik.http.routers.traefik.tls.domains[0].main=example.com"
- "traefik.http.routers.traefik.tls.domains[0].sans=*.example.com"
ports:
- 80:80
- 443:443
- 8080:8080
restart: always
and this is the dynamic.yml I use to put non-docker services behind reverse proxy:
http:
routers:
nvr:
rule: Host(`nvr.example.com`)
service: nvr
middlewares:
- sslheader
#- https-redirect
tls: {}
services:
nvr:
loadBalancer:
servers:
- url: "https://192.168.1.102:7443"
middlewares:
https-redirect:
redirectScheme:
scheme: https
permanent: true
port: "7443"
sslheader:
headers:
customRequestHeaders:
X-Forwarded-Proto: https
If I go to nvr.example.com I get to the web UI with valid certificate and all. But when I try to view a video stream from one of the cameras I get this error in browser console:
WebSocket connection to 'wss://nvr.example.com:7446/xxx' failed:
I assume the service tries to access WebSocket through different port than what is used to access the web UI (7446 vs 7443) and that is why it fails. How should I configure Traefik so accessing WebSocket over wss://nvr.example.com:7446
possible?