terraform { required_providers { coder = { source = "coder/coder" } docker = { source = "kreuzwerker/docker" } # Not used directly in this config. Existing workspace state from before # the jetbrains module was removed still has resources tagged under this # provider (the module used it internally to fetch IDE metadata) - # terraform init only installs providers the current config declares, so # without this, plan/apply fails with "Missing required provider" while # trying to reconcile/destroy those leftover state entries. Safe to drop # once every workspace has updated past the jetbrains-module version. http = { source = "hashicorp/http" } } } locals { env_name = "Web Applications" profile = jsondecode(file("${path.module}/profile.code-profile")) settings_raw = jsondecode(local.profile.settings).settings extensions = [for e in jsondecode(local.profile.extensions) : e.identifier.id] } variable "docker_socket" { default = "" description = "(Optional) Docker socket URI" type = string } provider "docker" { # Defaulting to null if the variable is an empty string lets us have an optional variable without having to set our own default host = var.docker_socket != "" ? var.docker_socket : null } data "coder_provisioner" "me" {} data "coder_workspace" "me" {} data "coder_workspace_owner" "me" {} resource "coder_agent" "main" { arch = data.coder_provisioner.me.arch os = "linux" startup_script = <<-EOT set -e # Prepare user home with default files on first start. if [ ! -f ~/.init_done ]; then cp -rT /etc/skel ~ touch ~/.init_done fi # Add any commands that should be executed at workspace startup (e.g install requirements, start a program, etc) here EOT # These environment variables allow you to make Git commits right away after creating a # workspace. Note that they take precedence over configuration defined in ~/.gitconfig! # You can remove this block if you'd prefer to configure Git manually or using # dotfiles. (see docs/dotfiles.md) # # RUST_BACKTRACE/PNPM_HOME/BUN_INSTALL are also baked in as image ENV (see # Dockerfile) so every process picks them up; restated here so they surface # on the workspace dashboard too. env = { GIT_AUTHOR_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) GIT_AUTHOR_EMAIL = "${data.coder_workspace_owner.me.email}" GIT_COMMITTER_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}" RUST_BACKTRACE = "1" PNPM_HOME = "/home/coder/.local/share/pnpm" BUN_INSTALL = "/home/coder/.bun" } # 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 = < "$HOME/.local/share/code-server/User/settings.json" EOT } # Drops the shared CLI setup wizard onto the workspace and hooks it into # every new interactive shell (via .bashrc) until the user completes it. # See ./cli-setup-wizard.sh for what it actually asks. resource "coder_script" "cli_setup_wizard" { agent_id = coder_agent.main.id display_name = "Install CLI Setup Wizard" run_on_start = true script = <<-EOT #!/bin/bash set -e mkdir -p /opt/coder echo '${base64encode(file("${path.module}/cli-setup-wizard.sh"))}' | base64 -d > /opt/coder/cli-setup-wizard.sh chmod +x /opt/coder/cli-setup-wizard.sh MARKER="# >>> coder cli setup wizard >>>" if ! grep -qF "$MARKER" "$HOME/.bashrc" 2>/dev/null; then { echo "" echo "$MARKER" echo 'export PATH="$HOME/.local/bin:$PATH"' echo 'source /opt/coder/cli-setup-wizard.sh' echo "# <<< coder cli setup wizard <<<" } >> "$HOME/.bashrc" fi EOT } # Bun (and the rest of the toolchain - Rust, Node/pnpm/yarn, Python CV/ONNX # packages, DB clients) is baked into the workspace image at build time (see # Dockerfile) rather than installed here on every start. Docker populates a # fresh, empty named volume from the image's directory contents on first # mount, so $HOME/.bun, $HOME/.cargo, $HOME/.rustup etc. land in the # persistent home_volume automatically the first time a workspace boots - # same mechanism the /etc/skel copy above relies on. BUN_INSTALL and PATH # are set as image ENV plus restated on coder_agent.env above. # Installs this repo's Agent Skills into Claude Code, GitHub Copilot CLI, and # Antigravity CLI's skills directories. See ./install-skills.sh. # Web has no matching entry in extensions/custom-specialty-plugin/skills, # so it only gets the common awesome-skills-plugin bundle. resource "coder_script" "install_skills" { agent_id = coder_agent.main.id display_name = "Install Agent Skills" run_on_start = true script = <<-EOT #!/bin/bash set -e mkdir -p /opt/coder echo '${base64encode(file("${path.module}/install-skills.sh"))}' | base64 -d > /opt/coder/install-skills.sh chmod +x /opt/coder/install-skills.sh SPECIALTY_SKILLS="" /opt/coder/install-skills.sh EOT }