Auto-generate backend/.env and frontend/.env.local from .env.deploy
The deploy script now generates both env files automatically — no more manual file creation on the server. All secrets and VITE_ vars are centralised in .env.deploy (gitignored). Updated .env.deploy.example with all required variables and inline documentation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ff1c809249
commit
da63629720
2 changed files with 137 additions and 119 deletions
|
|
@ -1,47 +1,91 @@
|
|||
# ModComms Deployment Configuration
|
||||
# Copy this file to .env.deploy and update with your server values
|
||||
# Copy this file to .env.deploy and fill in your values.
|
||||
# .env.deploy is gitignored — safe to store secrets here.
|
||||
#
|
||||
# For running prod and dev on the same server, clone the repo twice:
|
||||
# /opt/modcomms-prod/ - production (main branch)
|
||||
# /opt/modcomms-dev/ - development (develop branch)
|
||||
# Then configure each .env.deploy with different values below.
|
||||
# The deploy script auto-generates backend/.env and frontend/.env.local
|
||||
# from the variables below. You do NOT need to create those files manually.
|
||||
|
||||
# Docker project name (creates unique container names)
|
||||
# -----------------------------------------------------------------------
|
||||
# Docker / Compose
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
# Unique name per instance (creates unique container names)
|
||||
# Examples: modcomms-prod, modcomms-dev
|
||||
COMPOSE_PROJECT_NAME=modcomms-prod
|
||||
|
||||
# Backend port (must be unique per instance)
|
||||
# Examples: 8000 for prod, 8001 for dev
|
||||
# Backend port (must be unique per instance on this host)
|
||||
BACKEND_PORT=8000
|
||||
|
||||
# PostgreSQL port (must be unique per instance)
|
||||
# Examples: 5432 for prod, 5433 for dev
|
||||
# PostgreSQL port (must be unique per instance on this host)
|
||||
POSTGRES_PORT=5432
|
||||
|
||||
# PostgreSQL credentials (change in production!)
|
||||
# PostgreSQL credentials
|
||||
POSTGRES_USER=modcomms
|
||||
POSTGRES_PASSWORD=change_this_in_production
|
||||
POSTGRES_DB=modcomms
|
||||
|
||||
# Frontend deployment directory (Apache document root)
|
||||
# Production: /var/vhosts/baic.oliver.solutions/htdocs/modcomms
|
||||
# Dev/staging: /var/www/html/modcomms
|
||||
# -----------------------------------------------------------------------
|
||||
# Apache / Frontend
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
# Directory where the built frontend is served from
|
||||
FRONTEND_DEPLOY_DIR=/var/vhosts/baic.oliver.solutions/htdocs/modcomms
|
||||
|
||||
# CORS origins (should match your frontend domain)
|
||||
# Multiple origins can be comma-separated
|
||||
# Subpath the app is served under (trailing slash required).
|
||||
# Use / if served from the domain root.
|
||||
VITE_BASE_PATH=/modcomms/
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Backend URLs
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
# HTTP base URL of the backend (no trailing slash)
|
||||
VITE_BACKEND_URL=https://baic.oliver.solutions/back
|
||||
|
||||
# WebSocket URL for the analysis endpoint
|
||||
VITE_BACKEND_WS_URL=wss://baic.oliver.solutions/back/ws/analyze
|
||||
|
||||
# CORS origins allowed by the backend (must match VITE_BACKEND_URL origin)
|
||||
CORS_ORIGINS=https://baic.oliver.solutions
|
||||
|
||||
# NOTE: Frontend environment variables (VITE_*) are NOT configured here.
|
||||
# Create frontend/.env.local manually with:
|
||||
# VITE_BASE_PATH=/modcomms/
|
||||
# VITE_BACKEND_URL=https://baic.oliver.solutions/back
|
||||
# VITE_BACKEND_WS_URL=wss://baic.oliver.solutions/back/ws/analyze
|
||||
# VITE_AZURE_CLIENT_ID=your_azure_client_id
|
||||
# VITE_AZURE_TENANT_ID=your_azure_tenant_id
|
||||
# VITE_AZURE_REDIRECT_URI=https://baic.oliver.solutions/modcomms/
|
||||
# -----------------------------------------------------------------------
|
||||
# Azure AD
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
AZURE_TENANT_ID=your_azure_tenant_id
|
||||
AZURE_CLIENT_ID=your_azure_client_id
|
||||
|
||||
# URL Azure redirects back to after login/logout (must match App Registration)
|
||||
VITE_AZURE_REDIRECT_URI=https://baic.oliver.solutions/modcomms/
|
||||
|
||||
# Set to true only for local dev without Azure AD
|
||||
DISABLE_AUTH=false
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# AI / LLM APIs
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
GEMINI_API_KEY=your_gemini_api_key
|
||||
LLAMA_CLOUD_API_KEY=your_llama_cloud_api_key
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Email (Mailgun)
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
MAILGUN_API_URL=https://api.mailgun.net/v3/oliver.solutions/messages
|
||||
MAILGUN_API_KEY=your_mailgun_api_key
|
||||
MAILGUN_FROM=admin@oliver.solutions
|
||||
SUPPORT_EMAIL=BAICsupport@oliver.agency
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Apache proxy config (for reference — configure in Apache vhost, not here)
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
# Apache proxy config (production, port 8000):
|
||||
# ProxyPass /back/ws/analyze ws://localhost:8000/ws/analyze
|
||||
# ProxyPass /back/ http://localhost:8000/
|
||||
# ProxyPassReverse /back/ http://localhost:8000/
|
||||
#
|
||||
# # SPA fallback (serve index.html for all non-file routes under /modcomms/)
|
||||
# <Directory /var/vhosts/baic.oliver.solutions/htdocs/modcomms>
|
||||
# FallbackResource /modcomms/index.html
|
||||
# </Directory>
|
||||
|
|
|
|||
162
deploy.sh
162
deploy.sh
|
|
@ -38,23 +38,43 @@ else
|
|||
fi
|
||||
|
||||
# Validate required variables
|
||||
if [ -z "$FRONTEND_DEPLOY_DIR" ]; then
|
||||
echo "Error: FRONTEND_DEPLOY_DIR not set in .env.deploy"
|
||||
exit 1
|
||||
fi
|
||||
require_var() {
|
||||
local var_name="$1"
|
||||
local value="${!var_name}"
|
||||
if [ -z "$value" ] || [[ "$value" == *"your_"* ]]; then
|
||||
echo ""
|
||||
echo "Error: ${var_name} is not configured in .env.deploy"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ ${var_name}"
|
||||
}
|
||||
|
||||
# Set defaults for docker compose variables
|
||||
echo ""
|
||||
echo "[Config] Validating required variables..."
|
||||
require_var FRONTEND_DEPLOY_DIR
|
||||
require_var GEMINI_API_KEY
|
||||
require_var AZURE_TENANT_ID
|
||||
require_var AZURE_CLIENT_ID
|
||||
require_var VITE_BACKEND_URL
|
||||
require_var VITE_BACKEND_WS_URL
|
||||
require_var VITE_AZURE_REDIRECT_URI
|
||||
|
||||
# Set defaults
|
||||
COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-modcomms}"
|
||||
BACKEND_PORT="${BACKEND_PORT:-8000}"
|
||||
POSTGRES_PORT="${POSTGRES_PORT:-5432}"
|
||||
POSTGRES_USER="${POSTGRES_USER:-modcomms}"
|
||||
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-modcomms_dev}"
|
||||
POSTGRES_DB="${POSTGRES_DB:-modcomms}"
|
||||
VITE_BASE_PATH="${VITE_BASE_PATH:-/}"
|
||||
DISABLE_AUTH="${DISABLE_AUTH:-false}"
|
||||
CORS_ORIGINS="${CORS_ORIGINS:-}"
|
||||
|
||||
echo " Environment: ${COMPOSE_PROJECT_NAME} (backend:${BACKEND_PORT}, postgres:${POSTGRES_PORT})"
|
||||
|
||||
# Create .env file for docker compose (so manual docker compose commands work)
|
||||
# --- Generate .env (docker compose) ---
|
||||
cat > .env << EOF
|
||||
# Auto-generated by deploy.sh - do not edit manually
|
||||
# Auto-generated by deploy.sh — do not edit manually
|
||||
# Edit .env.deploy instead and re-run deploy.sh
|
||||
COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME}
|
||||
BACKEND_PORT=${BACKEND_PORT}
|
||||
|
|
@ -65,47 +85,47 @@ POSTGRES_DB=${POSTGRES_DB}
|
|||
EOF
|
||||
echo " ✓ .env created for docker compose"
|
||||
|
||||
# --- Check backend/.env exists (required for GEMINI_API_KEY) ---
|
||||
if [ ! -f backend/.env ]; then
|
||||
if [ -f backend/.env.example ]; then
|
||||
echo ""
|
||||
echo "Error: backend/.env not found"
|
||||
echo "Create it from the template:"
|
||||
echo " cp backend/.env.example backend/.env"
|
||||
echo " nano backend/.env # Add your GEMINI_API_KEY"
|
||||
exit 1
|
||||
else
|
||||
echo "Error: backend/.env not found and no template available"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo " ✓ backend/.env exists"
|
||||
# --- Generate backend/.env ---
|
||||
echo ""
|
||||
echo "[Config] Generating backend/.env..."
|
||||
cat > backend/.env << EOF
|
||||
# Auto-generated by deploy.sh — do not edit manually
|
||||
# Edit .env.deploy instead and re-run deploy.sh
|
||||
GEMINI_API_KEY=${GEMINI_API_KEY}
|
||||
CORS_ORIGINS=${CORS_ORIGINS}
|
||||
HOST=0.0.0.0
|
||||
PORT=${BACKEND_PORT}
|
||||
AZURE_TENANT_ID=${AZURE_TENANT_ID}
|
||||
AZURE_CLIENT_ID=${AZURE_CLIENT_ID}
|
||||
DISABLE_AUTH=${DISABLE_AUTH}
|
||||
MAILGUN_API_URL=${MAILGUN_API_URL}
|
||||
MAILGUN_API_KEY=${MAILGUN_API_KEY}
|
||||
MAILGUN_FROM=${MAILGUN_FROM}
|
||||
SUPPORT_EMAIL=${SUPPORT_EMAIL}
|
||||
LLAMA_CLOUD_API_KEY=${LLAMA_CLOUD_API_KEY}
|
||||
EOF
|
||||
echo " ✓ backend/.env generated"
|
||||
|
||||
# Validate that critical backend env vars are actually set (not placeholders)
|
||||
check_backend_env() {
|
||||
local var_name="$1"
|
||||
local value
|
||||
value=$(grep -E "^${var_name}=" backend/.env | cut -d= -f2- | tr -d '"' | tr -d "'")
|
||||
if [ -z "$value" ] || [[ "$value" == *"your_"* ]]; then
|
||||
echo ""
|
||||
echo "Error: ${var_name} is not configured in backend/.env"
|
||||
echo " Open backend/.env and set a real value for ${var_name}"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ ${var_name} is set"
|
||||
}
|
||||
# --- Generate frontend/.env.local ---
|
||||
echo ""
|
||||
echo "[Config] Generating frontend/.env.local..."
|
||||
cat > frontend/.env.local << EOF
|
||||
# Auto-generated by deploy.sh — do not edit manually
|
||||
# Edit .env.deploy instead and re-run deploy.sh
|
||||
VITE_BASE_PATH=${VITE_BASE_PATH}
|
||||
VITE_BACKEND_URL=${VITE_BACKEND_URL}
|
||||
VITE_BACKEND_WS_URL=${VITE_BACKEND_WS_URL}
|
||||
VITE_AZURE_CLIENT_ID=${AZURE_CLIENT_ID}
|
||||
VITE_AZURE_TENANT_ID=${AZURE_TENANT_ID}
|
||||
VITE_AZURE_REDIRECT_URI=${VITE_AZURE_REDIRECT_URI}
|
||||
EOF
|
||||
echo " ✓ frontend/.env.local generated"
|
||||
|
||||
check_backend_env GEMINI_API_KEY
|
||||
check_backend_env AZURE_TENANT_ID
|
||||
check_backend_env AZURE_CLIENT_ID
|
||||
# DATABASE_URL is intentionally omitted here — it is injected by docker-compose.yml
|
||||
|
||||
# --- 1. Pull latest code (skip if not a git repo or no remote) ---
|
||||
# --- 1. Pull latest code ---
|
||||
echo ""
|
||||
echo "[1/6] Updating code..."
|
||||
if [ -d .git ]; then
|
||||
if git remote -v | grep -q origin; then
|
||||
# Discard local changes to package-lock.json (regenerated by npm install anyway)
|
||||
git checkout -- frontend/package-lock.json 2>/dev/null || true
|
||||
git pull || echo "Warning: git pull failed, continuing with local code"
|
||||
else
|
||||
|
|
@ -119,70 +139,26 @@ fi
|
|||
echo ""
|
||||
echo "[2/6] Building frontend..."
|
||||
cd frontend
|
||||
|
||||
# Install dependencies (npm install is idempotent)
|
||||
npm install
|
||||
|
||||
# Check that .env.local exists (must be created manually with credentials)
|
||||
if [ ! -f .env.local ]; then
|
||||
echo ""
|
||||
echo "Error: frontend/.env.local not found"
|
||||
echo "Create it manually with your environment-specific values:"
|
||||
echo ""
|
||||
echo " cat > frontend/.env.local << 'EOF'"
|
||||
echo " VITE_BACKEND_WS_URL=wss://your-domain.com/ws/analyze"
|
||||
echo " VITE_BACKEND_URL=https://your-domain.com"
|
||||
echo " VITE_AZURE_CLIENT_ID=your_azure_client_id"
|
||||
echo " VITE_AZURE_TENANT_ID=your_azure_tenant_id"
|
||||
echo " VITE_AZURE_REDIRECT_URI=https://your-domain.com"
|
||||
echo " EOF"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ .env.local exists"
|
||||
|
||||
npm run build
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
# --- 3. Deploy frontend to Apache ---
|
||||
echo ""
|
||||
echo "[3/6] Deploying frontend to ${FRONTEND_DEPLOY_DIR}..."
|
||||
|
||||
# Create directory if it doesn't exist
|
||||
sudo mkdir -p "$FRONTEND_DEPLOY_DIR"
|
||||
|
||||
# Clear existing files (safe deletion with variable check)
|
||||
if [ -n "$FRONTEND_DEPLOY_DIR" ] && [ -d "$FRONTEND_DEPLOY_DIR" ]; then
|
||||
sudo find "$FRONTEND_DEPLOY_DIR" -mindepth 1 -delete 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Copy new build
|
||||
sudo cp -r frontend/dist/* "$FRONTEND_DEPLOY_DIR/"
|
||||
sudo chown -R www-data:www-data "$FRONTEND_DEPLOY_DIR"
|
||||
echo " ✓ Frontend deployed"
|
||||
|
||||
# --- 4. Update backend configuration ---
|
||||
# --- 4. Build containers and run database migrations ---
|
||||
echo ""
|
||||
echo "[4/6] Updating backend configuration..."
|
||||
|
||||
# Update CORS_ORIGINS if specified
|
||||
if [ -n "$CORS_ORIGINS" ]; then
|
||||
if grep -q "^CORS_ORIGINS=" backend/.env; then
|
||||
sed -i "s|^CORS_ORIGINS=.*|CORS_ORIGINS=${CORS_ORIGINS}|" backend/.env
|
||||
else
|
||||
echo "CORS_ORIGINS=${CORS_ORIGINS}" >> backend/.env
|
||||
fi
|
||||
echo " ✓ CORS_ORIGINS updated"
|
||||
fi
|
||||
|
||||
# --- 5. Build containers and run database migrations ---
|
||||
echo ""
|
||||
echo "[5/6] Building containers and running database migrations..."
|
||||
|
||||
# Build image (always rebuild to pick up code changes)
|
||||
echo "[4/6] Building containers..."
|
||||
docker compose build
|
||||
|
||||
# Start PostgreSQL first and wait for it to be healthy
|
||||
echo " Starting PostgreSQL..."
|
||||
docker compose up -d postgres
|
||||
|
||||
|
|
@ -200,8 +176,9 @@ for i in {1..30}; do
|
|||
sleep 1
|
||||
done
|
||||
|
||||
# Run database migrations
|
||||
echo " Running database migrations..."
|
||||
# --- 5. Run database migrations ---
|
||||
echo ""
|
||||
echo "[5/6] Running database migrations..."
|
||||
if docker compose run --rm backend alembic upgrade head; then
|
||||
echo " ✓ Database migrations complete"
|
||||
else
|
||||
|
|
@ -212,11 +189,8 @@ fi
|
|||
# --- 6. Start backend service ---
|
||||
echo ""
|
||||
echo "[6/6] Starting backend service..."
|
||||
|
||||
# Start backend container (force recreate to ensure new image is used)
|
||||
docker compose up -d --force-recreate backend
|
||||
|
||||
# Wait for health check
|
||||
echo " Waiting for backend to be healthy..."
|
||||
for i in {1..30}; do
|
||||
if curl -sf "http://localhost:${BACKEND_PORT}/health" > /dev/null 2>&1; then
|
||||
|
|
@ -229,7 +203,7 @@ for i in {1..30}; do
|
|||
sleep 1
|
||||
done
|
||||
|
||||
# --- Deployment summary ---
|
||||
# --- Summary ---
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo " Deployment Complete!"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue