Skip to content

Commit ff71f60

Browse files
CoderCococlaude
andauthored
chore(terraform): anonymize tfvars examples and remove game_servers default (#39)
## Summary This PR removes hardcoded default game server configurations and makes the `game_servers` variable required, shifting to a more flexible example-driven approach. The example configuration is now generic and commented out, requiring users to explicitly define their own game servers. ## Key Changes - **Removed default game server definitions** from `variables.tf`: Deleted pre-configured examples for Palworld, Satisfactory, and FoundryVTT that were provided as defaults - **Made `game_servers` variable required**: Removed the `default` block, making this variable mandatory for all deployments - **Updated `terraform.tfvars.example`**: - Changed `hosted_zone_name` from `"codercoco.com"` to generic `"example.com"` - Replaced concrete game server examples with a single commented-out Palworld example - Added comprehensive documentation explaining the game server structure and how to add custom entries - Updated ACM certificate domain example to use `example.com` - **Updated variable descriptions**: - `hosted_zone_name`: Now explicitly states it must already exist and provides example format - `acm_certificate_domain`: Clarified default behavior when null - **Updated documentation** in `terraform.md` to reflect the new required variable approach ## Implementation Details The change encourages explicit configuration over implicit defaults, reducing the risk of users accidentally deploying unwanted services. Users must now copy the example configuration and customize it for their specific needs, making the deployment process more intentional and transparent. https://claude.ai/code/session_011XwGyddBHntiQYnmtgePVw Co-authored-by: Claude <noreply@anthropic.com>
1 parent 069c245 commit ff71f60

3 files changed

Lines changed: 77 additions & 165 deletions

File tree

docs/docs/components/terraform.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ step 3 of the [setup guide](/setup) for details.
3232
| `project_name` | `string` | `game-servers` | Prefix for named resources and the Secrets Manager paths. |
3333
| `vpc_cidr` | `string` | `10.0.0.0/16` | Parent CIDR; subnets are /24s within it. |
3434
| `game_servers` | `map(object)` || The single source of truth. Per-game: `image`, `cpu`, `memory`, `ports[]`, `environment[]`, `volumes[]` (`name` + `container_path`), `https`. Each `volumes` entry creates its own EFS access point rooted at `/${game}/${name}`. |
35-
| `hosted_zone_name` | `string` | `codercoco.com` | Existing Route 53 zone looked up as a data source. |
35+
| `hosted_zone_name` | `string` | _(required)_ | Existing Route 53 zone looked up as a data source (e.g. `example.com`). |
3636
| `acm_certificate_domain` | `string` | `null``*.{hosted_zone_name}` | Wildcard ACM cert for the ALB listener. |
3737
| `dns_ttl` | `number` | `30` | TTL on Route 53 A records the update-dns Lambda writes. Keep low for fast task churn. |
3838
| `watchdog_interval_minutes` | `number` | `15` | How often the watchdog schedule fires. |

terraform/terraform.tfvars.example

Lines changed: 74 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,74 @@
1-
# Copy this file to terraform.tfvars and customize.
2-
# terraform.tfvars is gitignored — safe to put passwords here.
3-
4-
aws_region = "us-east-1"
5-
project_name = "game-servers"
6-
7-
# Domain for server DNS records (must have a hosted zone in Route 53)
8-
# Creates: palworld.codercoco.com, satisfactory.codercoco.com, etc.
9-
hosted_zone_name = "codercoco.com"
10-
11-
# Watchdog: auto-shuts down idle servers after (interval × idle_checks) minutes
12-
# Defaults: 15 min × 4 checks = 60 minutes of idle before shutdown
13-
# For testing, use: watchdog_interval_minutes=2, watchdog_idle_checks=2
14-
watchdog_interval_minutes = 15
15-
watchdog_idle_checks = 4
16-
watchdog_min_packets = 100
17-
18-
# ACM certificate domain for HTTPS game servers (default: *.{hosted_zone_name})
19-
# acm_certificate_domain = "*.codercoco.com"
20-
21-
# Discord bot credentials (optional — leave commented out to configure via the web UI).
22-
# If set here, they seed the backing stores on the first `terraform apply`.
23-
# terraform.tfvars is gitignored, so it's safe to put real values here.
24-
# Get all three from https://discord.com/developers/applications → your app:
25-
# - Application ID: General Information → "Application ID". (goes to DynamoDB)
26-
# - Bot token: Bot → Reset Token → copy once (like a password). (goes to Secrets Manager)
27-
# - Public key: General Information → "Public Key". (goes to Secrets Manager)
28-
# discord_application_id = "1234567890"
29-
# discord_bot_token = "MTIz...xyz"
30-
# discord_public_key = "0123abc..."
31-
32-
# Base allowlist / admins (optional — permanent floor managed by Terraform).
33-
# Guilds and admin user/role IDs listed here are written to a separate
34-
# BASE#discord DynamoDB row on every `terraform apply`. The management UI
35-
# shows them as locked and cannot remove them; only editing these lists and
36-
# re-applying Terraform can change the base set.
37-
# base_allowed_guilds = ["123456789012345678"]
38-
# base_admin_user_ids = ["987654321098765432"]
39-
# base_admin_role_ids = []
40-
41-
# Override game server settings (optional — defaults are set in variables.tf)
42-
game_servers = {
43-
palworld = {
44-
image = "thijsvanloef/palworld-server-docker:latest"
45-
cpu = 2048
46-
memory = 8192
47-
ports = [
48-
{ container = 8211, protocol = "udp" },
49-
{ container = 27015, protocol = "udp" },
50-
]
51-
environment = [
52-
{ name = "PLAYERS", value = "8" },
53-
{ name = "MULTITHREADING", value = "true" },
54-
{ name = "RCON_ENABLED", value = "true" },
55-
{ name = "RCON_PORT", value = "25575" },
56-
{ name = "ADMIN_PASSWORD", value = "your_secure_password_here" },
57-
{ name = "SERVER_NAME", value = "CoderCoco Palworld" },
58-
{ name = "UPDATE_ON_BOOT", value = "true" },
59-
{ name = "BACKUP_ENABLED", value = "true" },
60-
{ name = "BACKUP_CRON_EXPRESSION", value = "0 */6 * * *" },
61-
{ name = "DIFFICULTY", value = "Normal" },
62-
]
63-
# Each entry gets its own EFS access point rooted at /${game}/${name}.
64-
# Add more entries if the image expects multiple mount paths.
65-
volumes = [
66-
{ name = "saves", container_path = "/palworld" },
67-
]
68-
https = false
69-
}
70-
71-
# FoundryVTT — web-based virtual tabletop (requires HTTPS)
72-
# The felddy/foundryvtt image needs FOUNDRY_USERNAME + FOUNDRY_PASSWORD
73-
# to download the licensed FoundryVTT software on first run.
74-
foundryvtt = {
75-
image = "felddy/foundryvtt:release"
76-
cpu = 1024
77-
memory = 2048
78-
ports = [
79-
{ container = 30000, protocol = "tcp" },
80-
]
81-
environment = [
82-
{ name = "FOUNDRY_USERNAME", value = "your_foundry_username" },
83-
{ name = "FOUNDRY_PASSWORD", value = "your_foundry_password" },
84-
{ name = "FOUNDRY_ADMIN_KEY", value = "your_admin_key" },
85-
{ name = "FOUNDRY_PROXY_SSL", value = "true" },
86-
{ name = "FOUNDRY_PROXY_PORT", value = "443" },
87-
{ name = "CONTAINER_VERBOSE", value = "true" },
88-
{ name = "FOUNDRY_WORLD", value = "my-world" },
89-
]
90-
volumes = [
91-
{ name = "data", container_path = "/data" },
92-
]
93-
https = true
94-
}
95-
}
1+
# Copy this file to terraform.tfvars and customize.
2+
# terraform.tfvars is gitignored — safe to put passwords here.
3+
4+
aws_region = "us-east-1"
5+
project_name = "game-servers"
6+
7+
# Domain for server DNS records (must have a hosted zone in Route 53)
8+
# Creates: {game}.example.com for each entry in game_servers below.
9+
hosted_zone_name = "example.com"
10+
11+
# Watchdog: auto-shuts down idle servers after (interval × idle_checks) minutes
12+
# Defaults: 15 min × 4 checks = 60 minutes of idle before shutdown
13+
# For testing, use: watchdog_interval_minutes=2, watchdog_idle_checks=2
14+
watchdog_interval_minutes = 15
15+
watchdog_idle_checks = 4
16+
watchdog_min_packets = 100
17+
18+
# ACM certificate domain for HTTPS game servers (default: *.{hosted_zone_name})
19+
# acm_certificate_domain = "*.example.com"
20+
21+
# Discord bot credentials (optional — leave commented out to configure via the web UI).
22+
# If set here, they seed the backing stores on the first `terraform apply`.
23+
# terraform.tfvars is gitignored, so it's safe to put real values here.
24+
# Get all three from https://discord.com/developers/applications → your app:
25+
# - Application ID: General Information → "Application ID". (goes to DynamoDB)
26+
# - Bot token: Bot → Reset Token → copy once (like a password). (goes to Secrets Manager)
27+
# - Public key: General Information → "Public Key". (goes to Secrets Manager)
28+
# discord_application_id = "1234567890"
29+
# discord_bot_token = "MTIz...xyz"
30+
# discord_public_key = "0123abc..."
31+
32+
# Base allowlist / admins (optional — permanent floor managed by Terraform).
33+
# Guilds and admin user/role IDs listed here are written to a separate
34+
# BASE#discord DynamoDB row on every `terraform apply`. The management UI
35+
# shows them as locked and cannot remove them; only editing these lists and
36+
# re-applying Terraform can change the base set.
37+
# base_allowed_guilds = ["123456789012345678"]
38+
# base_admin_user_ids = ["987654321098765432"]
39+
# base_admin_role_ids = []
40+
41+
# Game server definitions — required, no defaults are provided.
42+
# Each entry creates its own ECS task definition, EFS access point, log group,
43+
# and security group rules. Add as many games as you need.
44+
#
45+
# Example entry (Palworld):
46+
# game_servers = {
47+
# palworld = {
48+
# image = "thijsvanloef/palworld-server-docker:latest"
49+
# cpu = 2048
50+
# memory = 8192
51+
# ports = [
52+
# { container = 8211, protocol = "udp" },
53+
# { container = 27015, protocol = "udp" },
54+
# ]
55+
# environment = [
56+
# { name = "PLAYERS", value = "16" },
57+
# { name = "MULTITHREADING", value = "true" },
58+
# { name = "RCON_ENABLED", value = "true" },
59+
# { name = "RCON_PORT", value = "25575" },
60+
# { name = "ADMIN_PASSWORD", value = "your_secure_password_here" },
61+
# { name = "SERVER_NAME", value = "My Palworld Server" },
62+
# { name = "UPDATE_ON_BOOT", value = "true" },
63+
# { name = "BACKUP_ENABLED", value = "true" },
64+
# { name = "BACKUP_CRON_EXPRESSION", value = "0 */6 * * *" },
65+
# { name = "DIFFICULTY", value = "Normal" },
66+
# ]
67+
# # Each entry gets its own EFS access point rooted at /${game}/${name}.
68+
# # Add more entries if the image expects multiple mount paths.
69+
# volumes = [
70+
# { name = "saves", container_path = "/palworld" },
71+
# ]
72+
# https = false
73+
# }
74+
# }

terraform/variables.tf

Lines changed: 2 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -41,78 +41,12 @@ variable "game_servers" {
4141
])
4242
error_message = "Each game server must have at least one volume entry with non-empty name and container_path."
4343
}
44-
45-
default = {
46-
palworld = {
47-
image = "thijsvanloef/palworld-server-docker:latest"
48-
cpu = 2048
49-
memory = 8192
50-
ports = [
51-
{ container = 8211, protocol = "udp" },
52-
{ container = 27015, protocol = "udp" }, # Steam query port
53-
]
54-
environment = [
55-
{ name = "PLAYERS", value = "16" },
56-
{ name = "MULTITHREADING", value = "true" },
57-
{ name = "RCON_ENABLED", value = "true" },
58-
{ name = "RCON_PORT", value = "25575" },
59-
{ name = "ADMIN_PASSWORD", value = "changeme_please" },
60-
{ name = "SERVER_NAME", value = "Palworld Server" },
61-
{ name = "UPDATE_ON_BOOT", value = "true" },
62-
{ name = "BACKUP_ENABLED", value = "true" },
63-
{ name = "BACKUP_CRON_EXPRESSION", value = "0 */6 * * *" },
64-
{ name = "DIFFICULTY", value = "Normal" },
65-
]
66-
volumes = [
67-
{ name = "saves", container_path = "/palworld" },
68-
]
69-
https = false
70-
}
71-
72-
satisfactory = {
73-
image = "wolveix/satisfactory-server:latest"
74-
cpu = 2048
75-
memory = 8192
76-
ports = [
77-
{ container = 7777, protocol = "udp" },
78-
{ container = 15000, protocol = "udp" },
79-
{ container = 15777, protocol = "udp" },
80-
]
81-
environment = [
82-
{ name = "MAXPLAYERS", value = "4" },
83-
{ name = "PGID", value = "1000" },
84-
{ name = "PUID", value = "1000" },
85-
]
86-
volumes = [
87-
{ name = "config", container_path = "/config" },
88-
]
89-
https = false
90-
}
91-
92-
foundryvtt = {
93-
image = "felddy/foundryvtt:release"
94-
cpu = 1024
95-
memory = 2048
96-
ports = [
97-
{ container = 30000, protocol = "tcp" },
98-
]
99-
environment = [
100-
{ name = "FOUNDRY_PROXY_SSL", value = "true" },
101-
{ name = "FOUNDRY_PROXY_PORT", value = "443" },
102-
{ name = "CONTAINER_VERBOSE", value = "true" },
103-
]
104-
volumes = [
105-
{ name = "data", container_path = "/data" },
106-
]
107-
https = true
108-
}
109-
}
11044
}
11145

11246
# ── HTTPS / ALB ─────────────────────────────────────────────────────────────
11347

11448
variable "acm_certificate_domain" {
115-
description = "Domain for the ACM TLS certificate used by the ALB (e.g. *.codercoco.com)"
49+
description = "Domain for the ACM TLS certificate used by the ALB (e.g. *.example.com). Defaults to *.{hosted_zone_name} when null."
11650
type = string
11751
default = null # When null, defaults to *.{hosted_zone_name}
11852
}
@@ -140,9 +74,8 @@ variable "watchdog_min_packets" {
14074
# ── DNS ──────────────────────────────────────────────────────────────────────
14175

14276
variable "hosted_zone_name" {
143-
description = "Route 53 hosted zone domain (must already exist)"
77+
description = "Route 53 hosted zone domain (must already exist, e.g. example.com)"
14478
type = string
145-
default = "codercoco.com"
14679
}
14780

14881
variable "dns_ttl" {

0 commit comments

Comments
 (0)