From 5ff1c7d86fdfb98beb5522d077d570014f187f40 Mon Sep 17 00:00:00 2001 From: brymut Date: Fri, 25 Jul 2025 21:39:04 +0300 Subject: [PATCH] feat: add Hetzner Cloud server template and configuration files --- .github/typos.toml | 1 + .icons/hetzner.svg | 5 + registry/brymut/.images/avatar.png | Bin 0 -> 31311 bytes registry/brymut/README.md | 8 + .../brymut/templates/hetzner-linux/README.md | 28 +++ .../hetzner-linux/cloud-config.yaml.tftpl | 46 +++++ .../brymut/templates/hetzner-linux/main.tf | 191 ++++++++++++++++++ 7 files changed, 279 insertions(+) create mode 100644 .icons/hetzner.svg create mode 100644 registry/brymut/.images/avatar.png create mode 100644 registry/brymut/README.md create mode 100644 registry/brymut/templates/hetzner-linux/README.md create mode 100644 registry/brymut/templates/hetzner-linux/cloud-config.yaml.tftpl create mode 100644 registry/brymut/templates/hetzner-linux/main.tf diff --git a/.github/typos.toml b/.github/typos.toml index f27257a2..4704aab1 100644 --- a/.github/typos.toml +++ b/.github/typos.toml @@ -2,6 +2,7 @@ muc = "muc" # For Munich location code Hashi = "Hashi" HashiCorp = "HashiCorp" +hel1 = "hel1" # For Helsinki location code [files] extend-exclude = ["registry/coder/templates/aws-devcontainer/architecture.svg"] #False positive \ No newline at end of file diff --git a/.icons/hetzner.svg b/.icons/hetzner.svg new file mode 100644 index 00000000..74bb87c1 --- /dev/null +++ b/.icons/hetzner.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/registry/brymut/.images/avatar.png b/registry/brymut/.images/avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..d23ac61f24e394462b091d558941c98e407e016e GIT binary patch literal 31311 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 API Tokens) + +### Authentication + +This template assumes that the Coder Provisioner is run in an environment that is authenticated with Hetzner Cloud. + +Obtain a Hetzner Cloud API token from your [Hetzner Cloud Console](https://console.hetzner.cloud/projects) and provide it as the `hcloud_token` variable when creating a workspace. +For more authentication options, see the [Terraform provider documentation](https://registry.terraform.io/providers/hetznercloud/hcloud/latest/docs#authentication). + +> **Note** +> This template is designed to be a starting point! Edit the Terraform to extend the template to support your use case. diff --git a/registry/brymut/templates/hetzner-linux/cloud-config.yaml.tftpl b/registry/brymut/templates/hetzner-linux/cloud-config.yaml.tftpl new file mode 100644 index 00000000..a2400b54 --- /dev/null +++ b/registry/brymut/templates/hetzner-linux/cloud-config.yaml.tftpl @@ -0,0 +1,46 @@ +#cloud-config +users: + - name: ${username} + sudo: ["ALL=(ALL) NOPASSWD:ALL"] + groups: sudo + shell: /bin/bash +packages: + - git +mounts: + - [ + "LABEL=${home_volume_label}", + "/home/${username}", + auto, + "defaults,uid=1000,gid=1000", + ] +write_files: + - path: /opt/coder/init + permissions: "0755" + encoding: b64 + content: ${init_script} + - path: /etc/systemd/system/coder-agent.service + permissions: "0644" + content: | + [Unit] + Description=Coder Agent + After=network-online.target + Wants=network-online.target + + [Service] + User=${username} + ExecStart=/opt/coder/init + Environment=CODER_AGENT_TOKEN=${coder_agent_token} + Restart=always + RestartSec=10 + TimeoutStopSec=90 + KillMode=process + + OOMScoreAdjust=-900 + SyslogIdentifier=coder-agent + + [Install] + WantedBy=multi-user.target +runcmd: + - chown ${username}:${username} /home/${username} + - systemctl enable coder-agent + - systemctl start coder-agent diff --git a/registry/brymut/templates/hetzner-linux/main.tf b/registry/brymut/templates/hetzner-linux/main.tf new file mode 100644 index 00000000..b248e10d --- /dev/null +++ b/registry/brymut/templates/hetzner-linux/main.tf @@ -0,0 +1,191 @@ +terraform { + required_providers { + hcloud = { + source = "hetznercloud/hcloud" + } + coder = { + source = "coder/coder" + } + } +} + +variable "hcloud_token" { + sensitive = true +} + +provider "hcloud" { + token = var.hcloud_token +} + +data "coder_parameter" "hcloud_location" { + name = "hcloud_location" + display_name = "Hetzner Location" + description = "Select the Hetzner Cloud location for your workspace." + type = "string" + default = "fsn1" + option { + name = "DE Falkenstein" + value = "fsn1" + } + option { + name = "US Ashburn, VA" + value = "ash" + } + option { + name = "US Hillsboro, OR" + value = "hil" + } + option { + name = "SG Singapore" + value = "sin" + } + option { + name = "DE Nuremberg" + value = "nbg1" + } + option { + name = "FI Helsinki" + value = "hel1" + } +} + +data "coder_parameter" "hcloud_server_type" { + name = "hcloud_server_type" + display_name = "Hetzner Server Type" + description = "Select the Hetzner Cloud server type for your workspace." + type = "string" + default = "cx22" + option { + name = "CX22 (2 vCPU, 4GB RAM, 40GB, $3.99/mo)" + value = "cx22" + } + option { + name = "CPX11 (2 vCPU, 2GB RAM, 40GB, $4.49/mo)" + value = "cpx11" + } + option { + name = "CX32 (4 vCPU, 8GB RAM, 80GB, $6.99/mo)" + value = "cx32" + } + option { + name = "CPX21 (3 vCPU, 4GB RAM, 80GB, $7.99/mo)" + value = "cpx21" + } + option { + name = "CPX31 (4 vCPU, 8GB RAM, 160GB, $14.99/mo)" + value = "cpx31" + } + option { + name = "CX42 (8 vCPU, 16GB RAM, 160GB, $17.99/mo)" + value = "cx42" + } + option { + name = "CPX41 (8 vCPU, 16GB RAM, 240GB, $27.49/mo)" + value = "cpx41" + } + option { + name = "CX52 (16 vCPU, 32GB RAM, 320GB, $35.49/mo)" + value = "cx52" + } + option { + name = "CPX51 (16 vCPU, 32GB RAM, 360GB, $60.49/mo)" + value = "cpx51" + } +} + +resource "hcloud_server" "dev" { + name = "dev" + image = "ubuntu-24.04" + server_type = data.coder_parameter.hcloud_server_type.value + location = data.coder_parameter.hcloud_location.value + public_net { + ipv4_enabled = true + ipv6_enabled = true + } + user_data = templatefile("cloud-config.yaml.tftpl", { + username = lower(data.coder_workspace_owner.me.name) + home_volume_label = hcloud_volume.home_volume.name + init_script = base64encode(coder_agent.main.init_script) + coder_agent_token = coder_agent.main.token + }) +} + +resource "hcloud_volume" "home_volume" { + name = "coder-${data.coder_workspace.me.id}-home" + size = data.coder_parameter.home_volume_size.value + location = data.coder_parameter.hcloud_location.value + format = "ext4" + delete_protection = true +} + +resource "hcloud_volume_attachment" "home_volume_attachment" { + volume_id = hcloud_volume.home_volume.id + server_id = hcloud_server.dev.id +} + +locals { + username = data.coder_workspace_owner.me.name +} + +data "coder_provisioner" "me" { +} + +provider "coder" { +} + +data "coder_workspace" "me" { +} + +data "coder_workspace_owner" "me" { +} + +data "coder_parameter" "home_volume_size" { + name = "home_volume_size" + display_name = "Home volume size" + description = "How large would you like your home volume to be (in GB)?" + type = "number" + default = "20" + mutable = false + validation { + min = 1 + max = 100 # Adjust the max size as needed + } +} + +resource "coder_agent" "main" { + os = "linux" + arch = "amd64" + + metadata { + key = "cpu" + display_name = "CPU Usage" + interval = 5 + timeout = 5 + script = "coder stat cpu" + } + metadata { + key = "memory" + display_name = "Memory Usage" + interval = 5 + timeout = 5 + script = "coder stat mem" + } + metadata { + key = "home" + display_name = "Home Usage" + interval = 600 # every 10 minutes + timeout = 30 # df can take a while on large filesystems + script = "coder stat disk --path /home/${lower(data.coder_workspace_owner.me.name)}" + } +} + +module "code-server" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/code-server/coder" + + # This ensures that the latest non-breaking version of the module gets downloaded, you can also pin the module version to prevent breaking changes in production. + version = "~> 1.0" + + agent_id = coder_agent.main.id + order = 1 +}