Suivi installation Osm2pgsql et Underpass
publié le , mis à jourIssue créée pour tracer 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
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;'
Si besoin de vider la base : sudo -u postgres psql postgres --command='DROP DATABASE osm;'
ajustement de la configuration
https://osm2pgsql.org/doc/manual-v1.html#tuning-the-postgresql-server
en suivant strictement les valeurs proposées ➡️ alors qu'elles sont 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
Remplissage de la DB
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 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 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 !
Exempls sur la Bretagne :
- l'extrait compressé fait 346 Mo
- j'avais imagine un filtrage (dans
cartes-v1.style
) pour que la base fasse 300Mo, mais - activer
--slim
coûte déjà 3782 Mo (sans aucun élément filtré) - activer
--slim --extra-attributes
coû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-all
pour 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
- si on supprime manuellement les tags (remplacés par null), ça ne marche pas
téléchargement d'un extrait d'OSM
OSM-FR osm-fr ne fournit plus l'extrait europe mais seulement pays par pays.
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 🤔
import dans la base (pour vérif perfs)
osm2pgsql -U ubuntu -d osm -c bretagne-latest.osm.pbf
- l'import prend 2m33s (pour le 1er serveur de test sans SSD)
- au lieu de 6min si on oublie d'ajuster la configuration
- et au lieu de 2min chez moi
- la base fait 1875MB
- au lieu de 2366MB chez moi. Peut -être des améliorations entre osm2pgsql v1.6 (chez moi) et 1.11 (sur le serveur) ?
transfert du fichier de style personnalisé
scp cartes-v1.style ubuntu@xx.xx.xx.xx:~/cartes-v1.style
import de la France
osm2pgsql -U ubuntu -d osm -c -s -S cartes-v1.style --extra-attributes --hstore-all --hstore-match-only france-latest.osm.pbf
explication :
- création initiale :
-c
- en mode slim (nécessaire pour ensuite gérer les update) :
-s
- en utilisant un style personnalisé pour la sélection des tags pertinents :
-S cartes-v1.style
- on garde les metadata :
--extra-attributes
(si on les a dans l'extrait évidemment) - on garde l'intégralité des tags dans la colonne tags au format hstore (sinon ça enlève les tags déjà dans une colonne) :
--hstore-all
- mais en revanche, pour alléger la base, on supprime les éléments qui n'ont aucun des tags listés dans le style
--hstore-match-only
remarque : 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
...
import de l'Europe
à partir du fichier public de geofabrik (donc sans metadata) :
osm2pgsql -U ubuntu -d osm -c -s -S cartes-v1.style --hstore-all --hstore-match-only pbf/geofabrik/europe-latest.osm.pbf
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
2 avril : nouveau test d'import France
avec les géométries de tous les objets
- avec un fichier style "vide" (sans aucun tag sélectionné pour mise en colonne), mais l'option
--hstore-all
pour enregistrer les tags en entier, et donc calculer les géométries de tous les objets. - il faudra utiliser l'option
--proj=4632
pour que les géométries soient compatibles avecUnderpass-API
- il faudra utiliser l'option
--flat-nodes FILE --middle-with-nodes
pour :- stocker TOUS les nodes dans un fichier plutôt que dans la base
- mais quand même stocker dans la base les nodes qui ont des tags pour que l'api maison puisse les trouver (il y a 25 M de nodes avec tag sur les 507 M de nodes en France)
osm2pgsql -U ubuntu -d osmFrance -c -s --flat-nodes DB-flat-nodes --middle-with-nodes --proj=4632 -S vide.style --hstore-all france.osm.pbf
- sans les métadata : le remplissage prend 1h14. La base fait 58 GB + le fichier flat-nodes de 95GB (taille fixe quel que soit l'extrait)
2025-04-02 23:15:39 Reading input files done in 2761s (46m 1s).
2025-04-02 23:15:39 Processed 507325455 nodes in 457s (7m 37s) - 1110k/s
2025-04-02 23:15:39 Processed 71276568 ways in 1567s (26m 7s) - 45k/s
2025-04-02 23:15:39 Processed 1061360 relations in 737s (12m 17s) - 1k/s
2025-04-02 23:43:35 Done postprocessing on table 'planet_osm_ways' in 1623s (27m 3s)
2025-04-02 23:43:35 Done postprocessing on table 'planet_osm_rels' in 120s (2m 0s)
2025-04-02 23:43:35 All postprocessing on table 'planet_osm_point' done in 217s (3m 37s).
2025-04-02 23:43:35 All postprocessing on table 'planet_osm_line' done in 731s (12m 11s).
2025-04-02 23:43:35 All postprocessing on table 'planet_osm_polygon' done in 101s (1m 41s).
- avec les métadata : le remplissage prend 1h21. La base fait 73 GB + le fichier flat-nodes de 95GB (taille fixe quel que soit l'extrait)
Processing: Node(507325k 489.2k/s) Way(71276k 41.93k/s) Relation(1059500 1473.6/s)
2025-04-03 07:20:38 Writing 81392 entries to table 'planet_osm_users'...
2025-04-03 07:20:39 Reading input files done in 3458s (57m 38s).
2025-04-03 07:20:39 Processed 507325455 nodes in 1037s (17m 17s) - 489k/s
2025-04-03 07:20:39 Processed 71276568 ways in 1700s (28m 20s) - 42k/s
2025-04-03 07:20:39 Processed 1061360 relations in 721s (12m 1s) - 1k/s
2025-04-03 07:44:22 Done postprocessing on table 'planet_osm_ways' in 1329s (22m 9s)
2025-04-03 07:44:22 Done postprocessing on table 'planet_osm_rels' in 117s (1m 57s)
2025-04-03 07:44:22 All postprocessing on table 'planet_osm_point' done in 298s (4m 58s).
2025-04-03 07:44:22 All postprocessing on table 'planet_osm_line' done in 899s (14m 59s).
2025-04-03 07:44:22 All postprocessing on table 'planet_osm_polygon' done in 152s (2m 32s).
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.io
version 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 ubuntu
puisnewgrp 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 ?)- le yaml a l'option
restart: unless-stopped
donc 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
Bizarrement, on ne peut tester l'url dans overpass-turbo. Peut-être à cause du http:// sans s ?
✅ chercher 1 élément donné à partir de son type+id fonctionne (encore heureux !)
[out:json][timeout:25];
node(4164995705);
out center meta;
time curl 'http://51.159.100.169:9292/interpreter' -X POST -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' --data-raw 'data=%5Bout%3Ajson%5D%5Btimeout%3A25%5D%3B%0Anode%284164995705%29%3B%0Aout%20center%20meta%3B' > result.json
✅ filtrage par tag et par bbox
- en local :
- en prod sur France : ✅ 350ms exemple qui renvoie 419 aires de jeux à Rennes :
[out:json][timeout:25];
nwr["leisure"="playground"](48.05,-1.75,48.15,-1.6);
out center;
time curl 'http://51.159.100.169:9292/interpreter' -X POST -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' --data-raw '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
✅ filtrage par tag et par area issue d'un way
- en local
- en prod : ✅ ≃600ms
fonctionne bien (donne les 2 aires de jeux du Parc des Gayeulles) mais fournit toute la géométrie des ways aires de jeux alors que je demandais juste les tags
[out:json][timeout:25];
area(23255048)->.a;
nwr["leisure"="playground"](area.a);
out tags;
time curl 'http://51.159.100.169:9292/interpreter' -X POST -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' --data-raw 'data=%5Bout%3Ajson%5D%5Btimeout%3A25%5D%3B%0Aarea%2823255048%29-%3E.a%3B%0Anwr%5B%22leisure%22%3D%22playground%22%5D%28area.a%29%3B%0Aout%20tags%3B' > result.json
✅ filtrage par tag et par area issue d'une relation
- en local
- en prod avec géométries brutes : ✅ ≃600ms
Attention il faut que la relation soit dans la BDD, et typiquement les villes n'y sont pas pour l'instant ... J'ai eu besoin de corriger les ID des areas provenant de relation pour ajouter le facteur 3600000000 cher à Overpass, mais maintenant c'est bon ça marche. Exemple avec les aires de jeu dans le parc du Thabor
[out:json][timeout:25];
area(id:3606848340)->.a;
nwr["leisure"="playground"](area.a);
out center tags;
time curl 'http://51.159.100.169:9292/interpreter' -X POST -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' --data-raw 'data=%5Bout%3Ajson%5D%5Btimeout%3A25%5D%3B%0Aarea%28id%3A3606848340%29-%3E.a%3B%0Anwr%5B%22leisure%22%3D%22playground%22%5D%28area.a%29%3B%0Aout%20center%20tags%3B' > result.json
⚠️ filtrage avec is_in puis tag les leisure à une coordonnées données -> 2 éléments
[out:json][timeout:25];
is_in(48.114093,-1.667733);
area._["leisure"];
out tags;
time curl 'http://51.159.100.169:9292/interpreter' -X POST -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' --data-raw 'data=%5Bout%3Ajson%5D%5Btimeout%3A25%5D%3B%0Ais_in%2848.114093%2C-1.667733%29%3B%0Aarea._%5B%22leisure%22%5D%3B%0Aout%20tags%3B' > result.json
à tester mais a priori devrait marcher
⚠️ filtrage avec around
à tester, mais a priori ne devrait pas marcher !