Two prod-readiness hardening changes: DB tuning scales with the container budget. Replace the fixed 8 GB 20-tuning.sql with 20-tuning.sh, which derives shared_buffers (25%), effective_cache_size (75%), work_mem, maintenance_work_mem and duckdb.max_memory (50%) from the DB_MEMORY the compose db service now passes in. The ratios reproduce the historical 8 GB tuning exactly and scale linearly, so the 48 GB prod box (db_memory 16g) gets shared_buffers 4 GB / duckdb 8 GB with no separate edit. Beta/local (8g default) are unchanged. Docs that told operators to raise the tuning by hand are updated. Boot ordering for the self-hosted archive. On an openmeteo host, install a docker.service drop-in (Wants/After rclone-om.service) so Docker starts after the object-storage mount is ready on every boot — the restart-policy containers never bind an empty mount point. rclone-om is Type=notify, so After waits for the mount to actually be ready. Cleaned up when openmeteo is toggled off.
106 lines
4.6 KiB
Text
106 lines
4.6 KiB
Text
# Copy to terraform.tfvars and fill in real IPs + secrets.
|
|
# cp terraform.tfvars.example terraform.tfvars
|
|
# terraform.tfvars is gitignored (it holds secrets, and those land in local state).
|
|
# NEVER commit real values.
|
|
|
|
# ---------------------------------------------------------------------------------
|
|
# Hosts
|
|
# ---------------------------------------------------------------------------------
|
|
# Two VPS hosts. (The `dev` branch deploys to the LAN dev server via
|
|
# deploy/deploy-dev.sh — that box is NOT managed by Terraform.)
|
|
hosts = {
|
|
# Production: the NEW 48 GB / 12-core VPS serving thermograph.org (branch `release`).
|
|
prod = {
|
|
host = "REPLACE_WITH_NEW_VPS_IP" # <-- the new prod VPS IP/hostname
|
|
ssh_user = "deploy"
|
|
ssh_private_key_path = "~/.ssh/id_ed25519" # key that can log in as deploy@ and sudo
|
|
role = "prod"
|
|
git_branch = "release"
|
|
domain = "thermograph.org" # Caddy TLS in front, app on loopback
|
|
compose_files = ["docker-compose.yml"]
|
|
app_dir = "/opt/thermograph"
|
|
# Sized up for the big box — tune freely. The Postgres internal budget scales from
|
|
# db_memory automatically (deploy/db/init/20-tuning.sh); no separate tuning edit.
|
|
workers = 8
|
|
app_cpus = 8
|
|
db_cpus = 4
|
|
db_memory = "16g"
|
|
# Self-host the ERA5 archive here: layers docker-compose.openmeteo.yml and
|
|
# provisions the rclone mount of the object-storage bucket (om_* vars below).
|
|
openmeteo = true
|
|
om_data_dir = "/mnt/om-archive"
|
|
}
|
|
|
|
# Beta / testing: the OLD VPS, repurposed (branch `main`).
|
|
beta = {
|
|
host = "75.119.132.91"
|
|
ssh_user = "deploy"
|
|
ssh_private_key_path = "~/.ssh/id_ed25519"
|
|
role = "beta"
|
|
git_branch = "main"
|
|
# No public domain by default: no Caddy/TLS, firewall opens the app port. NOTE:
|
|
# with compose_files = ["docker-compose.yml"] the app binds 127.0.0.1 only, so
|
|
# until you either set a domain (e.g. "beta.thermograph.org", which fronts it with
|
|
# Caddy) or add the 0.0.0.0-publishing dev overlay, reach it via an SSH tunnel.
|
|
domain = ""
|
|
compose_files = ["docker-compose.yml"]
|
|
app_dir = "/opt/thermograph"
|
|
workers = 4
|
|
app_cpus = 4
|
|
db_cpus = 2
|
|
db_memory = "8g"
|
|
}
|
|
}
|
|
|
|
# Optional overrides (shown with their defaults):
|
|
# repo_url = "https://github.com/griffemi/thermograph.git"
|
|
# app_port = 8137
|
|
|
|
# ---------------------------------------------------------------------------------
|
|
# Self-hosted Open-Meteo archive (only used by hosts with openmeteo = true) --------
|
|
# ---------------------------------------------------------------------------------
|
|
# The ERA5 .om archive lives in an object-storage bucket, rclone-mounted on the host.
|
|
# om_rclone_conf holds bucket credentials (sensitive; lands in state — keep out of git).
|
|
# See deploy/openmeteo/README.md for the bucket + mount setup.
|
|
om_bucket_remote = "om-archive:REPLACE_WITH_BUCKET_NAME"
|
|
om_vfs_cache_max = "80G"
|
|
om_rclone_conf = <<-RCLONE
|
|
[om-archive]
|
|
type = s3
|
|
provider = Cloudflare
|
|
endpoint = https://REPLACE.r2.cloudflarestorage.com
|
|
access_key_id = REPLACE_WITH_ACCESS_KEY
|
|
secret_access_key = REPLACE_WITH_SECRET_KEY
|
|
RCLONE
|
|
|
|
# ---------------------------------------------------------------------------------
|
|
# Shared secrets (DUMMY values — replace, and keep this file out of git)
|
|
# ---------------------------------------------------------------------------------
|
|
postgres_password = "REPLACE_WITH_A_STRONG_DB_PASSWORD"
|
|
# python -c "import secrets; print(secrets.token_urlsafe(48))"
|
|
auth_secret = "REPLACE_WITH_A_LONG_RANDOM_STRING"
|
|
# cd backend && ../.venv/bin/python -c "import push,json;k=push._generate();print(k['private_key']);print(k['public_key'])"
|
|
vapid_private_key = "REPLACE_WITH_VAPID_PRIVATE_KEY"
|
|
vapid_public_key = "REPLACE_WITH_VAPID_PUBLIC_KEY"
|
|
vapid_contact = "mailto:you@example.com"
|
|
|
|
# ---- Optional: search-engine verification (leave "" to omit) --------------------
|
|
# google_verify = ""
|
|
# bing_verify = ""
|
|
|
|
# ---- Optional: outbound email (leave "" to omit) --------------------------------
|
|
# mail_backend = "smtp"
|
|
# smtp_host = "127.0.0.1"
|
|
# smtp_port = "25"
|
|
# smtp_user = ""
|
|
# smtp_password = ""
|
|
# smtp_starttls = ""
|
|
# mail_from = "Thermograph <no-reply@thermograph.org>"
|
|
# mail_reply_to = ""
|
|
|
|
# ---- Optional: Discord (leave "" to omit) ---------------------------------------
|
|
# discord_webhook = ""
|
|
# discord_public_key = ""
|
|
# discord_app_id = ""
|
|
# discord_bot_token = ""
|
|
# discord_client_secret = ""
|