How to Run a Minecraft Server on AWS For Less Than 3 USD a Month

Sat, 07 Aug 2021

#aws #serverless #minecraft #tutorial

During the first weeks of the COVID-19 pandemic, back in April 2020 my son ask me to build a Minecraft server in order to play on the same world with his school friend. After checking some available services (yeah not so expensive finally), I have chosen to build a server on a EC2 instance. This article will explain you how to optimize the cost 😜, based on the usage!

Some Tools Used in the Article

AWS

I want to rely only on AWS services as I want to increase my knowledge on this big cloud offering. There is always one service you don't know ! In this particular example I will use the following services:

Minecraft

Minecraft is a popular sandbox video-game. In this case I will focus on the Minecraft Java Edition, because the server version is running well on Linux server, and my son is running a laptop on Debian.

Global Architecture of the Solution

The first month operating the server, I noticed that my son is using it a couple of hours each day, and then the server was idle. It's built on a EC2 t2.small with a 8 GB disk so I have a monthly cost of about **18 US) and I know that it's not used 100% of the time. The global idea is to start the server only when my son is using it, but he doesn't have access to my AWS Console so I need to find a sweet solution!

Here is the various blocks used:

And that's it. My son is using it this way:

Let's Build it Together

Build the EC2 Instance

This is the initial part, you must create a new EC2 instance. From the EC2 dashboard, click on Launch Instance and choose the Amazon Linux 2 AMI with the x86 option.

minecraft1.png

Next you must choose the Instance Type. I recommend you the t2.small for Minecraft. You will able to change it after the creation.

minecraft2.png

Click on Next: Configure Instance Details to continue the configuration. Keep the default settings, and the default size for the disk (8 GB) as it's enough.

For the tag screen I generally provide a Name (it's then displayed on EC2 instance list) and a costcenter (I use it for cost management later).

minecraft4.png

For the Security Group, it the equivalent of a firewall on EC2 and you must configure which port will be accessible from internet on your server. I add SSH port and the Minecraft port (25565) like you see on the following screen:

minecraft5.png

Then to start the instance you must select or create a key pair. It's mandatory and allow then to connect remotely to your EC2 instance. In my case I am using an existing key pair but if you create a new key don't forget to download on your laptop the private key file.

minecraft6.png

Yes my key is named caroline. Why not?

Then you must connect your instance via SSH, I recommend this guide if you need help. Basically you must run this kind of command:

ssh -i my_private_key.pem ec2-user@public-ipv4

The public-ipv4 is available in the instance list:

minecraft7.png

You first need java. As newer build of minecraft (since 1.17) are running only on Java 17, I recommend to use Corretto (the Amazon Java version):

sudo rpm --import https://yum.corretto.aws/corretto.key
sudo curl -L -o /etc/yum.repos.d/corretto.repo https://yum.corretto.aws/corretto.repo
sudo yum install -y java-17-amazon-corretto-devel.x86_64
java --version

You must have something like:

openjdk 17.0.1 2021-10-19 LTS
OpenJDK Runtime Environment Corretto-17.0.1.12.1 (build 17.0.1+12-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.1.12.1 (build 17.0.1+12-LTS, mixed mode, sharing)

Thanks @mudhen459 for the research on this java issue ;)

And I want a dedicated user:

sudo adduser minecraft

To install Minecraft you can rely on the Minecraft server page here.

For example for the version 1.17.1 I can run the following:

sudo su
mkdir /opt/minecraft/
mkdir /opt/minecraft/server/
cd /opt/minecraft/server
wget https://launcher.mojang.com/v1/objects/a16d67e5807f57fc4e550299cf20226194497dc2/server.jar
sudo chown -R minecraft:minecraft /opt/minecraft/

⚠️ Warning regarding Java version: It seems that starting with Minecraft 1.17, it require now a Java JRE 16 (instead of Java JRE 8).This site is giving you links to download older Minecraft versions if needed.

Java version

It seems that starting with Minecraft 1.17, it require now a Java JRE 16 (instead of Java JRE 8).This site is giving you links to download older Minecraft versions if needed.

Exception in thread "main" java.lang.UnsupportedClassVersionError: net/minecraft/server/Main has been compiled by a more recent version of the Java Runtime (class file version 60.0), this version of the Java Runtime only recognizes class file versions up to 52.0

I have created a little service to avoid start manually the server. I want the Minecraft process to start as soon as I start the server.

To do that I have created a file under /etc/systemd/system/minecraft.service with the following content:

[Unit]
Description=Minecraft Server
After=network.target

[Service]
User=minecraft
Nice=5
KillMode=none
SuccessExitStatus=0 1
InaccessibleDirectories=/root /sys /srv /media -/lost+found
NoNewPrivileges=true
WorkingDirectory=/opt/minecraft/server
ReadWriteDirectories=/opt/minecraft/server
ExecStart=/usr/bin/java -Xmx1024M -Xms1024M -jar server.jar nogui
ExecStop=/opt/minecraft/tools/mcrcon/mcrcon -H 127.0.0.1 -P 25575 -p strong-password stop

[Install]
WantedBy=multi-user.target

Then advise the new service by the following:

chmod 664 /etc/systemd/system/minecraft.service
systemctl daemon-reload

More information on systemd here.

Success

Now if you restart the EC2 instance a Minecraft server must be available! You can check ✅ this first step!

Build the Start Scenario

Let's first create our Lambda function. Go into Lambda, and click on Create function to build a new one. Name it mc_start and use a Node.js 14.x or more runtime.

Then you must have this type of screen:

minecraft8.png

Replace the content of index.js file with the following:

const AWS = require("aws-sdk");
var ec2 = new AWS.EC2();

exports.handler = async (event) => {
  try {
    var result;
    var params = {
      InstanceIds: [process.env.INSTANCE_ID],
    };
    var data = await ec2.startInstances(params).promise();
    result = "instance started"

    const response = {
      statusCode: 200,
      body: result,
    };
    return response;
  } catch (error) {
    console.error(error);
    const response = {
      statusCode: 500,
      body: "error during script",
    };
    return response;
  }
};

In Configuration, set the following:

minecraft9.png

In Simple Email Service, it's time to create a new Rule Set in the Email Receiving section:

minecraft10.png

Click on Create rule inside default-rule-set. Take note that the Email Receiving feature is only available today in 3 regions: us-east-1us-west-2 and eu-west-1 (source here).

If SES is receiving an email on this particular identity: