Host a game server on Starlink with a free VPS relay
Yes, for a game that uses TCP, such as Minecraft Java Edition: Starlink's help page says its default IPv4 configuration uses carrier-grade NAT (CGNAT) and "does not allow inbound traffic" (October 2026), so players connect to a cloud VM with a public IPv4 address instead, and a relay there passes each connection over a tailnet to the game server at home. In October 2026, a Minecraft Java server at home on a Starlink connection answered 30 of 30 server-list pings through such a relay on a free-tier VM, sent over the public internet from the same home connection; the relay leg, VM to server and back, was a median of about 20 ms (the three sittings' medians ran from 17.9 to 23.6 ms), estimated as the round trip through the relay less the round trip to the VM and the server's answer time. Games that use UDP, such as Minecraft Bedrock Edition and Palworld, need a relay that carries UDP: one UDP packet sent to the tested relay's game port got no answer, as at a closed port.
Promo: $100 off Starlink with my referral link
If you've never been a Starlink customer and you order an eligible Residential or Roam plan through my link, we both get Starlink's reward for your country. In the US, that is a $100 credit on your second monthly bill, and I get $100 too. Use my referral link
How players reach a server at home without port forwarding
If your router has no public IPv4 address, players' connections from the internet arrive at your provider's NAT first, and a port forward on your own router gets them only if that NAT forwards the port too. The guide to self-hosting without a public IPv4 address shows what that looks like from a home Starlink connection.
Starlink's help page What IP address does Starlink provide? says its default IPv4 configuration uses carrier-grade NAT (CGNAT), and that this "default" policy "does not allow inbound traffic" (checked October 2026). A public IPv4 address on the line itself is a Priority plan option, Starlink's help page on setting a public IP says.
A relay turns the connection around. The path has four steps:
- A player's game connects to the public IPv4 address of a cloud VM, the relay VM, on the game's port.
- A relay program on the VM accepts the connection and opens its own connection to the game server's address on a tailnet, the private network your machines join with Tailscale's client.
- The tailnet carries that connection home, straight between the two machines or through a DERP relay server. Tailscale's page on connection types says every connection starts out relayed through DERP and goes direct where it can, and that some networks, which it calls hard NAT, prevent the direct path (checked October 2026).
- The game server answers the same way back.
Players connect only to the relay VM's public address, and the relay, not the player, opens the connection to your home.
Minecraft Java answered 30 of 30 server-list pings through the relay
I host a Minecraft Java Edition server this way, in Docker at home on a Starlink connection. Players connect to a free-tier cloud VM with a public IPv4 address, where socat relays each TCP connection on port 25565 over my Headscale tailnet, which runs on WireGuard, to the game server. I set the tailnet's policy so the relay VM can reach that one port at home and nothing else.
A read on the game server in October 2026 found the itzg/minecraft-server image with online-mode, the whitelist and enforce-whitelist all on. Docker publishes TCP 25565 to it, not UDP.
The test ran in October 2026 from a wired computer on the home network, in three sittings of 10 rounds each, all on one day, every probe at least 2 s after the one before. Each round made a bare TCP connection to the relay VM's public address on port 25565, then a server-list ping through the relay: the status request a Minecraft client sends to show a server in its list, followed by a ping and pong on the same connection. It never logs in. Before each sitting, the route to the VM's address was checked: it left by the home connection's default route, not the tailnet. In every sitting, the status answer through the relay matched the one read straight from the game server over the tailnet, so the relay led to this server.
| Probe | Result |
|---|---|
| TCP connection to the relay VM, port 25565 | 30 of 30 connected |
| Server-list ping through the relay | 30 of 30 answered |
| Control: TCP connection to port 25566 on the VM, which nothing serves | 0 of 3 connected; each timed out, none was refused |
| Control: server-list ping straight to the game server over the tailnet | 29 of 30 answered |
The one direct ping that failed, and two that connected only after their first packet was sent again, were on the direct tailnet path inside the home network. The relay answered normally in the same rounds. Why the direct path stalled wasn't examined, since it was only a control.
Limitation
Every probe ran from the same home connection the game server uses: out over the public internet to the relay VM, then back home through the relay. A player on another network wasn't part of the test. The pings asked for the server's status only, with no login and no play.
The test's pings left no line in the game server's log. The log's existing player lines, from earlier logins, all carry one private address from the network Docker set up on that machine: never the relay VM's tailnet address and never a player's own address. The log doesn't show which way those players came in.
The relay leg, from the VM to the game server and back, came to about 20 ms (an estimate)
A round trip through the relay covers the leg from the player to the relay VM and the relay leg: from the VM over the tailnet to the game server and back, with the relay's own forwarding. The relay leg came to about 20 ms, as an estimate. That is the median of 27 rounds, and the three sittings' medians ranged from 17.9 to 23.6 ms. The satellite internet comparison sets this estimate beside the minimum round trip through a geostationary satellite.
For each round, the estimate takes the ping-to-pong time through the relay, less that same connection's round trip to the VM, measured a moment before, and less the game server's own answer time, measured straight over the tailnet. The parts weren't measured at the same instant, and the home connection's round trip changes from second to second, as the latency guide shows. Three rounds were left out because their direct connection, which the estimate relies on, failed or needed a packet sent again.
The test computer and the game server share the home connection, so every probe through the relay left home over Starlink to the VM and came back in over Starlink inside the tailnet. For a player elsewhere, their own leg to the VM takes the place of the test computer's, and the relay leg stays.
Limitation
Not measured: a remote player's own leg to the VM, which depends on their network and how far they are from the VM; real play, as opposed to status pings; the round trip the game shows; whether the tailnet path from the VM to home ran direct or through a DERP relay server; the VM's own load; and other days and times.
A TCP relay carries TCP games; UDP games need a UDP relay
A TCP relay carries TCP only. Each game's own documentation or wiki says which protocol its server uses (checked October 2026):
| Game | Default ports, from its docs | Relay it needs |
|---|---|---|
| Minecraft Java Edition | TCP 25565 | TCP, the relay tested here |
| Minecraft Bedrock Edition | UDP 19132 (19133 for IPv6 with the RakNet transport) | UDP |
| Terraria | TCP 7777 | TCP; see below |
| Factorio | UDP 34197 | UDP |
| Palworld | UDP 8211 | UDP |
| ARK | UDP 7777 (game), 7778 (peer) and 27015 (query) | UDP |
| Satisfactory | TCP and UDP 7777, TCP 8888 | TCP and UDP |
The rows come from the Minecraft Wiki's pages on server.properties and Bedrock Dedicated Server, a community wiki; the Official Terraria Wiki's Server page; the Factorio Wiki's Multiplayer page, which says "Factorio uses UDP only"; the Requirements page of Pocketpair's Palworld Server Guide; the ARK Official Community Wiki's Dedicated server setup; and the Official Satisfactory Wiki's Dedicated servers page. Each lets you change the default port. Terraria's page says its server "runs on TCP port 7777 by default", and its note for cloud providers says to open 7777 on TCP and UDP. Satisfactory's says "Port redirection is not supported at the moment for the standard port", so a relay there keeps that port's number, 7777 by default, the same on both sides. Its reliable messaging port, TCP 8888 by default, "can be remapped" with the -ExternalReliablePort= command-line parameter, the same page says.
At the tested relay's address, one UDP packet, the discovery ping a Bedrock client sends to find servers, got no answer within 5 s on port 25565. The same packet to port 25566, which nothing serves, got the same silence, while a server-list ping over TCP on 25565 answered in the same minute. On the game server, Docker publishes 25565 for TCP only.
Free cloud VMs come with terms to check first
The relay needs a VM with a public IPv4 address that stays up while people play. Several cloud providers publish free offers: the AWS Free Tier, Azure's free services, Google Cloud's free features and the Oracle Cloud Free Tier (pages checked October 2026). Free offers change, so read the provider's current page before you build on one. Look for:
- whether the VM stays free with no end date, or only for a trial period;
- whether the free VM includes a public IPv4 address, and whether that address is billed separately;
- how much outbound data is free each month;
- whether the provider can reclaim a VM it considers idle;
- what signing up needs, such as a payment card.
A relay sends every player's traffic through the VM, so its outbound data grows with players and play time.
Build it with one open port, one tailnet rule and the game's own login
These steps use Minecraft Java Edition. For another TCP game, use its port from the table above.
At home, run the game server in Docker with the game's own login checks on. The
itzg/minecraft-serverimage takes its settings as environment variables, per its documentation (checked October 2026):scrolls sideways docker run -d -it --name mc -p 25565:25565 \ -e EULA=TRUE -e ONLINE_MODE=TRUE \ -e WHITELIST=your-friend-1,your-friend-2 \ -e ENFORCE_WHITELIST=true \ -v "$PWD/data:/data" itzg/minecraft-server-p 25565:25565publishes the port for TCP. Docker's page on port publishing maps a port to TCP unless it ends in/udp(checked October 2026).EULA=TRUEaccepts Minecraft's end-user license agreement, which the image's documentation says to "always include".ONLINE_MODE=TRUEkeeps online-mode on, which the Minecraft Wiki describes as "Whether to only allow players verified with the Minecraft account database to join". It is on by default.WHITELISTturns the whitelist on and lists who may join. Put your players' Java Edition profile names in place ofyour-friend-1,your-friend-2; the image's documentation says to use those, "not Xbox gamertags".ENFORCE_WHITELIST=truesets enforce-whitelist. With it on, the Minecraft Wiki says, "players not present on the whitelist get kicked from the server after the server reloads the whitelist file".-v "$PWD/data:/data"keeps the world in adatafolder where you run the command, since the image stores the server's data in the container's/data.
Other games have their own join checks, such as the server password in ARK's start command, on the same wiki page as its ports.
Get a cloud VM with a public IPv4 address (what to check in a free offer). The relay needs only Tailscale's client and socat on it.
Join the game server's machine and the relay VM to one tailnet. With Headscale, which this page doesn't set up, each machine runs
tailscale up --login-serverwith your Headscale server's address, and you approve it on the Headscale server (Headscale's registration methods, checked October 2026). The guide to leaving a wired ISP covers what a tailnet reaches on its own.Allow the relay VM to reach the game port and nothing else. Headscale's policy page says that by default "no policy is loaded which means that Headscale allows all traffic between nodes", that it reads the file at the
policy.pathsetting of its configuration, and that it "needs to be reloaded to pick up changes" (checked October 2026). This policy file allows one thing: the relay VM opening TCP connections to port 25565 on the game server. On Headscale 0.29.7, in October 2026, this policy loaded,headscale nodes tagapplied both tags and refused a tag the policy doesn't define, and the rules Headscale built from it allowed only TCP to port 25565 on the game server, from the relay; no client was connected for that check.scrolls sideways { "tagOwners": { "tag:game-relay": [], "tag:game-server": [] }, "acls": [ { "action": "accept", "src": ["tag:game-relay"], "proto": "tcp", "dst": ["tag:game-server:25565"] } ] }Tailscale's policy syntax reference, whose file format Headscale uses, says access rules "deny access by default". So once this policy loads, anything it doesn't allow is blocked: if other devices on your tailnet need to reach each other, add rules for them. Without
"proto": "tcp", the same reference says, a rule "applies to all TCP and UDP traffic". In Tailscale's syntax, an empty list undertagOwnersis shorthand for the tailnet's admins; on Headscale, the administrator sets tags with theheadscale nodes tagcommand in the next step. Headscale's policy page recommends grants, Tailscale's newer rule syntax, and supports rules like this one too.Tag the two machines on the Headscale server, with the IDs that
headscale nodes listshows for them in place of 1 and 2, as Headscale's page on tags describes (checked October 2026):scrolls sideways headscale nodes list headscale nodes tag -i 1 -t tag:game-server headscale nodes tag -i 2 -t tag:game-relayOn the relay VM, start the relay.
game-serverstands for the game server's name or address on the tailnet:scrolls sideways socat TCP4-LISTEN:25565,fork,reuseaddr \ TCP4:game-server:25565socat's manual calls a
TCP4-LISTENaddress with aTCP4address "a simple TCP port forwarder". Withfork, socat "handles its channel in a child process" for each connection, so several players can connect at once.reuseaddr"Allows other sockets to bind to an address even if parts of it (e.g. the local port) are already in use by socat" (checked October 2026). Run the command under the VM's service manager so it starts again after a reboot.Open one port. In the provider's firewall for the VM, and in the VM's own firewall if it runs one, allow TCP 25565 from anywhere. Keep every other port closed, apart from the one you log in to the VM through if you log in over the internet.
Give players the relay VM's public IPv4 address, such as 203.0.113.10 in this page's examples, or a DNS name you point at it, such as
mc.example.com.
Three ways to relay a UDP game, from their documentation
Limitation
None of the methods in this section was tested here. Each comes from its project's own documentation, checked October 2026.
UDP has no connection for a relay to accept. socat's manual says that with UDP "no real connection is established; data has to arrive from the peer first", and that "no end-of-file condition is specified in UDP". So a UDP relay keeps track of each player and has to drop that player after a time with no data.
In each method below, the game server publishes its port for UDP (-p 34197:34197/udp in Docker), and the policy rule takes "proto": "udp" and the game's port. Factorio's port, 34197, is the example.
socat in UDP mode
On the relay VM:
socat -T 60 UDP4-LISTEN:34197,fork,reuseaddr \
UDP4:game-server:34197-T is socat's "Total inactivity timeout", which the manual calls "Useful with protocols like UDP that cannot transfer EOF". Here it ends a player's child process after 60 seconds with no data. Up to socat 1.8.0.0, -T 0 meant no timeout; since 1.8.0.1 it means 0, the manual says, so give it a number.
Destination NAT in the VM's kernel
The nftables wiki's NAT page shows the two rules this takes: a dnat to rule in a prerouting chain of type nat, which sends the game port's packets on to the game server's tailnet address, and masquerade in a postrouting chain, where "the source address is automagically set to the address of the output interface", here the VM's tailnet address, so the game server answers the VM. The kernel must also forward packets between its interfaces, which is the setting net.ipv4.ip_forward: "Forward Packets between interfaces", in the kernel's documentation.
nginx's stream module
In nginx's stream core module, listen 34197 udp reuseport; in a server block opens a socket "for working with datagrams"; the page says reuseport "should also be specified" so that packets from one address and port stay in one session. The stream proxy module passes them on with proxy_pass to the game server, and proxy_timeout, 10 minutes by default, closes a session when "no data is transmitted within this time". The core module's page says it "is not built by default" and needs the --with-stream build option, so check that your nginx has it.
Bedrock Edition can need more than one port. The Minecraft Wiki's copy of the server.properties file that ships with Bedrock Dedicated Server 1.26.60.6 sets transport=nethernet and server-udp-ports=19132, a setting that "Configures UDP client transport ports": that is a "Single UDP port shared by all clients". If it isn't set, the file says, "UDP ports are allocated from the operating system's ephemeral port range", and a relay would have to carry those ports too. With that transport, the file's IPv6 port setting is ignored and IPv6 uses 19132 as well. This page hasn't tried Bedrock through a relay.
Managed tunnels skip the VM, from their own pages
None of these was tested here. Each one runs the public end for you, so there's no VM to set up or patch; in return, their network carries your players' traffic. All pages were checked October 2026.
playit.gg calls itself "a global proxy that lets you host a server without port forwarding", with an agent on your machine: "Only you run the agent, your players just connect." Its home page names a free tier and a paid Premium plan; its game list puts Minecraft Java and Bedrock, Palworld, Terraria, Factorio and a plain "UDP" entry under "Free", and plain "TCP" and "TCP+UDP" entries, with some other games, under "Requires Playit Premium".
ngrok's pricing page says that on its Free plan "TCP endpoints also need a verified credit card, and ngrok doesn't charge it".
Tailscale Funnel "can only listen on ports 443, 8443, and 10000", and "only works over TLS-encrypted connections". Minecraft Java Edition's default port, TCP 25565, isn't one of those ports. On Headscale's features page, Funnel is one of the items without a tick.
Cloudflare Tunnel needs Cloudflare's client on each player's machine for anything other than a web service, as the guide to leaving a wired ISP quotes. Cloudflare Spectrum's page says "Custom TCP/UDP applications require an Enterprise plan with Spectrum as a paid add-on" (last updated April 2026). Its protocols per plan table (last updated August 2026) lists Minecraft, one app, on the Pro and Business plans too, where Spectrum is a paid add-on.
A mesh VPN that every player joins needs no relay at all, but each player installs the client and joins your tailnet (what a mesh VPN reaches).
Not tested here yet
- A player on another network. Every probe ran from the same home connection the game server uses.
- Real play. No probe logged in or played, so the round trip the game shows, several players at once and a whole session are untested.
- UDP through any relay, Bedrock Edition and every game but Minecraft Java Edition.
- The relay VM's side. Whether its path home ran direct or through a DERP relay server, its load, its firewall settings and whether the tailnet policy keeps it from reaching anything else at home weren't checked from the VM.
- What the game server logs for a player who came through the relay. The log's player lines came from earlier logins whose path isn't known.
- A VM in another region, other days and times, the managed tunnels, and running the game on the VM itself.
Promo: $100 off Starlink with my referral link
If you've never been a Starlink customer and you order an eligible Residential or Roam plan through my link, we both get Starlink's reward for your country. In the US, that is a $100 credit on your second monthly bill, and I get $100 too. Use my referral link
Sources
- What IP address does Starlink provide?, Starlink, accessed
- How do I set my IP address to a public IP?, Starlink, accessed
- Connection types, Tailscale, accessed
- Syntax reference for the tailnet policy file, Tailscale, accessed
- Policy, Headscale, accessed
- Tags, Headscale, accessed
- Registration methods, Headscale, accessed
- Features, Headscale, accessed
- socat manual, dest-unreach.org, accessed
- Port publishing and mapping, Docker, accessed
- Minecraft Server on Docker (Java Edition), Intro, itzg/docker-minecraft-server, accessed
- Minecraft Server on Docker (Java Edition), Server properties, itzg/docker-minecraft-server, accessed
- server.properties, Minecraft Wiki, accessed
- Bedrock Dedicated Server, Minecraft Wiki, accessed
- Server, Official Terraria Wiki, accessed
- Multiplayer, Factorio Wiki, accessed
- Requirements, Palworld Server Guide (Pocketpair), accessed
- Dedicated server setup, ARK Official Community Wiki, accessed
- Dedicated servers, Official Satisfactory Wiki, accessed
- Performing Network Address Translation (NAT), nftables wiki, accessed
- IP Sysctl, Linux kernel documentation, accessed
- Module ngx_stream_core_module, nginx, accessed
- Module ngx_stream_proxy_module, nginx, accessed
- AWS Free Tier, Amazon Web Services, accessed
- Explore Free Azure Services, Microsoft Azure, accessed
- Free Google Cloud features and trial offer, Google Cloud, accessed
- Oracle Cloud Free Tier, Oracle, accessed
- Make Your Game Server Public, playit.gg, accessed
- ngrok Pricing, ngrok, accessed
- Tailscale Funnel, Tailscale, accessed
- Cloudflare Spectrum, Cloudflare, accessed
- Protocols per plan, Cloudflare, accessed
- Does Starlink have a referral program?, Starlink, accessed
- Referral Program Terms (US), section 4.1, Starlink, accessed
Retest log
- Test Three sittings from a wired computer on the home network, over the public internet through the relay VM, with controls; one UDP packet to the relay's game port.
Related guides
- Can you host a server on Starlink without a public IPv4 address?
Not directly over IPv4: without a public IPv4 address, connections from the internet arrive at your provider's NAT, and a port forward on your own router doesn't reach it.
- Leaving a wired ISP: does Starlink give you a public IP address?
For IPv4, only as an option on Priority plans: Starlink's help pages say its default IPv4 configuration uses carrier-grade NAT (CGNAT) and "does not allow inbound traffic", that public IPv4 is "an optional configuration available to Local and Global Priority customers", and that "truly static IPs are not available" (October 2026).
- Is Starlink good for a homelab? A verdict from five tests
On the one home Starlink connection tested, packets of 1500 bytes crossed over IPv4 and IPv6 in October 2026, and round trips over IPv4 spiked at four set seconds each minute in one of two one-hour tests, with 901 of 143,462 pings lost over both; the ways around carrier-grade NAT (CGNAT), such as a tunnel that starts inside your network, aren't tested here.