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 kubernetes = {
7 source = "hashicorp/kubernetes"
8 }
9 }
10}
11
12data "coder_parameter" "home_disk" {
13 name = "Disk Size"
14 description = "How large should the disk storing the home directory be?"
15 icon = "https://cdn-icons-png.flaticon.com/512/2344/2344147.png"
16 type = "number"
17 default = 10
18 mutable = true
19 validation {
20 min = 10
21 max = 100
22 }
23}
24
25variable "use_kubeconfig" {
26 type = bool
27 sensitive = true
28 default = true
29 description = <<-EOF
30 Use host kubeconfig? (true/false)
31 Set this to false if the Coder host is itself running as a Pod on the same
32 Kubernetes cluster as you are deploying workspaces to.
33 Set this to true if the Coder host is running outside the Kubernetes cluster
34 for workspaces. A valid "~/.kube/config" must be present on the Coder host.
35 EOF
36}
37
38provider "coder" {
39}
40
41variable "namespace" {
42 type = string
43 sensitive = true
44 description = "The namespace to create workspaces in (must exist prior to creating workspaces)"
45}
46
47variable "create_tun" {
48 type = bool
49 sensitive = true
50 description = "Add a TUN device to the workspace."
51 default = false
52}
53
54variable "create_fuse" {
55 type = bool
56 description = "Add a FUSE device to the workspace."
57 sensitive = true
58 default = false
59}
60
61variable "max_cpus" {
62 type = string
63 sensitive = true
64 description = "Max number of CPUs the workspace may use (e.g. 2)."
65}
66
67variable "min_cpus" {
68 type = string
69 sensitive = true
70 description = "Minimum number of CPUs the workspace may use (e.g. .1)."
71}
72
73variable "max_memory" {
74 type = string
75 description = "Maximum amount of memory to allocate the workspace (in GB)."
76 sensitive = true
77}
78
79variable "min_memory" {
80 type = string
81 description = "Minimum amount of memory to allocate the workspace (in GB)."
82 sensitive = true
83}
84
85provider "kubernetes" {
86 # Authenticate via ~/.kube/config or a Coder-specific ServiceAccount, depending on admin preferences
87 config_path = var.use_kubeconfig == true ? "~/.kube/config" : null
88}
89
90data "coder_workspace" "me" {}
91data "coder_workspace_owner" "me" {}
92
93resource "coder_agent" "main" {
94 os = "linux"
95 arch = "amd64"
96 startup_script = <<EOT
97 #!/bin/bash
98 # home folder can be empty, so copying default bash settings
99 if [ ! -f ~/.profile ]; then
100 cp /etc/skel/.profile $HOME
101 fi
102 if [ ! -f ~/.bashrc ]; then
103 cp /etc/skel/.bashrc $HOME
104 fi
105 # install and start code-server
106 curl -fsSL https://code-server.dev/install.sh | sh -s -- --version 4.8.3 | tee code-server-install.log
107 code-server --auth none --port 13337 | tee code-server-install.log &
108 EOT
109}
110
111# code-server
112resource "coder_app" "code-server" {
113 agent_id = coder_agent.main.id
114 slug = "code-server"
115 display_name = "code-server"
116 icon = "/icon/code.svg"
117 url = "http://localhost:13337?folder=/home/coder"
118 subdomain = false
119 share = "owner"
120
121 healthcheck {
122 url = "http://localhost:13337/healthz"
123 interval = 3
124 threshold = 10
125 }
126}
127
128resource "kubernetes_persistent_volume_claim" "home" {
129 metadata {
130 name = "coder-${lower(data.coder_workspace_owner.me.name)}-${lower(data.coder_workspace.me.name)}-home"
131 namespace = var.namespace
132 }
133 wait_until_bound = false
134 spec {
135 access_modes = ["ReadWriteOnce"]
136 resources {
137 requests = {
138 storage = "${data.coder_parameter.home_disk.value}Gi"
139 }
140 }
141 }
142}
143
144resource "kubernetes_pod" "main" {
145 count = data.coder_workspace.me.start_count
146
147 metadata {
148 name = "coder-${lower(data.coder_workspace_owner.me.name)}-${lower(data.coder_workspace.me.name)}"
149 namespace = var.namespace
150 }
151
152 spec {
153 restart_policy = "Never"
154
155 container {
156 name = "dev"
157 # We highly recommend pinning this to a specific release of envbox, as the latest tag may change.
158 image = "ghcr.io/coder/envbox:latest"
159 image_pull_policy = "Always"
160 command = ["/envbox", "docker"]
161
162 security_context {
163 privileged = true
164 }
165
166 resources {
167 requests = {
168 "cpu" : "${var.min_cpus}"
169 "memory" : "${var.min_memory}G"
170 }
171
172 limits = {
173 "cpu" : "${var.max_cpus}"
174 "memory" : "${var.max_memory}G"
175 }
176 }
177
178 env {
179 name = "CODER_AGENT_TOKEN"
180 value = coder_agent.main.token
181 }
182
183 env {
184 name = "CODER_AGENT_URL"
185 value = data.coder_workspace.me.access_url
186 }
187
188 env {
189 name = "CODER_INNER_IMAGE"
190 value = "index.docker.io/codercom/enterprise-base@sha256:069e84783d134841cbb5007a16d9025b6aed67bc5b95eecc118eb96dccd6de68"
191 }
192
193 env {
194 name = "CODER_INNER_USERNAME"
195 value = "coder"
196 }
197
198 env {
199 name = "CODER_BOOTSTRAP_SCRIPT"
200 value = coder_agent.main.init_script
201 }
202
203 env {
204 name = "CODER_MOUNTS"
205 value = "/home/coder:/home/coder"
206 }
207
208 env {
209 name = "CODER_ADD_FUSE"
210 value = var.create_fuse
211 }
212
213 env {
214 name = "CODER_INNER_HOSTNAME"
215 value = data.coder_workspace.me.name
216 }
217
218 env {
219 name = "CODER_ADD_TUN"
220 value = var.create_tun
221 }
222
223 env {
224 name = "CODER_CPUS"
225 value_from {
226 resource_field_ref {
227 resource = "limits.cpu"
228 }
229 }
230 }
231
232 env {
233 name = "CODER_MEMORY"
234 value_from {
235 resource_field_ref {
236 resource = "limits.memory"
237 }
238 }
239 }
240
241 volume_mount {
242 mount_path = "/home/coder"
243 name = "home"
244 read_only = false
245 sub_path = "home"
246 }
247
248 volume_mount {
249 mount_path = "/var/lib/coder/docker"
250 name = "home"
251 sub_path = "cache/docker"
252 }
253
254 volume_mount {
255 mount_path = "/var/lib/coder/containers"
256 name = "home"
257 sub_path = "cache/containers"
258 }
259
260 volume_mount {
261 mount_path = "/var/lib/sysbox"
262 name = "sysbox"
263 }
264
265 volume_mount {
266 mount_path = "/var/lib/containers"
267 name = "home"
268 sub_path = "envbox/containers"
269 }
270
271 volume_mount {
272 mount_path = "/var/lib/docker"
273 name = "home"
274 sub_path = "envbox/docker"
275 }
276
277 volume_mount {
278 mount_path = "/usr/src"
279 name = "usr-src"
280 }
281
282 volume_mount {
283 mount_path = "/lib/modules"
284 name = "lib-modules"
285 }
286 }
287
288 volume {
289 name = "home"
290 persistent_volume_claim {
291 claim_name = kubernetes_persistent_volume_claim.home.metadata.0.name
292 read_only = false
293 }
294 }
295
296 volume {
297 name = "sysbox"
298 empty_dir {}
299 }
300
301 volume {
302 name = "usr-src"
303 host_path {
304 path = "/usr/src"
305 type = ""
306 }
307 }
308
309 volume {
310 name = "lib-modules"
311 host_path {
312 path = "/lib/modules"
313 type = ""
314 }
315 }
316 }
317}
318