-
Notifications
You must be signed in to change notification settings - Fork 513
/
Copy pathmain.tf
186 lines (161 loc) · 6.1 KB
/
main.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
Connect with friends via a shared digital space in Minecraft.
This is a safe Minecraft server that won't break the bank. Game data is preserved across sessions.
Server is hosted on a permenant IP address. You need to start the VM each session, but it
will shutdown within 24 hours if you forget to turn it off.
Process is run in a sandboxed VM, so any server exploits cannot do any serious damage.
We are experimenting with providing support through a [google doc](https://docs.google.com/document/d/1TXyzHKqoKMS-jY9FSMrYNLEGathqSG8YuHdj0Z9GP34).
Help us make this simple for others to use by asking for help.
Features
- Runs [itzg/minecraft-server](https://hub.docker.com/r/itzg/minecraft-server/) Docker image
- Preemtible VM (cheapest), shuts down automatically within 24h if you forget to stop the VM
- Reserves a stable public IP, so the minecraft clients do not need to be reconfigured
- Reserves the disk, so game data is remembered across sessions
- Restricted service account, VM has no ability to consume GCP resources beyond its instance and disk
- 2$ per month
- Reserved IP address costs: $1.46 per month
- Reserved 10Gb disk costs: $0.40
- VM cost: $0.01 per hour, max session cost $0.24
*/
# We require a project to be provided upfront
# Create a project at https://cloud.google.com/
# Make note of the project ID
# We need a storage bucket created upfront too to store the terraform state
terraform {
backend "gcs" {
prefix = "minecraft/state"
bucket = "terraform-larkworthy"
}
}
# You need to fill these locals out with the project, region and zone
# Then to boot it up, run:-
# gcloud auth application-default login
# terraform init
# terraform apply
locals {
# The Google Cloud Project ID that will host and pay for your Minecraft server
project = "larkworthy-tester"
region = "europe-west1"
zone = "europe-west1-b"
# Allow members of an external Google group to turn on the server
# through the Cloud Console mobile app or https://console.cloud.google.com
# Create a group at https://groups.google.com/forum/#!creategroup
# and invite members by their email address.
enable_switch_access_group = 1
minecraft_switch_access_group = "[email protected]"
}
provider "google" {
project = local.project
region = local.region
}
# Create service account to run service with no permissions
resource "google_service_account" "minecraft" {
account_id = "minecraft"
display_name = "minecraft"
}
# Permenant Minecraft disk, stays around when VM is off
resource "google_compute_disk" "minecraft" {
name = "minecraft"
type = "pd-standard"
zone = local.zone
image = "cos-cloud/cos-stable"
}
# Permenant IP address, stays around when VM is off
resource "google_compute_address" "minecraft" {
name = "minecraft-ip"
region = local.region
}
# VM to run Minecraft, we use preemptable which will shutdown within 24 hours
resource "google_compute_instance" "minecraft" {
name = "minecraft"
machine_type = "n1-standard-1"
zone = local.zone
tags = ["minecraft"]
# Run itzg/minecraft-server docker image on startup
# The instructions of https://hub.docker.com/r/itzg/minecraft-server/ are applicable
# For instance, Ssh into the instance and you can run
# docker logs mc
# docker exec -i mc rcon-cli
# Once in rcon-cli you can "op <player_id>" to make someone an operator (admin)
# Use 'sudo journalctl -u google-startup-scripts.service' to retrieve the startup script output
metadata_startup_script = "docker run -d -p 25565:25565 -e EULA=TRUE -e VERSION=1.12.2 -v /var/minecraft:/data --name mc -e TYPE=FORGE -e FORGEVERSION=14.23.0.2552 -e MEMORY=2G --rm=true itzg/minecraft-server:latest;"
metadata = {
enable-oslogin = "TRUE"
}
boot_disk {
auto_delete = false # Keep disk after shutdown (game data)
source = google_compute_disk.minecraft.self_link
}
network_interface {
network = google_compute_network.minecraft.name
access_config {
nat_ip = google_compute_address.minecraft.address
}
}
service_account {
email = google_service_account.minecraft.email
scopes = ["userinfo-email"]
}
scheduling {
preemptible = true # Closes within 24 hours (sometimes sooner)
automatic_restart = false
}
}
# Create a private network so the minecraft instance cannot access
# any other resources.
resource "google_compute_network" "minecraft" {
name = "minecraft"
}
# Open the firewall for Minecraft traffic
resource "google_compute_firewall" "minecraft" {
name = "minecraft"
network = google_compute_network.minecraft.name
# Minecraft client port
allow {
protocol = "tcp"
ports = ["25565"]
}
# ICMP (ping)
allow {
protocol = "icmp"
}
# SSH (for RCON-CLI access)
allow {
protocol = "tcp"
ports = ["22"]
}
source_ranges = ["0.0.0.0/0"]
target_tags = ["minecraft"]
}
resource "google_project_iam_custom_role" "minecraftSwitcher" {
role_id = "MinecraftSwitcher"
title = "Minecraft Switcher"
description = "Can turn a VM on and off"
permissions = ["compute.instances.start", "compute.instances.stop", "compute.instances.get"]
}
resource "google_project_iam_custom_role" "instanceLister" {
role_id = "InstanceLister"
title = "Instance Lister"
description = "Can list VMs in project"
permissions = ["compute.instances.list"]
}
resource "google_compute_instance_iam_member" "switcher" {
count = local.enable_switch_access_group
project = local.project
zone = local.zone
instance_name = google_compute_instance.minecraft.name
role = google_project_iam_custom_role.minecraftSwitcher.id
member = "group:${local.minecraft_switch_access_group}"
}
resource "google_project_iam_member" "projectBrowsers" {
count = local.enable_switch_access_group
project = local.project
role = "roles/browser"
member = "group:${local.minecraft_switch_access_group}"
}
resource "google_project_iam_member" "computeViewer" {
count = local.enable_switch_access_group
project = local.project
role = google_project_iam_custom_role.instanceLister.id
member = "group:${local.minecraft_switch_access_group}"
}