coder-template/hetzner-cloud/main.tf
Peter Kurfer 94741b563d
All checks were successful
continuous-integration/drone/push Build is passing
feat: install Terraform
2023-06-15 18:35:29 +02:00

344 lines
7.1 KiB
HCL

terraform {
required_providers {
coder = {
source = "coder/coder"
version = "~> 0.7.0"
}
hcloud = {
source = "hetznercloud/hcloud"
version = "1.40.0"
}
}
}
provider "hcloud" {
token = var.hcloud_token
}
provider "coder" {
feature_use_managed_variables = "true"
}
variable "hcloud_token" {
description = <<EOF
Coder requires a Hetzner Cloud token to provision workspaces.
EOF
sensitive = true
validation {
condition = length(var.hcloud_token) == 64
error_message = "Please provide a valid Hetzner Cloud API token."
}
}
variable "use_subdomain" {
description = "If apps are published under a subdomain"
default = "true"
validation {
condition = contains(["true", "false"], var.use_subdomain)
error_message = "Your answer can only be yes or no!"
}
}
variable "private_network_id" {
description = "ID of private network the server will be joined to"
default = ""
}
data "coder_parameter" "instance_location" {
name = "instance_location"
display_name = "Instance location"
default = "fsn1"
mutable = false
option {
name = "Nuernberg"
value = "nbg1"
}
option {
name = "Falkenstein"
value = "fsn1"
}
option {
name = "Helsinki"
value = "hel1"
}
}
data "coder_parameter" "instance_type" {
name = "instance_type"
display_name = "Instance type"
default = "cpx11"
type = "string"
mutable = true
option {
name = "cx11"
value = "cx11"
}
option {
name = "cpx11"
value = "cpx11"
}
option {
name = "cx21"
value = "cx21"
}
option {
name = "cpx21"
value = "cpx21"
}
option {
name = "cx31"
value = "cx31"
}
option {
name = "cpx31"
value = "cpx31"
}
option {
name = "cx41"
value = "cx41"
}
option {
name = "cpx41"
value = "cpx41"
}
option {
name = "cx51"
value = "cx51"
}
option {
name = "cpx51"
value = "cpx51"
}
}
data "coder_parameter" "instance_os" {
name = "instance_os"
display_name = "Instance OS"
description = "Which operating system should your workspace use?"
default = "fedora-38"
type = "string"
mutable = false
option {
name = "Fedora37"
value = "fedora-37"
}
option {
name = "Fedora38"
value = "fedora-38"
}
}
data "coder_parameter" "volume_size" {
name = "volume_size"
display_name = "Volume Size"
description = "How much storage space do you need in GB (can't be less then 10)?"
default = 10
type = "number"
validation {
min = 10
max = 100
monotonic = "increasing"
}
}
data "coder_parameter" "code_server" {
name = "install_code_server"
description = "Should Code Server be installed?"
default = "true"
type = "string"
mutable = true
option {
name = "Install"
value = "true"
}
option {
name = "Don't install"
value = "false"
}
}
data "coder_parameter" "install_go" {
name = "install_go"
description = "Should Go SDK be installed?"
default = "true"
type = "string"
mutable = true
option {
name = "Install"
value = "true"
}
option {
name = "Don't install"
value = "false"
}
}
data "coder_parameter" "install_dotnet" {
name = "install_dotnet"
description = "Should .NET SDK be installed?"
default = "true"
type = "string"
mutable = true
option {
name = "Install"
value = "true"
}
option {
name = "Don't install"
value = "false"
}
}
data "coder_parameter" "install_podman" {
name = "install_podman"
description = "Should Podman be installed?"
default = "true"
type = "string"
mutable = true
option {
name = "Install"
value = "true"
}
option {
name = "Don't install"
value = "false"
}
}
data "coder_parameter" "install_terraform" {
name = "install_terraform"
description = "Should Terraform be installed?"
default = "true"
type = "string"
mutable = true
option {
name = "Install"
value = "true"
}
option {
name = "Don't install"
value = "false"
}
}
data "coder_workspace" "me" {
}
resource "coder_agent" "dev" {
arch = "amd64"
os = "linux"
}
resource "coder_app" "code-server" {
display_name = "code-server"
count = data.coder_parameter.code_server.value ? 1 : 0
agent_id = coder_agent.dev.id
slug = "code-server"
icon = "/icon/code.svg"
url = "http://localhost:8080"
subdomain = var.use_subdomain
}
# Generate a dummy ssh key that is not accessible so Hetzner cloud does not spam the admin with emails.
resource "tls_private_key" "rsa_4096" {
algorithm = "RSA"
rsa_bits = 4096
}
resource "hcloud_ssh_key" "root" {
name = "coder-${data.coder_workspace.me.owner}-${data.coder_workspace.me.name}"
public_key = tls_private_key.rsa_4096.public_key_openssh
}
resource "hcloud_server" "root" {
count = data.coder_workspace.me.start_count
name = "coder-${data.coder_workspace.me.owner}-${data.coder_workspace.me.name}"
server_type = data.coder_parameter.instance_type.value
location = data.coder_parameter.instance_location.value
image = data.coder_parameter.instance_os.value
ssh_keys = [hcloud_ssh_key.root.id]
user_data = templatefile("cloud-config.yaml.tftpl", {
username = data.coder_workspace.me.owner
volume_path = "/dev/disk/by-id/scsi-0HC_Volume_${hcloud_volume.root.id}"
init_script = base64encode(coder_agent.dev.init_script)
coder_agent_token = coder_agent.dev.token
code_server_setup = data.coder_parameter.code_server.value
install_go_setup = data.coder_parameter.install_go.value
install_dotnet_setup = data.coder_parameter.install_dotnet.value
install_podman_setup = data.coder_parameter.install_podman.value
install_terraform_setup = data.coder_parameter.install_terraform.value
})
dynamic "network" {
for_each = var.private_network_id == "" ? [] : [""]
content {
network_id = var.private_network_id
}
}
public_net {
ipv4_enabled = true
ipv6_enabled = true
}
}
resource "hcloud_volume" "root" {
name = "coder-${data.coder_workspace.me.id}-home"
size = data.coder_parameter.volume_size.value
format = "ext4"
location = data.coder_parameter.instance_location.value
lifecycle {
ignore_changes = all
}
}
resource "hcloud_volume_attachment" "root" {
count = data.coder_workspace.me.start_count
volume_id = hcloud_volume.root.id
server_id = hcloud_server.root[count.index].id
automount = false
}
resource "hcloud_firewall" "root" {
name = "coder-${data.coder_workspace.me.owner_id}-${data.coder_workspace.me.id}-root"
rule {
direction = "in"
protocol = "icmp"
source_ips = [
"0.0.0.0/0",
"::/0"
]
}
}
resource "hcloud_firewall_attachment" "root_fw_attach" {
count = data.coder_workspace.me.start_count
firewall_id = hcloud_firewall.root.id
server_ids = [hcloud_server.root[count.index].id]
}