A Dockerised stack that runs GeoServer behind a Traefik reverse-proxy (with automatic HTTPS via Let's Encrypt) together with a lightweight React front-end for uploading and managing spatial data sources.
┌──────────────────────────────────────────────────────┐
│ Traefik :80 → redirect to HTTPS │
│ Traefik :443 (TLS – Let's Encrypt) │
│ ├─ /geoserver ──► GeoServer :8080 │
│ └─ / ──► Frontend :80 │
└──────────────────────────────────────────────────────┘
- Docker ≥ 24 and Docker Compose v2
- A public domain with an A record pointing to your server (required for Let's Encrypt)
- Ports 80 and 443 open on the server firewall
Copy and edit the environment file:
cp .env.example .env
# then edit .env with your domain, email and passwordsKey variables (set in .env at the project root):
| Variable | Default | Description |
|---|---|---|
DOMAIN |
amp-gis.dgstg.org |
Public domain for the deployment |
ACME_EMAIL |
admin@amp-gis.dgstg.org |
Email for Let's Encrypt notifications |
GEOSERVER_ADMIN_USER |
admin |
GeoServer admin username |
GEOSERVER_ADMIN_PASSWORD |
changeme |
GeoServer admin password – change this |
GEOSERVER_PROXY_BASE_URL |
https://amp-gis.dgstg.org/geoserver |
Public URL of GeoServer |
GEOSERVER_CSRF_WHITELIST |
amp-gis.dgstg.org |
Allowed CSRF origins |
PROXY_BASE_URL |
https://amp-gis.dgstg.org |
Top-level public base URL |
docker compose up -d --buildGeoServer data directory: On first start, Docker will create a
geoserver_data/folder in the project root and bind-mount it into the container at/opt/geoserver_data. All workspaces, stores, and uploaded files are persisted there and are directly accessible on the host.
| Service | URL |
|---|---|
| React front-end | https://amp-gis.dgstg.org/ |
| GeoServer web UI | https://amp-gis.dgstg.org/geoserver/web |
| Traefik dashboard | http://<server-ip>:8080/ (restrict in production) |
First boot: Traefik will automatically request a TLS certificate from Let's Encrypt
using the HTTP-01 challenge over port 80. This takes a few seconds.
The certificate is stored in theletsencryptDocker volume and auto-renewed.
HTTP → HTTPS redirect: Any request to
http://amp-gis.dgstg.orgis permanently
redirected tohttps://amp-gis.dgstg.orgby Traefik.
- Enter your GeoServer credentials in the credentials bar at the top (defaults:
admin/changeme). - Workspaces panel – create or delete workspaces.
- Upload Data Source panel – upload spatial data directly into a workspace:
- Shapefile – upload a
.zipcontaining.shp,.dbf,.shx, and (optionally).prjfiles. A bare.shpfile is not accepted on its own because GeoServer requires all companion files to be present. - GeoTIFF – upload a
.tif/.tiffraster file. - CSV – upload a comma-separated file (requires the GeoServer CSV store extension).
- GeoPackage – upload a
.gpkgvector/raster package.
- Shapefile – upload a
- Published Layers panel – browse layers in any workspace and open a quick WMS preview.
- Domain DNS A record points to the server IP
- Ports 80 and 443 are open in the firewall
-
GEOSERVER_ADMIN_PASSWORDis set to a strong password in.env - Port 8080 (Traefik dashboard) is firewalled or restricted to trusted IPs
Run the React app locally against a running GeoServer:
cd frontend
npm install
npm run dev # http://localhost:5173Vite automatically proxies /geoserver requests to http://localhost:8080 by default.
Override the target with the VITE_GS_TARGET env variable if GeoServer is running elsewhere:
VITE_GS_TARGET=http://my-geoserver:8080 npm run dev.
├── .env.example # Copy to .env and configure for your domain
├── docker-compose.yml # Traefik + GeoServer + React frontend (HTTPS)
└── frontend/ # React application (Vite)
├── Dockerfile # Multi-stage build → nginx image
├── nginx.conf # nginx SPA config
├── package.json
├── vite.config.js
├── index.html
└── src/
├── main.jsx
├── App.jsx
├── index.css
├── components/
│ ├── WorkspaceManager.jsx
│ ├── DataUploader.jsx
│ └── LayerList.jsx
└── services/
└── geoserverApi.js # GeoServer REST API helpers