My friends and I wanted a Minecraft server that only we could contribute to, but didn't want to pay the steep price for Mojang's solution, and also wanted control of the server so that modifications, our own backups, and more would be easily configured.
The main problem was that none of us had a PC we could guarantee would be turned on. So the solution was a Linux EC2 spot instance hosted on AWS. To save money, the machine would turn itself off automatically if no player had connected in over 10 minutes, and would need one of us to request to turn it on again.
To turn it on, we pressed a button on a static webpage hosted on Amplify. This then triggered a Lambda function, through API Gateway:
import boto3 region = 'ca-central-1' instances = ['your_ec2_instance_id'] ec2 = boto3.client('ec2', region_name=region) # brings user to page with server status and its dynamic IP address for this launch def rgo(code, ip): response = {} response["statusCode"] = 303 response["headers"] = {'Location': "https://your_amplify_url.amplifyapp.com/ip.html?ip="+str(ip)+"&code="+str(code)} response["body"] = "{}" return response def lambda_handler(event, context): instance = boto3.resource('ec2').Instance(instances[0]) st = instance.state["Name"] # starts server if stopped. if another user has started it, show this user its IP address if st=="stopped": ni = ec2.start_instances(InstanceIds=instances) instance.wait_until_running() instance = boto3.resource('ec2').Instance(instances[0]) elif st=="pending": instance.wait_until_running() instance = boto3.resource('ec2').Instance(instances[0]) if st=="running" or st=="pending" or st=="stopped": public_ip = instance.public_ip_address return rgo("GS", public_ip) return rgo("NA", "null")
This redirected us to another static page that displayed the current IP address of the server (a static IP costs money on AWS!) From there, we'd have everything we needed to start playing.
Once we'd had our fun, we would log out and forget about it. The machine had a chron job set up to check if any players were active every 10 minutes. If it checked twice in a row and no players were online, it would trigger the following Lambda:
import boto3 import rcon region = 'ca-central-1' instances = ['your_ec2_instance_id'] ec2 = boto3.client('ec2', region_name=region) def lambda_handler(event, context): instance = boto3.resource('ec2').Instance(instances[0]) # first stop Minecraft server so it saves correctly with rcon.Client(str(instance.public_ip_address), ((((minecraft_port)))), passwd='your_rcon_password') as client: response = client.run('stop') # now shut down EC2 instance ni = ec2.stop_instances(InstanceIds=instances)