# Templates Templates are written in standard Terraform and describe the infrastructure for workspaces (e.g., aws_instance, kubernetes_pod, or both). In most cases, a small group of users (Coder admins) manage templates. Then, other users provision their development workspaces from templates. ## Add a template Before users can create workspaces, you'll need at least one template in Coder. ```sh # create a local directory to store templates mkdir -p $HOME/coder/templates cd $HOME/coder/templates # start from an example coder templates init # optional: modify the template vim /main.tf # add the template to Coder deployment coder templates ``` > See the documentation and source code for each example in the > [examples/](https://github.com/coder/coder/tree/main/examples/templates) > directory in the repo. ## Customize templates Example templates are not designed to support every use (e.g [examples/aws-linux](https://github.com/coder/coder/tree/main/examples/templates/aws-linux) does not support custom VPCs). You can add these features by editing the Terraform code once you run `coder templates init` (new) or `coder templates pull` (existing). - See [Creating and troubleshooting templates](#creating--troubleshooting-templates) for more info ## Concepts in templates While templates are written with standard Terraform, the [Coder Terraform Provider](https://registry.terraform.io/providers/coder/coder/latest/docs) is used to define the workspace lifecycle and establish a connection from resources to Coder. Below is an overview of some key concepts in templates (and workspaces). For all template options, reference [Coder Terraform provider docs](https://registry.terraform.io/providers/coder/coder/latest/docs). ### Resource Resources in Coder are simply [Terraform resources](https://www.terraform.io/language/resources). If a Coder agent is attached to a resource, users can connect directly to the resource over SSH or web apps. ### Coder agent Once a Coder workspace is created, the Coder agent establishes a connection between a resource (docker_container) and Coder, so that a user can connect to their workspace from the web UI or CLI. A template can have multiple agents to allow users to connect to multiple resources in their workspace. > Resources must download and start the Coder agent binary to connect to Coder. > This means the resource must be able to reach your Coder URL. Use the Coder agent's init script to ```hcl data "coder_workspace" "me" { } resource "coder_agent" "pod1" { os = "linux" arch = "amd64" } resource "kubernetes_pod" "pod1" { spec { ... container { command = ["sh", "-c", coder_agent.pod1.init_script] env { name = "CODER_AGENT_TOKEN" value = coder_agent.dev.token } } } } ``` The `coder_agent` resource can be configured as described in the [documentation for the `coder` Terraform provider.](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent) For example, you can use the `env` property to set environment variables that will be inherited by all child processes of the agent, including SSH sessions. #### startup_script Use the Coder agent's `startup_script` to run additional commands like installing IDEs, [cloning dotfiles](./dotfiles.md#templates), and cloning project repos. ```hcl resource "coder_agent" "coder" { os = "linux" arch = "amd64" dir = "/home/coder" startup_script = <> ~/.ssh/known_hosts git clone --progress git@github.com:${var.repo} # use coder CLI to clone and install dotfiles coder dotfiles -y ${var.dotfiles_uri} EOT } ``` ### Parameters Templates often contain _parameters_. These are defined by `variable` blocks in Terraform. There are two types of parameters: - **Admin/template-wide parameters** are set when a template is created/updated. These values are often cloud configuration, such as a `VPC`, and are annotated with `sensitive = true` in the template code. - **User/workspace parameters** are set when a user creates a workspace. These values are often personalization settings such as "preferred region" or "workspace image". The template sample below uses _admin and user parameters_ to allow developers to create workspaces from any image as long as it is in the proper registry: ```hcl variable "image_registry_url" { description = "The image registry developers can select" default = "artifactory1.organization.com" sensitive = true # admin (template-wide) parameter } variable "docker_image_name" { description = "The image your workspace will start from" default = "base_image" sensitive = false # user (workspace) parameter } resource "docker_image" "workspace" { # ... other config name = "${var.image_registry_url}/${var.docker_image_name}" } ``` ### Persistent vs. ephemeral resources You can use the workspace state to ensure some resources in Coder are persistent, while others are ephemeral. #### Start/stop Coder workspaces can be started/stopped. This is often used to save on cloud costs or enforce ephemeral workflows. When a workspace is started or stopped, the Coder server runs an additional [terraform apply](https://www.terraform.io/cli/commands/apply), informing the Coder provider that the workspace has a new transition state. This template sample has one persistent resource (docker volume) and one ephemeral resource (docker image). ```sh data "coder_workspace" "me" { } resource "docker_volume" "home_volume" { # persistent resource (remains a workspace is stopped) count = 1 name = "coder-${data.coder_workspace.me.owner}-${data.coder_workspace.me.name}-root" } resource "docker_container" "workspace" { # ephemeral resource (deleted when workspace is stopped, created when started) count = data.coder_workspace.me.start_count # 0 (stopped), 1 (started) volumes { container_path = "/home/coder/" volume_name = docker_volume.home_volume.name read_only = false } # ... other config } ``` #### Using updated images when rebuilding a workspace To ensure that Coder uses an updated image when rebuilding a workspace, we suggest that admins update the tag in the template (e.g., `my-image:v0.4.2` -> `my-image:v0.4.3`) or digest (`my-image@sha256:[digest]` -> `my-image@sha256:[new_digest]`). Alternatively, if you're willing to wait for longer start times from Coder, you can set the `imagePullPolicy` to `Always` in your Terraform template; when set, Coder will check `image:tag` on every build and update if necessary: ```tf resource "kubernetes_pod" "podName" { spec { container { image_pull_policy = "Always" } } } ``` ### Delete templates You can delete a template using both the coder CLI and UI. Only [template admins and owners](./admin/users.md) can delete a template, and the template must not have any running workspaces associated to it. Using the CLI, login to Coder and run the following command to delete a template: ```console coder templates delete ``` In the UI, navigate to the template you want to delete, and select the dropdown in the right-hand corner of the page to delete the template. ![delete-template](./images/delete-template.png) #### Delete workspaces When a workspace is deleted, the Coder server essentially runs a [terraform destroy](https://www.terraform.io/cli/commands/destroy) to remove all resources associated with the workspace. > Terraform's > [prevent-destroy](https://www.terraform.io/language/meta-arguments/lifecycle#prevent_destroy) > and > [ignore-changes](https://www.terraform.io/language/meta-arguments/lifecycle#ignore_changes) > meta-arguments can be used to accidental data loss. ### Coder apps By default, all templates allow developers to connect over SSH and a web terminal. See [Configuring Web IDEs](./ides/web-ides.md) to learn how to give users access to additional web applications. ### Data source When a workspace is being started or stopped, the `coder_workspace` data source provides some useful parameters. See the [documentation for the `coder` Terraform provider](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace) for more information. For example, the [Docker quick-start template](https://github.com/coder/coder/tree/main/examples/templates/docker) sets a few environment variables based on the username and email address of the workspace's owner, so that you can make Git commits immediately without any manual configuration: ```tf resource "coder_agent" "main" { # ... env = { GIT_AUTHOR_NAME = "${data.coder_workspace.me.owner}" GIT_COMMITTER_NAME = "${data.coder_workspace.me.owner}" GIT_AUTHOR_EMAIL = "${data.coder_workspace.me.owner_email}" GIT_COMMITTER_EMAIL = "${data.coder_workspace.me.owner_email}" } } ``` You can add these environment variable definitions to your own templates, or customize them however you like. ## Creating & troubleshooting templates You can use any Terraform resources or modules with Coder! When working on templates, we recommend you refer to the following resources: - this document - [example templates](https://github.com/coder/coder/tree/main/examples/templates) code - [Coder Terraform provider](https://registry.terraform.io/providers/coder/coder/latest/docs) documentation Occasionally, you may run into scenarios where the agent is not able to connect. This means the start script has failed. ```sh $ coder ssh myworkspace Waiting for [agent] to connect... ``` While troubleshooting steps vary by resource, here are some general best practices: - Ensure the resource has `curl` installed - Ensure the resource can reach your Coder URL - Manually connect to the resource (e.g., `docker exec` or AWS console) - The Coder agent logs are typically stored in `/var/log/coder-agent.log` - The Coder agent startup script logs are typically stored in `/var/log/coder-startup-script.log` ## Change Management We recommend source controlling your templates as you would other code. CI is as simple as running `coder templates push` with the appropriate credentials. ## Next Steps - Learn about [Authentication & Secrets](templates/authentication.md) - Learn about [Workspaces](workspaces.md)