This project deploys a Minecraft server infrastructure on AWS where the compute (EC2) is ephemeral and on-demand, while the state is persisted in S3.
- Terraform: Manages persistent resources (S3, DynamoDB, Lambda, IAM, Security Groups).
- Lambda: Orchestrates the server lifecycle (Start/Stop/Monitor).
- EC2: Ephemeral instances that run the Minecraft server using Docker.
- S3: Stores world data, configuration, and scripts.
- DynamoDB: Tracks the state of the worlds (Running/Stopped, IP address).
-
Deploy Terraform:
cd terraform terraform init terraform applyNote the
function_urloutput. -
Prepare S3: The
server_lifecycle.shscript is automatically uploaded tos3://<bucket>/scripts/.To create a new world (e.g., "survival"):
- Create a folder
worlds/survival/in the S3 bucket. - (Optional) Upload a
compose.yamltoworlds/survival/compose.yaml. If not provided, a default one will be created on first launch.
- Create a folder
Start Server:
curl -X POST "https://<function_url>/" \
-H "Content-Type: application/json" \
-d '{"action": "start", "world": "survival"}'The repo includes a small helper that reads Terraform outputs automatically, so you don't need to hard-code the Function URL or bucket names.
./mcctl.sh start survival
./mcctl.sh status survival
./mcctl.sh stop survivalYou can also keep using wrappers:
./start.sh survival
./status.sh survival
./stop.sh survivalIf the server is running and you need to inspect the instance, you can open a Session Manager shell via SSM:
./mcctl.sh connect survivalRequirements:
- Your AWS CLI identity must have permissions for
ssm:StartSession(and related actions). - The instance role already includes
AmazonSSMManagedInstanceCore.
-
data_bucket_name/config_bucket_name(latest state)scripts/server_lifecycle.shworlds/<world>/compose.yamlworlds/<world>/data.tar
-
snapshot_bucket_name(history)worlds/<world>/snapshots/<UTC>.tar
Snapshots are deleted automatically by S3 Lifecycle after snapshot_retention_days (default: 3 days).
If you want to snapshot without stopping the server:
./mcctl.sh snapshot survivalThis creates:
s3://<snapshot_bucket>/worlds/survival/snapshots/<UTC>.tar(history)s3://<data_bucket>/worlds/survival/data.tar(overwrites latest)
Stop Server:
curl -X POST "https://<function_url>/" \
-H "Content-Type: application/json" \
-d '{"action": "stop", "world": "survival"}'Check Status:
curl "https://<function_url>/?action=status&world=survival"An EventBridge rule triggers the Lambda every 10 minutes to check for idle servers (0 players). If a server is idle for more than 30 minutes, it will be automatically stopped and terminated.
- Instance Type: Change
instance_typeinterraform/variables.tf. - Minecraft Version: Edit the
compose.yamlin S3 or the default generation logic inscripts/server_lifecycle.sh.