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