Skip to content

Commit a70dd7c

Browse files
committed
feat: add Hetzner Cloud server template and configuration files
1 parent ce1d0cb commit a70dd7c

File tree

5 files changed

+280
-0
lines changed

5 files changed

+280
-0
lines changed

.icons/hetzner.svg

Lines changed: 5 additions & 0 deletions
Loading

registry/brymut/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
display_name: brymut (Bryan Mutai)
3+
bio: Independent software developer based in Kenya, passionate about DevOps and Cloud Native solutions. Combining expert automation and scalability with a strong commitment to the community. Explore collaboration and drive success together.
4+
avatar: https://avatars.githubusercontent.com/u/1020837?v=4
5+
github: brymut
6+
support_email: mutaiwork@gmail.com
7+
status: community
8+
---
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
display_name: Hetzner Cloud Server
3+
description: Provision Hetzner Cloud servers as Coder workspaces
4+
icon: ../../../../.icons/hetzner.svg
5+
maintainer_github: brymut
6+
verified: false
7+
tags: [vm, linux, hetzner]
8+
---
9+
10+
11+
# Remote Development on Hetzner Cloud (Linux)
12+
13+
Provision Hetzner Cloud servers as [Coder workspaces](https://coder.com/docs/workspaces) with this example template.
14+
15+
16+
## Prerequisites
17+
18+
To deploy workspaces as Hetzner Cloud servers, you'll need:
19+
20+
- Hetzner Cloud [API token](https://console.hetzner.cloud/projects) (create under Security > API Tokens)
21+
22+
### Authentication
23+
24+
This template assumes that the Coder Provisioner is run in an environment that is authenticated with Hetzner Cloud.
25+
26+
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.
27+
For more authentication options, see the [Terraform provider documentation](https://registry.terraform.io/providers/hetznercloud/hcloud/latest/docs#authentication).
28+
29+
> **Note**
30+
> This template is designed to be a starting point! Edit the Terraform to extend the template to support your use case.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#cloud-config
2+
users:
3+
- name: ${username}
4+
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
5+
groups: sudo
6+
shell: /bin/bash
7+
packages:
8+
- git
9+
mounts:
10+
- [
11+
"LABEL=${home_volume_label}",
12+
"/home/${username}",
13+
auto,
14+
"defaults,uid=1000,gid=1000",
15+
]
16+
write_files:
17+
- path: /opt/coder/init
18+
permissions: "0755"
19+
encoding: b64
20+
content: ${init_script}
21+
- path: /etc/systemd/system/coder-agent.service
22+
permissions: "0644"
23+
content: |
24+
[Unit]
25+
Description=Coder Agent
26+
After=network-online.target
27+
Wants=network-online.target
28+
29+
[Service]
30+
User=${username}
31+
ExecStart=/opt/coder/init
32+
Environment=CODER_AGENT_TOKEN=${coder_agent_token}
33+
Restart=always
34+
RestartSec=10
35+
TimeoutStopSec=90
36+
KillMode=process
37+
38+
OOMScoreAdjust=-900
39+
SyslogIdentifier=coder-agent
40+
41+
[Install]
42+
WantedBy=multi-user.target
43+
runcmd:
44+
- chown ${username}:${username} /home/${username}
45+
- systemctl enable coder-agent
46+
- systemctl start coder-agent
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
terraform {
2+
required_providers {
3+
hcloud = {
4+
source = "hetznercloud/hcloud"
5+
}
6+
coder = {
7+
source = "coder/coder"
8+
}
9+
}
10+
}
11+
12+
variable "hcloud_token" {
13+
sensitive = true
14+
}
15+
16+
provider "hcloud" {
17+
token = var.hcloud_token
18+
}
19+
20+
data "coder_parameter" "hcloud_location" {
21+
name = "hcloud_location"
22+
display_name = "Hetzner Location"
23+
description = "Select the Hetzner Cloud location for your workspace."
24+
type = "string"
25+
default = "fsn1"
26+
option {
27+
name = "DE Falkenstein"
28+
value = "fsn1"
29+
}
30+
option {
31+
name = "US Ashburn, VA"
32+
value = "ash"
33+
}
34+
option {
35+
name = "US Hillsboro, OR"
36+
value = "hil"
37+
}
38+
option {
39+
name = "SG Singapore"
40+
value = "sin"
41+
}
42+
option {
43+
name = "DE Nuremberg"
44+
value = "nbg1"
45+
}
46+
option {
47+
name = "FI Helsinki"
48+
value = "hel1"
49+
}
50+
}
51+
52+
data "coder_parameter" "hcloud_server_type" {
53+
name = "hcloud_server_type"
54+
display_name = "Hetzner Server Type"
55+
description = "Select the Hetzner Cloud server type for your workspace."
56+
type = "string"
57+
default = "cx22"
58+
option {
59+
name = "CX22 (2 vCPU, 4GB RAM, 40GB, $3.99/mo)"
60+
value = "cx22"
61+
}
62+
option {
63+
name = "CPX11 (2 vCPU, 2GB RAM, 40GB, $4.49/mo)"
64+
value = "cpx11"
65+
}
66+
option {
67+
name = "CX32 (4 vCPU, 8GB RAM, 80GB, $6.99/mo)"
68+
value = "cx32"
69+
}
70+
option {
71+
name = "CPX21 (3 vCPU, 4GB RAM, 80GB, $7.99/mo)"
72+
value = "cpx21"
73+
}
74+
option {
75+
name = "CPX31 (4 vCPU, 8GB RAM, 160GB, $14.99/mo)"
76+
value = "cpx31"
77+
}
78+
option {
79+
name = "CX42 (8 vCPU, 16GB RAM, 160GB, $17.99/mo)"
80+
value = "cx42"
81+
}
82+
option {
83+
name = "CPX41 (8 vCPU, 16GB RAM, 240GB, $27.49/mo)"
84+
value = "cpx41"
85+
}
86+
option {
87+
name = "CX52 (16 vCPU, 32GB RAM, 320GB, $35.49/mo)"
88+
value = "cx52"
89+
}
90+
option {
91+
name = "CPX51 (16 vCPU, 32GB RAM, 360GB, $60.49/mo)"
92+
value = "cpx51"
93+
}
94+
}
95+
96+
resource "hcloud_server" "dev" {
97+
name = "dev"
98+
image = "ubuntu-24.04"
99+
server_type = data.coder_parameter.hcloud_server_type.value
100+
location = data.coder_parameter.hcloud_location.value
101+
public_net {
102+
ipv4_enabled = true
103+
ipv6_enabled = true
104+
}
105+
user_data = templatefile("cloud-config.yaml.tftpl", {
106+
username = lower(data.coder_workspace_owner.me.name)
107+
home_volume_label = hcloud_volume.home_volume.name
108+
init_script = base64encode(coder_agent.main.init_script)
109+
coder_agent_token = coder_agent.main.token
110+
})
111+
}
112+
113+
resource "hcloud_volume" "home_volume" {
114+
name = "coder-${data.coder_workspace.me.id}-home"
115+
size = data.coder_parameter.home_volume_size.value
116+
location = data.coder_parameter.hcloud_location.value
117+
format = "ext4"
118+
delete_protection = true
119+
}
120+
121+
resource "hcloud_volume_attachment" "home_volume_attachment" {
122+
volume_id = hcloud_volume.home_volume.id
123+
server_id = hcloud_server.dev.id
124+
}
125+
126+
locals {
127+
username = data.coder_workspace_owner.me.name
128+
}
129+
130+
data "coder_provisioner" "me" {
131+
}
132+
133+
provider "coder" {
134+
}
135+
136+
data "coder_workspace" "me" {
137+
}
138+
139+
data "coder_workspace_owner" "me" {
140+
}
141+
142+
data "coder_parameter" "home_volume_size" {
143+
name = "home_volume_size"
144+
display_name = "Home volume size"
145+
description = "How large would you like your home volume to be (in GB)?"
146+
type = "number"
147+
default = "20"
148+
mutable = false
149+
validation {
150+
min = 1
151+
max = 100 # Adjust the max size as needed
152+
}
153+
}
154+
155+
resource "coder_agent" "main" {
156+
os = "linux"
157+
arch = "amd64"
158+
159+
metadata {
160+
key = "cpu"
161+
display_name = "CPU Usage"
162+
interval = 5
163+
timeout = 5
164+
script = "coder stat cpu"
165+
}
166+
metadata {
167+
key = "memory"
168+
display_name = "Memory Usage"
169+
interval = 5
170+
timeout = 5
171+
script = "coder stat mem"
172+
}
173+
metadata {
174+
key = "home"
175+
display_name = "Home Usage"
176+
interval = 600 # every 10 minutes
177+
timeout = 30 # df can take a while on large filesystems
178+
script = "coder stat disk --path /home/${lower(data.coder_workspace_owner.me.name)}"
179+
}
180+
}
181+
182+
module "code-server" {
183+
count = data.coder_workspace.me.start_count
184+
source = "registry.coder.com/coder/code-server/coder"
185+
186+
# 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.
187+
version = "~> 1.0"
188+
189+
agent_id = coder_agent.main.id
190+
order = 1
191+
}

0 commit comments

Comments
 (0)