setupmc.com

NetherNet on iPhone and iPad: HTTPS for BDS and Geyser

Fix NetherNet issues on iOS and iPadOS: set up HTTPS for BDS or Geyser and choose between Warden Cloud, playit.gg and Tailscale.

Networking
setupmc.com Team

Windows joins, but your iPhone or iPad cannot connect

Record the full error, client version, server build and whether the test uses Wi-Fi, mobile data or VPN. InitialConnection-13, Door and NetherNet alone do not identify a certificate problem. First check the setup for vanilla BDS or Geyser.

Documented: NetherNet separates HTTP/HTTPS signaling from UDP gameplay. TLS protects signaling; it does not replace the UDP path. Mojang documents HTTP signaling, so do not assume that all iOS and iPadOS versions universally require HTTPS. See the protocol guide.

Reported workaround: In BDS-23108, an iOS 26.52 client failed against BDS 1.26.52.3 over direct HTTP, then joined through HTTPS with the gameplay endpoint unchanged. The test also changed the signaling hostname and path, so it did not isolate the root cause. itzg #680, still open on 29 October 2026, reports TLS alert 40 on ARM64/Box64 with BDS 1.26.51.1 and iOS 26.51. These reports do not prove the same defect affects every 26.60 client.

Find your public IP without renting a server

If Minecraft runs on your PC or NAS at home, you do not need a rented server to have a public IP: your internet connection determines that. If you only want to play on someone else's server, ask its operator for the join address; you do not need your own IP.

  1. On a device on the same home network as the Minecraft machine, open ipify's IPv4 display. Do not use a VPN/proxy exit or mobile hotspot for this comparison. The result is the outgoing IPv4 seen by that service.
  2. Compare it with the router's WAN/internet IPv4. On a FRITZ!Box, look under Internet → Online Monitor, then Connection Details depending on FRITZ!OS. Your PC's LAN address from ipconfig, such as 192.168.178.20, is different.
  3. If both match and the router address is public, use it for the IPv4 examples. Then configure the required TCP/UDP forwarding and test a complete join from outside the network.

Alternatively, on Linux/macOS or in a shell with curl:

curl -4 --fail --max-time 10 https://api.ipify.org

Windows PowerShell also supports:

Invoke-RestMethod -Uri 'https://api.ipify.org'

Seeing an IP does not prove inbound reachability. Different addresses can indicate another router, a VPN or provider NAT. A router WAN address in 100.64.0.0–100.127.255.255 indicates CGNAT; private ranges such as 10.x.x.x, 172.16.x.x–172.31.x.x and 192.168.x.x are not public IPv4 addresses either. DS-Lite often lacks a dedicated public IPv4. Ask your provider about an address accepting inbound connections, or use a suitable tunnel/IPv6 route. See the FRITZ! router diagnostic.

When your public IP changes, update DNS/DDNS and the advertised UDP address. A hostname alone does not update a literal IP in the server configuration. Another device's public IPv6 or the router's WAN IPv6 is not automatically the Minecraft machine's correct IPv6. With hosting or tunnels, use the provider's assigned endpoints instead of your home connection's IP.

Choose how to provide HTTPS

SetupSuitable approachWhat remains necessary
Geyser with certificate filesBuilt-in HTTPSReachable gameplay UDP and certificate renewal
Self-hosted Geyser or BDSHTTPS reverse proxy in front of signalingCorrect upstream, certificate hostname and separate UDP route
Geyser with WardenExternal HTTPS signalingWorking gameplay connectivity; verify an actual join
Private Tailscale groupTailnet connectivity, optionally a ts.net certificatePlayers need access to the tailnet and advertised gameplay destination

The examples below use a domain certificate: players enter play.example.com, not the server IP. Point its DNS records at the HTTPS endpoint. Publish an AAAA record only if the IPv6 path works too.

What Caddy does here

Caddy is a web server used here as a reverse proxy: it accepts the game's HTTPS request and forwards it internally over HTTP to Geyser or BDS. Clients still connect directly to the Minecraft server for UDP gameplay.

Caddy can obtain and renew the certificate for your hostname automatically. Your domain and certificate validation must be configured as described below. Install Caddy as a separate service on the server machine; players do not install anything extra. The Caddyfile is its configuration file, usually /etc/caddy/Caddyfile with a Linux package installation.

Choose one HTTPS approach: if you already have certificate files for Geyser, use the next section. To let Caddy manage certificates, follow the Caddy example for Geyser or BDS. If you use Geyser with Warden, Warden provides HTTPS signaling, so you do not need Caddy for that.

Geyser: use a certificate directly

Merge this into the existing bedrock.signaling configuration, retaining the NetherNet transport and reachable UDP advertisement from the main guide:

bedrock:
  signaling:
    mode: builtin
    builtin:
      https:
        certificate: /path/to/fullchain.pem
        private-key: /path/to/privkey.pem
        password: ''

Obtain a trusted certificate for the hostname before setting these paths. The Geyser process must be able to read the chain and key; container paths must exist inside the container. Keep the private key private. Restart after configuring it, and arrange certificate renewal plus restart or certificate reload after renewal. See the official Geyser HTTPS instructions for issuance and platform details.

Geyser: put Caddy in front of HTTP signaling

For Caddy and Geyser on the same host/network namespace, use public TCP 19132 for Caddy, private TCP 19133 for signaling and UDP 19132 for gameplay. Replace YOUR_PUBLIC_IP before saving. Merge these settings into the existing file, preserving authentication:

bedrock:
  address: 0.0.0.0
  port: 19133
  clone-remote-port: false
  transport: nethernet
  webrtc-port: 19132
  signaling:
    mode: builtin
    advertise-addresses:
      - "YOUR_PUBLIC_IP:19132"
advanced:
  bedrock:
    signaling-trusted-proxies:
      - 127.0.0.1

Use this Caddyfile after installing Caddy:

{
    servers {
        protocols h1 h2
    }
}

play.example.com:19132 {
    reverse_proxy 127.0.0.1:19133
}

Keep TCP 19133 inaccessible externally. Leave Geyser's bind address at 0.0.0.0; restrict access through firewall rules or container publication. If Caddy runs in another container, 127.0.0.1 is not Geyser: use its service address and trust only the actual proxy source address. Do not trust every sender of X-Forwarded-For.

Validate with caddy validate --config /etc/caddy/Caddyfile, restart Geyser and reload Caddy using your service manager. Permit public TCP 19132 and gameplay UDP 19132. The protocols h1 h2 setting prevents HTTP/3 from competing for gameplay UDP on that port. Certificate issuance/renewal also needs a working ACME challenge: make TCP 80 reachable for the HTTP challenge, or configure a supported DNS challenge. DNS validation does not create a gameplay route through CGNAT.

BDS: HTTPS proxy with a separate UDP range

For BDS, use the BDS configuration with transport=nethernet, internal signaling TCP 19132 and a reachable advertised UDP range, for example 19140–19149 for ten connections.

For Caddy running on the Docker host, publish BDS signaling only on host loopback and retain the gameplay publications in the existing BDS Compose service:

ports:
  - "127.0.0.1:19132:19132/tcp"
  - "19140-19149:19140-19149/udp"

Keep SERVER_UDP_PORTS: "YOUR_PUBLIC_IP:19140-19149:19140-19149" and MAX_PLAYERS: "10" in that service, replacing the IP. Preserve the data volume. Recreate the service after changing publications with docker compose up -d bds, using your actual service name.

Use this alternative Caddyfile, not the preceding Geyser block:

play.example.com:443 {
    reverse_proxy 127.0.0.1:19132
}

Players add play.example.com with port 443. Allow/forward TCP 443 to Caddy and UDP 19140–19149 to BDS, plus the challenge path required for certificate renewal. The HTTPS port and gameplay ports do not need to match. For native BDS, restrict access to its upstream TCP listener with the host firewall. If Caddy is containerized, adapt the upstream network instead of using host loopback.

This topology applies HTTPS termination to signaling. It does not rewrite SDP/ICE candidates or relay gameplay: if BDS advertises an unreachable address, fix the BDS advertisement and UDP mappings. Forward both GET /v1/join and POST /v1/join/{networkId} with bodies intact, without browser login, CAPTCHA or redirects.

Warden Cloud, playit.gg and Tailscale

Warden Cloud: HTTPS signaling for Geyser

Warden Cloud is an external service for the initial contact between Bedrock and Geyser. Geyser registers with it; players enter the assigned Warden address in Minecraft and need no extra app. Warden provides and renews the HTTPS certificate.

Gameplay then connects directly to the Geyser server. Warden does not tunnel this traffic or hide the server IP. UDP port forwarding is preferred; assisted connections through NAT can help without forwarding, depending on both networks. Test a full join. For vanilla BDS, use the HTTPS proxy from the preceding section.

For Geyser, merge this into the existing configuration:

bedrock:
  transport: nethernet
  signaling:
    mode: nxs

Keep your UDP settings. Fully restart and use the Warden hostname and port printed in the console, commonly 443. Successful registration alone does not prove a successful game connection; test from the actual player network.

playit.gg: a public tunnel to your home server

playit.gg forwards connections from a public address to your Minecraft machine. Install the playit agent on the server machine; players need no extra app. This is an option when you cannot forward ports on your router.

Choose a tunnel covering the required TCP and UDP paths. Geyser needs one gameplay UDP port; BDS needs its configured UDP range. A plain TCP/UDP tunnel does not provide an HTTPS certificate. The HTTPS tunnel guide describes local TLS termination with Caddy and requires Premium. The playit website currently lists NetherNet as a Premium feature too. Check the appropriate tunnel type and plan before setting up.

The older Bedrock instructions still recommend switching back to RakNet. This does not work for clients from 26.60 onward. With Geyser, you can combine Warden for HTTPS signaling and a suitable playit UDP tunnel for gameplay. Set bedrock.signaling.advertise-addresses to the public UDP hostname or IP and external port assigned by playit. The local tunnel destination must match Geyser’s webrtc-port; with webrtc-port: 0, this is bedrock.port.

Tailscale: a private network for your player group

Tailscale connects devices through a private VPN network called a tailnet. In the simple setup, both the server operator and players install Tailscale on their devices and receive access to that network. This suits a fixed group on supported devices; it does not give the server a public join address for arbitrary players.

Players use a reachable Tailscale address of the server machine. The UDP address advertised by NetherNet must also be reachable through that network. VPN encryption does not replace an HTTPS certificate: tailscale cert can obtain one for the machine's full *.ts.net name. If you install the files in Geyser yourself, arrange renewal and certificate reloads.

If joining works through Tailscale but fails through the public address, compare both network paths. The successful VPN test alone does not identify whether TLS or routing caused the public connection failure.

Test the certificate, signaling and game in order

From outside the server network, test the actual player hostname and port:

curl --fail --max-time 10 https://play.example.com:443/v1/join
openssl s_client -connect play.example.com:443 -servername play.example.com -verify_hostname play.example.com -verify_return_error </dev/null

For Geyser’s built-in HTTPS and the Geyser/Caddy example, use 19132 instead of 443. For Warden, use its assigned hostname and port; for the BDS/Caddy example, use your hostname with port 443. Do not bypass certificate verification with curl -k as proof that TLS works. Then use the connection test and make a full Minecraft join on the affected iPhone or iPad. Compare the same client over mobile data and Wi-Fi, then another platform. For BDS, also test a second simultaneous player.

SymptomNext check / evidence
Certificate name mismatch or untrusted issuerPlayer hostname, complete chain, validity and DNS target
HTTP browser test works but iOS join never reaches signalingCompare TLS logs and the hostname used
HTTPS returns HTML, redirect, 404 or authentication screenReverse-proxy route and any access layer in front of the signaling paths
GET succeeds but joining failsCheck the join POST and server logs, then gameplay UDP; GET alone is insufficient
Server listed, join times outAdvertised ICE address, full UDP path and any HTTP/3 port conflict
Only the second BDS player failsUDP range capacity and forwarding for every allocated port
Geyser cannot start HTTPS after renewalFile paths, permissions, key/chain match, password and application reload

For Geyser-specific HTTP 500, native-library and data-channel errors, see the versioned troubleshooting reports. Keep your existing world and identity files while diagnosing network failures.

Sources

Sources checked: 29 October 2026.

Use the matching tool

Bedrock connection test

Test initial contact with your public Bedrock NetherNet endpoint and get practical troubleshooting steps.

Open Bedrock connection test

Frequently asked questions