services: skillspector-web: build: context: . dockerfile: Dockerfile container_name: skillspector-web restart: unless-stopped environment: # --- Zugriff ------------------------------------------------------- REQUIRE_AUTH: ${REQUIRE_AUTH:-true} # "false" = öffentlich ohne Login WEBUI_USER: ${WEBUI_USER:-admin} WEBUI_PASSWORD: ${WEBUI_PASSWORD} # --- Schutz gegen Missbrauch (greift v. a. im Public-Mode) --------- MAX_SCANS_PER_HOUR_PER_IP: ${MAX_SCANS_PER_HOUR_PER_IP:-10} MAX_CONCURRENT_SCANS: ${MAX_CONCURRENT_SCANS:-2} SCAN_TIMEOUT_SECONDS: ${SCAN_TIMEOUT_SECONDS:-300} # --- Optionale LLM-Analyse via OpenRouter (OpenAI-kompatible API) -- # Muss zusätzlich per ENABLE_LLM_OPTION freigeschaltet werden, damit # öffentliche Nutzer nicht unbemerkt dein OpenRouter-Guthaben verbrauchen. ENABLE_LLM_OPTION: ${ENABLE_LLM_OPTION:-false} SKILLSPECTOR_PROVIDER: openai OPENAI_API_KEY: ${OPENROUTER_API_KEY} OPENAI_BASE_URL: https://openrouter.ai/api/v1 SKILLSPECTOR_MODEL: ${OPENROUTER_MODEL:-anthropic/claude-sonnet-4.5} # Nur auf localhost binden – Zugriff von außen läuft über deinen # bestehenden Reverse Proxy (CloudPanel) mit TLS + eigenem Vhost. # HOST_PORT frei wählbar, falls 8000 schon belegt ist (siehe README). ports: - "127.0.0.1:${HOST_PORT:-8010}:8000" # Härtung: kein Zugriff auf den Docker-Socket, kein Host-Mount, # Root-Dateisystem read-only, keine erweiterten Rechte. read_only: true tmpfs: - /tmp - /app/scan-tmp cap_drop: - ALL security_opt: - no-new-privileges:true mem_limit: 1g cpus: 1.0 healthcheck: test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/healthz', timeout=3)"] interval: 30s timeout: 5s retries: 3