Back to Modules
code-server

code-server

By coder

VS Code in the browser

474K installs
View on GitHub (link opens in new tab)

Automatically install code-server in a workspace, create an app to access it via the dashboard, install extensions, and pre-configure editor settings.

module "code-server" {
  count    = data.coder_workspace.me.start_count
  source   = "registry.coder.com/modules/code-server/coder"
  version  = "1.1.0"
  agent_id = coder_agent.example.id
}

Screenshot 1

Examples

Pin Versions

module "code-server" {
  count           = data.coder_workspace.me.start_count
  source          = "registry.coder.com/modules/code-server/coder"
  version         = "1.1.0"
  agent_id        = coder_agent.example.id
  install_version = "4.8.3"
}

Pre-install Extensions

Install the Dracula theme from OpenVSX:

module "code-server" {
  count    = data.coder_workspace.me.start_count
  source   = "registry.coder.com/modules/code-server/coder"
  version  = "1.1.0"
  agent_id = coder_agent.example.id
  extensions = [
    "dracula-theme.theme-dracula"
  ]
}

Enter the <author>.<name> into the extensions array and code-server will automatically install on start.

Pre-configure Settings

Configure VS Code's settings.json file:

module "code-server" {
  count      = data.coder_workspace.me.start_count
  source     = "registry.coder.com/modules/code-server/coder"
  version    = "1.1.0"
  agent_id   = coder_agent.example.id
  extensions = ["dracula-theme.theme-dracula"]
  settings = {
    "workbench.colorTheme" = "Dracula"
  }
}

Install multiple extensions

Just run code-server in the background, don't fetch it from GitHub:

module "code-server" {
  count      = data.coder_workspace.me.start_count
  source     = "registry.coder.com/modules/code-server/coder"
  version    = "1.1.0"
  agent_id   = coder_agent.example.id
  extensions = ["dracula-theme.theme-dracula", "ms-azuretools.vscode-docker"]
}

Offline and Use Cached Modes

By default the module looks for code-server at /tmp/code-server but this can be changed with install_prefix.

Run an existing copy of code-server if found, otherwise download from GitHub:

module "code-server" {
  count      = data.coder_workspace.me.start_count
  source     = "registry.coder.com/modules/code-server/coder"
  version    = "1.1.0"
  agent_id   = coder_agent.example.id
  use_cached = true
  extensions = ["dracula-theme.theme-dracula", "ms-azuretools.vscode-docker"]
}

Just run code-server in the background, don't fetch it from GitHub:

module "code-server" {
  count    = data.coder_workspace.me.start_count
  source   = "registry.coder.com/modules/code-server/coder"
  version  = "1.1.0"
  agent_id = coder_agent.example.id
  offline  = true
}
1terraform {
2  required_version = ">= 1.0"
3
4  required_providers {
5    coder = {
6      source  = "coder/coder"
7      version = ">= 2.1"
8    }
9  }
10}
11
12variable "agent_id" {
13  type        = string
14  description = "The ID of a Coder agent."
15}
16
17variable "extensions" {
18  type        = list(string)
19  description = "A list of extensions to install."
20  default     = []
21}
22
23variable "port" {
24  type        = number
25  description = "The port to run code-server on."
26  default     = 13337
27}
28
29variable "display_name" {
30  type        = string
31  description = "The display name for the code-server application."
32  default     = "code-server"
33}
34
35variable "slug" {
36  type        = string
37  description = "The slug for the code-server application."
38  default     = "code-server"
39}
40
41variable "settings" {
42  type        = any
43  description = "A map of settings to apply to code-server."
44  default     = {}
45}
46
47variable "folder" {
48  type        = string
49  description = "The folder to open in code-server."
50  default     = ""
51}
52
53variable "install_prefix" {
54  type        = string
55  description = "The prefix to install code-server to."
56  default     = "/tmp/code-server"
57}
58
59variable "log_path" {
60  type        = string
61  description = "The path to log code-server to."
62  default     = "/tmp/code-server.log"
63}
64
65variable "install_version" {
66  type        = string
67  description = "The version of code-server to install."
68  default     = ""
69}
70
71variable "share" {
72  type    = string
73  default = "owner"
74  validation {
75    condition     = var.share == "owner" || var.share == "authenticated" || var.share == "public"
76    error_message = "Incorrect value. Please set either 'owner', 'authenticated', or 'public'."
77  }
78}
79
80variable "order" {
81  type        = number
82  description = "The order determines the position of app in the UI presentation. The lowest order is shown first and apps with equal order are sorted by name (ascending order)."
83  default     = null
84}
85
86variable "offline" {
87  type        = bool
88  description = "Just run code-server in the background, don't fetch it from GitHub"
89  default     = false
90}
91
92variable "use_cached" {
93  type        = bool
94  description = "Uses cached copy code-server in the background, otherwise fetched it from GitHub"
95  default     = false
96}
97
98variable "use_cached_extensions" {
99  type        = bool
100  description = "Uses cached copy of extensions, otherwise do a forced upgrade"
101  default     = false
102}
103
104variable "extensions_dir" {
105  type        = string
106  description = "Override the directory to store extensions in."
107  default     = ""
108}
109
110variable "auto_install_extensions" {
111  type        = bool
112  description = "Automatically install recommended extensions when code-server starts."
113  default     = false
114}
115
116variable "subdomain" {
117  type        = bool
118  description = <<-EOT
119    Determines whether the app will be accessed via it's own subdomain or whether it will be accessed via a path on Coder.
120    If wildcards have not been setup by the administrator then apps with "subdomain" set to true will not be accessible.
121  EOT
122  default     = false
123}
124
125variable "open_in" {
126  type        = string
127  description = <<-EOT
128    Determines where the app will be opened. Valid values are `"tab"` and `"slim-window" (default)`.
129    `"tab"` opens in a new tab in the same browser window.
130    `"slim-window"` opens a new browser window without navigation controls.
131  EOT
132  default     = "slim-window"
133  validation {
134    condition     = contains(["tab", "slim-window"], var.open_in)
135    error_message = "The 'open_in' variable must be one of: 'tab', 'slim-window'."
136  }
137}
138
139resource "coder_script" "code-server" {
140  agent_id     = var.agent_id
141  display_name = "code-server"
142  icon         = "/icon/code.svg"
143  script = templatefile("${path.module}/run.sh", {
144    VERSION : var.install_version,
145    EXTENSIONS : join(",", var.extensions),
146    APP_NAME : var.display_name,
147    PORT : var.port,
148    LOG_PATH : var.log_path,
149    INSTALL_PREFIX : var.install_prefix,
150    // This is necessary otherwise the quotes are stripped!
151    SETTINGS : replace(jsonencode(var.settings), "\"", "\\\""),
152    OFFLINE : var.offline,
153    USE_CACHED : var.use_cached,
154    USE_CACHED_EXTENSIONS : var.use_cached_extensions,
155    EXTENSIONS_DIR : var.extensions_dir,
156    FOLDER : var.folder,
157    AUTO_INSTALL_EXTENSIONS : var.auto_install_extensions,
158  })
159  run_on_start = true
160
161  lifecycle {
162    precondition {
163      condition     = !var.offline || length(var.extensions) == 0
164      error_message = "Offline mode does not allow extensions to be installed"
165    }
166
167    precondition {
168      condition     = !var.offline || !var.use_cached
169      error_message = "Offline and Use Cached can not be used together"
170    }
171  }
172}
173
174resource "coder_app" "code-server" {
175  agent_id     = var.agent_id
176  slug         = var.slug
177  display_name = var.display_name
178  url          = "http://localhost:${var.port}/${var.folder != "" ? "?folder=${urlencode(var.folder)}" : ""}"
179  icon         = "/icon/code.svg"
180  subdomain    = var.subdomain
181  share        = var.share
182  order        = var.order
183  open_in      = var.open_in
184
185  healthcheck {
186    url       = "http://localhost:${var.port}/healthz"
187    interval  = 5
188    threshold = 6
189  }
190}
191