# Hinterstein Mieterportal – Portal-Stack auf hocks.eu # TLS + Subdomain liefert der Nginx Proxy Manager (npm_default-Netz). # Deploy: ./deploy.sh baut dist/ + API-Image und lädt alles auf den Server. # # Dienste: # mp-portal nginx, statisches dist/ (SPA), proxiet /api/ → mp-api # und POST /api/mail/send → mp-mail-api (Token aus portal.env) # mp-api Node-API (Express + PostgreSQL-Client), baut sich aus ./server # mp-db PostgreSQL 16 (persistiertes Volume mp_pgdata) # # portal.env (nur auf dem Server, gitignored) liefert: # MAIL_API_TOKEN, POSTGRES_PASSWORD services: mp-portal: image: nginx:1.27-alpine container_name: mp-portal restart: unless-stopped volumes: - ./dist:/usr/share/nginx/html:ro # envsubst ersetzt ${MAIL_API_TOKEN} beim Start aus portal.env - ./docker/templates/default.conf.template:/etc/nginx/templates/default.conf.template:ro env_file: - portal.env depends_on: - mp-api networks: - npm_default mp-api: build: ./server container_name: mp-api restart: unless-stopped environment: DATABASE_URL: postgres://mp:${POSTGRES_PASSWORD}@mp-db:5432/mieterportal MAIL_API_URL: http://mp-mail-api:8080 MAIL_API_TOKEN: ${MAIL_API_TOKEN} # KI-Antworten auf Schadensmeldungen über n8n (Webhook-URL auf dem VPS) N8N_TICKET_WEBHOOK: ${N8N_TICKET_WEBHOOK:-} # Token, mit dem n8n die fertige KI-Antwort zurück an die API postet KI_API_TOKEN: ${KI_API_TOKEN:-} # Beleg-Import aus SparkReceipt (Shared Token für den Webhook) SPARKRECEIPT_WEBHOOK_TOKEN: ${SPARKRECEIPT_WEBHOOK_TOKEN:-} # KI-Assistent (v1.37): N8N-Webhook + gemeinsame Geheimnisse N8N_ASSIST_WEBHOOK: ${N8N_ASSIST_WEBHOOK:-} ASSIST_SHARED_SECRET: ${ASSIST_SHARED_SECRET:-} ASSIST_API_KEY: ${ASSIST_API_KEY:-} # PDF-Ablage im Dokumentenmodul (persistiertes Volume) UPLOAD_DIR: /app/uploads PORT: 3000 volumes: - mp_uploads:/app/uploads depends_on: - mp-db networks: - npm_default mp-db: image: postgres:16-alpine container_name: mp-db restart: unless-stopped environment: POSTGRES_USER: mp POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: mieterportal volumes: - mp_pgdata:/var/lib/postgresql/data healthcheck: test: ['CMD-SHELL', 'pg_isready -U mp -d mieterportal'] interval: 10s timeout: 5s retries: 5 networks: - npm_default # OCR-Dienst für die Beleg-Analyse (Tesseract Deutsch); nur intern erreichbar mp-ocr: build: ./server/ocr container_name: mp-ocr restart: unless-stopped healthcheck: test: ['CMD-SHELL', "python -c \"import urllib.request;urllib.request.urlopen('http://localhost:8081/healthz')\""] interval: 30s timeout: 5s retries: 5 networks: - npm_default networks: npm_default: external: true volumes: mp_pgdata: mp_uploads: