opengeos--geolibre
7df9ebf22c
Sync labels / sync (push) Failing after 1m9s
Publish Container Image / Build and publish container image (push) Has been cancelled
Deploy Website / Deploy to GitHub Pages (push) Has been cancelled
Deploy Website / Build website and demo (push) Has been cancelled
Deploy viewer / Deploy viewer proxy to Cloudflare Workers (push) Has been cancelled
Deploy tiles / Deploy planetary tile proxy to Cloudflare Workers (push) Has been cancelled
Deploy collab / Deploy collaboration relay to Cloudflare Workers (push) Has been cancelled
CI / Dependency audit (push) Has been cancelled
CI / E2E smoke (Playwright) (push) Has been cancelled
CI / Validate CITATION.cff (push) Has been cancelled
CI / Build and test (push) Has been cancelled
114 行
6.3 KiB
Nginx Configuration File
114 行
6.3 KiB
Nginx Configuration File
server {
|
|
listen 80;
|
|
server_name _;
|
|
|
|
root /usr/share/nginx/html;
|
|
index index.html;
|
|
|
|
# Optional HTTP Basic Auth. entrypoint.sh rewrites this snippet on every
|
|
# container start: when GEOLIBRE_AUTH_USER/GEOLIBRE_AUTH_PASSWORD are set
|
|
# it enables auth_basic with a generated htpasswd, otherwise it leaves the
|
|
# snippet empty (no auth, the default). Living at server level, the
|
|
# directives inherit into every location below, including the /sidecar/
|
|
# proxy. Basic Auth sends credentials with each request, so pair it with
|
|
# TLS (a reverse proxy in front) on anything but a trusted network.
|
|
include /etc/nginx/geolibre-auth.conf;
|
|
|
|
# Unauthenticated health endpoint for the container HEALTHCHECK (and any
|
|
# external monitor). Must stay outside auth or enabling a password would
|
|
# flip the container to unhealthy.
|
|
location = /healthz {
|
|
auth_basic off;
|
|
access_log off;
|
|
default_type text/plain;
|
|
return 200 "ok\n";
|
|
}
|
|
|
|
gzip on;
|
|
gzip_vary on;
|
|
gzip_proxied any;
|
|
gzip_types text/css application/javascript application/json application/wasm image/svg+xml;
|
|
gzip_min_length 1024;
|
|
|
|
# Reverse-proxy the optional Python sidecar bundled in the same image. The
|
|
# trailing slash strips the /sidecar/ prefix, so /sidecar/conversion/status
|
|
# reaches the sidecar at /conversion/status. Being same-origin avoids CORS.
|
|
location /sidecar/ {
|
|
proxy_pass http://127.0.0.1:8765/;
|
|
proxy_http_version 1.1;
|
|
# The sidecar's TrustedHostMiddleware only accepts loopback hosts, so
|
|
# forward a loopback Host rather than the public $host (which would be
|
|
# rejected as a rebinding attempt).
|
|
proxy_set_header Host 127.0.0.1;
|
|
# Authenticate the proxy to the sidecar. entrypoint.sh substitutes the
|
|
# per-container token here (and exports the same value to uvicorn). The
|
|
# browser never holds this secret; nginx is the trusted caller.
|
|
proxy_set_header X-GeoLibre-Token "__GEOLIBRE_SIDECAR_TOKEN__";
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_connect_timeout 5s;
|
|
proxy_read_timeout 600s;
|
|
}
|
|
|
|
location / {
|
|
try_files $uri /index.html;
|
|
add_header Cache-Control "no-cache, must-revalidate" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
# Closely mirrors the Tauri desktop CSP (the browser build additionally
|
|
# permits data: URIs in connect-src). 'unsafe-eval' is required by the
|
|
# @google/earthengine and maplibre-gl-geoagent bundles; connect-src
|
|
# stays broad because users connect to arbitrary tile/WMS endpoints.
|
|
# The http://localhost:* / http://127.0.0.1:* (and ws:// equivalents)
|
|
# allowances let users load PMTiles/COGs and other local test data from
|
|
# a dev server on another port (e.g. http://localhost:8081) even though
|
|
# the app itself is served from a different origin (issue #387). NOTE:
|
|
# this Docker image is intended for local/single-user use. If it is ever
|
|
# deployed to a shared or internet-facing host, the localhost allowances
|
|
# let the served JS probe each visitor's own loopback (from the browser,
|
|
# localhost is the visitor's machine, not the server) -- drop them if
|
|
# you publish the image publicly.
|
|
# The jsDelivr script-src allowances are path-scoped: /npm/ covers
|
|
# maplibre-gl-vector's DuckDB-WASM + geojson-vt/vt-pbf (Add Vector
|
|
# Layer) loaded via dynamic import()/importScripts(), and /pyodide/
|
|
# covers the Pyodide vector engine.
|
|
# When adding or removing a *named* host from any CSP directive (e.g. a
|
|
# collaboration server in connect-src, or a new CDN in script-src),
|
|
# mirror the change in the Tauri CSP in
|
|
# apps/geolibre-desktop/src-tauri/tauri.conf.json as well --
|
|
# wss://collab.geolibre.app is an example of a host duplicated in both.
|
|
# (The browser build intentionally adds data: to connect-src; that
|
|
# difference is documented in the "Closely mirrors" note above.)
|
|
# The Tauri CSP additionally allows http://127.0.0.1:* / http://localhost:*
|
|
# in frame-src/child-src so the desktop app can embed its locally
|
|
# launched JupyterLab server in the Notebook panel. That is desktop-only
|
|
# and intentionally NOT mirrored here: the web build embeds the
|
|
# same-origin self-hosted JupyterLite site, already covered by 'self'.
|
|
add_header Content-Security-Policy "default-src 'self'; connect-src 'self' https: data: blob: http://127.0.0.1:* http://localhost:* wss://collab.geolibre.app ws://127.0.0.1:* ws://localhost:*; img-src 'self' data: blob: https:; media-src 'self' blob: https:; style-src 'self' 'unsafe-inline'; script-src 'self' blob: 'unsafe-eval' 'wasm-unsafe-eval' https://cdn.jsdelivr.net/npm/ https://cdn.jsdelivr.net/pyodide/ https://accounts.google.com; child-src 'self' https://accounts.google.com https://www.google.com; frame-src 'self' https://accounts.google.com https://www.google.com; worker-src blob: 'self'" always;
|
|
}
|
|
|
|
# The service worker has a stable filename, so it must always revalidate;
|
|
# otherwise the immutable asset rule below would pin an old worker for a year
|
|
# and the autoUpdate flow could never pick up a redeploy. (Workbox's own
|
|
# runtime chunk, workbox-<hash>.js, is content-hashed and safely immutable.)
|
|
location = /sw.js {
|
|
add_header Cache-Control "no-cache, must-revalidate" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
}
|
|
|
|
# nginx's default mime.types has no entry for .webmanifest; serve it with the
|
|
# correct type and let it revalidate (it is small and changes on redeploys).
|
|
location = /manifest.webmanifest {
|
|
default_type application/manifest+json;
|
|
add_header Cache-Control "no-cache" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
}
|
|
|
|
location ~* \.(?:css|js|mjs|png|jpg|jpeg|gif|ico|svg|webp|avif|wasm|woff2?|ttf|otf)$ {
|
|
try_files $uri =404;
|
|
add_header Cache-Control "public, max-age=31536000, immutable";
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
}
|
|
}
|