Improve deployment process and add login redirect logic

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>
This commit is contained in:
poduck
2025-12-20 23:13:56 -05:00
parent 2a33e4cf57
commit f8d8419622
38 changed files with 2471 additions and 396 deletions

136
deploy.sh
View File

@@ -1,15 +1,33 @@
#!/bin/bash
# ==============================================================================
# SmoothSchedule Production Deployment Script
# Usage: ./deploy.sh [server_user@server_host] [services...]
# Example: ./deploy.sh poduck@smoothschedule.com # Build all
# Example: ./deploy.sh poduck@smoothschedule.com traefik # Build only traefik
# Example: ./deploy.sh poduck@smoothschedule.com django nginx # Build django and nginx
# ==============================================================================
#
# Available services: django, traefik, nginx, postgres, celeryworker, celerybeat, flower, awscli
# Use --no-migrate to skip migrations (useful for config-only changes like traefik)
# Usage: ./deploy.sh [server] [options] [services...]
#
# This script deploys from git repository, not local files.
# Changes must be committed and pushed before deploying.
# Examples:
# ./deploy.sh # Deploy all services
# ./deploy.sh --no-migrate # Deploy without migrations
# ./deploy.sh django nginx # Deploy specific services
# ./deploy.sh --deploy-ap # Build & deploy Activepieces image
# ./deploy.sh poduck@server.com # Deploy to custom server
#
# Options:
# --no-migrate Skip database migrations
# --deploy-ap Build Activepieces image locally and transfer to server
#
# Available services:
# django, traefik, nginx, postgres, celeryworker, celerybeat, flower, awscli, activepieces
#
# IMPORTANT: Activepieces Image
# -----------------------------
# The production server cannot build the Activepieces image (requires 4GB+ RAM).
# Use --deploy-ap to build locally and transfer, or manually:
# ./scripts/build-activepieces.sh deploy
#
# First-time setup:
# Run ./smoothschedule/scripts/init-production.sh on the server
# ==============================================================================
set -e
@@ -23,12 +41,23 @@ NC='\033[0m' # No Color
SERVER=""
SERVICES=""
SKIP_MIGRATE=false
DEPLOY_AP=false
for arg in "$@"; do
if [[ "$arg" == "--no-migrate" ]]; then
SKIP_MIGRATE=true
elif [[ -z "$SERVER" ]]; then
elif [[ "$arg" == "--deploy-ap" ]]; then
DEPLOY_AP=true
elif [[ "$arg" == *"@"* ]]; then
# Looks like user@host
SERVER="$arg"
elif [[ -z "$SERVER" && ! "$arg" =~ ^- ]]; then
# First non-flag argument could be server or service
if [[ "$arg" =~ ^(django|traefik|nginx|postgres|celeryworker|celerybeat|flower|awscli|activepieces|redis|verdaccio)$ ]]; then
SERVICES="$SERVICES $arg"
else
SERVER="$arg"
fi
else
SERVICES="$SERVICES $arg"
fi
@@ -38,6 +67,7 @@ SERVER=${SERVER:-"poduck@smoothschedule.com"}
SERVICES=$(echo "$SERVICES" | xargs) # Trim whitespace
REPO_URL="https://git.talova.net/poduck/smoothschedule.git"
REMOTE_DIR="/home/poduck/smoothschedule"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo -e "${GREEN}==================================="
echo "SmoothSchedule Deployment"
@@ -51,6 +81,9 @@ fi
if [[ "$SKIP_MIGRATE" == "true" ]]; then
echo "Migrations: SKIPPED"
fi
if [[ "$DEPLOY_AP" == "true" ]]; then
echo "Activepieces: BUILDING AND DEPLOYING"
fi
echo ""
# Function to print status
@@ -94,8 +127,36 @@ fi
print_status "All changes committed and pushed!"
# Step 2: Deploy on server
print_status "Step 2: Deploying on server..."
# Step 2: Build and deploy Activepieces image (if requested)
if [[ "$DEPLOY_AP" == "true" ]]; then
print_status "Step 2: Building and deploying Activepieces image..."
# Check if the build script exists
if [[ -f "$SCRIPT_DIR/scripts/build-activepieces.sh" ]]; then
"$SCRIPT_DIR/scripts/build-activepieces.sh" deploy "$SERVER"
else
print_warning "Build script not found, building manually..."
# Build the image
print_status "Building Activepieces Docker image locally..."
cd "$SCRIPT_DIR/activepieces-fork"
docker build -t smoothschedule_production_activepieces .
# Save and transfer
print_status "Transferring image to server..."
docker save smoothschedule_production_activepieces | gzip > /tmp/ap-image.tar.gz
scp /tmp/ap-image.tar.gz "$SERVER:/tmp/"
ssh "$SERVER" "gunzip -c /tmp/ap-image.tar.gz | docker load && rm /tmp/ap-image.tar.gz"
rm /tmp/ap-image.tar.gz
cd "$SCRIPT_DIR"
fi
print_status "Activepieces image deployed!"
fi
# Step 3: Deploy on server
print_status "Step 3: Deploying on server..."
ssh "$SERVER" "bash -s" << ENDSSH
set -e
@@ -174,6 +235,58 @@ docker compose -f docker-compose.production.yml up -d
echo ">>> Waiting for containers to start..."
sleep 5
# Setup Activepieces database (if not exists)
echo ">>> Setting up Activepieces database..."
AP_DB_USER=\$(grep AP_POSTGRES_USERNAME .envs/.production/.activepieces | cut -d= -f2)
AP_DB_PASS=\$(grep AP_POSTGRES_PASSWORD .envs/.production/.activepieces | cut -d= -f2)
AP_DB_NAME=\$(grep AP_POSTGRES_DATABASE .envs/.production/.activepieces | cut -d= -f2)
if [ -n "\$AP_DB_USER" ] && [ -n "\$AP_DB_PASS" ] && [ -n "\$AP_DB_NAME" ]; then
# Check if user exists, create if not
docker compose -f docker-compose.production.yml exec -T postgres psql -U \${POSTGRES_USER:-postgres} -d postgres -tc "SELECT 1 FROM pg_roles WHERE rolname='\$AP_DB_USER'" | grep -q 1 || {
echo " Creating Activepieces database user..."
docker compose -f docker-compose.production.yml exec -T postgres psql -U \${POSTGRES_USER:-postgres} -d postgres -c "CREATE USER \"\$AP_DB_USER\" WITH PASSWORD '\$AP_DB_PASS';"
}
# Check if database exists, create if not
docker compose -f docker-compose.production.yml exec -T postgres psql -U \${POSTGRES_USER:-postgres} -d postgres -tc "SELECT 1 FROM pg_database WHERE datname='\$AP_DB_NAME'" | grep -q 1 || {
echo " Creating Activepieces database..."
docker compose -f docker-compose.production.yml exec -T postgres psql -U \${POSTGRES_USER:-postgres} -d postgres -c "CREATE DATABASE \$AP_DB_NAME OWNER \"\$AP_DB_USER\";"
}
echo " Activepieces database ready."
else
echo " Warning: Could not read Activepieces database config from .envs/.production/.activepieces"
fi
# Wait for Activepieces to be ready
echo ">>> Waiting for Activepieces to be ready..."
for i in {1..30}; do
if curl -s http://localhost:80/api/v1/health 2>/dev/null | grep -q "ok"; then
echo " Activepieces is ready."
break
fi
if [ \$i -eq 30 ]; then
echo " Warning: Activepieces health check timed out. It may still be starting."
fi
sleep 2
done
# Check if Activepieces platform exists
echo ">>> Checking Activepieces platform..."
AP_PLATFORM_ID=\$(grep AP_PLATFORM_ID .envs/.production/.activepieces | cut -d= -f2)
if [ -z "\$AP_PLATFORM_ID" ] || [ "\$AP_PLATFORM_ID" = "" ]; then
echo " WARNING: No AP_PLATFORM_ID configured in .envs/.production/.activepieces"
echo " To initialize Activepieces for the first time:"
echo " 1. Visit https://automations.smoothschedule.com"
echo " 2. Create an admin user (this creates the platform)"
echo " 3. Get the platform ID from the response or database"
echo " 4. Update AP_PLATFORM_ID in .envs/.production/.activepieces"
echo " 5. Also update AP_PLATFORM_ID in .envs/.production/.django"
echo " 6. Restart Activepieces: docker compose -f docker-compose.production.yml restart activepieces"
else
echo " Activepieces platform configured: \$AP_PLATFORM_ID"
fi
# Run migrations unless skipped
if [[ "$SKIP_MIGRATE" != "true" ]]; then
echo ">>> Running database migrations..."
@@ -210,6 +323,7 @@ echo "Your application should now be running at:"
echo " - https://smoothschedule.com"
echo " - https://platform.smoothschedule.com"
echo " - https://*.smoothschedule.com (tenant subdomains)"
echo " - https://automations.smoothschedule.com (Activepieces)"
echo ""
echo "To view logs:"
echo " ssh $SERVER 'cd ~/smoothschedule/smoothschedule && docker compose -f docker-compose.production.yml logs -f'"