GeoLibre Python Sidecar (FastAPI) Architecture: A Complete Guide to Geoprocessing Tools and Implementation
The GeoLibre Python sidecar is an optional FastAPI server running on 127.0.0.1:8765 that hosts heavyweight geoprocessing libraries—WhiteboxTools, GDAL/Rasterio, GeoPandas, Apache Sedona, and SamGeo—behind a secure, token-gated API with asynchronous job queuing.
The GeoLibre Python sidecar bridges the gap between browser-based GIS workflows and computationally demanding geoprocessing tasks. According to the opengeos/GeoLibre source code, this FastAPI application runs locally as a trusted companion to the desktop client, executing operations that cannot safely run inside the Tauri sandbox or browser environment. This guide examines its architecture, security model, router organization, managed runtime system, and the complete set of geoprocessing tools it exposes.
FastAPI Application Structure and Entry Point
The sidecar's foundation lives in geolibre_server/app/main.py, where the FastAPI instance is created and configured with modular routers for each tool category.
# backend/geolibre_server/geolibre_server/app/main.py
app = FastAPI(title="GeoLibre Server", version="0.8.0")
app.include_router(whitebox_router)
app.include_router(conversion_router)
app.include_router(raster_router)
app.include_router(vector_router)
app.include_router(postgis_router)
app.include_router(sql_router)
app.include_router(ml_router)
This router-based organization keeps each geoprocessing domain isolated and testable. The application follows standard FastAPI patterns: Pydantic models for request validation, dependency injection for shared services, and explicit path prefixes for API versioning.
Security Architecture and Request Gating
The GeoLibre sidecar implements defense-in-depth for a local service that handles file system paths and subprocess execution.
| Security Layer | Implementation | Source Location |
|---|---|---|
| Per-launch token authentication | Desktop shell generates GEOLIBRE_SIDECAR_TOKEN; middleware validates X-GeoLibre-Token or Authorization: Bearer headers; exempted only when unset for local testing |
main.py lines 37–84 |
| Trusted host validation | TrustedHostMiddleware restricts to loopback addresses (localhost, 127.0.0.1, testserver) |
main.py lines 87–97 |
| CORS policy | Limited to Vite dev server (:5173) and Tauri webview origins; credentials disallowed |
main.py lines 98–110 |
| Health endpoint exemption | /health skips token checks for readiness probes via _TOKEN_EXEMPT_PATHS |
main.py line 53 |
The token middleware aggressively rejects requests from unexpected origins, mitigating DNS rebinding attacks against local services. As implemented in opengeos/GeoLibre, the environment variable escape hatch (GEOLIBRE_SIDECAR_TOKEN unset) exists solely for pytest automation, not production deployments.
Router Modules and Geoprocessing Tool Groups
Each router encapsulates a specific geoprocessing domain. The GeoLibre sidecar provides seven primary tool groups:
WhiteboxRouter (/whitebox)
WhiteboxTools integration via geolibre_server/app/whitebox.py. This router wraps the WhiteboxTools CLI, automatically bootstrapping a managed virtual environment on first use. Heavy geomorphometric and hydrologic analyses execute in isolated subprocesses with streaming output capture.
ConversionRouter (/conversion)
The most complex router, implemented in geolibre_server/app/conversion.py, handles format conversion across the geospatial stack:
- Vector → GeoParquet (Hilbert-sorted for spatial performance)
- Vector → FlatGeobuf
- Vector → PMTiles (via freestiler)
- CSV (lon/lat) → GeoParquet
- Raster → Cloud-Optimized GeoTIFF
This router implements uv-managed runtime bootstrapping, job queuing, and persistent result storage.
RasterRouter (/raster)
Lightweight wrapper in geolibre_server/app/raster.py for rio-cogeo Cloud-Optimized GeoTIFF generation. Delegates to the conversion runtime for actual execution.
VectorRouter (/vector)
Placeholder utilities in geolibre_server/app/vector.py: bounding box extraction, buffer operations, and reprojection. Future iterations will integrate full GDAL/GeoPandas workflows.
PostGISRouter (/postgis)
Remote PostGIS connection management with strict host whitelisting via GEOLIBRE_POSTGIS_HOSTS. See geolibre_server/app/postgis.py for connection registration and status monitoring.
SQLRouter (/sql) — Apache Sedona Integration
Apache Sedona spatial SQL via the Rust SedonaDB engine. The geolibre_server/app/sql.py router exposes:
GET /sql/status— Engine availability probePOST /sql/run— Execute spatial SQL over registered layers
MLRouter (/ml) — SamGeo Proxy
Reverse-proxy design in geolibre_server/app/ml.py. The sidecar never loads PyTorch; instead, it forwards requests to an external SamGeo server running the Segment Anything Model 3. This architecture keeps the sidecar lightweight while enabling AI-powered segmentation.
Managed Runtime System with uv
The conversion and raster tools require heavy native dependencies (DuckDB, rio-cogeo, freestiler) that cannot bloat the base sidecar installation. The GeoLibre sidecar solves this with an on-demand virtual environment managed by uv.
Bootstrap Flow
-
Interpreter resolution —
GEOLIBRE_CONVERSION_PYTHONenvironment variable takes precedence; otherwise_ensure_managed_runtime()creates a venv under~/.cache/geolibre/conversion-runtime -
Package installation —
_run_runtime_setup_commandinstalls locked dependency versions -
Verification and caching —
_check_runtime_importvalidates imports; path cached in_CHECKED_RUNTIME_PYTHON
All runtime management functions reside in conversion.py lines 461–735: _runtime_python, _ensure_managed_runtime, and _check_runtime_import.
This design ensures native wheels download once, remain isolated from the sidecar process, and can be rebuilt independently when dependency versions change.
Asynchronous Job Queue Architecture
Conversion and raster operations are long-running and CPU-bound. The GeoLibre sidecar implements a lightweight async job system without external message queues.
Job Lifecycle
# Simplified flow from conversion.py
def submit_conversion(request: ConversionRequest) -> JobState:
job_id = str(uuid.uuid4())
state = JobState(id=job_id, status="pending", ...)
_JOBS[job_id] = state
threading.Thread(
target=_run_conversion_job,
args=(job_id, request),
daemon=True
).start()
return state
The background thread:
- Spawns the managed runtime subprocess
- Streams stdout for progress messages
- Parses
__GEOLIBRE_CONVERSION_RESULT__or__GEOLIBRE_CONVERSION_ERROR__markers - Updates
_JOBS[job_id]with status, messages, and final result
Memory is bounded via MAX_RETAINED_JOBS = 100; completed jobs evict oldest entries first.
Polling-Based Client Interaction
Clients poll /conversion/jobs/{job_id} for state transitions:
curl http://127.0.0.1:8765/conversion/jobs/$JOB_ID \
-H "X-GeoLibre-Token: $GEOLIBRE_SIDECAR_TOKEN"
Response schema includes status (pending|running|succeeded|failed), messages (progress log), and result (final output metadata on completion).
Optional Dependencies and Extras Installation
The sidecar's pyproject.toml defines modular extras for selective capability enablement:
[project.optional-dependencies]
conversion = ["duckdb>=1.1.0", "rio-cogeo>=5.0.0", "freestiler>=0.1.0", ...]
vector = ["geopandas", "shapely"]
raster = ["rasterio"]
sedona = ["apache-sedona[db]"]
ml = ["samgeo-api"] # client-only; model server external
whitebox = ["whitebox-workflows"]
Install patterns:
# Core sidecar only
pip install -e .
# With conversion tools
pip install -e ".[conversion]"
# Full geoprocessing stack
pip install -e ".[conversion,vector,raster,sedona,whitebox]"
Router endpoints dynamically respond to availability; the UI queries /conversion/status, /sql/status, and /ml/status to enable or disable features.
Complete Endpoint Reference
| Method | Path | Description | Router |
|---|---|---|---|
GET |
/health |
Service readiness | Core |
GET |
/algorithms |
Placeholder algorithm registry | Core |
POST |
/shutdown |
Graceful termination | Core |
GET |
/conversion/status |
Runtime availability | Conversion |
POST |
/conversion/vector-to-geoparquet |
Shapefile/GeoJSON → GeoParquet | Conversion |
POST |
/conversion/vector-to-flatgeobuf |
ZIP shapefile → FlatGeobuf | Conversion |
POST |
/conversion/csv-to-geoparquet |
CSV with lon/lat → GeoParquet | Conversion |
POST |
/conversion/vector-to-pmtiles |
Vector → PMTiles via freestiler | Conversion |
POST |
/conversion/raster-to-cog |
GeoTIFF → Cloud-Optimized GeoTIFF | Conversion |
GET/POST |
/conversion/jobs/{id} |
Job status polling and control | Conversion |
GET |
/whitebox/status |
WhiteboxTools runtime check | Whitebox |
POST |
/whitebox/run |
Execute WhiteboxTools command | Whitebox |
GET |
/raster/status |
rio-cogeo availability | Raster |
POST |
/raster/to-cog |
Raster COG conversion | Raster |
GET |
/postgis/status |
Connection pool health | PostGIS |
POST |
/postgis/connect |
Register whitelisted PostGIS server | PostGIS |
GET |
/sql/status |
SedonaDB engine availability | SQL |
POST |
/sql/run |
Execute spatial SQL | SQL |
GET |
/ml/status |
SamGeo proxy reachability | ML |
POST |
/ml/segment/* |
SAM 3 segmentation endpoints | ML |
Typical Usage Flow
-
Desktop launcher spawns
geolibre-serverwithGEOLIBRE_SIDECAR_TOKENset; binds to127.0.0.1:8765 -
Health probe — UI polls
/healthuntil{"status":"ok"} -
Capability detection — Parallel queries to
/*/statusendpoints determine enabled features -
Job submission — POST to conversion endpoint returns
job_idimmediately; work continues in background thread -
Progress monitoring — Client polls
/conversion/jobs/{id}at interval, updating UI withmessagesarray -
Result retrieval — On
status: succeeded, client readsresult.output_pathfor generated file location -
Cleanup — Desktop app calls
POST /shutdownon exit; sidecar terminates cleanly
Summary
-
The GeoLibre Python sidecar is a FastAPI application providing secure, local access to heavyweight geoprocessing libraries that cannot run in browser or Tauri contexts
-
Security layers include per-launch token authentication, trusted host validation, and restricted CORS—implemented in
main.pylines 37–110 -
Seven router modules organize tools by domain: WhiteboxTools, conversion, raster, vector, PostGIS, Apache Sedona SQL, and SamGeo ML proxy
-
uv-managed runtimes isolate heavy dependencies (DuckDB, rio-cogeo, freestiler) in cached virtual environments, bootstrapped on demand via
conversion.py -
Asynchronous job execution uses in-memory state with background threads, bounded retention, and polling-based client interaction
-
Optional extras in
pyproject.tomlenable selective installation; routers degrade gracefully when dependencies are absent
Frequently Asked Questions
What is the default port for the GeoLibre Python sidecar?
The sidecar binds to 127.0.0.1:8765 by default. This loopback-only binding, combined with TrustedHostMiddleware, prevents external network access. The port is not currently configurable without source modification.
Why does the sidecar use a reverse proxy for SamGeo instead of loading PyTorch directly?
The ML router in geolibre_server/app/ml.py forwards requests to an external SamGeo server to keep the sidecar memory footprint small and startup time fast. Loading PyTorch and the SAM 3 model would add gigabytes to the runtime and complicate cross-platform distribution. This architecture lets the SamGeo server run on GPU hardware while the sidecar remains CPU-only.
How does the conversion job queue handle failures and retries?
Failed jobs capture __GEOLIBRE_CONVERSION_ERROR__ markers from subprocess stderr, storing the error message in JobState.messages. The sidecar does not implement automatic retry; clients receive status: failed and must resubmit. Successful and failed jobs persist in _JOBS until MAX_RETAINED_JOBS eviction, allowing post-hoc debugging.
Can I run the sidecar without the GeoLibre desktop application?
Yes. Set GEOLIBRE_SIDECAR_TOKEN to any value for development mode where token checks are skipped, or provide a consistent token via environment variable for scripted access. The README in backend/geolibre_server/README.md documents manual startup with python -m geolibre_server.app.main or uvicorn.
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 →