Self-Hosting GeoLibre with CDN-Free Builds: A Complete Guide to Offline Deployment
Set environment flags like GEOLIBRE_NO_EXTERNAL_CDN=1 during the Vite build process to bundle all WASM engines locally and eliminate external CDN dependencies.
GeoLibre's default web distribution fetches heavy WebAssembly assets—Pyodide, PGlite/PostGIS, CereusDB, gdal3.js, and DuckDB-WASM—from public CDNs such as jsDelivr and unpkg.com. For enterprises, air-gapped networks, or privacy-focused deployments, the codebase provides granular environment flags that control whether each asset is fetched at runtime or bundled into your application. This article explains how to self-host GeoLibre using these CDN-free build options.
Core CDN-Removal Flags
GeoLibre implements a hierarchical flag system in apps/geolibre-desktop/vite.config.ts and docker/Dockerfile. The master flag overrides all others, with individual flags controlling specific engines.
| Flag | Default | Effect when cleared | Use case |
|---|---|---|---|
GEOLIBRE_NO_EXTERNAL_CDN |
unset | Strips all GeoLibre-controlled CDN references. Disables story-map HTML export, ONNX runtime, 3D Tiles Draco/KTX2 decoders, and GDAL export. Forces other CDN flags to 0. |
Enterprise deployments with strict no-CDN policies |
GEOLIBRE_PGLITE_CDN |
1 (CDN) |
Bundles PGlite + PostGIS WASM (~22 MiB) into /assets/ |
Offline SQL + PostGIS support |
GEOLIBRE_CEREUS_CDN |
1 (CDN) |
Bundles CereusDB (Apache Sedona) WASM (~40 MiB) | Offline spatial analytics |
GEOLIBRE_GDAL_CDN |
1 (CDN) |
Disables gdal3.js export feature entirely |
When client-side GeoTIFF/COG export is unnecessary |
GEOLIBRE_DUCKDB_WASM_CDN |
0 (bundled) |
Moves DuckDB-WASM (~40 MiB) to jsDelivr | Cloudflare Pages/Workers deployments (25 MiB asset limit) |
VITE_PYODIDE_INDEX_URL |
jsDelivr URL | Redirects Pyodide to a custom mirror | Private Pyodide hosting without disabling Python support |
These flags are documented in docs/self-hosting.md and docs/getting-started.md.
Building a Fully Offline-Capable Distribution
Complete CDN-Free Build
Eliminate all external GeoLibre CDN references:
GEOLIBRE_NO_EXTERNAL_CDN=1 npx vite build
This configuration:
- Emits all bundleable assets to
/assets/ - Removes external script tag injections
- Disables features requiring exclusive CDN URLs (story-map export, object detection, GDAL export)
Trade-offs: Certain advanced capabilities become unavailable. Core GIS functions—vector rendering, raster analysis, 3D Tiles viewing, and the processing toolbox—remain fully operational.
Selective Engine Bundling
Bundle specific WASM engines while retaining other CDN dependencies:
GEOLIBRE_PGLITE_CDN=0 GEOLIBRE_CEREUS_CDN=0 npx vite build
Result: PGlite/PostGIS and CereusDB assets are copied into /assets/, enabling offline SQL processing and Sedona-style analytics without bundling the full CDN-free stack.
Self-Hosting Pyodide on Private Infrastructure
Pyodide requires special handling. The VITE_PYODIDE_INDEX_URL flag redirects fetches without disabling Python support:
VITE_PYODIDE_INDEX_URL=https://my.cdn.example.com/pyodide/ \
GEOLIBRE_NO_EXTERNAL_CDN=1 npx vite build
GeoLibre itself becomes CDN-free; Python + GeoPandas functionality loads from your controlled infrastructure. Mirror the complete Pyodide distribution—including pyodide.asm.wasm, python_stdlib.zip, and package files—to this endpoint.
Docker-Based Self-Hosted Deployment
The repository provides production-ready containerization in docker/Dockerfile and docker/nginx.conf:
# Build the CDN-free bundle
GEOLIBRE_NO_EXTERNAL_CDN=1 npx vite build
# Construct the container image
docker build -t my-geolibre .
# Run with exposed port
docker run -p 8080:80 my-geolibre
The Dockerfile copies ./dist to /usr/share/nginx/html, serving all bundled assets from the same origin. Customize docker/nginx.conf to add your own CDN mirrors or implement additional security headers.
Performance and Architecture Implications
Service Worker Behavior
With bundled assets, the service worker's CacheFirst strategy for CDN engines becomes unnecessary. Assets served from /assets/ leverage standard HTTP caching and same-origin security policies. The vite.config.ts logic adjusts cache rules automatically based on build flags.
Binary Size Budget
| Configuration | Size Impact |
|---|---|
GEOLIBRE_PGLITE_CDN=0 |
+~22 MiB |
GEOLIBRE_CEREUS_CDN=0 |
+~40 MiB |
GEOLIBRE_GDAL_CDN=0 |
-~40 MiB (complete removal) |
GEOLIBRE_DUCKDB_WASM_CDN=1 |
-~40 MiB (moves to external CDN) |
Calculation: A fully bundled desktop installer or web deployment with PGlite and CereusDB but no GDAL export adds approximately 62 MiB to the base build.
Cloudflare Pages Compatibility
Static hosting platforms often enforce per-asset size limits. GeoLibre's DuckDB-WASM flag specifically addresses Cloudflare's 25 MiB threshold:
GEOLIBRE_DUCKDB_WASM_CDN=1 npx vite build
This moves the ~40 MiB DuckDB-WASM distribution to jsDelivr while keeping GeoLibre's own code self-hosted.
Embed Build Customization
The script scripts/build-embed.mjs generates @geolibre/embed, a distributable iframe-compatible version. This build respects the same environment flags:
GEOLIBRE_NO_EXTERNAL_CDN=1 GEOLIBRE_PGLITE_CDN=0 npx vite build
node scripts/build-embed.mjs
Result: A CDN-free embeddable map component suitable for intranet portals or restricted environments.
Critical Source Files Reference
| File | Purpose |
|---|---|
apps/geolibre-desktop/vite.config.ts |
Reads environment variables, configures Vite build pipeline, service-worker cache rules |
docker/Dockerfile |
Production container assembly, copies bundled assets to Nginx |
docker/nginx.conf |
Static asset serving configuration |
docs/self-hosting.md |
Master CDN-free deployment documentation (#L151) |
docs/getting-started.md |
Per-engine flag reference table (#L590-594) |
scripts/build-embed.mjs |
CDN-free embeddable build generator |
packages/processing/src/ort.ts |
ONNX Runtime WASM URL derivation—CDN flag removes this dependency |
Summary
- Master control: Set
GEOLIBRE_NO_EXTERNAL_CDN=1to eliminate all GeoLibre-managed CDN references - Granular bundling: Use individual
GEOLIBRE_*_CDNflags to select which WASM engines ship with your build - Pyodide flexibility: Redirect to private mirrors via
VITE_PYODIDE_INDEX_URLwithout losing Python support - Platform constraints: Enable
GEOLIBRE_DUCKDB_WASM_CDNfor size-limited static hosts - Production deployment: Leverage the provided Docker configuration for same-origin asset serving
Frequently Asked Questions
What features break when I disable all CDNs?
Story-map HTML export, built-in ONNX-based object detection, 3D Tiles Draco/KTX2 decoders, and GDAL export functionality become unavailable. All vector, raster, 3D visualization, and processing toolbox operations continue working because their WASM engines either bundle locally or remain fetchable from infrastructure you control.
Can I self-host Pyodide while keeping other engines on CDNs?
Yes. Set VITE_PYODIDE_INDEX_URL to your private mirror without enabling GEOLIBRE_NO_EXTERNAL_CDN. PGlite, CereusDB, and other engines continue loading from public CDNs while Pyodide fetches exclusively from your specified origin.
How do I verify my build contains no external CDN references?
Inspect the generated index.html and JavaScript chunks in /dist. Search for patterns matching unpkg.com, cdn.jsdelivr.net, or jsDelivr. The vite.config.ts logic strips these URLs when GEOLIBRE_NO_EXTERNAL_CDN is active, and service-worker precache manifests will list only same-origin /assets/ paths.
What's the minimum viable CDN-free configuration for offline desktop use?
For Tauri or Electron deployments targeting offline-first scenarios: build with GEOLIBRE_NO_EXTERNAL_CDN=1 GEOLIBRE_PGLITE_CDN=0. This provides core GIS capabilities plus SQL/PostGIS processing without network dependencies, at a cost of approximately +22 MiB in installer size.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →