Add infrastructure documentation and project setup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
271
docs/infrastructure.md
Normal file
271
docs/infrastructure.md
Normal file
@@ -0,0 +1,271 @@
|
||||
# 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 = <stored on node>
|
||||
|
||||
[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*
|
||||
Reference in New Issue
Block a user