Files
PocketVeto/UPDATING.md
Jack Levy a96bd024e9 docs: v1.0.0 — full documentation update
- ROADMAP.md: mark all v0.9.8–v0.9.10 items shipped; Phase 4
  accountability features complete; v1.0 criteria all met; update to
  reflect current state as of v0.9.10
- DEPLOYING.md: add SMTP/email section, ENCRYPTION_SECRET_KEY entry,
  fix OPENAI_MODEL default (gpt-4o → gpt-4o-mini), add pocketveto.org
  reference
- UPDATING.md: replace personal git remote with YOUR_GIT_REMOTE
  placeholder for public deployability
- ARCHITECTURE.md: add member_scores table, alignment API, LLM Batch
  API, email unsubscribe, bill tab UI, topic tags constant, Fernet
  encryption pattern, feature history through v0.9.10

Authored by: Jack Levy
2026-03-15 01:10:52 -04:00

254 lines
5.8 KiB
Markdown

# Updating PocketVeto — Remote Server Setup & Deployment Workflow
How to push new code from your development machine and pull it on the production server.
---
## Overview
The workflow is:
```
Local machine → git push → YOUR_GIT_REMOTE → (pull on server) → docker compose up --build -d
```
You develop locally, push to the Gitea remote, then update the production server — either manually over SSH or via an automated webhook.
---
## 1. SSH access to the production server
Make sure you can SSH into the server without a password:
```bash
# On your local machine — generate a key if you don't have one
ssh-keygen -t ed25519 -C "pocketveto-deploy"
# Copy the public key to the server
ssh-copy-id user@YOUR_SERVER_IP
```
Test:
```bash
ssh user@YOUR_SERVER_IP "echo ok"
```
---
## 2. Server: clone the repo and authenticate
On the server, clone from your Gitea instance:
```bash
ssh user@YOUR_SERVER_IP
cd /opt # or wherever you want to host it
git clone https://YOUR_GIT_REMOTE.git
cd civicstack
```
If your Gitea repo is private, create a **deploy token** in Gitea:
- Gitea → Repository → Settings → Deploy Keys → Add Deploy Key (read-only is fine)
- Or: Gitea → User Settings → Applications → Generate Token
Store credentials so `git pull` doesn't prompt:
```bash
# Using a personal access token stored in the URL
git remote set-url origin https://YOUR_TOKEN@YOUR_GIT_REMOTE.git
```
Verify:
```bash
git pull # should succeed with no password prompt
```
---
## 3. Option A — Manual update (simplest)
SSH in and run:
```bash
ssh user@YOUR_SERVER_IP
cd /opt/civicstack
git pull origin main
docker compose up --build -d
```
That's it. Docker rebuilds only the images that changed (layer cache means unchanged services rebuild in seconds). Migrations run automatically when the API container restarts.
**One-liner from your local machine:**
```bash
ssh user@YOUR_SERVER_IP "cd /opt/civicstack && git pull origin main && docker compose up --build -d"
```
---
## 4. Option B — Deploy script
Create `/opt/civicstack/deploy.sh` on the server:
```bash
#!/bin/bash
set -e
cd /opt/civicstack
echo "==> Pulling latest code"
git pull origin main
echo "==> Building and restarting containers"
docker compose up --build -d
echo "==> Done. Current status:"
docker compose ps
```
```bash
chmod +x /opt/civicstack/deploy.sh
```
Now from your local machine:
```bash
ssh user@YOUR_SERVER_IP /opt/civicstack/deploy.sh
```
---
## 5. Option C — Automated webhook (Gitea → server)
This triggers a deploy automatically every time you push to `main`.
### 5a. Create a webhook listener on the server
Install a simple webhook runner. The easiest is [`webhook`](https://github.com/adnanh/webhook):
```bash
apt install webhook
```
Create `/etc/webhook/hooks.json`:
```json
[
{
"id": "civicstack-deploy",
"execute-command": "/opt/civicstack/deploy.sh",
"command-working-directory": "/opt/civicstack",
"response-message": "Deploying...",
"trigger-rule": {
"match": {
"type": "payload-hmac-sha256",
"secret": "your-webhook-secret",
"parameter": { "source": "header", "name": "X-Gitea-Signature-256" }
}
}
}
]
```
Start the webhook service:
```bash
# Test it first
webhook -hooks /etc/webhook/hooks.json -port 9000 -verbose
# Or create a systemd service (recommended)
```
`/etc/systemd/system/webhook.service`:
```ini
[Unit]
Description=Webhook listener for civicstack deploys
After=network.target
[Service]
ExecStart=/usr/bin/webhook -hooks /etc/webhook/hooks.json -port 9000
Restart=on-failure
User=root
[Install]
WantedBy=multi-user.target
```
```bash
systemctl enable --now webhook
```
Expose port 9000 (or proxy it through nginx/Caddy at a path like `/hooks/`).
### 5b. Add the webhook in Gitea
- Gitea → Repository → Settings → Webhooks → Add Webhook → Gitea
- **Target URL:** `http://YOUR_SERVER_IP:9000/hooks/civicstack-deploy`
- **Secret:** same value as `your-webhook-secret` above
- **Trigger:** Push events → branch `main`
Now every `git push origin main` automatically triggers a deploy.
---
## 6. Checking the deployed version
After any update you can confirm what's running:
```bash
# Check the git commit on the server
ssh user@YOUR_SERVER_IP "cd /opt/civicstack && git log --oneline -3"
# Check container status
ssh user@YOUR_SERVER_IP "cd /opt/civicstack && docker compose ps"
# Hit the health endpoint
curl http://YOUR_SERVER_IP/api/health
```
---
## 7. Rolling back
If a bad deploy goes out:
```bash
ssh user@YOUR_SERVER_IP
cd /opt/civicstack
# Roll back to the previous commit
git revert HEAD --no-edit # preferred — creates a revert commit, keeps history clean
# Or hard reset if you're sure (discards the bad commit locally — use with care)
# git reset --hard HEAD~1
git push origin main # if using Option C, this triggers a new deploy automatically
docker compose up --build -d # if manual
```
---
## 8. Environment and secrets
`.env` is **not** tracked in git. If you need to update a secret or add a new API key on the server:
```bash
ssh user@YOUR_SERVER_IP
nano /opt/civicstack/.env
# Then restart only the affected services (usually api + worker)
cd /opt/civicstack
docker compose up -d --no-build api worker beat
```
`--no-build` skips the rebuild step — only a config reload is needed for env var changes.
---
## Summary
| Goal | Command |
|---|---|
| Manual deploy | `ssh server "cd /opt/civicstack && git pull && docker compose up --build -d"` |
| One-step deploy script | `ssh server /opt/civicstack/deploy.sh` |
| Automated on push | Gitea webhook → webhook listener → `deploy.sh` |
| Rollback | `git revert HEAD` + redeploy |
| Update env only | Edit `.env` on server + `docker compose up -d --no-build api worker beat` |
| Check what's running | `ssh server "cd /opt/civicstack && git log --oneline -1 && docker compose ps"` |