157 lines
4.9 KiB
Markdown
157 lines
4.9 KiB
Markdown
|
---
|
||
|
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:<INTERNAL_MUMBLE_PORT>;
|
||
|
}
|
||
|
|
||
|
upstream fosscat {
|
||
|
server localhost:<NEW_NGINX_SSL_PORT>; # 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 <NEW_NGINX_SSL_PORT> 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
|
||
|
|