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