A lightweight HTTP server for serving static content directly from the Guardian Connector data lake (or any mounted volume).
This service runs a minimal BusyBox httpd web server and exposes files stored within the Guardian Connector data lake over HTTP. It is particularly useful for hosting custom HTML, JavaScript, CSS, images, or other static assets that interact with data already managed by Guardian Connector.
By default, the container mounts the Guardian Connector data lake and serves files directly from it.
The service supports the following environment variables:
| Env var | Required | Default | Purpose |
|---|---|---|---|
DIRECTORY |
yes | — | App subdirectory under the datalake to serve at / |
DATA_DIRECTORY |
no | — | Additional subdirectory exposed at /data/ |
AUTH_ENABLED |
no | false |
true requires an Auth0 login before any file is served |
Host layout (CapRover default): /mnt/persistent-storage/datalake/{DIRECTORY}
When DATA_DIRECTORY is configured, the server creates a temporary document
root containing links to the app files and the selected data directory. The
source directories are not modified, and no other datalake directories are
exposed.
For example:
DIRECTORY=my_app
DATA_DIRECTORY=comapeo_data
serves the app at / and its selected data at /data/.
One of Guardian Connector's goals is to allow communities and organizations to control their own data and the applications built around it.
Users can upload files or entire directories into the data lake using tools such as File Browser. Once uploaded, this HTTP server can simply be pointed at that directory, immediately making those files available over HTTP without requiring another deployment pipeline.
When deployed through CapRover, access can be restricted either with this server's Auth0 login or with CapRover's HTTP Basic Auth. Use one of those controls, not both. Auth0 gives each approved Guardian Connector user their own login. Basic Auth uses one shared username and password.
This creates a simple workflow:
- Upload files into the Guardian Connector data lake.
- Point the HTTP server at that directory using
DIRECTORY. - Access the application through the web.
Guardian Connector already provides tools such as GC Explorer for visualizing ingested datasets.
However, sometimes a project requires a completely custom experience—a presentation-quality map, a storytelling application, or a bespoke dashboard tailored to a particular audience.
In that case, you can:
- Ingest field data using GC Scripts Hub (for example, CoMapeo observations).
- Create your own HTML and JavaScript application using Leaflet, Mapbox GL JS, OpenLayers, or any other frontend framework.
- Upload the application into the Guardian Connector data lake using File Browser.
- Configure this HTTP server to serve that directory.
Your application can then load and visualize the same Guardian Connector data while remaining entirely user-controlled. Both the underlying datasets and the web application itself live inside the Guardian Connector data lake, providing a lightweight and flexible way to build custom exploration experiences without requiring additional infrastructure.
This repository is for a unique data exploration or analysis experience that the standard applications deployed on Guardian Connector (i.e. Superset and GC Explorer) cannot provide.
Before adding an application to a Guardian Connector instance, carefully consider the overhead of maintaining it. A developer or technical support partner has to understand the code, keep it working as the data and the stack change, and support the people who use it. That cost is highest for a one-off built for a single project. Code generated by a LLM carries the same obligation and risk.
One suggested litmus test is to ask yourself if the user experience you are designing is not already possible with one of core Guardian Connector applications, or, if there is not already an existing application that we might consider adopting.
Set AUTH_ENABLED=true to require login before any mounted file is served. In this mode oauth2-proxy is the only server process: it handles Auth0 and reads the selected directory itself. /, nested assets, and /data/ all require a session. /ping and /ready stay open so the container can report health, and /oauth2/ is reserved for login, callback, and logout.
An anonymous browser request is redirected to Auth0. It does not receive the file. A request that sends Accept: application/json gets 401 instead of a redirect. The ID token must include Member or Admin in urn:gc:roles, the claim the tenant's Add Roles Claim Post-Login action copies from the user's Auth0 roles. Guest, SignedIn, and a missing claim are refused with 403 and no session cookie. Check Approval can still deny login before a token is issued. An unverified email does not deny a Member or Admin.
Create one Auth0 Regular Web Application for each public site:
| Auth0 setting | Value |
|---|---|
| Allowed Callback URLs | https://<host>/oauth2/callback |
| Allowed Logout URLs | https://<host>/ |
| Allowed Web Origins | https://<host> |
| Connections | The tenant's existing database and Google connections |
No Auth0 Management API scopes are required. Roles are read from the ID token claim urn:gc:roles.
| Env var | Required when Auth0 is enabled | Purpose |
|---|---|---|
OAUTH2_PROXY_OIDC_ISSUER_URL |
yes | Issuer from the tenant's /.well-known/openid-configuration, including its trailing slash. Example: https://<tenant>.us.auth0.com/ |
OAUTH2_PROXY_CLIENT_ID |
yes | Auth0 application client ID |
OAUTH2_PROXY_CLIENT_SECRET |
yes | Auth0 application client secret |
OAUTH2_PROXY_REDIRECT_URL |
yes | https://<host>/oauth2/callback |
OAUTH2_PROXY_COOKIE_SECRET |
yes | 32-byte secret used to sign the session cookie |
OAUTH2_PROXY_COOKIE_SECURE |
no | Defaults to true. Set false only for local http:// testing |
Generate a cookie secret with:
openssl rand -base64 32 | tr '+/' '-_'On CapRover, enable Force HTTPS. Leave CapRover HTTP Basic Auth off; the two prompts conflict, and Basic Auth would sit in front of the Auth0 redirect.
/oauth2/sign_out clears the site session. The Auth0 session can still silently sign the same browser back in. To end that session too, link to:
/oauth2/sign_out?rd=<urlencoded https://<tenant>.us.auth0.com/v2/logout?client_id=<client-id>&returnTo=https://<host>/>
returnTo must match an Auth0 Allowed Logout URL. The tenant host is already allowed as a post-login redirect target.
Authenticated files use Go's built-in content types. mime.types adds the font, Markdown, source-map, icon, and WebM types that BusyBox otherwise gets from httpd.conf. HTML, CSS, JavaScript, JSON, images, fonts, PDF, and common audio and video files are served with their usual types. Unauthenticated serving still uses BusyBox and httpd.conf.
docker build <YOUR_REGISTRY>/gc-http-server:latest .The image is about 66 MB because it includes oauth2-proxy. Without Auth0 it uses about 400 KB of memory; with Auth0 enabled it uses about 7 MB.
On a fresh CapRover VM the data UID/GID is usually 1000.
docker run -p 8080:8080 \
-e DIRECTORY=demo \
-e DATA_DIRECTORY=demo-data \
-v "$(pwd)/data_mount:/data_mount" \
<YOUR_REGISTRY>/gc-http-server:latestNote
Until this image is available publicly i.e. on Docker Hub, you need to build it yourself and host it on your own registry.
And, you need to add your Docker Registry to CapRover in the Cluster tab of the CapRover dashboard UI.
Prefer the one-click app in caprover/gc-http-server.yml.
It mounts the host datalake at /data_mount and asks for DIRECTORY plus an
optional DATA_DIRECTORY.
Manual (Method 6) — one-time Persistent Directories setup:
-
Push the image to your registry.
-
Create the app with Has Persistent Data.
-
Persistent Directories (set once, then leave alone):
- Path in App:
/data_mount - Path on Host:
/mnt/persistent-storage/datalake
- Path in App:
-
Environment Variables:
DIRECTORY=<your-folder> DATA_DIRECTORY=<optional-data-folder> AUTH_ENABLED=falseFor Auth0, set
AUTH_ENABLED=trueand supply the issuer, client ID, client secret, redirect URL, and cookie secret from Auth0 protection. -
Container HTTP Port:
8080. -
Deploy via ImageName.
To serve a different folder later, change DIRECTORY only — do not edit Persistent Directories.
DIRECTORY is required: set theDIRECTORYenv var.serve path does not exist: Path on Host must be the whole data lake (/mnt/persistent-storage/datalake), not a single subdirectory. ThenDIRECTORYselects the folder under it.data path does not exist:DATA_DIRECTORY, when set, must identify a directory beneath the mounted data lake.reserved path .../data: The app directory cannot contain a top-leveldataentry whenDATA_DIRECTORYis enabled because/data/is reserved.AUTH_ENABLED=true requires: the Auth0 client, issuer, redirect URL, and cookie secret must all be set.- Redirect or cookie-secure errors: a public CapRover site uses an
https://<host>/oauth2/callbackredirect and the default secure cookie.OAUTH2_PROXY_COOKIE_SECURE=falseis only valid with anhttp://redirect for local testing. - Login succeeds but the next request is anonymous: the callback URL, Auth0 Allowed Callback URL, and public host disagree, or the app is not using HTTPS while the cookie is marked secure.
- 403
Invalid session: unauthorized: the account has neither the Auth0 roleMembernorAdmin, or the login flow is not writingurn:gc:rolesonto the ID token. - 500 after Auth0 redirects back: the proxy error page hides the cause. The container log line is
Error redeeming code during OAuth2 callback.email_verified: falseis accepted. The callback reads email and roles from the ID token and does not call Auth0's userinfo endpoint. /pingor/readydoes not show a mounted file: those paths are health checks when Auth0 is enabled.