Create a Minecraft server with only an Nginx server!

I’ve recently acquired my very first server, a Dell R620. Because my brother has lots of fun playing Minecraft with his friends I thought I could host a Minecraft server in my brand new server for the sake of learning and, of course, his hapiness. But starting from scratch and with zero knowledge I already knew it wouldn’t be easy. Either way, I like struggling to solve problems and do it with the best approach I can think of, so I went all in!

Being 100% honest here, I lied a bit. I’m not starting with zero knowledge with Nginx as I already host some simple static webpages -like this one- so let’s say I know, at least, the very basics of it. In this post I won’t be explaining how to set up a RAID, installing the Operating Systems remotely, creating the Virtual Machines etc… This is going to focus on setting up the Minecraft server and Nginx to make it playable from anywhere.

But first, I want to explain a little bit what I started with and what I had in my head… My server has XCP-ng installed, a Citrix XenServer based hypervisor™. It’s clean, simple and open source, exactly what I wanted! But that’s only the hypervisor, that means that I needed some kind of manager to be able to control all the VMs, that’s where Xen Orchestra comes into the game. With this incredibly handy software I can create, control and monitor all the virtual machines I will be creating in my server. The structure will be something like this:

  • XCP-ng
    • Xen Orchestra VM
    • Nginx proxy VM
    • Minecraft VM

Easy, right? Using Xen Orchestra I created two Virtual Machines with Debian 10, one hosting Nginx and the other one hosting the Minecraft server. Why Debian? Because it’s simple, lightweight, stable… and I love it! The Nginx proxy VM is going to be the only VM that will receive connections from the outside, for the sake of extra simplicity and security. That means that the Minecraft VM is only aware of the internal network.

Part 1: The Minecraft server

Once the VM in charge of hosting the Minecraft server was up and running, I had to install a Minecraft server. I decided to go for Spigot, the ‘high performance, no lag customized CraftBukkit Minecraft server’. For that, I used their BuildTools tool.

Their wiki is very clear and easy to follow, that’s why I won’t be covering this part here. Also, this gets updated quite often so at some point they might change how to build it and I will be receiving hundreds of emails complaining that my step by step tutorial does not work anymore… Following those steps you can get your Minecraft server running in less than 10 minutes! This server will be serving to port 25565 by default. But… how are we going to access this server from the outside? As I mentioned earlier, this VM has no access at all to expose the server!

Part 2: Nginx comes to save us

This is the part I’ve struggled to get to work for HOURS. A lot of information on the Internet, most of it very old, with outdated versions of Nginx that do not support certain features, with strange domain SRV records that they do not explain very well how to wire that up to get everything working easily.

After a lot of research, try and fail, I finally found some very interesting documentation that showcased something very similar to what I was trying to do.

Installing Nginx on the VM that has access to the Internet is the first step as we have to route the TCP traffic coming from the outside to another VM connected in the same internal network. To be able to achieve this you have to follow the next steps:

  1. Install Nginx: sudo apt install nginx
  2. Create the Nginx stream module: touch /etc/nginx/modules-available/minecraft.conf
  3. Edit the file according to the template:
    stream {
         server {
                 listen 25565; # Port of Minecraft server
                 proxy_pass minecraft;
         }
    
         upstream minecraft {
                 server 10.0.0.2:25565; # IP of the VM hosting Minecraft, port of Minecraft server.
         }
    }
    
  4. Generate the symlink to enable it: ln -s /etc/nginx/modules-available/minecraft.conf /etc/nginx/modules-enabled/minecraft.conf
  5. Restart Nginx: sudo service nginx restart

And voilà! As easy as that! I can’t believe it took me such long time to end up with this minuscule piece of code.