Compare commits

...

18 Commits

Author SHA1 Message Date
Hugo Dutka 91bcb61d53 rename app id 2025-08-02 20:20:05 +02:00
Hugo Dutka 36578b3546 rename app 2025-08-02 20:13:10 +02:00
Hugo Dutka bb35c87a00 rename app 2025-08-02 20:11:58 +02:00
Hugo Dutka 7533c87ae3 rename app 2025-08-02 19:35:56 +02:00
Hugo Dutka 21b1a188d3 tmp: remove workaround 2025-08-02 19:33:56 +02:00
Hugo Dutka 482320a857 Update main.tf 2025-08-02 14:36:19 +02:00
Hugo Dutka 8982d15c0d Update main.tf 2025-08-02 14:32:38 +02:00
Hugo Dutka 20170e1a24 Update main.tf 2025-08-02 10:59:43 +02:00
Hugo Dutka c54668f27a Update main.tf 2025-08-02 10:57:25 +02:00
Hugo Dutka 32c5f40d8a Update main.tf 2025-08-02 10:31:44 +02:00
Hugo Dutka 9b2171c007 Update main.tf 2025-08-02 10:28:20 +02:00
Hugo Dutka c9cccc783f Update main.tf 2025-08-02 10:19:03 +02:00
Phorcys 3afa72095b chore: polish some modules readme (#272) 2025-08-01 21:12:05 -05:00
Michael Smith cf66809349 fix: update HCP vault links to use current URL patterns (#275)
Realized this was an issue while fixing how we're rendering GFM alerts
on the Registry website.

## Description

Basically, the URLs we're using right now are technically valid, but
they were using the old URL pattern from before we created the
`coder/registry` repo. The Registry website has logic to handle
redirects for these, but we should avoid triggering it as it adds
unnecessary entries to the user's browser history.

### Changes made
- Updated all Registry links in the HCP Vault alert to include `coder`
as the namespace

## Type of Change

- [ ] New module
- [ ] Bug fix
- [ ] Feature/enhancement
- [x] Documentation
- [ ] Other

## Testing & Validation

- [x] Tests pass (`bun test`)
- [x] Code formatted (`bun run fmt`)
- [x] Changes tested locally
2025-07-31 19:50:37 -05:00
Michael Smith 020a2cba79 fix: update icon path for k8s-username (#276)
## Description

This is an issue that doesn't exist within `coder/registry`, but was
breaking our build process for the Registry website. We were using an
invalid image path.

## Type of Change

- [ ] New module
- [x] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [ ] Other

## Testing & Validation

- [x] Tests pass (`bun test`)
- [x] Code formatted (`bun run fmt`)
- [x] Changes tested locally
2025-07-31 20:58:06 +01:00
Eric Paulsen 3fd7b47097 feat: dynamic username template (#261)
## Description

this PR adds a new template that creates & runs Coder workspaces on K8s
with the user's Coder `username` as the Linux UID. a commonly requested
use-case by customers.

## Type of Change

- [x] New module
- [ ] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [ ] Other

## Module Information

<!-- Delete this section if not applicable -->

**Path:** `registry/ericpaulsen/templates/k8s-pod-username.tf`  

## Testing & Validation

- [x] Changes tested locally
2025-07-31 14:25:29 +00:00
Atif Ali e1f077dac3 chore: deploy registry changes nightly (#264) 2025-07-30 22:33:25 -04:00
Marcin Tojek 29c52b7072 feat: jupyter-notebook: preinstall Python packages (#263) 2025-07-30 20:25:53 -05:00
14 changed files with 462 additions and 55 deletions
+3
View File
@@ -1,6 +1,9 @@
name: deploy-registry
on:
schedule:
# Runs at 02:30 UTC Monday through Friday
- cron: "30 2 * * 1-5"
push:
tags:
# Matches release/<namespace>/<resource_name>/<semantic_version>
+7 -6
View File
@@ -1,21 +1,22 @@
---
display_name: AgentAPI
description: Building block for modules that need to run an agentapi server
description: Building block for modules that need to run an AgentAPI server
icon: ../../../../.icons/coder.svg
verified: true
tags: [internal]
tags: [internal, library]
---
# AgentAPI
The AgentAPI module is a building block for modules that need to run an agentapi server. It is intended primarily for internal use by Coder to create modules compatible with Tasks.
> [!CAUTION]
> We do not recommend using this module directly. Instead, please consider using one of our [Tasks-compatible AI agent modules](https://registry.coder.com/modules?search=tag%3Atasks).
We do not recommend using this module directly. Instead, please consider using one of our [Tasks-compatible AI agent modules](https://registry.coder.com/modules?search=tag%3Atasks).
The AgentAPI module is a building block for modules that need to run an AgentAPI server. It is intended primarily for internal use by Coder to create modules compatible with Tasks.
```tf
module "agentapi" {
source = "registry.coder.com/coder/agentapi/coder"
version = "1.0.1"
version = "1.0.2"
agent_id = var.agent_id
web_app_slug = local.app_slug
@@ -50,4 +51,4 @@ module "agentapi" {
## For module developers
For a complete example of how to use this module, see the [goose module](https://github.com/coder/registry/blob/main/registry/coder/modules/goose/main.tf).
For a complete example of how to use this module, see the [Goose module](https://github.com/coder/registry/blob/main/registry/coder/modules/goose/main.tf).
+8 -33
View File
@@ -13,7 +13,7 @@ Run [Aider](https://aider.chat) AI pair programming in your workspace. This modu
```tf
module "aider" {
source = "registry.coder.com/coder/aider/coder"
version = "1.1.1"
version = "1.1.2"
agent_id = coder_agent.example.id
}
```
@@ -30,29 +30,8 @@ module "aider" {
## Module Parameters
| Parameter | Description | Type | Default |
| ---------------------------------- | -------------------------------------------------------------------------- | -------- | ------------------- |
| `agent_id` | The ID of a Coder agent (required) | `string` | - |
| `folder` | The folder to run Aider in | `string` | `/home/coder` |
| `install_aider` | Whether to install Aider | `bool` | `true` |
| `aider_version` | The version of Aider to install | `string` | `"latest"` |
| `use_screen` | Whether to use screen for running Aider in the background | `bool` | `true` |
| `use_tmux` | Whether to use tmux instead of screen for running Aider in the background | `bool` | `false` |
| `session_name` | Name for the persistent session (screen or tmux) | `string` | `"aider"` |
| `order` | Position of the app in the UI presentation | `number` | `null` |
| `icon` | The icon to use for the app | `string` | `"/icon/aider.svg"` |
| `experiment_report_tasks` | Whether to enable task reporting | `bool` | `true` |
| `system_prompt` | System prompt for instructing Aider on task reporting and behavior | `string` | See default in code |
| `task_prompt` | Task prompt to use with Aider | `string` | `""` |
| `ai_provider` | AI provider to use with Aider (openai, anthropic, azure, etc.) | `string` | `"anthropic"` |
| `ai_model` | AI model to use (can use Aider's built-in aliases like "sonnet", "4o") | `string` | `"sonnet"` |
| `ai_api_key` | API key for the selected AI provider | `string` | `""` |
| `custom_env_var_name` | Custom environment variable name when using custom provider | `string` | `""` |
| `experiment_pre_install_script` | Custom script to run before installing Aider | `string` | `null` |
| `experiment_post_install_script` | Custom script to run after installing Aider | `string` | `null` |
| `experiment_additional_extensions` | Additional extensions configuration in YAML format to append to the config | `string` | `null` |
> **Note**: `use_screen` and `use_tmux` cannot both be enabled at the same time. By default, `use_screen` is set to `true` and `use_tmux` is set to `false`.
> [!NOTE]
> The `use_screen` and `use_tmux` parameters cannot both be enabled at the same time. By default, `use_screen` is set to `true` and `use_tmux` is set to `false`.
## Usage Examples
@@ -68,7 +47,7 @@ variable "anthropic_api_key" {
module "aider" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/aider/coder"
version = "1.1.1"
version = "1.1.2"
agent_id = coder_agent.example.id
ai_api_key = var.anthropic_api_key
}
@@ -93,7 +72,7 @@ variable "openai_api_key" {
module "aider" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/aider/coder"
version = "1.1.1"
version = "1.1.2"
agent_id = coder_agent.example.id
use_tmux = true
ai_provider = "openai"
@@ -114,7 +93,7 @@ variable "custom_api_key" {
module "aider" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/aider/coder"
version = "1.1.1"
version = "1.1.2"
agent_id = coder_agent.example.id
ai_provider = "custom"
custom_env_var_name = "MY_CUSTOM_API_KEY"
@@ -131,7 +110,7 @@ You can extend Aider's capabilities by adding custom extensions:
module "aider" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/aider/coder"
version = "1.1.1"
version = "1.1.2"
agent_id = coder_agent.example.id
ai_api_key = var.anthropic_api_key
@@ -210,7 +189,7 @@ data "coder_parameter" "ai_prompt" {
module "aider" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/aider/coder"
version = "1.1.1"
version = "1.1.2"
agent_id = coder_agent.example.id
ai_api_key = var.anthropic_api_key
task_prompt = data.coder_parameter.ai_prompt.value
@@ -308,7 +287,3 @@ If you encounter issues:
3. **Browser mode issues**: If the browser interface doesn't open, check that you're accessing it from a machine that can reach your Coder workspace
For more information on using Aider, see the [Aider documentation](https://aider.chat/docs/).
```
```
+5 -4
View File
@@ -13,8 +13,9 @@ Run [Amazon Q](https://aws.amazon.com/q/) in your workspace to access Amazon's A
```tf
module "amazon-q" {
source = "registry.coder.com/coder/amazon-q/coder"
version = "1.1.1"
version = "1.1.2"
agent_id = coder_agent.example.id
# Required: see below for how to generate
experiment_auth_tarball = var.amazon_q_auth_tarball
}
@@ -81,7 +82,7 @@ module "amazon-q" {
```tf
module "amazon-q" {
source = "registry.coder.com/coder/amazon-q/coder"
version = "1.1.1"
version = "1.1.2"
agent_id = coder_agent.example.id
experiment_auth_tarball = var.amazon_q_auth_tarball
experiment_use_tmux = true
@@ -93,7 +94,7 @@ module "amazon-q" {
```tf
module "amazon-q" {
source = "registry.coder.com/coder/amazon-q/coder"
version = "1.1.1"
version = "1.1.2"
agent_id = coder_agent.example.id
experiment_auth_tarball = var.amazon_q_auth_tarball
experiment_report_tasks = true
@@ -105,7 +106,7 @@ module "amazon-q" {
```tf
module "amazon-q" {
source = "registry.coder.com/coder/amazon-q/coder"
version = "1.1.1"
version = "1.1.2"
agent_id = coder_agent.example.id
experiment_auth_tarball = var.amazon_q_auth_tarball
experiment_pre_install_script = "echo Pre-install!"
+2 -1
View File
@@ -9,6 +9,7 @@ terraform {
}
}
variable "agent_id" {
type = string
description = "The ID of a Coder agent."
@@ -250,7 +251,7 @@ resource "coder_script" "claude_code" {
resource "coder_app" "claude_code_web" {
# use a short slug to mitigate https://github.com/coder/coder/issues/15178
slug = local.claude_code_app_slug
display_name = "Claude Code Web"
display_name = "Claude Code Webxz yoxy"
agent_id = var.agent_id
url = "http://localhost:3284/"
icon = var.icon
+2 -2
View File
@@ -26,7 +26,7 @@ variable "order" {
variable "group" {
type = string
description = "The name of a group that this app belongs to."
description = "The name of a group that this app belongs to!"
default = null
}
@@ -155,7 +155,7 @@ module "agentapi" {
set -o pipefail
echo -n '${base64encode(local.install_script)}' | base64 -d > /tmp/install.sh
chmod +x /tmp/install.sh
chmod +x /tmp/install.sh
ARG_PROVIDER='${var.goose_provider}' \
ARG_MODEL='${var.goose_model}' \
@@ -15,9 +15,9 @@ tags: [integration, vault, hashicorp, hvs]
>
> **Use these Coder registry modules instead:**
>
> - **[vault-token](https://registry.coder.com/modules/vault-token)** - Connect to Vault using access tokens
> - **[vault-jwt](https://registry.coder.com/modules/vault-jwt)** - Connect to Vault using JWT/OIDC authentication
> - **[vault-github](https://registry.coder.com/modules/vault-github)** - Connect to Vault using GitHub authentication
> - **[vault-token](https://registry.coder.com/modules/coder/vault-token)** - Connect to Vault using access tokens
> - **[vault-jwt](https://registry.coder.com/modules/coder/vault-jwt)** - Connect to Vault using JWT/OIDC authentication
> - **[vault-github](https://registry.coder.com/modules/coder/vault-github)** - Connect to Vault using GitHub authentication
>
> These modules work with both self-hosted Vault and HCP Vault Dedicated. For migration help, see the [official HashiCorp announcement](https://developer.hashicorp.com/hcp/docs/vault-secrets/end-of-sale-announcement).
@@ -26,7 +26,7 @@ This module lets you fetch all or selective secrets from a [HCP Vault Secrets](h
```tf
module "vault" {
source = "registry.coder.com/coder/hcp-vault-secrets/coder"
version = "1.0.33"
version = "1.0.34"
agent_id = coder_agent.example.id
app_name = "demo-app"
project_id = "aaa-bbb-ccc"
@@ -52,7 +52,7 @@ To fetch all secrets from the HCP Vault Secrets app, skip the `secrets` input.
```tf
module "vault" {
source = "registry.coder.com/coder/hcp-vault-secrets/coder"
version = "1.0.33"
version = "1.0.34"
agent_id = coder_agent.example.id
app_name = "demo-app"
project_id = "aaa-bbb-ccc"
@@ -66,7 +66,7 @@ To fetch selective secrets from the HCP Vault Secrets app, set the `secrets` inp
```tf
module "vault" {
source = "registry.coder.com/coder/hcp-vault-secrets/coder"
version = "1.0.33"
version = "1.0.34"
agent_id = coder_agent.example.id
app_name = "demo-app"
project_id = "aaa-bbb-ccc"
@@ -81,7 +81,7 @@ Set `client_id` and `client_secret` as module inputs.
```tf
module "vault" {
source = "registry.coder.com/coder/hcp-vault-secrets/coder"
version = "1.0.33"
version = "1.0.34"
agent_id = coder_agent.example.id
app_name = "demo-app"
project_id = "aaa-bbb-ccc"
@@ -16,7 +16,7 @@ A module that adds Jupyter Notebook in your Coder template.
module "jupyter-notebook" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jupyter-notebook/coder"
version = "1.1.1"
version = "1.2.0"
agent_id = coder_agent.example.id
}
```
@@ -48,13 +48,27 @@ variable "group" {
default = null
}
variable "requirements_path" {
type = string
description = "The path to requirements.txt with packages to preinstall"
default = ""
}
variable "pip_install_extra_packages" {
type = string
description = "List of extra packages to preinstall (example: numpy==1.26.4 pandas matplotlib<4 scikit-learn)"
default = ""
}
resource "coder_script" "jupyter-notebook" {
agent_id = var.agent_id
display_name = "jupyter-notebook"
icon = "/icon/jupyter.svg"
script = templatefile("${path.module}/run.sh", {
LOG_PATH : var.log_path,
PORT : var.port
PORT : var.port,
REQUIREMENTS_PATH : var.requirements_path,
PIP_INSTALL_EXTRA_PACKAGES : var.pip_install_extra_packages
})
run_on_start = true
}
@@ -20,6 +20,24 @@ else
echo "🥳 jupyter-notebook is already installed\n\n"
fi
# Install packages selected with REQUIREMENTS_PATH
if [ -n "${REQUIREMENTS_PATH}" ]; then
if [ -f "${REQUIREMENTS_PATH}" ]; then
echo "📄 Installing packages from ${REQUIREMENTS_PATH}..."
pipx -q runpip notebook install -r "${REQUIREMENTS_PATH}"
echo "🥳 Packages from ${REQUIREMENTS_PATH} have been installed\n\n"
else
echo "⚠️ REQUIREMENTS_PATH is set to '${REQUIREMENTS_PATH}' but the file does not exist!\n\n"
fi
fi
# Install packages selected with PIP_INSTALL_EXTRA_PACKAGES
if [ -n "${PIP_INSTALL_EXTRA_PACKAGES}" ]; then
echo "📦 Installing additional packages: ${PIP_INSTALL_EXTRA_PACKAGES}"
pipx -q runpip notebook install ${PIP_INSTALL_EXTRA_PACKAGES}
echo "🥳 Additional packages have been installed\n\n"
fi
echo "👷 Starting jupyter-notebook in background..."
echo "check logs at ${LOG_PATH}"
$HOME/.local/bin/jupyter-notebook --NotebookApp.ip='0.0.0.0' --ServerApp.port=${PORT} --no-browser --ServerApp.token='' --ServerApp.password='' > ${LOG_PATH} 2>&1 &
Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

+16
View File
@@ -0,0 +1,16 @@
---
display_name: "Eric Paulsen"
bio: "Field CTO, EMEA @ Coder"
avatar_url: "./.images/avatar.png"
github: "ericpaulsen"
linkedin: "https://www.linkedin.com/in/ericpaulsen17" # Optional
website: "https://ericpaulsen.io" # Optional
support_email: "ericpaulsen@hey.com" # Optional
status: "community"
---
# Eric Paulsen
I'm Eric Paulsen, Coder's EMEA Field CTO based in London, originating from Miami.
Outside of working with our customers, I enjoy teaching myself things,
playing volleyball, and dabbling in a bit of DJing & photography.
@@ -0,0 +1,51 @@
---
display_name: Kubernetes (Deployment) with Dynamic Username
description: Provision Kubernetes Deployments as Coder workspaces with your Username
icon: ../../../../.icons/kubernetes.svg
verified: true
tags: [kubernetes, container, username]
---
# Remote development on Kubernetes with dynamic usernames
Provision Kubernetes Pods as [Coder workspaces](https://coder.com/docs/workspaces) with this example template. This template
will run the workspace container as a non-root UID using your Coder username.
Here is the entrypoint logic in the template that enables Coder to source your username and write it to the Ubuntu operating system at start-up.
> These commands may differ if you run your workspace image with a distro other than Ubuntu.
```terraform
command = ["sh", "-c", <<EOF
# Create user and setup home directory
sudo useradd ${data.coder_workspace_owner.me.name} --home=/home/${data.coder_workspace_owner.me.name} --shell=/bin/bash --uid=1001 --user-group
sudo chown -R ${data.coder_workspace_owner.me.name}:${data.coder_workspace_owner.me.name} /home/${data.coder_workspace_owner.me.name}
# Switch to user and run agent
exec sudo --preserve-env=CODER_AGENT_TOKEN -u ${data.coder_workspace_owner.me.name} sh -c '${coder_agent.main.init_script}'
EOF
]
```
<!-- TODO: Add screenshot -->
## Prerequisites
### Infrastructure
**Cluster**: This template requires an existing Kubernetes cluster
**Container Image**: This template uses the [codercom/enterprise-base:ubuntu image](https://github.com/coder/enterprise-images/tree/main/images/base) with some dev tools preinstalled. To add additional tools, extend this image or build it yourself.
### Authentication
This template authenticates using a `~/.kube/config`, if present on the server, or via built-in authentication if the Coder provisioner is running on Kubernetes with an authorized ServiceAccount. To use another [authentication method](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs#authentication), edit the template.
## Architecture
This template provisions the following resources:
- Kubernetes Deployment (ephemeral)
- Kubernetes persistent volume claim (persistent on `/home/${username}`, where `${username}` is your Coder username)
This means, when the workspace restarts, any tools or files outside of the home directory are not persisted. To pre-bake tools into the workspace (e.g. `python3`), modify the container image. Alternatively, individual developers can [personalize](https://coder.com/docs/dotfiles) their workspaces with dotfiles.
@@ -0,0 +1,327 @@
terraform {
required_providers {
coder = {
source = "coder/coder"
}
kubernetes = {
source = "hashicorp/kubernetes"
}
}
}
provider "coder" {
}
variable "use_kubeconfig" {
type = bool
description = <<-EOF
Use host kubeconfig? (true/false)
Set this to false if the Coder host is itself running as a Pod on the same
Kubernetes cluster as you are deploying workspaces to.
Set this to true if the Coder host is running outside the Kubernetes cluster
for workspaces. A valid "~/.kube/config" must be present on the Coder host.
EOF
default = false
}
variable "namespace" {
type = string
description = "The Kubernetes namespace to create workspaces in (must exist prior to creating workspaces). If the Coder host is itself running as a Pod on the same Kubernetes cluster as you are deploying workspaces to, set this to the same namespace."
}
data "coder_parameter" "cpu" {
name = "cpu"
display_name = "CPU"
description = "The number of CPU cores"
default = "2"
icon = "/icon/memory.svg"
mutable = true
option {
name = "2 Cores"
value = "2"
}
option {
name = "4 Cores"
value = "4"
}
option {
name = "6 Cores"
value = "6"
}
option {
name = "8 Cores"
value = "8"
}
}
data "coder_parameter" "memory" {
name = "memory"
display_name = "Memory"
description = "The amount of memory in GB"
default = "2"
icon = "/icon/memory.svg"
mutable = true
option {
name = "2 GB"
value = "2"
}
option {
name = "4 GB"
value = "4"
}
option {
name = "6 GB"
value = "6"
}
option {
name = "8 GB"
value = "8"
}
}
data "coder_parameter" "home_disk_size" {
name = "home_disk_size"
display_name = "Home disk size"
description = "The size of the home disk in GB"
default = "10"
type = "number"
icon = "/emojis/1f4be.png"
mutable = false
validation {
min = 1
max = 99999
}
}
provider "kubernetes" {
# Authenticate via ~/.kube/config or a Coder-specific ServiceAccount, depending on admin preferences
config_path = var.use_kubeconfig == true ? "~/.kube/config" : null
}
data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {}
module "vscode-web" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vscode-web/coder"
version = "1.3.1"
agent_id = coder_agent.main.id
accept_license = true
}
resource "coder_agent" "main" {
os = "linux"
arch = "amd64"
# The following metadata blocks are optional. They are used to display
# information about your workspace in the dashboard. You can remove them
# if you don't want to display any information.
# For basic resources, you can use the `coder stat` command.
# If you need more control, you can write your own script.
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
}
metadata {
display_name = "Home Disk"
key = "3_home_disk"
script = "coder stat disk --path $${HOME}"
interval = 60
timeout = 1
}
metadata {
display_name = "CPU Usage (Host)"
key = "4_cpu_usage_host"
script = "coder stat cpu --host"
interval = 10
timeout = 1
}
metadata {
display_name = "Memory Usage (Host)"
key = "5_mem_usage_host"
script = "coder stat mem --host"
interval = 10
timeout = 1
}
metadata {
display_name = "Load Average (Host)"
key = "6_load_host"
# get load avg scaled by number of cores
script = <<EOT
echo "`cat /proc/loadavg | awk '{ print $1 }'` `nproc`" | awk '{ printf "%0.2f", $1/$2 }'
EOT
interval = 60
timeout = 1
}
}
resource "kubernetes_persistent_volume_claim" "home" {
metadata {
name = "coder-${data.coder_workspace.me.id}-home"
namespace = var.namespace
labels = {
"app.kubernetes.io/name" = "coder-pvc"
"app.kubernetes.io/instance" = "coder-pvc-${data.coder_workspace.me.id}"
"app.kubernetes.io/part-of" = "coder"
//Coder-specific labels.
"com.coder.resource" = "true"
"com.coder.workspace.id" = data.coder_workspace.me.id
"com.coder.workspace.name" = data.coder_workspace.me.name
"com.coder.user.id" = data.coder_workspace_owner.me.id
"com.coder.user.username" = data.coder_workspace_owner.me.name
}
annotations = {
"com.coder.user.email" = data.coder_workspace_owner.me.email
}
}
wait_until_bound = false
spec {
access_modes = ["ReadWriteOnce"]
resources {
requests = {
storage = "${data.coder_parameter.home_disk_size.value}Gi"
}
}
}
}
resource "kubernetes_deployment" "main" {
count = data.coder_workspace.me.start_count
depends_on = [
kubernetes_persistent_volume_claim.home
]
wait_for_rollout = false
metadata {
name = "coder-${data.coder_workspace.me.id}"
namespace = var.namespace
labels = {
"app.kubernetes.io/name" = "coder-workspace"
"app.kubernetes.io/instance" = "coder-workspace-${data.coder_workspace.me.id}"
"app.kubernetes.io/part-of" = "coder"
"com.coder.resource" = "true"
"com.coder.workspace.id" = data.coder_workspace.me.id
"com.coder.workspace.name" = data.coder_workspace.me.name
"com.coder.user.id" = data.coder_workspace_owner.me.id
"com.coder.user.username" = data.coder_workspace_owner.me.name
}
annotations = {
"com.coder.user.email" = data.coder_workspace_owner.me.email
}
}
spec {
replicas = 1
selector {
match_labels = {
"app.kubernetes.io/name" = "coder-workspace"
"app.kubernetes.io/instance" = "coder-workspace-${data.coder_workspace.me.id}"
"app.kubernetes.io/part-of" = "coder"
"com.coder.resource" = "true"
"com.coder.workspace.id" = data.coder_workspace.me.id
"com.coder.workspace.name" = data.coder_workspace.me.name
"com.coder.user.id" = data.coder_workspace_owner.me.id
"com.coder.user.username" = data.coder_workspace_owner.me.name
}
}
strategy {
type = "Recreate"
}
template {
metadata {
labels = {
"app.kubernetes.io/name" = "coder-workspace"
"app.kubernetes.io/instance" = "coder-workspace-${data.coder_workspace.me.id}"
"app.kubernetes.io/part-of" = "coder"
"com.coder.resource" = "true"
"com.coder.workspace.id" = data.coder_workspace.me.id
"com.coder.workspace.name" = data.coder_workspace.me.name
"com.coder.user.id" = data.coder_workspace_owner.me.id
"com.coder.user.username" = data.coder_workspace_owner.me.name
}
}
spec {
container {
name = "dev"
image = "codercom/enterprise-base:ubuntu"
image_pull_policy = "Always"
command = ["sh", "-c", <<EOF
# Create user and setup home directory
sudo useradd ${lower(data.coder_workspace_owner.me.name)} --home=/home/${lower(data.coder_workspace_owner.me.name)} --shell=/bin/bash --uid=1001 --user-group
sudo chown -R ${lower(data.coder_workspace_owner.me.name)}:${lower(data.coder_workspace_owner.me.name)} /home/${lower(data.coder_workspace_owner.me.name)}
# Switch to user and run agent
exec sudo --preserve-env=CODER_AGENT_TOKEN -u ${lower(data.coder_workspace_owner.me.name)} sh -c '${coder_agent.main.init_script}'
EOF
]
env {
name = "CODER_AGENT_TOKEN"
value = coder_agent.main.token
}
resources {
requests = {
"cpu" = "250m"
"memory" = "512Mi"
}
limits = {
"cpu" = "${data.coder_parameter.cpu.value}"
"memory" = "${data.coder_parameter.memory.value}Gi"
}
}
volume_mount {
mount_path = "/home/${lower(data.coder_workspace_owner.me.name)}"
name = "home"
read_only = false
}
}
volume {
name = "home"
persistent_volume_claim {
claim_name = kubernetes_persistent_volume_claim.home.metadata.0.name
read_only = false
}
}
affinity {
// This affinity attempts to spread out all workspace pods evenly across
// nodes.
pod_anti_affinity {
preferred_during_scheduling_ignored_during_execution {
weight = 1
pod_affinity_term {
topology_key = "kubernetes.io/hostname"
label_selector {
match_expressions {
key = "app.kubernetes.io/name"
operator = "In"
values = ["coder-workspace"]
}
}
}
}
}
}
}
}
}
}