The on-demand GPU droplet (model-boss/vLLM) must land at a free mesh IP; .6 was reassigned to com.uvlava.ct.redroid. .9 matches the canonical model-boss endpoint http://10.9.0.9:8000 that prospector (MODEL_BOSS_URL) and mr-number (RATING_LLM_URL) now point at. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
224 lines
7.5 KiB
HCL
224 lines
7.5 KiB
HCL
###############################################################################
|
|
# Credentials (never commit values — pass via TF_VAR_* env or a gitignored
|
|
# terraform.tfvars). See terraform.tfvars.example.
|
|
###############################################################################
|
|
|
|
variable "do_token" {
|
|
description = "DigitalOcean API token (read/write)."
|
|
type = string
|
|
sensitive = true
|
|
}
|
|
|
|
variable "spaces_access_id" {
|
|
description = "DigitalOcean Spaces access key ID (S3-compatible). Required only at apply (Spaces resources); empty default lets validate/plan run without it."
|
|
type = string
|
|
sensitive = true
|
|
default = ""
|
|
}
|
|
|
|
variable "spaces_secret_key" {
|
|
description = "DigitalOcean Spaces secret access key. Required only at apply; empty default lets validate/plan run."
|
|
type = string
|
|
sensitive = true
|
|
default = ""
|
|
}
|
|
|
|
###############################################################################
|
|
# Placement
|
|
###############################################################################
|
|
|
|
variable "region" {
|
|
description = "DO region. nyc3 co-locates Droplets + Managed PG + Spaces (operator is in NYC)."
|
|
type = string
|
|
default = "nyc3"
|
|
|
|
validation {
|
|
condition = contains(["nyc3", "fra1", "ams3"], var.region)
|
|
error_message = "Use nyc3 (NYC, operator-local) or an EEA region (fra1/ams3) if GDPR residency wins out."
|
|
}
|
|
}
|
|
|
|
variable "project_name" {
|
|
description = "DO project that groups all rebuild resources."
|
|
type = string
|
|
default = "lilith-store"
|
|
}
|
|
|
|
variable "vpc_ip_range" {
|
|
description = "Private VPC CIDR for the DO store tier (kept off the WG 10.9.0.0/24 range)."
|
|
type = string
|
|
default = "10.20.0.0/24"
|
|
}
|
|
|
|
###############################################################################
|
|
# Network access control
|
|
###############################################################################
|
|
|
|
variable "wg_hub_public_ip" {
|
|
description = "Public IP of the WireGuard hub (vps-0 / yuzu) that the droplet peers with."
|
|
type = string
|
|
default = "89.127.233.145"
|
|
}
|
|
|
|
variable "admin_ips" {
|
|
description = "CIDRs allowed to SSH the backend droplet for bootstrap (before WG is up). Lock to vps-0 + your current IP; do not leave 0.0.0.0/0."
|
|
type = list(string)
|
|
default = ["89.127.233.145/32"]
|
|
}
|
|
|
|
variable "wg_listen_port" {
|
|
description = "WireGuard UDP port the droplet listens on (matches mesh wg1)."
|
|
type = number
|
|
default = 51820
|
|
}
|
|
|
|
###############################################################################
|
|
# Managed Postgres
|
|
###############################################################################
|
|
|
|
variable "pg_version" {
|
|
description = "Managed Postgres major version."
|
|
type = string
|
|
default = "16"
|
|
}
|
|
|
|
variable "pg_size" {
|
|
description = "Managed PG node size slug."
|
|
type = string
|
|
default = "db-s-1vcpu-2gb"
|
|
}
|
|
|
|
variable "pg_node_count" {
|
|
description = "PG nodes (1 = primary only; 2 adds a standby for failover — the thing black never had)."
|
|
type = number
|
|
default = 1
|
|
}
|
|
|
|
variable "pg_databases" {
|
|
description = "Logical databases to create on the cluster (mirrors black's quinn + quinn_admin). Per-service DBs (people, prospector) are owned by their own service-scoped terraform modules that data-source this cluster."
|
|
type = list(string)
|
|
default = ["quinn", "quinn_admin"]
|
|
}
|
|
|
|
###############################################################################
|
|
# Backend droplet
|
|
###############################################################################
|
|
|
|
variable "droplet_size" {
|
|
description = "Backend droplet size (Forgejo + Verdaccio + workers + MCP + mac-sync + WG↔VPC pgBouncer bridge)."
|
|
type = string
|
|
default = "s-2vcpu-4gb"
|
|
}
|
|
|
|
variable "droplet_image" {
|
|
description = "Base image for the backend droplet."
|
|
type = string
|
|
default = "ubuntu-24-04-x64"
|
|
}
|
|
|
|
variable "ssh_key_fingerprints" {
|
|
description = "MD5 fingerprints of DO-registered SSH keys authorized on the droplet (plum + CI)."
|
|
type = list(string)
|
|
}
|
|
|
|
variable "wg_droplet_address" {
|
|
description = "Mesh (wg1) address assigned to the backend droplet peer."
|
|
type = string
|
|
default = "10.9.0.5/32"
|
|
}
|
|
|
|
###############################################################################
|
|
# Essential-services host (com.uvlava.quinn.infra) — DO/nyc3 WG hub + DNS.
|
|
###############################################################################
|
|
|
|
variable "infra_size" {
|
|
description = "Size for the quinn.infra host (DNS + WG hub; light, no app load)."
|
|
type = string
|
|
default = "s-1vcpu-1gb"
|
|
}
|
|
|
|
variable "wg_infra_address" {
|
|
description = "Mesh (wg1) address for the nyc3 hub. /24 so the hub owns the subnet route and relays spoke-to-spoke."
|
|
type = string
|
|
default = "10.9.0.7/24"
|
|
}
|
|
|
|
variable "wg_infra_addr_only" {
|
|
description = "Bare hub mesh IP (no mask) for the dnsmasq hosts file."
|
|
type = string
|
|
default = "10.9.0.7"
|
|
}
|
|
|
|
variable "mesh_domain" {
|
|
description = "Internal DNS zone dnsmasq serves on the mesh (forward-only for everything else)."
|
|
type = string
|
|
default = "uvlava.mesh"
|
|
}
|
|
|
|
###############################################################################
|
|
# Spaces (object storage)
|
|
###############################################################################
|
|
|
|
variable "spaces_bucket_name" {
|
|
description = "Globally-unique Spaces bucket for photo originals + protected downloads."
|
|
type = string
|
|
default = "lilith-quinn-media"
|
|
}
|
|
|
|
variable "enable_cdn" {
|
|
description = "Front the Spaces bucket with the DO CDN (vps-0 edge-caches /photos from it)."
|
|
type = bool
|
|
default = true
|
|
}
|
|
|
|
variable "tags" {
|
|
description = "Tags applied to taggable resources."
|
|
type = list(string)
|
|
default = ["lilith", "store-tier", "managed-by-terraform"]
|
|
}
|
|
|
|
###############################################################################
|
|
# GPU (hybrid inference, item 12b/12c) — adult-context drafting + imajin.
|
|
#
|
|
# NOTE: as of account check 2026-06-27 this DO account is NOT allowlisted for
|
|
# GPU Droplets (the /v2/sizes endpoint returns zero gpu-* slugs). DO gates GPU
|
|
# access behind a request. Keep gpu_enabled=false until access is granted, or
|
|
# `terraform apply` will fail at droplet create. The serverless side (12a) does
|
|
# not depend on this.
|
|
###############################################################################
|
|
|
|
variable "gpu_enabled" {
|
|
description = "Create the self-hosted GPU droplet. Requires DO GPU-droplet access on the account."
|
|
type = bool
|
|
default = false
|
|
}
|
|
|
|
variable "gpu_size" {
|
|
description = "GPU droplet size slug (only valid once allowlisted, e.g. gpu-h100x1-80gb)."
|
|
type = string
|
|
default = "gpu-h100x1-80gb"
|
|
}
|
|
|
|
variable "gpu_image" {
|
|
description = "GPU droplet image (DO AI/ML images ship CUDA drivers)."
|
|
type = string
|
|
default = "gpu-h100x1-base"
|
|
}
|
|
|
|
variable "gpu_region" {
|
|
description = "GPU droplet region (GPU availability is region-limited; often not nyc3)."
|
|
type = string
|
|
default = "nyc2"
|
|
}
|
|
|
|
variable "wg_gpu_address" {
|
|
description = "Mesh (wg1) address for the GPU droplet peer."
|
|
type = string
|
|
default = "10.9.0.9/32"
|
|
}
|
|
|
|
variable "forge_public_ip" {
|
|
description = "Bootstrap public IP used only when templating cloud-init/forge.yaml (Forgejo DOMAIN/ROOT_URL etc at first boot). After the droplet resource is created or imported, all DNS and runtime references use digitalocean_droplet.forge.ipv4_address. Keep this in sync only for fresh reprovisions."
|
|
type = string
|
|
default = "134.199.243.61"
|
|
}
|