diff --git a/docs/images/templates/coder-login-web.png b/docs/images/templates/coder-login-web.png
index 161ff92a00401..423cc17f06a22 100644
Binary files a/docs/images/templates/coder-login-web.png and b/docs/images/templates/coder-login-web.png differ
diff --git a/docs/images/templates/coder-session-token.png b/docs/images/templates/coder-session-token.png
index f982550901813..571c28ccd0568 100644
Binary files a/docs/images/templates/coder-session-token.png and b/docs/images/templates/coder-session-token.png differ
diff --git a/docs/images/templates/upload-create-template-form.png b/docs/images/templates/upload-create-template-form.png
new file mode 100644
index 0000000000000..e2d038e602bb8
Binary files /dev/null and b/docs/images/templates/upload-create-template-form.png differ
diff --git a/docs/images/templates/upload-create-your-first-template.png b/docs/images/templates/upload-create-your-first-template.png
new file mode 100644
index 0000000000000..858a8533f0c3c
Binary files /dev/null and b/docs/images/templates/upload-create-your-first-template.png differ
diff --git a/docs/images/templates/workspace-apps.png b/docs/images/templates/workspace-apps.png
index cf4f8061899e6..4ace0f542ff4a 100644
Binary files a/docs/images/templates/workspace-apps.png and b/docs/images/templates/workspace-apps.png differ
diff --git a/docs/tutorials/template-from-scratch.md b/docs/tutorials/template-from-scratch.md
index c1a9b556fdae2..3198b622724bf 100644
--- a/docs/tutorials/template-from-scratch.md
+++ b/docs/tutorials/template-from-scratch.md
@@ -1,30 +1,15 @@
-# A guided tour of a template
+# Write a template from scratch
-This guided tour introduces you to the different parts of a Coder template by
-showing you how to create a template from scratch.
+A template is a common configuration that you use to deploy workspaces.
-You'll write a simple template that provisions a workspace as a Docker container
-with Ubuntu.
+This tutorial teaches you how to create a template that provisions a workspace
+as a Docker container with Ubuntu.
## Before you start
-To follow this guide, you'll need:
-
-- A computer or cloud computing instance with both
- [Docker](https://docs.docker.com/get-docker/) and [Coder](../install/index.md)
- installed on it.
-
-> When setting up your computer or computing instance, make sure to install
-> Docker first, then Coder. Otherwise, you'll need to add the `coder` user to
-> the `docker` group.
-
-- The URL for your Coder instance. If you're running Coder locally, the default
- URL is [http://127.0.0.1:3000](http://127.0.0.1:3000).
-
-- A text editor. For this tour, we use [GNU nano](https://nano-editor.org/).
-
-> Haven't written Terraform before? Check out Hashicorp's
-> [Getting Started Guides](https://developer.hashicorp.com/terraform/tutorials).
+You'll need a computer or cloud computing instance with both
+[Docker](https://docs.docker.com/get-docker/) and [Coder](../install/index.md)
+installed on it.
## What's in a template
@@ -36,25 +21,25 @@ Coder can provision all Terraform modules, resources, and properties. The Coder
server essentially runs a `terraform apply` every time a workspace is created,
started, or stopped.
+> Haven't written Terraform before? Check out Hashicorp's
+> [Getting Started Guides](https://developer.hashicorp.com/terraform/tutorials).
+
Here's a simplified diagram that shows the main parts of the template we'll
-create.
+create:

## 1. Create template files
On your local computer, create a directory for your template and create the
-`Dockerfile`.
+`Dockerfile`. You will upload the files to your Coder instance later.
```sh
-mkdir template-tour
-cd template-tour
-mkdir build
-nano build/Dockerfile
+mkdir -p template-tour/build && cd $_
```
-You'll enter a simple `Dockerfile` that starts with the
-[official Ubuntu image](https://hub.docker.com/_/ubuntu/). In the editor, enter
+Enter content into a `Dockerfile` that starts with the
+[official Ubuntu image](https://hub.docker.com/_/ubuntu/). In your editor, enter
and save the following text in `Dockerfile` then exit the editor:
```dockerfile
@@ -72,56 +57,48 @@ RUN useradd --groups sudo --no-create-home --shell /bin/bash ${USER} \
&& chmod 0440 /etc/sudoers.d/${USER}
USER ${USER}
WORKDIR /home/${USER}
-
```
-Notice how `Dockerfile` adds a few things to the parent `ubuntu` image, which
-your template needs later:
+`Dockerfile` adds a few things to the parent `ubuntu` image, which your template
+needs later:
- It installs the `sudo` and `curl` packages.
- It adds a `coder` user, including a home directory.
## 2. Set up template providers
-Now you can edit the Terraform file, which provisions the workspace's resources.
-
-```shell
-nano main.tf
-```
+Edit the Terraform `main.tf` file to provision the workspace's resources.
-We'll start by setting up our providers. At a minimum, we need the `coder`
-provider. For this template, we also need the `docker` provider:
+Start by setting up the providers. At a minimum, we need the `coder` provider.
+For this template, we also need the `docker` provider:
```tf
terraform {
required_providers {
coder = {
source = "coder/coder"
- version = "~> 0.8.3"
}
docker = {
source = "kreuzwerker/docker"
- version = "~> 3.0.1"
}
}
}
-provider "coder" {
+locals {
+ username = data.coder_workspace_owner.me.name
}
-provider "docker" {
+data "coder_provisioner" "me" {
}
-locals {
- username = data.coder_workspace.me.owner
+provider "docker" {
}
-data "coder_provisioner" "me" {
+provider "coder" {
}
data "coder_workspace" "me" {
}
-
```
Notice that the `provider` blocks for `coder` and `docker` are empty. In a more
@@ -132,8 +109,7 @@ The
[`coder_workspace`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace)
data source provides details about the state of a workspace, such as its name,
owner, and so on. The data source also lets us know when a workspace is being
-started or stopped. We'll take advantage of this information in later steps to
-do these things:
+started or stopped. We'll use this information in later steps to:
- Set some environment variables based on the workspace owner.
- Manage ephemeral and persistent storage.
@@ -147,29 +123,27 @@ runs inside the compute aspect of your workspace, typically a VM or container.
In our case, it will run in Docker.
You do not need to have any open ports on the compute aspect, but the agent
-needs `curl` access to the Coder server. Remember that we installed `curl` in
-`Dockerfile`, earlier.
+needs `curl` access to the Coder server.
-This snippet creates the agent:
+Add this snippet after the last closing `}` in `main.tf` to create the agent:
```tf
resource "coder_agent" "main" {
arch = data.coder_provisioner.me.arch
os = "linux"
- startup_script_timeout = 180
startup_script = <<-EOT
set -e
# install and start code-server
- curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server --version 4.11.0
+ curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server
/tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 &
EOT
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}"
+ GIT_AUTHOR_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
+ GIT_AUTHOR_EMAIL = "${data.coder_workspace_owner.me.email}"
+ GIT_COMMITTER_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
+ GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}"
}
metadata {
@@ -188,34 +162,37 @@ resource "coder_agent" "main" {
timeout = 1
}
}
-
```
Because Docker is running locally in the Coder server, there is no need to
-authenticate `coder_agent`. But if your `coder_agent` were running on a remote
-host, your template would need
+authenticate `coder_agent`. But if your `coder_agent` is running on a remote
+host, your template will need
[authentication credentials](../admin/external-auth.md).
This template's agent also runs a startup script, sets environment variables,
and provides metadata.
-The
-[`startup script`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
-installs [code-server](https://coder.com/docs/code-server), a browser-based
-[VS Code](https://code.visualstudio.com/) app that runs in the workspace. We'll
-give users access to code-server through `coder_app`, later.
+- [`startup script`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
-The
-[`env`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#env)
-block sets environments variables for the workspace. We use the data source from
-`coder_workspace` to set the environment variables based on the workspace's
-owner. This way, the owner can make git commits immediately without any manual
-configuration.
+ - Installs [code-server](https://coder.com/docs/code-server), a browser-based
+ [VS Code](https://code.visualstudio.com/) app that runs in the workspace.
+
+ We'll give users access to code-server through `coder_app`, later.
+
+- [`env` block](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#env)
+
+ - Sets environments variables for the workspace.
+
+ We use the data source from `coder_workspace` to set the environment
+ variables based on the workspace's owner. This way, the owner can make git
+ commits immediately without any manual configuration.
+
+- [`metadata`](../admin/templates/extending-templates/agent-metadata.md) blocks
+
+ - Your template can use metadata to show information to the workspace owner
+ Coder displays this metadata in the Coder dashboard.
-Your template can use metadata to show information to the workspace owner. Coder
-displays this metadata in the Coder dashboard. Our template has
-[`metadata`](../admin/templates/extending-templates/agent-metadata.md) blocks
-for CPU and RAM usage.
+ Our template has `metadata` blocks for CPU and RAM usage.
## 4. coder_app
@@ -229,10 +206,9 @@ This is commonly used for
[web IDEs](../user-guides/workspace-access/web-ides.md) such as
[code-server](https://coder.com/docs/code-server), RStudio, and JupyterLab.
-To install and code-server in the workspace, remember that we installed it in
-the `startup_script` argument in `coder_agent`. We make it available from a
-workspace with a `coder_app` resource. See
-[web IDEs](../user-guides/workspace-access/web-ides.md) for more examples.
+We installed code-server in the `startup_script` argument. To add code-server to
+the workspace, make it available in the workspace with a `coder_app` resource.
+See [web IDEs](../user-guides/workspace-access/web-ides.md) for more examples:
```tf
resource "coder_app" "code-server" {
@@ -250,11 +226,10 @@ resource "coder_app" "code-server" {
threshold = 6
}
}
-
```
You can also use a `coder_app` resource to link to external apps, such as links
-to wikis or cloud consoles.
+to wikis or cloud consoles:
```tf
resource "coder_app" "coder-server-doc" {
@@ -264,7 +239,6 @@ resource "coder_app" "coder-server-doc" {
url = "https://coder.com/docs/code-server"
external = true
}
-
```
## 5. Persistent and ephemeral resources
@@ -283,10 +257,9 @@ We do this in 2 parts:
workspace name change, we use an immutable parameter, like
`data.coder_workspace.me.id`.
-You'll see later that we make sure that our Docker container is ephemeral with
-the Terraform
+Later, we use the Terraform
[count](https://developer.hashicorp.com/terraform/language/meta-arguments/count)
-meta-argument.
+meta-argument to make sure that our Docker container is ephemeral.
```tf
resource "docker_volume" "home_volume" {
@@ -296,7 +269,6 @@ resource "docker_volume" "home_volume" {
ignore_changes = all
}
}
-
```
For details, see
@@ -305,7 +277,7 @@ For details, see
## 6. Set up the Docker container
To set up our Docker container, our template has a `docker_image` resource that
-uses `build/Dockerfile`, which we created earlier.
+uses `build/Dockerfile`, which we created earlier:
```tf
resource "docker_image" "main" {
@@ -320,7 +292,6 @@ resource "docker_image" "main" {
dir_sha1 = sha1(join("", [for f in fileset(path.module, "build/*") : filesha1(f)]))
}
}
-
```
Our `docker_container` resource uses `coder_workspace` `start_count` to start
@@ -331,7 +302,7 @@ resource "docker_container" "workspace" {
count = data.coder_workspace.me.start_count
image = docker_image.main.name
# Uses lower() to avoid Docker restriction on container names.
- name = "coder-${data.coder_workspace.me.owner}-${lower(data.coder_workspace.me.name)}"
+ name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
# Hostname makes the shell more user friendly: coder@my-workspace:~$
hostname = data.coder_workspace.me.name
# Use the docker gateway if the access URL is 127.0.0.1
@@ -349,7 +320,6 @@ resource "docker_container" "workspace" {
read_only = false
}
}
-
```
## 7. Create the template in Coder
@@ -359,59 +329,102 @@ Save `main.tf` and exit the editor.
Now that we've created the files for our template, we can add them to our Coder
deployment.
-We can do this with the Coder CLI or the Coder dashboard. For this tour, we'll
+We can do this with the Coder CLI or the Coder dashboard. In this example, we'll
use the Coder CLI.
-First, you'll need to log in to your Coder deployment from the CLI. This is
-where you need the URL for your deployment:
+1. Log in to your Coder deployment from the CLI. This is where you need the URL
+ for your deployment:
-```sh
-$ coder login https://coder.example.com
-Your browser has been opened to visit:
+ ```console
+ $ coder login https://coder.example.com
+ Attempting to authenticate with config URL: 'https://coder.example.com'
+ Open the following in your browser:
- https://coder.example.com/cli-auth
+ https://coder.example.com/cli-auth
-> Paste your token here:
-```
+ > Paste your token here:
+ ```
-In your web browser, enter your credentials:
+1. In your web browser, enter your credentials:
-
+