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