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" {}
91
92resource "coder_agent" "main" {
93 os = "linux"
94 arch = "amd64"
95 startup_script = <<EOT
96 #!/bin/bash
97 # home folder can be empty, so copying default bash settings
98 if [ ! -f ~/.profile ]; then
99 cp /etc/skel/.profile $HOME
100 fi
101 if [ ! -f ~/.bashrc ]; then
102 cp /etc/skel/.bashrc $HOME
103 fi
104 # install and start code-server
105 curl -fsSL https://code-server.dev/install.sh | sh -s -- --version 4.8.3 | tee code-server-install.log
106 code-server --auth none --port 13337 | tee code-server-install.log &
107 EOT
108}
109
110# code-server
111resource "coder_app" "code-server" {
112 agent_id = coder_agent.main.id
113 slug = "code-server"
114 display_name = "code-server"
115 icon = "/icon/code.svg"
116 url = "http://localhost:13337?folder=/home/coder"
117 subdomain = false
118 share = "owner"
119
120 healthcheck {
121 url = "http://localhost:13337/healthz"
122 interval = 3
123 threshold = 10
124 }
125}
126
127resource "kubernetes_persistent_volume_claim" "home" {
128 metadata {
129 name = "coder-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}-home"
130 namespace = var.namespace
131 }
132 wait_until_bound = false
133 spec {
134 access_modes = ["ReadWriteOnce"]
135 resources {
136 requests = {
137 storage = "${data.coder_parameter.home_disk.value}Gi"
138 }
139 }
140 }
141}
142
143resource "kubernetes_pod" "main" {
144 count = data.coder_workspace.me.start_count
145
146 metadata {
147 name = "coder-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}"
148 namespace = var.namespace
149 }
150
151 spec {
152 restart_policy = "Never"
153
154 container {
155 name = "dev"
156 image = "ghcr.io/coder/envbox:latest"
157 image_pull_policy = "Always"
158 command = ["/envbox", "docker"]
159
160 security_context {
161 privileged = true
162 }
163
164 resources {
165 requests = {
166 "cpu" : "${var.min_cpus}"
167 "memory" : "${var.min_memory}G"
168 }
169
170 limits = {
171 "cpu" : "${var.max_cpus}"
172 "memory" : "${var.max_memory}G"
173 }
174 }
175
176 env {
177 name = "CODER_AGENT_TOKEN"
178 value = coder_agent.main.token
179 }
180
181 env {
182 name = "CODER_AGENT_URL"
183 value = data.coder_workspace.me.access_url
184 }
185
186 env {
187 name = "CODER_INNER_IMAGE"
188 value = "index.docker.io/codercom/enterprise-base@sha256:069e84783d134841cbb5007a16d9025b6aed67bc5b95eecc118eb96dccd6de68"
189 }
190
191 env {
192 name = "CODER_INNER_USERNAME"
193 value = "coder"
194 }
195
196 env {
197 name = "CODER_BOOTSTRAP_SCRIPT"
198 value = coder_agent.main.init_script
199 }
200
201 env {
202 name = "CODER_MOUNTS"
203 value = "/home/coder:/home/coder"
204 }
205
206 env {
207 name = "CODER_ADD_FUSE"
208 value = var.create_fuse
209 }
210
211 env {
212 name = "CODER_INNER_HOSTNAME"
213 value = data.coder_workspace.me.name
214 }
215
216 env {
217 name = "CODER_ADD_TUN"
218 value = var.create_tun
219 }
220
221 env {
222 name = "CODER_CPUS"
223 value_from {
224 resource_field_ref {
225 resource = "limits.cpu"
226 }
227 }
228 }
229
230 env {
231 name = "CODER_MEMORY"
232 value_from {
233 resource_field_ref {
234 resource = "limits.memory"
235 }
236 }
237 }
238
239 volume_mount {
240 mount_path = "/home/coder"
241 name = "home"
242 read_only = false
243 sub_path = "home"
244 }
245
246 volume_mount {
247 mount_path = "/var/lib/coder/docker"
248 name = "home"
249 sub_path = "cache/docker"
250 }
251
252 volume_mount {
253 mount_path = "/var/lib/coder/containers"
254 name = "home"
255 sub_path = "cache/containers"
256 }
257
258 volume_mount {
259 mount_path = "/var/lib/sysbox"
260 name = "sysbox"
261 }
262
263 volume_mount {
264 mount_path = "/var/lib/containers"
265 name = "home"
266 sub_path = "envbox/containers"
267 }
268
269 volume_mount {
270 mount_path = "/var/lib/docker"
271 name = "home"
272 sub_path = "envbox/docker"
273 }
274
275 volume_mount {
276 mount_path = "/usr/src"
277 name = "usr-src"
278 }
279
280 volume_mount {
281 mount_path = "/lib/modules"
282 name = "lib-modules"
283 }
284 }
285
286 volume {
287 name = "home"
288 persistent_volume_claim {
289 claim_name = kubernetes_persistent_volume_claim.home.metadata.0.name
290 read_only = false
291 }
292 }
293
294 volume {
295 name = "sysbox"
296 empty_dir {}
297 }
298
299 volume {
300 name = "usr-src"
301 host_path {
302 path = "/usr/src"
303 type = ""
304 }
305 }
306
307 volume {
308 name = "lib-modules"
309 host_path {
310 path = "/lib/modules"
311 type = ""
312 }
313 }
314 }
315}
316