feat: PocketVeto v1.0.0 — initial public release
Self-hosted US Congress monitoring platform with AI policy briefs, bill/member/topic follows, ntfy + RSS + email notifications, alignment scoring, collections, and draft-letter generator. Authored by: Jack Levy
This commit is contained in:
253
UPDATING.md
Normal file
253
UPDATING.md
Normal file
@@ -0,0 +1,253 @@
|
||||
# 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"` |
|
||||
Reference in New Issue
Block a user