Introduction


My eldest daughter, plays with her friends a lot with the Minecraft Pocket Edition (PE). The PE Edition, really limits it to WiiU, xbox or ipad. This is the most connivent gaming version for them as they all have iPads.

Occasionally the world they are all playing on gets corrupted and she looses all the work they have done. There is ways to recover it, but its rather time consuming.

So thought I would look into making a server for them. This means we have more control over the backup process. I am not a GCP expert, but this was a great little process to get familiar with some of the functionality that comes with GCP.

Create a new Project


Navigate to Google Cloud Console

In the left side, there will be a drop down, and you can navigate here to Create a new project.

GCP Project

Google Cloud Console — Create New ProjectI named this project Minecraft.

The ProjectID that it generates is important for a future step, so you can copy and paste that to a notepad, or write it down.

On the left side there will be 3 horizontal lines, which we will refer to as the GCP Console, its the quick navigation to all the googles functionality.

GCP Project - Menu

Create the VM (Virtual Machine)


In the GCP console, click Compute Engine > VM Instances

Click create instance

GCP VM Instances

We want to the below options to be input: VM Configuration

Under Management, security, disks, networking, sole tenancy.

Network Security and Disks

Click first on Disks Click Add new Disk

We want to the below options to be input: Disk Configuration

Click Done Click now on Networking

We want to the below options to be input: Networking

Click Done Click Create

Setup the firewall


In the GCP console, Click on VPC Network > Firewall rules

Click on create firewall rule Firewall

We want to the below options to be input: Firewall Configuration

Click Create

Setup the VM


This disk is attached to the compute instance, but its not mounted.

Click on SSH to pop out a terminal and connect to your compute instance Create a directory that will become the mount point for the disk

sudo mkdir -p /home/minecraft

Then we need to format the disk run. The disk name may vary

fdisk -ls

in my case it was /dev/sda1

sudo mkfs.ext4 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/sda1

To mount the disk run the following

sudo mount -o discard,defaults /dev/sda1 /home/minecraft

Update the OS repositories on the VM, runing the below

sudo apt-get update && sudo apt-get upgrade && sudo apt-get dist-upgrade

now install unzip, wget, screen, htop, headless JRE

sudo apt-get install -y default-jre-headless
sudo apt-get install zip unzip
sudo apt-get install wget
sudo apt-get install screen
sudo apt-get install htop

Now lets install the bedrock server (which is specific for Pocket Edition)

cd /home/minecraft
sudo mkdir downloads
sudo wget -O downloads/version.html https://minecraft.net/en-us/download/server/bedrock/
sudo DownloadURL=$(grep -o 'https://minecraft.azureedge.net/bin-linux/[^"]*' downloads/version.html)
sudo DownloadFile=$(echo "$DownloadURL"| sed 's#.*/##')
sudo wget -O "downloads/$DownloadFile""$DownloadURL"
sudo unzip -o "downloads/$DownloadFile"

Run the server

sudo LD_LIBRARY_PATH=. ./bedrock_server

Create Backups


In the GCP console, Click on Compute Engine > VM Instances

We already have the mc-server created, so click on SSH We want to create a global unique bucket name

export YOUR_BUCKET_NAME=<Enter your bucket name here>
gsutil mb gs://$YOUR_BUCKET_NAME-minecraft-backup

Now we want to create a backup shell script.

cd /home/minecraft
sudo nano /home/minecraft/backup.sh

The below code will enable you to save the world, to your backup bucket

#!/bin/bash
'/save-all\n/save-off\n'
/usr/bin/gsutil -m cp -R /home/minecraft/worlds/* gs://${YOUR_BUCKET_NAME}-minecraft-backup/world
'/save-on\n'
/usr/bin/gsutil -m cp -R /home/minecraft/server.properties gs://${YOUR_BUCKET_NAME}-minecraft-backup/config/
/usr/bin/gsutil -m cp -R /home/minecraft/permissions.json gs://${YOUR_BUCKET_NAME}-minecraft-backup/config/
/usr/bin/gsutil -m cp -R /home/minecraft/whitelist.json gs://${YOUR_BUCKET_NAME}-minecraft-backup/config/
/usr/bin/gsutil -m cp -R /home/minecraft/valid_known_packs.json gs://${YOUR_BUCKET_NAME}-minecraft-backup/config/
/usr/bin/gsutil -m cp -R /home/minecraft/*.sh gs://${YOUR_BUCKET_NAME}-minecraft-backup/config/

Press Ctrl O, then Enter to Save, then Ctrl X to exit

We can then allow the script to execute

sudo chmod 755 /home/minecraft/backup.sh

We can test the script is working by running

. /home/minecraft/backup.sh

Then verify it in the Storage by navigating here https://console.cloud.google.com/storage/browser

Some other utility scripts I created are here;

#!/bin/bash
gsutil -m cp -R "gs://${YOUR_BUCKET_NAME}-minecraft-backup/config/*""/home/minecraft"
gsutil -m cp -R "gs://${YOUR_BUCKET_NAME}-minecraft-backup/worlds/*""/home/minecraft/worlds/"
# Change directory to server directory
sudo cd /home/minecraft

# Retrieve latest version of Minecraft Bedrock dedicated server
echo "Checking for the latest version of Minecraft Bedrock server ..."

# Test internet connectivity first
wget --quiet http://www.minecraft.net/ -O /dev/null
if [ "$?" != 0 ]; then
    echo "Unable to connect to update website (internet connection may be down).  Skipping update ..."
else
    # Download server index.html to check latest version
    sudo wget -O downloads/version.html https://minecraft.net/en-us/download/server/bedrock/
    sudo DownloadURL=$(grep -o 'https://minecraft.azureedge.net/bin-linux/[^"]*' downloads/version.html)
    sudo DownloadFile=$(echo "$DownloadURL" | sed 's#.*/##')

    # Download latest version of Minecraft Bedrock dedicated server if a new one is available
    if [ -f "downloads/$DownloadFile" ]
    then
        echo "Minecraft Bedrock server is up to date..."
    else
        echo "New version $DownloadFile is available.  Updating Minecraft Bedrock server ..."
        sudo wget -O "downloads/$DownloadFile" "$DownloadURL"
        sudo unzip -o "downloads/$DownloadFile" -x "*server.properties*" "*permissions.json*" "*whitelist.json*" "*valid_known_packs.json*"
    fi
fi

Start up scripts on server


Click on mc-server Click edit

Custom metadata add a new key/value pair

Key: startup-script

Value:

#!/bin/bash 

# Minecraft Bedrock server startup script using screen
sudo -i
sudo mount /dev/sda1 /home/minecraft

# Check if server is already started
if screen -list | grep -q "servername"; then
    echo "Server is already started!  Press screen -r servername to open it"
    exit 1
fi

# Change directory to server directory
cd /home/minecraft

# Retrieve latest version of Minecraft Bedrock dedicated server
echo "Checking for the latest version of Minecraft Bedrock server ..."

# Test internet connectivity first
wget --quiet http://www.minecraft.net/ -O /dev/null
if [ "$?" != 0 ]; then
    echo "Unable to connect to update website (internet connection may be down).  Skipping update ..."
else
    # Download server index.html to check latest version
    wget -O downloads/version.html https://minecraft.net/en-us/download/server/bedrock/
    DownloadURL=$(grep -o 'https://minecraft.azureedge.net/bin-linux/[^"]*' downloads/version.html)
    DownloadFile=$(echo "$DownloadURL" | sed 's#.*/##')

    # Download latest version of Minecraft Bedrock dedicated server if a new one is available
    if [ -f "downloads/$DownloadFile" ]
    then
        echo "Minecraft Bedrock server is up to date..."
    else
        echo "New version $DownloadFile is available.  Updating Minecraft Bedrock server ..."
        wget -O "downloads/$DownloadFile" "$DownloadURL"
        unzip -o "downloads/$DownloadFile" -x "*server.properties*" "*permissions.json*" "*whitelist.json*" "*valid_known_packs.json*"
    fi
fi

echo "Starting Minecraft server.  To view window type screen -r servername"
echo "To minimize the window and let the server run in the background, press Ctrl+A then Ctrl+D"

screen -dmS servername /bin/bash -c "LD_LIBRARY_PATH=. ./bedrock_server"

Key: shutdown-script

Value:

#!/bin/bash
# Minecraft Server stop script - primarily called by minecraft service but can be ran manually

sudo -i
/home/minecraft/backup.sh

screen -Rd servername -X stuff "stop$(printf '\r')"

screen -S servername -X quit

Click Save

Create Auto Start/Shutdown Instance


In the GCP console, Click on Cloud Scheduler

Click on Create Job Cloud Scheduler

For my server, I want it to start at 2pm, and close by 10pm.

We want to the below options to be input: Start Server Configuration

Stop Server Configuration

In the GCP console, Click on Cloud Functions Click on Create Functions Create Functions

We want to the below options to be input: Functions Configuration

Code:

from googleapiclient import discovery

def start_server_pubsub(event, context):
   
    service = discovery.build('compute', 'v1')
    print('VM Instance starting')

    # Project ID for this request.
    project = 'minecraft-xxxxxx' 

    # The name of the zone for this request.
    zone = 'australia-southeast1-a'  

    # Name of the instance resource to start.
    instance = 'mc-server'

    request = service.instances().start(project=project, zone=zone, instance=instance)
    response = request.execute()

    print('VM Instance started')

Click on Create Functions Cloud Functions

We want to the below options to be input: Cloud Functions Configuration

Code:

from googleapiclient import discovery

def stop_server_pubsub(event, context):

    service = discovery.build('compute', 'v1')
    print('VM Instance stopping')

    # Project ID for this request.
    project = 'minecraft-xxxxxx' 

    # The name of the zone for this request.
    zone = 'australia-southeast1-a'  

    # Name of the instance resource to start.
    instance = 'mc-server'

    request = service.instances().stop(project=project, zone=zone, instance=instance)
    response = request.execute()

    print('VM Instance stopped')

There is likely lots of improvements that can be made on this, so if you do have any recommendations let me know.