Tenant Upgrade Runbook¶
Last Updated: December 5, 2025
This document describes how to upgrade tenant cbapp instances to the latest code, including running migrations and restarting services.
Prerequisites¶
- SSH access to server
- cbapp repo has latest code pushed to
mainbranch - Tenant is registered in cbtenant database
Quick Reference¶
# Variables - set these for your tenant
TENANT_SLUG="ky04"
TENANT_DIR="/home/bisenbek/projects/nominate/${TENANT_SLUG}"
TENANT_PORT="32321" # Check cbtenant DB for actual port
# 1. Pull latest code
cd $TENANT_DIR
git fetch origin main:main
git stash # if needed
git checkout main
# 2. Add API_KEYS to .env (if not present)
grep "API_KEYS" .env || echo 'API_KEYS=test-api-key-for-development' >> .env
# 3. Run migrations
./venv/bin/python scripts/migrate_add_import_metadata.py
./venv/bin/python scripts/add_person_indexes.py
# 4. Restart service
PID=$(ps aux | grep "run_api.py.*${TENANT_PORT}" | grep -v grep | awk '{print $2}')
kill $PID
nohup ./venv/bin/python run_api.py --host 0.0.0.0 --port $TENANT_PORT > /tmp/${TENANT_SLUG}-api.log 2>&1 &
# 5. Verify
curl http://localhost:${TENANT_PORT}/api/health
Detailed Steps¶
Step 1: Get Tenant Info¶
Query the cbtenant database for tenant details:
cd /home/bisenbek/projects/nominate/cbtenant
sqlite3 db/manager.db "SELECT slug, backend_port, directory FROM tenants;"
Output example:
mi20-clevenger|32311|/home/bisenbek/projects/nominate/mi20-clevenger
ky04|32321|/home/bisenbek/projects/nominate/ky04
Step 2: Update Code¶
cd /home/bisenbek/projects/nominate/<TENANT_SLUG>
# Check current remote (should be cbapp)
git remote -v
# If pointing to wrong repo, fix it:
git remote set-url origin git@github.com:Nominate-AI/cbapp.git
# Fetch and checkout main
git fetch origin main:main
git stash # Save any local changes
git checkout main
# Verify we have latest commits
git log --oneline -3
# Should show:
# d9ddc8e Add direct DuckDB bulk import endpoint for fast CSV imports
# 0d52d39 Add API key auth, import metadata, and performance indexes
# e50e9b1 Add comprehensive documentation for cbapp development
Step 3: Configure API Keys¶
The bulk import feature requires API key authentication:
# Check if API_KEYS is configured
grep "API_KEYS" .env
# If not present, add it:
echo 'API_KEYS=test-api-key-for-development' >> .env
Note: For production, generate a secure API key and update both:
- Tenant's .env (API_KEYS)
- cbtenant's .env (CBAPP_API_KEY)
Step 4: Run Migrations¶
Two migrations are required for the bulk import feature:
# Add import metadata columns (import_source, import_batch_id, etc.)
./venv/bin/python scripts/migrate_add_import_metadata.py
# Add performance indexes
./venv/bin/python scripts/add_person_indexes.py
Expected output for metadata migration:
Running migration on database at .../db/pocket.db
Adding import metadata columns to person table...
✓ Added import_source column
✓ Added import_date column
✓ Added import_batch_id column
✓ Added import_filename column
✓ Added original_data column
✓ Created index on import_batch_id
Migration completed successfully!
Step 5: Restart Service¶
# Find and kill existing process
TENANT_PORT=32321 # Replace with actual port
PID=$(ps aux | grep "run_api.py.*${TENANT_PORT}" | grep -v grep | awk '{print $2}')
echo "Killing PID: $PID"
kill $PID
# Wait for clean shutdown
sleep 2
# Start new process
nohup ./venv/bin/python run_api.py --host 0.0.0.0 --port $TENANT_PORT > /tmp/tenant-api.log 2>&1 &
echo "Started with PID: $!"
Step 6: Verify¶
# Health check
curl http://localhost:${TENANT_PORT}/api/health
# Expected: {"status":"healthy"}
# Test bulk import endpoint (should return validation error, not 404)
curl -X POST http://localhost:${TENANT_PORT}/api/persons/bulk-import \
-H "X-API-Key: test-api-key-for-development" \
-H "Content-Type: application/json" \
-d '{"file_path": "/tmp/test.csv", "mappings": {}, "batch_id": "test", "list_name": "test"}'
# Expected: {"detail":"File path must be within /tmp/imports"} or similar
Tenant Status¶
| Tenant | Port | Code Version | Migrations | Status |
|---|---|---|---|---|
| ky04 | 32321 | d9ddc8e (latest) | ✅ Complete | ✅ Running |
| mi20-clevenger | 32311 | d9ddc8e (latest) | ✅ Complete | ✅ Running |
Last Updated: December 5, 2025
Troubleshooting¶
Git checkout fails with "untracked files would be overwritten"¶
# Remove conflicting untracked files
rm scripts/add_person_columns.py # or whatever file is conflicting
git checkout main
Migration fails with "column already exists"¶
This is safe to ignore - the column was already added in a previous run.
Service won't start¶
Check the log file:
Common issues:
- Port already in use: Kill the old process first
- Missing dependencies: Run pip install -r requirements.txt
- Database locked: Wait for other operations to complete
API key authentication fails¶
Verify API_KEYS is set in .env:
Related Documentation¶
cbapp/CLAUDE.md- Developer documentationcbtenant/docs/DATABASE_ARCHITECTURE.md- Database schema details- GitHub Issues: Nominate-AI/cbapp#1-4 - Implementation details