Skip to content

Terraform Providers

Provider configuration for Kavi infrastructure - Complete guide to Hetzner Cloud, Cloudflare, and Docker providers (planned implementation).


Planned Architecture

This documentation describes the planned Terraform provider configuration. Terraform is not yet implemented.


Table of Contents


Overview

What Are Providers

Providers are Terraform plugins that interact with cloud platforms, SaaS services, and APIs.

For Kavi infrastructure: | Provider | Purpose | Resources Managed | |----------|---------|-------------------| | hcloud | Hetzner Cloud | VPS servers, SSH keys, networks, firewalls | | cloudflare | Cloudflare DNS | DNS records, zones | | docker | Docker Engine | Networks (infrastructure layer) |

Provider Declaration

providers.tf:

# Hetzner Cloud
provider "hcloud" {
  token = var.hcloud_token
}

# Cloudflare
provider "cloudflare" {
  api_token = var.cloudflare_api_token
}

# Docker
provider "docker" {
  host = "unix:///var/run/docker.sock"
}


Hetzner Cloud Provider

Configuration

Full configuration:

provider "hcloud" {
  token = var.hcloud_token  # From Infisical
}

Token from Infisical:

# Stored in Infisical
infisical secrets set HCLOUD_TOKEN="<token>" --env=dev --projectId=personal-vault

# Injected via environment variable
export TF_VAR_hcloud_token="$HCLOUD_TOKEN"

Available Resources

Servers:

resource "hcloud_server" "hetzner_vps" {
  name        = "hetzner-vps"
  server_type = "cpx42"
  image       = "ubuntu-24.04"
  location    = "fsn1"
  ssh_keys    = [hcloud_ssh_key.macbook.id]
}

SSH Keys:

resource "hcloud_ssh_key" "macbook" {
  name       = "macbook"
  public_key = file("/root/.ssh/id_ed25519_macbook.pub")
}

Networks:

resource "hcloud_network" "internal" {
  name     = "internal-network"
  ip_range = "10.0.0.0/16"
}

Firewalls:

resource "hcloud_firewall" "web" {
  name = "web-firewall"

  rule {
    direction = "in"
    protocol  = "tcp"
    port      = "443"
    source_ips = ["0.0.0.0/0"]
  }
}

Documentation

Provider docs: https://registry.terraform.io/providers/hetznercloud/hcloud/latest/docs


Cloudflare Provider

Configuration

Full configuration:

provider "cloudflare" {
  api_token = var.cloudflare_api_token  # From Infisical
}

Generate API Token: 1. Go to https://dash.cloudflare.com/profile/api-tokens 2. Click "Create Token" 3. Use template: "Edit zone DNS" 4. Zone Resources: Include → Specific zone → kua.cl 5. Copy token 6. Store in Infisical:

infisical secrets set CLOUDFLARE_API_TOKEN="<token>" --env=dev --projectId=personal-vault

Available Resources

DNS A Records:

resource "cloudflare_record" "root" {
  zone_id = var.cloudflare_zone_id
  name    = "@"
  value   = hcloud_server.hetzner_vps.ipv4_address
  type    = "A"
  proxied = false
  ttl     = 3600
}

DNS CNAME Records:

resource "cloudflare_record" "secrets" {
  zone_id = var.cloudflare_zone_id
  name    = "secrets"
  value   = "kua.cl"
  type    = "CNAME"
  proxied = false
  ttl     = 3600
}

Zone ID

Find zone ID:

# In Cloudflare dashboard
# Domain → Overview → Zone ID (right sidebar)

# Store as variable
variable "cloudflare_zone_id" {
  description = "Cloudflare zone ID for kua.cl"
  type        = string
  default     = "abc123def456"  # Replace with actual zone ID
}

Documentation

Provider docs: https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs


Docker Provider

Configuration

Full configuration:

provider "docker" {
  host = "unix:///var/run/docker.sock"
}

Note: Docker socket must be mounted into dev() container:

docker run -v /var/run/docker.sock:/var/run/docker.sock ...

Available Resources

Networks:

resource "docker_network" "traefik_public" {
  name = "traefik-public"
}

resource "docker_network" "infisical_internal" {
  name = "infisical-internal"
  internal = true  # No external access
}

Use case: Infrastructure-layer networks that services connect to

NOT managed by Terraform: - Application containers (use docker-compose) - Container configuration - Volumes

Documentation

Provider docs: https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs


Provider Versions

Version Constraints

terraform.tf:

terraform {
  required_version = ">= 1.6.0"

  required_providers {
    hcloud = {
      source  = "hetznercloud/hcloud"
      version = "~> 1.45.0"  # >= 1.45.0, < 1.46.0
    }
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = "~> 4.20.0"  # >= 4.20.0, < 4.21.0
    }
    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 3.0.0"   # >= 3.0.0, < 3.1.0
    }
  }
}

Why Pin Versions

Without version constraints:

required_providers {
  hcloud = {
    source = "hetznercloud/hcloud"
    # No version = latest
  }
}

Problems: - Breaking changes in new versions - Inconsistent behavior across machines - Unexpected errors

With version constraints:

version = "~> 1.45.0"

Benefits: - ✅ Predictable behavior - ✅ Prevent breaking changes - ✅ Controlled upgrades


Authentication

Best Practices

✅ DO:

# Use variables
provider "hcloud" {
  token = var.hcloud_token
}

# Inject via environment
export TF_VAR_hcloud_token="$HCLOUD_TOKEN"

❌ DON'T:

# Hardcode tokens
provider "hcloud" {
  token = "sk-abc123..."  # NEVER DO THIS
}

Token Storage

All tokens in Infisical:

# Hetzner
infisical secrets set HCLOUD_TOKEN="..." --env=dev --projectId=personal-vault

# Cloudflare
infisical secrets set CLOUDFLARE_API_TOKEN="..." --env=dev --projectId=personal-vault
infisical secrets set CLOUDFLARE_ZONE_ID="..." --env=dev --projectId=personal-vault

Load in dev() container:

# dev() already loads secrets from Infisical
# Just export for Terraform
export TF_VAR_hcloud_token="$HCLOUD_TOKEN"
export TF_VAR_cloudflare_api_token="$CLOUDFLARE_API_TOKEN"
export TF_VAR_cloudflare_zone_id="$CLOUDFLARE_ZONE_ID"


Configuration Examples

Complete providers.tf

# Hetzner Cloud Provider
provider "hcloud" {
  token = var.hcloud_token
}

# Cloudflare Provider
provider "cloudflare" {
  api_token = var.cloudflare_api_token
}

# Docker Provider
provider "docker" {
  host = "unix:///var/run/docker.sock"
}

Complete variables.tf

# Hetzner Cloud
variable "hcloud_token" {
  description = "Hetzner Cloud API token"
  type        = string
  sensitive   = true
}

# Cloudflare
variable "cloudflare_api_token" {
  description = "Cloudflare API token"
  type        = string
  sensitive   = true
}

variable "cloudflare_zone_id" {
  description = "Cloudflare zone ID for kua.cl"
  type        = string
}

Complete terraform.tf

terraform {
  # Terraform version
  required_version = ">= 1.6.0"

  # Remote state backend
  backend "s3" {
    bucket   = "terraform-state"
    key      = "infrastructure/terraform.tfstate"
    region   = "us-east-1"
    endpoint = "https://u522581.your-storagebox.de"

    skip_credentials_validation = true
    skip_region_validation      = true
    skip_metadata_api_check     = true
    force_path_style            = true
  }

  # Required providers
  required_providers {
    hcloud = {
      source  = "hetznercloud/hcloud"
      version = "~> 1.45.0"
    }
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = "~> 4.20.0"
    }
    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 3.0.0"
    }
  }
}

Summary

Terraform Providers for Kavi Infrastructure: - ✅ Hetzner Cloud: VPS, SSH keys, networks, firewalls - ✅ Cloudflare: DNS records - ✅ Docker: Infrastructure networks - ✅ Authentication: Tokens from Infisical, injected via TF_VAR_ - ✅ Versions*: Pinned with ~> constraints

What's Next: - Learn VPS Management - provision Hetzner VPS - Learn DNS Management - manage Cloudflare DNS - Learn Workflow - daily operations