feat(tf): hetzner_vm module (server + firewall + ssh key + cloud-init)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
29921428c4
commit
bbc287900a
3 changed files with 95 additions and 0 deletions
51
terraform/modules/hetzner_vm/main.tf
Normal file
51
terraform/modules/hetzner_vm/main.tf
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
# cloud-init: create the unprivileged `ansible` user with ubongo's key + sudo.
|
||||||
|
# (Mirrors the proxmox_vm module's user_account; Hetzner has no structured field.)
|
||||||
|
locals {
|
||||||
|
user_data = <<-EOT
|
||||||
|
#cloud-config
|
||||||
|
users:
|
||||||
|
- name: ansible
|
||||||
|
groups: [sudo]
|
||||||
|
sudo: "ALL=(ALL) NOPASSWD:ALL"
|
||||||
|
shell: /bin/bash
|
||||||
|
ssh_authorized_keys:
|
||||||
|
- ${var.ansible_ssh_pubkey}
|
||||||
|
package_update: true
|
||||||
|
packages:
|
||||||
|
- python3
|
||||||
|
EOT
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "hcloud_ssh_key" "ansible" {
|
||||||
|
name = "${var.name}-ansible"
|
||||||
|
public_key = var.ansible_ssh_pubkey
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "hcloud_firewall" "this" {
|
||||||
|
name = "${var.name}-fw"
|
||||||
|
|
||||||
|
# SSH from the control node only. NetBird ports (UDP 3478, TCP 80/443) are added
|
||||||
|
# in M4 when the coordinator deploys (ADR-020); host nftables stays catalog-driven.
|
||||||
|
rule {
|
||||||
|
direction = "in"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "22"
|
||||||
|
source_ips = var.ssh_admin_cidrs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "hcloud_server" "this" {
|
||||||
|
name = var.name
|
||||||
|
server_type = var.server_type
|
||||||
|
location = var.location
|
||||||
|
image = var.image
|
||||||
|
ssh_keys = [hcloud_ssh_key.ansible.id]
|
||||||
|
user_data = local.user_data
|
||||||
|
firewall_ids = [hcloud_firewall.this.id]
|
||||||
|
labels = var.labels
|
||||||
|
|
||||||
|
public_net {
|
||||||
|
ipv4_enabled = true
|
||||||
|
ipv6_enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
9
terraform/modules/hetzner_vm/outputs.tf
Normal file
9
terraform/modules/hetzner_vm/outputs.tf
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
output "ipv4_address" {
|
||||||
|
description = "Server public IPv4"
|
||||||
|
value = hcloud_server.this.ipv4_address
|
||||||
|
}
|
||||||
|
|
||||||
|
output "name" {
|
||||||
|
description = "Server name"
|
||||||
|
value = hcloud_server.this.name
|
||||||
|
}
|
||||||
35
terraform/modules/hetzner_vm/variables.tf
Normal file
35
terraform/modules/hetzner_vm/variables.tf
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
variable "name" {
|
||||||
|
description = "Server name (and hostname)"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "server_type" {
|
||||||
|
description = "Hetzner server type, e.g. cax11 (ARM)"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "location" {
|
||||||
|
description = "Hetzner location, e.g. hel1"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "image" {
|
||||||
|
description = "OS image slug, e.g. debian-13"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ansible_ssh_pubkey" {
|
||||||
|
description = "Public SSH key provisioned for the ansible user via cloud-init"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ssh_admin_cidrs" {
|
||||||
|
description = "Source CIDRs allowed to reach SSH (e.g. ubongo's address/32)"
|
||||||
|
type = list(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "labels" {
|
||||||
|
description = "Hetzner resource labels (metadata only)"
|
||||||
|
type = map(string)
|
||||||
|
default = {}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue