# nginx config for drive-frontend. # # /media/ requests are validated via auth_request to the Drive backend before # being proxied to SeaweedFS. This avoids exposing S3 credentials to the browser # while still serving private files through the CDN path. apiVersion: v1 kind: ConfigMap metadata: name: drive-frontend-nginx-conf namespace: lasuite data: default.conf: | server { listen 8080; server_name localhost; server_tokens off; root /usr/share/nginx/html; # Rewrite hardcoded upstream La Gaufre widget and services API URLs to our # integration service. sub_filter doesn't work on gzip-compressed responses. gzip off; sub_filter_once off; sub_filter_types text/html application/javascript; sub_filter 'https://static.suite.anct.gouv.fr/widgets/lagaufre.js' 'https://integration.DOMAIN_SUFFIX/api/v2/lagaufre.js'; sub_filter 'https://lasuite.numerique.gouv.fr/api/services' 'https://integration.DOMAIN_SUFFIX/api/v2/services.json'; sub_filter 'https://operateurs.suite.anct.gouv.fr/api/v1.0/lagaufre/services/?operator=9f5624fc-ef99-4d10-ae3f-403a81eb16ef&siret=21870030000013' 'https://integration.DOMAIN_SUFFIX/api/v2/services.json'; sub_filter '' ''; # Public file viewer — Next.js static export generates a literal [id].html # template for this dynamic route. Serve it for any file UUID so the # client-side router hydrates the correct FilePage component without auth. location ~ ^/explorer/items/files/[^/]+$ { try_files $uri $uri.html /explorer/items/files/[id].html; } # Item detail routes (folders, workspaces, shared items). location ~ ^/explorer/items/[^/]+$ { try_files $uri $uri.html /explorer/items/[id].html; } location / { # Try the exact path, then path + .html (Next.js static export generates # e.g. explorer/items/my-files.html), then fall back to index.html for # client-side routes that have no pre-rendered file. try_files $uri $uri.html /index.html; } # Protected media: auth via Drive backend, then proxy to S3 with signed headers. # media-auth returns S3 SigV4 Authorization/X-Amz-Date headers; nginx captures # and forwards them so SeaweedFS can verify the request. location /media/ { auth_request /internal/media-auth; auth_request_set $auth_header $upstream_http_authorization; auth_request_set $amz_date $upstream_http_x_amz_date; auth_request_set $amz_content $upstream_http_x_amz_content_sha256; proxy_set_header Authorization $auth_header; proxy_set_header X-Amz-Date $amz_date; proxy_set_header X-Amz-Content-Sha256 $amz_content; proxy_pass http://seaweedfs-filer.storage.svc.cluster.local:8333/sunbeam-drive/; } # Internal subrequest: Django checks session and item access, returns S3 auth headers. location = /internal/media-auth { internal; proxy_pass http://drive-backend.lasuite.svc.cluster.local:80/api/v1.0/items/media-auth/; proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_set_header Host drive.sunbeam.pt; proxy_set_header X-Original-URL $scheme://$host$request_uri; } error_page 500 502 503 504 @blank_error; location @blank_error { return 200 ''; add_header Content-Type text/html; } }