Automating Minecraft Server Updates with AWS Systems Manager

Posted January 2, 2025 by Trevor Roberts Jr ‐ 4 min read

"Dad! I can't connect to the Minecraft server! It's saying something about the version?" Things were going well with my daughter's Minecraft server until a game client update prevented connections to our older server: Dad to the rescue! Read on to see how I automated game server updates with AWS Systems Manager...

Introduction

In an earlier blog post, I shared how I deployed a Minecraft server for my daughter to play with her friends and I online. Well, a recent game client update required me to update the game server for her to continue playing. I researched how to update a Minecraft server without losing data, and devised a plan:

  1. Take a snapshot of the EC2 instance
  2. Transfer the latest game server JAR to the EC2 instance
  3. Restart the game server

Easy, right? Well, there was some trial and error along the way including mistakenly chown-ing the saved data to the root user and crashing the server. 😅 However, I persevered, and the server eventually started with all the save data in place. I resolved right then and there to streamline this process.

The steps listed above seemed reasonable enough to automate. I knew of AWS Systems Manager and its ability to provide configuration management capabilties akin to Ansible, Puppet, and Chef, but I had not used it before: No time like the present to learn!

DISCLAIMER: If you consider adopting the workflow below, PLEASE make sure you have a good backup strategy for your Minecraft data files!

Automating with AWS Systems Manager

AWS Systems Manager has a collection of capabilities that "helps you centrally view, manage, and operate nodes at scale in AWS, on-premises, and multicloud environments" per AWS documentation. One of those capabilities is Automation, which you can use to create runbooks to run one or more actions to complete your goal. My runbook consisted of two actions:

  1. Create an AMI from (aws:createImage)
  2. Run a series of Linux commands to update the server (aws:runCommand)

FYI, the full source code for my examples below can be found on GitHub:

First, I defined a couple of input parameters so that I could specify which EC2 instance to update and the URL for the updated Minecraft Java server JAR:

	"parameters": {
		"InstanceId": {
			"type": "String",
			"description": "The ID of the instance to create an AMI for and update Minecraft."
		},
		"MinecraftJarUrl": {
			"type": "String",
			"description": "The URL of the Minecraft server.jar file."
		}
	}

Then, I wrote my first action to create the AMI image of the game server. This action will reboot the instance by default to ensure a consistent snapshot of the EBS volume:

	{
		"name": "CreateAMI",
		"action": "aws:createImage",
		"inputs": {
			"InstanceId": "{{ InstanceId }}",
			"ImageName": "minecraft-{{ InstanceId }}-backup-{{ global:DATE_TIME }}"
		}
	}

Finally, I wrote my second action to run my Linux commands to stop the game server, download the game server, and restart the game server. Note that two prerequisites for this script to work are: (1) the Linux user that manages the game is called minecraft and (2) your minecraft user is in the sudoers list with the NOPASSWD option:

	{
		"name": "UpdateMinecraftServer",
		"action": "aws:runCommand",
		"inputs": {
			"DocumentName": "AWS-RunShellScript",
			"InstanceIds": ["{{ InstanceId }}"],
			"Parameters": {
				"commands": [
				"sudo su - minecraft -c 'sudo systemctl stop minecraft'",
				"sudo su - minecraft -c 'curl -o /opt/minecraft/server/server.jar {{ MinecraftJarUrl }}'",
				"sudo su - minecraft -c 'sudo systemctl start minecraft'"
				]
			}
		}
	}

Now that I had my Automation runbook ready, I needed to deploy it...

Create the AWS Systems Manager Automation Runbook with Pulumi

The Pulumi program was fairly simple. It was a matter of storing the runbook text in a variable called documentContent and then deploying the AWS Systems Manager Automation document resource. At the end of the program, I export the name of the document that you can use with the AWS CLI to execute the runbook:

package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v6/go/aws/ssm"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		// Create an SSM Document for automation
		document, err := ssm.NewDocument(ctx, "UpdateMinecraftServer", &ssm.DocumentArgs{
			Content:      pulumi.String(documentContent),
			DocumentType: pulumi.String("Automation"),
		})
		if err != nil {
			return err
		}

		ctx.Export("DocumentName", document.Name)

		return nil
	})
}

Update the Minecraft Server

With the Automation runbook deployed, I can now execute it

aws ssm start-automation-execution \
    --document-name "UpdateMinecraftServer-9561939" \
    --parameters "InstanceId=i-123456789abcd,MinecraftJarUrl=https://piston-data.mojang.com/v1/objects/4707d00eb834b446575d89a61a11b5d548d8c001/server.jar"

Wrapping Things Up...

In this blog post, we discussed how to update a Minecraft server using an AWS Systems Manager Automation runbook. Further, we discussed how to automate the creation of that runbook in AWS with Pulumi.

If you found this article useful, let me know on BlueSky or on LinkedIn!