Skip to content

Load the schema into Postgres

If you already run a Postgres / PostGIS server, you can install the Infrastructure Mapper schema into it directly — no Nix, no build step. End result: a fully populated gis (or whatever you name it) database that QGIS, web maps, and data-capture tools can read and write against.

Prerequisites

Requirement Tested against
PostgreSQL 14 or newer
PostGIS 3.x with topology and raster support optional
psql The standard PostgreSQL client, on the machine that loads the schema
tar Standard tar(1) to extract the release archive

If you don't have a Postgres handy, the postgis/postgis Docker image is the fastest path to one:

docker run --name im-pg \
  -e POSTGRES_PASSWORD=please-change-me \
  -e POSTGRES_DB=infrastructure \
  -p 5432:5432 \
  -d postgis/postgis:17-3.5

1. Download the schema

Every release on the GitHub Releases page publishes the schema as a single self-contained SQL file plus per-domain slices:

File Stable "latest" URL What it is
pg-schema-vX.Y.Z.sql pg-schema-latest.sql Everything — extensions, meta, all 13 domains, fixtures. Apply to an empty database to bootstrap the full schema.
pg-schema-NN-name-vX.Y.Z.sql pg-schema-NN-name-latest.sql One domain only — e.g. pg-schema-07-fencing-latest.sql. Self-contained; includes extensions, meta, that domain's tables, and the lookup-table fixtures it needs.
pg-fixtures-vX.Y.Z.sql pg-fixtures-latest.sql Data-only dump of lookup tables. Useful if you've already loaded the schema and want to refresh seed data.
pg-migrations-vX.Y.Z.tar.gz pg-migrations-latest.tar.gz Forward migrations from a previous baseline to this version. See Migrations for when to use these instead of a fresh load.
schema-diff-vX.Y.Z.sql schema-diff-latest.sql migra-generated diff vs the previous release — ALTER statements that would bring the prior version up to this one.

Pick whichever flavour you like — curl from the stable URL, or gh release download for the versioned filename:

# Composite (everything) — stable URL, always the latest release:
curl -LO https://github.com/kartoza/InfrastructureMapper/releases/latest/download/pg-schema-latest.sql

# Just one domain (example: fencing):
curl -LO https://github.com/kartoza/InfrastructureMapper/releases/latest/download/pg-schema-07-fencing-latest.sql

# Or, with versioned filenames via gh CLI:
gh release download --repo kartoza/InfrastructureMapper \
  --pattern 'pg-schema-v*.sql' \
  --pattern 'pg-fixtures-v*.sql'

2. Create your target database

createdb -h localhost -U postgres infrastructure
psql -h localhost -U postgres -d infrastructure \
  -c "CREATE EXTENSION IF NOT EXISTS postgis;"

Adjust the host / user / database name to match your environment. The schema only requires PostGIS — nothing else extra.

3. Apply the schema

The composite file is a single ordered SQL bundle — one psql invocation loads everything:

DB=infrastructure
psql -v ON_ERROR_STOP=1 -h localhost -U postgres -d $DB \
  -f pg-schema-latest.sql

ON_ERROR_STOP=1 is important — if any statement fails, the whole load aborts rather than leaving the schema half-applied.

Just one domain

The per-domain slices are equally self-contained — they bundle the extensions, meta layer, that domain's tables, and the lookup-table fixtures it needs. Loading pg-schema-07-fencing-vX.Y.Z.sql into an empty database gives you a working fence / fence_type / fence_conditions schema with no other domain present.

psql -v ON_ERROR_STOP=1 -h localhost -U postgres -d $DB \
  -f pg-schema-07-fencing-latest.sql

You can load several slices into the same database; they share the extensions and meta-layer DDL idempotently (CREATE TABLE IF NOT EXISTS), so re-running them after the first one is a no-op for the shared bits.

4. Verify

$PSQL -c "SELECT version FROM current_schema_version;"
--  version
-- ---------
--  v0.1.0

A row at the version you downloaded means the baseline + every released migration applied successfully.

5. Connect QGIS to your database

Once the schema is in Postgres, QGIS connects to it natively:

  1. Open QGIS, open the Browser panel (View → Panels → Browser).
  2. Right-click PostgreSQLNew Connection.
  3. Fill in the connection details:

    • Name — any friendly label, e.g. Infrastructure Mapper
    • Host — your server hostname or IP (localhost for the Docker example above)
    • Port — usually 5432
    • Databaseinfrastructure (or whatever you used)
    • Authentication — tick Basic and enter your username / password, or use a service file / Kerberos / SSL cert as appropriate
  4. Click Test Connection. Green ticks mean you're in. Click OK.

  5. Expand the new connection in the Browser panel. Every domain (infrastructure, electricity, water, …) shows up as a schema with its tables underneath.
  6. Drag any spatial table onto the canvas to add it as a layer. Lookup tables appear as aspatial entries you can use for table joins or attribute pick-lists.

Editing through QGIS

QGIS can edit Postgres data directly (toggle the pencil icon on the layer). The schema's last_update / last_update_by columns auto-stamp on update via triggers, so per-row provenance is preserved without you doing anything.

6. (Optional) Tighten access for production

The instructions above assume a single-developer setup. If you're deploying this to a team or to production:

  • Create a dedicated PostgreSQL role for the app and grant it USAGE on the schema, SELECT/INSERT/UPDATE on tables, and USAGE on sequences.
  • Keep the gen_random_uuid() default on every table — clients rely on it for UUID-stable sync to GeoPackages.
  • Put a regular pg_dump --clean on a cron alongside your other database backups. The schema is reproducible, but your captured data isn't.

What next?

  • Take a snapshot of your Postgres into a GeoPackage and into the field — see Field Workflow.
  • When a new version of the schema is released, apply pending migrations to your Postgres without reloading the whole baseline — see Migrations.
  • Browse the Data Model to see what each domain captures.