Suivi installation Osm2pgsql et Underpass
publié le , mis à jourIssue créée pour tracer (en mode bloc-note / wiki) les actions réalisées sur le serveur pour la création de la base OSM au schéma osm2pgsql et le déploiement de l'instance underpass.
installation et réglage de osm2pgsql
installation osm2pgsql
En suivant : https://osm2pgsql.org/doc/install.html
sudo apt install osm2pgsql
besoin de 383 MB
On est sous ubuntu 24 => installation release 1.11.0
Remarque : il est possible de forcer l'installation de la nouvelle version 2.0.1 à condition de compiler soi même, en suivant le readme. C'est ce que mael a fait pour les premiers tests.
installation postgreSQL
a priori déjà fait lors de la commande précédente => a installé la version 16.8
création de la DB
https://osm2pgsql.org/doc/manual-v1.html#preparing-the-database
En utilisant le user ubuntu avec lequel je suis connecté au serveur pour profiter ensuite de la peer authentification. ➡️ Je ne sais pas si c'est une bonne idée, si il ne faut pas plutôt créer un utilisateur spécifique ?
sudo -u postgres createuser ubuntu
sudo -u postgres createdb --encoding=UTF8 --owner=ubuntu osm
sudo -u postgres psql osm --command='CREATE EXTENSION postgis;'
sudo -u postgres psql osm --command='CREATE EXTENSION hstore;'
Remarque : hstore inutile si on définit des tables personnalisées (flex output) sans les tags.
Si besoin de vider la base : sudo -u postgres psql postgres --command='DROP DATABASE osm;'
Si besoin de renommer la DB : sudo -u postgres psql postgres --command='ALTER DATABASE osmfrance RENAME TO osm;' (et semblable pour une table avec ALTER TABLE)
ajustement de la configuration
https://osm2pgsql.org/doc/manual-v1.html#tuning-the-postgresql-server
en suivant strictement les valeurs proposées (annoncées pour 64GB de RAM et un disque SSD)
pour trouver où est la conf : sudo -u postgres psql -c 'SHOW config_file'
puis : sudo vi /etc/postgresql/16/main/postgresql.conf et modifications de valeurs
puis redémarrage : sudo service postgresql restart
Sources extrait d'OSM
OSM-FR
osm-fr ne fournit plus l'extrait europe mais seulement pays par pays. En revanche on pourrait demander les diff, et recréer manuellement l'Europe par ajout successif des pays (ou fusion préalable avec osmosis)
Geofabrik
Attention, les public downloads de geofabrik (disponibles sans connexion) n'ont pas les metadata
curl -O https://ftp5.gwdg.de/pub/misc/openstreetmap/download.geofabrik.de/europe-latest.osm.pbf (30GB, 8min20)
Besoin de se connecter via l'oauth osm pour accéder à : https://osm-internal.download.geofabrik.de/europe.html Et je ne sais pas le faire en ligne de commande sur le serveur 🤔
remarque sur fusion
il est possible de lister plusieurs fichiers à la suite sur la ligne de commande pour qu'ils soient traités ensemble :
osm2pgsql -U ubuntu -d osm -c -s -S cartes-v1.style --extra-attributes --hstore-all --hstore-match-only france.osm.pbf suisse.osm.pbf belgique.osm.pbf mais alors on ne pourra faire les update automatique avec osm2pgsql-replication ...
Bilan tests initiaux ➡️ Réfléxion sur la taille de la DB et le besoin de filtrage
Pour pouvoir faire les updates automatiques à partir des diff, il est nécessaire d'activer l'option --slim. Cela entraine la création de 3 tables middle pour stocker TOUS les _nodes, _ways et _relations de l'extrait traité. C'est nécessaire pour enregistrer les ajouts ou suppression d'éléments à chaque update. Et cela même si les tables "filtrées" spécifiques de osm2pgsql (output table) et contenant la géométrie (tables _point, _line et _polygon) ne contiennent que quelques éléments. Donc contrairement à ce que son nom laisse croire, cette option coûte cher en espace disque !
Exemple sur la Bretagne :
- l'extrait compressé fait 346 Mo
- j'avais imaginé un filtrage (dans
cartes-v1.style) pour que la base fasse 300Mo, mais - activer
--slimcoûte déjà 3782 Mo (sans aucun élément filtré) - activer
--slim --extra-attributescoûte 4636 Mo (sans aucun élément filtré) - avec en plus les éléments filtrés selon
cartes-v1.style, la base fait 4973 Mo- soit +337 Mo pour les éléments filtrés avec leur géométrie, c'est logique
- au maximum la base fait 8151 Mo (avec
--hstore-allpour stocker tous les objets avec tous leurs tags, et toutes leurs géométries)- si on ne demande pas les extra attributes, elle fait 6300 MB
Même chose avec la France, les 3 middle tables avec métadonnées (-x) prennent déjà 29 Go.
Remplissage de la base avec un flex output personnalisé
principe
On écrit un fichier geometries-alone.lua, basé sur l'exemple geometries.lua, mais encore plus simple :
- on ne garde que les géométries
- en SRID 4326 pour être compatible avec overpass/underpass (même si frodrigo a mis à jour underpass depuis)
- on ne garde pas les tags dans ces
outputtables- on utilisera les tags bruts qui sont déjà présents dans les
middletables _nodes, _ways et _rels. Il faudra néanmoins les indexer après coup car ça n'est pas fait par défaut
- on utilisera les tags bruts qui sont déjà présents dans les
- on stocke 1 seule ligne par élément OSM avec toute la géométrie en point, linestring ou en geometry
- d'habitude osm2pgsql coupe les grosses géométries sinon ça ralentit le calcul des tuiles (car il faut charger toute la géométrie même si un seul petit bout passe sur la tuile). On fait l'hypothèse ici que garder les grosses géométries entières ne ralentit pas trop les requêtes sql/postgis, mais ça méritera d'être vérifié.
remarque : donc plus besoin de l'extension hstore lors de la création de la DB
Remarque sur la structure la DB
Avec la version initiale geometries.lua, les relations étaient stockées avec un index négatif dans les tables polygons et lines. ça empêchait postgres d'utiliser l'index pour les JOIN. J'ai alors modifié le lua pour utiliser les vrais id des éléments OSM, ce qui implique de créer 1 table par type d'élément OSM (node, way, rel), et non 1 table par type de géométrie (point, line, polygon).
remarque sur les flat nodes
Attention : à partir de l'Europe, il est très fortement recommandé d'utiliser le mode --flat-nodes FILE pour stocker les nodes dans un fichier et pas dans la base. Le fichier va prendre un peu plus de 100 GB quelle que soit la taille de l'extrait utilisé. Dans ce cas, il est conseillé de désactive le cache avec --cache 0
Mise en oeuvre
récupération de l'extrait
curl -O https://download.openstreetmap.fr/extracts/merge/france_metro_dom_com_nc.osm.pbf
commande pour osm2pgsql :
osm2pgsql -U ubuntu -d osm -c -s -x --flat-nodes DB-flat-nodes --middle-with-nodes -O flex -S geometries-alone.lua france_metro_dom_com_nc.osm.pbf
explication :
- dans la database
-d DBNAME - création initiale :
-cou--create - en mode slim (nécessaire pour ensuite gérer les update) :
-sou--slim - et on garde les metadata :
-xou--extra-attributes(si on les a dans l'extrait osm évidemment) - avec les nodes stockés dans un fichier texte séparé
--flat-nodes FILE - mais en ajoutant quand même dans la base les noeuds qui ont des tags :
--middle-with-nodes - on utilise le
flex outputpour avoir des tables personnalisées :-O flex - on indique le fichier .lua où trouver notre script pour le flex output :
-S FILE.lua
log
025-04-07 19:51:37 Reading input files done in 3608s (1h 0m 8s).
2025-04-07 19:51:37 Processed 524198002 nodes in 562s (9m 22s) - 933k/s
2025-04-07 19:51:37 Processed 73315494 ways in 2171s (36m 11s) - 34k/s
2025-04-07 19:51:37 Processed 1076415 relations in 875s (14m 35s) - 1k/s
2025-04-07 19:51:41 Done postprocessing on table 'planet_osm_nodes' in 0s
2025-04-07 20:18:42 Done postprocessing on table 'planet_osm_ways' in 1621s (27m 1s)
2025-04-07 20:18:42 Done postprocessing on table 'planet_osm_rels' in 123s (2m 3s)
2025-04-07 20:18:42 All postprocessing on table 'points' done in 427s (7m 7s).
2025-04-07 20:18:42 All postprocessing on table 'lines' done in 509s (8m 29s).
2025-04-07 20:18:42 All postprocessing on table 'areas' done in 1414s (23m 34s).
2025-04-07 20:18:42 osm2pgsql took 5233s (1h 27m 13s) overall.
Modifs sur la base post création
Après création des tables, besoin de donner accès en lecture à l'utilisateur idoine :
GRANT SELECT ON planet_osm_nodes TO readonlyuser;
GRANT SELECT ON planet_osm_ways TO readonlyuser;
GRANT SELECT ON planet_osm_rels TO readonlyuser;
GRANT SELECT ON planet_osm_users TO readonlyuser;
GRANT SELECT ON nodes_geom TO readonlyuser;
GRANT SELECT ON ways_geom TO readonlyuser;
GRANT SELECT ON rels_geom TO readonlyuser;
Et de créer des index sur les tags (pas besoin d'indexer les id de ces 3 tables car ce sont déjà des primary keys)
CREATE INDEX nodes_tags_idx ON planet_osm_nodes USING GIN (tags); //
CREATE INDEX ways_tags_idx ON planet_osm_ways USING GIN (tags);
CREATE INDEX rels_tags_idx ON planet_osm_rels USING GIN (tags);
ça prend plusieurs minutes pour chaque.
Sizing
La base fait 57 Go (+ le fichier flat nodes de 100 Go).
Poid des différentes parties de la base.
Cas de la France+domtom : le .osm.pbf fait 5,2 Go
| partie | poids |
|---|---|
| éléments OSM bruts dans middle tables | 29Go |
| indexation des tags | +2 Go |
| ajout des géométries dans output tables | +26 Go |
| TOTAL | 57 Go |
Installation et démarrage d'Underpass-API avec docker
adaptation du code à Osm2pgsql
Une PR a été créée pour ajouter la gestion du schéma osm2pgsql.
En attendant, j'utilise mon fork : git clone https://github.com/etienneJr/Underpass-API.git
récupération de la branche : git switch osm2pgsql-backend
Modifs dans le code
Pour que ça marche avec docker, il faut modifier backends/postgres_osm2pgsql/docker-compose.yaml :
- supprimer/commenter le service osm2pgsql
- supprimer/commenter le service postgress
- modifier la ligne avec l'url de la DB :
DATABASE_URL: postgres://readonlyuser:iwanttoreadfree@51.159.100.169:5432/osm - supprimer/commenter
depends_on: - postgres
installations diverses
- installation de docker lui même :
sudo apt install docker.ioversion 26.1.3-0ubuntu1~24.04.1 (302MB) - maj liste :
sudo apt-get update - installation plugin compose :
sudo apt-get install docker-compose-plugin❌ échecE: Unable to locate package docker-compose-plugin - installation manuelle du plugin compose en suivant ça
- ajout du user ubuntu dans le groupe docker (d'après ça) :
sudo usermod -a -G docker ubuntupuisnewgrp docker - build du container
docker compose --profile '*' build
démarrage
- en foreground (ctrl+c pour arrêter) :
docker compose up - en background (reste actif) :
docker-compose up -d(comment on l'arrête alors ?downje crois, sinonstop)- le yaml a l'option
restart: unless-stoppeddonc a priori il redémarre tout seul ?!? enfin il faut peut-être changer en always. Cf cette page mais qui est pour docker sans compose. Il est écrit qu'il faut désactiver l'optionrestart:si on préfère utilisersystemd.
- le yaml a l'option
Utilisation
- underpass en local :
time curl http://localhost:9292/interpreter?data= - underpass en prod :
time curl http://51.159.100.169:9292/interpreter?data= - pour comparaison avec overpass interne :
time curl https://overpass.cartes.app/api/interpreter?data=
Tests de rapidité
filtrage par tag et par bbox
Exemple : 419 aires de jeux à Rennes
[out:json][timeout:25];
nwr["leisure"="playground"](48.05,-1.75,48.15,-1.6);
out center;
data=%5Bout%3Ajson%5D%5Btimeout%3A25%5D%3B%0Anwr%5B%22leisure%22%3D%22playground%22%5D%2848.05%2C-1.75%2C48.15%2C-1.6%29%3B%0Aout%20center%3B > result.json
- en local : (sur base Bretagne 7Go : 50 ms ✅)
- en prod (base FR 60 Go) pour juste la requête SQL : 900 ms ⚠️
- en prod sur serveur overpass : ✅ 600-700 ms exemple qui renvoie 419 aires de jeux à Rennes :
C'est bizarre que ça passe de 50 ms à 900 ms, on dirait un pb d'indexation.
GhostJe viens de commencer à suivre les actions pour avoir un underpass que sur la région Bretagne dans mon cas. J'ai créé un compte unix "ubuntu" : c'est nécessaire pour que l'authentification "peer" de postgresql fonctionne. Je télécharge avec wget -O bretagne-latest.osm.pbf https://download.geofabrik.de/europe/france/bretagne-latest.osm.pbf
Mais je ne trouve pas le fichier cartes-v1.style !
etienneJr
Mais je ne trouve pas le fichier cartes-v1.style !
Ah oui désolé je ne l'ai pas encore poussé. C'est une personnalisation de ce fichier pour avoir une base plus légère. Mais vu que tu n'importes que la Bretagne, tu n'as pas cette problématique, tu peux tout importer avec le style par défaut, donc avec la commande sans l'option
-S xxx.stylelaem
Sur le nouveau serveur SSD, france : osm2pgsql took 5793s (1h 36m 33s) overall. On a un db psql complète (installation neuve) de 85 go. Si on extrapole à l'europe selon la taille du osm.pbf ça donne x6 donc ~500 go.
etienneJr
Sur le nouveau serveur SSD, france : osm2pgsql took 5793s (1h 36m 33s) overall. On a un db psql complète (installation neuve) de 85 go. Si on extrapole à l'europe selon la taille du osm.pbf ça donne x6 donc ~500 go.
Bizarre, chez moi la bdd pour la France faisait environ 10Go. Là 85Go ça ressemble à la taille d'une base incluant tous les éléments OSM en France. T'es sûr que le fichier de filtrage a été pris en compte ? [edit] je confirme, il y a dans la base des relations
type=boundaryettype=associatedStreetqui sont normalement exclues de mon fichier. (Mais c'est cool d'avoir tout pour vérifier que l'api osm maison marche dans tous les cas !)laem
Ah mince, j'ai fait plusieurs essais, j'ai du oublier. J'ai téléchargé le fichier via scp, mais peut-être oublié de l'utiliser. À re-tester pour l'Europe pour alléger alors.
laem
Je suis la documentation de MAJ de la db, et ça semble fonctionner !
[edit] :
osm2pgsql-replication update -d osmsuffit car les infos nécessaires (url, sequence_number, style) sont dans la table osm2pgsql_properties.etienneJr
france.osm.pbf
Tu fournis l'extrait complet ?!? Ou c'est bien un diff malgré son nom ?
laem
Haha bonne question, c'était marqué "<parameters to osm2pgsql>" donc j'ai copié, mais peut-être qu'il faut pas inclure le fichier en effet
laem
Je crois que t'as raison. Sans le fichier en argument, ça semble avoir marché. Il faut que je vérifie sur des changements récents.
laem
Avant :
Après la commande de MAJ :
http://localhost:8080/api/osm?featureType=node&osmId=11888827583
C'est bon, ça marche :)
laem
je mets en place les services system.d
cat /etc/systemd/system/osm2pgsql-update.timer[Unit] Description=Trigger a osm2pgsql database update [Timer] OnBootSec=10 OnUnitActiveSec=10minutes [Install] WantedBy=timers.targetcat /etc/systemd/system/osm2pgsql-update.service[Unit] Description=Keep osm2pgsql database up-to-date [Service] WorkingDirectory=/home/ubuntu ExecStart=/bin/bash -c 'source /home/ubuntu/.venv/bin/activate && osm2pgsql-replication update -d osm' StandardOutput=append:/var/log/osm2pgsql-updates.log User=ubuntu Type=simple Restart=on-failure RestartSec=5minsudo systemctl daemon-reload sudo systemctl enable osm2pgsql-update.timer sudo systemctl start osm2pgsql-update.timer cat /var/log/osm2pgsql-updates.loglaem
Pour contrôler que ça marche, le mieux est de chercher les noeuds récemment changés via ça
[out:json][timeout:25]; ( node({{bbox}})(changed:"2025-03-28T17:09:00Z"); ); out meta;Puis de suivre les liens OSM pour voir l'historique.
etienneJr
osm2pgsql-replication update -d osm -- -U ubuntu -a -s -S /home/ubuntu/cartes-v1.style --extra-attributes --hstore-all --hstore-match-only'
J'ai lu la doc : il faut remettre tous les arguments si tu fais une mise à jour via la commande
osm2pgsql -a. Mais si tu utilisesosm2pgsql-replicationalors il regarde tous les paramètres utilisés lors de la création initiale (le fichier de style, le serveur où trouver les diff, le fichier où sont stockés les nodes, l'index de la dernière maj, ...) dans la tableosm2pgsql_propertiesdonc en fait la commande est tout simplementosm2pgsql-replication update -d osm, pas besoin d'arguments supplémentaires. Tu peux modifier dans ton fichier pour systemd.Ex trace chez moi :
etienne@Inspiron2Ubuntu:~/Dev/osm2pgsql$ osm2pgsql-replication init -d osm 2025-03-28 23:35:06 [INFO]: Initialised updates for service 'http://download.openstreetmap.fr/replication/./europe/france/bretagne/minute'. 2025-03-28 23:35:06 [INFO]: Starting at sequence 6530599 (2025-03-27T01:42:00Z). etienne@Inspiron2Ubuntu:~/Dev/osm2pgsql$ osm2pgsql-replication update -d osm 2025-03-28 23:35:31 [INFO]: Using replication service 'http://download.openstreetmap.fr/replication/./europe/france/bretagne/minute'. 2025-03-28 23:37:07 osm2pgsql version 2.0.1 2025-03-28 23:37:07 Database version: 14.17 (Ubuntu 14.17-0ubuntu0.22.04.1) 2025-03-28 23:37:07 PostGIS version: 3.2 2025-03-28 23:37:07 Loading properties from table '"public"."osm2pgsql_properties"'. 2025-03-28 23:37:07 Updating with attributes (same as on import). 2025-03-28 23:37:07 Using flat node file '/home/etienne/Documents/nodes-osm' (same as on import). 2025-03-28 23:37:07 Using output 'pgsql' (same as on import). 2025-03-28 23:37:07 Using style file '/home/etienne/Dev/osm2pgsql/cartes-v1.style' (same as on import). 2025-03-28 23:37:07 Storing properties to table '"public"."osm2pgsql_properties"'. [...] Processing: Node(4k 4.0k/s) Way(0k 0.00k/s) Relation(10 10.0/s) 2025-03-28 23:37:08 Writing 52 entries to table 'planet_osm_users'... 2025-03-28 23:37:08 Reading input files done in 1s. 2025-03-28 23:37:08 Processed 4163 nodes in 1s - 4k/s 2025-03-28 23:37:08 Processed 984 ways in 0s - 984/s 2025-03-28 23:37:08 Processed 98 relations in 0s - 98/s 2025-03-28 23:37:08 Going over 82 pending ways # ça je pense que c'est le recalcul de la géométrie des ways et relations modifiées 2025-03-28 23:37:08 Processing 82 pending ways took 0s at a rate of 0.00/s 2025-03-28 23:37:08 Going over 170 pending relations (using 4 threads) 2025-03-28 23:37:10 Processing 170 pending relations took 2s at a rate of 85.00/s [...] 2025-03-28 23:37:10 Storing properties to table '"public"."osm2pgsql_properties"'. 2025-03-28 23:37:10 osm2pgsql took 3s overall. 2025-03-28 23:37:10 [INFO]: Data imported until 2025-03-28T22:34:17Z. Backlog remaining: 2 minute(s) 53 second(s) etienne@Inspiron2Ubuntu:~/Dev/osm2pgsql$ osm2pgsql-replication init -d osm 2025-03-28 23:43:40 [INFO]: Initialised updates for service 'http://download.openstreetmap.fr/replication/./europe/france/bretagne/minute'. 2025-03-28 23:43:40 [INFO]: Starting at sequence 6533243 (2025-03-28T22:34:17Z).etienneJr
@laem c'est bon j'ai résolu le pb du filtrage par bbox avec Underpass-API, c'était une question de SRID différent entre osm2pgsql et overpass (cf PR3).
Donc je crois que c'est bon, on peut filtrer par ID, par tags, par area et par bbox. Tu vois autre chose dont on aurait besoin ? (c'est juste que j'ai pas testé, mais normalement c'est inclus dans Underpass-API, du moins tant que la requête n'est pas trop complexe)
Pour le déploiement, je me doute bien que l'option docker sera mieux mais je n'ai pas compris comment faire pour que le conteneur docker accède à la base postgres créée à l'exterieur du conteneur docker ... tu aurais une idée ?
[edit] j'ai essayé (aussi bien via bundle que docker) de mettre l'ip du serveur (avec login+mdp idoines) mais ça n'a pas marché. Tu as mis des restrictions d'accès aux extérieurs ?
laem
Je vais regarder ça pour Overpass. Mais d'abord, mettre en ligne la branche api OSM avec les noeuds, puis les autres formes.