feat: terraform + ansible config to provision a host on hetzner & set cloudflare DNS
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
|||||||
|
# Terraform
|
||||||
|
.terraform/
|
||||||
|
*.tfstate
|
||||||
|
*.tfstate.backup
|
||||||
|
*.tfvars
|
||||||
|
*.tfvars.json
|
||||||
|
.terraform.lock.hcl
|
||||||
|
|
||||||
|
# Ansible
|
||||||
|
ansible/inventory.ini
|
||||||
|
|
||||||
|
# Private Keys & Secrets
|
||||||
|
*.pem
|
||||||
|
*.key
|
||||||
|
*.pub
|
||||||
|
id_rsa
|
||||||
|
id_rsa.pub
|
||||||
|
|
||||||
|
# OS files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[defaults]
|
||||||
|
inventory = inventory.ini
|
||||||
|
host_key_checking = False
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
ansible_user: "ansible"
|
||||||
|
|
||||||
|
sysadmin_user: "alessandrovitali"
|
||||||
|
sysadmin_public_ssh_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAm/J+9YG+odym9In9C4iLcrfXlrlPK2TygtI7lBNNpl"
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
[dokploy]
|
||||||
|
dokploy ansible_host=${public_ip} ansible_user=debian
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
## ansible/setup.yml
|
||||||
|
|
||||||
|
- name: Setup dokploy machine
|
||||||
|
hosts: all
|
||||||
|
roles:
|
||||||
|
- role: studio.ansible.base
|
||||||
|
- role: studio.ansible.users
|
||||||
|
- role: studio.ansible.security
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
## ansible/requirements.yml
|
||||||
|
|
||||||
|
collections:
|
||||||
|
- name: studio.ansible
|
||||||
|
source: https://git.studiovita.li/studio/ansible.git ## HTTPS
|
||||||
|
type: git
|
||||||
|
version: dokploy
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user