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