Skip to content

Tenant Deployment

This guide covers deploying new tenant instances.

Prerequisites

  • Tenant Manager running
  • SSH access to cbapp repository
  • Available ports

Deployment Process

sequenceDiagram
    participant API as Tenant Manager API
    participant FS as File System
    participant GH as GitHub
    participant SYS as Systemd

    API->>FS: Create tenant directory
    API->>GH: Clone cbapp repository
    API->>FS: Create virtual environment
    API->>FS: Install dependencies
    API->>FS: Generate .env configuration
    API->>FS: Initialize database
    API->>SYS: Create systemd services
    API->>SYS: Start services
    API->>API: Health check

Step-by-Step

1. Create Tenant via API

curl -X POST http://localhost:32201/api/tenants \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Campaign",
    "slug": "my-campaign",
    "domain": "mycampaign.example.com",
    "api_domain": "api.mycampaign.example.com"
  }'

2. Deploy Tenant

curl -X POST http://localhost:32201/api/tenants/{tenant_id}/deploy \
  -H "Authorization: Bearer $TOKEN"

3. Verify Deployment

# Check service status
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:32201/api/tenants/{tenant_id}/services/status

# Check health
curl http://localhost:{api_port}/docs

Directory Structure

After deployment:

/home/bisenbek/projects/nominate/{slug}/
├── venv/                 # Python virtual environment
├── db/
│   └── pocket.db        # Tenant database
├── src/
│   ├── api/             # FastAPI backend
│   └── app/             # FastHTML frontend
├── scripts/             # Migration scripts
├── .env                 # Configuration
├── requirements.txt
└── VERSION

Systemd Services

Two services are created per tenant:

API Service ({slug}-api.service):

[Unit]
Description={name} API
After=network.target

[Service]
Type=simple
User=bisenbek
WorkingDirectory=/path/to/{slug}
ExecStart=/path/to/{slug}/venv/bin/uvicorn src.api.main:app --host 0.0.0.0 --port {api_port}
Restart=always

[Install]
WantedBy=multi-user.target

Frontend Service ({slug}-frontend.service):

[Unit]
Description={name} Frontend
After=network.target

[Service]
Type=simple
User=bisenbek
WorkingDirectory=/path/to/{slug}
ExecStart=/path/to/{slug}/venv/bin/python run_frontend.py
Restart=always

[Install]
WantedBy=multi-user.target

Troubleshooting

Port Already in Use

# Check what's using the port
lsof -i :32310

# Force stop and restart
curl -X POST http://localhost:32201/api/tenants/{id}/services/stop
curl -X POST http://localhost:32201/api/tenants/{id}/services/start

Service Won't Start

# Check logs
sudo journalctl -u {slug}-api -f

# Check permissions
ls -la /path/to/{slug}/

See Also