Webserver
webserver (VMID 114, 10.0.0.14) is the sole public web ingress for *.abair.ie. Every other server is on the private 10.0.0.0/24 network and unreachable from the internet directly — this VM terminates TLS and reverse-proxies everything.
Configured by ansible/hetzner-main/setup-webserver.yml.
What's running
- nginx, tuned for WebSocket-heavy backends (streaming ASR, dictation): a systemd drop-in raises
LimitNOFILEto 65536,worker_processes auto,worker_connections 8192. - Certbot, using the Cloudflare DNS-01 challenge (
python3-certbot-dns-cloudflare) to issue a single wildcard certificate coveringabair.ie,*.abair.ie,*.geabaire.abair.ie, and*.scealai.abair.ie. - Cloudflare real-IP passthrough — the actual Cloudflare IP ranges are fetched live from
cloudflare.com/ips-v4/ips-v6and templated into nginx so backend apps see real client IPs. - JSON-formatted access logs (time, host, method, uri, status, bytes, referer, UA, IP, duration) for ingestion by the observability stack.
- Basic-auth (
htpasswd) protecting anadminuser for admin-only endpoints. - Grafana Alloy, tailing
/var/log/nginx/access.logand shipping parsed fields to Loki, plus host metrics to Prometheus, both on the observability VM.
Site configuration
Every vhost is defined in networking/nginx-config/ in the automation repo (one file per subdomain) and pushed wholesale on every make update-webserver run — the playbook wipes sites-available/sites-enabled and replaces them from that directory, so the automation repo, not the live server, is the source of truth for nginx config. See Modifying Infrastructure for how to add a new site.
Firewall
UFW allows only 22 (SSH), 80, and 443 inbound; everything else is denied by default.
Resizing this VM — read before you qm set
Terraform reaches the Proxmox API via proxmox.abair.ie, which is served by this VM's own nginx. Stopping the VM to resize it (terraform apply, or any live-resize workflow) can break Terraform's own path to the Proxmox API while the VM is down. There's also no CPU/memory hotplug, so a resize needs a cold boot regardless.
The correct procedure is to resize directly on the Proxmox host, then update the .tf file to match so Terraform shows no drift:
qm shutdown 114
qm set 114 --cores <N> --memory <M>
qm start 114
Resizing also regenerates the cloud-init ISO, which rotates the VM's SSH host keys. Your next SSH or Ansible run will fail with REMOTE HOST IDENTIFICATION HAS CHANGED — fix it with:
ssh-keygen -R 10.0.0.14
ssh-keygen -R webserver-vm