feat: Swapped tofu init scripting for ansible scripting
This commit is contained in:
@@ -9,12 +9,6 @@ locals {
|
||||
# var.allowed_ssh_source_ips for direct SSH access.
|
||||
vpn_ssh_source_ips = ["${module.vpn.ipv4}/32"]
|
||||
|
||||
# Rendered once and uploaded+run by every host module immediately after its
|
||||
# server is created - see scripts/bootstrap.sh.tftpl.
|
||||
bootstrap_script = templatefile("${path.module}/scripts/bootstrap.sh.tftpl", {
|
||||
deploy_user = var.deploy_user
|
||||
})
|
||||
|
||||
# IDs for every named key in var.ssh_key_names - installed on every server.
|
||||
ssh_key_ids = [for k in data.hcloud_ssh_key.main : k.id]
|
||||
|
||||
@@ -59,10 +53,6 @@ module "dev" {
|
||||
volume_size = var.dev_volume_size
|
||||
allowed_ssh_source_ips = local.vpn_ssh_source_ips
|
||||
network_ip_range = var.network_ip_range
|
||||
bootstrap_script = local.bootstrap_script
|
||||
ssh_private_key_path = var.ssh_private_key_path
|
||||
deploy_user = var.deploy_user
|
||||
runner_count = var.dev_runner_count
|
||||
|
||||
# module.network.id alone doesn't guarantee the subnet exists yet, and a server
|
||||
# can't join a network before it has a subnet.
|
||||
@@ -81,9 +71,6 @@ module "prod" {
|
||||
volume_size = var.prod_volume_size
|
||||
allowed_ssh_source_ips = local.vpn_ssh_source_ips
|
||||
network_ip_range = var.network_ip_range
|
||||
bootstrap_script = local.bootstrap_script
|
||||
ssh_private_key_path = var.ssh_private_key_path
|
||||
deploy_user = var.deploy_user
|
||||
|
||||
depends_on = [module.network]
|
||||
}
|
||||
@@ -96,9 +83,6 @@ module "vpn" {
|
||||
location = var.location
|
||||
ssh_key_ids = local.ssh_key_ids
|
||||
allowed_ssh_source_ips = var.allowed_ssh_source_ips
|
||||
bootstrap_script = local.bootstrap_script
|
||||
ssh_private_key_path = var.ssh_private_key_path
|
||||
deploy_user = var.deploy_user
|
||||
}
|
||||
|
||||
module "dns" {
|
||||
|
||||
@@ -56,30 +56,12 @@ resource "hcloud_server" "this" {
|
||||
location = var.location
|
||||
ssh_keys = var.ssh_key_ids
|
||||
firewall_ids = [hcloud_firewall.this.id]
|
||||
labels = { role = "dev" } # picked up by ansible/inventory/hcloud.yml
|
||||
|
||||
network {
|
||||
network_id = var.network_id
|
||||
ip = var.private_ip
|
||||
}
|
||||
|
||||
connection {
|
||||
type = "ssh"
|
||||
host = self.ipv4_address
|
||||
user = "root"
|
||||
private_key = file(var.ssh_private_key_path)
|
||||
}
|
||||
|
||||
provisioner "file" {
|
||||
content = var.bootstrap_script
|
||||
destination = "/root/bootstrap.sh"
|
||||
}
|
||||
|
||||
provisioner "remote-exec" {
|
||||
inline = [
|
||||
"chmod +x /root/bootstrap.sh",
|
||||
"/root/bootstrap.sh",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
resource "hcloud_volume" "storage" {
|
||||
@@ -98,85 +80,8 @@ locals {
|
||||
# Hetzner's automount convention (hc-utils' 99-hc-volume-automount.rules) is
|
||||
# always /mnt/HC_Volume_<id> - deterministic once the volume exists, since the
|
||||
# id is stable for the volume's lifetime regardless of which server it's
|
||||
# attached to.
|
||||
# attached to. Kept here only as a human-readable output (see outputs.tf) -
|
||||
# ansible/roles/deploy looks this up itself from the Hetzner API, it doesn't
|
||||
# read this value.
|
||||
data_dir = "/mnt/HC_Volume_${hcloud_volume.storage.id}"
|
||||
}
|
||||
|
||||
# Renders services/dev/Runners/docker-compose.yml directly into the repo, with
|
||||
# one runner service per var.runner_count. This only touches the local working
|
||||
# tree - deploying the change still goes through the normal scp + spinup.sh flow.
|
||||
resource "local_file" "runners_compose" {
|
||||
filename = "${path.root}/../services/dev/Runners/docker-compose.yml"
|
||||
content = templatefile("${path.module}/templates/runners-docker-compose.yml.tftpl", {
|
||||
runner_count = var.runner_count
|
||||
data_dir = local.data_dir
|
||||
})
|
||||
file_permission = "0644"
|
||||
}
|
||||
|
||||
# DATA_DIR is picked up automatically by `docker compose` (which auto-loads
|
||||
# .env from its working directory) for every dev/*-docker-compose.yml bind
|
||||
# mount - see services/dev/*.yml. Not committed (see .gitignore): it's tied to
|
||||
# the live volume's ID, so it's regenerated by tofu apply, not handed off via git.
|
||||
resource "local_file" "env" {
|
||||
filename = "${path.root}/../services/dev/.env"
|
||||
content = "DATA_DIR=${local.data_dir}\n"
|
||||
file_permission = "0644"
|
||||
}
|
||||
|
||||
locals {
|
||||
# Everything under services/dev except the two files above: those are
|
||||
# tracked via their own resource content (reading them back with fileset()/
|
||||
# filesha1() before they exist would fail during `tofu plan`).
|
||||
dev_static_files = sort([
|
||||
for f in fileset("${path.root}/../services/dev", "**") :
|
||||
f if f != ".env" && f != "Runners/docker-compose.yml"
|
||||
])
|
||||
|
||||
dev_static_files_hash = sha1(join("", [
|
||||
for f in local.dev_static_files : filesha1("${path.root}/../services/dev/${f}")
|
||||
]))
|
||||
}
|
||||
|
||||
# Copies services/dev to the server on every apply that changes it (a hand-edited
|
||||
# compose file, a new runner count, ...) or recreates the server - not just once
|
||||
# at first creation. Split from hcloud_server.this because it must run after the
|
||||
# generated files above, which in turn depend on the volume, which depends on
|
||||
# the server - so it can't be a provisioner on the server resource itself.
|
||||
resource "null_resource" "deploy_services" {
|
||||
triggers = {
|
||||
server_id = hcloud_server.this.id
|
||||
static_files = local.dev_static_files_hash
|
||||
env = local_file.env.content
|
||||
runners = local_file.runners_compose.content
|
||||
}
|
||||
|
||||
connection {
|
||||
type = "ssh"
|
||||
host = hcloud_server.this.ipv4_address
|
||||
user = "root"
|
||||
private_key = file(var.ssh_private_key_path)
|
||||
}
|
||||
|
||||
provisioner "remote-exec" {
|
||||
inline = ["mkdir -p /home/${var.deploy_user}/services"]
|
||||
}
|
||||
|
||||
provisioner "file" {
|
||||
source = "${path.root}/../services/dev"
|
||||
destination = "/home/${var.deploy_user}/services"
|
||||
}
|
||||
|
||||
provisioner "remote-exec" {
|
||||
inline = [
|
||||
"chown -R ${var.deploy_user}:${var.deploy_user} /home/${var.deploy_user}/services",
|
||||
"chmod +x /home/${var.deploy_user}/services/dev/*.sh",
|
||||
]
|
||||
}
|
||||
|
||||
depends_on = [
|
||||
hcloud_server.this,
|
||||
local_file.env,
|
||||
local_file.runners_compose,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
# Generated by OpenTofu from var.dev_runner_count - do not hand-edit.
|
||||
# To change the number of runners, edit dev_runner_count in terraform.tfvars and
|
||||
# run tofu apply. To change their shape, edit
|
||||
# infra/modules/dev/templates/runners-docker-compose.yml.tftpl instead.
|
||||
#
|
||||
# GITEA_RUNNER_REGISTRATION_TOKEN is intentionally left as a compose variable
|
||||
# (not baked in here) - services/dev/spinup.sh generates a fresh token and
|
||||
# writes it to Runners/.env immediately before starting these containers.
|
||||
#
|
||||
# /data lives on dev's volume (${data_dir}) so runner identity survives a
|
||||
# server rebuild - baked in directly rather than via .env, since Runners/.env
|
||||
# is already reserved for the registration token above and gets overwritten
|
||||
# on every deploy.
|
||||
services:
|
||||
%{ for i in range(runner_count) ~}
|
||||
runner-${i + 1}:
|
||||
image: gitea/act_runner:latest
|
||||
container_name: gitea_runner_${i + 1}
|
||||
volumes:
|
||||
- ./config.yaml:/config.yaml
|
||||
- ${data_dir}/gitea_runner_${i + 1}:/data
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
networks:
|
||||
- proxy
|
||||
environment:
|
||||
CONFIG_FILE: /config.yaml
|
||||
GITEA_INSTANCE_URL: "https://git.luke-else.co.uk"
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: "$${GITEA_RUNNER_REGISTRATION_TOKEN}"
|
||||
GITEA_RUNNER_NAME: "CICD#${i + 1}"
|
||||
restart: unless-stopped
|
||||
%{ endfor ~}
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
@@ -42,23 +42,3 @@ variable "network_ip_range" {
|
||||
description = "CIDR of the private network, allowed through the firewall for traffic from prod."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "bootstrap_script" {
|
||||
description = "Rendered post-install script, uploaded and executed on the server immediately after creation."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "ssh_private_key_path" {
|
||||
description = "Local path to the private key matching one of var.ssh_key_ids, used to run the bootstrap script over SSH."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "runner_count" {
|
||||
description = "Number of Gitea Actions runner containers to render into services/dev/Runners/docker-compose.yml."
|
||||
type = number
|
||||
}
|
||||
|
||||
variable "deploy_user" {
|
||||
description = "Non-root sudo user created by the bootstrap script - services/dev is copied into this user's home directory."
|
||||
type = string
|
||||
}
|
||||
|
||||
@@ -83,30 +83,12 @@ resource "hcloud_server" "this" {
|
||||
location = var.location
|
||||
ssh_keys = var.ssh_key_ids
|
||||
firewall_ids = [hcloud_firewall.this.id]
|
||||
labels = { role = "prod" } # picked up by ansible/inventory/hcloud.yml
|
||||
|
||||
network {
|
||||
network_id = var.network_id
|
||||
ip = var.private_ip
|
||||
}
|
||||
|
||||
connection {
|
||||
type = "ssh"
|
||||
host = self.ipv4_address
|
||||
user = "root"
|
||||
private_key = file(var.ssh_private_key_path)
|
||||
}
|
||||
|
||||
provisioner "file" {
|
||||
content = var.bootstrap_script
|
||||
destination = "/root/bootstrap.sh"
|
||||
}
|
||||
|
||||
provisioner "remote-exec" {
|
||||
inline = [
|
||||
"chmod +x /root/bootstrap.sh",
|
||||
"/root/bootstrap.sh",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
resource "hcloud_volume" "storage" {
|
||||
@@ -125,70 +107,8 @@ locals {
|
||||
# Hetzner's automount convention (hc-utils' 99-hc-volume-automount.rules) is
|
||||
# always /mnt/HC_Volume_<id> - deterministic once the volume exists, since the
|
||||
# id is stable for the volume's lifetime regardless of which server it's
|
||||
# attached to.
|
||||
# attached to. Kept here only as a human-readable output (see outputs.tf) -
|
||||
# ansible/roles/deploy looks this up itself from the Hetzner API, it doesn't
|
||||
# read this value.
|
||||
data_dir = "/mnt/HC_Volume_${hcloud_volume.storage.id}"
|
||||
}
|
||||
|
||||
# DATA_DIR is picked up automatically by `docker compose` (which auto-loads
|
||||
# .env from its working directory) for every prod/*-docker-compose.yml bind
|
||||
# mount - see services/prod/*.yml. Not committed (see .gitignore): it's tied to
|
||||
# the live volume's ID, so it's regenerated by tofu apply, not handed off via git.
|
||||
resource "local_file" "env" {
|
||||
filename = "${path.root}/../services/prod/.env"
|
||||
content = "DATA_DIR=${local.data_dir}\n"
|
||||
file_permission = "0644"
|
||||
}
|
||||
|
||||
locals {
|
||||
# Everything under services/prod except .env: that's tracked via its own
|
||||
# resource content (reading it back with fileset()/filesha1() before it
|
||||
# exists would fail during `tofu plan`).
|
||||
prod_static_files = sort([
|
||||
for f in fileset("${path.root}/../services/prod", "**") : f if f != ".env"
|
||||
])
|
||||
|
||||
prod_static_files_hash = sha1(join("", [
|
||||
for f in local.prod_static_files : filesha1("${path.root}/../services/prod/${f}")
|
||||
]))
|
||||
}
|
||||
|
||||
# Copies services/prod to the server on every apply that changes it (a
|
||||
# hand-edited compose file, ...) or recreates the server - not just once at
|
||||
# first creation. Split from hcloud_server.this because it must run after
|
||||
# local_file.env, which in turn depends on the volume, which depends on the
|
||||
# server - so it can't be a provisioner on the server resource itself.
|
||||
resource "null_resource" "deploy_services" {
|
||||
triggers = {
|
||||
server_id = hcloud_server.this.id
|
||||
static_files = local.prod_static_files_hash
|
||||
env = local_file.env.content
|
||||
}
|
||||
|
||||
connection {
|
||||
type = "ssh"
|
||||
host = hcloud_server.this.ipv4_address
|
||||
user = "root"
|
||||
private_key = file(var.ssh_private_key_path)
|
||||
}
|
||||
|
||||
provisioner "remote-exec" {
|
||||
inline = ["mkdir -p /home/${var.deploy_user}/services"]
|
||||
}
|
||||
|
||||
provisioner "file" {
|
||||
source = "${path.root}/../services/prod"
|
||||
destination = "/home/${var.deploy_user}/services"
|
||||
}
|
||||
|
||||
provisioner "remote-exec" {
|
||||
inline = [
|
||||
"chown -R ${var.deploy_user}:${var.deploy_user} /home/${var.deploy_user}/services",
|
||||
"chmod +x /home/${var.deploy_user}/services/prod/*.sh",
|
||||
]
|
||||
}
|
||||
|
||||
depends_on = [
|
||||
hcloud_server.this,
|
||||
local_file.env,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -42,18 +42,3 @@ variable "network_ip_range" {
|
||||
description = "CIDR of the private network, allowed through the firewall for traffic from dev."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "bootstrap_script" {
|
||||
description = "Rendered post-install script, uploaded and executed on the server immediately after creation."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "ssh_private_key_path" {
|
||||
description = "Local path to the private key matching one of var.ssh_key_ids, used to run the bootstrap script over SSH."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "deploy_user" {
|
||||
description = "Non-root sudo user created by the bootstrap script - services/prod is copied into this user's home directory."
|
||||
type = string
|
||||
}
|
||||
|
||||
@@ -38,67 +38,5 @@ resource "hcloud_server" "this" {
|
||||
location = var.location
|
||||
ssh_keys = var.ssh_key_ids
|
||||
firewall_ids = [hcloud_firewall.this.id]
|
||||
|
||||
connection {
|
||||
type = "ssh"
|
||||
host = self.ipv4_address
|
||||
user = "root"
|
||||
private_key = file(var.ssh_private_key_path)
|
||||
}
|
||||
|
||||
provisioner "file" {
|
||||
content = var.bootstrap_script
|
||||
destination = "/root/bootstrap.sh"
|
||||
}
|
||||
|
||||
provisioner "remote-exec" {
|
||||
inline = [
|
||||
"chmod +x /root/bootstrap.sh",
|
||||
"/root/bootstrap.sh",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
locals {
|
||||
vpn_static_files = sort(fileset("${path.root}/../services/vpn", "**"))
|
||||
|
||||
vpn_static_files_hash = sha1(join("", [
|
||||
for f in local.vpn_static_files : filesha1("${path.root}/../services/vpn/${f}")
|
||||
]))
|
||||
}
|
||||
|
||||
# Copies services/vpn to the server on every apply that changes it (a
|
||||
# hand-edited compose file, ...) or recreates the server - not just once at
|
||||
# first creation. Split from hcloud_server.this so it's triggered by content
|
||||
# changes independently of the bootstrap provisioners above.
|
||||
resource "null_resource" "deploy_services" {
|
||||
triggers = {
|
||||
server_id = hcloud_server.this.id
|
||||
static_files = local.vpn_static_files_hash
|
||||
}
|
||||
|
||||
connection {
|
||||
type = "ssh"
|
||||
host = hcloud_server.this.ipv4_address
|
||||
user = "root"
|
||||
private_key = file(var.ssh_private_key_path)
|
||||
}
|
||||
|
||||
provisioner "remote-exec" {
|
||||
inline = ["mkdir -p /home/${var.deploy_user}/services"]
|
||||
}
|
||||
|
||||
provisioner "file" {
|
||||
source = "${path.root}/../services/vpn"
|
||||
destination = "/home/${var.deploy_user}/services"
|
||||
}
|
||||
|
||||
provisioner "remote-exec" {
|
||||
inline = [
|
||||
"chown -R ${var.deploy_user}:${var.deploy_user} /home/${var.deploy_user}/services",
|
||||
"chmod +x /home/${var.deploy_user}/services/vpn/*.sh",
|
||||
]
|
||||
}
|
||||
|
||||
depends_on = [hcloud_server.this]
|
||||
labels = { role = "vpn" } # picked up by ansible/inventory/hcloud.yml
|
||||
}
|
||||
|
||||
@@ -22,18 +22,3 @@ variable "allowed_ssh_source_ips" {
|
||||
description = "CIDRs allowed to reach port 22 on vpn."
|
||||
type = list(string)
|
||||
}
|
||||
|
||||
variable "bootstrap_script" {
|
||||
description = "Rendered post-install script, uploaded and executed on the server immediately after creation."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "ssh_private_key_path" {
|
||||
description = "Local path to the private key matching one of var.ssh_key_ids, used to run the bootstrap script over SSH."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "deploy_user" {
|
||||
description = "Non-root sudo user created by the bootstrap script - services/vpn is copied into this user's home directory."
|
||||
type = string
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Post-install bootstrap - uploaded and executed once by OpenTofu immediately
|
||||
# after server creation (see modules/<host>/main.tf). Idempotent-ish: safe to
|
||||
# re-run by hand, but only ever runs automatically on first create.
|
||||
set -euo pipefail
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
DEPLOY_USER="${deploy_user}"
|
||||
|
||||
apt-get update -y
|
||||
apt-get upgrade -y
|
||||
|
||||
# --- Docker Engine + Compose plugin ---
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
apt-get install -y ca-certificates curl gnupg
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
|
||||
chmod a+r /etc/apt/keyrings/docker.asc
|
||||
. /etc/os-release
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $VERSION_CODENAME stable" \
|
||||
> /etc/apt/sources.list.d/docker.list
|
||||
apt-get update -y
|
||||
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
fi
|
||||
|
||||
# --- Non-root sudo user, given the same key root was provisioned with ---
|
||||
if ! id -u "$DEPLOY_USER" >/dev/null 2>&1; then
|
||||
useradd --create-home --shell /bin/bash "$DEPLOY_USER"
|
||||
usermod -aG sudo,docker "$DEPLOY_USER"
|
||||
mkdir -p "/home/$DEPLOY_USER/.ssh"
|
||||
cp /root/.ssh/authorized_keys "/home/$DEPLOY_USER/.ssh/authorized_keys"
|
||||
chown -R "$DEPLOY_USER:$DEPLOY_USER" "/home/$DEPLOY_USER/.ssh"
|
||||
chmod 700 "/home/$DEPLOY_USER/.ssh"
|
||||
chmod 600 "/home/$DEPLOY_USER/.ssh/authorized_keys"
|
||||
echo "$DEPLOY_USER ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/90-$DEPLOY_USER"
|
||||
chmod 440 "/etc/sudoers.d/90-$DEPLOY_USER"
|
||||
fi
|
||||
|
||||
# --- SSH hardening: key-only auth everywhere. Root keeps key-only login as a
|
||||
# fallback rather than being fully locked out, in case $DEPLOY_USER setup above
|
||||
# ever fails silently on a future image. ---
|
||||
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
|
||||
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
|
||||
systemctl reload ssh 2>/dev/null || systemctl reload sshd
|
||||
|
||||
# --- Unattended security upgrades ---
|
||||
apt-get install -y unattended-upgrades
|
||||
dpkg-reconfigure -f noninteractive unattended-upgrades
|
||||
systemctl enable --now unattended-upgrades
|
||||
@@ -2,18 +2,13 @@
|
||||
# never commit real values there.
|
||||
#
|
||||
# The Hetzner API token is NOT set here: export it as HCLOUD_TOKEN in your shell
|
||||
# before running tofu plan/apply.
|
||||
# before running tofu plan/apply. The same token and SSH key are used again by
|
||||
# Ansible afterwards - see ../ansible/README.md.
|
||||
|
||||
# Names of SSH keys already uploaded to your Hetzner Cloud project
|
||||
# (Console > Security > SSH Keys). All of them are installed on every server. Required.
|
||||
ssh_key_names = ["your-key-name", "laptop", "phone"]
|
||||
|
||||
# Local path to the private key matching ONE of ssh_key_names above (doesn't need
|
||||
# to be all of them - just one you hold). OpenTofu uses this once per server to
|
||||
# upload and run the post-install bootstrap script
|
||||
# (infra/scripts/bootstrap.sh.tftpl) immediately after creation. Required.
|
||||
ssh_private_key_path = "~/.ssh/id_ed25519"
|
||||
|
||||
# Optional overrides - defaults live in variables.tf
|
||||
# location = "nbg1"
|
||||
# dev_server_type = "cx22"
|
||||
@@ -22,6 +17,4 @@ ssh_private_key_path = "~/.ssh/id_ed25519"
|
||||
# dev_volume_size = 20
|
||||
# prod_volume_size = 20
|
||||
# allowed_ssh_source_ips = ["203.0.113.4/32"]
|
||||
# deploy_user = "deploy"
|
||||
# dev_runner_count = 3
|
||||
# dns_zones = ["luke-else.co.uk", "divine-couture.co.uk", "snexo.co.uk"]
|
||||
|
||||
@@ -81,23 +81,6 @@ variable "allowed_ssh_source_ips" {
|
||||
default = ["0.0.0.0/0", "::/0"]
|
||||
}
|
||||
|
||||
variable "ssh_private_key_path" {
|
||||
description = "Local path to the private key matching one of var.ssh_key_names - only needs to be a key you hold yourself, not all of them. Used once per server by OpenTofu to upload and run the post-install bootstrap script over SSH immediately after creation (see infra/scripts/bootstrap.sh.tftpl)."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "deploy_user" {
|
||||
description = "Non-root sudo user created on every server by the bootstrap script, with the same SSH key as root."
|
||||
type = string
|
||||
default = "deploy"
|
||||
}
|
||||
|
||||
variable "dev_runner_count" {
|
||||
description = "Number of Gitea Actions runner containers to run on dev. Rendered into services/dev/Runners/docker-compose.yml on every tofu apply - see infra/modules/dev/templates/runners-docker-compose.yml.tftpl."
|
||||
type = number
|
||||
default = 1
|
||||
}
|
||||
|
||||
variable "dns_zones" {
|
||||
description = "Domains to manage as Hetzner DNS zones. Point each domain's registrar NS records at tofu output dns_nameservers for Hetzner to actually become authoritative."
|
||||
type = list(string)
|
||||
|
||||
@@ -6,14 +6,6 @@ terraform {
|
||||
source = "hetznercloud/hcloud"
|
||||
version = "~> 1.54" # hcloud_zone / hcloud_zone_rrset (DNS) require >= 1.54.0
|
||||
}
|
||||
local = {
|
||||
source = "hashicorp/local"
|
||||
version = "~> 2.5"
|
||||
}
|
||||
null = {
|
||||
source = "hashicorp/null"
|
||||
version = "~> 3.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user