feat(#swarm): Add Docker Swarm deployment with AI provider configuration
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
- Add setup-wizard.sh for interactive configuration - Add docker-compose.swarm.yml optimized for swarm deployment - Make CLAUDE_API_KEY optional based on AI_PROVIDER setting - Support multiple AI providers: Ollama, Claude API, OpenAI - Add BETTER_AUTH_SECRET to .env.example - Update deploy-swarm.sh to validate AI provider config - Add comprehensive documentation (DOCKER-SWARM.md, SWARM-QUICKREF.md) Changes: - AI_PROVIDER env var controls which AI backend to use - Ollama is default (no API key required) - Claude API and OpenAI require respective API keys - Deployment script validates based on selected provider - Removed Authentik services from swarm compose (using external) - Configured for upstream Traefik integration
This commit is contained in:
221
setup-wizard.sh
Executable file
221
setup-wizard.sh
Executable file
@@ -0,0 +1,221 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "═══════════════════════════════════════════════════════"
|
||||
echo " Mosaic Stack - Interactive Setup Wizard"
|
||||
echo "═══════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
|
||||
# Backup existing .env if it exists
|
||||
if [ -f .env ]; then
|
||||
BACKUP=".env.bak.$(date +%Y%m%d_%H%M%S)"
|
||||
cp .env "$BACKUP"
|
||||
echo "✓ Backed up existing .env to $BACKUP"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Start with .env.example as base
|
||||
if [ ! -f .env ]; then
|
||||
cp .env.example .env
|
||||
fi
|
||||
|
||||
# Helper function to update or add env var
|
||||
update_env() {
|
||||
local key=$1
|
||||
local value=$2
|
||||
if grep -q "^$key=" .env; then
|
||||
sed -i "s|^$key=.*|$key=$value|" .env
|
||||
else
|
||||
echo "$key=$value" >> .env
|
||||
fi
|
||||
}
|
||||
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " Domain Configuration"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
read -p "Web domain [app.mosaicstack.dev]: " WEB_DOMAIN
|
||||
WEB_DOMAIN=${WEB_DOMAIN:-app.mosaicstack.dev}
|
||||
update_env "MOSAIC_WEB_DOMAIN" "$WEB_DOMAIN"
|
||||
|
||||
read -p "API domain [api.mosaicstack.dev]: " API_DOMAIN
|
||||
API_DOMAIN=${API_DOMAIN:-api.mosaicstack.dev}
|
||||
update_env "MOSAIC_API_DOMAIN" "$API_DOMAIN"
|
||||
|
||||
# Update NEXT_PUBLIC_API_URL to use the configured domain
|
||||
update_env "NEXT_PUBLIC_API_URL" "https://$API_DOMAIN"
|
||||
update_env "MOSAIC_BASE_URL" "https://$WEB_DOMAIN"
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " Authentication Configuration"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
read -p "Authentik OIDC Issuer URL: " OIDC_ISSUER
|
||||
if [ -n "$OIDC_ISSUER" ]; then
|
||||
update_env "OIDC_ISSUER" "$OIDC_ISSUER"
|
||||
fi
|
||||
|
||||
read -p "OIDC Client ID: " OIDC_CLIENT_ID
|
||||
if [ -n "$OIDC_CLIENT_ID" ]; then
|
||||
update_env "OIDC_CLIENT_ID" "$OIDC_CLIENT_ID"
|
||||
fi
|
||||
|
||||
read -sp "OIDC Client Secret: " OIDC_CLIENT_SECRET
|
||||
echo ""
|
||||
if [ -n "$OIDC_CLIENT_SECRET" ]; then
|
||||
update_env "OIDC_CLIENT_SECRET" "$OIDC_CLIENT_SECRET"
|
||||
fi
|
||||
|
||||
# Auto-set redirect URI
|
||||
REDIRECT_URI="https://${API_DOMAIN}/auth/callback/authentik"
|
||||
update_env "OIDC_REDIRECT_URI" "$REDIRECT_URI"
|
||||
echo "✓ Set redirect URI to: $REDIRECT_URI"
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " AI Provider Configuration"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
echo "Choose AI provider for orchestrator agents:"
|
||||
echo " 1) Ollama (local or remote) - Recommended for self-hosted"
|
||||
echo " 2) Claude API (requires API key)"
|
||||
echo " 3) OpenAI API (requires API key)"
|
||||
echo " 4) Skip (configure manually later)"
|
||||
echo ""
|
||||
read -p "Select [1]: " AI_CHOICE
|
||||
AI_CHOICE=${AI_CHOICE:-1}
|
||||
|
||||
case $AI_CHOICE in
|
||||
1)
|
||||
echo ""
|
||||
read -p "Ollama endpoint [http://localhost:11434]: " OLLAMA_ENDPOINT
|
||||
OLLAMA_ENDPOINT=${OLLAMA_ENDPOINT:-http://localhost:11434}
|
||||
update_env "OLLAMA_ENDPOINT" "$OLLAMA_ENDPOINT"
|
||||
update_env "OLLAMA_MODE" "remote"
|
||||
|
||||
read -p "Ollama model for orchestrator [llama3.1:latest]: " OLLAMA_MODEL
|
||||
OLLAMA_MODEL=${OLLAMA_MODEL:-llama3.1:latest}
|
||||
update_env "OLLAMA_MODEL" "$OLLAMA_MODEL"
|
||||
|
||||
update_env "AI_PROVIDER" "ollama"
|
||||
echo "✓ Configured Ollama at $OLLAMA_ENDPOINT"
|
||||
echo " Note: Claude API key is NOT required for Ollama mode"
|
||||
;;
|
||||
2)
|
||||
echo ""
|
||||
read -sp "Claude API Key: " CLAUDE_API_KEY
|
||||
echo ""
|
||||
if [ -n "$CLAUDE_API_KEY" ]; then
|
||||
update_env "CLAUDE_API_KEY" "$CLAUDE_API_KEY"
|
||||
update_env "AI_PROVIDER" "claude"
|
||||
echo "✓ Configured Claude API"
|
||||
fi
|
||||
;;
|
||||
3)
|
||||
echo ""
|
||||
read -sp "OpenAI API Key: " OPENAI_API_KEY
|
||||
echo ""
|
||||
if [ -n "$OPENAI_API_KEY" ]; then
|
||||
update_env "OPENAI_API_KEY" "$OPENAI_API_KEY"
|
||||
update_env "AI_PROVIDER" "openai"
|
||||
echo "✓ Configured OpenAI API"
|
||||
fi
|
||||
;;
|
||||
4)
|
||||
echo "✓ Skipping AI provider configuration"
|
||||
update_env "AI_PROVIDER" "ollama"
|
||||
echo " Defaulting to Ollama (configure OLLAMA_ENDPOINT in .env)"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " Security Configuration"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
# Generate secrets if not present or contain REPLACE
|
||||
echo "Generating security secrets..."
|
||||
|
||||
if ! grep -q "^JWT_SECRET=" .env || grep -q "REPLACE" .env; then
|
||||
JWT_SECRET=$(openssl rand -base64 32)
|
||||
update_env "JWT_SECRET" "$JWT_SECRET"
|
||||
echo "✓ Generated JWT_SECRET"
|
||||
fi
|
||||
|
||||
if ! grep -q "^ENCRYPTION_KEY=" .env || grep -q "REPLACE" .env; then
|
||||
ENCRYPTION_KEY=$(openssl rand -hex 32)
|
||||
update_env "ENCRYPTION_KEY" "$ENCRYPTION_KEY"
|
||||
echo "✓ Generated ENCRYPTION_KEY"
|
||||
fi
|
||||
|
||||
if ! grep -q "^BETTER_AUTH_SECRET=" .env || grep -q "REPLACE" .env; then
|
||||
BETTER_AUTH_SECRET=$(openssl rand -base64 32)
|
||||
update_env "BETTER_AUTH_SECRET" "$BETTER_AUTH_SECRET"
|
||||
echo "✓ Generated BETTER_AUTH_SECRET"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " Database Configuration"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
if ! grep -q "^POSTGRES_PASSWORD=" .env || grep -q "REPLACE" .env; then
|
||||
echo "Generate new PostgreSQL password? (recommended for new installations)"
|
||||
read -p "[y/N]: " GEN_DB_PASS
|
||||
if [[ $GEN_DB_PASS =~ ^[Yy]$ ]]; then
|
||||
POSTGRES_PASSWORD=$(openssl rand -base64 24)
|
||||
update_env "POSTGRES_PASSWORD" "$POSTGRES_PASSWORD"
|
||||
# Update DATABASE_URL
|
||||
update_env "DATABASE_URL" "postgresql://mosaic:${POSTGRES_PASSWORD}@postgres:5432/mosaic"
|
||||
echo "✓ Generated PostgreSQL password"
|
||||
else
|
||||
echo "✓ Keeping existing PostgreSQL password"
|
||||
fi
|
||||
else
|
||||
echo "✓ Using existing PostgreSQL password"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " Traefik Configuration"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
echo "Use external Traefik instance? [Y/n]: "
|
||||
read -p "" USE_EXTERNAL_TRAEFIK
|
||||
USE_EXTERNAL_TRAEFIK=${USE_EXTERNAL_TRAEFIK:-Y}
|
||||
|
||||
if [[ $USE_EXTERNAL_TRAEFIK =~ ^[Yy]$ ]]; then
|
||||
update_env "TRAEFIK_MODE" "upstream"
|
||||
update_env "TRAEFIK_NETWORK" "traefik-public"
|
||||
echo "✓ Configured for upstream Traefik"
|
||||
else
|
||||
update_env "TRAEFIK_MODE" "bundled"
|
||||
echo "✓ Configured for bundled Traefik"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════════════════"
|
||||
echo " Configuration Complete!"
|
||||
echo "═══════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
echo "Configuration saved to .env"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Review .env file: nano .env"
|
||||
echo " 2. Deploy stack:"
|
||||
if [ -f deploy-swarm.sh ]; then
|
||||
echo " ./deploy-swarm.sh mosaic"
|
||||
else
|
||||
echo " docker compose up -d"
|
||||
fi
|
||||
echo ""
|
||||
echo "Services will be available at:"
|
||||
echo " Web: https://$WEB_DOMAIN"
|
||||
echo " API: https://$API_DOMAIN"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user