Deployment improvements: - Add template env files (.envs.example/) for documentation - Create init-production.sh for one-time server setup - Create build-activepieces.sh for building/deploying AP image - Update deploy.sh with --deploy-ap flag - Make custom-pieces-metadata.sql idempotent - Update DEPLOYMENT.md with comprehensive instructions Frontend: - Redirect logged-in business owners from root domain to tenant dashboard - Redirect logged-in users from /login to /dashboard on their tenant - Log out customers on wrong subdomain instead of redirecting 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
438 lines
12 KiB
Markdown
438 lines
12 KiB
Markdown
# SmoothSchedule Production Deployment Guide
|
|
|
|
This guide covers deploying SmoothSchedule to a production server.
|
|
|
|
## Table of Contents
|
|
|
|
1. [Prerequisites](#prerequisites)
|
|
2. [Quick Reference](#quick-reference)
|
|
3. [Initial Server Setup](#initial-server-setup-first-time-only)
|
|
4. [Regular Deployments](#regular-deployments)
|
|
5. [Activepieces Updates](#activepieces-updates)
|
|
6. [Troubleshooting](#troubleshooting)
|
|
7. [Maintenance](#maintenance)
|
|
|
|
## Prerequisites
|
|
|
|
### Server Requirements
|
|
- Ubuntu 20.04+ or Debian 11+
|
|
- 4GB RAM minimum (2GB works but cannot build Activepieces image)
|
|
- 40GB disk space
|
|
- Docker and Docker Compose v2 installed
|
|
- Domain with wildcard DNS configured
|
|
|
|
### Local Requirements (for deployment)
|
|
- Git access to the repository
|
|
- SSH access to the production server
|
|
- Docker (for building Activepieces image)
|
|
|
|
### Required Accounts/Services
|
|
- DigitalOcean Spaces (for static/media files)
|
|
- Stripe (for payments)
|
|
- Twilio (for SMS/phone features)
|
|
- OpenAI API (optional, for Activepieces AI copilot)
|
|
|
|
## Quick Reference
|
|
|
|
```bash
|
|
# Regular deployment (after initial setup)
|
|
./deploy.sh
|
|
|
|
# Deploy with Activepieces image rebuild
|
|
./deploy.sh --deploy-ap
|
|
|
|
# Deploy specific services only
|
|
./deploy.sh django nginx
|
|
|
|
# Skip migrations (config changes only)
|
|
./deploy.sh --no-migrate
|
|
```
|
|
|
|
## Initial Server Setup (First Time Only)
|
|
|
|
### 1. Server Preparation
|
|
|
|
```bash
|
|
# SSH into production server
|
|
ssh your-user@your-server
|
|
|
|
# Install Docker (if not already installed)
|
|
curl -fsSL https://get.docker.com -o get-docker.sh
|
|
sudo sh get-docker.sh
|
|
sudo usermod -aG docker $USER
|
|
|
|
# Logout and login again for group changes
|
|
exit
|
|
ssh your-user@your-server
|
|
```
|
|
|
|
### 2. Clone Repository
|
|
|
|
```bash
|
|
git clone https://your-repo-url ~/smoothschedule
|
|
cd ~/smoothschedule/smoothschedule
|
|
```
|
|
|
|
### 3. Create Environment Files
|
|
|
|
Copy the template files and fill in your values:
|
|
|
|
```bash
|
|
mkdir -p .envs/.production
|
|
cp .envs.example/.django .envs/.production/.django
|
|
cp .envs.example/.postgres .envs/.production/.postgres
|
|
cp .envs.example/.activepieces .envs/.production/.activepieces
|
|
```
|
|
|
|
Edit each file with your production values:
|
|
|
|
```bash
|
|
nano .envs/.production/.django
|
|
nano .envs/.production/.postgres
|
|
nano .envs/.production/.activepieces
|
|
```
|
|
|
|
**Key values to configure:**
|
|
|
|
| File | Variable | Description |
|
|
|------|----------|-------------|
|
|
| `.django` | `DJANGO_SECRET_KEY` | Generate: `openssl rand -hex 32` |
|
|
| `.django` | `DJANGO_ALLOWED_HOSTS` | `.yourdomain.com` |
|
|
| `.django` | `STRIPE_*` | Your Stripe keys (live keys for production) |
|
|
| `.django` | `TWILIO_*` | Your Twilio credentials |
|
|
| `.django` | `AWS_*` | DigitalOcean Spaces credentials |
|
|
| `.postgres` | `POSTGRES_USER` | Generate random username |
|
|
| `.postgres` | `POSTGRES_PASSWORD` | Generate: `openssl rand -hex 32` |
|
|
| `.activepieces` | `AP_JWT_SECRET` | Generate: `openssl rand -hex 32` |
|
|
| `.activepieces` | `AP_ENCRYPTION_KEY` | Generate: `openssl rand -hex 16` |
|
|
| `.activepieces` | `AP_POSTGRES_USERNAME` | Generate random username |
|
|
| `.activepieces` | `AP_POSTGRES_PASSWORD` | Generate: `openssl rand -hex 32` |
|
|
|
|
**Important:** `AP_JWT_SECRET` must be copied to `.django` as well!
|
|
|
|
### 4. DNS Configuration
|
|
|
|
Configure these DNS records:
|
|
|
|
```
|
|
Type Name Value TTL
|
|
A yourdomain.com YOUR_SERVER_IP 300
|
|
A *.yourdomain.com YOUR_SERVER_IP 300
|
|
CNAME www yourdomain.com 300
|
|
```
|
|
|
|
### 5. Build Activepieces Image (on your local machine)
|
|
|
|
The production server typically cannot build this image (requires 4GB+ RAM):
|
|
|
|
```bash
|
|
# On your LOCAL machine, not the server
|
|
cd ~/smoothschedule
|
|
./scripts/build-activepieces.sh deploy
|
|
```
|
|
|
|
Or manually:
|
|
|
|
```bash
|
|
cd activepieces-fork
|
|
docker build -t smoothschedule_production_activepieces .
|
|
docker save smoothschedule_production_activepieces | gzip > /tmp/ap.tar.gz
|
|
scp /tmp/ap.tar.gz your-user@your-server:/tmp/
|
|
ssh your-user@your-server 'gunzip -c /tmp/ap.tar.gz | docker load'
|
|
```
|
|
|
|
### 6. Run Initialization Script
|
|
|
|
```bash
|
|
# On the server
|
|
cd ~/smoothschedule/smoothschedule
|
|
chmod +x scripts/init-production.sh
|
|
./scripts/init-production.sh
|
|
```
|
|
|
|
This script will:
|
|
1. Verify environment files
|
|
2. Generate any missing security keys
|
|
3. Start PostgreSQL and Redis
|
|
4. Create the Activepieces database
|
|
5. Start all services
|
|
6. Run Django migrations
|
|
7. Guide you through Activepieces platform setup
|
|
|
|
### 7. Complete Activepieces Platform Setup
|
|
|
|
After the init script completes:
|
|
|
|
1. Visit `https://automations.yourdomain.com`
|
|
2. Create an admin account (this creates the platform)
|
|
3. Get the platform ID:
|
|
```bash
|
|
docker compose -f docker-compose.production.yml exec postgres \
|
|
psql -U <ap_db_user> -d activepieces -c "SELECT id FROM platform"
|
|
```
|
|
4. Update `AP_PLATFORM_ID` in both:
|
|
- `.envs/.production/.activepieces`
|
|
- `.envs/.production/.django`
|
|
5. Restart services:
|
|
```bash
|
|
docker compose -f docker-compose.production.yml restart
|
|
```
|
|
|
|
### 8. Create First Tenant
|
|
|
|
```bash
|
|
docker compose -f docker-compose.production.yml exec django python manage.py shell
|
|
```
|
|
|
|
```python
|
|
from smoothschedule.identity.core.models import Tenant, Domain
|
|
|
|
# Create tenant
|
|
tenant = Tenant.objects.create(
|
|
name="Demo Business",
|
|
subdomain="demo",
|
|
schema_name="demo"
|
|
)
|
|
|
|
# Create domain
|
|
Domain.objects.create(
|
|
tenant=tenant,
|
|
domain="demo.yourdomain.com",
|
|
is_primary=True
|
|
)
|
|
```
|
|
|
|
### 9. Provision Activepieces Connection
|
|
|
|
```bash
|
|
docker compose -f docker-compose.production.yml exec django \
|
|
python manage.py provision_ap_connections --tenant demo
|
|
```
|
|
|
|
### 10. Verify Deployment
|
|
|
|
```bash
|
|
# Check all containers are running
|
|
docker compose -f docker-compose.production.yml ps
|
|
|
|
# Test endpoints
|
|
curl https://yourdomain.com/api/
|
|
curl https://platform.yourdomain.com/
|
|
curl https://automations.yourdomain.com/api/v1/health
|
|
```
|
|
|
|
## Regular Deployments
|
|
|
|
After initial setup, deployments are simple:
|
|
|
|
```bash
|
|
# From your local machine
|
|
cd ~/smoothschedule
|
|
|
|
# Commit and push your changes
|
|
git add .
|
|
git commit -m "Your changes"
|
|
git push
|
|
|
|
# Deploy
|
|
./deploy.sh
|
|
```
|
|
|
|
### Deployment Options
|
|
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `./deploy.sh` | Full deployment with migrations |
|
|
| `./deploy.sh --no-migrate` | Deploy without running migrations |
|
|
| `./deploy.sh --deploy-ap` | Rebuild and deploy Activepieces image |
|
|
| `./deploy.sh django` | Rebuild only Django container |
|
|
| `./deploy.sh nginx traefik` | Rebuild specific services |
|
|
|
|
### What the Deploy Script Does
|
|
|
|
1. Checks for uncommitted changes
|
|
2. Verifies changes are pushed to remote
|
|
3. (If `--deploy-ap`) Builds and transfers Activepieces image
|
|
4. SSHs to server and pulls latest code
|
|
5. Backs up and restores `.envs` directory
|
|
6. Builds Docker images
|
|
7. Starts containers
|
|
8. Sets up Activepieces database (if needed)
|
|
9. Runs Django migrations (unless `--no-migrate`)
|
|
10. Seeds platform plugins for all tenants
|
|
|
|
## Activepieces Updates
|
|
|
|
When you modify custom pieces (in `activepieces-fork/`):
|
|
|
|
1. Make your changes to piece code
|
|
2. Commit and push
|
|
3. Deploy with the image flag:
|
|
```bash
|
|
./deploy.sh --deploy-ap
|
|
```
|
|
|
|
The Activepieces container will:
|
|
1. Start with the new image
|
|
2. Run `publish-pieces.sh` to register custom pieces
|
|
3. Insert piece metadata into the database
|
|
|
|
### Custom Pieces
|
|
|
|
Custom pieces are located in:
|
|
- `activepieces-fork/packages/pieces/community/smoothschedule/` - Main SmoothSchedule piece
|
|
- `activepieces-fork/packages/pieces/community/python-code/` - Python code execution
|
|
- `activepieces-fork/packages/pieces/community/ruby-code/` - Ruby code execution
|
|
|
|
Piece metadata is registered via:
|
|
- `activepieces-fork/custom-pieces-metadata.sql` - Database registration
|
|
- `activepieces-fork/publish-pieces.sh` - Container startup script
|
|
|
|
## Troubleshooting
|
|
|
|
### View Logs
|
|
|
|
```bash
|
|
# All services
|
|
docker compose -f docker-compose.production.yml logs -f
|
|
|
|
# Specific service
|
|
docker compose -f docker-compose.production.yml logs -f django
|
|
docker compose -f docker-compose.production.yml logs -f activepieces
|
|
docker compose -f docker-compose.production.yml logs -f traefik
|
|
```
|
|
|
|
### Restart Services
|
|
|
|
```bash
|
|
# All services
|
|
docker compose -f docker-compose.production.yml restart
|
|
|
|
# Specific service
|
|
docker compose -f docker-compose.production.yml restart django
|
|
docker compose -f docker-compose.production.yml restart activepieces
|
|
```
|
|
|
|
### Django Shell
|
|
|
|
```bash
|
|
docker compose -f docker-compose.production.yml exec django python manage.py shell
|
|
```
|
|
|
|
### Database Access
|
|
|
|
```bash
|
|
# SmoothSchedule database
|
|
docker compose -f docker-compose.production.yml exec postgres \
|
|
psql -U <postgres_user> -d smoothschedule
|
|
|
|
# Activepieces database
|
|
docker compose -f docker-compose.production.yml exec postgres \
|
|
psql -U <ap_user> -d activepieces
|
|
```
|
|
|
|
### Common Issues
|
|
|
|
**1. Activepieces pieces not showing up**
|
|
```bash
|
|
# Check if platform exists
|
|
docker compose -f docker-compose.production.yml exec postgres \
|
|
psql -U <ap_user> -d activepieces -c "SELECT id FROM platform"
|
|
|
|
# Restart to re-run piece registration
|
|
docker compose -f docker-compose.production.yml restart activepieces
|
|
|
|
# Check logs for errors
|
|
docker compose -f docker-compose.production.yml logs activepieces | grep -i error
|
|
```
|
|
|
|
**2. 502 Bad Gateway**
|
|
- Service is still starting, wait a moment
|
|
- Check container health: `docker compose ps`
|
|
- Check logs for errors
|
|
|
|
**3. Database connection errors**
|
|
- Verify credentials in `.envs/.production/`
|
|
- Ensure PostgreSQL is running: `docker compose ps postgres`
|
|
|
|
**4. Activepieces embedding not working**
|
|
- Verify `AP_JWT_SECRET` matches in both `.django` and `.activepieces`
|
|
- Verify `AP_PLATFORM_ID` is set correctly in both files
|
|
- Check `AP_EMBEDDING_ENABLED=true` in `.activepieces`
|
|
|
|
**5. SSL certificate issues**
|
|
```bash
|
|
# Check Traefik logs
|
|
docker compose -f docker-compose.production.yml logs traefik
|
|
|
|
# Verify DNS is pointing to server
|
|
dig yourdomain.com +short
|
|
|
|
# Ensure ports 80 and 443 are open
|
|
sudo ufw allow 80
|
|
sudo ufw allow 443
|
|
```
|
|
|
|
## Maintenance
|
|
|
|
### Backups
|
|
|
|
```bash
|
|
# Database backup
|
|
docker compose -f docker-compose.production.yml exec postgres backup
|
|
|
|
# List backups
|
|
docker compose -f docker-compose.production.yml exec postgres backups
|
|
|
|
# Restore from backup
|
|
docker compose -f docker-compose.production.yml exec postgres restore backup_filename.sql.gz
|
|
```
|
|
|
|
### Monitoring
|
|
|
|
- **Flower Dashboard**: `https://yourdomain.com:5555` - Celery task monitoring
|
|
- **Container Status**: `docker compose ps`
|
|
- **Resource Usage**: `docker stats`
|
|
|
|
### Security Checklist
|
|
|
|
- [x] SSL/HTTPS enabled via Let's Encrypt (automatic with Traefik)
|
|
- [x] All secret keys are unique random values
|
|
- [x] Database passwords are strong
|
|
- [x] Flower dashboard is password protected
|
|
- [ ] Firewall configured (UFW)
|
|
- [ ] SSH key-based authentication only
|
|
- [ ] Regular backups configured
|
|
- [ ] Monitoring/alerting set up
|
|
|
|
## File Structure
|
|
|
|
```
|
|
smoothschedule/
|
|
├── deploy.sh # Main deployment script
|
|
├── DEPLOYMENT.md # This file
|
|
├── scripts/
|
|
│ └── build-activepieces.sh # Activepieces image builder
|
|
├── smoothschedule/
|
|
│ ├── docker-compose.production.yml
|
|
│ ├── scripts/
|
|
│ │ └── init-production.sh # One-time initialization
|
|
│ ├── .envs/
|
|
│ │ └── .production/ # Production secrets (NOT in git)
|
|
│ │ ├── .django
|
|
│ │ ├── .postgres
|
|
│ │ └── .activepieces
|
|
│ └── .envs.example/ # Template files (in git)
|
|
│ ├── .django
|
|
│ ├── .postgres
|
|
│ └── .activepieces
|
|
└── activepieces-fork/
|
|
├── Dockerfile
|
|
├── custom-pieces-metadata.sql
|
|
├── publish-pieces.sh
|
|
└── packages/pieces/community/
|
|
├── smoothschedule/ # Main custom piece
|
|
├── python-code/
|
|
└── ruby-code/
|
|
```
|