feat: add flexible docker-compose architecture with profiles
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- Add OpenBao services to docker-compose.yml with profiles (openbao, full) - Add docker-compose.build.yml for local builds vs registry pulls - Make PostgreSQL and Valkey optional via profiles (database, cache) - Create example compose files for common deployment scenarios: - docker/docker-compose.example.turnkey.yml (all bundled) - docker/docker-compose.example.external.yml (all external) - docker/docker.example.hybrid.yml (mixed deployment) - Update documentation: - Enhance .env.example with profiles and external service examples - Update README.md with deployment mode quick starts - Add deployment scenarios to docs/OPENBAO.md - Create docker/DOCKER-COMPOSE-GUIDE.md with comprehensive guide - Clean up repository structure: - Move shell scripts to scripts/ directory - Move documentation to docs/ directory - Move docker compose examples to docker/ directory - Configure for external Authentik with internal services: - Comment out Authentik services (using external OIDC) - Comment out unused volumes for disabled services - Keep postgres, valkey, openbao as internal services This provides a flexible deployment architecture supporting turnkey, production (all external), and hybrid configurations via Docker Compose profiles. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
43
scripts/build-images.sh
Executable file
43
scripts/build-images.sh
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Mosaic Stack - Build Images for Swarm Deployment
|
||||
# This script builds all Docker images needed for the stack
|
||||
|
||||
echo "🔨 Building Mosaic Stack images for swarm deployment..."
|
||||
echo ""
|
||||
|
||||
# Build postgres with pgvector
|
||||
echo "📦 Building postgres..."
|
||||
docker build -t stack-postgres:latest -f docker/postgres/Dockerfile docker/postgres/
|
||||
|
||||
# Build openbao
|
||||
echo "📦 Building openbao..."
|
||||
docker build -t stack-openbao:latest -f docker/openbao/Dockerfile docker/openbao/
|
||||
|
||||
# Build API
|
||||
echo "📦 Building API..."
|
||||
docker build -t stack-api:latest -f apps/api/Dockerfile . --build-arg NODE_ENV=production
|
||||
|
||||
# Build orchestrator
|
||||
echo "📦 Building orchestrator..."
|
||||
docker build -t stack-orchestrator:latest -f apps/orchestrator/Dockerfile .
|
||||
|
||||
# Build web (using NEXT_PUBLIC_API_URL from .env if available)
|
||||
echo "📦 Building web..."
|
||||
if [ -f .env ]; then
|
||||
NEXT_PUBLIC_API_URL=$(grep "^NEXT_PUBLIC_API_URL=" .env | cut -d= -f2 || echo "https://api.mosaicstack.dev")
|
||||
else
|
||||
NEXT_PUBLIC_API_URL="https://api.mosaicstack.dev"
|
||||
fi
|
||||
docker build -t stack-web:latest -f apps/web/Dockerfile . --build-arg NEXT_PUBLIC_API_URL="$NEXT_PUBLIC_API_URL"
|
||||
|
||||
echo ""
|
||||
echo "✅ All images built successfully!"
|
||||
echo ""
|
||||
echo "Built images:"
|
||||
docker images | grep "^stack-"
|
||||
|
||||
echo ""
|
||||
echo "Next step:"
|
||||
echo " Deploy to swarm: ./deploy-swarm.sh mosaic"
|
||||
146
scripts/deploy-swarm.sh
Executable file
146
scripts/deploy-swarm.sh
Executable file
@@ -0,0 +1,146 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Mosaic Stack - Docker Swarm Deployment Script
|
||||
# Usage: ./deploy-swarm.sh [stack-name]
|
||||
|
||||
STACK_NAME="${1:-mosaic}"
|
||||
COMPOSE_FILE="docker-compose.swarm.yml"
|
||||
IMAGE_TAG="${IMAGE_TAG:-latest}"
|
||||
|
||||
echo "🚀 Deploying Mosaic Stack to Docker Swarm..."
|
||||
echo "Stack name: $STACK_NAME"
|
||||
echo "Compose file: $COMPOSE_FILE"
|
||||
echo "Image tag: $IMAGE_TAG"
|
||||
echo ""
|
||||
|
||||
# Check if .env exists
|
||||
if [ ! -f .env ]; then
|
||||
echo "❌ Error: .env file not found"
|
||||
echo "📝 Run the setup wizard to create it:"
|
||||
echo " ./setup-wizard.sh"
|
||||
echo ""
|
||||
echo "Or copy from example:"
|
||||
echo " cp .env.example .env"
|
||||
echo " nano .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check required environment variables
|
||||
echo "🔍 Checking required environment variables..."
|
||||
missing_vars=()
|
||||
|
||||
# Check critical variables
|
||||
for var in POSTGRES_PASSWORD JWT_SECRET OIDC_CLIENT_ID OIDC_CLIENT_SECRET ENCRYPTION_KEY BETTER_AUTH_SECRET; do
|
||||
if ! grep -q "^${var}=" .env || grep -q "^${var}=.*REPLACE" .env || [ -z "$(grep "^${var}=" .env | cut -d= -f2)" ]; then
|
||||
missing_vars+=("$var")
|
||||
fi
|
||||
done
|
||||
|
||||
# Check AI provider configuration
|
||||
AI_PROVIDER=$(grep "^AI_PROVIDER=" .env 2>/dev/null | cut -d= -f2 || echo "ollama")
|
||||
|
||||
if [ "$AI_PROVIDER" = "claude" ]; then
|
||||
if ! grep -q "^CLAUDE_API_KEY=" .env || grep -q "^CLAUDE_API_KEY=.*REPLACE" .env; then
|
||||
missing_vars+=("CLAUDE_API_KEY (required when AI_PROVIDER=claude)")
|
||||
fi
|
||||
elif [ "$AI_PROVIDER" = "openai" ]; then
|
||||
if ! grep -q "^OPENAI_API_KEY=" .env || grep -q "^OPENAI_API_KEY=.*REPLACE" .env; then
|
||||
missing_vars+=("OPENAI_API_KEY (required when AI_PROVIDER=openai)")
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ${#missing_vars[@]} -gt 0 ]; then
|
||||
echo "❌ Missing or placeholder values for:"
|
||||
printf " - %s\n" "${missing_vars[@]}"
|
||||
echo ""
|
||||
echo "Run the setup wizard to configure:"
|
||||
echo " ./setup-wizard.sh"
|
||||
echo ""
|
||||
echo "Or manually edit .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ All required variables configured"
|
||||
echo " AI Provider: $AI_PROVIDER"
|
||||
echo ""
|
||||
|
||||
# Check if traefik-public network exists
|
||||
if ! docker network ls --filter name=traefik-public --format '{{.Name}}' | grep -q '^traefik-public$'; then
|
||||
echo "⚠️ traefik-public network not found. Creating it..."
|
||||
docker network create --driver=overlay traefik-public
|
||||
echo "✅ traefik-public network created"
|
||||
else
|
||||
echo "✅ traefik-public network already exists"
|
||||
fi
|
||||
|
||||
# Check if using registry images or local images
|
||||
echo ""
|
||||
REGISTRY="git.mosaicstack.dev"
|
||||
USE_REGISTRY=true
|
||||
|
||||
# If IMAGE_TAG is set to "local", use local images
|
||||
if [ "$IMAGE_TAG" = "local" ]; then
|
||||
USE_REGISTRY=false
|
||||
echo "🔍 Using local images (IMAGE_TAG=local)"
|
||||
IMAGES_MISSING=0
|
||||
for img in stack-postgres stack-openbao stack-api stack-orchestrator stack-web; do
|
||||
if ! docker images --format "{{.Repository}}" | grep -q "^${img}$"; then
|
||||
echo " ⚠️ Missing: $img"
|
||||
IMAGES_MISSING=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $IMAGES_MISSING -eq 1 ]; then
|
||||
echo ""
|
||||
echo "❌ Some local images are missing. Build them first:"
|
||||
echo " ./build-images.sh"
|
||||
echo ""
|
||||
read -p "Build images now? [Y/n]: " BUILD_NOW
|
||||
BUILD_NOW=${BUILD_NOW:-Y}
|
||||
if [[ $BUILD_NOW =~ ^[Yy]$ ]]; then
|
||||
./build-images.sh || exit 1
|
||||
else
|
||||
echo "Aborting deployment. Build images first."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "✅ All local images are built"
|
||||
fi
|
||||
else
|
||||
echo "🔍 Using registry images from $REGISTRY"
|
||||
echo " Tag: $IMAGE_TAG"
|
||||
echo ""
|
||||
echo " Images will be pulled from:"
|
||||
echo " - $REGISTRY/mosaic/stack-postgres:$IMAGE_TAG"
|
||||
echo " - $REGISTRY/mosaic/stack-openbao:$IMAGE_TAG"
|
||||
echo " - $REGISTRY/mosaic/stack-api:$IMAGE_TAG"
|
||||
echo " - $REGISTRY/mosaic/stack-orchestrator:$IMAGE_TAG"
|
||||
echo " - $REGISTRY/mosaic/stack-web:$IMAGE_TAG"
|
||||
echo ""
|
||||
echo " Note: Ensure you're logged in to the registry:"
|
||||
echo " docker login $REGISTRY"
|
||||
fi
|
||||
|
||||
# Deploy the stack
|
||||
echo ""
|
||||
echo "📦 Deploying stack..."
|
||||
IMAGE_TAG=$IMAGE_TAG docker stack deploy -c $COMPOSE_FILE --with-registry-auth $STACK_NAME
|
||||
|
||||
echo ""
|
||||
echo "✅ Stack deployed successfully!"
|
||||
echo ""
|
||||
echo "📊 Stack status:"
|
||||
docker stack ps $STACK_NAME --format "table {{.Name}}\t{{.CurrentState}}\t{{.Error}}"
|
||||
|
||||
echo ""
|
||||
echo "🔍 To check stack services:"
|
||||
echo " docker stack services $STACK_NAME"
|
||||
echo ""
|
||||
echo "🔍 To check stack logs:"
|
||||
echo " docker service logs ${STACK_NAME}_api"
|
||||
echo " docker service logs ${STACK_NAME}_web"
|
||||
echo " docker service logs ${STACK_NAME}_postgres"
|
||||
echo ""
|
||||
echo "🗑️ To remove the stack:"
|
||||
echo " docker stack rm $STACK_NAME"
|
||||
92
scripts/diagnose-package-link.sh
Executable file
92
scripts/diagnose-package-link.sh
Executable file
@@ -0,0 +1,92 @@
|
||||
#!/bin/bash
|
||||
# Diagnostic script to determine why package linking is failing
|
||||
# This will help identify the correct package names and API format
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "$GITEA_TOKEN" ]; then
|
||||
echo "ERROR: GITEA_TOKEN environment variable is required"
|
||||
echo "Get your token from: https://git.mosaicstack.dev/user/settings/applications"
|
||||
echo "Then run: GITEA_TOKEN='your_token' ./diagnose-package-link.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BASE_URL="https://git.mosaicstack.dev"
|
||||
OWNER="mosaic"
|
||||
REPO="stack"
|
||||
|
||||
echo "=== Gitea Package Link Diagnostics ==="
|
||||
echo "Gitea URL: $BASE_URL"
|
||||
echo "Owner: $OWNER"
|
||||
echo "Repository: $REPO"
|
||||
echo ""
|
||||
|
||||
# Step 1: List all packages for the owner
|
||||
echo "Step 1: Listing all container packages for owner '$OWNER'..."
|
||||
PACKAGES_JSON=$(curl -s -X GET \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"$BASE_URL/api/v1/packages/$OWNER?type=container&limit=20")
|
||||
|
||||
echo "$PACKAGES_JSON" | jq -r '.[] | " - Name: \(.name), Type: \(.type), Version: \(.version)"' 2>/dev/null || {
|
||||
echo " Response (raw):"
|
||||
echo "$PACKAGES_JSON" | head -20
|
||||
}
|
||||
echo ""
|
||||
|
||||
# Step 2: Extract package names and test linking for each
|
||||
echo "Step 2: Testing package link API for each discovered package..."
|
||||
PACKAGE_NAMES=$(echo "$PACKAGES_JSON" | jq -r '.[].name' 2>/dev/null)
|
||||
|
||||
if [ -z "$PACKAGE_NAMES" ]; then
|
||||
echo " WARNING: No packages found or unable to parse response"
|
||||
echo " Falling back to known package names..."
|
||||
PACKAGE_NAMES="stack-api stack-web stack-postgres stack-openbao stack-orchestrator"
|
||||
fi
|
||||
|
||||
for package in $PACKAGE_NAMES; do
|
||||
echo ""
|
||||
echo " Testing package: $package"
|
||||
|
||||
# Test Format 1: Standard format
|
||||
echo " Format 1: POST /api/v1/packages/$OWNER/container/$package/-/link/$REPO"
|
||||
STATUS=$(curl -s -o /tmp/link-response.txt -w "%{http_code}" -X POST \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
"$BASE_URL/api/v1/packages/$OWNER/container/$package/-/link/$REPO")
|
||||
echo " Status: $STATUS"
|
||||
if [ "$STATUS" != "404" ]; then
|
||||
echo " Response:"
|
||||
cat /tmp/link-response.txt | head -5
|
||||
fi
|
||||
|
||||
# Test Format 2: Without /-/
|
||||
echo " Format 2: POST /api/v1/packages/$OWNER/container/$package/link/$REPO"
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"$BASE_URL/api/v1/packages/$OWNER/container/$package/link/$REPO")
|
||||
echo " Status: $STATUS"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "=== Analysis ==="
|
||||
echo "Expected successful status codes:"
|
||||
echo " - 200/201: Successfully linked"
|
||||
echo " - 204: No content (success)"
|
||||
echo " - 400: Already linked (also success)"
|
||||
echo ""
|
||||
echo "Error status codes:"
|
||||
echo " - 404: Endpoint or package doesn't exist"
|
||||
echo " - 401: Authentication failed"
|
||||
echo " - 403: Permission denied"
|
||||
echo ""
|
||||
echo "If all attempts return 404, possible causes:"
|
||||
echo " 1. Gitea version < 1.24.0 (check with: curl $BASE_URL/api/v1/version)"
|
||||
echo " 2. Package names are different than expected"
|
||||
echo " 3. Package type is not 'container'"
|
||||
echo " 4. API endpoint path has changed"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Check package names on web UI: $BASE_URL/$OWNER/-/packages"
|
||||
echo " 2. Check Gitea version in footer of: $BASE_URL"
|
||||
echo " 3. Try linking manually via web UI to verify it works"
|
||||
echo " 4. Check Gitea logs for API errors"
|
||||
221
scripts/setup-wizard.sh
Executable file
221
scripts/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 ""
|
||||
74
scripts/test-link-api.sh
Executable file
74
scripts/test-link-api.sh
Executable file
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
# Test script to find the correct Gitea package link API endpoint
|
||||
# Usage: Set GITEA_TOKEN environment variable and run this script
|
||||
|
||||
if [ -z "$GITEA_TOKEN" ]; then
|
||||
echo "Error: GITEA_TOKEN environment variable not set"
|
||||
echo "Usage: GITEA_TOKEN=your_token ./test-link-api.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PACKAGE="stack-api"
|
||||
OWNER="mosaic"
|
||||
REPO="stack"
|
||||
BASE_URL="https://git.mosaicstack.dev"
|
||||
|
||||
echo "Testing different API endpoint formats for package linking..."
|
||||
echo "Package: $PACKAGE"
|
||||
echo "Owner: $OWNER"
|
||||
echo "Repo: $REPO"
|
||||
echo ""
|
||||
|
||||
# Test 1: Current format with /-/
|
||||
echo "Test 1: POST /api/v1/packages/$OWNER/container/$PACKAGE/-/link/$REPO"
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"$BASE_URL/api/v1/packages/$OWNER/container/$PACKAGE/-/link/$REPO")
|
||||
echo "Status: $STATUS"
|
||||
echo ""
|
||||
|
||||
# Test 2: Without /-/
|
||||
echo "Test 2: POST /api/v1/packages/$OWNER/container/$PACKAGE/link/$REPO"
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"$BASE_URL/api/v1/packages/$OWNER/container/$PACKAGE/link/$REPO")
|
||||
echo "Status: $STATUS"
|
||||
echo ""
|
||||
|
||||
# Test 3: With PUT instead of POST (old method)
|
||||
echo "Test 3: PUT /api/v1/packages/$OWNER/container/$PACKAGE/-/link/$REPO"
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X PUT \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"$BASE_URL/api/v1/packages/$OWNER/container/$PACKAGE/-/link/$REPO")
|
||||
echo "Status: $STATUS"
|
||||
echo ""
|
||||
|
||||
# Test 4: Different path structure
|
||||
echo "Test 4: PUT /api/v1/packages/$OWNER/$PACKAGE/link/$REPO"
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X PUT \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"$BASE_URL/api/v1/packages/$OWNER/$PACKAGE/link/$REPO")
|
||||
echo "Status: $STATUS"
|
||||
echo ""
|
||||
|
||||
# Test 5: Check if package exists at all
|
||||
echo "Test 5: GET /api/v1/packages/$OWNER/container/$PACKAGE"
|
||||
STATUS=$(curl -s -w "%{http_code}" -X GET \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"$BASE_URL/api/v1/packages/$OWNER/container/$PACKAGE" | tail -1)
|
||||
echo "Status: $STATUS"
|
||||
echo ""
|
||||
|
||||
# Test 6: List all packages for owner
|
||||
echo "Test 6: GET /api/v1/packages/$OWNER"
|
||||
echo "First 3 packages:"
|
||||
curl -s -X GET \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"$BASE_URL/api/v1/packages/$OWNER?type=container&page=1&limit=10" | head -30
|
||||
echo ""
|
||||
|
||||
echo "=== Instructions ==="
|
||||
echo "1. Run this script with: GITEA_TOKEN=your_token ./test-link-api.sh"
|
||||
echo "2. Look for Status: 200, 201, 204 (success) or 400 (already linked)"
|
||||
echo "3. Status 404 means the endpoint doesn't exist"
|
||||
echo "4. Status 401/403 means authentication issue"
|
||||
Reference in New Issue
Block a user