TemplatesModules
Back to Templates
AWS EC2 (Linux) Icon

AWS EC2 (Linux)

By:
Provision AWS EC2 VMs as Coder workspaces
Source
README
Resources (2)

Copy and paste the following into main.tf and run coder template push:

1terraform {
2  required_providers {
3    coder = {
4      source = "coder/coder"
5    }
6    aws = {
7      source = "hashicorp/aws"
8    }
9  }
10}
11
12# Last updated 2023-03-14
13# aws ec2 describe-regions | jq -r '[.Regions[].RegionName] | sort'
14data "coder_parameter" "region" {
15  name         = "region"
16  display_name = "Region"
17  description  = "The region to deploy the workspace in."
18  default      = "us-east-1"
19  mutable      = false
20  option {
21    name  = "Asia Pacific (Tokyo)"
22    value = "ap-northeast-1"
23    icon  = "/emojis/1f1ef-1f1f5.png"
24  }
25  option {
26    name  = "Asia Pacific (Seoul)"
27    value = "ap-northeast-2"
28    icon  = "/emojis/1f1f0-1f1f7.png"
29  }
30  option {
31    name  = "Asia Pacific (Osaka)"
32    value = "ap-northeast-3"
33    icon  = "/emojis/1f1ef-1f1f5.png"
34  }
35  option {
36    name  = "Asia Pacific (Mumbai)"
37    value = "ap-south-1"
38    icon  = "/emojis/1f1ee-1f1f3.png"
39  }
40  option {
41    name  = "Asia Pacific (Singapore)"
42    value = "ap-southeast-1"
43    icon  = "/emojis/1f1f8-1f1ec.png"
44  }
45  option {
46    name  = "Asia Pacific (Sydney)"
47    value = "ap-southeast-2"
48    icon  = "/emojis/1f1e6-1f1fa.png"
49  }
50  option {
51    name  = "Canada (Central)"
52    value = "ca-central-1"
53    icon  = "/emojis/1f1e8-1f1e6.png"
54  }
55  option {
56    name  = "EU (Frankfurt)"
57    value = "eu-central-1"
58    icon  = "/emojis/1f1ea-1f1fa.png"
59  }
60  option {
61    name  = "EU (Stockholm)"
62    value = "eu-north-1"
63    icon  = "/emojis/1f1ea-1f1fa.png"
64  }
65  option {
66    name  = "EU (Ireland)"
67    value = "eu-west-1"
68    icon  = "/emojis/1f1ea-1f1fa.png"
69  }
70  option {
71    name  = "EU (London)"
72    value = "eu-west-2"
73    icon  = "/emojis/1f1ea-1f1fa.png"
74  }
75  option {
76    name  = "EU (Paris)"
77    value = "eu-west-3"
78    icon  = "/emojis/1f1ea-1f1fa.png"
79  }
80  option {
81    name  = "South America (São Paulo)"
82    value = "sa-east-1"
83    icon  = "/emojis/1f1e7-1f1f7.png"
84  }
85  option {
86    name  = "US East (N. Virginia)"
87    value = "us-east-1"
88    icon  = "/emojis/1f1fa-1f1f8.png"
89  }
90  option {
91    name  = "US East (Ohio)"
92    value = "us-east-2"
93    icon  = "/emojis/1f1fa-1f1f8.png"
94  }
95  option {
96    name  = "US West (N. California)"
97    value = "us-west-1"
98    icon  = "/emojis/1f1fa-1f1f8.png"
99  }
100  option {
101    name  = "US West (Oregon)"
102    value = "us-west-2"
103    icon  = "/emojis/1f1fa-1f1f8.png"
104  }
105}
106
107data "coder_parameter" "instance_type" {
108  name         = "instance_type"
109  display_name = "Instance type"
110  description  = "What instance type should your workspace use?"
111  default      = "t3.micro"
112  mutable      = false
113  option {
114    name  = "2 vCPU, 1 GiB RAM"
115    value = "t3.micro"
116  }
117  option {
118    name  = "2 vCPU, 2 GiB RAM"
119    value = "t3.small"
120  }
121  option {
122    name  = "2 vCPU, 4 GiB RAM"
123    value = "t3.medium"
124  }
125  option {
126    name  = "2 vCPU, 8 GiB RAM"
127    value = "t3.large"
128  }
129  option {
130    name  = "4 vCPU, 16 GiB RAM"
131    value = "t3.xlarge"
132  }
133  option {
134    name  = "8 vCPU, 32 GiB RAM"
135    value = "t3.2xlarge"
136  }
137}
138
139provider "aws" {
140  region = data.coder_parameter.region.value
141}
142
143data "coder_workspace" "me" {}
144data "coder_workspace_owner" "me" {}
145
146data "aws_ami" "ubuntu" {
147  most_recent = true
148  filter {
149    name   = "name"
150    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
151  }
152  filter {
153    name   = "virtualization-type"
154    values = ["hvm"]
155  }
156  owners = ["099720109477"] # Canonical
157}
158
159resource "coder_agent" "dev" {
160  count          = data.coder_workspace.me.start_count
161  arch           = "amd64"
162  auth           = "aws-instance-identity"
163  os             = "linux"
164  startup_script = <<-EOT
165    set -e
166
167    # Add any commands that should be executed at workspace startup (e.g install requirements, start a program, etc) here
168  EOT
169
170  metadata {
171    key          = "cpu"
172    display_name = "CPU Usage"
173    interval     = 5
174    timeout      = 5
175    script       = "coder stat cpu"
176  }
177  metadata {
178    key          = "memory"
179    display_name = "Memory Usage"
180    interval     = 5
181    timeout      = 5
182    script       = "coder stat mem"
183  }
184  metadata {
185    key          = "disk"
186    display_name = "Disk Usage"
187    interval     = 600 # every 10 minutes
188    timeout      = 30  # df can take a while on large filesystems
189    script       = "coder stat disk --path $HOME"
190  }
191}
192
193# See https://registry.coder.com/modules/code-server
194module "code-server" {
195  count  = data.coder_workspace.me.start_count
196  source = "registry.coder.com/modules/code-server/coder"
197
198  # This ensures that the latest version of the module gets downloaded, you can also pin the module version to prevent breaking changes in production.
199  version = ">= 1.0.0"
200
201  agent_id = coder_agent.dev[0].id
202  order    = 1
203}
204
205# See https://registry.coder.com/modules/jetbrains-gateway
206module "jetbrains_gateway" {
207  count  = data.coder_workspace.me.start_count
208  source = "registry.coder.com/modules/jetbrains-gateway/coder"
209
210  # JetBrains IDEs to make available for the user to select
211  jetbrains_ides = ["IU", "PY", "WS", "PS", "RD", "CL", "GO", "RM"]
212  default        = "IU"
213
214  # Default folder to open when starting a JetBrains IDE
215  folder = "/home/coder"
216
217  # This ensures that the latest version of the module gets downloaded, you can also pin the module version to prevent breaking changes in production.
218  version = ">= 1.0.0"
219
220  agent_id   = coder_agent.dev[0].id
221  agent_name = "dev"
222  order      = 2
223}
224
225locals {
226  hostname   = lower(data.coder_workspace.me.name)
227  linux_user = "coder"
228}
229
230data "cloudinit_config" "user_data" {
231  gzip          = false
232  base64_encode = false
233
234  boundary = "//"
235
236  part {
237    filename     = "cloud-config.yaml"
238    content_type = "text/cloud-config"
239
240    content = templatefile("${path.module}/cloud-init/cloud-config.yaml.tftpl", {
241      hostname   = local.hostname
242      linux_user = local.linux_user
243    })
244  }
245
246  part {
247    filename     = "userdata.sh"
248    content_type = "text/x-shellscript"
249
250    content = templatefile("${path.module}/cloud-init/userdata.sh.tftpl", {
251      linux_user = local.linux_user
252
253      init_script = try(coder_agent.dev[0].init_script, "")
254    })
255  }
256}
257
258resource "aws_instance" "dev" {
259  ami               = data.aws_ami.ubuntu.id
260  availability_zone = "${data.coder_parameter.region.value}a"
261  instance_type     = data.coder_parameter.instance_type.value
262
263  user_data = data.cloudinit_config.user_data.rendered
264  tags = {
265    Name = "coder-${data.coder_workspace_owner.me.name}-${data.coder_workspace.me.name}"
266    # Required if you are using our example policy, see template README
267    Coder_Provisioned = "true"
268  }
269  lifecycle {
270    ignore_changes = [ami]
271  }
272}
273
274resource "coder_metadata" "workspace_info" {
275  resource_id = aws_instance.dev.id
276  item {
277    key   = "region"
278    value = data.coder_parameter.region.value
279  }
280  item {
281    key   = "instance type"
282    value = aws_instance.dev.instance_type
283  }
284  item {
285    key   = "disk"
286    value = "${aws_instance.dev.root_block_device[0].volume_size} GiB"
287  }
288}
289
290resource "aws_ec2_instance_state" "dev" {
291  instance_id = aws_instance.dev.id
292  state       = data.coder_workspace.me.transition == "start" ? "running" : "stopped"
293}
294