Deployment Capabilities¶
A deployment can pin what the app it serves is allowed to do — a read-only kiosk, a classroom instance, and everything between that and the full app.
Capabilities are coarse on purpose. Each one names a whole class of action ("may add data at all"), not an individual menu item, so a locked-down deployment cannot be defeated by one item somebody forgot to list.
This is a client-side gate, not an authorization boundary
Withholding a capability removes the affordance: the menu is not rendered, the command palette does not list or run the action, the keyboard shortcut does nothing, and the embed API refuses the command. It does not stop someone with browser devtools, and it does not restrict the server.
The sidecar (/sidecar) and AI proxy (/ai) endpoints answer the same
requests whatever capabilities are configured. For a deployment that must
hold up against its own users, keep the server-side protections in
Self-Hosting — Basic Auth or a real auth proxy,
GEOLIBRE_CONVERSION_ROOTS, GEOLIBRE_DISABLE_SIDECAR — and treat
capabilities as the interface half of the story.
Not the same as UI Profiles¶
UI Profiles also hide menus and items, and the two run independently. The difference is who decides:
| UI Profiles | Deployment capabilities | |
|---|---|---|
| Purpose | Reduce clutter for the audience | Pin what the deployment permits |
| Set by | The user, or an admin-profile.json |
The build/deployment configuration |
| Reversible in the app | Yes, from Settings → Interface (unless lock is set) |
No — never surfaced in the UI |
| Granularity | Individual items, data sources, plugins | Whole capabilities |
Where both apply, the capability is checked first. An action the deployment withheld is never on offer, whatever the profile says.
The capabilities¶
| Capability | Grants |
|---|---|
project:edit |
Authoring the project: New, Open, Open Recent, Import, Project History, Save, Save As, Duplicate, Save as Template, Collaborate, StoryMap; Undo/Redo (the menu items and the Ctrl/Cmd+Z and Ctrl+Y shortcuts); Export Selection; adding a review comment; the embed API's loadProject. |
data:add |
Bringing data in: the whole Add Data menu, dragging a file onto the map (browser and desktop), and the embed API's addLayer and addData. |
processing:run |
The whole Processing menu — Whitebox, SQL, Python, the AI assistant, geocoding, Model Builder, conversion/vector/raster tools — and the embed API's openTool. |
export:data |
Getting data or a rendering back out: Share, Export HTML, Print, Print Layout, Offline Basemap, and the embed API's exportImage. |
plugins:install |
The Plugins menu, plugin-registered toolbar menus, activating or deactivating a plugin, and the plugin marketplace ("Manage plugins"). |
settings:manage |
The Settings dialog and the Style Manager. |
Anything not listed is unprivileged and stays available in every configuration: panning and zooming, the View and Controls menus, layer visibility and ordering, identify, the selection tools, and Help.
Configuring it¶
Set VITE_GEOLIBRE_CAPABILITIES to a comma-separated list of the capabilities
you want to grant, at build time:
VITE_GEOLIBRE_CAPABILITIES="data:add,processing:run,export:data" npm run build
For the Docker image, pass it as a build argument:
docker build \
--build-arg VITE_GEOLIBRE_CAPABILITIES="data:add,processing:run,export:data" \
-t geolibre-classroom .
Build time only, for now
Unlike GEOLIBRE_SHARE_URL, GEOLIBRE_EMBED_ORIGINS, and the other
deployment settings, this cannot yet be set with -e on a prebuilt
image — docker/entrypoint.sh does not publish it into the runtime
configuration, so it has to be baked in. Configuring a published image with
-e GEOLIBRE_MODE=kiosk, and having nginx refuse the corresponding
requests, is tracked in
#1673.
Defaults and parsing¶
- Unset (the default) grants everything. An existing deployment that configures nothing behaves exactly as it did before.
- Setting it at all is a restriction. Only the capabilities you name are granted; everything else is withheld.
- Unknown names are dropped, not granted. A build that does not recognize a capability treats it as ungranted rather than failing to start, so a config written for a newer version does not quietly widen an older one.
- The parse fails closed. A value that names nothing recognizable grants nothing at all, rather than falling back to the full set.
- A blank value reads as unset, and so grants everything. An empty string
is what
-e VAR=produces, and unset has to keep meaning "full". To grant nothing, writenone(see below) rather than leaving the value empty.
Examples¶
A kiosk or exhibit terminal — open the configured project, pan, zoom, toggle
layers, identify, and nothing else. none is the reserved spelling for an
empty grant:
VITE_GEOLIBRE_CAPABILITIES=none npm run build
The same kiosk, but visitors may save a picture of what they are looking at:
VITE_GEOLIBRE_CAPABILITIES="export:data" npm run build
A classroom instance — the full map and processing tools, but no plugin installs and no settings:
VITE_GEOLIBRE_CAPABILITIES="project:edit,data:add,processing:run,export:data" \
npm run build
An embedded map on a public site that should not become a general-purpose
data-fetching proxy for the page framing it. With none, the embed API refuses
loadProject, addLayer, addData, openTool, and exportImage, while
setView, highlight, and the layer-visibility commands keep working — so the
host page can still drive the map without being able to load anything into it.
Embed API behavior¶
A denied command rejects rather than silently doing nothing, so the host page can tell the difference between "refused" and "no effect":
await map.addData({ url: "https://example.com/data.geojson" });
// Error: Missing data:add capability
See Embedding & Sharing for the full command list.
The embed origin allowlist (GEOLIBRE_EMBED_ORIGINS) and capabilities are
independent: the allowlist decides who may send commands, capabilities decide
which commands exist.
Related pages¶
- Self-Hosting — the server-side protections this does not replace
- UI Profiles — non-destructive interface filtering
- Embedding & Sharing — the embed API and its origin allowlist
- Getting Started — the full container configuration list