HTTPS for NetherNet
Geyser's built-in signaling server uses plain HTTP by default. Over plain HTTP, Minecraft cannot verify which server it is talking to, so it prompts each Bedrock player on the first join whether they want to trust the server the first time they join ("trust on first use"). Over HTTPS, the server's certificate proves its identity, so Minecraft does not show this prompt.
This page is for people who host Geyser themselves. When using a hosting provider, ask your host instead for how you could use HTTPS. To learn what signaling is, read Preparing your Geyser server for NetherNet.
This page only matters if you use Geyser's built-in signaling: mode in the signaling section is builtin (the default) or hybrid.
What you need
- A domain name that points to your server, like
play.example.com. Players must connect with this name, not with an IP address, because the certificate is made for the name. If you do not have a domain, you could use a DDNS provider such as DuckDNS to obtain a free one, likemyserver.duckdns.org. - A working NetherNet setup without HTTPS. Make sure players can join first, then add HTTPS.
- A certificate for that domain. If you already have one, you can use it as is. Otherwise, you could use Let's Encrypt to obtain one for free. The steps below do this with Caddy, certbot or win-acme, which need TCP port 80 to be reachable from the internet while obtaining and renewing certificates. Forward it in your router like your Geyser port. Let's Encrypt's DNS challenge works without port 80, but is not covered here.
Setting up HTTPS
Geyser can serve HTTPS itself with a certificate set in its config. Alternatively, a reverse proxy such as Caddy or nginx can handle HTTPS in front of Geyser.
If you would rather not manage a certificate at all, external signaling (mode: nxs) is an option as well, if the signaling service provides HTTPS: Warden does, but not every service does.
- Certificate in the Geyser config
- Reverse proxy
Geyser serves HTTPS on the same port as HTTP, so no extra program is needed. Geyser reads the certificate when it starts, so it needs a restart after every renewal.
1. Obtain a certificate
If you already have a certificate for your domain, skip this step. Otherwise, you could use Let's Encrypt to obtain one, for example with certbot or win-acme. These need TCP port 80 to be reachable.
- Linux
- Windows
- macOS
On Linux, certbot is the recommended way to obtain certificates from Let's Encrypt. Follow the instructions over at certbot's website to see how.
Certbot no longer supports Windows, so use win-acme instead.
In a PowerShell window opened with Run as administrator, from the win-acme folder, replacing C:\path\to\Geyser with Geyser's config folder:
.\wacs.exe --source manual --host play.example.com --validation selfhosting --store pemfiles --pemfilespath C:\path\to\Geyser
This creates play.example.com-chain.pem and play.example.com-key.pem directly in Geyser's config folder, and renews them automatically.
On macOS, certbot is the recommended way to obtain certificates from Let's Encrypt. Follow the instructions over at certbot's website to see how.
2. Configure Geyser
Set the files in the signaling section of the Geyser config. With win-acme, use the -chain.pem and -key.pem files instead.
bedrock:
signaling:
builtin:
https:
certificate: /path/to/fullchain.pem
private-key: /path/to/privkey.pem
password: ''
- Paths can be relative to Geyser's config folder, or absolute.
- A PKCS12 file (
.p12or.pfx) works as well: put it incertificate, leaveprivate-keyempty, and set itspassword. Usefile:/path/to/password.txtto keep the password out of the config.
Geyser reads the certificate when it starts. After a renewal, restart the server or run geyser reload, or players will get an expired certificate.
A reverse proxy sits in front of Geyser. It handles HTTPS, and passes signaling on to Geyser. Gameplay (UDP) still goes straight to Geyser.
1. Prepare Geyser
The proxy now uses TCP port 19132, so Geyser's signaling has to move to another port, like 19133. Players keep using port 19132.
Set these values in the bedrock section of the Geyser config:
bedrock:
port: 19133
webrtc-port: 19132
port is now the port signaling used behind the proxy, and webrtc-port keeps gameplay on UDP 19132.
Then tell Geyser to trust the proxy, so it sees each player's real address. Add this to the advanced section of the config:
advanced:
bedrock:
haproxy-protocol-whitelisted-ips:
- 127.0.0.1
Leave address in the bedrock section at 0.0.0.0. NetherNet does not work if Geyser only listens on 127.0.0.1.
2. Set up the proxy
- Caddy
- nginx
Caddy can obtain and renew certificates from Let's Encrypt by itself.
2.1. Install Caddy
You can install Caddy by following its installation guide.
2.2. Write the Caddyfile
Replace play.example.com with your domain:
{
servers {
# Caddy would otherwise use UDP 19132 for HTTP/3, which Geyser needs for playing
protocols h1 h2
}
}
play.example.com:19132 {
reverse_proxy 127.0.0.1:19133
}
On its first start, Caddy will attempt to obtain a certificate for your domain, and will renew it automatically when necessary. This requires port 80 to be reachable.
To use an existing certificate instead, add tls /path/to/fullchain.pem /path/to/privkey.pem inside the play.example.com:19132 block.
2.3. Start Caddy
- Linux
- Windows
- macOS
sudo systemctl enable --now caddy
# after changing the Caddyfile:
sudo systemctl reload caddy
# to see what Caddy is doing:
journalctl -xb -u caddy
In a PowerShell window opened with Run as administrator, from the folder with caddy.exe:
.\caddy.exe run
To start Caddy automatically with Windows, install it as a service:
sc.exe create caddy start= auto binPath= "C:\caddy\caddy.exe run --config C:\caddy\Caddyfile"
sc.exe start caddy
brew services start caddy
# after changing the Caddyfile:
brew services restart caddy
nginx does not obtain certificates by itself. If you do not have one yet, you could use certbot or win-acme to obtain one from Let's Encrypt.
2.1. Install nginx, and obtain a certificate
- Linux
- Windows
- macOS
Follow nginx's installation guide, you likely want to install nginx from a package using your distribution's package manager.
If you need a certificate, certbot is the recommended way to obtain certificates from Let's Encrypt on Linux. Follow the instructions over at certbot's website to see how. Select "Nginx" as software.
Download nginx from nginx.org and unzip it to C:\nginx.
nginx on Windows is less polished than on Linux, but works for this.
If you need a certificate, certbot no longer supports Windows, so use win-acme instead. In a PowerShell window opened with Run as administrator, from the win-acme folder:
.\wacs.exe --source manual --host play.example.com --validation selfhosting --store pemfiles --pemfilespath C:\nginx\certs
This creates play.example.com-chain.pem and play.example.com-key.pem in C:\nginx\certs, and renews them automatically.
After a renewal, reload nginx with C:\nginx\nginx.exe -s reload.
Install nginx on macOS using the Homebrew package manager:
brew install nginx
If you need a certificate, certbot is the recommended way to obtain certificates from Let's Encrypt on macOS. Follow the instructions over at certbot's website to see how. Select "Nginx" as software.
Your nginx config folder is $(brew --prefix)/etc/nginx/servers/.
2.2. Configure nginx
Create a file called geyser.conf: on Linux in /etc/nginx/conf.d/, on macOS in $(brew --prefix)/etc/nginx/servers/,
and on Windows in C:\nginx\conf\, then add include geyser.conf; inside the http { } block of C:\nginx\conf\nginx.conf.
If you already have a certificate, point ssl_certificate and ssl_certificate_key to its files.
server {
listen 19132 ssl;
server_name play.example.com;
# On Windows: C:/nginx/certs/play.example.com-chain.pem and C:/nginx/certs/play.example.com-key.pem
ssl_certificate /etc/letsencrypt/live/play.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/play.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:19133;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Do not add quic or http3 to the listen line: Geyser needs UDP 19132 for playing.
2.3. Reload nginx
Use the following commands to reload nginx and activate the new configuration:
- Linux
- Windows
- macOS
sudo nginx -t && sudo systemctl reload nginx
cd C:\nginx
.\nginx.exe -t
.\nginx.exe -s reload
nginx -t && brew services restart nginx
Then open your ports, restart your Minecraft server, and check that it works.
Opening ports
Forward these in your router, and allow them in your firewall:
- TCP 80: only if you obtain certificates through Let's Encrypt as described above
- TCP 19132: signaling (HTTPS)
- UDP 19132: playing
With a reverse proxy, port 19133 stays inside your machine. Do not open it.
- Linux
- Windows
- macOS
With ufw:
sudo ufw allow 80/tcp && sudo ufw allow 19132/tcp && sudo ufw allow 19132/udp
With firewalld:
sudo firewall-cmd --permanent --add-port=80/tcp --add-port=19132/tcp --add-port=19132/udp && sudo firewall-cmd --reload
If you use nftables or iptables directly, you probably know how to do this by yourself anyway.
In a PowerShell window opened with Run as administrator:
New-NetFirewallRule -DisplayName "Geyser TCP" -Direction Inbound -Protocol TCP -LocalPort 80,19132 -Action Allow
New-NetFirewallRule -DisplayName "Geyser UDP" -Direction Inbound -Protocol UDP -LocalPort 19132 -Action Allow
The macOS firewall is off by default. If you turned it on, allow incoming connections for java and caddy or nginx when macOS asks,
or in System Settings → Network → Firewall → Options.
See port forwarding for help with your router.
Checking that it works
- Look at the Geyser console. With a certificate in the Geyser config, it says
Built-in signaling started on https:// and http://. When using a reverse proxy, it saysBuilt-in signaling started on http://with port 19133. - On Bedrock, add the server with your domain name and port
19132. Join it: Minecraft should not ask whether you trust the server.
| What you see | What to do |
|---|---|
| Players still get the trust prompt | Make sure they use the domain name, not the IP address. |
| Console: "Built-in signaling could not start. Make sure no other program is using TCP port …" after adding a certificate | Usually a wrong file path or password. Turn on debug-mode in the config and restart to see the real reason. |
| Caddy or certbot cannot get a certificate | Check that TCP port 80 is forwarded to this machine, and that your domain points to your current IP. |
| Server shows up, but joining times out | UDP 19132 is not reachable, or Caddy uses it. Check the protocols h1 h2 line, and your firewall. |