#!/bin/bash # Monaco USA Portal - Production Setup Script # This script prepares the deployment environment by: # 1. Generating missing secrets in .env # 2. Generating kong.yml from template with actual API keys # 3. Validating the configuration set -e echo "========================================" echo "Monaco USA Portal - Production Setup" echo "========================================" echo "" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Function to generate random string (alphanumeric only to avoid sed issues) generate_secret() { local length=${1:-32} openssl rand -hex $length | head -c $length } # Function to generate JWT token generate_jwt() { local role=$1 local secret=$2 # JWT Header (base64url encoded) local header='{"alg":"HS256","typ":"JWT"}' local header_b64=$(echo -n "$header" | base64 | tr '+/' '-_' | tr -d '=' | tr -d '\n') # JWT Payload - 100 years expiry local exp=$(($(date +%s) + 3153600000)) local payload="{\"role\":\"$role\",\"iss\":\"supabase\",\"iat\":$(date +%s),\"exp\":$exp}" local payload_b64=$(echo -n "$payload" | base64 | tr '+/' '-_' | tr -d '=' | tr -d '\n') # Create signature local signature=$(echo -n "${header_b64}.${payload_b64}" | openssl dgst -sha256 -hmac "$secret" -binary | base64 | tr '+/' '-_' | tr -d '=' | tr -d '\n') echo "${header_b64}.${payload_b64}.${signature}" } # Function to update a variable in .env file using awk (more robust than sed) update_env_var() { local var_name=$1 local var_value=$2 local env_file=".env" # Create temp file local tmp_file=$(mktemp) # Use awk to replace the line awk -v name="$var_name" -v value="$var_value" ' BEGIN { FS="="; OFS="=" } $1 == name { print name, value; next } { print } ' "$env_file" > "$tmp_file" # Move temp file to .env mv "$tmp_file" "$env_file" } # Check if .env exists if [ ! -f .env ]; then if [ -f .env.example ]; then echo -e "${YELLOW}No .env file found. Creating from .env.example...${NC}" cp .env.example .env echo -e "${GREEN}Created .env from template.${NC}" else echo -e "${RED}Error: No .env or .env.example file found.${NC}" echo "Please create a .env file with your configuration." exit 1 fi fi # Load environment (handle errors gracefully) set +e set -a source .env 2>/dev/null set +a set -e echo "" echo "Checking and generating secrets..." echo "" # Track if we made changes CHANGES_MADE=false # Generate POSTGRES_PASSWORD if not set or is placeholder if [ -z "$POSTGRES_PASSWORD" ] || [[ "$POSTGRES_PASSWORD" == *"CHANGE_ME"* ]] || [[ "$POSTGRES_PASSWORD" == *"change-this"* ]]; then NEW_POSTGRES_PASSWORD=$(generate_secret 32) update_env_var "POSTGRES_PASSWORD" "$NEW_POSTGRES_PASSWORD" POSTGRES_PASSWORD=$NEW_POSTGRES_PASSWORD echo -e "${GREEN}[Generated]${NC} POSTGRES_PASSWORD" CHANGES_MADE=true else echo -e "[OK] POSTGRES_PASSWORD is set" fi # Generate JWT_SECRET if not set or is placeholder if [ -z "$JWT_SECRET" ] || [[ "$JWT_SECRET" == *"CHANGE_ME"* ]] || [[ "$JWT_SECRET" == *"generate"* ]]; then NEW_JWT_SECRET=$(generate_secret 32) update_env_var "JWT_SECRET" "$NEW_JWT_SECRET" JWT_SECRET=$NEW_JWT_SECRET echo -e "${GREEN}[Generated]${NC} JWT_SECRET" CHANGES_MADE=true else echo -e "[OK] JWT_SECRET is set" fi # Generate SECRET_KEY_BASE if not set or is placeholder if [ -z "$SECRET_KEY_BASE" ] || [[ "$SECRET_KEY_BASE" == *"CHANGE_ME"* ]] || [[ "$SECRET_KEY_BASE" == *"generate"* ]]; then NEW_SECRET_KEY_BASE=$(generate_secret 64) update_env_var "SECRET_KEY_BASE" "$NEW_SECRET_KEY_BASE" SECRET_KEY_BASE=$NEW_SECRET_KEY_BASE echo -e "${GREEN}[Generated]${NC} SECRET_KEY_BASE" CHANGES_MADE=true else echo -e "[OK] SECRET_KEY_BASE is set" fi # Generate ANON_KEY if not set or is placeholder if [ -z "$ANON_KEY" ] || [[ "$ANON_KEY" == *"CHANGE_ME"* ]] || [[ "$ANON_KEY" == *"your-"* ]]; then NEW_ANON_KEY=$(generate_jwt "anon" "$JWT_SECRET") update_env_var "ANON_KEY" "$NEW_ANON_KEY" ANON_KEY=$NEW_ANON_KEY echo -e "${GREEN}[Generated]${NC} ANON_KEY (JWT with role=anon)" CHANGES_MADE=true else echo -e "[OK] ANON_KEY is set" fi # Generate SERVICE_ROLE_KEY if not set or is placeholder if [ -z "$SERVICE_ROLE_KEY" ] || [[ "$SERVICE_ROLE_KEY" == *"CHANGE_ME"* ]] || [[ "$SERVICE_ROLE_KEY" == *"your-"* ]]; then NEW_SERVICE_ROLE_KEY=$(generate_jwt "service_role" "$JWT_SECRET") update_env_var "SERVICE_ROLE_KEY" "$NEW_SERVICE_ROLE_KEY" SERVICE_ROLE_KEY=$NEW_SERVICE_ROLE_KEY echo -e "${GREEN}[Generated]${NC} SERVICE_ROLE_KEY (JWT with role=service_role)" CHANGES_MADE=true else echo -e "[OK] SERVICE_ROLE_KEY is set" fi # Also update PUBLIC_SUPABASE_ANON_KEY and SUPABASE_SERVICE_ROLE_KEY if they exist if grep -q "^PUBLIC_SUPABASE_ANON_KEY=" .env; then update_env_var "PUBLIC_SUPABASE_ANON_KEY" "\${ANON_KEY}" fi if grep -q "^SUPABASE_SERVICE_ROLE_KEY=" .env; then update_env_var "SUPABASE_SERVICE_ROLE_KEY" "\${SERVICE_ROLE_KEY}" fi echo "" # Reload environment after changes set +e set -a source .env 2>/dev/null set +a set -e # Validate required variables echo "Validating required variables..." REQUIRED_VARS=( "PORTAL_DOMAIN" "API_DOMAIN" "POSTGRES_USER" "POSTGRES_PASSWORD" "POSTGRES_DB" "JWT_SECRET" "ANON_KEY" "SERVICE_ROLE_KEY" "SECRET_KEY_BASE" ) MISSING_VARS=() for var in "${REQUIRED_VARS[@]}"; do if [ -z "${!var}" ]; then MISSING_VARS+=("$var") fi done if [ ${#MISSING_VARS[@]} -ne 0 ]; then echo "" echo -e "${RED}Error: The following required variables are not set in .env:${NC}" for var in "${MISSING_VARS[@]}"; do echo " - $var" done echo "" echo "Please edit .env and set these values, then run this script again." exit 1 fi echo -e "${GREEN}All required variables are set.${NC}" echo "" # Check for optional but recommended variables OPTIONAL_VARS=( "SMTP_HOST" "SMTP_USER" ) echo "Checking optional variables..." for var in "${OPTIONAL_VARS[@]}"; do if [ -z "${!var}" ]; then echo -e "${YELLOW}[Warning]${NC} $var is not set (optional)" else echo -e "[OK] $var is set" fi done echo "" # Generate kong.yml from template echo "Generating kong.yml from template..." if [ ! -f kong.yml.template ]; then echo -e "${RED}Error: kong.yml.template not found.${NC}" exit 1 fi # Use awk to replace placeholders (more robust than sed for complex strings) awk -v anon_key="$ANON_KEY" -v service_key="$SERVICE_ROLE_KEY" ' { gsub(/__ANON_KEY__/, anon_key) gsub(/__SERVICE_ROLE_KEY__/, service_key) print } ' kong.yml.template > kong.yml echo -e "${GREEN}Generated kong.yml with API keys.${NC}" echo "" # Summary echo "========================================" echo "Setup Complete!" echo "========================================" echo "" if [ "$CHANGES_MADE" = true ]; then echo -e "${YELLOW}IMPORTANT: New secrets were generated and saved to .env${NC}" echo "Make sure to backup your .env file securely!" echo "" fi echo "Next steps:" echo " 1. Review .env and configure any remaining settings" echo " 2. Start the services: docker compose up -d" echo " 3. Wait for all containers to be healthy: docker compose ps" echo " 4. Access the portal at: https://${PORTAL_DOMAIN:-portal.monacousa.org}" echo " 5. Create your admin account on first visit" echo "" echo "Useful commands:" echo " docker compose ps - Check container status" echo " docker compose logs -f - Follow all logs" echo " docker compose logs db - Check database logs" echo " docker compose down - Stop all services" echo ""