You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
4.7 KiB
202 lines
4.7 KiB
# Deployment Plan: motief.sgeboers.nl
|
|
|
|
**Date:** 2026-03-26
|
|
**Subdomain:** `motief.sgeboers.nl`
|
|
**Stack:** Streamlit · DuckDB · Docker · Nginx · Drone CI
|
|
**Target:** VPS, `webapps` user at `/home/webapps/motief/`
|
|
|
|
---
|
|
|
|
## What's already ready (no changes needed)
|
|
|
|
- `Dockerfile` — builds `streamlit run Home.py --server.port=8501`
|
|
- `docker-compose.yml` — `motief` + `scheduler` services, `DATA_DIR` env override
|
|
- `.drone.yml` — builds image, pushes to registry, SSH-deploys on push to `main`
|
|
- `Home.py`, `pages/1_Stemwijzer.py`, `pages/2_Explorer.py` — all exist
|
|
|
|
---
|
|
|
|
## Step A — VPS: one-time directory setup
|
|
|
|
SSH in as `webapps`:
|
|
|
|
```bash
|
|
mkdir -p /home/webapps/motief/data
|
|
```
|
|
|
|
Create `/home/webapps/motief/.env`:
|
|
|
|
```env
|
|
DOCKER_REGISTRY=<your-registry-url>
|
|
DOCKER_USERNAME=<registry-user>
|
|
DOCKER_PASSWORD=<registry-password>
|
|
OPENROUTER_API_KEY=<key>
|
|
OPENAI_API_KEY=<key>
|
|
```
|
|
|
|
Copy `docker-compose.yml` into place:
|
|
|
|
```bash
|
|
# From local machine
|
|
scp docker-compose.yml webapps@<vps>:/home/webapps/motief/
|
|
```
|
|
|
|
Or just clone the repo there and symlink — either works since Drone will overwrite it.
|
|
|
|
---
|
|
|
|
## Step B — Transfer the database
|
|
|
|
From local machine (~4 GB, takes a few minutes):
|
|
|
|
```bash
|
|
rsync -avz --progress data/motions.db webapps@<vps>:/home/webapps/motief/data/motions.db
|
|
```
|
|
|
|
Do this as close to go-live as possible so the data isn't stale on launch.
|
|
|
|
---
|
|
|
|
## Step C — DNS
|
|
|
|
Add an **A record** in your DNS provider:
|
|
|
|
```
|
|
stematlas → (obsolete, skip)
|
|
motief → <VPS IPv4>
|
|
```
|
|
|
|
TTL 300 for the first deploy so you can iterate quickly; bump to 3600 after it's stable.
|
|
|
|
---
|
|
|
|
## Step D — Nginx vhost
|
|
|
|
Create `/etc/nginx/sites-available/motief`:
|
|
|
|
```nginx
|
|
server {
|
|
listen 80;
|
|
server_name motief.sgeboers.nl;
|
|
return 301 https://$host$request_uri;
|
|
}
|
|
|
|
server {
|
|
listen 443 ssl;
|
|
server_name motief.sgeboers.nl;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/motief.sgeboers.nl/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/motief.sgeboers.nl/privkey.pem;
|
|
|
|
# Streamlit requires WebSocket upgrade for live updates
|
|
location / {
|
|
proxy_pass http://127.0.0.1:8501;
|
|
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_read_timeout 86400;
|
|
}
|
|
}
|
|
```
|
|
|
|
Enable and reload:
|
|
|
|
```bash
|
|
sudo ln -s /etc/nginx/sites-available/motief /etc/nginx/sites-enabled/
|
|
sudo nginx -t && sudo systemctl reload nginx
|
|
```
|
|
|
|
---
|
|
|
|
## Step E — TLS cert
|
|
|
|
```bash
|
|
sudo certbot --nginx -d motief.sgeboers.nl
|
|
```
|
|
|
|
(Assumes Certbot is already installed and working for other subdomains.)
|
|
|
|
---
|
|
|
|
## Step F — Configure Drone secrets
|
|
|
|
In the Gitea/Drone repo settings for `sgeboers/stemwijzer`, add:
|
|
|
|
| Secret | Value |
|
|
|--------|-------|
|
|
| `DOCKER_REGISTRY` | Your registry URL |
|
|
| `DOCKER_USERNAME` | Registry login |
|
|
| `DOCKER_PASSWORD` | Registry password |
|
|
| `DEPLOY_HOST` | VPS hostname/IP |
|
|
| `DEPLOY_SSH_PORT` | SSH port (usually 22) |
|
|
| `DEPLOY_USER` | `webapps` |
|
|
| `DEPLOY_PASSWORD` | webapps SSH password |
|
|
|
|
---
|
|
|
|
## Step G — First deploy
|
|
|
|
Option 1 — trigger Drone automatically:
|
|
```bash
|
|
git push origin main
|
|
```
|
|
Drone builds → pushes image → SSH into VPS → `docker-compose up -d`.
|
|
|
|
Option 2 — manual first deploy (on VPS):
|
|
```bash
|
|
cd /home/webapps/motief
|
|
docker-compose pull
|
|
docker-compose up -d
|
|
```
|
|
|
|
---
|
|
|
|
## Step H — Verify
|
|
|
|
```bash
|
|
# On VPS
|
|
docker-compose -f /home/webapps/motief/docker-compose.yml logs -f motief
|
|
|
|
# From local browser
|
|
open https://motief.sgeboers.nl
|
|
```
|
|
|
|
Checklist:
|
|
- [ ] Home.py loads with nav to Stemwijzer and Explorer
|
|
- [ ] Compass tab renders with correct party positions (GL-PvdA top-left, PVV bottom-right)
|
|
- [ ] SVD tab scree plot shows with highlighted top-2 bars
|
|
- [ ] Similarity search returns results
|
|
- [ ] Scheduler container is running (`docker-compose ps`)
|
|
|
|
---
|
|
|
|
## Ongoing: data updates
|
|
|
|
The `scheduler` service runs the weekly pipeline inside the container:
|
|
- Scrapes new motions from the TK OData API
|
|
- Re-embeds new motion text via OpenRouter
|
|
- Updates similarity cache
|
|
|
|
The `motions.db` file on the VPS is the single source of truth — it's bind-mounted into both containers. No cron job needed on the host.
|
|
|
|
If you ever need to force a full re-run:
|
|
```bash
|
|
docker-compose exec scheduler python pipeline/run_pipeline.py --db-path data/motions.db
|
|
```
|
|
|
|
---
|
|
|
|
## Dependency order
|
|
|
|
```
|
|
A (dirs + .env) ─┐
|
|
B (rsync DB) ─┤─► G (first deploy) ─► H (verify)
|
|
C (DNS) ─┤
|
|
D (nginx) ─┤
|
|
E (certbot) ─┘
|
|
F (Drone secrets) ──► future auto-deploys on push to main
|
|
```
|
|
|
|
Steps A–F can all be done in one SSH session. Total estimated time: **45 minutes** (mostly waiting on rsync).
|
|
|