Files
py-dvt-ate/deploy/readme.md
Kai Chappell ddf2c9439d Simplify deployment - use physics pause instead of container shutdown
- IDLE_PAUSE_SECONDS replaces IDLE_TIMEOUT_MINUTES
- Container stays running, physics pauses when idle
- No restart mechanism needed
- Remove wakeup service (no longer needed)
2026-01-29 21:37:18 +00:00

170 lines
3.8 KiB
Markdown

# py-dvt-ate Deployment
Deploy the DVT Simulation Platform dashboard with Cloudflare Tunnel for public access.
## Idle Auto-Pause
The physics simulation automatically pauses when no one is viewing the dashboard.
**Configuration:**
```bash
# In .env or docker-compose.yml
IDLE_PAUSE_SECONDS=30 # Pause physics after 30s idle
```
**Behaviour:**
- When someone views the dashboard, physics runs normally
- After `IDLE_PAUSE_SECONDS` with no viewers, physics engine pauses
- CPU drops to ~0% while paused
- Physics resumes instantly when someone visits
- Container stays running (no restart needed)
## Architecture
```
Internet
Cloudflare Edge (dvt-demo.kschappell.com)
↓ (tunnel)
cloudflared container
nginx container (WebSocket proxy + header handling)
streamlit container (port 8080)
```
## Directory Structure
```
/mnt/fast-pool/apps/portfolio-demos/py-dvt-ate/
├── docker-compose.yml
├── nginx.conf
├── .env
└── data/ # Persistent storage (created automatically)
├── py_dvt_ate.db # SQLite database
├── measurements/ # Test measurement files
└── reports/ # Generated PDFs
```
## Setup
### 1. Create Cloudflare Tunnel
1. Go to [Cloudflare Zero Trust Dashboard](https://one.dash.cloudflare.com/)
2. Navigate to **Networks****Tunnels**
3. Click **Create a tunnel**
4. Select **Cloudflared** as the connector
5. Name it `py-dvt-ate` (or similar)
6. Copy the tunnel token (long string starting with `eyJ...`)
### 2. Configure Public Hostname
Still in the tunnel configuration:
1. Go to the **Public Hostname** tab
2. Add a public hostname:
- **Subdomain:** `dvt-demo`
- **Domain:** `kschappell.com`
- **Service Type:** `HTTP`
- **URL:** `nginx:80`
This routes `dvt-demo.kschappell.com` → nginx container → Streamlit app.
### 3. Deploy
The build requires access to the full py-dvt-ate source code. Two options:
**Option A: Clone repo to TrueNAS (recommended)**
```bash
# Clone repo to apps directory
cd /mnt/fast-pool/apps/portfolio-demos
git clone https://gitea.kschappell.com/kschappell/py-dvt-ate.git
# Create data directory and .env
cd py-dvt-ate/deploy
mkdir -p data
cp .env.example .env
nano .env # Add your CLOUDFLARE_TUNNEL_TOKEN
# Build and start
docker compose up -d --build
```
**Option B: Build image locally, transfer to TrueNAS**
```bash
# On development machine
cd /path/to/py-dvt-ate
docker build -t py-dvt-ate:latest .
docker save py-dvt-ate:latest | gzip > py-dvt-ate.tar.gz
# Transfer to TrueNAS, then:
docker load < py-dvt-ate.tar.gz
# Update docker-compose.yml to use image instead of build:
# streamlit:
# image: py-dvt-ate:latest
```
**Check logs:**
```bash
docker compose logs -f
```
### 4. Verify
```bash
# Check tunnel is connected (in Cloudflare dashboard, tunnel should show "Healthy")
# Test the endpoint
curl https://dvt-demo.kschappell.com/health
# Test iframe headers
curl -I https://dvt-demo.kschappell.com | grep -i frame
# Should NOT show X-Frame-Options (we strip it)
```
## Troubleshooting
### Tunnel not connecting
Check cloudflared logs:
```bash
docker compose logs cloudflared
```
Common issues:
- Invalid token (regenerate in Cloudflare dashboard)
- Network/firewall blocking outbound connections
### Streamlit not loading in iframe
Check nginx is stripping headers:
```bash
curl -I https://dvt-demo.kschappell.com
```
Should see:
- No `X-Frame-Options` header
- `Content-Security-Policy: frame-ancestors 'self' https://kschappell.com ...`
### WebSocket errors
Check browser console for WebSocket connection failures. Ensure nginx WebSocket config is correct and timeouts are sufficient.
## Updating
```bash
cd /mnt/fast-pool/apps/portfolio-demos/py-dvt-ate/deploy
git pull
docker compose up -d --build
```
## Stopping
```bash
docker compose down
```