--- title: "Hosting Mumble on a Subdomain with Nginx" date: 2024-01-04T10:04:57-07:00 draft: false tags: ['nginx', 'self host', 'mumble'] summary: 'How to host a mumble server on a subdomain behind nginx reverse proxy' tocOpen: true cover: image: "/images/nginx-mumble.png" alt: "Nginx logo and Mumble Logo" caption: "Star-crossed lovers" relative: false --- # All I Found Was Tumble Weeds Well I couldn't find any actual examples of someone doing what I wanted, namely, hosting the murmur server on a subdomain on my machine behind an nginx proxy. I only have ports 80 and 443 opened on my router, so I chose to recieve the mumble traffic to come in on port 443. Sounds easy enough, but the problem comes when you let nginx decrypt the packets in the process of passing them to the murmur server, it raises a TLS/SSL Termination Error. Murmur insists on End to End Encryption (E2EE), which is a good thing. To not repeat the classic Cooking Recipe website mistake and put the solution at the bottom of an Ad riddled page, here is the nginx config that got my setup working, all of this is the default on an Arch Linux install, minus the `stream` block. Ports need to be defined for your setup for `INTERNAL_MUMBLE_PORT` (port that murmur is listening on) and `NEW_NGINX_SSL_PORT`. Previously, `NEW_NGINX_SSL_PORT` was 443, but the stream block now will be using 443, and you can't bind to the same port with seperate services. So pick a new port for the other ssl nginx services to listen on, as well as pass traffic to, internally. `nginx.conf` ```conf worker_processes 4; events { worker_connections 1024; } stream { # Define upstreams that nginx can route traffic to upstream mumble { server localhost:; } upstream fosscat { server localhost:; # Was 443 until I added murmur } # SNI, route to murmur if the subdomain matches map $ssl_preread_server_name $name { # Destination Upstream (above) to Route traffic to mumble.fosscat.com mumble; default fosscat; } server { # TCP traffic listen 443; # UDP traffic listen 443 udp; proxy_pass $name; # Necessary line # Dont decrypt packets, just pass them along ssl_preread on; } } http { include mime.types; include /etc/nginx/sites-enabled/*; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } } ``` Then here is this blog's nginx config file in `/etc/nginx/sites-available` that is sim-linked into `/etc/nginx/sites-enabled`. I'm using certbot for ssl certs. Note that a port needs to be provided in the second server block that matches the one provided above. `fosscat.com` file: ```conf server { if ($host = www.fosscat.com) { return 301 https://$host$request_uri; } # managed by Certbot if ($host = fosscat.com) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; server_name fosscat.com www.fosscat.com; } server { listen ssl; server_name fosscat.com www.fosscat.com; ssl_certificate /etc/letsencrypt/live/fosscat.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/fosscat.com/privkey.pem; # managed by Certbot root /usr/share/nginx/html/fosscat-site/public/; #Absolute path to where your hugo site is index index.html; # Hugo generates HTML location / { root /usr/share/nginx/html/fosscat-site/public; try_files $uri $uri/ =404; } error_page 404 /404.html; location = /404.html { root /usr/share/nginx/html/fosscat-site/public; internal; } } ``` ## Caveats I figured this setup out cobbling together some sparse posts online, the nginx docs, and asking chatGPT for explanations. Currently, all of my sites and services work as expected with TLS and whatnot, however the murmur server doesn't report as being online to clients before they connect. Also, the mumble client reports that only TLS is supported so it switches to TLS only mode automatically, i.e. increased latency. I'm not sure why either of these are the case. To use the `stream` block and `ssl_preread` you have to have your nginx compiled with those options. Running `nginx -V` should tell you whether you have a compatible nginx version. Thought I'd share my discovery in case anyone else runs into the same problem I did. As always, questions or corrections, feel free to open a PR on my git instance or email me @ tom@fosscat.com