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_provisioner" "me" {
13}
14
15provider "coder" {
16}
17
18variable "use_kubeconfig" {
19 type = bool
20 description = <<-EOF
21 Use host kubeconfig? (true/false)
22
23 Set this to false if the Coder host is itself running as a Pod on the same
24 Kubernetes cluster as you are deploying workspaces to.
25
26 Set this to true if the Coder host is running outside the Kubernetes cluster
27 for workspaces. A valid "~/.kube/config" must be present on the Coder host.
28 EOF
29 default = false
30}
31
32variable "namespace" {
33 type = string
34 description = "The Kubernetes namespace to create workspaces in (must exist prior to creating workspaces)"
35}
36
37provider "kubernetes" {
38 # Authenticate via ~/.kube/config or a Coder-specific ServiceAccount, depending on admin preferences
39 config_path = var.use_kubeconfig == true ? "~/.kube/config" : null
40}
41
42
43data "coder_workspace" "me" {
44}
45
46resource "coder_agent" "main" {
47 arch = data.coder_provisioner.me.arch
48 os = "linux"
49 startup_script = <<-EOT
50 set -e
51
52 # install and start code-server
53 curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server --version 4.11.0
54 /tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 &
55 EOT
56 dir = "/workspaces"
57
58 # These environment variables allow you to make Git commits right away after creating a
59 # workspace. Note that they take precedence over configuration defined in ~/.gitconfig!
60 # You can remove this block if you'd prefer to configure Git manually or using
61 # dotfiles. (see docs/dotfiles.md)
62 env = {
63 GIT_AUTHOR_NAME = coalesce(data.coder_workspace.me.owner_name, data.coder_workspace.me.owner)
64 GIT_AUTHOR_EMAIL = "${data.coder_workspace.me.owner_email}"
65 GIT_COMMITTER_NAME = coalesce(data.coder_workspace.me.owner_name, data.coder_workspace.me.owner)
66 GIT_COMMITTER_EMAIL = "${data.coder_workspace.me.owner_email}"
67 }
68
69}
70
71resource "coder_app" "code-server" {
72 agent_id = coder_agent.main.id
73 slug = "code-server"
74 display_name = "code-server"
75 url = "http://localhost:13337/?folder=/workspaces"
76 icon = "/icon/code.svg"
77 subdomain = false
78 share = "owner"
79
80 healthcheck {
81 url = "http://localhost:13337/healthz"
82 interval = 5
83 threshold = 6
84 }
85}
86
87resource "kubernetes_persistent_volume_claim" "workspaces" {
88 metadata {
89 name = "coder-${data.coder_workspace.me.id}"
90 namespace = var.namespace
91 labels = {
92 "coder.owner" = data.coder_workspace.me.owner
93 "coder.owner_id" = data.coder_workspace.me.owner_id
94 "coder.workspace_id" = data.coder_workspace.me.id
95 "coder.workspace_name_at_creation" = data.coder_workspace.me.name
96 }
97 }
98 wait_until_bound = false
99 spec {
100 access_modes = ["ReadWriteOnce"]
101 resources {
102 requests = {
103 storage = "10Gi" // adjust as needed
104 }
105 }
106 }
107 lifecycle {
108 ignore_changes = all
109 }
110}
111
112data "coder_parameter" "repo" {
113 name = "repo"
114 display_name = "Repository (auto)"
115 order = 1
116 description = "Select a repository to automatically clone and start working with a devcontainer."
117 mutable = true
118 option {
119 name = "vercel/next.js"
120 description = "The React Framework"
121 value = "https://github.com/vercel/next.js"
122 }
123 option {
124 name = "home-assistant/core"
125 description = "🏡 Open source home automation that puts local control and privacy first."
126 value = "https://github.com/home-assistant/core"
127 }
128 option {
129 name = "discourse/discourse"
130 description = "A platform for community discussion. Free, open, simple."
131 value = "https://github.com/discourse/discourse"
132 }
133 option {
134 name = "denoland/deno"
135 description = "A modern runtime for JavaScript and TypeScript."
136 value = "https://github.com/denoland/deno"
137 }
138 option {
139 name = "microsoft/vscode"
140 icon = "/icon/code.svg"
141 description = "Code editing. Redefined."
142 value = "https://github.com/microsoft/vscode"
143 }
144 option {
145 name = "Custom"
146 icon = "/emojis/1f5c3.png"
147 description = "Specify a custom repo URL below"
148 value = "custom"
149 }
150}
151
152data "coder_parameter" "custom_repo_url" {
153 name = "custom_repo"
154 display_name = "Repository URL (custom)"
155 order = 2
156 default = ""
157 description = "Optionally enter a custom repository URL, see [awesome-devcontainers](https://github.com/manekinekko/awesome-devcontainers)."
158 mutable = true
159}
160
161resource "kubernetes_deployment" "workspace" {
162 metadata {
163 name = "coder-${data.coder_workspace.me.owner}-${lower(data.coder_workspace.me.name)}"
164 namespace = var.namespace
165 labels = {
166 "coder.owner" = data.coder_workspace.me.owner
167 "coder.owner_id" = data.coder_workspace.me.owner_id
168 "coder.workspace_id" = data.coder_workspace.me.id
169 "coder.workspace_name" = data.coder_workspace.me.name
170 }
171 }
172 spec {
173 replicas = data.coder_workspace.me.start_count
174 selector {
175 match_labels = {
176 "coder.workspace_id" = data.coder_workspace.me.id
177 }
178 }
179 strategy {
180 type = "Recreate"
181 }
182 template {
183 metadata {
184 labels = {
185 "coder.workspace_id" = data.coder_workspace.me.id
186 }
187 }
188 spec {
189 container {
190 name = "coder-${data.coder_workspace.me.owner}-${lower(data.coder_workspace.me.name)}"
191 # Find the latest version here:
192 # https://github.com/coder/envbuilder/tags
193 image = "ghcr.io/coder/envbuilder:0.2.1"
194 env {
195 name = "CODER_AGENT_TOKEN"
196 value = coder_agent.main.token
197 }
198 env {
199 name = "CODER_AGENT_URL"
200 value = replace(data.coder_workspace.me.access_url, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")
201 }
202 env {
203 name = "GIT_URL"
204 value = data.coder_parameter.repo.value == "custom" ? data.coder_parameter.custom_repo_url.value : data.coder_parameter.repo.value
205 }
206 env {
207 name = "INIT_SCRIPT"
208 value = replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")
209 }
210 env {
211 name = "FALLBACK_IMAGE"
212 value = "codercom/enterprise-base:ubuntu"
213 }
214 volume_mount {
215 name = "workspaces"
216 mount_path = "/workspaces"
217 }
218 }
219 volume {
220 name = "workspaces"
221 persistent_volume_claim {
222 claim_name = kubernetes_persistent_volume_claim.workspaces.metadata.0.name
223 }
224 }
225 }
226 }
227 }
228}
229