Dedicated game server and AWS Instance Scheduler
Tags: aws, awsinstancescheduler, funproject
Published: 2023-12-20 11:17:01

Recently I've started playing a game ([Satisfactory](https://www.satisfactorygame.com/), for those who want to know) with my two kids. To make it easier to play together, I've set up a dedicated server on an EC2 instance so the game is also available when the host is not available.

To keep the costs down a bit, I was looking for a way to shut down the instance during the hours we wouldn't be playing anyway. That's when I came across [Instance Scheduler on AWS](https://aws.amazon.com/solutions/implementations/instance-scheduler-on-aws/).

> The Instance Scheduler on AWS solution automates the starting and stopping of Amazon Elastic Compute Cloud (Amazon EC2) and Amazon Relational Database Service (Amazon RDS) instances.  
> 
> This solution helps reduce operational costs by stopping resources that are not in use and starting resources when their capacity is needed. For example, a company can use Instance Scheduler on AWS in a production environment to automatically stop instances outside of business hours every day. If you leave all of your instances running at full utilization, this solution can result in up to 70% cost savings for those instances that are only necessary during regular business hours (weekly utilization reduced from 168 hours to 50 hours).  
> 
> Instance Scheduler on AWS leverages Amazon Web Services (AWS) resource tags and AWS Lambda to automatically stop and restart instances across multiple AWS Regions and accounts on a customer-defined schedule. This solution also allows you to use hibernation for stopped Amazon EC2 instances.
> 
> This solution can be deployed in a single account, or in a central account, managing multiple accounts. Since I'm using an AWS Organization, I've deployed the main stack in a hub account, and the remote stack in the account that hosts the dedicated server instance.  

To deploy Instance Scheduler (version 1.5.3 at the time of writing), go to the AWS CloudFormation console in your desired account and create a new stack using new resources. Paste the link to the [CloudFormation Instance Scheduler template](https://s3.amazonaws.com/solutions-reference/instance-scheduler-on-aws/latest/instance-scheduler-on-aws.template), as linked on the solution page, in the `Amazon S3 URL` field and click `Next`.

On the next page, you can configure the solution. Give the stack a meaningful name, and set the options you need. For mu configuration, I've set the default timezone to `Europe/Amsterdam`, set the option `This account` to `No` since I won't be hosting resources in the hub account, set the `Namespace`, and set `Use AWS Organizations` to `Yes`. When using AWS Organizations, provide the organization ID in the `Organization Id/Remote Account Ids` field, otherwise provide a comma separated list of account IDs you want to manage through this account. If you forget to provide a value for this, you will get an error on the `schedulereventbuspolicy` resource during deployment.

If you want to manage resources in other regions than where you're deploying the stack in, also make sure to enter those in the `Region(s)` field.

When you're done with this initial configuration, click on `Next`, review the settings on the `Configure stack options` page and click `Next` again.

Do a last review of the configuration, don't forget to tick the box to acknowledge that AWS CloudFormation might create IAM resources, and click on `Submit`.

The stack will create the resources for the solution, which takes a couple of minutes.

Once the resources have been deployed, we can create a schedule for the server.

The schedule is configured in DynamoDB. The CloudFormation stack created several DynamoDB tables. The schedules and periods used on the schedule are in a table names `InstanceScheduler-main-ConfigTable-XXXXXXXXXXXX`. 

I've created the following periods and schedule in the table.

Periods used:

_Workdays period_:

```json
{
  "type": {
    "S": "period"
  },
  "name": {
    "S": "satisfactory-workdays"
  },
  "begintime": {
    "S": "17:00"
  },
  "description": {
    "S": "Satisfactory Dedicated Server - workdays "
  },
  "endtime": {
    "S": "23:59"
  },
  "weekdays": {
    "SS": [
      "mon-thu"
    ]
  }
}
```

_Weekends period 'on'_:

```json
{
  "type": {
    "S": "period"
  },
  "name": {
    "S": "satisfactory-weekends-on"
  },
  "begintime": {
    "S": "12:00"
  },
  "description": {
    "S": "Satisfactory Dedicated Server - weekends"
  },
  "endtime": {
    "S": "23:59"
  },
  "weekdays": {
    "SS": [
      "fri-sun"
    ]
  }
}
```

_Weekends period 'off'_:

```json
{
  "type": {
    "S": "period"
  },
  "name": {
    "S": "satisfactory-weekends-off"
  },
  "begintime": {
    "S": "00:00"
  },
  "description": {
    "S": "Satisfactory Dedicated Server - weekends"
  },
  "endtime": {
    "S": "02:00"
  },
  "weekdays": {
    "SS": [
      "sat-sun"
    ]
  }
}
```

These periods turn the server on on weekdays between 17:00 and midnight, and for the weekends, turn it on on Fridays, Saturdays and Sundays at noon, until 02:00 on Saturdays and Sundays, and until midnight on Sundays, when combined into a schedule:

```json
{
  "type": {
    "S": "schedule"
  },
  "name": {
    "S": "satisfactory"
  },
  "description": {
    "S": "Schedule for Satisfactory Dedicated Server"
  },
  "periods": {
    "SS": [
      "satisfactory-weekends-off",
      "satisfactory-weekends-on",
      "satisfactory-workdays"
    ]
  }
}
```

Once that's done, switch over to the account and region the dedicated server is in, and deploy the [CloudFormation instance schedule remote template](https://s3.amazonaws.com/solutions-reference/instance-scheduler-on-aws/latest/instance-scheduler-on-aws-remote.template) in CloudFormation.

In the stack details, specify the same `Namespace` used in the stack in the hub account, provide the account ID of the hub account in `Hub Account ID` and set `Use AWS Organizations` to `Yes` because that's what I'm using in the hub account.

When that stack has deployed, the server needs a tag so Instance Scheduler knows to manage this instance, and what schedule to use.
The tag we need to set on the EC2 instance is `Schedule`, with the value of the schedule we created, `satisfactory`.

And that's that!

An alternative AWS provides is [Resource Scheduler](https://docs.aws.amazon.com/solutions/latest/instance-scheduler-on-aws/related-resources.html). With Resource Scheduler, you can 'only' schedule EC2 instances, and they are not checked for the desired state, but might fit your use case better. I chose for Instance Scheduler to see how it works, and because I like solutions that can be managed from a hub account.

For this post, I've written about a personal dedicated game server, a fun project. But in environments where you don't need your resources running all day (like test and dev) or even in production environments where you need to have an instance available only at specific times, this can be helpful to reduce costs.