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 docker = {
7 source = "kreuzwerker/docker"
8 }
9 }
10}
11
12locals {
13 username = data.coder_workspace_owner.me.name
14}
15
16variable "docker_socket" {
17 default = ""
18 description = "(Optional) Docker socket URI"
19 type = string
20}
21
22provider "docker" {
23 # Defaulting to null if the variable is an empty string lets us have an optional variable without having to set our own default
24 host = var.docker_socket != "" ? var.docker_socket : null
25}
26
27data "coder_provisioner" "me" {}
28data "coder_workspace" "me" {}
29data "coder_workspace_owner" "me" {}
30
31resource "coder_agent" "main" {
32 arch = data.coder_provisioner.me.arch
33 os = "linux"
34 startup_script = <<-EOT
35 set -e
36
37 # Prepare user home with default files on first start.
38 if [ ! -f ~/.init_done ]; then
39 cp -rT /etc/skel ~
40 touch ~/.init_done
41 fi
42
43 # Install the latest code-server.
44 # Append "--version x.x.x" to install a specific version of code-server.
45 curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server
46
47 # Start code-server in the background.
48 /tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 &
49 EOT
50
51 # These environment variables allow you to make Git commits right away after creating a
52 # workspace. Note that they take precedence over configuration defined in ~/.gitconfig!
53 # You can remove this block if you'd prefer to configure Git manually or using
54 # dotfiles. (see docs/dotfiles.md)
55 env = {
56 GIT_AUTHOR_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
57 GIT_AUTHOR_EMAIL = "${data.coder_workspace_owner.me.email}"
58 GIT_COMMITTER_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
59 GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}"
60 }
61
62 # The following metadata blocks are optional. They are used to display
63 # information about your workspace in the dashboard. You can remove them
64 # if you don't want to display any information.
65 # For basic resources, you can use the `coder stat` command.
66 # If you need more control, you can write your own script.
67 metadata {
68 display_name = "CPU Usage"
69 key = "0_cpu_usage"
70 script = "coder stat cpu"
71 interval = 10
72 timeout = 1
73 }
74
75 metadata {
76 display_name = "RAM Usage"
77 key = "1_ram_usage"
78 script = "coder stat mem"
79 interval = 10
80 timeout = 1
81 }
82
83 metadata {
84 display_name = "Home Disk"
85 key = "3_home_disk"
86 script = "coder stat disk --path $${HOME}"
87 interval = 60
88 timeout = 1
89 }
90
91 metadata {
92 display_name = "CPU Usage (Host)"
93 key = "4_cpu_usage_host"
94 script = "coder stat cpu --host"
95 interval = 10
96 timeout = 1
97 }
98
99 metadata {
100 display_name = "Memory Usage (Host)"
101 key = "5_mem_usage_host"
102 script = "coder stat mem --host"
103 interval = 10
104 timeout = 1
105 }
106
107 metadata {
108 display_name = "Load Average (Host)"
109 key = "6_load_host"
110 # get load avg scaled by number of cores
111 script = <<EOT
112 echo "`cat /proc/loadavg | awk '{ print $1 }'` `nproc`" | awk '{ printf "%0.2f", $1/$2 }'
113 EOT
114 interval = 60
115 timeout = 1
116 }
117
118 metadata {
119 display_name = "Swap Usage (Host)"
120 key = "7_swap_host"
121 script = <<EOT
122 free -b | awk '/^Swap/ { printf("%.1f/%.1f", $3/1024.0/1024.0/1024.0, $2/1024.0/1024.0/1024.0) }'
123 EOT
124 interval = 10
125 timeout = 1
126 }
127}
128
129resource "coder_app" "code-server" {
130 agent_id = coder_agent.main.id
131 slug = "code-server"
132 display_name = "code-server"
133 url = "http://localhost:13337/?folder=/home/${local.username}"
134 icon = "/icon/code.svg"
135 subdomain = false
136 share = "owner"
137
138 healthcheck {
139 url = "http://localhost:13337/healthz"
140 interval = 5
141 threshold = 6
142 }
143}
144
145resource "docker_volume" "home_volume" {
146 name = "coder-${data.coder_workspace.me.id}-home"
147 # Protect the volume from being deleted due to changes in attributes.
148 lifecycle {
149 ignore_changes = all
150 }
151 # Add labels in Docker to keep track of orphan resources.
152 labels {
153 label = "coder.owner"
154 value = data.coder_workspace_owner.me.name
155 }
156 labels {
157 label = "coder.owner_id"
158 value = data.coder_workspace_owner.me.id
159 }
160 labels {
161 label = "coder.workspace_id"
162 value = data.coder_workspace.me.id
163 }
164 # This field becomes outdated if the workspace is renamed but can
165 # be useful for debugging or cleaning out dangling volumes.
166 labels {
167 label = "coder.workspace_name_at_creation"
168 value = data.coder_workspace.me.name
169 }
170}
171
172resource "docker_image" "main" {
173 name = "coder-${data.coder_workspace.me.id}"
174 build {
175 context = "./build"
176 build_args = {
177 USER = local.username
178 }
179 }
180 triggers = {
181 dir_sha1 = sha1(join("", [for f in fileset(path.module, "build/*") : filesha1(f)]))
182 }
183}
184
185resource "docker_container" "workspace" {
186 count = data.coder_workspace.me.start_count
187 image = docker_image.main.name
188 # Uses lower() to avoid Docker restriction on container names.
189 name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
190 # Hostname makes the shell more user friendly: coder@my-workspace:~$
191 hostname = data.coder_workspace.me.name
192 # Use the docker gateway if the access URL is 127.0.0.1
193 entrypoint = ["sh", "-c", replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")]
194 env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"]
195 host {
196 host = "host.docker.internal"
197 ip = "host-gateway"
198 }
199 volumes {
200 container_path = "/home/${local.username}"
201 volume_name = docker_volume.home_volume.name
202 read_only = false
203 }
204
205 # Add labels in Docker to keep track of orphan resources.
206 labels {
207 label = "coder.owner"
208 value = data.coder_workspace_owner.me.name
209 }
210 labels {
211 label = "coder.owner_id"
212 value = data.coder_workspace_owner.me.id
213 }
214 labels {
215 label = "coder.workspace_id"
216 value = data.coder_workspace.me.id
217 }
218 labels {
219 label = "coder.workspace_name"
220 value = data.coder_workspace.me.name
221 }
222}
223