terraform { required_providers { coder = { source = "coder/coder" } docker = { source = "kreuzwerker/docker" } } } provider "docker" { host = var.docker_socket != "" ? var.docker_socket : null } locals { username = data.coder_workspace_owner.me.name } data "coder_provisioner" "me" {} data "coder_workspace" "me" {} data "coder_workspace_owner" "me" {} data "coder_parameter" "repo_url" { name = "Repository URL" description = "Git repository to clone when workspace is created (public repo only)" type = "string" default = "" } locals { effective_repo_url = var.repo_url != "" ? var.repo_url : data.coder_parameter.repo_url.value } 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 # Clone repo if URL is set if [ -n "${local.effective_repo_url}" ]; then if [ -d ~/repo ] && [ "$(ls -A ~/repo)" ]; then echo "⚠️ Skipping clone: ~/repo already exists and is not empty." else echo "==> Cloning repository from: ${local.effective_repo_url}" git clone --verbose "${local.effective_repo_url}" ~/repo \ && echo "✅ Clone successful." \ || echo "❌ Failed to clone repo. Please check the URL or access permissions." fi fi # Language-specific startup commands ${var.language_startup_script} EOT 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 } 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 } # Language-specific metadata dynamic "metadata" { for_each = var.language_metadata content { display_name = metadata.value.display_name key = metadata.value.key script = metadata.value.script interval = metadata.value.interval timeout = metadata.value.timeout } } } module "code-server" { count = data.coder_workspace.me.start_count source = "registry.coder.com/modules/code-server/coder" version = ">= 1.0.0" agent_id = coder_agent.main.id order = 1 extensions = var.vscode_extensions settings = var.vscode_settings } module "jetbrains_gateway" { count = data.coder_workspace.me.start_count source = "registry.coder.com/modules/jetbrains-gateway/coder" jetbrains_ides = var.jetbrains_ides default = var.jetbrains_default folder = "/home/coder" version = ">= 1.0.0" latest = true agent_id = coder_agent.main.id agent_name = "main" order = 2 } module "filebrowser" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/filebrowser/coder" version = ">= 1.0.0" agent_id = coder_agent.main.id } resource "docker_volume" "home_volume" { name = "coder-${data.coder_workspace.me.id}-home" lifecycle { ignore_changes = all } labels { label = "coder.owner" value = data.coder_workspace_owner.me.name } labels { label = "coder.owner_id" value = data.coder_workspace_owner.me.id } labels { label = "coder.workspace_id" value = data.coder_workspace.me.id } labels { label = "coder.workspace_name_at_creation" value = data.coder_workspace.me.name } } data "docker_registry_image" "coder-images" { name = var.docker_image } resource "docker_image" "coder-images" { name = data.docker_registry_image.coder-images.name pull_triggers = [data.docker_registry_image.coder-images.sha256_digest] } resource "docker_container" "workspace" { count = data.coder_workspace.me.start_count image = docker_image.coder-images.image_id name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}" hostname = data.coder_workspace.me.name 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/coder" volume_name = docker_volume.home_volume.name read_only = false } labels { label = "coder.owner" value = data.coder_workspace_owner.me.name } labels { label = "coder.owner_id" value = data.coder_workspace_owner.me.id } labels { label = "coder.workspace_id" value = data.coder_workspace.me.id } labels { label = "coder.workspace_name" value = data.coder_workspace.me.name } }