-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial revision: cloudformation template with UserData for calling i…
…n further setup from this repository.
- Loading branch information
Showing
4 changed files
with
297 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
AWSTemplateFormatVersion: '2010-09-09' | ||
Description: AWS CloudFormation Template for a hosted game server | ||
|
||
Parameters: | ||
ServerPortNumberStart: | ||
Type: Number | ||
Description: First TCP port for game server traffic | ||
|
||
ServerPortNumberEnd: | ||
Type: Number | ||
Description: Last TCP port for game server traffic | ||
|
||
SetupCommand: | ||
Type: String | ||
Description: Defines the setup invocation. Permits code execution. Direct secrets prohibited. | ||
|
||
ExistingVolumeId: | ||
Type: String | ||
Description: ID of an existing EBS volume to attach. Leave empty to create a new volume. | ||
Default: "" | ||
|
||
Conditions: | ||
CreateNewVolume: !Equals [ !Ref ExistingVolumeId, "" ] | ||
|
||
Resources: | ||
ServerInstance: | ||
Type: AWS::EC2::Instance | ||
Properties: | ||
InstanceType: t3.large # 8GB, 2vcpu, 0.1056 USD/hour | ||
ImageId: ami-02765a2a1f276edff # Amazon Linux 2 AMI (HVM) - Kernel 5.10, SSD Volume Type, 64-bit (x86) / https://ap-southeast-4.console.aws.amazon.com/ec2/home?region=ap-southeast-4#AMICatalog: | ||
KeyName: tim_ssh_to_game_server # EC2 / key pairs | ||
SecurityGroupIds: | ||
- !Ref ServerSecurityGroup | ||
UserData: | ||
Fn::Base64: !Sub | | ||
#!/bin/bash | ||
|
||
# Australia/Melbourne should be all that anyone will ever need... right? | ||
timedatectl set-timezone Australia/Melbourne | ||
|
||
echo "!! Check whether the attached volume is formatted.." | ||
REAL_DEVICE=$(sudo readlink -f /dev/sdf) | ||
echo "/dev/sdf maps to $REAL_DEVICE by symlink check" | ||
if [ "$(sudo file -s $REAL_DEVICE | awk '{print $2}')" == "data" ]; then | ||
echo "$REAL_DEVICE is not formatted, formatting as ext4..." | ||
sudo mkfs -t ext4 $REAL_DEVICE | ||
else | ||
echo "$REAL_DEVICE is already formatted." | ||
fi | ||
|
||
echo "!! Mount the attached volume to /mnt/persist" | ||
sudo mkdir -p /mnt/persist | ||
sudo mount $REAL_DEVICE /mnt/persist | ||
echo "$REAL_DEVICE /mnt/persist ext4 defaults,nofail 0 2" | sudo tee -a /etc/fstab > /dev/null | ||
|
||
echo "!! Clone and use AWS-Games" | ||
yum install -y git | ||
cd /home/ec2-user | ||
git clone https://github.com/TSheahan/AWS-Games.git | ||
chown -R ec2-user:ec2-user AWS-Games | ||
cd AWS-Games | ||
|
||
echo "!! Execute SetupCommand" | ||
# as root, invoke the setup command, expecting it to handle system & user setup tasks | ||
# use due caution for code execution capability | ||
${SetupCommand} | ||
|
||
|
||
NewVolume: | ||
Type: AWS::EC2::Volume | ||
Condition: CreateNewVolume | ||
Properties: | ||
Size: 10 # Adjust as needed for world files - 1.13GB after 1 months minecraft play | ||
VolumeType: gp3 | ||
AvailabilityZone: !GetAtt ServerInstance.AvailabilityZone | ||
Tags: | ||
- Key: "Purpose" | ||
Value: "GameServerPersistentFiles" | ||
DeletionPolicy: Retain | ||
|
||
PersistentVolumeAttachment: | ||
Type: AWS::EC2::VolumeAttachment | ||
Properties: | ||
InstanceId: !Ref ServerInstance | ||
VolumeId: !If [CreateNewVolume, !Ref NewVolume, !Ref ExistingVolumeId] | ||
Device: /dev/sdf | ||
|
||
ServerEIP: | ||
Type: AWS::EC2::EIP | ||
Properties: | ||
InstanceId: !Ref ServerInstance | ||
|
||
ServerSecurityGroup: | ||
Type: AWS::EC2::SecurityGroup | ||
Properties: | ||
GroupDescription: Allow SSH and game traffic | ||
SecurityGroupIngress: | ||
- IpProtocol: tcp | ||
FromPort: 22 | ||
ToPort: 22 | ||
CidrIp: 0.0.0.0/0 | ||
- IpProtocol: tcp | ||
FromPort: !Ref ServerPortNumberStart # Destination port range start | ||
ToPort: !Ref ServerPortNumberEnd # Destination port range end | ||
CidrIp: 0.0.0.0/0 | ||
|
||
Outputs: | ||
ServerIP: | ||
Description: IP Address of the server | ||
Value: !Ref ServerEIP | ||
ServerPortStart: | ||
Description: First TCP port used for the server | ||
Value: !Ref ServerPortNumberStart | ||
ServerPortEnd: | ||
Description: Last TCP port used for the server | ||
Value: !Ref ServerPortNumberEnd | ||
SetupCommand: | ||
Description: Displays the SetupCommand which was used at instance instantiation | ||
Value: !Ref SetupCommand | ||
NewVolumeId: | ||
Description: The ID of the newly created EBS volume (if created). | ||
Value: !If [ CreateNewVolume, !Ref NewVolume, "" ] | ||
ExistingVolumeId: | ||
Description: Mirrors the input for optional existing EBS volume ID. | ||
Value: !Ref ExistingVolumeId |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
#!/bin/env bash | ||
|
||
cat <<'EOF' | ||
====================================================================== | ||
This script sets up a Minecraft server with the following configurations: | ||
- Server Folder: The directory where the server files are stored. | ||
- Server Version: The version of the Minecraft server to be deployed. | ||
- used to compose jar filename upon download | ||
- JAR URL: The URL from which the Minecraft server JAR file is downloaded. | ||
Usage: | ||
minecraft/setup.sh --server-folder=<path> --server-version=<version> --jar-url=<url> | ||
The script is designed to be invoked as root via the UserData script of a | ||
linux game server instance (defined in a CloudFormation template). | ||
It expects to be executed from the repository root folder. | ||
The SetupCommand parameter must include the needed arguments. | ||
====================================================================== | ||
EOF | ||
|
||
if [ ! -d ../AWS-Games ]; then | ||
echo "setup must run from repository root" | ||
exit 1 | ||
fi | ||
|
||
# Initialize variables to hold the values of the arguments | ||
serverFolder="" | ||
serverVersion="" | ||
jarUrl="" | ||
|
||
# Error function to display an error message and exit | ||
error() { | ||
echo "Error: $1" >&2 | ||
echo "Usage: $0 --server-folder=<path> --server-version=<version> --jar-url=<url>" >&2 | ||
exit 1 | ||
} | ||
|
||
# Loop through arguments and process them | ||
for arg in "$@" | ||
do | ||
case $arg in | ||
--server-folder=*) | ||
serverFolder="${arg#*=}" | ||
;; | ||
--server-version=*) | ||
serverVersion="${arg#*=}" | ||
;; | ||
--jar-url=*) | ||
jarUrl="${arg#*=}" | ||
;; | ||
*) | ||
# Unknown option | ||
error "Unknown argument ${arg}" | ||
;; | ||
esac | ||
done | ||
|
||
# Check if any of the required arguments are missing | ||
if [ -z "$serverFolder" ]; then | ||
error "server-folder argument is required" | ||
fi | ||
if [ -z "$serverVersion" ]; then | ||
error "server-version argument is required" | ||
fi | ||
if [ -z "$jarUrl" ]; then | ||
error "jar-url argument is required" | ||
fi | ||
|
||
# If all arguments are provided, proceed with the rest of the script | ||
echo "Server Folder: $serverFolder" | ||
echo "Server Version: $serverVersion" | ||
echo "JAR URL: $jarUrl" | ||
|
||
|
||
echo "!! Install JDK" | ||
yum update -y | ||
yum install -y java-17-amazon-corretto-devel | ||
|
||
echo "!! Check Java version" | ||
java -version | ||
|
||
echo "!! Ensure /mnt/persist/minecraft exists and is owned by ec2-user" | ||
mkdir -p /mnt/persist/minecraft | ||
chown ec2-user:ec2-user /mnt/persist/minecraft | ||
|
||
echo "!! Ensure the server folder exists and is owned by ec2-user" | ||
mkdir -p "/mnt/persist/minecraft/${serverFolder}" | ||
chown ec2-user:ec2-user "/mnt/persist/minecraft/${serverFolder}" | ||
|
||
echo "!! Write /etc/systemd/system/minecraft-server.service" | ||
cat << EOF > /etc/systemd/system/minecraft-server.service | ||
[Unit] | ||
Description=Minecraft Server | ||
After=network.target | ||
[Service] | ||
User=ec2-user | ||
WorkingDirectory=/mnt/persist/minecraft/${serverFolder} | ||
ExecStart=/mnt/persist/minecraft/${serverFolder}/start-minecraft.sh | ||
ExecStop=/mnt/persist/minecraft/${serverFolder}/stop-minecraft.sh | ||
TimeoutStopSec=60 | ||
[Install] | ||
WantedBy=multi-user.target | ||
EOF | ||
|
||
startScriptPath="/mnt/persist/minecraft/${serverFolder}/start-minecraft.sh" | ||
echo "!! Install the start-minecraft.sh wrapper script at $startScriptPath" | ||
cp minecraft/start-minecraft.sh "$startScriptPath" | ||
# Make the script executable | ||
chmod +x "$startScriptPath" | ||
# Ensure the script is owned by ec2-user | ||
chown ec2-user:ec2-user "$startScriptPath" | ||
|
||
stopScriptPath="/mnt/persist/minecraft/${serverFolder}/stop-minecraft.sh" | ||
echo "!! Install the stop-minecraft.sh wrapper script at $stopScriptPath" | ||
cp minecraft/stop-minecraft.sh "$stopScriptPath" | ||
# Make the script executable | ||
chmod +x "$stopScriptPath" | ||
# Ensure the script is owned by ec2-user | ||
chown ec2-user:ec2-user "$stopScriptPath" | ||
|
||
jarPath="/home/ec2-user/minecraft_server_${serverVersion}.jar" | ||
echo "!! Download Minecraft server JAR to $jarPath" | ||
sudo -u ec2-user wget -O "$jarPath" "$jarUrl" | ||
|
||
symlinkPath="/mnt/persist/minecraft/${serverFolder}/minecraft_server.jar" | ||
echo "!! Symlink the jar to $symlinkPath" | ||
sudo -u ec2-user ln -s "$jarPath" "$symlinkPath" | ||
|
||
echo "!! reload systemd" | ||
# Reload systemd to recognize the new service and enable it to start on boot | ||
systemctl daemon-reload | ||
systemctl enable minecraft-server.service | ||
|
||
# echo "!! start minecraft-server" | ||
# systemctl start minecraft-server.service | ||
# ? consider rebooting here.. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#!/bin/bash | ||
|
||
if [ ! -e server.properties ]; then | ||
echo "server.properties not found, aborting." | ||
exit 1 | ||
fi | ||
|
||
# Flag indicating if the installed version of screen is < 4.06 | ||
# that does not support the -Logfile argument. | ||
# Set legacyScreen=1 for true, and legacyScreen=0 for false. | ||
legacyScreen=1 | ||
|
||
logFile="console_$(date +"%Y-%m-%d_%H-%M-%S").log" | ||
# TODO: | ||
# - investigate how closely this mirrors the minecraft logs in /logs | ||
# - verify the stop workflow vs instance shutdown - does the minecraft server stop properly? | ||
|
||
echo "logfile is $logFile" | ||
|
||
if [ "$legacyScreen" -eq 1 ]; then | ||
cat << EOF >/tmp/screenrc.$$ | ||
logfile $logFile | ||
EOF | ||
/usr/bin/screen -DmS minecraft -L -c /tmp/screenrc.$$ java -Xmx4092M -Xms4092M -jar minecraft_server.jar | ||
rm /tmp/screenrc.$$ | ||
else | ||
/usr/bin/screen -DmS minecraft -L -Logfile "$logFile" java -Xmx4092M -Xms4092M -jar minecraft_server.jar | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/usr/bin/screen -S minecraft -p 0 -X stuff "/say systemd is shutting down this service.^M" | ||
sleep 5 | ||
/usr/bin/screen -S minecraft -p 0 -X stuff "/stop^M" |