feat: terraform + ansible config to provision a host on hetzner & set cloudflare DNS

This commit is contained in:
2026-08-18 13:01:36 +02:00
commit fecf871eb1
9 changed files with 181 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
# SSH key shared with the VPS
resource "hcloud_ssh_key" "ansible" {
name = var.project_name
public_key = var.ssh_public_key
}
# Provision a small Hetzner Cloud VPS
resource "hcloud_server" "dokploy" {
name = var.project_name
image = var.hcloud_image
server_type = var.hcloud_server_type
location = var.hcloud_location
ssh_keys = [hcloud_ssh_key.ansible.id]
public_net {
ipv4_enabled = true
}
}
# Resolve the Cloudflare zone from its apex domain name
data "cloudflare_zone" "zone" {
filter = {
name = var.domain_name
}
}
locals {
public_ip = hcloud_server.dokploy.ipv4_address
}
# Automatically publish the VPS IP as a Cloudflare A record
resource "cloudflare_dns_record" "a" {
zone_id = data.cloudflare_zone.zone.id
name = var.record_name
type = "A"
content = local.public_ip
proxied = var.cloudflare_proxied
ttl = var.cloudflare_proxied ? 1 : 3600
}
# Write IP to Ansible inventory
resource "local_file" "ansible_inventory" {
content = templatefile("${path.module}/../ansible/inventory.tpl", {
public_ip = local.public_ip
})
filename = "${path.module}/../ansible/inventory.ini"
}
output "public_ip" {
description = "The public IPv4 address of the provisioned Hetzner Cloud VPS"
value = local.public_ip
}
+25
View File
@@ -0,0 +1,25 @@
terraform {
required_version = ">= 1.0.0"
required_providers {
hcloud = {
source = "hetznercloud/hcloud"
version = "~> 1.68.0"
}
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 5.23.0"
}
local = {
source = "hashicorp/local"
version = "~> 2.9.0"
}
}
}
provider "hcloud" {
token = var.hcloud_token
}
provider "cloudflare" {
api_token = var.cloudflare_api_token
}
+58
View File
@@ -0,0 +1,58 @@
variable "project_name" {
type = string
description = "VM name"
}
variable "ssh_public_key" {
type = string
description = "Public SSH key to install on the VM"
}
## HETZNER
variable "hcloud_token" {
type = string
description = "Hetzner Cloud API token"
sensitive = true
}
variable "hcloud_server_type" {
type = string
description = "Hetzner Cloud server type"
default = "cx22" # 2 vCPU / 4 GB RAM / 40 GB NVMe
}
variable "hcloud_image" {
type = string
description = "OS image name to boot the VPS from"
default = "debian-13"
}
variable "hcloud_location" {
type = string
description = "Hetzner Cloud location"
default = "nbg1" # Nuremberg, Germany
}
## CLOUDFLARE
variable "cloudflare_api_token" {
type = string
description = "Cloudflare API token with Zone.DNS edit permission"
sensitive = true
}
variable "domain_name" {
type = string
description = "Cloudflare zone (apex domain) in which to create the A record"
}
variable "record_name" {
type = string
description = "DNS record name relative to the zone; use \"@\" for the apex"
default = "dokploy"
}
variable "cloudflare_proxied" {
type = bool
description = "Whether Cloudflare should proxy (orange-cloud) the A record"
default = true
}