3.2 KiB
🚀 Provisioning Servers with RailianceHosts
This guide explains where you declare servers, how Terraform uses that declaration, and how to provision (and later destroy) machines on Hetzner.
1) Where you define servers
All desired hosts live in inventory/servers.yaml. Each entry is a simple YAML object with the required attributes:
servers:
- name: core-01
labels: [core, wireguard, git]
role: "core"
region: "nbg1" # Hetzner location (e.g., nbg1, fsn1, hel1)
type: "cpx21" # Hetzner server type/flavor
image: "ubuntu-24.04" # OS image slug
ssh_user: "admin" # bootstrap user (cloud-init creates this)
Tip: Keep names stable. Renaming a server in this file makes Terraform think the old one was destroyed and a new one should be created.
2) Two ways to add a server
A) Edit YAML by hand (simple)
Open inventory/servers.yaml, add a new entry, save, commit.
B) Use the helper script (safe & quick)
# requires scripts/new_host.py
make new-host NAME=web-01 TYPE=cpx21 REGION=nbg1 ROLE=web
# or directly:
python3 scripts/new_host.py --name web-01 --type cpx21 --region nbg1 --role web
You can also do add + provision in one step:
scripts/hcloud_new_server.sh web-01 --type cpx21 --region nbg1 --role web
3) How Terraform uses your declaration
The module at terraform/hetzner/:
- Reads
inventory/servers.yaml(for_eachoverservers) - Registers your SSH key from
keys/admin_ssh.pub - Injects cloud-init that sets up the
adminuser and basic hardening - Creates/updates/destroys servers to match the YAML
Outputs include a map of server names → IPv4 addresses.
4) Provision (create/update)
Make sure your Hetzner API token is present and SOPS-decryptable in inventory/group_vars/secrets.sops.yaml under ops.hcloud_token.
Then run either:
# plan and apply in separate steps
make tf-plan
make tf-apply
or the end-to-end convenience:
make apply # terraform apply + ansible bootstrap
If you used the one-shot script:
scripts/hcloud_new_server.sh web-01 --type cpx21 --region nbg1 --role web
Terraform will print the new servers’ IPv4 addresses at the end.
5) Connect & converge
Connect via SSH:
ssh admin@<server-ip>
Run Ansible base bootstrap (if not using make apply):
make ansible-bootstrap
6) Destroy (tear down)
To remove all servers managed by this repo:
make tf-destroy
To remove just one server, delete its entry from inventory/servers.yaml, commit, then:
make tf-apply
Terraform will destroy the missing server and leave others intact.
7) Notes & conventions
- Idempotent: You can run
make applyrepeatedly; Terraform converges infra, Ansible converges config. - SSH keys: Ensure
keys/admin_ssh.pubexists before provisioning. - Secret token: The Hetzner API token must be in
inventory/group_vars/secrets.sops.yaml(encrypted with SOPS). - Cloud-init delay: Allow ~30–60s after creation for first-boot tasks before first SSH.
- Labels & role:
labelsare freeform tags;rolecan drive Ansible plays as you grow.