#!/usr/bin/env bash # ============================================================================= # tOS Installation Script # ============================================================================= # Interaktiver Installationsassistent fuer das tOS Production Deployment. # # Ausfuehren mit: chmod +x install.sh && ./install.sh # # Das Script: # 1. Prueft Voraussetzungen (Docker, Docker Compose, openssl) # 2. Sammelt Konfiguration (Domain, SSL-Modus) # 3. Generiert kryptographische Secrets # 4. Startet alle Services # 5. Wartet auf Bereitschaft und zeigt Setup-URL an # ============================================================================= set -euo pipefail # ANSI Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' BOLD='\033[1m' NC='\033[0m' # No Color SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" banner() { echo -e "${BLUE}${BOLD}" echo " ████████╗ ██████╗ ███████╗" echo " ██╔══╝██╔═══██╗██╔════╝" echo " ██║ ██║ ██║███████╗" echo " ██║ ██║ ██║╚════██║" echo " ██║ ╚██████╔╝███████║" echo " ╚═╝ ╚═════╝ ╚══════╝" echo -e "${NC}" echo -e "${BOLD} tOS - Enterprise Web Operating System${NC}" echo -e " Installationsassistent" echo "" } check_prerequisites() { echo -e "${BOLD}[1/4] Voraussetzungen pruefen...${NC}" if ! command -v docker &> /dev/null; then echo -e "${RED}[FEHLER] Docker nicht gefunden. Bitte installiere Docker: https://docs.docker.com/get-docker/${NC}" exit 1 fi echo -e "${GREEN}[OK] Docker gefunden: $(docker --version)${NC}" if ! docker compose version &> /dev/null; then echo -e "${RED}[FEHLER] Docker Compose Plugin nicht gefunden. Bitte aktualisiere Docker.${NC}" exit 1 fi echo -e "${GREEN}[OK] Docker Compose gefunden: $(docker compose version --short)${NC}" if ! command -v openssl &> /dev/null; then echo -e "${RED}[FEHLER] openssl nicht gefunden. Bitte installiere openssl.${NC}" exit 1 fi echo -e "${GREEN}[OK] openssl gefunden${NC}" echo "" } collect_configuration() { echo -e "${BOLD}[2/4] Konfiguration${NC}" echo -e "Domain fuer tOS (z.B. tos.meinefirma.de):" read -r -p " Domain: " APP_DOMAIN APP_DOMAIN="${APP_DOMAIN:-tos.example.com}" echo "" echo -e "SSL-Konfiguration:" echo " [1] Let's Encrypt (Caddy - empfohlen fuer oeffentliche Domain)" echo " [2] Externer Reverse Proxy (nginx, Apache, Cloudflare etc.)" read -r -p " Auswahl [1/2]: " SSL_CHOICE SSL_MODE="external" LETSENCRYPT_EMAIL="" if [[ "${SSL_CHOICE}" == "1" ]]; then SSL_MODE="letsencrypt" read -r -p " E-Mail fuer Let's Encrypt: " LETSENCRYPT_EMAIL fi echo "" } generate_secrets() { echo -e "${BOLD}[3/4] Secrets generieren...${NC}" POSTGRES_PASSWORD=$(openssl rand -hex 32) JWT_SECRET=$(openssl rand -hex 32) ENCRYPTION_KEY=$(openssl rand -hex 32) NEXTAUTH_SECRET=$(openssl rand -hex 32) KEYCLOAK_ADMIN_PASSWORD=$(openssl rand -base64 24 | tr -d '/+=' | head -c 32) # Generate SETUP_TOKEN if command -v uuidgen &> /dev/null; then SETUP_TOKEN=$(uuidgen | tr '[:upper:]' '[:lower:]') else SETUP_TOKEN=$(cat /proc/sys/kernel/random/uuid 2>/dev/null || openssl rand -hex 16) fi echo -e "${GREEN}[OK] Secrets generiert${NC}" echo "" # docker/.env erstellen cat > "${SCRIPT_DIR}/docker/.env" << EOF # ============================================================================= # tOS Production Configuration - Generated by install.sh on $(date) # ============================================================================= # ---- Domain ----------------------------------------------------------------- APP_DOMAIN=${APP_DOMAIN} LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL} # ---- PostgreSQL ------------------------------------------------------------- POSTGRES_USER=tos_user POSTGRES_PASSWORD=${POSTGRES_PASSWORD} POSTGRES_DB=tos_db POSTGRES_PORT=5432 # ---- Redis ------------------------------------------------------------------ REDIS_PORT=6379 # ---- Keycloak --------------------------------------------------------------- KEYCLOAK_ADMIN=admin KEYCLOAK_ADMIN_PASSWORD=${KEYCLOAK_ADMIN_PASSWORD} KEYCLOAK_PORT=8080 KEYCLOAK_REALM=tOS # ---- Application Secrets --------------------------------------------------- JWT_SECRET=${JWT_SECRET} ENCRYPTION_KEY=${ENCRYPTION_KEY} NEXTAUTH_SECRET=${NEXTAUTH_SECRET} # ---- Keycloak OAuth Clients ------------------------------------------------ KEYCLOAK_CLIENT_ID=tos-backend KEYCLOAK_CLIENT_SECRET= NEXTAUTH_KEYCLOAK_CLIENT_ID=tos-nextauth NEXTAUTH_KEYCLOAK_CLIENT_SECRET= # ---- Setup Token (nach Einrichtung entfernen) ------------------------------- SETUP_TOKEN=${SETUP_TOKEN} EOF echo -e "${GREEN}[OK] Konfigurationsdatei erstellt: docker/.env${NC}" echo "" } start_services() { echo -e "${BOLD}[4/4] Dienste starten...${NC}" cd "${SCRIPT_DIR}/docker" if [[ "${SSL_MODE}" == "letsencrypt" ]]; then echo -e "${YELLOW}Starte alle Dienste mit Let's Encrypt (SSL)...${NC}" docker compose -f docker-compose.prod.yml --profile ssl up -d --build else echo -e "${YELLOW}Starte alle Dienste ohne SSL (externer Reverse Proxy)...${NC}" docker compose -f docker-compose.prod.yml up -d --build echo -e "${YELLOW}Hinweis: Konfiguriere deinen Reverse Proxy fuer Ports 3000 (Web), 3001 (API) und 8080 (Keycloak).${NC}" fi echo "" echo -e "${YELLOW}Warte auf API-Bereitschaft (max. 3 Minuten)...${NC}" API_URL="http://localhost:3001/api/v1/health/liveness" for i in $(seq 1 36); do if curl -sf "${API_URL}" > /dev/null 2>&1; then echo "" echo -e "${GREEN}[OK] API ist bereit!${NC}" break fi if [[ $i -eq 36 ]]; then echo "" echo -e "${RED}[WARNUNG] API hat nicht innerhalb von 3 Minuten geantwortet.${NC}" echo -e " Pruefe die Logs mit: docker compose -f docker/docker-compose.prod.yml logs api" echo -e " Die Dienste laufen moeglicherweise noch hoch. Pruefe den Status mit:" echo -e " docker compose -f docker/docker-compose.prod.yml ps" break fi echo -n "." sleep 5 done echo "" cd "${SCRIPT_DIR}" } print_completion() { local SETUP_URL if [[ "${SSL_MODE}" == "letsencrypt" ]]; then SETUP_URL="https://${APP_DOMAIN}/setup?token=${SETUP_TOKEN}" else SETUP_URL="http://localhost:3000/setup?token=${SETUP_TOKEN}" fi echo "" echo -e "${GREEN}${BOLD}================================================================${NC}" echo -e "${GREEN}${BOLD} Infrastruktur erfolgreich gestartet!${NC}" echo -e "${GREEN}${BOLD}================================================================${NC}" echo "" echo -e " Fahre jetzt mit der Einrichtung im Browser fort:" echo "" echo -e " ${BOLD}${BLUE}${SETUP_URL}${NC}" echo "" echo -e "${YELLOW} WICHTIG: Notiere dir diesen Setup-Token:${NC}" echo -e " ${BOLD}${SETUP_TOKEN}${NC}" echo "" echo -e " Der Token wird nur einmal angezeigt und ist in" echo -e " docker/.env gespeichert (SETUP_TOKEN=...)." echo "" echo -e " Nach der Einrichtung kannst du SETUP_TOKEN aus" echo -e " docker/.env entfernen." echo "" echo -e " Nuetzliche Befehle:" echo -e " ${BOLD}docker compose -f docker/docker-compose.prod.yml logs -f${NC} # Alle Logs" echo -e " ${BOLD}docker compose -f docker/docker-compose.prod.yml ps${NC} # Service Status" echo -e " ${BOLD}docker compose -f docker/docker-compose.prod.yml down${NC} # Stoppen" echo -e " ${BOLD}docker compose -f docker/docker-compose.prod.yml up -d${NC} # Starten" echo "" } main() { banner check_prerequisites collect_configuration generate_secrets start_services print_completion } main "$@"