Tuesday, February 6, 2024

Running an OpenRCT2 multiplayer server from a jumphost

So, you want to run an OpenRCT2 server ey?
And you have a cheap remote VPS with a public IP, but you run all your server stuff selfhosted at home with a more powerful machine because VPS costs are bullshit ey?
Well, come take a looksie, here's how I got things to "kind-of-work".

I say "kind of" because there are still some issues, namely:
1. Effectively zero security :(
2. Manual park setup and pause/unpause :(
3. Unusable IP logs because all IPs connect as the VPS from the proxy :(

What I had to start:
1. A public domain name and IP address (I use an AWS Lightsail VPS)
2. Your selfhosting machine (I use a second computer at home)
3. A third, "client" machine to play the game with
4. Patience and some shell scripting ability

What I did to get things working:
1. Purchase Roller Coaster Tycoon 2 on Steam
2. Build a local podman container of OpenRCT 0.4.8 on your selfhosting machine
3. Launch the OpenRCT server using the container on your selfhosting machine
4. Setup a reverse proxy on the VPS and connect it with the selfhosting machine

Let's dive in!


1. A public domain name and an IP address

First you'll need a public IP address and preferably, a world-resolvable domain name. I use AWS Lightsail because they cost 5 dollars a month for Amazon backed unmanaged-hosting (soon to be 7.50 because of IPv4 migration costs). Not an advertisement, but just letting you know what I work with. Debian 12 running on a weak little VPS. I bought a domain name from the Cloudflare Registry, turned off the Cloudflare proxy (because non HTTP traffic through the Cloudflare proxy is against their TOS), and we are off to the races!

2. A selfhosting machine at home
My selfhosting machine is a server box running at home. I run as AsRock DeskMini X300 that I've wired into the wall with Cat 5, and swapped the Wifi card out for an Intel AX210. Running on a Ryzen 5600G that I've TDP limited to 35W. Again, not too important - you are hosting a multiplayer server for a 30 year old game.

3. Buy the game. You'll need Roller Coaster Tycoon 2, which I bought on Steam. Download the OpenRCT2 client as well (the latest at this time is 0.4.8). Make sure the game runs on your machine.

4. Launching the game as a dedicated server.
Ok finally.

So, we are going to spin up a container for the dedicated server, and run the container on our selfhosting machine. To do this, we will first need to build the OpenRCT2 server container, because while OpenRCT2 publishes the image on Docker Hub, it hasn't been updated since 0.4.4 (the latest at the time of writing is 0.4.8)

4a. First you'll need to build the OpenRCT2 container on your selfhosting machine. To do this easily for myself, I've written a small dockerize script, though you can roll your own - whatever gets 0.4.8 in a container on your machine.

4b. Next you'll first need to create a new save. First you'll need to launch the client and start any scenario you want. Immediately save the game. Find the OpenRCT2 game folder on your machine (for me it was in $HOME/.config/OpenRCT2), and copy the saved .park file out of the save directory.

4c. Volume mount the save file to the OpenRCT2 container, and launch the container as a dedicated server, providing it the file to your park. For this, I use a runner script.

4d. At this point your dedicated server should be running. You can test it by launching the game client, and clicking the "Add Server" button, providing localhost as the server address.

4e. You might notice when you connect that your game is paused. In order to unpause the game, you'll need to type into the openrct2> console in the container that is running (you allocated a PTY and attached stdio didn't you?), and issue the command context.executeAction("pausetoggle", {});

4f. You may also notice your connected player joins as a "Spectator", unable to do anything. To fix this, you need to grant your player admin level access to the Scenario, by running network.players[1].group = 0 in the openrct2 container console.

5. Opening the server to the world for others to join you
What's multiplayer without other players? This is the "port-forwarding" step, but a bit more complex.
You'll need a way to proxy raw TCP traffic from your VPS machine to your selfhosted machine. This was a little tricky for me, as I run Caddy for HTTP related proxy stuff, but Caddy doesn't speak raw TCP (it's a layer thing), so I needed something else. I decided to use frp.

5a. Run frps on the VPS

5b. Run frpc on the selfhosted machine

5c. Open the OpenRCT2 port on the firewalls for both the VPS and the selfhosted machine.

5d. At this point, you should be all done! Go into the OpenRCT2 client, and this time add a server using your VPS domain name. You should be able to connect!

--
To recap, here is what I run when starting my OpenRCT2 server

On the VPS
$ systemctl --user start frps@openrct2

On the selfhosted machine
$ systemctl --user start openrct2-server@my_save_file.park
$ systemctl --user start frpc@openrct2-server
$ podman attach openrct2-server
openrct2> context.executeAction("pausetoggle", {});
openrct2> network.players[1].group = 0


Some shortcomings are:
1. Zero security. Any person in the world can connect to your VPS now at the OpenRCT2 port and get access to your multiplayer game if they know/guess the password. Security at this point is left up to OpenRCT2, and being as it's a video game, security is not a first priority per-se.

2. No way to know the IP of the client connecting to your server. All player IPs in the openrct2 logs will come over as your network interface IP, since connections are being proxied through fprs and frpc, and OpenRCT2 itself does not have support for the PROXY TCP protocol. No way to know which IP is doing what because of this.

3. Despite using the "pause when empty" config option, your server always seems to start permanently paused, and does not pause the game when you leave. You'll need to manage pause/unpause state yourself, so it's not a "fully set and forget" style setup just yet.



Get out there and put people on Mr. Bones Wild Ride.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================