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:
136
deploy.sh
136
deploy.sh
@@ -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'"
|
||||
|
||||
Reference in New Issue
Block a user