From 3fb4a54a9f09017adafebf192fe8ceb3d90d0bee Mon Sep 17 00:00:00 2001 From: Excellencedev Date: Sun, 23 Nov 2025 14:12:57 +0100 Subject: [PATCH] Add Hetzner Cloud server template example --- .github/typos.toml | 1 + .icons/hetzner.svg | 5 + registry/Excellencedev/.images/avatar.jfif | Bin 0 -> 18614 bytes registry/Excellencedev/README.md | 7 + .../templates/hetzner-linux/README.md | 29 +++ .../hetzner-linux/cloud-config.yaml.tftpl | 62 ++++++ .../hetzner_server_types.json\342\200\216" | 27 +++ .../templates/hetzner-linux/main.tf | 183 ++++++++++++++++++ 8 files changed, 314 insertions(+) create mode 100644 .icons/hetzner.svg create mode 100644 registry/Excellencedev/.images/avatar.jfif create mode 100644 registry/Excellencedev/README.md create mode 100644 registry/Excellencedev/templates/hetzner-linux/README.md create mode 100644 registry/Excellencedev/templates/hetzner-linux/cloud-config.yaml.tftpl create mode 100644 "registry/Excellencedev/templates/hetzner-linux/hetzner_server_types.json\342\200\216" create mode 100644 registry/Excellencedev/templates/hetzner-linux/main.tf diff --git a/.github/typos.toml b/.github/typos.toml index 7ebdacef4..d0b1f2863 100644 --- a/.github/typos.toml +++ b/.github/typos.toml @@ -3,6 +3,7 @@ muc = "muc" # For Munich location code tyo = "tyo" # For Tokyo location code Hashi = "Hashi" HashiCorp = "HashiCorp" +hel = "hel" # For Helsinki location code mavrickrishi = "mavrickrishi" # Username mavrick = "mavrick" # Username inh = "inh" # Option in setpriv command diff --git a/.icons/hetzner.svg b/.icons/hetzner.svg new file mode 100644 index 000000000..74bb87c1a --- /dev/null +++ b/.icons/hetzner.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/registry/Excellencedev/.images/avatar.jfif b/registry/Excellencedev/.images/avatar.jfif new file mode 100644 index 0000000000000000000000000000000000000000..b6663550b0fb75a86fa62b907827bc27728196b2 GIT binary patch literal 18614 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

tPtxl0p8Q`i8H-`===4 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 D(a7_~ literal 0 HcmV?d00001 diff --git a/registry/Excellencedev/README.md b/registry/Excellencedev/README.md new file mode 100644 index 000000000..b1aea7171 --- /dev/null +++ b/registry/Excellencedev/README.md @@ -0,0 +1,7 @@ +--- +display_name: "Excellencedev" +bio: "Love to contribute" +avatar: "./.images/avatar.jfif" +support_email: "ademiluyisuccessandexcellence@gmail.com" +status: "community" +--- \ No newline at end of file diff --git a/registry/Excellencedev/templates/hetzner-linux/README.md b/registry/Excellencedev/templates/hetzner-linux/README.md new file mode 100644 index 000000000..a7ae7a0bc --- /dev/null +++ b/registry/Excellencedev/templates/hetzner-linux/README.md @@ -0,0 +1,29 @@ +--- +display_name: Hetzner Cloud Server +description: Provision Hetzner Cloud servers as Coder workspaces +icon: ../../../../.icons/hetzner.svg +tags: [vm, linux, hetzner] +--- + +# Remote Development on Hetzner Cloud (Linux) + +Provision Hetzner Cloud servers as [Coder workspaces](https://coder.com/docs/workspaces) with this example template. + +> [!IMPORTANT] +> **Volume Management & Costs:** Hetzner Cloud volumes persist even when workspaces are stopped and will continue to incur storage costs (€0.0476/GB/month). Volumes are only automatically deleted when the workspace is completely deleted. Monitor your volumes in the [Hetzner Cloud Console](https://console.hetzner.cloud/) to manage costs effectively. + +## Prerequisites + +To deploy workspaces as Hetzner Cloud servers, you'll need: + +- Hetzner Cloud [API token](https://console.hetzner.cloud/projects) (create under Security > 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. \ No newline at end of file diff --git a/registry/Excellencedev/templates/hetzner-linux/cloud-config.yaml.tftpl b/registry/Excellencedev/templates/hetzner-linux/cloud-config.yaml.tftpl new file mode 100644 index 000000000..4478ee621 --- /dev/null +++ b/registry/Excellencedev/templates/hetzner-linux/cloud-config.yaml.tftpl @@ -0,0 +1,62 @@ +#cloud-config +users: + - name: ${username} + sudo: ["ALL=(ALL) NOPASSWD:ALL"] + groups: sudo + shell: /bin/bash +packages: + - git +%{ if home_volume_label != "" ~} +fs_setup: + - device: /dev/disk/by-id/scsi-0HC_Volume_${volume_id} + filesystem: ext4 + label: ${home_volume_label} + overwrite: false # This prevents reformatting the disk on every boot + +mounts: + - [ + "/dev/disk/by-id/scsi-0HC_Volume_${volume_id}", + "/home/${username}", + auto, + "defaults,uid=1000,gid=1000", + ] +%{ endif ~} +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: +%{ if home_volume_label != "" ~} + - | + until [ -e /dev/disk/by-id/scsi-0HC_Volume_${volume_id} ]; do + echo "Waiting for volume device..." + sleep 2 + done +%{ endif ~} + - mount -a + - chown ${username}:${username} /home/${username} + - systemctl enable coder-agent + - systemctl start coder-agent \ No newline at end of file diff --git "a/registry/Excellencedev/templates/hetzner-linux/hetzner_server_types.json\342\200\216" "b/registry/Excellencedev/templates/hetzner-linux/hetzner_server_types.json\342\200\216" new file mode 100644 index 000000000..6be0938a7 --- /dev/null +++ "b/registry/Excellencedev/templates/hetzner-linux/hetzner_server_types.json\342\200\216" @@ -0,0 +1,27 @@ +{ + "type_meta": { + "cx22": { "cores": 2, "memory_gb": 4, "disk_gb": 40 }, + "cx32": { "cores": 4, "memory_gb": 8, "disk_gb": 80 }, + "cx42": { "cores": 8, "memory_gb": 16, "disk_gb": 160 }, + "cx52": { "cores": 16, "memory_gb": 32, "disk_gb": 320 }, + "cpx11": { "cores": 2, "memory_gb": 2, "disk_gb": 40 }, + "cpx21": { "cores": 3, "memory_gb": 4, "disk_gb": 80 }, + "cpx31": { "cores": 4, "memory_gb": 8, "disk_gb": 160 }, + "cpx41": { "cores": 8, "memory_gb": 16, "disk_gb": 240 }, + "cpx51": { "cores": 16, "memory_gb": 32, "disk_gb": 360 }, + "ccx13": { "cores": 2, "memory_gb": 8, "disk_gb": 80 }, + "ccx23": { "cores": 4, "memory_gb": 16, "disk_gb": 160 }, + "ccx33": { "cores": 8, "memory_gb": 32, "disk_gb": 240 }, + "ccx43": { "cores": 16, "memory_gb": 64, "disk_gb": 360 }, + "ccx53": { "cores": 32, "memory_gb": 128, "disk_gb": 600 }, + "ccx63": { "cores": 48, "memory_gb": 192, "disk_gb": 960 } + }, + "availability": { + "fsn1": ["cpx11", "cpx21", "cpx31", "cpx41", "cpx51", "ccx13", "ccx23", "ccx33"], + "ash": ["cpx11", "cpx21", "cpx31", "cpx41", "cpx51", "ccx13", "ccx23", "ccx33"], + "hel1": ["cx22", "cpx11", "cpx21", "cpx31", "cpx41", "cpx51", "ccx13", "ccx23", "ccx33"], + "hil": ["cpx11", "cpx21", "cpx31", "cpx41", "ccx13", "ccx23", "ccx33"], + "nbg1": ["cx22", "cx32", "cx42", "cx52", "cpx11", "cpx21", "cpx31", "cpx41", "cpx51", "ccx13", "ccx23", "ccx33"], + "sin": ["cpx11", "cpx21", "cpx31", "cpx41", "cpx51", "ccx13", "ccx23", "ccx33"] + } +} diff --git a/registry/Excellencedev/templates/hetzner-linux/main.tf b/registry/Excellencedev/templates/hetzner-linux/main.tf new file mode 100644 index 000000000..4806230ce --- /dev/null +++ b/registry/Excellencedev/templates/hetzner-linux/main.tf @@ -0,0 +1,183 @@ +terraform { + required_providers { + hcloud = { + source = "hetznercloud/hcloud" + } + coder = { + source = "coder/coder" + } + } +} + +variable "hcloud_token" { + sensitive = true +} + +provider "hcloud" { + token = var.hcloud_token +} + +# Available locations: https://docs.hetzner.com/cloud/general/locations/ +data "coder_parameter" "hcloud_location" {Expand commentComment on line R21ResolvedCode has comments. Press enter to view. + 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" + } +} + +# Available server types: https://docs.hetzner.com/cloud/servers/overview/ +data "coder_parameter" "hcloud_server_type" {Expand commentComment on line R54ResolvedCode has comments. Press enter to view. + name = "hcloud_server_type" + display_name = "Hetzner Server Type" + description = "Select the Hetzner Cloud server type for your workspace." + type = "string" + + dynamic "option" { + for_each = local.hcloud_server_type_options_for_selected_location + content { + name = option.value.name + value = option.value.value + } + } +} + +resource "hcloud_server" "dev" { + count = data.coder_workspace.me.start_count + name = "coder-${data.coder_workspace.me.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 = "coder-${data.coder_workspace.me.id}-home" + volume_id = hcloud_volume.home_volume.id + init_script = base64encode(coder_agent.main.init_script) + coder_agent_token = coder_agent.main.token + }) + labels = { + "coder_workspace_name" = data.coder_workspace.me.name, + "coder_workspace_owner" = data.coder_workspace_owner.me.name, + } +} + +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 + labels = { + "coder_workspace_name" = data.coder_workspace.me.name, + "coder_workspace_owner" = data.coder_workspace_owner.me.name, + } +} + +resource "hcloud_volume_attachment" "home_volume_attachment" { + count = data.coder_workspace.me.start_count + volume_id = hcloud_volume.home_volume.id + server_id = hcloud_server.dev[count.index].id + automount = false +} + +locals { + username = lower(data.coder_workspace_owner.me.name) + + # Data source: local JSON file under the module directory + # Check API for latest server types & availability: https://docs.hetzner.cloud/reference/cloud#server-types + hcloud_server_types_data = jsondecode(file("${path.module}/hetzner_server_types.json")) + hcloud_server_type_meta = local.hcloud_server_types_data.type_meta + hcloud_server_types_by_location = local.hcloud_server_types_data.availability + + hcloud_server_type_options_for_selected_location = [ + for type_name in lookup(local.hcloud_server_types_by_location, data.coder_parameter.hcloud_location.value, []) : { + name = format("%s (%d vCPU, %dGB RAM, %dGB)", upper(type_name), local.hcloud_server_type_meta[type_name].cores, local.hcloud_server_type_meta[type_name].memory_gb, local.hcloud_server_type_meta[type_name].disk_gb) + value = type_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/${local.username}" + } +} + +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 +} \ No newline at end of file