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 google = {
7 source = "hashicorp/google"
8 }
9 }
10}
11
12provider "coder" {
13}
14
15variable "project_id" {
16 description = "Which Google Compute Project should your workspace live in?"
17}
18
19data "coder_parameter" "zone" {
20 name = "zone"
21 display_name = "Zone"
22 description = "Which zone should your workspace live in?"
23 type = "string"
24 icon = "/emojis/1f30e.png"
25 default = "us-central1-a"
26 mutable = false
27 option {
28 name = "North America (Northeast)"
29 value = "northamerica-northeast1-a"
30 icon = "/emojis/1f1fa-1f1f8.png"
31 }
32 option {
33 name = "North America (Central)"
34 value = "us-central1-a"
35 icon = "/emojis/1f1fa-1f1f8.png"
36 }
37 option {
38 name = "North America (West)"
39 value = "us-west2-c"
40 icon = "/emojis/1f1fa-1f1f8.png"
41 }
42 option {
43 name = "Europe (West)"
44 value = "europe-west4-b"
45 icon = "/emojis/1f1ea-1f1fa.png"
46 }
47 option {
48 name = "South America (East)"
49 value = "southamerica-east1-a"
50 icon = "/emojis/1f1e7-1f1f7.png"
51 }
52}
53
54provider "google" {
55 zone = data.coder_parameter.zone.value
56 project = var.project_id
57}
58
59data "google_compute_default_service_account" "default" {
60}
61
62data "coder_workspace" "me" {
63}
64data "coder_workspace_owner" "me" {}
65
66resource "google_compute_disk" "root" {
67 name = "coder-${data.coder_workspace.me.id}-root"
68 type = "pd-ssd"
69 zone = data.coder_parameter.zone.value
70 image = "debian-cloud/debian-11"
71 lifecycle {
72 ignore_changes = [name, image]
73 }
74}
75
76resource "coder_agent" "main" {
77 auth = "google-instance-identity"
78 arch = "amd64"
79 os = "linux"
80 startup_script = <<-EOT
81 set -e
82
83 # Install the latest code-server.
84 # Append "--version x.x.x" to install a specific version of code-server.
85 curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server
86
87 # Start code-server in the background.
88 /tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 &
89 EOT
90
91 metadata {
92 key = "cpu"
93 display_name = "CPU Usage"
94 interval = 5
95 timeout = 5
96 script = <<-EOT
97 #!/bin/bash
98 set -e
99 top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4 "%"}'
100 EOT
101 }
102 metadata {
103 key = "memory"
104 display_name = "Memory Usage"
105 interval = 5
106 timeout = 5
107 script = <<-EOT
108 #!/bin/bash
109 set -e
110 free -m | awk 'NR==2{printf "%.2f%%\t", $3*100/$2 }'
111 EOT
112 }
113 metadata {
114 key = "disk"
115 display_name = "Disk Usage"
116 interval = 600 # every 10 minutes
117 timeout = 30 # df can take a while on large filesystems
118 script = <<-EOT
119 #!/bin/bash
120 set -e
121 df /home/coder | awk '$NF=="/"{printf "%s", $5}'
122 EOT
123 }
124}
125
126# code-server
127resource "coder_app" "code-server" {
128 agent_id = coder_agent.main.id
129 slug = "code-server"
130 display_name = "code-server"
131 icon = "/icon/code.svg"
132 url = "http://localhost:13337?folder=/home/coder"
133 subdomain = false
134 share = "owner"
135
136 healthcheck {
137 url = "http://localhost:13337/healthz"
138 interval = 3
139 threshold = 10
140 }
141}
142
143resource "google_compute_instance" "dev" {
144 zone = data.coder_parameter.zone.value
145 count = data.coder_workspace.me.start_count
146 name = "coder-${lower(data.coder_workspace_owner.me.name)}-${lower(data.coder_workspace.me.name)}-root"
147 machine_type = "e2-medium"
148 network_interface {
149 network = "default"
150 access_config {
151 // Ephemeral public IP
152 }
153 }
154 boot_disk {
155 auto_delete = false
156 source = google_compute_disk.root.name
157 }
158 service_account {
159 email = data.google_compute_default_service_account.default.email
160 scopes = ["cloud-platform"]
161 }
162 # The startup script runs as root with no $HOME environment set up, so instead of directly
163 # running the agent init script, create a user (with a homedir, default shell and sudo
164 # permissions) and execute the init script as that user.
165 metadata_startup_script = <<EOMETA
166#!/usr/bin/env sh
167set -eux
168
169# If user does not exist, create it and set up passwordless sudo
170if ! id -u "${local.linux_user}" >/dev/null 2>&1; then
171 useradd -m -s /bin/bash "${local.linux_user}"
172 echo "${local.linux_user} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/coder-user
173fi
174
175exec sudo -u "${local.linux_user}" sh -c '${coder_agent.main.init_script}'
176EOMETA
177}
178
179locals {
180 # Ensure Coder username is a valid Linux username
181 linux_user = lower(substr(data.coder_workspace_owner.me.name, 0, 32))
182}
183
184resource "coder_metadata" "workspace_info" {
185 count = data.coder_workspace.me.start_count
186 resource_id = google_compute_instance.dev[0].id
187
188 item {
189 key = "type"
190 value = google_compute_instance.dev[0].machine_type
191 }
192}
193
194resource "coder_metadata" "home_info" {
195 resource_id = google_compute_disk.root.id
196
197 item {
198 key = "size"
199 value = "${google_compute_disk.root.size} GiB"
200 }
201}
202