The Hetzner Cloud Firewall SSH rule is now conditional on a non-empty ssh_admin_cidrs (default []); askari sets it empty so the WAN :22 rule is removed on the next apply. SSH is reached over wt0; break-glass is the Hetzner console. Apply is the live cutover (Task 5). Mesh-hardening 1/3. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
79 lines
2.1 KiB
HCL
79 lines
2.1 KiB
HCL
# 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 {
|
|
# Indentation matches the closing EOT (2 spaces) so `<<-` strips to column 0 —
|
|
# cloud-config requires `#cloud-config` as the first line with no leading space.
|
|
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 — and only when admin CIDRs are set. An empty
|
|
# ssh_admin_cidrs removes the WAN :22 rule entirely (mesh-only SSH; reach the host over
|
|
# wt0, break-glass = Hetzner console). Mesh-hardening 1/3.
|
|
dynamic "rule" {
|
|
for_each = length(var.ssh_admin_cidrs) > 0 ? [1] : []
|
|
content {
|
|
direction = "in"
|
|
protocol = "tcp"
|
|
port = "22"
|
|
source_ips = var.ssh_admin_cidrs
|
|
}
|
|
}
|
|
|
|
# Public web (Caddy 80/443) + NetBird STUN/TURN (3478/udp) — only when public_web
|
|
# (ADR-024, M4). Host nftables stays catalog-driven (ADR-020).
|
|
dynamic "rule" {
|
|
for_each = var.public_web ? ["80", "443"] : []
|
|
content {
|
|
direction = "in"
|
|
protocol = "tcp"
|
|
port = rule.value
|
|
source_ips = ["0.0.0.0/0", "::/0"]
|
|
}
|
|
}
|
|
|
|
dynamic "rule" {
|
|
for_each = var.public_web ? ["3478"] : []
|
|
content {
|
|
direction = "in"
|
|
protocol = "udp"
|
|
port = rule.value
|
|
source_ips = ["0.0.0.0/0", "::/0"]
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|