docs: reorganize template docs (#10297)
* docs: rework our "templates" section * wikistuff * fix formatting * add diagram * reorganize some things * docs: improve workspaces and templates doc (#9139) * Reorg, updated/new screenshots, consistent terminology * First pass * Another pass * Added integration section * New outline for template pages, small updates * Revised outline for templates, added tutorial * First pass at tutorial * Some feedback from Ben. * Update docs/workspaces.md Co-authored-by: Muhammad Atif Ali <matifali@live.com> * Update docs/workspaces.md Co-authored-by: Muhammad Atif Ali <matifali@live.com> * Update docs/workspaces.md Co-authored-by: Muhammad Atif Ali <matifali@live.com> * Fixed typos * Expanded tutorial I have read the CLA Document and I hereby sign the CLA * New screenshots, improved tutorial, revised anatomy * Improved tutorial. Anatomy is now a guided tour. * First pass at guided tour * Updated authentication info * Reorganized the guided tour * Edited more template pages * Update docs/templates/tour.md Co-authored-by: Muhammad Atif Ali <matifali@live.com> * Update docs/templates/tour.md Co-authored-by: Muhammad Atif Ali <matifali@live.com> * Update docs/templates/tour.md Co-authored-by: Muhammad Atif Ali <matifali@live.com> * Update docs/templates/tutorial.md Co-authored-by: Muhammad Atif Ali <matifali@live.com> * Update docs/templates/tour.md Co-authored-by: Muhammad Atif Ali <matifali@live.com> * Update docs/templates/tour.md Co-authored-by: Muhammad Atif Ali <matifali@live.com> * Update docs/templates/tour.md Co-authored-by: Muhammad Atif Ali <matifali@live.com> * Update docs/templates/tour.md Co-authored-by: Muhammad Atif Ali <matifali@live.com> * Update docs/templates/tour.md Co-authored-by: Muhammad Atif Ali <matifali@live.com> * Revised devcontainers and docker-in-workspaces * Edited and added screenshots * Prepared first draft, except docs/templates/open-in-coder.md * Fix typo * remove legacy parameters and migration guide * Use coder templates create * Added screenshot for workspace template variables * Made it prettier * Fixed minor typos and markdown problems * edits to repairing workspaces * fix broken links in product * Added troubleshooting, minor corrections. * fix terminal links * fmt --------- Co-authored-by: Muhammad Atif Ali <matifali@live.com> Co-authored-by: Ben Potter <me@bpmct.net> Co-authored-by: Atif Ali <atif@coder.com> * make fmt * fix merge conflict * make fmt * make gen * update * lint * Discard changes to coderd/database/queries.sql.go * Discard changes to cli/templates.go * Discard changes to cli/templateversionarchive.go * Discard changes to cli/templateversions.go * Update docker-in-workspaces.md * replace ```sh with ```shell * open-in-coder * fmt * mention coder_metadata in icons.md * resource_metadata * use shell * modules.md * mention coder registry module * workspace.md * resource_metadata * remove duplication * address comments * cleanup * fmt * fix broken links * fix numbering * mention module registry * add example * demote heading * remove top level entry from manifest * fmt --------- Co-authored-by: Ben <me@bpmct.net> Co-authored-by: Marc Paquette <22124737+marcpaq@users.noreply.github.com>
|
@ -1,4 +1,4 @@
|
|||
# Provisioners
|
||||
# External provisioners
|
||||
|
||||
By default, the Coder server runs
|
||||
[built-in provisioner daemons](../cli/server.md#provisioner-daemons), which
|
||||
|
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 525 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 93 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 140 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 226 KiB |
After Width: | Height: | Size: 170 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 497 KiB |
After Width: | Height: | Size: 110 KiB |
After Width: | Height: | Size: 34 KiB |
|
@ -139,55 +139,86 @@
|
|||
},
|
||||
{
|
||||
"title": "Templates",
|
||||
"description": "Learn about templates, which define the infrastructure underlying workspaces",
|
||||
"description": "Templates define the infrastructure for workspaces",
|
||||
"path": "./templates/index.md",
|
||||
"icon_path": "./images/icons/picture.svg",
|
||||
"children": [
|
||||
{
|
||||
"title": "Resource Persistence",
|
||||
"description": "Learn how resource persistence works in Coder",
|
||||
"path": "./templates/resource-persistence.md",
|
||||
"icon_path": "./images/icons/infinity.svg"
|
||||
"title": "Working with templates",
|
||||
"description": "Creating, editing, and updating templates",
|
||||
"path": "./templates/creating.md"
|
||||
},
|
||||
{
|
||||
"title": "Provider Authentication",
|
||||
"description": "Learn how to authenticate the provisioner",
|
||||
"path": "./templates/authentication.md",
|
||||
"icon_path": "./images/icons/key.svg"
|
||||
"title": "Your first template",
|
||||
"description": "A tutorial for creating and editing your first template",
|
||||
"path": "./templates/tutorial.md"
|
||||
},
|
||||
{
|
||||
"title": "Change Management",
|
||||
"description": "Learn how to source-control templates with git and CI",
|
||||
"path": "./templates/change-management.md",
|
||||
"icon_path": "./images/icons/git.svg"
|
||||
"title": "Guided tour",
|
||||
"description": "Create a template from scratch",
|
||||
"path": "./templates/tour.md"
|
||||
},
|
||||
{
|
||||
"title": "Resource Metadata",
|
||||
"description": "Learn how to expose resource data to users",
|
||||
"path": "./templates/resource-metadata.md",
|
||||
"icon_path": "./images/icons/table-rows.svg"
|
||||
"title": "Setting up templates",
|
||||
"description": "Best practices for writing templates",
|
||||
"path": "./templates/best-practices.md",
|
||||
"children": [
|
||||
{
|
||||
"title": "Change management",
|
||||
"description": "Versioning templates with git and CI",
|
||||
"path": "./templates/change-management.md",
|
||||
"icon_path": "./images/icons/git.svg"
|
||||
},
|
||||
{
|
||||
"title": "Provider authentication",
|
||||
"description": "Authenticate the provisioner",
|
||||
"path": "./templates/authentication.md",
|
||||
"icon_path": "./images/icons/key.svg"
|
||||
},
|
||||
{
|
||||
"title": "Resource persistence",
|
||||
"description": "How resource persistence works in Coder",
|
||||
"path": "./templates/resource-persistence.md",
|
||||
"icon_path": "./images/icons/infinity.svg"
|
||||
},
|
||||
{
|
||||
"title": "Terraform modules",
|
||||
"description": "Reuse code across Coder templates",
|
||||
"path": "./templates/modules.md"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Agent Metadata",
|
||||
"description": "Learn how to expose live agent information to users",
|
||||
"path": "./templates/agent-metadata.md",
|
||||
"icon_path": "./images/icons/table-rows.svg"
|
||||
},
|
||||
{
|
||||
"title": "Parameters",
|
||||
"description": "Use parameters to customize templates",
|
||||
"path": "./templates/parameters.md",
|
||||
"icon_path": "./images/icons/code.svg"
|
||||
"title": "Customizing templates",
|
||||
"description": "Give information and options to workspace users",
|
||||
"path": "./templates/customizing.md",
|
||||
"children": [
|
||||
{
|
||||
"title": "Agent metadata",
|
||||
"description": "Show operational metrics in the workspace",
|
||||
"path": "./templates/agent-metadata.md"
|
||||
},
|
||||
{
|
||||
"title": "Resource metadata",
|
||||
"description": "Show information in the workspace about template resources",
|
||||
"path": "./templates/resource-metadata.md"
|
||||
},
|
||||
{
|
||||
"title": "Parameters",
|
||||
"description": "Prompt the user for additional information about a workspace",
|
||||
"path": "./templates/parameters.md"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Open in Coder",
|
||||
"description": "Learn how to add an \"Open in Coder\" button to your repos",
|
||||
"description": "Add an \"Open in Coder\" button to your repos",
|
||||
"path": "./templates/open-in-coder.md",
|
||||
"icon_path": "./images/icons/key.svg"
|
||||
},
|
||||
{
|
||||
"title": "Docker in Workspaces",
|
||||
"description": "Use docker inside containerized templates",
|
||||
"title": "Docker in workspaces",
|
||||
"description": "Use Docker inside containerized templates",
|
||||
"path": "./templates/docker-in-workspaces.md",
|
||||
"icon_path": "./images/icons/docker.svg"
|
||||
},
|
||||
|
@ -198,9 +229,9 @@
|
|||
"state": "alpha"
|
||||
},
|
||||
{
|
||||
"title": "Terraform Modules",
|
||||
"description": "Reuse code across Coder templates",
|
||||
"path": "./templates/modules.md"
|
||||
"title": "Troubleshooting templates",
|
||||
"description": "Fix common template problems",
|
||||
"path": "./templates/troubleshooting.md"
|
||||
},
|
||||
{
|
||||
"title": "Process Logging",
|
||||
|
@ -337,7 +368,7 @@
|
|||
"icon_path": "./images/icons/scale.svg"
|
||||
},
|
||||
{
|
||||
"title": "Provisioners",
|
||||
"title": "External Provisioners",
|
||||
"description": "Run provisioners isolated from the Coder server",
|
||||
"path": "./admin/provisioners.md",
|
||||
"icon_path": "./images/icons/queue.svg",
|
||||
|
|
|
@ -24,6 +24,10 @@ The admin-level access token is used to provision user tokens and is never expos
|
|||
developers or stored in workspaces.
|
||||
</blockquote>
|
||||
|
||||
<blockquote class="info">
|
||||
You can skip the whole page and use [JFrog module](https://registry.coder.com/modules/jfrog) for easy JFrog Artifactory integration.
|
||||
</blockquote>
|
||||
|
||||
## Provisioner Authentication
|
||||
|
||||
The most straight-forward way to authenticate your template with Artifactory is
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
# Agent Metadata
|
||||
# Agent metadata
|
||||
|
||||
![agent-metadata](../images/agent-metadata.png)
|
||||
|
||||
With Agent Metadata, template admins can expose operational metrics from their
|
||||
workspaces to their users. It is the dynamic complement of
|
||||
[Resource Metadata](./resource-metadata.md).
|
||||
You can show live operational metrics to workspace users with agent metadata. It
|
||||
is the dynamic complement of [resource metadata](./resource-metadata.md).
|
||||
|
||||
See the
|
||||
[Terraform reference](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#metadata).
|
||||
You specify agent metadata in the
|
||||
[`coder_agent`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent).
|
||||
|
||||
## Examples
|
||||
|
||||
|
@ -16,9 +15,10 @@ All of these examples use
|
|||
for the script declaration. With heredoc strings, you can script without messy
|
||||
escape codes, just as if you were working in your terminal.
|
||||
|
||||
Some of the below examples use the [`coder stat`](../cli/stat.md) command. This
|
||||
is useful for determining CPU/memory usage inside a container, which can be
|
||||
tricky otherwise.
|
||||
Some of the examples use the [`coder stat`](../cli/stat.md) command. This is
|
||||
useful for determining CPU and memory usage of the VM or container that the
|
||||
workspace is running in, which is more accurate than resource usage about the
|
||||
workspace's host.
|
||||
|
||||
Here's a standard set of metadata snippets for Linux agents:
|
||||
|
||||
|
@ -86,11 +86,13 @@ resource "coder_agent" "main" {
|
|||
}
|
||||
```
|
||||
|
||||
## Utilities
|
||||
## Useful utilities
|
||||
|
||||
[top](https://linux.die.net/man/1/top) is available in most Linux distributions
|
||||
and provides virtual memory, CPU and IO statistics. Running `top` produces
|
||||
output that looks like:
|
||||
You can also show agent metadata for information about the workspace's host.
|
||||
|
||||
[top](https://manpages.ubuntu.com/manpages/jammy/en/man1/top.1.html) is
|
||||
available in most Linux distributions and provides virtual memory, CPU and IO
|
||||
statistics. Running `top` produces output that looks like:
|
||||
|
||||
```text
|
||||
%Cpu(s): 65.8 us, 4.4 sy, 0.0 ni, 29.3 id, 0.3 wa, 0.0 hi, 0.2 si, 0.0 st
|
||||
|
@ -98,9 +100,9 @@ MiB Mem : 16009.0 total, 493.7 free, 4624.8 used, 10890.5 buff/cache
|
|||
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 11021.3 avail Mem
|
||||
```
|
||||
|
||||
[vmstat](https://linux.die.net/man/8/vmstat) is available in most Linux
|
||||
distributions and provides virtual memory, CPU and IO statistics. Running
|
||||
`vmstat` produces output that looks like:
|
||||
[vmstat](https://manpages.ubuntu.com/manpages/jammy/en/man8/vmstat.8.html) is
|
||||
available in most Linux distributions and provides virtual memory, CPU and IO
|
||||
statistics. Running `vmstat` produces output that looks like:
|
||||
|
||||
```text
|
||||
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
|
||||
|
@ -108,10 +110,10 @@ r b swpd free buff cache si so bi bo in cs us sy id wa st
|
|||
0 0 19580 4781680 12133692 217646944 0 2 4 32 1 0 1 1 98 0 0
|
||||
```
|
||||
|
||||
[dstat](https://linux.die.net/man/1/dstat) is considerably more parseable than
|
||||
`vmstat` but often not included in base images. It is easily installed by most
|
||||
package managers under the name `dstat`. The output of running `dstat 1 1` looks
|
||||
like:
|
||||
[dstat](https://manpages.ubuntu.com/manpages/jammy/man1/dstat.1.html) is
|
||||
considerably more parseable than `vmstat` but often not included in base images.
|
||||
It is easily installed by most package managers under the name `dstat`. The
|
||||
output of running `dstat 1 1` looks like:
|
||||
|
||||
```text
|
||||
--total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--
|
||||
|
@ -119,27 +121,28 @@ usr sys idl wai stl| read writ| recv send| in out | int csw
|
|||
1 1 98 0 0|3422k 25M| 0 0 | 153k 904k| 123k 174k
|
||||
```
|
||||
|
||||
## DB Write Load
|
||||
## Managing the database load
|
||||
|
||||
Agent metadata can generate a significant write load and overwhelm your database
|
||||
if you're not careful. The approximate writes per second can be calculated using
|
||||
the following formula (applied once for each unique metadata interval):
|
||||
Agent metadata can generate a significant write load and overwhelm your Coder
|
||||
database if you're not careful. The approximate writes per second can be
|
||||
calculated using the formula:
|
||||
|
||||
```text
|
||||
num_running_agents * write_multiplier / metadata_interval
|
||||
(metadata_count * num_running_agents * 2) / metadata_avg_interval
|
||||
```
|
||||
|
||||
For example, let's say you have:
|
||||
For example, let's say you have
|
||||
|
||||
- 10 running agents
|
||||
- each with 4 metadata snippets
|
||||
- where two have an interval of 4 seconds, and the other two 6 seconds
|
||||
- each with 6 metadata snippets
|
||||
- with an average interval of 4 seconds
|
||||
|
||||
You can expect at most `(10 * 2 / 4) + (10 * 2 / 6)` or ~8 writes per second.
|
||||
The actual writes per second may be a bit lower due to batching of metadata.
|
||||
Adding more metadata with the same interval will not increase writes per second,
|
||||
but it may still increase database load slightly.
|
||||
You can expect `(10 * 6 * 2) / 4`, or 30 writes per second.
|
||||
|
||||
We use a `write_multiplier` of `2` because each metadata write generates two
|
||||
writes. One of the writes is to the `UNLOGGED` `workspace_agent_metadata` table
|
||||
and the other to the `NOTIFY` query that enables live stats streaming in the UI.
|
||||
One of the writes is to the `UNLOGGED` `workspace_agent_metadata` table and the
|
||||
other to the `NOTIFY` query that enables live stats streaming in the UI.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Resource metadata](./resource-metadata.md)
|
||||
- [Parameters](./parameters.md)
|
||||
|
|
|
@ -7,31 +7,42 @@
|
|||
</p>
|
||||
</blockquote>
|
||||
|
||||
Coder's provisioner process needs to authenticate with cloud provider APIs to
|
||||
provision workspaces. You can either pass credentials to the provisioner as
|
||||
parameters or execute Coder in an environment that is authenticated with the
|
||||
cloud provider.
|
||||
The Coder server's
|
||||
[provisioner](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/provisioner)
|
||||
process needs to authenticate with other provider APIs to provision workspaces.
|
||||
There are two approaches to do this:
|
||||
|
||||
We encourage the latter where supported. This approach simplifies the template,
|
||||
keeps cloud provider credentials out of Coder's database (making it a less
|
||||
valuable target for attackers), and is compatible with agent-based
|
||||
authentication schemes (that handle credential rotation and/or ensure the
|
||||
credentials are not written to disk).
|
||||
- Pass credentials to the provisioner as parameters.
|
||||
- Preferred: Execute the Coder server in an environment that is authenticated
|
||||
with the provider.
|
||||
|
||||
Cloud providers for which the Terraform provider supports authenticated
|
||||
environments include
|
||||
We encourage the latter approach where supported:
|
||||
|
||||
- Simplifies the template.
|
||||
- Keeps provider credentials out of Coder's database, making it a less valuable
|
||||
target for attackers.
|
||||
- Compatible with agent-based authentication schemes, which handle credential
|
||||
rotation or ensure the credentials are not written to disk.
|
||||
|
||||
Generally, you can set up an environment to provide credentials to Coder in
|
||||
these ways:
|
||||
|
||||
- A well-known location on disk. For example, `~/.aws/credentials` for AWS on
|
||||
POSIX systems.
|
||||
- Environment variables.
|
||||
|
||||
It is usually sufficient to authenticate using the CLI or SDK for the provider
|
||||
before running Coder, but check the Terraform provider's documentation for
|
||||
details.
|
||||
|
||||
These platforms have Terraform providers that support authenticated
|
||||
environments:
|
||||
|
||||
- [Google Cloud](https://registry.terraform.io/providers/hashicorp/google/latest/docs)
|
||||
- [Amazon Web Services](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)
|
||||
- [Microsoft Azure](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)
|
||||
- [Kubernetes](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs)
|
||||
|
||||
Additional providers may be supported; check the
|
||||
Other providers might also support authenticated environments. Check the
|
||||
[documentation of the Terraform provider](https://registry.terraform.io/browse/providers)
|
||||
for details.
|
||||
|
||||
The way these generally work is via the credentials being available to Coder
|
||||
either in some well-known location on disk (e.g. `~/.aws/credentials` for AWS on
|
||||
posix systems), or via environment variables. It is usually sufficient to
|
||||
authenticate using the CLI or SDK for the cloud provider before running Coder
|
||||
for this to work, but check the Terraform provider documentation for details.
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# Template best practices
|
||||
|
||||
We recommend a few ways to manage workspace resources, authentication, and
|
||||
versioning.
|
||||
|
||||
<children>
|
||||
</children>
|
|
@ -1,7 +1,7 @@
|
|||
# Template Change Management
|
||||
|
||||
We recommend source controlling your templates as you would other code.
|
||||
[Install Coder](../install/) in CI/CD pipelines to push new template versions.
|
||||
We recommend source-controlling your templates as you would other code. You can
|
||||
[install Coder](../install/) in CI/CD pipelines to push new template versions.
|
||||
|
||||
```console
|
||||
# Install the Coder CLI
|
||||
|
@ -21,14 +21,12 @@ export CODER_TEMPLATE_DIR=.coder/templates/kubernetes
|
|||
export CODER_TEMPLATE_VERSION=$(git rev-parse --short HEAD)
|
||||
|
||||
# Push the new template version to Coder
|
||||
coder login --url $CODER_URL --token $CODER_SESSION_TOKEN
|
||||
coder templates push --yes $CODER_TEMPLATE_NAME \
|
||||
--directory $CODER_TEMPLATE_DIR \
|
||||
--name=$CODER_TEMPLATE_VERSION # Version name is optional
|
||||
```
|
||||
|
||||
> Looking for an example? See how we push our development image and template
|
||||
> [via GitHub actions](https://github.com/coder/coder/blob/main/.github/workflows/dogfood.yaml).
|
||||
|
||||
> To cap token lifetime on creation,
|
||||
> [configure Coder server to set a shorter max token lifetime](../cli/server.md#--max-token-lifetime)
|
||||
To cap token lifetime on creation,
|
||||
[configure Coder server to set a shorter max token lifetime](../cli/server.md#--max-token-lifetime).
|
||||
For an example, see how we push our development image and template
|
||||
[with GitHub actions](https://github.com/coder/coder/blob/main/.github/workflows/dogfood.yaml).
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
# Working with templates
|
||||
|
||||
You create and edit Coder templates as [Terraform](./tour.md) configuration
|
||||
files (`.tf`) and any supporting files, like a README or configuration files for
|
||||
other services.
|
||||
|
||||
## Who creates templates?
|
||||
|
||||
The [Template Admin](../admin/users.md) role (and above) can create templates.
|
||||
End users, like developers, create workspaces from them.
|
||||
|
||||
Templates can also be [managed with git](./change-management.md), allowing any
|
||||
developer to propose changes to a template.
|
||||
|
||||
You can give different users and groups access to templates with
|
||||
[role-based access control](../admin/rbac.md).
|
||||
|
||||
## Starter templates
|
||||
|
||||
We provide starter templates for common cloud providers, like AWS, and
|
||||
orchestrators, like Kubernetes. From there, you can modify them to use your own
|
||||
images, VPC, cloud credentials, and so on. Coder supports all Terraform
|
||||
resources and properties, so fear not if your favorite cloud provider isn't
|
||||
here!
|
||||
|
||||
![Starter templates](../images/templates/starter-templates.png)
|
||||
|
||||
If you prefer to use Coder on the [command line](../cli.md), use
|
||||
`coder templates init`.
|
||||
|
||||
> Coder starter templates are also available on our
|
||||
> [GitHub repo](https://github.com/coder/coder/tree/main/examples/templates).
|
||||
|
||||
## Community Templates
|
||||
|
||||
As well as Coder's starter templates, you can see a list of community templates
|
||||
by our users
|
||||
[here](https://github.com/coder/coder/blob/main/examples/templates/community-templates.md).
|
||||
|
||||
## Editing templates
|
||||
|
||||
Our starter templates are meant to be modified for your use cases. You can edit
|
||||
any template's files directly in the Coder dashboard.
|
||||
|
||||
![Editing a template](../images/templates/choosing-edit-template.gif)
|
||||
|
||||
If you'd prefer to use the CLI, use `coder templates pull`, edit the template
|
||||
files, then `coder templates push`.
|
||||
|
||||
> Even if you are a Terraform expert, we suggest reading our
|
||||
> [guided tour](./tour.md).
|
||||
|
||||
## Updating templates
|
||||
|
||||
Coder tracks a template's versions, keeping all developer workspaces up-to-date.
|
||||
When you publish a new version, developers are notified to get the latest
|
||||
infrastructure, software, or security patches. Learn more about
|
||||
[change management](./change-management.md).
|
||||
|
||||
![Updating a template](../images/templates/update.png)
|
||||
|
||||
## 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.
|
||||
|
||||
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)
|
||||
|
||||
Using the CLI, login to Coder and run the following command to delete a
|
||||
template:
|
||||
|
||||
```shell
|
||||
coder templates delete <template-name>
|
||||
```
|
||||
|
||||
### 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 prevent accidental data loss.
|
||||
|
||||
## Next steps
|
||||
|
||||
- [Your first template](./tutorial.md)
|
|
@ -0,0 +1,6 @@
|
|||
# Customizing templates
|
||||
|
||||
You can give developers more information and control over their workspaces:
|
||||
|
||||
<children>
|
||||
</children>
|
|
@ -2,31 +2,31 @@
|
|||
|
||||
[Devcontainers](https://containers.dev) are an open source specification for
|
||||
defining development environments.
|
||||
|
||||
[envbuilder](https://github.com/coder/envbuilder) is an open source project by
|
||||
Coder that runs devcontainers via Coder templates and your underlying
|
||||
infrastructure.
|
||||
infrastructure. It can run on Docker or Kubernetes.
|
||||
|
||||
There are several benefits to adding a devcontainer-compatible template to
|
||||
Coder:
|
||||
|
||||
- Drop-in migration from Codespaces (or any existing repositories that use
|
||||
devcontainers)
|
||||
- Easier to start projects from Coder (new workspace, pick starter devcontainer)
|
||||
- Easier to start projects from Coder. Just create a new workspace then pick a
|
||||
starter devcontainer.
|
||||
- Developer teams can "bring their own image." No need for platform teams to
|
||||
manage complex images, registries, and CI pipelines.
|
||||
|
||||
## How it works
|
||||
|
||||
- Coder admins add a devcontainer-compatible template to Coder (envbuilder can
|
||||
run on Docker or Kubernetes)
|
||||
A Coder admin adds a devcontainer-compatible template to Coder (envbuilder).
|
||||
Then developers enter their repository URL as a [parameter](./parameters.md)
|
||||
when they create their workspace.
|
||||
[envbuilder](https://github.com/coder/envbuilder) clones the repo and builds a
|
||||
container from the `devcontainer.json` specified in the repo.
|
||||
|
||||
- Developers enter their repository URL as a [parameter](./parameters.md) when
|
||||
they create their workspace. [envbuilder](https://github.com/coder/envbuilder)
|
||||
clones the repo and builds a container from the `devcontainer.json` specified
|
||||
in the repo.
|
||||
|
||||
- Developers can edit the `devcontainer.json` in their workspace to rebuild to
|
||||
iterate on their development environments.
|
||||
Developers can edit the `devcontainer.json` in their workspace to rebuild to
|
||||
iterate on their development environments.
|
||||
|
||||
## Example templates
|
||||
|
||||
|
@ -35,13 +35,13 @@ Coder:
|
|||
|
||||
![Devcontainer parameter screen](../images/templates/devcontainers.png)
|
||||
|
||||
[Parameters](./parameters.md) can be used to prompt the user for a repo URL when
|
||||
they are creating a workspace.
|
||||
Your template can prompt the user for a repo URL with
|
||||
[Parameters](./parameters.md).
|
||||
|
||||
## Authentication
|
||||
|
||||
You may need to authenticate to your container registry (e.g. Artifactory) or
|
||||
git provider (e.g. GitLab) to use envbuilder. Refer to the
|
||||
You may need to authenticate to your container registry, such as Artifactory, or
|
||||
git provider such as GitLab, to use envbuilder. See the
|
||||
[envbuilder documentation](https://github.com/coder/envbuilder/) for more
|
||||
information.
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ There are a few ways to run Docker within container-based Coder workspaces.
|
|||
|
||||
| Method | Description | Limitations |
|
||||
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [Sysbox container runtime](#sysbox-container-runtime) | Install the sysbox runtime on your Kubernetes nodes for secure docker-in-docker and systemd-in-docker. Works with GKE, EKS, AKS. | Requires [compatible nodes](https://github.com/nestybox/sysbox#host-requirements). |
|
||||
| [Sysbox container runtime](#sysbox-container-runtime) | Install the sysbox runtime on your Kubernetes nodes for secure docker-in-docker and systemd-in-docker. Works with GKE, EKS, AKS. | Requires [compatible nodes](https://github.com/nestybox/sysbox#host-requirements). [Limitations](https://github.com/nestybox/sysbox/blob/master/docs/user-guide/limitations.md) |
|
||||
| [Envbox](#envbox) | A container image with all the packages necessary to run an inner sysbox container. Removes the need to setup sysbox-runc on your nodes. Works with GKE, EKS, AKS. | Requires running the outer container as privileged (the inner container that acts as the workspace is locked down). Requires compatible [nodes](https://github.com/nestybox/sysbox/blob/master/docs/distro-compat.md#sysbox-distro-compatibility). |
|
||||
| [Rootless Podman](#rootless-podman) | Run podman inside Coder workspaces. Does not require a custom runtime or privileged containers. Works with GKE, EKS, AKS, RKE, OpenShift | Requires smarter-device-manager for FUSE mounts. [See all](https://github.com/containers/podman/blob/main/rootless.md#shortcomings-of-rootless-podman) |
|
||||
| [Privileged docker sidecar](#privileged-sidecar-container) | Run docker as a privileged sidecar container. | Requires a privileged container. Workspaces can break out to root on the host machine. |
|
||||
|
@ -18,10 +18,6 @@ from the workspace containers. Sysbox requires a
|
|||
to implement these security features. Sysbox can also be used to run systemd
|
||||
inside Coder workspaces. See [Systemd in Docker](#systemd-in-docker).
|
||||
|
||||
The Sysbox container runtime is not compatible with our
|
||||
[workspace process logging](./process-logging.md) feature. Envbox is compatible
|
||||
with process logging, however.
|
||||
|
||||
### Use Sysbox in Docker-based templates
|
||||
|
||||
After [installing Sysbox](https://github.com/nestybox/sysbox#installation) on
|
||||
|
@ -197,8 +193,7 @@ env {
|
|||
compatible with OCI containers specification. which can run rootless inside
|
||||
Kubernetes pods. No custom RuntimeClass is required.
|
||||
|
||||
Prior to completing the steps below, please review the following Podman
|
||||
documentation:
|
||||
Before using Podman, please review the following documentation:
|
||||
|
||||
- [Basic setup and use of Podman in a rootless environment](https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md)
|
||||
|
||||
|
@ -256,7 +251,7 @@ documentation:
|
|||
> Otherwise, your nodes may drop the labels and break podman functionality.
|
||||
|
||||
3. For systems running SELinux (typically Fedora-, CentOS-, and Red Hat-based
|
||||
systems), you may need to disable SELinux or set it to permissive mode.
|
||||
systems), you might need to disable SELinux or set it to permissive mode.
|
||||
|
||||
4. Import our
|
||||
[kubernetes-with-podman](https://github.com/coder/coder/tree/main/examples/templates/kubernetes-with-podman)
|
||||
|
|
|
@ -20,6 +20,7 @@ come bundled with your Coder deployment.
|
|||
[`option`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/parameter#nested-schema-for-option)
|
||||
blocks
|
||||
- [`coder_script`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/script#icon)
|
||||
- [`coder_metadata`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/metadata#icon)
|
||||
|
||||
These can all be configured to use an icon by setting the `icon` field.
|
||||
|
||||
|
|
|
@ -1,633 +1,8 @@
|
|||
# Templates
|
||||
|
||||
Templates are written in [Terraform](https://www.terraform.io/) and describe the
|
||||
infrastructure for workspaces (e.g., docker_container, aws_instance,
|
||||
kubernetes_pod).
|
||||
Templates define the underlying infrastructure that Coder
|
||||
[workspaces](../workspaces.md) run on. All workspaces are created from
|
||||
templates.
|
||||
|
||||
In most cases, a small group of users (team leads or Coder administrators)
|
||||
[have permissions](../admin/users.md#roles) to create and manage templates.
|
||||
Then, other users provision their [workspaces](../workspaces.md) from templates
|
||||
using the UI or CLI.
|
||||
|
||||
## Get the CLI
|
||||
|
||||
The CLI and the server are the same binary. We did this to encourage virality so
|
||||
individuals can start their own Coder deployments.
|
||||
|
||||
From your local machine, download the CLI for your operating system from the
|
||||
[releases](https://github.com/coder/coder/releases/latest) or run:
|
||||
|
||||
```shell
|
||||
curl -fsSL https://coder.com/install.sh | sh
|
||||
```
|
||||
|
||||
To see the sub-commands for managing templates, run:
|
||||
|
||||
```shell
|
||||
coder templates --help
|
||||
```
|
||||
|
||||
## Login to your Coder Deployment
|
||||
|
||||
Before you can create templates, you must first login to your Coder deployment
|
||||
with the CLI.
|
||||
|
||||
```shell
|
||||
coder login https://coder.example.com # aka the URL to your coder instance
|
||||
```
|
||||
|
||||
This will open a browser and ask you to authenticate to your Coder deployment,
|
||||
returning an API Key.
|
||||
|
||||
> Make a note of the API Key. You can re-use the API Key in future CLI logins or
|
||||
> sessions.
|
||||
|
||||
```shell
|
||||
coder --token <your-api-key> login https://coder.example.com/ # aka the URL to your coder instance
|
||||
```
|
||||
|
||||
## Add a template
|
||||
|
||||
Before users can create workspaces, you'll need at least one template in Coder.
|
||||
|
||||
```shell
|
||||
# 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 <template-name>/main.tf
|
||||
|
||||
# add the template to Coder deployment
|
||||
coder templates create <template-name>
|
||||
```
|
||||
|
||||
> See the documentation and source code for each example as well as community
|
||||
> templates in the
|
||||
> [examples/](https://github.com/coder/coder/tree/main/examples/templates)
|
||||
> directory in the repo.
|
||||
|
||||
## Configure Max Workspace Autostop
|
||||
|
||||
To control cost, specify a maximum time to live flag for a template in hours or
|
||||
minutes.
|
||||
|
||||
```shell
|
||||
coder templates create my-template --default-ttl 4h
|
||||
```
|
||||
|
||||
## 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).
|
||||
|
||||
Refer to the following resources to build your own templates:
|
||||
|
||||
- Terraform: [Documentation](https://developer.hashicorp.com/terraform/docs) and
|
||||
[Registry](https://registry.terraform.io)
|
||||
- Common [concepts in templates](#concepts-in-templates) and
|
||||
[Coder Terraform provider](https://registry.terraform.io/providers/coder/coder/latest/docs)
|
||||
- [Coder example templates](https://github.com/coder/coder/tree/main/examples/templates)
|
||||
code
|
||||
|
||||
## 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.
|
||||
|
||||
```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 with additional arguments. 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. See
|
||||
the
|
||||
[Coder Terraform Provider documentation](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent)
|
||||
for the full list of supported arguments for the `coder_agent`.
|
||||
|
||||
#### `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.
|
||||
|
||||
**Note:** By default, the startup script is executed in the background. This
|
||||
allows users to access the workspace before the script completes. If you want to
|
||||
change this, see [`startup_script_behavior`](#startup_script_behavior) below.
|
||||
|
||||
Here are a few guidelines for writing a good startup script (more on these
|
||||
below):
|
||||
|
||||
1. Use `set -e` to exit the script if any command fails and `|| true` for
|
||||
commands that are allowed to fail
|
||||
2. Use `&` to start a process in the background, allowing the startup script to
|
||||
complete
|
||||
3. Inform the user about what's going on via `echo`
|
||||
|
||||
```hcl
|
||||
resource "coder_agent" "coder" {
|
||||
os = "linux"
|
||||
arch = "amd64"
|
||||
dir = "/home/coder"
|
||||
startup_script = <<EOT
|
||||
#!/bin/bash
|
||||
|
||||
# Install code-server 4.8.3 under /tmp/code-server using the "standalone" installation
|
||||
# that does not require root permissions. Note that /tmp may be mounted in tmpfs which
|
||||
# can lead to increased RAM usage. To avoid this, you can pre-install code-server inside
|
||||
# the Docker image or VM image.
|
||||
echo "Installing code-server..."
|
||||
curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server --version 4.8.3
|
||||
|
||||
# The & prevents the startup_script from blocking so the next commands can run.
|
||||
# The stdout and stderr of code-server is redirected to /tmp/code-server.log.
|
||||
echo "Starting code-server..."
|
||||
/tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 &
|
||||
|
||||
# Notice: var.repo and var.dotfiles_uri are specified elsewhere in the Terraform
|
||||
# code as input variables.
|
||||
REPO=${var.repo}
|
||||
DOTFILES_URI=${var.dotfiles_uri}
|
||||
|
||||
# clone repo
|
||||
ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts
|
||||
echo "Cloning $REPO..."
|
||||
git clone --progress git@github.com:"$REPO"
|
||||
|
||||
# use coder CLI to clone and install dotfiles
|
||||
echo "Cloning dotfiles..."
|
||||
coder dotfiles -y "$DOTFILES_URI"
|
||||
EOT
|
||||
}
|
||||
```
|
||||
|
||||
The startup script can contain important steps that must be executed
|
||||
successfully so that the workspace is in a usable state, for this reason we
|
||||
recommend using `set -e` (exit on error) at the top and `|| true` (allow command
|
||||
to fail) to ensure the user is notified when something goes wrong. These are not
|
||||
shown in the example above because, while useful, they need to be used with
|
||||
care. For more assurance, you can utilize
|
||||
[shellcheck](https://www.shellcheck.net) to find bugs in the script and employ
|
||||
[`set -euo pipefail`](https://wizardzines.com/comics/bash-errors/) to exit on
|
||||
error, unset variables, and fail on pipe errors.
|
||||
|
||||
We also recommend that startup scripts do not run forever. Long-running
|
||||
processes, like code-server, should be run in the background. This is usually
|
||||
achieved by adding `&` to the end of the command. For example, `sleep 10 &` will
|
||||
run the command in the background and allow the startup script to complete.
|
||||
|
||||
> **Note:** If a backgrounded command (`&`) writes to stdout or stderr, the
|
||||
> startup script will not complete until the command completes or closes the
|
||||
> file descriptors. To avoid this, you can redirect the stdout and stderr to a
|
||||
> file. For example, `sleep 10 >/dev/null 2>&1 &` will redirect the stdout and
|
||||
> stderr to `/dev/null` (discard) and run the command in the background.
|
||||
|
||||
PS. Notice how each step starts with `echo "..."` to provide feedback to the
|
||||
user about what is happening? This is especially useful when the startup script
|
||||
behavior is set to blocking because the user will be informed about why they're
|
||||
waiting to access their workspace.
|
||||
|
||||
#### `startup_script_behavior`
|
||||
|
||||
Use the Coder agent's `startup_script_behavior` to change the behavior between
|
||||
`blocking` and `non-blocking` (default). The blocking behavior is recommended
|
||||
for most use cases because it allows the startup script to complete before the
|
||||
user accesses the workspace. For example, let's say you want to check out a very
|
||||
large repo in the startup script. If the startup script is non-blocking, the
|
||||
user may log in via SSH or open the IDE before the repo is fully checked out.
|
||||
This can lead to a poor user experience.
|
||||
|
||||
```hcl
|
||||
resource "coder_agent" "coder" {
|
||||
os = "linux"
|
||||
arch = "amd64"
|
||||
startup_script_behavior = "blocking"
|
||||
startup_script = "echo 'Starting...'"
|
||||
```
|
||||
|
||||
Whichever behavior is enabled, the user can still choose to override it by
|
||||
specifying the appropriate flags (or environment variables) in the CLI when
|
||||
connecting to the workspace. The behavior can be overridden by one of the
|
||||
following means:
|
||||
|
||||
- Set an environment variable (for use with `ssh` or `coder ssh`):
|
||||
- `export CODER_SSH_WAIT=yes` (blocking)
|
||||
- `export CODER_SSH_WAIT=no` (non-blocking)
|
||||
- Use a flag with `coder ssh`:
|
||||
- `coder ssh --wait=yes my-workspace` (blocking)
|
||||
- `coder ssh --wait=no my-workspace` (non-blocking)
|
||||
- Use a flag to configure all future `ssh` connections:
|
||||
- `coder config-ssh --wait=yes` (blocking)
|
||||
- `coder config-ssh --wait=no` (non-blocking)
|
||||
|
||||
### Start/stop
|
||||
|
||||
[Learn about resource persistence in Coder](./resource-persistence.md)
|
||||
|
||||
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 container).
|
||||
|
||||
```hcl
|
||||
data "coder_workspace" "me" {
|
||||
}
|
||||
|
||||
resource "docker_volume" "home_volume" {
|
||||
# persistent resource (remains a workspace is stopped)
|
||||
count = 1
|
||||
name = "coder-${data.coder_workspace.me.id}-home"
|
||||
lifecycle {
|
||||
ignore_changes = all
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
|
||||
```hcl
|
||||
resource "kubernetes_pod" "podName" {
|
||||
spec {
|
||||
container {
|
||||
image_pull_policy = "Always"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Edit templates
|
||||
|
||||
You can edit a template using the coder CLI or the UI. Only
|
||||
[template admins and owners](../admin/users.md) can edit a template.
|
||||
|
||||
Using the UI, navigate to the template page, click on the menu, and select "Edit
|
||||
files". In the template editor, you create, edit and remove files. Before
|
||||
publishing a new template version, you can test your modifications by clicking
|
||||
the "Build template" button. Newly published template versions automatically
|
||||
become the default version selection when creating a workspace.
|
||||
|
||||
> **Tip**: Even without publishing a version as active, you can still use it to
|
||||
> create a workspace before making it the default for everybody in your
|
||||
> organization. This may help you debug new changes without impacting others.
|
||||
|
||||
Using the CLI, login to Coder and run the following command to edit a single
|
||||
template:
|
||||
|
||||
```shell
|
||||
coder templates edit <template-name> --description "This is my template"
|
||||
```
|
||||
|
||||
Review editable template properties by running `coder templates edit -h`.
|
||||
|
||||
Alternatively, you can pull down the template as a tape archive (`.tar`) to your
|
||||
current directory:
|
||||
|
||||
```shell
|
||||
coder templates pull <template-name> file.tar
|
||||
```
|
||||
|
||||
Then, extract it by running:
|
||||
|
||||
```shell
|
||||
tar -xf file.tar
|
||||
```
|
||||
|
||||
Make the changes to your template then run this command from the root of the
|
||||
template folder:
|
||||
|
||||
```shell
|
||||
coder templates push <template-name>
|
||||
```
|
||||
|
||||
Your updated template will now be available. Outdated workspaces will have a
|
||||
prompt in the dashboard to update.
|
||||
|
||||
### 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:
|
||||
|
||||
```shell
|
||||
coder templates delete <template-name>
|
||||
```
|
||||
|
||||
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 prevent 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.
|
||||
|
||||
Template administrators can hide apps like the web-based Terminal or VS Code
|
||||
Desktop with the
|
||||
[`display_apps`](https://registry.terraform.io/providers/coder/coder/0.11.2/docs/resources/agent#display_apps)
|
||||
configuration in the
|
||||
[`coder_agent`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent)
|
||||
resource. For example, the following configuration block will hide all default
|
||||
Coder apps except the web terminal.
|
||||
|
||||
```hcl
|
||||
display_apps {
|
||||
vscode = false
|
||||
vscode_insiders = false
|
||||
ssh_helper = false
|
||||
port_forwarding_helper = false
|
||||
web_terminal = true
|
||||
}
|
||||
```
|
||||
|
||||
Example use cases for `display_apps` are JetBrains users or zero-trust
|
||||
deployments who do not want nor should have access to a local VS Code IDE.
|
||||
|
||||
![display-apps](../images/display-apps.png)
|
||||
|
||||
### Data source
|
||||
|
||||
When a workspace is being started or stopped, the `coder_workspace` data source
|
||||
provides some useful parameters. See 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:
|
||||
|
||||
```hcl
|
||||
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.
|
||||
|
||||
## Troubleshooting templates
|
||||
|
||||
Occasionally, you may run into scenarios where a workspace is created, but the
|
||||
agent is either not connected or the
|
||||
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
|
||||
has failed or timed out.
|
||||
|
||||
### Agent connection issues
|
||||
|
||||
If the agent is not connected, it means the agent or
|
||||
[init script](https://github.com/coder/coder/tree/main/provisionersdk/scripts)
|
||||
has failed on the resource.
|
||||
|
||||
```console
|
||||
$ coder ssh myworkspace
|
||||
⢄⡱ Waiting for connection from [agent]...
|
||||
```
|
||||
|
||||
While troubleshooting steps vary by resource, here are some general best
|
||||
practices:
|
||||
|
||||
- Ensure the resource has `curl` installed (alternatively, `wget` or `busybox`)
|
||||
- Ensure the resource can `curl` your Coder
|
||||
[access URL](../admin/configure.md#access-url)
|
||||
- Manually connect to the resource and check the agent logs (e.g.,
|
||||
`kubectl exec`, `docker exec` or AWS console)
|
||||
- The Coder agent logs are typically stored in `/tmp/coder-agent.log`
|
||||
- The Coder agent startup script logs are typically stored in
|
||||
`/tmp/coder-startup-script.log`
|
||||
- The Coder agent shutdown script logs are typically stored in
|
||||
`/tmp/coder-shutdown-script.log`
|
||||
- This can also happen if the websockets are not being forwarded correctly when
|
||||
running Coder behind a reverse proxy.
|
||||
[Read our reverse-proxy docs](../admin/configure.md#tls--reverse-proxy)
|
||||
|
||||
### Startup script issues
|
||||
|
||||
Depending on the contents of the
|
||||
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script),
|
||||
and whether or not the
|
||||
[startup script behavior](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script_behavior)
|
||||
is set to blocking or non-blocking, you may notice issues related to the startup
|
||||
script. In this section we will cover common scenarios and how to resolve them.
|
||||
|
||||
#### Unable to access workspace, startup script is still running
|
||||
|
||||
If you're trying to access your workspace and are unable to because the
|
||||
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
|
||||
is still running, it means the
|
||||
[startup script behavior](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script_behavior)
|
||||
option is set to blocking or you have enabled the `--wait=yes` option (for e.g.
|
||||
`coder ssh` or `coder config-ssh`). In such an event, you can always access the
|
||||
workspace by using the web terminal, or via SSH using the `--wait=no` option. If
|
||||
the startup script is running longer than it should, or never completing, you
|
||||
can try to [debug the startup script](#debugging-the-startup-script) to resolve
|
||||
the issue. Alternatively, you can try to force the startup script to exit by
|
||||
terminating processes started by it or terminating the startup script itself (on
|
||||
Linux, `ps` and `kill` are useful tools).
|
||||
|
||||
For tips on how to write a startup script that doesn't run forever, see the
|
||||
[`startup_script`](#startup_script) section. For more ways to override the
|
||||
startup script behavior, see the
|
||||
[`startup_script_behavior`](#startup_script_behavior) section.
|
||||
|
||||
Template authors can also set the
|
||||
[startup script behavior](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script_behavior)
|
||||
option to non-blocking, which will allow users to access the workspace while the
|
||||
startup script is still running. Note that the workspace must be updated after
|
||||
changing this option.
|
||||
|
||||
#### Your workspace may be incomplete
|
||||
|
||||
If you see a warning that your workspace may be incomplete, it means you should
|
||||
be aware that programs, files, or settings may be missing from your workspace.
|
||||
This can happen if the
|
||||
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
|
||||
is still running or has exited with a non-zero status (see
|
||||
[startup script error](#startup-script-error)). No action is necessary, but you
|
||||
may want to
|
||||
[start a new shell session](#session-was-started-before-the-startup-script-finished-web-terminal)
|
||||
after it has completed or check the
|
||||
[startup script logs](#debugging-the-startup-script) to see if there are any
|
||||
issues.
|
||||
|
||||
#### Session was started before the startup script finished
|
||||
|
||||
The web terminal may show this message if it was started before the
|
||||
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
|
||||
finished, but the startup script has since finished. This message can safely be
|
||||
dismissed, however, be aware that your preferred shell or dotfiles may not yet
|
||||
be activated for this shell session. You can either start a new session or
|
||||
source your dotfiles manually. Note that starting a new session means that
|
||||
commands running in the terminal will be terminated and you may lose unsaved
|
||||
work.
|
||||
|
||||
Examples for activating your preferred shell or sourcing your dotfiles:
|
||||
|
||||
- `exec zsh -l`
|
||||
- `source ~/.bashrc`
|
||||
|
||||
#### Startup script exited with an error
|
||||
|
||||
When the
|
||||
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
|
||||
exits with an error, it means the last command run by the script failed. When
|
||||
`set -e` is used, this means that any failing command will immediately exit the
|
||||
script and the remaining commands will not be executed. This also means that
|
||||
[your workspace may be incomplete](#your-workspace-may-be-incomplete). If you
|
||||
see this error, you can check the
|
||||
[startup script logs](#debugging-the-startup-script) to figure out what the
|
||||
issue is.
|
||||
|
||||
Common causes for startup script errors:
|
||||
|
||||
- A missing command or file
|
||||
- A command that fails due to missing permissions
|
||||
- Network issues (e.g., unable to reach a server)
|
||||
|
||||
#### Debugging the startup script
|
||||
|
||||
The simplest way to debug the
|
||||
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
|
||||
is to open the workspace in the Coder dashboard and click "Show startup log" (if
|
||||
not already visible). This will show all the output from the script. Another
|
||||
option is to view the log file inside the workspace (usually
|
||||
`/tmp/coder-startup-script.log`). If the logs don't indicate what's going on or
|
||||
going wrong, you can increase verbosity by adding `set -x` to the top of the
|
||||
startup script (note that this will show all commands run and may output
|
||||
sensitive information). Alternatively, you can add `echo` statements to show
|
||||
what's going on.
|
||||
|
||||
Here's a short example of an informative startup script:
|
||||
|
||||
```shell
|
||||
echo "Running startup script..."
|
||||
echo "Run: long-running-command"
|
||||
/path/to/long-running-command
|
||||
status=$?
|
||||
echo "Done: long-running-command, exit status: ${status}"
|
||||
if [ $status -ne 0 ]; then
|
||||
echo "Startup script failed, exiting..."
|
||||
exit $status
|
||||
fi
|
||||
```
|
||||
|
||||
> **Note:** We don't use `set -x` here because we're manually echoing the
|
||||
> commands. This protects against sensitive information being shown in the log.
|
||||
|
||||
This script tells us what command is being run and what the exit status is. If
|
||||
the exit status is non-zero, it means the command failed and we exit the script.
|
||||
Since we are manually checking the exit status here, we don't need `set -e` at
|
||||
the top of the script to exit on error.
|
||||
|
||||
## Template permissions (enterprise)
|
||||
|
||||
Template permissions can be used to give users and groups access to specific
|
||||
templates. [Learn more about RBAC](../admin/rbac.md) to learn how to manage
|
||||
|
||||
## Community Templates
|
||||
|
||||
You can see a list of community templates by our users
|
||||
[here](https://github.com/coder/coder/blob/main/examples/templates/community-templates.md).
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Learn about [Authentication & Secrets](./authentication.md)
|
||||
- Learn about [Change Management](./change-management.md)
|
||||
- Learn about [Resource Metadata](./resource-metadata.md)
|
||||
- Learn about [Workspaces](../workspaces.md)
|
||||
<children>
|
||||
</children>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# Template inheritance
|
||||
# Reusing template code
|
||||
|
||||
In instances where you want to reuse code across different Coder templates, such
|
||||
as common scripts or resource definitions, we suggest using
|
||||
To reuse code across different Coder templates, such as common scripts or
|
||||
resource definitions, we suggest using
|
||||
[Terraform Modules](https://developer.hashicorp.com/terraform/language/modules).
|
||||
|
||||
These modules can be stored externally from Coder, like in a Git repository or a
|
||||
Terraform registry. Below is an example of how to reference a module in your
|
||||
template:
|
||||
You can store these modules externally from your Coder deployment, like in a git
|
||||
repository or a Terraform registry. This example shows how to reference a module
|
||||
from your template:
|
||||
|
||||
```hcl
|
||||
data "coder_workspace" "me" {}
|
||||
|
@ -29,32 +29,32 @@ resource "coder_agent" "dev" {
|
|||
}
|
||||
```
|
||||
|
||||
> Learn more about
|
||||
> [creating modules](https://developer.hashicorp.com/terraform/language/modules)
|
||||
> and
|
||||
> [module sources](https://developer.hashicorp.com/terraform/language/modules/sources)
|
||||
> in the Terraform documentation.
|
||||
Learn more about
|
||||
[creating modules](https://developer.hashicorp.com/terraform/language/modules)
|
||||
and
|
||||
[module sources](https://developer.hashicorp.com/terraform/language/modules/sources)
|
||||
in the Terraform documentation.
|
||||
|
||||
## Git authentication
|
||||
|
||||
If you are importing a module from a private git repository, the Coder server
|
||||
[or provisioner](../admin/provisioners.md) needs git credentials. Since this
|
||||
token will only be used for cloning your repositories with modules, it is best
|
||||
to create a token with limited access to repositories and no extra permissions.
|
||||
If you are importing a module from a private git repository, the Coder server or
|
||||
[provisioner](../admin/provisioners.md) needs git credentials. Since this token
|
||||
will only be used for cloning your repositories with modules, it is best to
|
||||
create a token with access limited to the repository and no extra permissions.
|
||||
In GitHub, you can generate a
|
||||
[fine-grained token](https://docs.github.com/en/rest/overview/permissions-required-for-fine-grained-personal-access-tokens?apiVersion=2022-11-28)
|
||||
with read only access to repos.
|
||||
with read only access to the necessary repos.
|
||||
|
||||
If you are running Coder on a VM, make sure you have `git` installed and the
|
||||
`coder` user has access to the following files
|
||||
If you are running Coder on a VM, make sure that you have `git` installed and
|
||||
the `coder` user has access to the following files:
|
||||
|
||||
```toml
|
||||
```shell
|
||||
# /home/coder/.gitconfig
|
||||
[credential]
|
||||
helper = store
|
||||
```
|
||||
|
||||
```toml
|
||||
```shell
|
||||
# /home/coder/.git-credentials
|
||||
|
||||
# GitHub example:
|
||||
|
@ -68,8 +68,8 @@ a Docker volume mount or Kubernetes secrets.
|
|||
### Passing git credentials in Kubernetes
|
||||
|
||||
First, create a `.gitconfig` and `.git-credentials` file on your local machine.
|
||||
You may want to do this in a temporary directory to avoid conflicting with your
|
||||
own git credentials.
|
||||
You might want to do this in a temporary directory to avoid conflicting with
|
||||
your own git credentials.
|
||||
|
||||
Next, create the secret in Kubernetes. Be sure to do this in the same namespace
|
||||
that Coder is installed in.
|
||||
|
@ -158,3 +158,4 @@ Learn more about
|
|||
[here](https://jfrog.com/help/r/jfrog-artifactory-documentation/terraform-registry).
|
||||
- Configuring the JFrog toolchain inside a workspace
|
||||
[here](../platforms/jfrog.md).
|
||||
- Coder Module Registry [here](https://registry.coder.com/modules)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Open in Coder
|
||||
|
||||
An "Open in Coder" button can be embedded into your git repos or internal wikis
|
||||
to allow developers to quickly launch a new workspace.
|
||||
You can embed an "Open in Coder" button into your git repos or internal wikis to
|
||||
let developers quickly launch a new workspace.
|
||||
|
||||
<video autoplay playsinline loop>
|
||||
<source src="https://github.com/coder/coder/blob/main/docs/images/templates/open-in-coder.mp4?raw=true" type="video/mp4">
|
||||
|
@ -13,112 +13,108 @@ Your browser does not support the video tag.
|
|||
To support any infrastructure and software stack, Coder provides a generic
|
||||
approach for "Open in Coder" flows.
|
||||
|
||||
1. Set up
|
||||
[Git Authentication](../admin/external-auth.md#require-git-authentication-in-templates)
|
||||
in your Coder deployment
|
||||
### 1. Set up git authentication
|
||||
|
||||
1. Modify your template to auto-clone repos:
|
||||
See [External Authentication](../admin/external-auth.md) to set up git
|
||||
authentication in your Coder deployment.
|
||||
|
||||
> The id in the template's `coder_git_auth` data source must match the
|
||||
> `CODER_GITAUTH_0_ID` in the Coder deployment configuration.
|
||||
### 2. Modify your template to auto-clone repos
|
||||
|
||||
- If you want the template to clone a specific git repo
|
||||
The id in the template's `coder_git_auth` data source must match the
|
||||
`CODER_GITAUTH_0_ID` in the Coder deployment configuration.
|
||||
|
||||
```hcl
|
||||
# Require git authentication to use this template
|
||||
data "coder_git_auth" "github" {
|
||||
id = "primary-github"
|
||||
}
|
||||
If you want the template to clone a specific git repo:
|
||||
|
||||
resource "coder_agent" "dev" {
|
||||
# ...
|
||||
dir = "~/coder"
|
||||
startup_script =<<EOF
|
||||
```hcl
|
||||
# Require git authentication to use this template
|
||||
data "coder_git_auth" "github" {
|
||||
id = "primary-github"
|
||||
}
|
||||
|
||||
# Clone repo from GitHub
|
||||
if [ ! -d "coder" ]
|
||||
then
|
||||
git clone https://github.com/coder/coder
|
||||
fi
|
||||
resource "coder_agent" "dev" {
|
||||
# ...
|
||||
dir = "~/coder"
|
||||
startup_script =<<EOF
|
||||
|
||||
EOF
|
||||
}
|
||||
```
|
||||
# Clone repo from GitHub
|
||||
if [ ! -d "coder" ]
|
||||
then
|
||||
git clone https://github.com/coder/coder
|
||||
fi
|
||||
|
||||
> Note: The `dir` attribute can be set in multiple ways, for example:
|
||||
>
|
||||
> - `~/coder`
|
||||
> - `/home/coder/coder`
|
||||
> - `coder` (relative to the home directory)
|
||||
EOF
|
||||
}
|
||||
```
|
||||
|
||||
- If you want the template to support any repository via
|
||||
[parameters](./parameters.md)
|
||||
> Note: The `dir` attribute can be set in multiple ways, for example:
|
||||
>
|
||||
> - `~/coder`
|
||||
> - `/home/coder/coder`
|
||||
> - `coder` (relative to the home directory)
|
||||
|
||||
```hcl
|
||||
# Require git authentication to use this template
|
||||
data "coder_git_auth" "github" {
|
||||
id = "primary-github"
|
||||
}
|
||||
If you want the template to support any repository via
|
||||
[parameters](./parameters.md)
|
||||
|
||||
# Prompt the user for the git repo URL
|
||||
data "coder_parameter" "git_repo" {
|
||||
name = "git_repo"
|
||||
display_name = "Git repository"
|
||||
default = "https://github.com/coder/coder"
|
||||
}
|
||||
```hcl
|
||||
# Require git authentication to use this template
|
||||
data "coder_git_auth" "github" {
|
||||
id = "primary-github"
|
||||
}
|
||||
|
||||
locals {
|
||||
folder_name = try(element(split("/", data.coder_parameter.git_repo.value), length(split("/", data.coder_parameter.git_repo.value)) - 1), "")
|
||||
}
|
||||
# Prompt the user for the git repo URL
|
||||
data "coder_parameter" "git_repo" {
|
||||
name = "git_repo"
|
||||
display_name = "Git repository"
|
||||
default = "https://github.com/coder/coder"
|
||||
}
|
||||
|
||||
resource "coder_agent" "dev" {
|
||||
# ...
|
||||
dir = "~/${local.folder_name}"
|
||||
startup_script =<<EOF
|
||||
locals {
|
||||
folder_name = try(element(split("/", data.coder_parameter.git_repo.value), length(split("/", data.coder_parameter.git_repo.value)) - 1), "")
|
||||
}
|
||||
|
||||
# Clone repo from GitHub
|
||||
if [ ! -d "${local.folder_name}" ]
|
||||
then
|
||||
git clone ${data.coder_parameter.git_repo.value}
|
||||
fi
|
||||
resource "coder_agent" "dev" {
|
||||
# ...
|
||||
dir = "~/${local.folder_name}"
|
||||
startup_script =<<EOF
|
||||
|
||||
EOF
|
||||
}
|
||||
```
|
||||
# Clone repo from GitHub
|
||||
if [ ! -d "${local.folder_name}" ]
|
||||
then
|
||||
git clone ${data.coder_parameter.git_repo.value}
|
||||
fi
|
||||
|
||||
1. Embed the "Open in Coder" button with Markdown
|
||||
EOF
|
||||
}
|
||||
```
|
||||
|
||||
```md
|
||||
[![Open in Coder](https://YOUR_ACCESS_URL/open-in-coder.svg)](https://YOUR_ACCESS_URL/templates/YOUR_TEMPLATE/workspace)
|
||||
```
|
||||
### 3. Embed the "Open in Coder" button with Markdown
|
||||
|
||||
> Be sure to replace `YOUR_ACCESS_URL` with your Coder access url (e.g.
|
||||
> https://coder.example.com) and `YOUR_TEMPLATE` with the name of your
|
||||
> template.
|
||||
```md
|
||||
[![Open in Coder](https://YOUR_ACCESS_URL/open-in-coder.svg)](https://YOUR_ACCESS_URL/templates/YOUR_TEMPLATE/workspace)
|
||||
```
|
||||
|
||||
1. Optional: pre-fill parameter values in the "Create Workspace" page
|
||||
Be sure to replace `YOUR_ACCESS_URL` with your Coder access url (e.g.
|
||||
<https://coder.example.com>) and `YOUR_TEMPLATE` with the name of your template.
|
||||
|
||||
This can be used to pre-fill the git repo URL, disk size, image, etc.
|
||||
### 4. Optional: pre-fill parameter values in the "Create Workspace" page
|
||||
|
||||
```md
|
||||
[![Open in Coder](https://YOUR_ACCESS_URL/open-in-coder.svg)](https://YOUR_ACCESS_URL/templates/YOUR_TEMPLATE/workspace?param.git_repo=https://github.com/coder/slog¶m.home_disk_size%20%28GB%29=20)
|
||||
```
|
||||
This can be used to pre-fill the git repo URL, disk size, image, etc.
|
||||
|
||||
![Pre-filled parameters](../images/templates/pre-filled-parameters.png)
|
||||
```md
|
||||
[![Open in Coder](https://YOUR_ACCESS_URL/open-in-coder.svg)](https://YOUR_ACCESS_URL/templates/YOUR_TEMPLATE/workspace?param.git_repo=https://github.com/coder/slog¶m.home_disk_size%20%28GB%29=20)
|
||||
```
|
||||
|
||||
1. Optional: disable specific parameter fields by including their names as
|
||||
specified in your template in the `disable_params` search params list
|
||||
![Pre-filled parameters](../images/templates/pre-filled-parameters.png)
|
||||
|
||||
```md
|
||||
[![Open in Coder](https://YOUR_ACCESS_URL/open-in-coder.svg)](https://YOUR_ACCESS_URL/templates/YOUR_TEMPLATE/workspace?disable_params=first_parameter,second_parameter)
|
||||
```
|
||||
### 5. Optional: disable specific parameter fields by including their names as
|
||||
|
||||
## Example: Kubernetes
|
||||
specified in your template in the `disable_params` search params list
|
||||
|
||||
```md
|
||||
[![Open in Coder](https://YOUR_ACCESS_URL/open-in-coder.svg)](https://YOUR_ACCESS_URL/templates/YOUR_TEMPLATE/workspace?disable_params=first_parameter,second_parameter)
|
||||
```
|
||||
|
||||
### Example: Kubernetes
|
||||
|
||||
For a full example of the Open in Coder flow in Kubernetes, check out
|
||||
[this example template](https://github.com/bpmct/coder-templates/tree/main/kubernetes-open-in-coder).
|
||||
|
||||
## Devcontainer support
|
||||
|
||||
Devcontainer support is on the roadmap.
|
||||
[Follow along here](https://github.com/coder/coder/issues/5559)
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
# Parameters
|
||||
|
||||
Templates can contain _parameters_, which allow prompting the user for
|
||||
additional information when creating workspaces in both the UI and CLI.
|
||||
A template can prompt the user for additional information when creating
|
||||
workspaces with
|
||||
[_parameters_](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/parameter).
|
||||
|
||||
![Parameters in Create Workspace screen](../images/parameters.png)
|
||||
|
||||
The user can set parameters in the dashboard UI and CLI.
|
||||
|
||||
You'll likely want to hardcode certain template properties for workspaces, such
|
||||
as security group. But you can let developers specify other properties with
|
||||
parameters like instance size, geographical location, repository URL, etc.
|
||||
|
||||
This example lets a developer choose a Docker host for the workspace:
|
||||
|
||||
```hcl
|
||||
data "coder_parameter" "docker_host" {
|
||||
name = "Region"
|
||||
|
@ -33,7 +42,7 @@ data "coder_parameter" "docker_host" {
|
|||
}
|
||||
```
|
||||
|
||||
From there, parameters can be referenced during build-time:
|
||||
From there, a template can refer to a parameter's value:
|
||||
|
||||
```hcl
|
||||
provider "docker" {
|
||||
|
@ -41,21 +50,19 @@ provider "docker" {
|
|||
}
|
||||
```
|
||||
|
||||
> For a complete list of supported parameter properties, see the
|
||||
> [coder_parameter Terraform reference](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/parameter)
|
||||
|
||||
## Types
|
||||
|
||||
The following parameter types are supported: `string`, `list(string)`, `bool`,
|
||||
and `number`.
|
||||
A Coder parameter can have one of these types:
|
||||
|
||||
### List of strings
|
||||
- `string`
|
||||
- `bool`
|
||||
- `number`.
|
||||
- `list(string)`
|
||||
|
||||
List of strings is a specific parameter type, that can't be easily mapped to the
|
||||
default value, which is string type. Parameters with the `list(string)` type
|
||||
must be converted to JSON arrays using
|
||||
To specify a default value for a parameter with the `list(string)` type, use a
|
||||
JSON array and the Terraform
|
||||
[jsonencode](https://developer.hashicorp.com/terraform/language/functions/jsonencode)
|
||||
function.
|
||||
function. For example:
|
||||
|
||||
```hcl
|
||||
data "coder_parameter" "security_groups" {
|
||||
|
@ -74,7 +81,7 @@ data "coder_parameter" "security_groups" {
|
|||
|
||||
## Options
|
||||
|
||||
A _string_ parameter can provide a set of options to limit the choice:
|
||||
A `string` parameter can provide a set of options to limit the user's choices:
|
||||
|
||||
```hcl
|
||||
data "coder_parameter" "docker_host" {
|
||||
|
@ -135,9 +142,8 @@ Example:
|
|||
|
||||
## Required and optional parameters
|
||||
|
||||
A parameter is considered to be _required_ if it doesn't have the `default`
|
||||
property. The user **must** provide a value to this parameter before creating a
|
||||
workspace.
|
||||
A parameter is _required_ if it doesn't have the `default` property. The user
|
||||
**must** provide a value to this parameter before creating a workspace:
|
||||
|
||||
```hcl
|
||||
data "coder_parameter" "account_name" {
|
||||
|
@ -170,30 +176,18 @@ data "coder_parameter" "dotfiles_url" {
|
|||
}
|
||||
```
|
||||
|
||||
Terraform
|
||||
[conditional expressions](https://developer.hashicorp.com/terraform/language/expressions/conditionals)
|
||||
can be used to determine whether the user specified a value for an optional
|
||||
parameter:
|
||||
|
||||
```hcl
|
||||
resource "coder_agent" "main" {
|
||||
# ...
|
||||
startup_script_timeout = 180
|
||||
startup_script = <<-EOT
|
||||
set -e
|
||||
|
||||
echo "The optional parameter value is: ${data.coder_parameter.optional.value == "" ? "[empty]" : data.coder_parameter.optional.value}"
|
||||
|
||||
EOT
|
||||
}
|
||||
```
|
||||
|
||||
## Mutability
|
||||
|
||||
Immutable parameters can be only set before workspace creation, or during update
|
||||
on the first usage to set the initial value for required parameters. The idea is
|
||||
to prevent users from modifying fragile or persistent workspace resources like
|
||||
volumes, regions, etc.:
|
||||
Immutable parameters can only be set in these situations:
|
||||
|
||||
- Creating a workspace for the first time.
|
||||
- Updating a workspace to a new template version. This sets the initial value
|
||||
for required parameters.
|
||||
|
||||
The idea is to prevent users from modifying fragile or persistent workspace
|
||||
resources like volumes, regions, and so on.
|
||||
|
||||
Example:
|
||||
|
||||
```hcl
|
||||
data "coder_parameter" "region" {
|
||||
|
@ -204,19 +198,19 @@ data "coder_parameter" "region" {
|
|||
}
|
||||
```
|
||||
|
||||
It is allowed to modify the mutability state anytime. In case of emergency,
|
||||
template authors can temporarily allow for changing immutable parameters to fix
|
||||
an operational issue, but it is not advised to overuse this opportunity.
|
||||
You can modify a parameter's `mutable` attribute state anytime. In case of
|
||||
emergency, you can temporarily allow for changing immutable parameters to fix an
|
||||
operational issue, but it is not advised to overuse this opportunity.
|
||||
|
||||
## Ephemeral parameters
|
||||
|
||||
Ephemeral parameters are introduced to users in the form of "build options."
|
||||
This functionality can be used to model specific behaviors within a Coder
|
||||
workspace, such as reverting to a previous image, restoring from a volume
|
||||
snapshot, or building a project without utilizing cache.
|
||||
Ephemeral parameters are introduced to users in the form of "build options." Use
|
||||
ephemeral parameters to model specific behaviors in a Coder workspace, such as
|
||||
reverting to a previous image, restoring from a volume snapshot, or building a
|
||||
project without using cache.
|
||||
|
||||
As these parameters are ephemeral in nature, subsequent builds will proceed in
|
||||
the standard manner.
|
||||
Since these parameters are ephemeral in nature, subsequent builds proceed in the
|
||||
standard manner:
|
||||
|
||||
```hcl
|
||||
data "coder_parameter" "force_rebuild" {
|
||||
|
@ -229,17 +223,18 @@ data "coder_parameter" "force_rebuild" {
|
|||
}
|
||||
```
|
||||
|
||||
## Validation
|
||||
## Validating parameters
|
||||
|
||||
Rich parameters support multiple validation modes - min, max, monotonic numbers,
|
||||
and regular expressions.
|
||||
Coder supports rich parameters with multiple validation modes: min, max,
|
||||
monotonic numbers, and regular expressions.
|
||||
|
||||
### Number
|
||||
|
||||
A _number_ parameter can be limited to boundaries - min, max. Additionally, the
|
||||
monotonicity (`increasing` or `decreasing`) between the current parameter value
|
||||
and the new one can be verified too. Monotonicity can be enabled for resources
|
||||
that can't be shrunk without implications, for instance - disk volume size.
|
||||
You can limit a `number` parameter to `min` and `max` boundaries.
|
||||
|
||||
You can also specify its monotonicity as `increasing` or `decreasing` to verify
|
||||
the current and new values. Use the `monotonic` aatribute for resources that
|
||||
can't be shrunk or grown without implications, like disk volume size.
|
||||
|
||||
```hcl
|
||||
data "coder_parameter" "instances" {
|
||||
|
@ -256,9 +251,8 @@ data "coder_parameter" "instances" {
|
|||
|
||||
### String
|
||||
|
||||
A _string_ parameter can have a regular expression defined to make sure that the
|
||||
parameter value matches the pattern. The `regex` property requires a
|
||||
corresponding `error` property.
|
||||
You can validate a `string` parameter to match a regular expression. The `regex`
|
||||
property requires a corresponding `error` property.
|
||||
|
||||
```hcl
|
||||
data "coder_parameter" "project_id" {
|
||||
|
@ -266,106 +260,24 @@ data "coder_parameter" "project_id" {
|
|||
description = "Alpha-numeric project ID"
|
||||
validation {
|
||||
regex = "^[a-z0-9]+$"
|
||||
error = "Unfortunately, it isn't a valid project ID"
|
||||
error = "Unfortunately, this isn't a valid project ID"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Legacy
|
||||
|
||||
### Legacy parameters are unsupported now
|
||||
|
||||
In Coder, workspaces using legacy parameters can't be deployed anymore. To
|
||||
address this, it is necessary to either remove or adjust incompatible templates.
|
||||
In some cases, deleting a workspace with a hard dependency on a legacy parameter
|
||||
may be challenging. To cleanup unsupported workspaces, administrators are
|
||||
advised to take the following actions for affected templates:
|
||||
|
||||
1. Enable the `feature_use_managed_variables` provider flag.
|
||||
2. Ensure that every legacy variable block has defined missing default values,
|
||||
or convert it to `coder_parameter`.
|
||||
3. Push the new template version using UI or CLI.
|
||||
4. Update unsupported workspaces to the newest template version.
|
||||
5. Delete the affected workspaces that have been updated to the newest template
|
||||
version.
|
||||
|
||||
### Migration
|
||||
|
||||
> ⚠️ Migration is available until v0.24.0 (Jun 2023) release.
|
||||
|
||||
Terraform `variable` shouldn't be used for workspace scoped parameters anymore,
|
||||
and it's required to convert `variable` to `coder_parameter` resources. To make
|
||||
the migration smoother, there is a special property introduced -
|
||||
`legacy_variable` and `legacy_variable_name` , which can link `coder_parameter`
|
||||
with a legacy variable.
|
||||
|
||||
```hcl
|
||||
variable "legacy_cpu" {
|
||||
sensitive = false
|
||||
description = "CPU cores"
|
||||
default = 2
|
||||
}
|
||||
|
||||
data "coder_parameter" "cpu" {
|
||||
name = "CPU cores"
|
||||
type = "number"
|
||||
description = "Number of CPU cores"
|
||||
mutable = true
|
||||
|
||||
legacy_variable_name = "legacy_cpu"
|
||||
legacy_variable = var.legacy_cpu
|
||||
}
|
||||
```
|
||||
|
||||
#### Steps
|
||||
|
||||
1. Prepare and update a new template version:
|
||||
|
||||
- Add `coder_parameter` resource matching the legacy variable to migrate.
|
||||
- Use `legacy_variable_name` and `legacy_variable` to link the
|
||||
`coder_parameter` to the legacy variable.
|
||||
- Mark the new parameter as `mutable`, so that Coder will not block updating
|
||||
existing workspaces.
|
||||
|
||||
2. Update all workspaces to the updated template version. Coder will populate
|
||||
the added `coder_parameter`s with values from legacy variables.
|
||||
3. Prepare another template version:
|
||||
|
||||
- Remove the migrated variables.
|
||||
- Remove properties `legacy_variable` and `legacy_variable_name` from
|
||||
`coder_parameter`s.
|
||||
|
||||
4. Update all workspaces to the updated template version (2nd).
|
||||
5. Prepare a third template version:
|
||||
|
||||
- Enable the `feature_use_managed_variables` provider flag to use managed
|
||||
Terraform variables for template customization. Once the flag is enabled,
|
||||
legacy variables won't be used.
|
||||
|
||||
6. Update all workspaces to the updated template version (3rd).
|
||||
7. Delete legacy parameters.
|
||||
|
||||
As a template improvement, the template author can consider making some of the
|
||||
new `coder_parameter` resources `mutable`.
|
||||
|
||||
## Terraform template-wide variables
|
||||
|
||||
> ⚠️ Flag `feature_use_managed_variables` is available until v0.25.0 (Jul 2023)
|
||||
> release. After this release, template-wide Terraform variables will be enabled
|
||||
> by default.
|
||||
|
||||
As parameters are intended to be used only for workspace customization purposes,
|
||||
Terraform variables can be freely managed by the template author to build
|
||||
templates. Workspace users are not able to modify template variables.
|
||||
|
||||
The template author can enable Terraform template-wide variables mode by
|
||||
specifying the following flag:
|
||||
|
||||
```hcl
|
||||
provider "coder" {
|
||||
feature_use_managed_variables = "true"
|
||||
}
|
||||
```
|
||||
|
||||
Once it's defined, coder will allow for modifying variables by using CLI and UI
|
||||
forms, but it will not be possible to use legacy parameters.
|
||||
variable "CLOUD_API_KEY" {
|
||||
type = string
|
||||
description = "API key for the service"
|
||||
default = "1234567890"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
```
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
# Resource Metadata
|
||||
|
||||
Expose key workspace information to your users via
|
||||
Expose key workspace information to your users with
|
||||
[`coder_metadata`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/metadata)
|
||||
resources in your template code.
|
||||
|
||||
You can use `coder_metadata` to show Terraform resource attributes like these:
|
||||
|
||||
- Compute resources
|
||||
- IP addresses
|
||||
- [Secrets](../secrets.md#displaying-secrets)
|
||||
- Important file paths
|
||||
|
||||
![ui](../images/metadata-ui.png)
|
||||
|
||||
<blockquote class="info">
|
||||
Coder automatically generates the <code>type</code> metadata.
|
||||
</blockquote>
|
||||
|
||||
You can use `coder_metadata` to show
|
||||
|
||||
- Compute resources
|
||||
- IP addresses
|
||||
- [Secrets](../secrets.md#displaying-secrets)
|
||||
- Important file paths
|
||||
|
||||
and any other Terraform resource attribute.
|
||||
You can also present automatically updating, dynamic values with
|
||||
[agent metadata](./agent-metadata.md).
|
||||
|
||||
## Example
|
||||
|
||||
|
@ -57,10 +58,11 @@ resource "coder_metadata" "deployment" {
|
|||
}
|
||||
```
|
||||
|
||||
## Hiding resources in the UI
|
||||
## Hiding resources in the dashboard
|
||||
|
||||
Some resources don't need to be exposed in the UI; this helps keep the workspace
|
||||
view clean for developers. To hide a resource, use the `hide` attribute:
|
||||
Some resources don't need to be exposed in the dashboard's UI. This helps keep
|
||||
the workspace view clean for developers. To hide a resource, use the `hide`
|
||||
attribute:
|
||||
|
||||
```hcl
|
||||
resource "coder_metadata" "hide_serviceaccount" {
|
||||
|
@ -74,10 +76,10 @@ resource "coder_metadata" "hide_serviceaccount" {
|
|||
}
|
||||
```
|
||||
|
||||
## Using custom resource icon
|
||||
## Using a custom resource icon
|
||||
|
||||
To use custom icons on your resources, use the `icon` attribute (must be a valid
|
||||
path or URL):
|
||||
To use custom icons for your resource metadata, use the `icon` attribute. It
|
||||
must be a valid path or URL.
|
||||
|
||||
```hcl
|
||||
resource "coder_metadata" "resource_with_icon" {
|
||||
|
@ -91,7 +93,8 @@ resource "coder_metadata" "resource_with_icon" {
|
|||
}
|
||||
```
|
||||
|
||||
To make easier for you to customize your resource we added some built-in icons:
|
||||
To make it easier for you to customize your resource we added some built-in
|
||||
icons:
|
||||
|
||||
- Folder `/icon/folder.svg`
|
||||
- Memory `/icon/memory.svg`
|
||||
|
@ -99,31 +102,10 @@ To make easier for you to customize your resource we added some built-in icons:
|
|||
- Widgets `/icon/widgets.svg`
|
||||
- Database `/icon/database.svg`
|
||||
|
||||
We also have other icons related to the IDEs. You can see all the icons
|
||||
[here](https://github.com/coder/coder/tree/main/site/static/icon).
|
||||
|
||||
## Agent Metadata
|
||||
|
||||
In cases where you want to present automatically updating, dynamic values. You
|
||||
can use the `metadata` block in the `coder_agent` resource. For example:
|
||||
|
||||
```hcl
|
||||
resource "coder_agent" "dev" {
|
||||
os = "linux"
|
||||
arch = "amd64"
|
||||
dir = "/workspace"
|
||||
metadata {
|
||||
name = "Process Count"
|
||||
script = "ps aux | wc -l"
|
||||
interval = 1
|
||||
timeout = 3
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Read more [here](./agent-metadata.md).
|
||||
We also have other icons related to the IDEs. You can see more information on
|
||||
how to use the builtin icons [here](./icons.md).
|
||||
|
||||
## Up next
|
||||
|
||||
- Learn about [secrets](../secrets.md)
|
||||
- Learn about [Agent Metadata](./agent-metadata.md)
|
||||
- [Secrets](../secrets.md)
|
||||
- [Agent metadata](./agent-metadata.md)
|
||||
|
|
|
@ -1,25 +1,28 @@
|
|||
# Resource Persistence
|
||||
# Resource persistence
|
||||
|
||||
By default, all Coder resources are persistent, but production templates
|
||||
**must** use the practices laid out in this document to prevent accidental
|
||||
deletion.
|
||||
|
||||
Coder templates have full control over workspace ephemerality. In a completely
|
||||
ephemeral workspace, there are zero resources in the Off state. In a completely
|
||||
persistent workspace, there is no difference between the Off and On states.
|
||||
|
||||
Most workspaces fall somewhere in the middle, persisting user data such as
|
||||
filesystem volumes, but deleting expensive, reproducible resources such as
|
||||
The needs of most workspaces fall somewhere in the middle, persisting user data
|
||||
like filesystem volumes, but deleting expensive, reproducible resources such as
|
||||
compute instances.
|
||||
|
||||
By default, all Coder resources are persistent, but production templates
|
||||
**must** employ the practices laid out in this document to prevent accidental
|
||||
deletion.
|
||||
## Disabling persistence
|
||||
|
||||
## Disabling Persistence
|
||||
|
||||
The
|
||||
The Terraform
|
||||
[`coder_workspace` data source](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace)
|
||||
exposes the `start_count = [0 | 1]` attribute that other resources reference to
|
||||
become ephemeral.
|
||||
exposes the `start_count = [0 | 1]` attribute. To make a resource ephemeral, you
|
||||
can assign the `start_count` attribute to resource's
|
||||
[`count`](https://developer.hashicorp.com/terraform/language/meta-arguments/count)
|
||||
meta-argument.
|
||||
|
||||
For example:
|
||||
In this example, Coder will provision or tear down the `docker_container`
|
||||
resource:
|
||||
|
||||
```hcl
|
||||
data "coder_workspace" "me" {
|
||||
|
@ -32,7 +35,7 @@ resource "docker_container" "workspace" {
|
|||
}
|
||||
```
|
||||
|
||||
## ⚠️ Persistence Pitfalls
|
||||
## ⚠️ Persistence pitfalls
|
||||
|
||||
Take this example resource:
|
||||
|
||||
|
@ -46,10 +49,10 @@ resource "docker_volume" "home_volume" {
|
|||
```
|
||||
|
||||
Because we depend on `coder_workspace.me.owner`, if the owner changes their
|
||||
username, Terraform would recreate the volume (wiping its data!) the next time
|
||||
the workspace restarts.
|
||||
username, Terraform will recreate the volume (wiping its data!) the next time
|
||||
that Coder starts the workspace.
|
||||
|
||||
Therefore, persistent resource names must only depend on immutable IDs such as:
|
||||
To prevent this, use immutable IDs:
|
||||
|
||||
- `coder_workspace.me.owner_id`
|
||||
- `coder_workspace.me.id`
|
||||
|
@ -67,12 +70,12 @@ resource "docker_volume" "home_volume" {
|
|||
|
||||
## 🛡 Bulletproofing
|
||||
|
||||
Even if our persistent resource depends exclusively on static IDs, a change to
|
||||
the `name` format or other attributes would cause Terraform to rebuild the
|
||||
Even if your persistent resource depends exclusively on immutable IDs, a change
|
||||
to the `name` format or other attributes would cause Terraform to rebuild the
|
||||
resource.
|
||||
|
||||
Prevent Terraform from recreating the resource under any circumstance by setting
|
||||
the
|
||||
You can prevent Terraform from recreating a resource under any circumstance by
|
||||
setting the
|
||||
[`ignore_changes = all` directive in the `lifecycle` block](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#ignore_changes).
|
||||
|
||||
```hcl
|
||||
|
@ -88,7 +91,3 @@ resource "docker_volume" "home_volume" {
|
|||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Up next
|
||||
|
||||
- [Templates](../templates/index.md)
|
||||
|
|
|
@ -0,0 +1,418 @@
|
|||
# A guided tour of a template
|
||||
|
||||
This guided tour introduces you to the different parts of a Coder template by
|
||||
showing you how to create a template from scratch.
|
||||
|
||||
You'll write a simple template that provisions a workspace as a Docker container
|
||||
with Ubuntu. This simple template is based on the same Docker starter template
|
||||
that the [tutorial](./tutorial.md) uses.
|
||||
|
||||
## 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.
|
||||
|
||||
- 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).
|
||||
|
||||
## What's in a template
|
||||
|
||||
The main part of a Coder template is a [Terraform](https://terraform.io) `tf`
|
||||
file. A Coder template often has other files to configure the other resources
|
||||
that the template needs. In this tour you'll also create a `Dockerfile`.
|
||||
|
||||
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.
|
||||
|
||||
Here's a simplified diagram that shows the main parts of the template we'll
|
||||
create.
|
||||
|
||||
![Template architecture](../images/templates/template-architecture.png)
|
||||
|
||||
## 1. Create template files
|
||||
|
||||
On your local computer, create a directory for your template and create the
|
||||
`Dockerfile`.
|
||||
|
||||
```shell
|
||||
mkdir template-tour
|
||||
cd template-tour
|
||||
mkdir build
|
||||
nano build/Dockerfile
|
||||
```
|
||||
|
||||
You'll enter a simple `Dockerfile` that starts with the
|
||||
[official Ubuntu image](https://hub.docker.com/_/ubuntu/). In the editor, enter
|
||||
and save the following text in `Dockerfile` then exit the editor:
|
||||
|
||||
```dockerfile
|
||||
FROM ubuntu
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y \
|
||||
sudo \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG USER=coder
|
||||
RUN useradd --groups sudo --no-create-home --shell /bin/bash ${USER} \
|
||||
&& echo "${USER} ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/${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:
|
||||
|
||||
- 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
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
required_providers {
|
||||
coder = {
|
||||
source = "coder/coder"
|
||||
version = "~> 0.8.3"
|
||||
}
|
||||
docker = {
|
||||
source = "kreuzwerker/docker"
|
||||
version = "~> 3.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "coder" {
|
||||
}
|
||||
|
||||
provider "docker" {
|
||||
}
|
||||
|
||||
locals {
|
||||
username = data.coder_workspace.me.owner
|
||||
}
|
||||
|
||||
data "coder_provisioner" "me" {
|
||||
}
|
||||
|
||||
data "coder_workspace" "me" {
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Notice that the `provider` blocks for `coder` and `docker` are empty. In a more
|
||||
practical template, you would add arguments to these blocks to configure the
|
||||
providers, if needed.
|
||||
|
||||
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:
|
||||
|
||||
- Set some environment variables based on the workspace owner.
|
||||
- Manage ephemeral and persistent storage.
|
||||
|
||||
## 3. coder_agent
|
||||
|
||||
All templates need to create and run a
|
||||
[Coder agent](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent).
|
||||
This lets developers connect to their workspaces. The `coder_agent` resource
|
||||
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.
|
||||
|
||||
This snippet creates the agent:
|
||||
|
||||
```hcl
|
||||
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
|
||||
/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}"
|
||||
}
|
||||
|
||||
metadata {
|
||||
display_name = "CPU Usage"
|
||||
key = "0_cpu_usage"
|
||||
script = "coder stat cpu"
|
||||
interval = 10
|
||||
timeout = 1
|
||||
}
|
||||
|
||||
metadata {
|
||||
display_name = "RAM Usage"
|
||||
key = "1_ram_usage"
|
||||
script = "coder stat mem"
|
||||
interval = 10
|
||||
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
|
||||
[authentication credentials](./authentication.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.
|
||||
|
||||
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.
|
||||
|
||||
Your template can use metadata to show information to the workspace owner. Coder
|
||||
displays this metadata in the Coder dashboard. Our template has
|
||||
[`metadata`](./agent-metadata.md) blocks for CPU and RAM usage.
|
||||
|
||||
## 4. coder_app
|
||||
|
||||
A
|
||||
[`coder_app`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app)
|
||||
resource lets a developer use an app from the workspace's Coder dashboard.
|
||||
|
||||
![Apps in a Coder workspace](../images/templates/workspace-apps.png)
|
||||
|
||||
This is commonly used for [web IDEs](../ides/web-ides.md) such as
|
||||
[code-server](https://coder.com/docs/code-server/latest), 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](../ides/web-ides.md) for
|
||||
more examples.
|
||||
|
||||
```hcl
|
||||
resource "coder_app" "code-server" {
|
||||
agent_id = coder_agent.main.id
|
||||
slug = "code-server"
|
||||
display_name = "code-server"
|
||||
url = "http://localhost:13337/?folder=/home/${local.username}"
|
||||
icon = "/icon/code.svg"
|
||||
subdomain = false
|
||||
share = "owner"
|
||||
|
||||
healthcheck {
|
||||
url = "http://localhost:13337/healthz"
|
||||
interval = 5
|
||||
threshold = 6
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
You can also use a `coder_app` resource to link to external apps, such as links
|
||||
to wikis or cloud consoles.
|
||||
|
||||
```hcl
|
||||
resource "coder_app" "coder-server-doc" {
|
||||
agent_id = coder_agent.main.id
|
||||
icon = "/emojis/1f4dd.png"
|
||||
slug = "getting-started"
|
||||
url = "https://coder.com/docs/code-server"
|
||||
external = true
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 5. Persistent and ephemeral resources
|
||||
|
||||
Managing the lifecycle of template resources is important. We want to make sure
|
||||
that workspaces use computing, storage, and other services efficiently.
|
||||
|
||||
We want our workspace's home directory to persist after the workspace is stopped
|
||||
so that a developer can continue their work when they start the workspace again.
|
||||
|
||||
We do this in 2 parts:
|
||||
|
||||
- Our `docker_volume` resource uses the `lifecycle` block with the
|
||||
`ignore_changes = all` argument to prevent accidental deletions.
|
||||
- To prevent Terraform from destroying persistent Docker volumes in case of a
|
||||
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
|
||||
[count](https://developer.hashicorp.com/terraform/language/meta-arguments/count)
|
||||
meta-argument.
|
||||
|
||||
```hcl
|
||||
resource "docker_volume" "home_volume" {
|
||||
name = "coder-${data.coder_workspace.me.id}-home"
|
||||
# Protect the volume from being deleted due to changes in attributes.
|
||||
lifecycle {
|
||||
ignore_changes = all
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
For details, see [Resource persistence](./resource-persistence.md).
|
||||
|
||||
## 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.
|
||||
|
||||
```hcl
|
||||
resource "docker_image" "main" {
|
||||
name = "coder-${data.coder_workspace.me.id}"
|
||||
build {
|
||||
context = "./build"
|
||||
build_args = {
|
||||
USER = local.username
|
||||
}
|
||||
}
|
||||
triggers = {
|
||||
dir_sha1 = sha1(join("", [for f in fileset(path.module, "build/*") : filesha1(f)]))
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Our `docker_container` resource uses `coder_workspace` `start_count` to start
|
||||
and stop the Docker container:
|
||||
|
||||
```hcl
|
||||
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)}"
|
||||
# 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
|
||||
entrypoint = ["sh", "-c", replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")]
|
||||
env = [
|
||||
"CODER_AGENT_TOKEN=${coder_agent.main.token}",
|
||||
]
|
||||
host {
|
||||
host = "host.docker.internal"
|
||||
ip = "host-gateway"
|
||||
}
|
||||
volumes {
|
||||
container_path = "/home/${local.username}"
|
||||
volume_name = docker_volume.home_volume.name
|
||||
read_only = false
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 7. Create the template in Coder
|
||||
|
||||
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
|
||||
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:
|
||||
|
||||
```console
|
||||
$ coder login https://coder.example.com
|
||||
Your browser has been opened to visit:
|
||||
|
||||
https://coder.example.com/cli-auth
|
||||
|
||||
> Paste your token here:
|
||||
```
|
||||
|
||||
In your web browser, enter your credentials:
|
||||
|
||||
![Logging in to your Coder deployment](../images/templates/coder-login-web.png)
|
||||
|
||||
Copy the session token into the clipboard:
|
||||
|
||||
![Logging in to your Coder deployment](../images/templates/coder-session-token.png)
|
||||
|
||||
And paste it into the CLI:
|
||||
|
||||
```
|
||||
> Welcome to Coder, marc! You're authenticated.
|
||||
$
|
||||
```
|
||||
|
||||
Now you can add your template files to your Coder deployment:
|
||||
|
||||
```console
|
||||
$ pwd
|
||||
/home/marc/template-tour
|
||||
$ coder templates create
|
||||
> Upload "."? (yes/no) yes
|
||||
```
|
||||
|
||||
The Coder CLI tool gives progress information then prompts you to confirm:
|
||||
|
||||
```console
|
||||
> Confirm create? (yes/no) yes
|
||||
|
||||
The template-tour template has been created! Developers can provision a workspace with this template using:
|
||||
|
||||
coder create --template="template-tour" [workspace name]
|
||||
```
|
||||
|
||||
In your web browser, log in to your Coder dashboard, select **Templates**. Your
|
||||
template is ready to use for new workspaces.
|
||||
|
||||
![Your new template, ready to use](../images/templates/template-tour.png)
|
||||
|
||||
## Next steps
|
||||
|
||||
- [Setting up templates](./best-practices.md)
|
||||
- [Customizing templates](./customizing.md)
|
||||
- [Troubleshooting template](./troubleshooting.md)
|
|
@ -0,0 +1,152 @@
|
|||
# Troubleshooting templates
|
||||
|
||||
Occasionally, you may run into scenarios where a workspace is created, but the
|
||||
agent is either not connected or the
|
||||
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
|
||||
has failed or timed out.
|
||||
|
||||
## Agent connection issues
|
||||
|
||||
If the agent is not connected, it means the agent or
|
||||
[init script](https://github.com/coder/coder/tree/main/provisionersdk/scripts)
|
||||
has failed on the resource.
|
||||
|
||||
```console
|
||||
$ coder ssh myworkspace
|
||||
⢄⡱ Waiting for connection from [agent]...
|
||||
```
|
||||
|
||||
While troubleshooting steps vary by resource, here are some general best
|
||||
practices:
|
||||
|
||||
- Ensure the resource has `curl` installed (alternatively, `wget` or `busybox`)
|
||||
- Ensure the resource can `curl` your Coder
|
||||
[access URL](../admin/configure.md#access-url)
|
||||
- Manually connect to the resource and check the agent logs (e.g.,
|
||||
`kubectl exec`, `docker exec` or AWS console)
|
||||
- The Coder agent logs are typically stored in `/tmp/coder-agent.log`
|
||||
- The Coder agent startup script logs are typically stored in
|
||||
`/tmp/coder-startup-script.log`
|
||||
- The Coder agent shutdown script logs are typically stored in
|
||||
`/tmp/coder-shutdown-script.log`
|
||||
- This can also happen if the websockets are not being forwarded correctly when
|
||||
running Coder behind a reverse proxy.
|
||||
[Read our reverse-proxy docs](../admin/configure.md#tls--reverse-proxy)
|
||||
|
||||
## Startup script issues
|
||||
|
||||
Depending on the contents of the
|
||||
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script),
|
||||
and whether or not the
|
||||
[startup script behavior](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script_behavior)
|
||||
is set to blocking or non-blocking, you may notice issues related to the startup
|
||||
script. In this section we will cover common scenarios and how to resolve them.
|
||||
|
||||
### Unable to access workspace, startup script is still running
|
||||
|
||||
If you're trying to access your workspace and are unable to because the
|
||||
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
|
||||
is still running, it means the
|
||||
[startup script behavior](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script_behavior)
|
||||
option is set to blocking or you have enabled the `--wait=yes` option (for e.g.
|
||||
`coder ssh` or `coder config-ssh`). In such an event, you can always access the
|
||||
workspace by using the web terminal, or via SSH using the `--wait=no` option. If
|
||||
the startup script is running longer than it should, or never completing, you
|
||||
can try to [debug the startup script](#debugging-the-startup-script) to resolve
|
||||
the issue. Alternatively, you can try to force the startup script to exit by
|
||||
terminating processes started by it or terminating the startup script itself (on
|
||||
Linux, `ps` and `kill` are useful tools).
|
||||
|
||||
For tips on how to write a startup script that doesn't run forever, see the
|
||||
[`startup_script`](#startup_script) section. For more ways to override the
|
||||
startup script behavior, see the
|
||||
[`startup_script_behavior`](#startup_script_behavior) section.
|
||||
|
||||
Template authors can also set the
|
||||
[startup script behavior](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script_behavior)
|
||||
option to non-blocking, which will allow users to access the workspace while the
|
||||
startup script is still running. Note that the workspace must be updated after
|
||||
changing this option.
|
||||
|
||||
### Your workspace may be incomplete
|
||||
|
||||
If you see a warning that your workspace may be incomplete, it means you should
|
||||
be aware that programs, files, or settings may be missing from your workspace.
|
||||
This can happen if the
|
||||
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
|
||||
is still running or has exited with a non-zero status (see
|
||||
[startup script error](#startup-script-error)). No action is necessary, but you
|
||||
may want to
|
||||
[start a new shell session](#session-was-started-before-the-startup-script-finished-web-terminal)
|
||||
after it has completed or check the
|
||||
[startup script logs](#debugging-the-startup-script) to see if there are any
|
||||
issues.
|
||||
|
||||
### Session was started before the startup script finished
|
||||
|
||||
The web terminal may show this message if it was started before the
|
||||
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
|
||||
finished, but the startup script has since finished. This message can safely be
|
||||
dismissed, however, be aware that your preferred shell or dotfiles may not yet
|
||||
be activated for this shell session. You can either start a new session or
|
||||
source your dotfiles manually. Note that starting a new session means that
|
||||
commands running in the terminal will be terminated and you may lose unsaved
|
||||
work.
|
||||
|
||||
Examples for activating your preferred shell or sourcing your dotfiles:
|
||||
|
||||
- `exec zsh -l`
|
||||
- `source ~/.bashrc`
|
||||
|
||||
### Startup script exited with an error
|
||||
|
||||
When the
|
||||
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
|
||||
exits with an error, it means the last command run by the script failed. When
|
||||
`set -e` is used, this means that any failing command will immediately exit the
|
||||
script and the remaining commands will not be executed. This also means that
|
||||
[your workspace may be incomplete](#your-workspace-may-be-incomplete). If you
|
||||
see this error, you can check the
|
||||
[startup script logs](#debugging-the-startup-script) to figure out what the
|
||||
issue is.
|
||||
|
||||
Common causes for startup script errors:
|
||||
|
||||
- A missing command or file
|
||||
- A command that fails due to missing permissions
|
||||
- Network issues (e.g., unable to reach a server)
|
||||
|
||||
### Debugging the startup script
|
||||
|
||||
The simplest way to debug the
|
||||
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
|
||||
is to open the workspace in the Coder dashboard and click "Show startup log" (if
|
||||
not already visible). This will show all the output from the script. Another
|
||||
option is to view the log file inside the workspace (usually
|
||||
`/tmp/coder-startup-script.log`). If the logs don't indicate what's going on or
|
||||
going wrong, you can increase verbosity by adding `set -x` to the top of the
|
||||
startup script (note that this will show all commands run and may output
|
||||
sensitive information). Alternatively, you can add `echo` statements to show
|
||||
what's going on.
|
||||
|
||||
Here's a short example of an informative startup script:
|
||||
|
||||
```shell
|
||||
echo "Running startup script..."
|
||||
echo "Run: long-running-command"
|
||||
/path/to/long-running-command
|
||||
status=$?
|
||||
echo "Done: long-running-command, exit status: ${status}"
|
||||
if [ $status -ne 0 ]; then
|
||||
echo "Startup script failed, exiting..."
|
||||
exit $status
|
||||
fi
|
||||
```
|
||||
|
||||
> **Note:** We don't use `set -x` here because we're manually echoing the
|
||||
> commands. This protects against sensitive information being shown in the log.
|
||||
|
||||
This script tells us what command is being run and what the exit status is. If
|
||||
the exit status is non-zero, it means the command failed and we exit the script.
|
||||
Since we are manually checking the exit status here, we don't need `set -e` at
|
||||
the top of the script to exit on error.
|
|
@ -0,0 +1,130 @@
|
|||
# Your first template
|
||||
|
||||
A common way to create a template is to begin with a starter template then
|
||||
modify it for your needs. Coder makes this easy with starter templates for
|
||||
popular development targets like Docker, Kubernetes, Azure, and so on. Once your
|
||||
template is up and running, you can edit it in the Coder dashboard. Coder even
|
||||
handles versioning for you so you can publish official updates or revert to
|
||||
previous versions.
|
||||
|
||||
In this tutorial, you'll create your first template from the Docker starter
|
||||
template.
|
||||
|
||||
## Before you start
|
||||
|
||||
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.
|
||||
|
||||
## 1. Log in to Coder
|
||||
|
||||
In your web browser, go to your Coder dashboard to log in.
|
||||
|
||||
## 2. Choose a starter template
|
||||
|
||||
Select **Templates** > **Starter Templates**.
|
||||
|
||||
![Starter Templates button](../images/templates/starter-templates-button.png)
|
||||
|
||||
In **Filter**, select **Docker** then select **Develop in Docker**.
|
||||
|
||||
![Choosing a starter template](../images/templates/develop-in-docker-template.png)
|
||||
|
||||
Select **Use template**.
|
||||
|
||||
![Using a starter template](../images/templates/use-template.png)
|
||||
|
||||
## 3. Create your template
|
||||
|
||||
In **Create template**, fill in **Name** and **Display name**,then scroll down
|
||||
and select **Create template**.
|
||||
|
||||
![Creating a template](../images/templates/create-template.png)
|
||||
|
||||
## 4. Create a workspace from your template
|
||||
|
||||
When the template is ready, select **Create Workspace**.
|
||||
|
||||
![Create workspace](../images/templates/create-workspace.png)
|
||||
|
||||
In **New workspace**, fill in **Name** then scroll down to select **Create
|
||||
Workspace**.
|
||||
|
||||
![New workspace](../images/templates/new-workspace.png)
|
||||
|
||||
Coder starts your new workspace from your template.
|
||||
|
||||
After a few seconds, your workspace is ready to use.
|
||||
|
||||
![Workspace is ready](../images/templates/workspace-ready.png)
|
||||
|
||||
## 5. Try out your new workspace
|
||||
|
||||
This starter template lets you connect to your workspace in a few ways:
|
||||
|
||||
- VS Code Desktop: Loads your workspace into
|
||||
[VS Code Desktop](https://code.visualstudio.com/Download) installed on your
|
||||
local computer.
|
||||
- code-server: Opens [browser-based VS Code](../ides/web-ides.md) with your
|
||||
workspace.
|
||||
- Terminal: Opens a browser-based terminal with a shell in the workspace's
|
||||
Docker instance.
|
||||
- SSH: Use SSH to log in to the workspace from your local machine. If you
|
||||
haven't already, you'll have to install Coder on your local machine to
|
||||
configure your SSH client.
|
||||
|
||||
> **Tip**: You can edit the template to let developers connect to a workspace in
|
||||
> [a few more ways](../ides.md).
|
||||
|
||||
When you're done, you can stop the workspace.
|
||||
|
||||
## 6. Modify your template
|
||||
|
||||
Now you can modify your template to suit your team's needs.
|
||||
|
||||
Let's replace the `golang` package in the Docker image with the `python3`
|
||||
package. You can do this by editing the template's `Dockerfile` directly in your
|
||||
web browser.
|
||||
|
||||
In the Coder dashboard, select **Templates** then your first template.
|
||||
|
||||
![Selecting the first template](../images/templates/select-template.png)
|
||||
|
||||
In the drop-down menu, select **Edit files**.
|
||||
|
||||
![Edit template files](../images/templates/edit-files.png)
|
||||
|
||||
Expand the **build** directory and select **Dockerfile**.
|
||||
|
||||
![Selecting source code](../images/templates/source-code.png)
|
||||
|
||||
Edit `build/Dockerfile` to replace `golang` with `python3`.
|
||||
|
||||
![Editing source code](../images/templates/edit-source-code.png)
|
||||
|
||||
Select **Build template** and wait for Coder to prepare the template for
|
||||
workspaces.
|
||||
|
||||
![Building a template](../images/templates/build-template.png)
|
||||
|
||||
Select **Publish version**. In the **Publish new version** dialog, make sure
|
||||
**Promote to default version** is checked then select **Publish**.
|
||||
|
||||
![Publish a template](../images/templates/publish.png)
|
||||
|
||||
Now when developers create a new workspace from this template, they can use
|
||||
Python 3 instead of Go.
|
||||
|
||||
For developers with workspaces that were created with a previous version of your
|
||||
template, Coder will notify them that there's a new version of the template.
|
||||
|
||||
You can also handle [change management](./change-management.md) through your own
|
||||
repo and continuous integration.
|
||||
|
||||
## Next steps
|
||||
|
||||
- [Write your own template](./tour.md)
|
||||
- [Setting up templates](./best-practices.md)
|
|
@ -1,9 +1,25 @@
|
|||
# Workspaces
|
||||
|
||||
Workspaces contain the IDEs, dependencies, and configuration information needed
|
||||
for software development.
|
||||
A workspace is the environment that a developer works in. Developers in a team
|
||||
each work from their own workspace and can use [multiple IDEs](./ides.md).
|
||||
|
||||
## Create workspaces
|
||||
A developer creates a workspace from a [shared template](./templates/index.md).
|
||||
This lets an entire team work in environments that are identically configured
|
||||
and provisioned with the same resources.
|
||||
|
||||
## Creating workspaces
|
||||
|
||||
You can create a workspace in the UI. Log in to your Coder instance, go to the
|
||||
**Templates** tab, find the template you need, and select **Create Workspace**.
|
||||
|
||||
![Creating a workspace in the UI](./images/creating-workspace-ui.png)
|
||||
|
||||
When you create a workspace, you will be prompted to give it a name. You might
|
||||
also be prompted to set some parameters that the template provides.
|
||||
|
||||
You can manage your existing templates in the **Workspaces** tab.
|
||||
|
||||
You can also create a workspace from the command line:
|
||||
|
||||
Each Coder user has their own workspaces created from
|
||||
[shared templates](./templates/index.md):
|
||||
|
@ -16,11 +32,72 @@ coder create --template="<templateName>" <workspaceName>
|
|||
coder show <workspace-name>
|
||||
```
|
||||
|
||||
## IDEs
|
||||
## Workspace filtering
|
||||
|
||||
Coder [supports multiple IDEs](./ides.md) for use with your workspaces.
|
||||
In the Coder UI, you can filter your workspaces using pre-defined filters or
|
||||
Coder's filter query. For example, you can find the workspaces that you own or
|
||||
that are currently running.
|
||||
|
||||
## Workspace lifecycle
|
||||
The following filters are supported:
|
||||
|
||||
- `owner` - Represents the `username` of the owner. You can also use `me` as a
|
||||
convenient alias for the logged-in user.
|
||||
- `template` - Specifies the name of the template.
|
||||
- `status` - Indicates the status of the workspace. For a list of supported
|
||||
statuses, see
|
||||
[WorkspaceStatus documentation](https://pkg.go.dev/github.com/coder/coder/codersdk#WorkspaceStatus).
|
||||
|
||||
## Starting and stopping workspaces
|
||||
|
||||
By default, you manually start and stop workspaces as you need. You can also
|
||||
schedule a workspace to start and stop automatically.
|
||||
|
||||
To set a workspace's schedule, go to the workspace, then **Settings** >
|
||||
**Schedule**.
|
||||
|
||||
![Scheduling UI](./images/schedule.png)
|
||||
|
||||
Coder might also stop a workspace automatically if there is a
|
||||
[template update](./templates/index.md#Start/stop) available.
|
||||
|
||||
### Autostart and autostop
|
||||
|
||||
Use autostart to start a workspace at a specified time and which days of the
|
||||
week. Also, you can choose your preferred timezone.
|
||||
|
||||
![Autostart UI](./images/autostart.png)
|
||||
|
||||
Use autostop to stop a workspace after a number of hours. Autostop won't stop a
|
||||
workspace if you're still using it. It waits for another hour before checking
|
||||
again. Coder checks for active connections in the IDE, SSH, Port Forwarding, and
|
||||
coder_app.
|
||||
|
||||
![Autostop UI](./images/autostop.png)
|
||||
|
||||
### Max lifetime
|
||||
|
||||
Max lifetime is a template setting that determines the number of hours a
|
||||
workspace will run before Coder automatically stops it, regardless of any active
|
||||
connections. Use this setting to ensure that workspaces do not run in perpetuity
|
||||
when connections are left open inadvertently.
|
||||
|
||||
## Updating workspaces
|
||||
|
||||
After updating the default version of the template that a workspace was created
|
||||
from, you can update the workspace.
|
||||
|
||||
![Updating a workspace](./images/workspace-update.png)
|
||||
|
||||
If the workspace is running, Coder stops it, updates it, then starts the
|
||||
workspace again.
|
||||
|
||||
On the command line:
|
||||
|
||||
```shell
|
||||
coder update <workspace-name>
|
||||
```
|
||||
|
||||
## Workspace resources
|
||||
|
||||
Workspaces in Coder are started and stopped, often based on whether there was
|
||||
any activity or if there was a
|
||||
|
@ -33,53 +110,13 @@ though the exact behavior depends on the template. For more information, see
|
|||
> ⚠️ To avoid data loss, refer to your template documentation for information on
|
||||
> where to store files, install software, etc., so that they persist. Default
|
||||
> templates are documented in
|
||||
> [../examples/templates](https://github.com/coder/coder/tree/c6b1daabc5a7aa67bfbb6c89966d728919ba7f80/examples/templates).
|
||||
> [../examples/templates](https://github.com/coder/coder/tree/main/examples/templates).
|
||||
>
|
||||
> You can use `coder show <workspace-name>` to see which resources are
|
||||
> persistent and which are ephemeral.
|
||||
|
||||
When a workspace is deleted, all of the workspace's resources are deleted.
|
||||
|
||||
## Workspace scheduling
|
||||
|
||||
By default, workspaces are manually turned on/off by the user. However, a
|
||||
schedule can be defined on a per-workspace basis to automate the workspace
|
||||
start/stop.
|
||||
|
||||
![Scheduling UI](./images/schedule.png)
|
||||
|
||||
### Autostart
|
||||
|
||||
The autostart feature automates the workspace build at a user-specified time and
|
||||
day(s) of the week. In addition, users can select their preferred timezone.
|
||||
|
||||
![Autostart UI](./images/autostart.png)
|
||||
|
||||
### Autostop
|
||||
|
||||
The autostop feature shuts off workspaces after given number of hours in the
|
||||
"on" state. If Coder detects workspace connection activity, the autostop timer
|
||||
is bumped up one hour. IDE, SSH, Port Forwarding, and coder_app activity trigger
|
||||
this bump.
|
||||
|
||||
![autostop UI](./images/autostop.png)
|
||||
|
||||
### Max lifetime
|
||||
|
||||
Max lifetime is a template-level setting that determines the number of hours a
|
||||
workspace can run before it is automatically shutdown, regardless of any active
|
||||
connections. This setting ensures workspaces do not run in perpetuity when
|
||||
connections are left open inadvertently.
|
||||
|
||||
## Updating workspaces
|
||||
|
||||
Use the following command to update a workspace to the latest template version.
|
||||
The workspace will be stopped and started:
|
||||
|
||||
```shell
|
||||
coder update <workspace-name>
|
||||
```
|
||||
|
||||
## Repairing workspaces
|
||||
|
||||
Use the following command to re-enter template input variables in an existing
|
||||
|
@ -90,6 +127,33 @@ state is out of sync with the template.
|
|||
coder update <your workspace name> --always-prompt
|
||||
```
|
||||
|
||||
First, try re-entering parameters from a workspace. In the Coder UI, you can
|
||||
filter your workspaces using pre-defined filters or employing the Coder's filter
|
||||
query. Take a look at the following examples to understand how to use the
|
||||
Coder's filter query:
|
||||
|
||||
- To find the workspaces that you own, use the filter `owner:me`.
|
||||
- To find workspaces that are currently running, use the filter
|
||||
`status:running`.
|
||||
|
||||
![Re-entering template variables](./images/template-variables.png)
|
||||
|
||||
You can also do this in the CLI with the following command:
|
||||
|
||||
```shell
|
||||
coder update <your workspace name> --always-prompt
|
||||
```
|
||||
|
||||
If that does not work, a Coder admin can manually push and pull the Terraform
|
||||
state for a given workspace. This can lead to state corruption or deleted
|
||||
resources if you do not know what you are doing.
|
||||
|
||||
```shell
|
||||
coder state pull <username>/<workspace name>
|
||||
# Make changes
|
||||
coder state push <username>/<workspace name>
|
||||
```
|
||||
|
||||
## Logging
|
||||
|
||||
Coder stores macOS and Linux logs at the following locations:
|
||||
|
@ -102,27 +166,6 @@ Coder stores macOS and Linux logs at the following locations:
|
|||
|
||||
> Note: Logs are truncated once they reach 5MB in size.
|
||||
|
||||
## Workspace filtering
|
||||
|
||||
In the Coder UI, you can filter your workspaces using pre-defined filters or
|
||||
employing the Coder's filter query. Take a look at the following examples to
|
||||
understand how to use the Coder's filter query:
|
||||
|
||||
- To find the workspaces that you own, use the filter `owner:me`.
|
||||
- To find workspaces that are currently running, use the filter
|
||||
`status:running`.
|
||||
|
||||
The following filters are supported:
|
||||
|
||||
- `owner` - Represents the `username` of the owner. You can also use `me` as a
|
||||
convenient alias for the logged-in user.
|
||||
- `template` - Specifies the name of the template.
|
||||
- `status` - Indicates the status of the workspace. For a list of supported
|
||||
statuses, please refer to the
|
||||
[WorkspaceStatus documentation](https://pkg.go.dev/github.com/coder/coder/v2/codersdk#WorkspaceStatus).
|
||||
|
||||
---
|
||||
|
||||
## Up next
|
||||
|
||||
- Learn about how to personalize your workspace with [Dotfiles](./dotfiles.md)
|
||||
|
|
|
@ -51,7 +51,7 @@ export const EmptyTemplates: FC<{
|
|||
for workspaces (e.g., docker_container, aws_instance,
|
||||
kubernetes_pod). Select a starter template below or
|
||||
<Link
|
||||
href={docs("/templates#add-a-template")}
|
||||
href={docs("/templates/tutorial")}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
|
|
|
@ -68,7 +68,7 @@ const TemplateHelpTooltip: React.FC = () => {
|
|||
<HelpTooltipTitle>{Language.templateTooltipTitle}</HelpTooltipTitle>
|
||||
<HelpTooltipText>{Language.templateTooltipText}</HelpTooltipText>
|
||||
<HelpTooltipLinksGroup>
|
||||
<HelpTooltipLink href={docs("/templates#manage-templates")}>
|
||||
<HelpTooltipLink href={docs("/templates")}>
|
||||
{Language.templateTooltipLink}
|
||||
</HelpTooltipLink>
|
||||
</HelpTooltipLinksGroup>
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
import { AlertColor } from "@mui/material/Alert/Alert";
|
||||
import Button from "@mui/material/Button";
|
||||
import Link from "@mui/material/Link";
|
||||
import { Alert } from "components/Alert/Alert";
|
||||
import { ReactNode } from "react";
|
||||
import { docs } from "utils/docs";
|
||||
|
||||
export type TerminalPageAlertType = "error" | "starting" | "success";
|
||||
|
||||
type MapAlertTypeToComponent = {
|
||||
[key in TerminalPageAlertType]: {
|
||||
severity: AlertColor;
|
||||
children: ReactNode | undefined;
|
||||
};
|
||||
};
|
||||
|
||||
const mapAlertTypeToText: MapAlertTypeToComponent = {
|
||||
error: {
|
||||
severity: "warning",
|
||||
children: (
|
||||
<>
|
||||
The workspace{" "}
|
||||
<Link
|
||||
title="startup script has exited with an error"
|
||||
href={docs(
|
||||
"/templates/troubleshooting#startup-script-exited-with-an-error",
|
||||
)}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
startup script has exited with an error
|
||||
</Link>
|
||||
, we recommend reloading this session and{" "}
|
||||
<Link
|
||||
title=" debugging the startup script"
|
||||
href={docs("/templates/troubleshooting#debugging-the-startup-script")}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
debugging the startup script
|
||||
</Link>{" "}
|
||||
because{" "}
|
||||
<Link
|
||||
title="your workspace may be incomplete."
|
||||
href={docs(
|
||||
"/templates/troubleshooting#your-workspace-may-be-incomplete",
|
||||
)}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
your workspace may be incomplete.
|
||||
</Link>{" "}
|
||||
</>
|
||||
),
|
||||
},
|
||||
starting: {
|
||||
severity: "info",
|
||||
children: (
|
||||
<>
|
||||
Startup script is still running. You can continue using this terminal,
|
||||
but{" "}
|
||||
<Link
|
||||
title="your workspace may be incomplete."
|
||||
href={docs(
|
||||
"/templates/troubleshooting#your-workspace-may-be-incomplete",
|
||||
)}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{" "}
|
||||
your workspace may be incomplete.
|
||||
</Link>
|
||||
</>
|
||||
),
|
||||
},
|
||||
success: {
|
||||
severity: "success",
|
||||
children: (
|
||||
<>
|
||||
Startup script has completed successfully. The workspace is ready but
|
||||
this{" "}
|
||||
<Link
|
||||
title="session was started before the startup script finished"
|
||||
href={docs(
|
||||
"/templates/troubleshooting#your-workspace-may-be-incomplete",
|
||||
)}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
session was started before the startup script finished.
|
||||
</Link>{" "}
|
||||
To ensure your shell environment is up-to-date, we recommend reloading
|
||||
this session.
|
||||
</>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export default ({
|
||||
alertType,
|
||||
onDismiss,
|
||||
}: {
|
||||
alertType: TerminalPageAlertType;
|
||||
onDismiss: () => void;
|
||||
}) => {
|
||||
const severity = mapAlertTypeToText[alertType].severity;
|
||||
return (
|
||||
<Alert
|
||||
severity={severity}
|
||||
sx={{
|
||||
borderRadius: 0,
|
||||
borderWidth: 0,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: (theme) => theme.palette.divider,
|
||||
backgroundColor: (theme) => theme.palette.background.paperLight,
|
||||
borderLeft: (theme) => `3px solid ${theme.palette[severity].light}`,
|
||||
marginBottom: 1,
|
||||
}}
|
||||
onDismiss={onDismiss}
|
||||
dismissible
|
||||
actions={[
|
||||
<Button
|
||||
key="refresh-session"
|
||||
size="small"
|
||||
variant="text"
|
||||
onClick={() => {
|
||||
// By redirecting the user without the session in the URL we
|
||||
// create a new one
|
||||
window.location.href = window.location.pathname;
|
||||
}}
|
||||
>
|
||||
Refresh session
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
{mapAlertTypeToText[alertType].children}
|
||||
</Alert>
|
||||
);
|
||||
};
|
|
@ -23,15 +23,12 @@ export const WorkspaceHelpTooltip: FC = () => {
|
|||
<HelpTooltipTitle>{Language.workspaceTooltipTitle}</HelpTooltipTitle>
|
||||
<HelpTooltipText>{Language.workspaceTooltipText}</HelpTooltipText>
|
||||
<HelpTooltipLinksGroup>
|
||||
<HelpTooltipLink href={docs("/workspaces#create-workspaces")}>
|
||||
<HelpTooltipLink href={docs("/workspaces")}>
|
||||
{Language.workspaceTooltipLink1}
|
||||
</HelpTooltipLink>
|
||||
<HelpTooltipLink href={docs("/workspaces#connect-with-ssh")}>
|
||||
<HelpTooltipLink href={docs("/ides")}>
|
||||
{Language.workspaceTooltipLink2}
|
||||
</HelpTooltipLink>
|
||||
<HelpTooltipLink href={docs("/workspaces#editors-and-ides")}>
|
||||
{Language.workspaceTooltipLink3}
|
||||
</HelpTooltipLink>
|
||||
</HelpTooltipLinksGroup>
|
||||
</HelpTooltip>
|
||||
);
|
||||
|
|