small fix, don't worry about it

This commit is contained in:
Tomas Dvorak
2026-04-10 12:02:36 +02:00
parent 08bd0c6e5c
commit 08cb5754f3
638 changed files with 57330 additions and 34704 deletions
+135 -134
View File
@@ -1,172 +1,170 @@
#!/bin/bash
#!/usr/bin/env bash
# Unified Docker Compose Management Script
# Usage: ./start-unified.sh [dev|prod|cloudflare|stop|logs|status|clean]
set -euo pipefail
set -e
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOCAL_COMPOSE_FILE="$ROOT_DIR/docker-compose.yml"
SELFHOSTED_COMPOSE_FILE="$ROOT_DIR/infra/docker-compose.yml"
LOCAL_ENV_FILE="$ROOT_DIR/.env"
PROD_ENV_FILE="$ROOT_DIR/.env.prod"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Function to print colored output
print_status() {
echo -e "${BLUE}[INFO]${NC} $1"
info() {
printf '[INFO] %s\n' "$1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
success() {
printf '[OK] %s\n' "$1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
error() {
printf '[ERROR] %s\n' "$1" >&2
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
docker_compose() {
docker compose "$@"
}
# Check if docker-compose.yml exists
if [ ! -f "docker-compose.yml" ]; then
print_error "docker-compose.yml not found!"
exit 1
fi
ensure_file() {
local file_path="$1"
local message="$2"
if [[ ! -f "$file_path" ]]; then
error "$message"
exit 1
fi
}
load_env() {
local env_file="$1"
ensure_file "$env_file" "Environment file not found: $env_file"
set -a
# shellcheck disable=SC1090
source "$env_file"
set +a
}
require_prod_prerequisites() {
load_env "$PROD_ENV_FILE"
if [[ -z "${DOMAIN:-}" || "${DOMAIN:-}" == "localhost" ]]; then
error "DOMAIN must be set to a real domain for production."
exit 1
fi
if [[ -z "${JWT_SECRET:-}" || "${JWT_SECRET:-}" == "dev_jwt_secret_key_change_in_production" || "${JWT_SECRET:-}" == "your-secret-key-change-in-production" ]]; then
error "JWT_SECRET must be set to a strong non-default value in production."
exit 1
fi
if (( ${#JWT_SECRET} < 32 )); then
error "JWT_SECRET must be at least 32 characters in production."
exit 1
fi
if [[ -z "${BETTER_AUTH_SECRET:-}" || "${BETTER_AUTH_SECRET:-}" == "PLACEHOLDER_BETTER_AUTH_SECRET_CHANGE_ME_32CHARS_MIN" || ${#BETTER_AUTH_SECRET} -lt 32 ]]; then
error "BETTER_AUTH_SECRET must be set to a strong non-placeholder value in production."
exit 1
fi
if [[ -z "${BETTER_AUTH_INTERNAL_TOKEN:-}" || "${BETTER_AUTH_INTERNAL_TOKEN:-}" == "PLACEHOLDER_INTERNAL_AUTH_TOKEN" ]]; then
error "BETTER_AUTH_INTERNAL_TOKEN must be set in production."
exit 1
fi
if [[ "${COOKIE_SECURE:-false}" != "true" ]]; then
error "COOKIE_SECURE must be true in production."
exit 1
fi
if [[ -z "${TRAEFIK_AUTH:-}" ]]; then
error "TRAEFIK_AUTH must be set (basic auth hash) for dashboard protection in production."
exit 1
fi
if [[ -z "${CONTAINR_AGENT_AUTH_TOKEN:-}" && -z "${CONTAINR_AGENT_AUTH_TOKENS:-}" ]]; then
error "CONTAINR_AGENT_AUTH_TOKEN or CONTAINR_AGENT_AUTH_TOKENS must be set in production."
exit 1
fi
}
# Function to show help
show_help() {
echo "Usage: $0 [COMMAND]"
echo ""
echo "Commands:"
echo " dev - Start development environment with hot reload"
echo " prod - Start production environment"
echo " cloudflare- Start production with Cloudflare tunnel"
echo " stop - Stop all services"
echo " logs - Show logs for all services"
echo " status - Show status of all services"
echo " clean - Remove all containers, volumes, and images"
echo " help - Show this help message"
echo ""
echo "Examples:"
echo " $0 dev # Start development mode"
echo " $0 prod # Start production mode"
echo " $0 cloudflare # Start with Cloudflare tunnel"
echo " $0 logs # View logs"
cat <<'EOF'
Usage: ./start-unified.sh <command>
Commands:
dev Start the full local stack from docker-compose.yml
prod Start the self-hosted production stack from infra/docker-compose.yml
cloudflare Start the self-hosted production stack with the cloudflared profile
stop Stop both local and self-hosted compose stacks
logs Show logs for the local stack
status Show compose status for both stacks
config Validate both compose files
clean Stop both stacks and remove volumes
help Show this help message
EOF
}
# Function to start development environment
start_dev() {
print_status "Starting development environment..."
# Set development environment variables
export ENVIRONMENT=development
export LOG_LEVEL=DEBUG
export DOMAIN=localhost
export ACME_EMAIL=admin@localhost
export DEV_MODE=./internal # Enable development volumes
export VITE_API_URL=http://api.localhost
export CORS_ALLOWED_ORIGINS=http://localhost,http://localhost:3000
# Stop existing containers
docker compose down 2>/dev/null || true
# Start services
docker compose up -d --build
print_success "Development environment started!"
print_status "Frontend: http://localhost"
print_status "API: http://api.localhost"
print_status "Traefik Dashboard: http://localhost:8080"
print_status "Traefik Auth: admin/admin"
ensure_file "$LOCAL_ENV_FILE" "Missing $LOCAL_ENV_FILE. Copy .env.example to .env first."
info "Starting local full stack with $LOCAL_COMPOSE_FILE"
docker_compose --env-file "$LOCAL_ENV_FILE" -f "$LOCAL_COMPOSE_FILE" up -d --build
success "Local stack is starting."
}
# Function to start production environment
start_prod() {
print_status "Starting production environment..."
# Check if required environment variables are set
if [ -z "$DOMAIN" ] || [ "$DOMAIN" = "localhost" ]; then
print_error "Please set DOMAIN environment variable for production!"
print_status "Example: export DOMAIN=yourdomain.com"
exit 1
fi
# Unset development mode
unset DEV_MODE
# Stop existing containers
docker compose down 2>/dev/null || true
# Start services
docker compose up -d --build
print_success "Production environment started!"
print_status "Frontend: https://$DOMAIN"
print_status "API: https://api.$DOMAIN"
print_status "Traefik Dashboard: https://traefik.$DOMAIN"
require_prod_prerequisites
info "Starting self-hosted production stack with $SELFHOSTED_COMPOSE_FILE"
docker_compose --env-file "$PROD_ENV_FILE" -f "$SELFHOSTED_COMPOSE_FILE" up -d --build
success "Self-hosted production stack is starting."
}
# Function to start with Cloudflare tunnel
start_cloudflare() {
print_status "Starting production environment with Cloudflare tunnel..."
# Check if Cloudflare token is set
if [ -z "$CLOUDFLARED_TOKEN" ]; then
print_error "Please set CLOUDFLARED_TOKEN environment variable!"
print_status "Get token from: https://dash.cloudflare.com/argotunnel"
require_prod_prerequisites
if [[ -z "${CLOUDFLARED_TOKEN:-}" ]]; then
error "CLOUDFLARED_TOKEN must be set."
exit 1
fi
# Unset development mode
unset DEV_MODE
# Stop existing containers
docker compose down 2>/dev/null || true
# Start services with cloudflared profile
docker compose --profile cloudflared up -d --build
print_success "Production with Cloudflare tunnel started!"
print_warning "Note: Cloudflare tunnel will expose your services publicly"
print_status "Check Cloudflare dashboard for your tunnel URL"
info "Starting self-hosted production stack with Cloudflare tunnel"
docker_compose --env-file "$PROD_ENV_FILE" -f "$SELFHOSTED_COMPOSE_FILE" --profile cloudflared up -d --build
success "Cloudflare-enabled production stack is starting."
}
# Function to stop services
stop_services() {
print_status "Stopping all services..."
docker compose down
print_success "All services stopped!"
stop_all() {
info "Stopping compose stacks"
docker_compose --env-file "$LOCAL_ENV_FILE" -f "$LOCAL_COMPOSE_FILE" down --remove-orphans 2>/dev/null || true
docker_compose --env-file "$PROD_ENV_FILE" -f "$SELFHOSTED_COMPOSE_FILE" --profile cloudflared down --remove-orphans 2>/dev/null || true
success "Compose stacks stopped."
}
# Function to show logs
show_logs() {
docker compose logs -f
ensure_file "$LOCAL_ENV_FILE" "Missing $LOCAL_ENV_FILE. Copy .env.example to .env first."
docker_compose --env-file "$LOCAL_ENV_FILE" -f "$LOCAL_COMPOSE_FILE" logs -f
}
# Function to show status
show_status() {
print_status "Service status:"
docker compose ps
info "Local stack"
docker_compose --env-file "$LOCAL_ENV_FILE" -f "$LOCAL_COMPOSE_FILE" ps 2>/dev/null || true
info "Self-hosted production stack"
docker_compose --env-file "$PROD_ENV_FILE" -f "$SELFHOSTED_COMPOSE_FILE" ps 2>/dev/null || true
}
show_config() {
ensure_file "$LOCAL_ENV_FILE" "Missing $LOCAL_ENV_FILE. Copy .env.example to .env first."
ensure_file "$PROD_ENV_FILE" "Missing $PROD_ENV_FILE. Copy .env.production.example to .env.prod first."
info "Validating local compose file"
docker_compose --env-file "$LOCAL_ENV_FILE" -f "$LOCAL_COMPOSE_FILE" config -q
info "Validating self-hosted production compose file"
docker_compose --env-file "$PROD_ENV_FILE" -f "$SELFHOSTED_COMPOSE_FILE" config -q
success "Compose configuration is valid."
}
# Function to clean everything
clean_all() {
print_warning "This will remove ALL containers, volumes, and images!"
read -p "Are you sure? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
print_status "Removing containers, volumes, and images..."
docker compose down -v --rmi all
docker system prune -f
print_success "Cleanup complete!"
else
print_status "Cleanup cancelled."
fi
info "Removing local and self-hosted compose stacks with volumes"
docker_compose --env-file "$LOCAL_ENV_FILE" -f "$LOCAL_COMPOSE_FILE" down -v --remove-orphans 2>/dev/null || true
docker_compose --env-file "$PROD_ENV_FILE" -f "$SELFHOSTED_COMPOSE_FILE" --profile cloudflared down -v --remove-orphans 2>/dev/null || true
success "Compose cleanup finished."
}
# Main script logic
case "${1:-help}" in
dev)
start_dev
@@ -178,7 +176,7 @@ case "${1:-help}" in
start_cloudflare
;;
stop)
stop_services
stop_all
;;
logs)
show_logs
@@ -186,6 +184,9 @@ case "${1:-help}" in
status)
show_status
;;
config)
show_config
;;
clean)
clean_all
;;
@@ -193,7 +194,7 @@ case "${1:-help}" in
show_help
;;
*)
print_error "Unknown command: $1"
error "Unknown command: ${1}"
show_help
exit 1
;;