# ============================================================= # MPM – Reverse Proxy (Nginx) # Master has restricted capabilities; workers run as unprivileged user app. # - / -> Management-Frontend (SPA, statische Dateien) # - /api/ -> Management-Backend (127.0.0.1:3000) # Moduloberflächen liegen auf einem eigenen Host; der Hostname wird beim Start # aus MODULE_PUBLIC_ORIGIN in diese Konfiguration eingesetzt. # ============================================================= worker_processes auto; user app; pid /tmp/nginx.pid; error_log /dev/stderr warn; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; access_log /dev/stdout; server_tokens off; sendfile on; tcp_nopush on; # Upload-Grenze (z. B. für Modul-ZIP-Pakete ab Phase 3) client_max_body_size 10m; gzip on; gzip_types text/plain text/css application/javascript application/json image/svg+xml; gzip_min_length 1024; client_body_temp_path /tmp/nginx/client_body; proxy_temp_path /tmp/nginx/proxy; fastcgi_temp_path /tmp/nginx/fastcgi; uwsgi_temp_path /tmp/nginx/uwsgi; scgi_temp_path /tmp/nginx/scgi; upstream platform_backend { server 127.0.0.1:3000; } server { listen 8080 default_server; server_name _; root /app/public; index index.html; # Sicherheits-Header add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "DENY" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always; # Gehashte Frontend-Assets: lange cachen location /assets/ { expires 1y; try_files $uri =404; } # Management-API ans Backend proxien # Modulstarts können durch Docker-Builds deutlich länger als 30 Sekunden dauern. # Der Client muss auf die Lifecycle-Antwort warten können. location /api/v1/modules/ { proxy_pass http://platform_backend; proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 600s; } # Marketplace-Updates klonen Branches, bauen Images und starten Compose-Stacks. # Diese Lifecycle-Antworten können länger als das normale API-Limit dauern. location /api/v1/marketplace/modules/ { proxy_pass http://platform_backend; proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 600s; } location /api/ { proxy_pass http://platform_backend; proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 30s; } # Alte Modul-Links auf dem Plattformhost führen über das Einmal-Ticket # zum getrennten Modulhost. Hier wird kein Modul-JavaScript ausgeliefert. location ~ "^/(?!api/|assets/|login|profile|admin|403|404)(?[a-z0-9][a-z0-9-]{2,100})(?/.*)?$" { proxy_pass http://platform_backend/api/v1/auth/module-open/$module_slug; proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 30s; } # SPA-Fallback für React Router location / { try_files $uri $uri/ /index.html; } } # Dieser Host liefert ausschließlich Modulpfade und den Ticket-Übergang. # Management-API, Login, Admin-Frontend und Plattform-Cookies sind hier # nicht erreichbar. Der Name wird beim Containerstart validiert eingesetzt. server { listen 8080; server_name __MODULE_HOSTNAME__; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "DENY" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; worker-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always; # Auf lokalen Macs kann dieser Host zuvor für MPM verwendet worden sein. # Bekannte Plattform-Einstiege führen zum konfigurierten Plattformhost. location = / { return 302 __PLATFORM_ORIGIN__/; } location ~ "^/(login|admin|profile|assets|403|404)(/|$)" { return 302 __PLATFORM_ORIGIN__$request_uri; } location = /__mpm_module_handoff { access_log off; proxy_pass http://platform_backend/api/v1/auth/module-handoff$is_args$args; proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 30s; } location ^~ /api/ { return 404; } location ~ "^/(?[a-z0-9][a-z0-9-]{2,100})(?/.*)?$" { proxy_pass http://platform_backend/api/v1/gateway/$module_slug$module_path$is_args$args; proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 60s; proxy_hide_header Content-Security-Policy; proxy_hide_header Service-Worker-Allowed; } location / { return 404; } } }