philippine statistics authority · geospatial data management & engineering
an open geospatial
data portal
bnhr.xyz
--- ## Contents 1. The Discovery Problem 2. Spatial Data Infrastructure 3. GeoNode 4. Demo --- ## Retrieval practice *Without looking at your notes:* What is the difference between **WMS** and **WFS**? Note: No slides. Prompt on the board. 2 min individual write, cold-call 3–4 people. 2–3 min correction only. Expected: WMS = rendered image, use for display (show where aquafarms are on a map); WFS = raw features, use for analysis/download (download aquafarm geometries for a spatial join in QGIS). ---
the discovery
problem
--- ## 50 layers in GeoServer — can you answer these questions? - What years does `aquafarm` cover? - Who collected the `mango` data? - Is `aquafarms` licensed for use in published reports? - Which layer covers only Region II? GeoServer cannot answer any of these. It publishes data. It says nothing *about* it. Note: This is the motivation for GeoNode. PostGIS solved version chaos (Day 1). GeoServer solved sharing (Day 2). Today's question: how does anyone find the data, understand it, and know whether to trust it? Note: GeoServer does have a metadata plugin — but it is an admin-side tool, not a user-facing catalog. Users still need direct GeoServer access to read those fields, and there is no search, no browse, and no download button for end users. --- ## The same gap looks different depending on your role
Custodian
I published 50 layers in GeoServer. But no one knows they exist. No one knows which version is current. No one knows who to call when something is wrong.
User
I found `psa:aquafarms` in GeoServer. But I don't know what's in it. I don't know if it covers my region. I don't know if I can cite it in a report.
Note: GeoServer was built for service administrators. GeoNode was built to be the user-facing front door to the same data. Both the custodian problem (no one can find my data) and the user problem (I can't evaluate this data) are solved by the same thing: a catalog that makes layers discoverable, describable, and self-service. --- ## GeoNode is a catalog; GeoServer is a service endpoint
| Task | GeoServer | GeoNode | |---|---|---| | **Browse available layers** | Layer Preview list — layer names only | Catalog with titles, thumbnails, categories | | **Search by keyword** | Not available for simple users | Full-text search: title, abstract, tags | | **Filter by region or date** | Not available | Spatial filter, date range, category filter | | **Metadata** | Available via plugin | Built-in as core component of the catalog | | **Read what the data contains** | Layer name, CRS, bounding box| Title, abstract, owner, license, revision date, other metadata | | **Preview before downloading** | Basic OpenLayers viewer (permitted accounts) | Interactive map preview on any resource page | | **Layer access** | Managed by user/group/roles | Managed by users/group | | **Download the data** | Via WFS | Via web UI |
Note: GeoServer's Layer Preview is intended for administrators verifying that a layer published correctly — not for analysts deciding whether to use the data. GeoNode's catalog is the tool for that. Both point at the same PostGIS tables and the same GeoServer endpoints; GeoNode adds the discovery and governance layer on top. --- ## Adding a layer in QGIS: GeoServer path vs GeoNode path
GeoServer path
1. Get the OGC (WMS or WFS) URL from an admin 2. Layer → Add WMS/WMTS Layer → paste URL → Connect 3. Browse a flat list of layer names — no titles, no descriptions, no dates 4. Add the layer — no context on what it contains or who owns it
GeoNode path
1. Install the QGIS GeoNode Plugin. 2. Connect a GeoNode instance via the QGIS GeoNode plugin in the Data Source Manager. 3. Search for a layer (e.g. `aquafarms`) 4. Click result → read title, abstract, date, owner, license 5. Load layer to QGIS (WMS, WFS, etc) — with full understanding of what you are adding
Note: After step 3 in both paths, the QGIS workflow is identical — you are connecting to the same GeoServer WMS endpoint. The difference is that the GeoNode path gives the user enough information to decide whether to use a layer before they add it. From a custodian's perspective, publishing through GeoNode means users arrive informed rather than blind. ---
spatial data
infrastructure
--- ## An SDI has five components — not just a technology stack | Component | What it is | |---|---| | **Data** | The spatial datasets — PostGIS, GeoPackages, rasters | | **Services** | OGC endpoints for access — WMS, WFS, WMTS from GeoServer | | **Metadata** | Descriptions of the data: coverage, date, owner, CRS, license | | **Policies** | Rules governing access, usage constraints, data retention | | **People** | Roles responsible for each layer: owner, custodian, admin | Note: An SDI is an organizational framework, not a piece of software. National examples: Philippines PhilGIS (built on GeoNode), EU INSPIRE directive, US NSDI. The key insight: PostGIS + GeoServer give you the first two components. Days 1–2 completed those. Today adds the rest. --- ## PostGIS and GeoServer cover two components — GeoNode completes the SDI
PostGIS: x, , , , GeoServer: , x, , , GeoNode: x, x, x, x, x
Note: GeoNode doesn't replace PostGIS or GeoServer — it wraps them and adds the missing three components. Every GeoNode layer is a GeoServer layer. Every GeoNode upload goes into PostGIS. ---
metadata
--- ## How would you feel if you saw this | Data | Abstract | |---|---| | Aquafarm | Aquafarm data | | Mango | Mango data | --- ## Six metadata fields every PSA AFCD layer must have
| Field | What it captures | |---|---| | **Title** | Human-readable name — not a filename | | **Abstract** | What the data contains, how it was collected | | **Date** | Creation date and most recent revision | | **Spatial extent** | Bounding box — what area does this cover? | | **Point of contact** | Who to call if the data is wrong or unclear | | **License** | How the data may be used and shared | *GeoNode supports different metadata standards (e.g. ISO 19115, FGDC) and you can even create your own metadata models.*
Note: ISO 19115 is the international standard for geographic information metadata. GeoNode's metadata editor maps directly to these fields. --- ## Good metadata is written for someone who has never seen the dataset
Bad abstract
`aquafarm_poly` Aquafarm data.
Good abstract
Polygon locations of licensed aquaculture farms in the Philippines, collected by PSA AFCD regional offices during the 2024 census cycle. Coverage: all coastal regions. Use for aquaculture planning and fisheries statistics.
Note: Write the bad abstract first on screen, ask the room: "Would you use this data in a report? Would you trust it?" Then write the good one. The contrast is what makes the standard concrete. The good abstract answers: what, how collected, when, where, and for what purpose. ---
geonode
--- ## GeoNode adds capabilities on top of GeoServer and PostGIS - **Catalog** — searchable index of all layers, maps, and documents - **Upload and publish** — drag-and-drop to PostGIS + GeoServer in one step - **Map composer** — browser-based map builder using MapStore2 - **Dashboards and GeoStories** — create dashboards and geostories (think storymaps) - **User and group management** — roles, permissions, public/private/org visibility - **GeoServer integration** — GeoNode controls GeoServer via its REST API; every GeoNode layer is a GeoServer layer Note: GeoNode is built on Django, uses GeoServer as its service backend, and stores metadata and user data in PostgreSQL. The Docker stack runs all four together. --- ## GeoNode replaces every ArcGIS Online portal component
| ArcGIS Online | GeoNode | |---|---| | Portal / item browser | GeoNode catalog (search, browse, filter) | | Item detail page | Resource detail page (metadata, preview, download) | | Hosted feature layer (upload) | Upload → auto-imported to PostGIS + GeoServer | | Web map | GeoNode map composer | | Groups and sharing settings | GeoNode groups + layer permissions |
Note: Migration path: export AGOL item → upload to GeoNode → fill metadata → set permissions → add to a GeoNode map. The WMS/WFS service URL is the same GeoServer endpoint GeoNode manages automatically. --- ## GeoNode connects several containers in the Docker stack - **GeoNode** (Django) — catalog, UI, user management, metadata editor - **GeoServer** — service backend; GeoNode controls and interacts with it - **PostgreSQL / PostGIS** — stores both spatial and non-spatial data - **Nginx** — reverse proxy: `localhost/` → GeoNode, `localhost:8080/` → GeoServer - **LetsEncrypt** - SSL/TLS certificates - **Celery** - asynchronous engine/task system - **Redis** (GeoNode 5.X) - Celery backend - **RabbitMQ** (<= GeoNode 4.X) - Celery backend Note: The key question participants will ask: "Is this the same GeoServer from Day 2?" Yes. GeoNode manages the same instance. Layers published directly in GeoServer are not automatically in GeoNode — they must be imported via Remote Services (shown in Demo Part 2). The recommended workflow going forward: always upload through GeoNode, not directly to GeoServer. --- ## One upload triggers three updates at once
Upload, PostGIS, GeoServer, catalog
Note: This is what makes GeoNode the recommended entry point for all future data. One action keeps PostGIS (the authoritative store), GeoServer (the service layer), and the catalog (the discovery layer) all in sync. --- ## Uploading a layer to GeoNode Resources → Upload layer → select file → Upload - **Supported formats:** GeoPackage, Shapefile (zipped), GeoJSON, KML, CSV with coordinates - GeoNode imports the file into **PostGIS** automatically - GeoNode calls the **GeoServer REST API** to publish the layer - The layer appears immediately in the **catalog**, the database, and GeoServer One upload — three systems updated at once. Note: Narrate: "I'm not opening GeoServer. I'm not running ogr2ogr. One form, one button." The progress bar shows each step — PostGIS import, GeoServer publish, catalog index. For large files (>100 MB), bulk-load via ogr2ogr into PostGIS first, then import the existing GeoServer layer via Remote Services. --- ## Uploading a layer: GeoNode vs GeoServer
GeoNode
1. Resources → Upload layer 2. Drag file → Upload 3. Fill metadata → Save PostGIS, GeoServer, and the catalog update automatically. No GeoServer admin access needed.
GeoServer
1. Load data into PostGIS manually (`ogr2ogr`) 2. Data → Stores → Add new store → PostGIS 3. Data → Layers → Publish layer 4. Set CRS and bounding box Layer is in GeoServer only — not in the catalog.
Note: The GeoServer path requires four separate steps and admin access to the GeoServer UI. GeoNode collapses this into one upload form. The result in GeoServer is identical — GeoNode calls the same REST API behind the scenes — but the entry point is one screen instead of four. --- ## Adding a style to a layer in GeoNode On the layer resource page → Edit → Styles Two paths: - **Upload an SLD file** — style in QGIS → Layer Properties → Symbology → Style → Save as SLD → upload directly on the GeoNode layer page - **Use the browser style editor** — CSS-like editor for simple colour and symbol changes Set as default → the WMS service reflects the new style immediately. No GeoServer admin login required. Note: The QGIS → SLD export path is the standard workflow — participants have already done this in Day 2. The browser editor is useful for quick adjustments. Either way, GeoNode calls GeoServer's REST API to create and assign the style automatically. --- ## Adding a style: GeoNode vs GeoServer
GeoNode
1. Open the layer resource page 2. Edit → Styles → Upload SLD 3. Set as default → Save Any user with edit permission can update the style — no admin access needed. WMS reflects the change immediately.
GeoServer
1. Styles → Add new style 2. Upload `.sld` → Validate → Submit 3. Layers → select layer → Publishing tab 4. Default Style → select → Save Requires GeoServer admin access. Styles and layers are managed on separate screens.
Note: The underlying mechanism is identical — GeoNode calls GeoServer's REST API to create and assign the style. The difference is access: GeoNode exposes style management to any authorised layer editor, without requiring GeoServer admin credentials. --- ## Managing permissions on GeoNode On any resource page → Edit → Permissions | Level | Who | What they can do | |---|---|---| | **Public** | Anyone, no login required | View only | | **Registered users** | Any logged-in user | View and download | | **Groups** | Named group (e.g. `afcd_staff`) | View, download, edit, manage | Individual users can also be granted permissions directly. Note: This maps directly to the AFCD governance framework: public layers (admin boundaries, basemaps), registered-user layers (statistical tables), group-restricted layers (aquafarm coordinates, production-sensitive data). The data custodian sets permissions directly — no admin involvement needed for routine access changes. --- ## Managing permissions: GeoNode vs GeoServer
GeoNode
Per-resource permissions set on the layer page. Levels: public, registered users, named groups, individuals. Any layer owner can set permissions — no admin required. Enforced across catalog, WMS/WFS endpoints, and downloads.
GeoServer
Workspace- or layer-level security rules set in the admin panel. Roles mapped to `ROLE_*` entries or an external directory. Requires GeoServer admin access to configure. Enforced on WMS/WFS endpoints only — no catalog or download context.
Note: GeoServer's security model is powerful but requires admin involvement for every change. GeoNode delegates permission management to layer owners — the person responsible for the data controls who can access it. This makes governance operational rather than procedural. --- ## Traffic light check-in
1. I can name all five components of a Spatial Data Infrastructure. 2. I understand why metadata is needed for data to be discoverable and trustworthy. 3. I understand how GeoNode connects to GeoServer and PostGIS. 4. I can describe what happens in the system when I upload a file through GeoNode. 5. I can upload and style a layer in GeoNode. 6. I understand how GeoNode permissions work. **Green** = confident | **Yellow** = mostly | **Red** = still unclear
Note: Hands or sticky notes. If more than 1/3 of the room is red or yellow on statement 3 (architecture connection), trace the four-container diagram before opening the demo. Statement 4 checks pipeline comprehension — re-run the upload slide if needed. Statements 5–6 are the governance angle; if red, revisit the permissions slide before Demo Part 2. ---
demo | builders
deploy geonode
with docker
--- ## Before you start — what you need - **Git** — to clone the project - **Docker** (v20+) and **Docker Compose** — to run the containers - **Python 3** — to generate the `.env` configuration file - ~**4 GB RAM** free for the Docker containers - **Port 80** available — Nginx will bind to it Check Docker is running before proceeding: `docker info` Note: If port 80 is in use by another web server, stop it first or change NGINX_BASE_URL in the .env file. Compose v2 is bundled with Docker Desktop; on Linux install it separately with `apt install docker-compose-plugin`. --- ## Step 1 — Clone geonode-project ```bash git clone https://github.com/GeoNode/geonode-project.git -b [your_branch] cd geonode-project ``` - `geonode-project` is a ready-to-deploy Django project wired up with Docker Compose. Clone it, configure it, and run it — no scaffolding needed. - You can change which version of GeoNode you want to build by changing the `[your branch]` part of the git clone command. - **NOTE:** different versions may have different installation instructions. For this exercise, we will be using the `master` branch so you can remove the -b [your_branch] part when running git clone. - **For production**, fork the repo to your own organisation first so you can rename the folder and version-control your configuration. For this training, cloning directly is fine. --- ## The .env file holds all configuration `create-envfile.py` generates it from your parameters: - **Hostname** — where GeoNode will be served (`localhost` for local use) - **Passwords** — GeoNode admin, GeoServer admin, two PostgreSQL databases - **OAuth2 credentials** — `clientid` and `clientsecret` for GeoServer-to-GeoNode authentication All secrets go into `.env`. Docker Compose reads it at startup. **Never commit `.env` to version control.** Note: The .env.sample file in the repo shows every available option with defaults. For a training environment the simple passwords in the next slide are fine. For production, use `openssl rand -hex 32` to generate each password. --- ## Step 2 — Generate the .env file - Create `.env` with random values for parameters ```bash python create-envfile.py ``` - Create `.env` with provided parameters ```bash python create-envfile.py \ --hostname localhost \ --geonodepwd admin \ --geoserverpwd geoserver \ ... ``` - Copy the `.env.sample` -> rename it `.env` -> edit the parameter values Note: Random values are generated for any parameter you omit, except hostname. The clientid and clientsecret are used by GeoServer to authenticate back to GeoNode's OAuth2 endpoint — they must match on both sides, so set them explicitly here. --- ## Step 3 — Build and start ```bash docker compose build --no-cache docker compose up -d ``` - `build --no-cache` — pulls base images and builds fresh; **5–15 min** on first run - `up -d` — starts all containers in the background - Verify with `docker compose ps` — every service should show `Up` Note: If `docker compose` is not recognised, try `docker-compose` (with hyphen) for older installs. The first build downloads ~2 GB of base images. If a container shows "Exited", check its logs: `docker compose logs
`. The most common cause is a misconfigured .env. --- ## Containers that power the stack
| Container | What it does | Exposed | |---|---|---| | `db` | PostgreSQL / PostGIS — stores GeoNode metadata and spatial layers | internal | | `geoserver` | GeoServer — serves WMS, WFS, WMTS for all published layers | internal | | `django` | GeoNode Django app — catalog, UI, upload, user management | internal | | `geonode` | Nginx reverse proxy — routes `/` to Django, `/geoserver` to GeoServer | **:80** | | `celery` | Background task worker — handles uploads, thumbnails, indexing | internal | | `redis (5.X) or rabbitmq` | Message broker between Django and Celery | internal |
Note: Only Nginx (port 80) is exposed to the host. All other containers communicate on an internal Docker network. GeoServer is not directly reachable from the browser — all requests go through Nginx, which proxies to the right container based on the URL path. --- ## Check if GeoNode is running | Account | URL | Username | Password | |---|---|---|---| | GeoNode | `http://localhost` | value in `.env` file | value in `.env` file | | GeoServer | `http://localhost/geoserver/web` | value in `.env` file | value in `.env` file | Log in to GeoNode and confirm the catalog loads. The stack is ready for the next demo. **NOTES**: - GeoServer may take 1–2 minutes longer than GeoNode to be fully ready — if the GeoServer page returns a 502, wait and reload. - If localhost does not load at all: check `docker compose ps` (all Up), check `docker compose logs [name-of-container]` for errors, and confirm no firewall is blocking the appropriate ports. Note: GeoServer may take 1–2 minutes longer than GeoNode to be fully ready — if the GeoServer page returns a 502, wait and reload. If localhost does not load at all: check `docker compose ps` (all Up), check `docker compose logs geonode` for Nginx errors, and confirm no firewall is blocking port 80. ---
questions?
---
demo | managers • users
uploading layers
---
demo | managers • users
styling layers
---
demo | managers • users
maps
---
demo | managers • users
dashboards
---
demo | managers • users
geostories
---
demo | managers
admin panel
---
demo | managers
simple theming
---
demo | managers
managing users & groups
---
demo | managers
managing layers & permissions
---
demo | managers
geonode management commands
---
demo | users
connecting geonode to qgis
---
demo | managers
geonode api
--- ## Exit ticket
*Let's check how we're doing* 1. How clear was this session for you? 2. How confident are you to try this on your own? 3. Which topic did you find most difficult or confusing? 4. In one word — what's your reaction to what we just covered? 5. What is your biggest question right now? 6. How would you share data with your colleague using GeoNode?
--- #
Questions?