# OTIVM Infrastructure *Established: April 2026* This document describes the complete infrastructure built for OTIVM. It is the authoritative reference for all incoming assistants and the project owner. --- ## 1. Overview OTIVM runs on a dedicated LXC container (CT 1105) on the TheRON development Proxmox host (srv-a). It is proxied through the WireGuard mesh hub (wg-pk) and served over HTTPS at https://otium.civicus.us. OTIVM is completely isolated from CIVICVS and TESSERA infrastructure. It shares only the WireGuard mesh and the Nginx proxy node. --- ## 2. Network Topology ``` Browser → otium.civicus.us (DNS A record → 198.58.111.109) → wg-pk Nginx (HTTPS, SSL termination) → WireGuard tunnel → otivm-dev (10.110.0.18) → Node.js app (port 3000) ``` --- ## 3. DNS | Record | Type | Value | |--------|------|-------| | otium.civicus.us | A | 198.58.111.109 | No AAAA record. Traffic is proxied through wg-pk to a container with no public IPv6. Consistent with shell.infra.civicus.us pattern. DNS is managed in BIND9 on the Linode DNS server. Glue records are at Gandi. --- ## 4. Container — CT 1105 | Property | Value | |----------|-------| | VMID | 1105 | | Name | otivm-dev | | Proxmox host | srv-a (10.0.0.11) | | Template | debian-12-standard_12.12-1_amd64 | | Memory | 512MB | | Cores | 2 | | Disk | 8GB (local-lvm) | | LAN IP | 10.0.0.23/24 | | Gateway | 10.0.0.1 | | WireGuard IP | 10.110.0.18/32 | | Unprivileged | yes | --- ## 5. WireGuard This container is peer 10.110.0.18 on the TheRON WireGuard mesh. The hub is wg-pk (198.58.111.109, mesh address 10.110.0.1). ### /etc/wireguard/wg0.conf on otivm-dev ```ini [Interface] Address = 10.110.0.18/32 ListenPort = 51820 PrivateKey = [Peer] PublicKey = 1+Wb++fjXNbY0joOvj4AZvJgF6b125YOPSFsmNqVo3I= AllowedIPs = 10.110.0.0/22 Endpoint = 198.58.111.109:51820 PersistentKeepalive = 25 ``` ### Public key ``` GmJcIZguLxLjh8CNEITp5XUwb1xIDXBYOW/FHj47YUw= ``` ### Peer stanza on wg-pk ```ini [Peer] PublicKey = GmJcIZguLxLjh8CNEITp5XUwb1xIDXBYOW/FHj47YUw= AllowedIPs = 10.110.0.18/32 Endpoint = 73.36.246.43:51820 ``` ### Service management ```bash systemctl status wg-quick@wg0 systemctl restart wg-quick@wg0 wg show ping -c 3 10.110.0.1 # test mesh ``` --- ## 6. Nginx on wg-pk File: /etc/nginx/sites-available/otium.civicus.us ```nginx server { listen 80; listen [::]:80; server_name otium.civicus.us; return 301 https://$host$request_uri; } server { listen 443 ssl; listen [::]:443 ssl; server_name otium.civicus.us; ssl_certificate /etc/letsencrypt/live/otium.civicus.us/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/otium.civicus.us/privkey.pem; location /.well-known/acme-challenge/ { root /var/www/html; } location / { proxy_pass http://10.110.0.18:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; } } ``` --- ## 7. SSL Certificate | Property | Value | |----------|-------| | Domain | otium.civicus.us | | Authenticator | --nginx | | Certificate path | /etc/letsencrypt/live/otium.civicus.us/ | | Issued | April 2026 | | Expires | July 2026 | | Auto-renewal | certbot.timer (systemd, twice daily) | Test renewal: `certbot renew --dry-run` on wg-pk. ⚠ RULE: Always issue SSL certificates FIRST with --nginx authenticator, then add any basic auth after. Never reverse this order. --- ## 8. Application Stack | Component | Value | |-----------|-------| | Runtime | Node.js v22.22.2 | | npm | 10.9.7 | | App user | otivm | | App port | 3000 | | PM2 service | pm2-otivm (systemd, enabled) | | Python | 3.11.2 | | Python venv | /home/otivm/venv | | Claude Code | v2.1.119 | --- ## 9. Users | User | Role | |------|------| | root | Container administration only | | otivm | App user — all app activity, PM2, git, Claude Code | PM2 is always run as otivm. Never as root. Python is always run inside /home/otivm/venv. Never outside. --- ## 10. Webmin Webmin is installed on otivm-dev for file management and container access. It is disabled by default and started manually when needed. ```bash # Aliases in /root/.bashrc webmin-on # systemctl start webmin webmin-off # systemctl stop webmin ``` Port 10000. Not exposed beyond the container network. Auto-start is disabled — Webmin is off after every reboot. --- ## 11. Gitea | Property | Value | |----------|-------| | Repo | https://gitea.barternetwork.us/TheRON/OTIVM | | Branch | main | | Push user | otivm@otivm-dev | | Clone path | /home/otivm/OTIVM | | License | BSD 2-Clause | Git credentials are stored in /home/otivm/.git-credentials (via credential.helper store). --- ## 12. Backup Baseline backup taken immediately after provisioning, before any code deployed: ``` /var/lib/vz/dump/vzdump-lxc-1105-2026_04_25-04_10_53.tar.zst ``` Size: 551MB. Downloaded offline via Webmin. Backup command: ```bash vzdump 1105 --storage local --compress zstd --mode stop ``` --- ## 13. Quick Reference ### Check everything is running ```bash # On otivm-dev systemctl status wg-quick@wg0 ping -c 3 10.110.0.1 # As otivm user pm2 list ``` ### Test the app endpoint ```bash curl -s http://localhost:3000/ ``` ### Test through the full stack ```bash curl -s https://otium.civicus.us/ ``` --- *docs/infrastructure.md — OTIVM — April 2026*