pgRouting 4.0.2 with PostGIS on AWS User Guide
Overview
This guide covers launching and verifying pgRouting 4.0.2 with PostGIS on Ubuntu 24.04 from cloudimg on Amazon EC2. It is one version of the cloudimg Hardened PostgreSQL 18, PostGIS & Postgres Extension AMIs listing on AWS Marketplace; you pick it as the software version when you subscribe and launch. The other PostgreSQL builds and extensions in the listing are described on the listing's guide hub.
pgRouting adds routing and network analysis to PostgreSQL and PostGIS. Your road, rail, pipe or cable network is an ordinary table of PostGIS LINESTRING edges with a cost per edge, and functions such as pgr_dijkstra, pgr_aStar, pgr_bellmanFord and pgr_drivingDistance answer "what is the shortest route from A to B?" or "what can I reach within 1 km?" in plain SQL. Results come back as rows you can join to your own data, or as PostGIS geometry you can hand straight to a web map.
The image installs PostgreSQL 18.6, PostGIS 3.6.4 and pgRouting 4.0.2, all unmodified official PostgreSQL (PGDG) packages. PostgreSQL and PostGIS come from the PGDG apt repository. pgRouting 4.0.2 is the current upstream release; PGDG's stable channel still carries 4.0.1, so the image installs PGDG's own 4.0.2 packages checked against pinned SHA-256 digests, and keeps only the stable channel enabled. Unattended upgrades are configured for the PGDG archive as well as Ubuntu, so later PostgreSQL, PostGIS and pgRouting releases keep arriving through apt.
What this image is not:
- No road data ships. The image carries a small synthetic demonstration network (Step 4) and nothing else. To route on real streets, load your own network, for example an OpenStreetMap extract (see "Loading your own network").
- Not a routing web service. There is no HTTP API, tile server or map UI. pgRouting is a SQL library inside the database; your application calls it.
- One PostgreSQL instance. No replication or clustering is configured.
What is on the image:
- PostgreSQL 18.6 (
postgresql@18-main.service) with the PostGIS 3.6.4 and pgRouting 4.0.2 extensions - A
routingdbdatabase withpostgisandpgroutingalready enabled, owned by the application roleroutingapp, holding the demonstration tablesrouting_edgesandrouting_vertices - A non-superuser application role
routingappand thepostgressuperuser; both passwords are generated on your instance's first boot - TLS with a certificate generated on your instance's first boot (TLS 1.2 minimum)
- A credential guard that runs on every boot and refuses to serve if a published or example password ever authenticates
Default user: ubuntu · Architecture: x86_64 · Root volume: 12 GiB gp3
Security posture
- No database ships in the image. The image contains no PostgreSQL cluster at all, so it carries no role, password, data or key from the build. First boot creates a fresh cluster, the
routingdbdatabase with the demonstration network and two different passwords, one forpostgresand one forroutingapp, and writes them to/root/pgrouting-credentials.txt, readable by root only. Locally,postgresis also reachable as thepostgressystem user (peer authentication). - Nothing is served before first boot finishes. PostgreSQL will not start until first boot has created the cluster, the certificate and the passwords. While it sets them, the server listens on its local socket only, with no TCP port.
- Per-instance TLS certificate. First boot creates this instance's own private key and self-signed certificate under
/etc/postgresql/18/main/and turns TLS on, so no two instances share a key. - Localhost only. PostgreSQL listens on
127.0.0.1:5432, and the listing's security group opens SSH (22) only. Reach the database through an SSH tunnel, or open it to your VPC as described in Step 8. - Remote connections require TLS.
pg_hba.confaccepts non-loopback clients only overhostsslwithscram-sha-256and rejects plain-text remote connections; there is notrustrule. - No metadata access for the database. A database user can make PostgreSQL open outbound connections (for example
COPY ... FROM PROGRAMas a superuser, or PostGIS raster network drivers if you enable them), so every PostgreSQL unit and both first-boot services are blocked from reaching the instance metadata service (169.254.169.254 and fd00:ec2::254). Amazon Time Sync (169.254.169.123) still works. If you add backups to S3 from inside the database, give them explicit credentials; they cannot use the instance role. - No core dumps. The database and first-boot services may not write core files, so process memory holding a password never lands on disk.
- IMDSv2 required. The AMI is registered with
ImdsSupport v2.0, so instances launched from it refuse token-less (IMDSv1) metadata requests. - Fails closed. If first boot cannot finish, PostgreSQL stays stopped and first boot tries again on the next boot.
- Per-instance identity. SSH host keys and the machine ID are generated fresh on every instance. SSH allows key login only, root cannot log in over SSH, and root has no password.
- What we changed in Ubuntu: the
fwupd-refreshtimer is masked (EC2 has no firmware that fwupd can update), the C header packages the base image carried are removed (no compiler is installed), and only the running kernel is kept.
Prerequisites
- An AWS account and permission to launch EC2 instances and create security groups
- An EC2 key pair in the Region you launch in
- A VPC subnet, with a public IP on the instance if you connect over the internet
Recommended instance type: m5.large. Size up for large networks (a country-scale OpenStreetMap graph needs far more memory than the demonstration network) or many concurrent routing queries.
Connecting to your instance
| Version | Operating system | SSH user |
|---|---|---|
| pgRouting 4.0.2 with PostGIS on Ubuntu 24.04 | Ubuntu 24.04 LTS | ubuntu |
Step 1: Launch the instance
Option A: AWS Marketplace console
- Open the cloudimg Hardened PostgreSQL 18, PostGIS & Postgres Extension AMIs listing on AWS Marketplace and choose View purchase options, then Subscribe. One subscription covers every version in the listing.
- Once the subscription is active, choose Launch your software.
- Choose One-click launch from AWS Marketplace (or Launch from EC2 Console for the full launch wizard). In Version, choose pgRouting 4.0.2 with PostGIS on Ubuntu 24.04, then choose your Region.
- Pick an instance type (
m5.largerecommended; the software charge is $0.04 per vCPU per hour) and your key pair. - Security group: the listing's default group allows SSH (22) only. Restrict it to your own IP address. Do not open 5432 to the internet.
- Choose your VPC and subnet, leave the metadata defaults (the image already requires IMDSv2), then choose Launch.
Option B: AWS CLI
Run this on your own workstation. Replace the AMI ID with the one shown for your Region on the Marketplace launch page, and the VPC, subnet, key pair and CIDR with your own:
SG=$(aws ec2 create-security-group --group-name pgrouting \
--description "pgRouting" --vpc-id vpc-0123456789abcdef0 \
--query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 22 --cidr <your-mgmt-cidr>
aws ec2 run-instances \
--image-id ami-0123456789abcdef0 \
--instance-type m5.large \
--key-name my-key-pair \
--security-group-ids "$SG" \
--subnet-id subnet-0123456789abcdef0 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=pgrouting}]'
You do not need --metadata-options: the AMI already makes IMDSv2 required. To give the database more room, add a --block-device-mappings entry for /dev/sda1 with a bigger VolumeSize.
Step 2: Connect and read your credentials
Connect as ubuntu with the key pair you chose:
ssh -i ~/.ssh/my-key-pair.pem ubuntu@<public-ip>
First boot finishes within a minute of launch. Show the connection details (the two password lines are left out here; read them with sudo cat /root/pgrouting-credentials.txt and keep them in your secrets manager):
sudo grep -v -e '^POSTGRES_SUPERUSER_PASSWORD=' -e '^ROUTINGAPP_PASSWORD=' /root/pgrouting-credentials.txt | head -12
# pgRouting 4.0.2 with PostGIS 3.6.4 on PostgreSQL 18.6 (cloudimg AWS Marketplace image)
# Generated on THIS instance's first boot by pgrouting-firstboot.service; these passwords exist
# nowhere else. Rotate a password (never on a command line) with: sudo -u postgres psql
# then \password routingapp and update this file to match (pgrouting-credguard reads it at boot).
# Routing database 'routingdb' (owner routingapp; postgis 3.6.4 + pgrouting 4.0.2
# enabled; demonstration tables routing_edges + routing_vertices) on 127.0.0.1:5432. Connect locally with TLS:
# psql "host=127.0.0.1 dbname=routingdb user=routingapp sslmode=require"
# Private address of this instance: 172.31.81.209
#
# NO ROAD DATA SHIPS: the demonstration network is a small synthetic lattice. Load your own network
The commands below read the routingapp password from that file at run time, so it never appears on screen. In your own sessions you can instead put it in ~/.pgpass (mode 0600) as 127.0.0.1:5432:routingdb:routingapp:<ROUTINGAPP_PASSWORD>.
Step 3: Confirm PostgreSQL, PostGIS and pgRouting are running
psql --version
systemctl is-active postgresql@18-main.service pgrouting-firstboot.service pgrouting-credguard.service
sudo ss -Hltn
psql (PostgreSQL) 18.6 (Ubuntu 18.6-1.pgdg24.04+2)
active
active
active
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:*
LISTEN 0 4096 127.0.0.54:53 0.0.0.0:*
LISTEN 0 200 127.0.0.1:5432 0.0.0.0:*
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 4096 [::]:22 [::]:*
PostgreSQL listens on 127.0.0.1:5432 only; port 53 on 127.0.0.53/127.0.0.54 is the operating system's local DNS stub. Now connect as routingapp over TLS, list the extensions in routingdb and show the versions:
export PGPASSWORD="$(sudo sed -n 's/^ROUTINGAPP_PASSWORD=//p' /root/pgrouting-credentials.txt)"
psql "host=127.0.0.1 dbname=routingdb user=routingapp sslmode=require" \
-c "\dx" \
-c "SELECT pgr_version() AS pgrouting, postgis_lib_version() AS postgis, version() ~ '^PostgreSQL 18\.6' AS postgresql_18_6;" \
-c "SELECT ssl, version AS tls_version FROM pg_stat_ssl WHERE pid = pg_backend_pid();"
List of installed extensions
Name | Version | Default version | Schema | Description
-----------+---------+-----------------+------------+------------------------------------------------------------
pgrouting | 4.0.2 | 4.0.2 | public | pgRouting Extension
plpgsql | 1.0 | 1.0 | pg_catalog | PL/pgSQL procedural language
postgis | 3.6.4 | 3.6.4 | public | PostGIS geometry and geography spatial types and functions
(3 rows)
pgrouting | postgis | postgresql_18_6
-----------+---------+-----------------
4.0.2 | 3.6.4 | t
(1 row)
ssl | tls_version
-----+-------------
t | TLSv1.3
(1 row)
Step 4: Explore the demonstration network
First boot loads a small synthetic network into routingdb so you can try routing straight away: a 6 x 6 grid of junctions in south-west London (60 streets) plus a separate three-junction "island" about 40 km away that is deliberately not connected to it. Each street is a PostGIS LINESTRING in EPSG:4326 whose cost is its real length in metres, and routing_vertices holds the junctions, built from the street geometry with pgr_extractVertices. The SQL that builds it is /usr/local/share/cloudimg/pgrouting-demo-network.sql.
export PGPASSWORD="$(sudo sed -n 's/^ROUTINGAPP_PASSWORD=//p' /root/pgrouting-credentials.txt)"
psql "host=127.0.0.1 dbname=routingdb user=routingapp sslmode=require" -v ON_ERROR_STOP=1 <<'SQL'
SELECT kind, count(*) AS streets, round(sum(cost)::numeric) AS total_metres FROM routing_edges GROUP BY kind ORDER BY kind;
SELECT id, name, source, target, round(cost::numeric, 1) AS metres, ST_AsText(geom) AS wkt FROM routing_edges ORDER BY id LIMIT 3;
SELECT count(*) AS junctions FROM routing_vertices;
SELECT component, count(*) AS junctions
FROM pgr_connectedComponents('SELECT id, source, target, cost, reverse_cost FROM routing_edges')
GROUP BY component ORDER BY junctions DESC;
SQL
kind | streets | total_metres
---------+---------+--------------
island | 2 | 1380
lattice | 60 | 54221
(2 rows)
id | name | source | target | metres | wkt
----+----------+--------+--------+--------+------------------------------------
1 | ew-c0-r0 | 4 | 10 | 695.2 | LINESTRING(-0.2 51.45,-0.19 51.45)
2 | ew-c0-r1 | 5 | 11 | 695.0 | LINESTRING(-0.2 51.46,-0.19 51.46)
3 | ew-c0-r2 | 6 | 12 | 694.9 | LINESTRING(-0.2 51.47,-0.19 51.47)
(3 rows)
junctions
-----------
39
(1 row)
component | junctions
-----------+-----------
4 | 36
1 | 3
(2 rows)
pgr_connectedComponents confirms two separate pieces: the 36-junction grid and the 3-junction island.
Step 5: Find the shortest route
Pick the junctions nearest two points (here the south-west and north-east corners of the grid, found with the PostGIS <-> distance operator) and ask pgr_dijkstra for the shortest route between them. Then check that two other algorithms, pgr_aStar (which uses the street coordinates as a heuristic) and pgr_bellmanFord, find a route of the same length:
export PGPASSWORD="$(sudo sed -n 's/^ROUTINGAPP_PASSWORD=//p' /root/pgrouting-credentials.txt)"
psql "host=127.0.0.1 dbname=routingdb user=routingapp sslmode=require" -v ON_ERROR_STOP=1 <<'SQL'
-- The junctions nearest two points: the south-west and north-east corners of the lattice
CREATE TEMP VIEW ends AS
SELECT (SELECT id FROM routing_vertices ORDER BY geom <-> ST_SetSRID(ST_MakePoint(-0.20, 51.45), 4326) LIMIT 1) AS a,
(SELECT id FROM routing_vertices ORDER BY geom <-> ST_SetSRID(ST_MakePoint(-0.15, 51.50), 4326) LIMIT 1) AS b;
-- Shortest path, street by street, with the running distance in metres
SELECT d.seq, d.node, e.name AS street, round(d.agg_cost::numeric, 1) AS metres_so_far
FROM ends, pgr_dijkstra('SELECT id, source, target, cost, reverse_cost FROM routing_edges', ends.a, ends.b) d
LEFT JOIN routing_edges e ON e.id = d.edge
ORDER BY d.seq;
-- Three independent algorithms must agree on the length of the best route
SELECT 'pgr_dijkstra' AS algorithm, round(max(agg_cost)::numeric, 1) AS metres
FROM ends, pgr_dijkstra('SELECT id, source, target, cost, reverse_cost FROM routing_edges', ends.a, ends.b)
UNION ALL
SELECT 'pgr_aStar', round(max(agg_cost)::numeric, 1)
FROM ends, pgr_aStar('SELECT id, source, target, cost, reverse_cost, ST_X(ST_StartPoint(geom)) AS x1, ST_Y(ST_StartPoint(geom)) AS y1, ST_X(ST_EndPoint(geom)) AS x2, ST_Y(ST_EndPoint(geom)) AS y2 FROM routing_edges', ends.a, ends.b)
UNION ALL
SELECT 'pgr_bellmanFord', round(max(agg_cost)::numeric, 1)
FROM ends, pgr_bellmanFord('SELECT id, source, target, cost, reverse_cost FROM routing_edges', ends.a, ends.b);
SQL
CREATE VIEW
seq | node | street | metres_so_far
-----+------+----------+---------------
1 | 4 | ns-c0-r0 | 0.0
2 | 5 | ns-c0-r1 | 1112.6
3 | 6 | ns-c0-r2 | 2225.1
4 | 7 | ns-c0-r3 | 3337.7
5 | 8 | ns-c0-r4 | 4450.3
6 | 9 | ew-c0-r5 | 5562.9
7 | 15 | ew-c1-r5 | 6257.3
8 | 21 | ew-c2-r5 | 6951.7
9 | 27 | ew-c3-r5 | 7646.1
10 | 33 | ew-c4-r5 | 8340.5
11 | 39 | | 9034.9
(11 rows)
algorithm | metres
-----------------+--------
pgr_dijkstra | 9034.9
pgr_aStar | 9034.9
pgr_bellmanFord | 9034.9
(3 rows)
On a grid many routes have the same length; any of them is a correct answer. The route is also available as one PostGIS geometry, ready for a web map (GeoJSON) or for further spatial queries:
export PGPASSWORD="$(sudo sed -n 's/^ROUTINGAPP_PASSWORD=//p' /root/pgrouting-credentials.txt)"
psql "host=127.0.0.1 dbname=routingdb user=routingapp sslmode=require" -v ON_ERROR_STOP=1 <<'SQL'
-- The route as ONE geometry, ready for a web map (GeoJSON) or another PostGIS query
WITH ends AS (
SELECT (SELECT id FROM routing_vertices ORDER BY geom <-> ST_SetSRID(ST_MakePoint(-0.20, 51.45), 4326) LIMIT 1) AS a,
(SELECT id FROM routing_vertices ORDER BY geom <-> ST_SetSRID(ST_MakePoint(-0.15, 51.50), 4326) LIMIT 1) AS b),
route AS (
SELECT ST_LineMerge(ST_Union(e.geom)) AS geom
FROM ends, pgr_dijkstra('SELECT id, source, target, cost, reverse_cost FROM routing_edges', ends.a, ends.b) d
JOIN routing_edges e ON e.id = d.edge)
SELECT ST_GeometryType(geom) AS type, ST_NumPoints(geom) AS points, round(ST_Length(geom::geography)::numeric) AS metres,
left(ST_AsGeoJSON(geom, 4), 70) || '...' AS geojson
FROM route;
SQL
type | points | metres | geojson
---------------+--------+--------+---------------------------------------------------------------------------
ST_LineString | 11 | 9035 | {"type":"LineString","coordinates":[[-0.2,51.45],[-0.2,51.46],[-0.2,51...
(1 row)
Step 6: Road closures, service areas and unreachable places
Three common questions on the same network:
- A road closure. Inside a transaction, give one street a negative cost (pgRouting skips edges with a negative cost), compare the route before and after, then roll the change back so the table is untouched.
- A service area.
pgr_drivingDistancereturns every junction reachable within a distance (here 1,000 m of the centre junction). - No route. Routing to the island returns an empty result, not an error and not an invented route.
export PGPASSWORD="$(sudo sed -n 's/^ROUTINGAPP_PASSWORD=//p' /root/pgrouting-credentials.txt)"
psql "host=127.0.0.1 dbname=routingdb user=routingapp sslmode=require" -v ON_ERROR_STOP=1 <<'SQL'
\set edges 'SELECT id, source, target, cost, reverse_cost FROM routing_edges'
CREATE TEMP VIEW pts AS
SELECT (SELECT id FROM routing_vertices ORDER BY geom <-> ST_SetSRID(ST_MakePoint(-0.20, 51.45), 4326) LIMIT 1) AS sw,
(SELECT id FROM routing_vertices ORDER BY geom <-> ST_SetSRID(ST_MakePoint(-0.15, 51.45), 4326) LIMIT 1) AS se,
(SELECT id FROM routing_vertices ORDER BY geom <-> ST_SetSRID(ST_MakePoint(-0.175, 51.475), 4326) LIMIT 1) AS mid,
(SELECT id FROM routing_vertices ORDER BY geom <-> ST_SetSRID(ST_MakePoint(-0.50, 51.80), 4326) LIMIT 1) AS island;
-- Close a street (a road closure) inside a transaction, compare the routes, then roll the closure back
BEGIN;
SELECT 'open' AS street_ew_c2_r0, round(max(agg_cost)::numeric, 1) AS metres FROM pts, pgr_dijkstra(:'edges', pts.sw, pts.se);
UPDATE routing_edges SET cost = -1, reverse_cost = -1 WHERE name = 'ew-c2-r0';
SELECT 'closed' AS street_ew_c2_r0, round(max(agg_cost)::numeric, 1) AS metres FROM pts, pgr_dijkstra(:'edges', pts.sw, pts.se);
ROLLBACK;
-- Everything reachable within 1,000 m of the centre junction (a service area)
SELECT count(*) AS junctions_within_1000m FROM pts, pgr_drivingDistance(:'edges', pts.mid, 1000);
-- The island is not connected to the lattice: no route is an empty result, not an error
SELECT count(*) AS route_rows_to_island FROM pts, pgr_dijkstra(:'edges', pts.sw, pts.island);
SQL
CREATE VIEW
BEGIN
street_ew_c2_r0 | metres
-----------------+--------
open | 3475.8
(1 row)
UPDATE 1
street_ew_c2_r0 | metres
-----------------+--------
closed | 5700.2
(1 row)
ROLLBACK
junctions_within_1000m
------------------------
3
(1 row)
route_rows_to_island
----------------------
0
(1 row)
With the street closed the route detours one block north and grows from 3,475.8 m to 5,700.2 m. The east-west streets are about 695 m and the north-south streets about 1,113 m, so only the centre junction and its two east-west neighbours are within 1,000 m.
Loading your own network
Replace the demonstration tables with your own network when you are ready. pgRouting needs an edge table with id, source, target, cost (and optionally reverse_cost) columns; with PostGIS geometry you can build source/target exactly as the demonstration does, with pgr_extractVertices. Common sources:
- OpenStreetMap. Load an extract (for example from Geofabrik) with
osm2pgroutingorosm2pgsqlon your workstation or a separate loader instance, through an SSH tunnel to this database. OpenStreetMap data is licensed under the ODbL; its licence and currency are yours to manage. - Your own GIS data. Load a shapefile or GeoPackage with
ogr2ogr(GDAL) or QGIS over the same tunnel.
ogr2ogr -f PostgreSQL "PG:host=127.0.0.1 dbname=routingdb user=routingapp sslmode=require" roads.gpkg -nln roads -lco GEOMETRY_NAME=geom
To drop the demonstration network: DROP TABLE routing_edges, routing_vertices; as routingapp.
Step 7: Check the security controls
The PostgreSQL unit carries the metadata block, routingapp is not a superuser, PostgreSQL listens on loopback and uses this instance's own certificate, and the fwupd refresh timer is masked:
systemctl show -p IPAddressDeny postgresql@18-main.service
sudo -u postgres psql -tAc "SELECT rolname, rolsuper FROM pg_roles WHERE rolname IN ('routingapp', 'postgres') ORDER BY 1;"
sudo -u postgres psql -tAc "SHOW listen_addresses;"
sudo -u postgres psql -tAc "SHOW ssl_cert_file;"
systemctl is-enabled fwupd-refresh.timer 2>/dev/null || true
IPAddressDeny=169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32
postgres|t
routingapp|f
127.0.0.1
/etc/postgresql/18/main/cloudimg-server.crt
masked
Step 8: Connect from your application
PostgreSQL accepts connections on localhost only. Two ways to reach it:
- SSH tunnel (no change to the instance). On your workstation run
ssh -N -L 5432:127.0.0.1:5432 ubuntu@<public-ip>, then connect your client to127.0.0.1:5432asroutingappwithsslmode=require. - Open it to your VPC. In
/etc/postgresql/18/main/conf.d/10-cloudimg.confchangelisten_addresses = '127.0.0.1'tolisten_addresses = '*', restart PostgreSQL, then add an inbound rule for 5432 to the instance's security group from your application subnet or VPC CIDR only (never 0.0.0.0/0). Remote clients must use TLS (sslmode=require, orverify-fullwith this instance's certificate/etc/postgresql/18/main/cloudimg-server.crt) and the role's password:
sudo sed -i "s/^listen_addresses = '127.0.0.1'/listen_addresses = '*'/" /etc/postgresql/18/main/conf.d/10-cloudimg.conf
sudo systemctl restart postgresql@18-main.service
A plain-text (non-TLS) connection from another host is refused by pg_hba.conf, and a wrong password is refused by scram-sha-256:
OUT="$(PGPASSWORD=wrong-password psql "host=127.0.0.1 dbname=routingdb user=routingapp sslmode=require" -c "SELECT 1" 2>&1 || true)"
echo "${OUT#*failed: }"
FATAL: password authentication failed for user "routingapp"
Maintenance
- Change a password. Run
sudo -u postgres psqland type\password routingapp(or\password postgres) at the prompt; it asks for the new password twice and never puts it on a command line. Then update/root/pgrouting-credentials.txt(the credential guard reads it on every boot) and your secrets manager. - Configuration. cloudimg's settings are in
/etc/postgresql/18/main/conf.d/10-cloudimg.conf(listener, port, password hashing) and20-cloudimg-tls.conf(this instance's certificate). Apply changes withsudo systemctl restart postgresql@18-main.service. - Updates.
sudo apt update && sudo apt upgradeinstalls PostgreSQL 18, PostGIS 3.6 and pgRouting releases from PGDG and Ubuntu updates; unattended upgrades also apply them automatically. After a PostGIS or pgRouting upgrade, runALTER EXTENSION postgis UPDATE;andALTER EXTENSION pgrouting UPDATE;in each database. - PostGIS raster.
postgis_rasteris installed but not enabled. It is the only part of the image that uses the GDAL library; if you enable it (CREATE EXTENSION postgis_raster;aspostgres), note that Ubuntu publishes some GDAL security fixes for Ubuntu 24.04 only through Ubuntu Pro (ESM Apps), so attach Ubuntu Pro if you rely on raster import of untrusted files. - Backups. Take EBS snapshots of the root volume or
pg_dump -Fc routingdbbackups regularly. - Logs.
/var/log/postgresql/postgresql-18-main.logandjournalctl -u postgresql@18-main.service; first boot and the credential guard log tojournalctl -u pgrouting-firstboot.serviceandjournalctl -u pgrouting-credguard.service. - Licences. pgRouting and PostGIS are GPL-2.0-or-later and PostgreSQL is under The PostgreSQL License. All are unmodified PGDG packages;
/usr/share/doc/cloudimg/GPL-2-WRITTEN-OFFER.txtexplains how to get the pgRouting and PostGIS source (apt-get source, or ask support@cloudimg.co.uk), and/usr/share/doc/cloudimg/LICENCE-AUDIT.txtrecords the audited licence files.
Support
cloudimg supports this image by email at support@cloudimg.co.uk. Include the instance ID, the version (pgRouting 4.0.2 with PostGIS on Ubuntu 24.04) and what you were doing.
PostgreSQL is a trademark of the PostgreSQL Community Association of Canada. Ubuntu is a trademark of Canonical Ltd. OpenStreetMap is a trademark of the OpenStreetMap Foundation. PostGIS and pgRouting are the names of their open-source projects. cloudimg is not affiliated with or endorsed by these organisations or projects.