Centrer la carte sur le GPS du téléphone (HTTPS terminé par le proxy)
Le bouton ⌖ recentre la carte sur la position GPS du téléphone. L'API Geolocation exige un contexte sécurisé : la webapp sert désormais du HTTP et le TLS est porté par le reverse proxy (Traefik, labels dans l'override local) ; le webapp est transparent au proxy (URLs relatives, X-Forwarded-For pour la restriction LIDAR_REGEN_CIDR). Ajoute le modèle d'override docker-compose.webapp.override.yml.example, un rebuild d'index à la demande et met à jour doc/déploiement ; les tuiles sont servies à la demande.
This commit is contained in:
@ -10,7 +10,7 @@ Navigateur ──HTTP──▶ Raspberry Pi (image légère, Dockerfile.webapp)
|
||||
│ sert carte + vignettes (régénérées localement)
|
||||
│ /api/generate, /api/preview, /api/status
|
||||
│ └─ transmis à ──▶ machine de traitement
|
||||
│ /api/sync : rsync output/ ──◀── machine puissante
|
||||
│ /api/sync : rebuild local (tuiles servies à la demande)
|
||||
▼
|
||||
Machine de traitement (image complète,
|
||||
docker-compose.worker.yml service `worker`) :
|
||||
@ -21,7 +21,7 @@ Navigateur ──HTTP──▶ Raspberry Pi (image légère, Dockerfile.webapp)
|
||||
|
||||
Le service `worker` joue le rôle de générateur : il accepte les demandes
|
||||
de génération envoyées par les webapp distantes (téléchargement IGN +
|
||||
traitement PDAL/GPU) et expose les tuiles produites pour le rsync.
|
||||
traitement PDAL/GPU) et expose les tuiles produites, servies à la demande par les webapp.
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.worker.yml up -d --build # API sur http://<ip-machine>:8973
|
||||
@ -54,8 +54,8 @@ environment:
|
||||
- **Docker + plugin compose** : installation officielle
|
||||
[docs.docker.com/engine/install](https://docs.docker.com/engine/install/)
|
||||
(tester avec `docker compose version`).
|
||||
- **rsync/ssh côté client** : inutile sur l'hôte — ils sont dans l'image —
|
||||
mais la **clé SSH** de l'hôte est montée dans le conteneur.
|
||||
- **Clé SSH côté hôte** : montée dans le conteneur pour le déploiement et le
|
||||
`git pull` distant (le rsync de tuiles, supprimé, n'en avait pas besoin).
|
||||
- **Espace disque** : prévoir la taille du cache de tuiles (compter la
|
||||
taille de `output/` sur la machine de traitement, ~quelques dizaines de
|
||||
Mo par dalle et par résolution).
|
||||
@ -67,31 +67,37 @@ git clone ssh://git@git.example.fr:2222/code_public/lidar_rendu.git lidar
|
||||
cd lidar
|
||||
```
|
||||
|
||||
Le clone SSH utilise la même clé que le rsync (`~/.ssh`, voir ci-dessous) ;
|
||||
si le serveur git n'est pas encore connu, faire une première connexion pour
|
||||
accepter son empreinte. `output/` et `input/` sont ignorés par git : le
|
||||
dépôt ne contient que le code, le cache de tuiles se remplit ensuite par
|
||||
rsync (premier chargement, section 4).
|
||||
Le clone SSH utilise la clé de l'hôte (`~/.ssh`, section 2). Si le serveur
|
||||
git n'est pas encore connu, faire une première connexion pour accepter son
|
||||
empreinte. `output/` et `input/` sont ignorés par git : le dépôt ne contient
|
||||
que le code, le cache de tuiles se remplit à la demande depuis la machine de
|
||||
traitement (section 4).
|
||||
|
||||
### 2. Accès SSH pour le rsync (la Pi tire les tuiles traitées)
|
||||
### 2. Accès SSH (déploiement)
|
||||
|
||||
Le rsync ayant été retiré, le SSH ne sert plus à ramener les tuiles (elles
|
||||
sont servies à la demande, section 4). Il sert au déploiement et au support
|
||||
: se connecter à la machine de traitement pour y inspecter `output/` ou y
|
||||
déposer des tuiles manuellement.
|
||||
|
||||
```bash
|
||||
ssh-keygen -t ed25519 # si pas encore de clé
|
||||
ssh-copy-id lidar@<ip-machine> # compte lecture sur output/
|
||||
ssh-copy-id lidar@<ip-machine> # compte sur la machine de traitement
|
||||
ssh lidar@<ip-machine> exit # 1re connexion : enregistre known_hosts
|
||||
```
|
||||
|
||||
La dernière commande évite le prompt « authenticity of host » pendant le
|
||||
rsync (le conteneur ne peut pas répondre interactivement).
|
||||
La dernière commande évite le prompt « authenticity of host » en connexion
|
||||
non interactive (le conteneur ne peut pas répondre).
|
||||
|
||||
Sur la machine puissante, le dossier `output/` doit être lisible par ce
|
||||
compte (ex. `/srv/lidar/output` si vous préférez un chemin dédié — adaptez
|
||||
LIDAR_SYNC_CMD).
|
||||
Le cache de tuiles du Pi se remplit à la demande depuis la machine de
|
||||
traitement ; ce compte SSH sert à l'inspecter ou à y déposer des tuiles
|
||||
manuellement si besoin.
|
||||
|
||||
Avec `serve-webapp.sh` et `run.sh`, `~/.ssh` (clé + known_hosts) est monté
|
||||
automatiquement en lecture seule dans le conteneur ; avec `docker compose`,
|
||||
le montage équivalent est à décommenter dans `docker-compose.webapp.yml`
|
||||
(voir l'option c ci-dessous).
|
||||
Avec `serve-webapp.sh` et `run.sh`, la clé SSH de l'hôte (`~/.ssh`, clé +
|
||||
known_hosts) est montée automatiquement en lecture seule dans le conteneur ;
|
||||
avec `docker compose`, le montage équivalent est à décommenter dans
|
||||
`docker-compose.webapp.yml` (voir l'option c ci-dessous). Le wrapper local
|
||||
`ssh` (agent forwarding) simplifie ces connexions.
|
||||
|
||||
### 3. Configurer et lancer
|
||||
|
||||
@ -103,12 +109,12 @@ configuration vit dans `webapp.env` (copie du modèle, non versionné) :
|
||||
|
||||
```bash
|
||||
cp webapp.env.example webapp.env
|
||||
nano webapp.env # LIDAR_GENERATION_URL, LIDAR_SYNC_CMD, jeton...
|
||||
nano webapp.env # LIDAR_GENERATION_URL, jeton...
|
||||
./serve-webapp.sh # démarre (build au premier lancement) et attend le serveur
|
||||
```
|
||||
|
||||
Sous-commandes : `stop`, `restart` (relit `webapp.env`), `status` (conteneur
|
||||
+ état de la sync), `sync` (force rsync + vignettes), `logs`, `update`
|
||||
+ état du rebuild), `sync` (rebuild + vignettes), `logs`, `update`
|
||||
(`git pull` + rebuild + redémarrage). Port hôte via `WEBAPP_PORT` dans
|
||||
`webapp.env` ou l'environnement (`WEBAPP_PORT=9000 ./serve-webapp.sh`).
|
||||
|
||||
@ -119,16 +125,13 @@ est monté automatiquement :
|
||||
```bash
|
||||
LIDAR_GENERATION_URL=http://192.168.1.50:8973 \
|
||||
LIDAR_REMOTE_TOKEN=un-secret-à-partager \
|
||||
LIDAR_SYNC_CMD="rsync -a --delete --exclude=*.tif --exclude=.generation* --exclude=index_thumbs --exclude=index_subtiles lidar@192.168.1.50:/srv/lidar/output/ /data/output/" \
|
||||
LIDAR_AUTO_SYNC_SECONDS=600 \
|
||||
./run.sh --serve-webapp # port 8973, ou --serve-webapp 9000
|
||||
```
|
||||
|
||||
`LIDAR_AUTO_SYNC_SECONDS` entretient le cache tout seul : toutes les N
|
||||
secondes, rsync ramène les nouvelles tuiles et les vignettes manquantes
|
||||
sont régénérées (les mtimes évitent tout recalcul inutile). Sans cette
|
||||
variable, le cache se rafraîchit à la demande : bouton ↻, fin d'un run,
|
||||
ou `POST /api/sync`.
|
||||
Les tuiles sont servies à la demande : une image absente du cache local est
|
||||
téléchargée depuis la machine de traitement au premier affichage, le cache
|
||||
se remplit ainsi progressivement. Le bouton ↻, la fin d'un run ou `POST
|
||||
/api/sync` déclenchent un rebuild de l'index et régénèrent les vignettes.
|
||||
|
||||
`LIDAR_REGEN_CIDR` restreint le lancement des générations (`POST
|
||||
/api/generate` : zones, sélection, complétion, régénération) aux clients
|
||||
@ -147,14 +150,10 @@ génération sont masqués et l'API répond 403.
|
||||
- `LIDAR_GENERATION_URL` : `http://<ip-machine>:8973`
|
||||
- `LIDAR_REMOTE_TOKEN` : la valeur de `LIDAR_API_TOKEN` de la machine
|
||||
(inutile si aucun token là-bas)
|
||||
- `LIDAR_SYNC_CMD` : la commande rsync qui copie `output/` distant vers
|
||||
`/data/output/` local, ex :
|
||||
- le cache local se remplit à la demande depuis `LIDAR_GENERATION_URL` (pas
|
||||
de `LIDAR_SYNC_CMD`)
|
||||
|
||||
```yaml
|
||||
- LIDAR_SYNC_CMD=rsync -a --delete --exclude=*.tif --exclude=.generation* --exclude=index_thumbs --exclude=index_subtiles lidar@192.168.1.50:/srv/lidar/output/ /data/output/
|
||||
```
|
||||
|
||||
Décommenter aussi le montage de la clé SSH (rsync) :
|
||||
Décommenter aussi le montage de la clé SSH (déploiement) :
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
@ -191,6 +190,52 @@ curl -X POST http://<ip-pi>:8973/api/sync
|
||||
(puis attendre la fin : `curl http://<ip-pi>:8973/api/sync` → `"running":
|
||||
false`.) Le bouton ↻ de la carte fait la même chose (sync + vignettes).
|
||||
|
||||
### 5. Centrer la carte sur la position GPS (téléphone)
|
||||
|
||||
Le bouton **⌖** (barre d'outils de la carte, à côté du recadrage) recentre la
|
||||
carte sur la position GPS du téléphone et y dessine un marqueur vert.
|
||||
|
||||
Les navigateurs n'exposent l'API Geolocation qu'en **contexte sécurisé**
|
||||
(HTTPS). Servie en `http://<ip-pi>:8973`, la carte ne peut donc pas obtenir la
|
||||
position sur téléphone : le bouton affiche alors « connexion sécurisée (HTTPS)
|
||||
requise ».
|
||||
|
||||
**TLS terminé par le proxy (cas d'usage ici)** — le certificat est porté par
|
||||
**Traefik** : le webapp sert du HTTP, Traefik expose `https://<domaine>` et y
|
||||
applique son certificat (valable, sans avertissement). Le téléphone se connecte
|
||||
sur l'URL Traefik → contexte sécurisé → le bouton ⌖ fonctionne.
|
||||
|
||||
La config Traefik (routage HTTPS) vit dans le fichier **override** local
|
||||
`docker-compose.webapp.override.yml` (non versionné, sur le Pi) — Compose le
|
||||
merge par-dessus `docker-compose.webapp.yml`. Le modèle versionné
|
||||
`docker-compose.webapp.override.yml.example` fournit les labels (provider
|
||||
Docker) qui routent `Host(\`${LIDAR_WEBAPP_HOST}\`)` vers le service, en
|
||||
`websecure` (443) + TLS avec le certificat porté par Traefik. Sur le Pi :
|
||||
|
||||
```bash
|
||||
cp docker-compose.webapp.override.yml.example docker-compose.webapp.override.yml
|
||||
# adapter le domaine : LIDAR_WEBAPP_HOST=carte.example.fr (dans un .env à
|
||||
# côté du compose, l'environnement, ou en dur dans la règle Host())
|
||||
# docker compose n'auto-charge PAS un override au nom custom (seulement
|
||||
# docker-compose.override.yml) → passer -f explicitement :
|
||||
docker compose -f docker-compose.webapp.yml \
|
||||
-f docker-compose.webapp.override.yml up -d --build
|
||||
```
|
||||
|
||||
Adapter si le proxy n'est pas en `websecure` ou que le provider n'est pas
|
||||
Docker : changer `entrypoints` / ajouter
|
||||
`traefik.http.routers.lidar-webapp.tls.certresolver=…`, ou déclarer le
|
||||
service directement dans la config Traefik. Le webapp est transparent au
|
||||
proxy (URLs relatives) et remonte l'IP réelle via `X-Forwarded-For` pour la
|
||||
restriction `LIDAR_REGEN_CIDR` : l'IP du téléphone doit y figurer pour lancer
|
||||
des générations.
|
||||
|
||||
> **Sans Traefik** — servir la carte en HTTPS avec un certificat auto-signé :
|
||||
> `./make-tls-cert.sh` crée `tls/webapp.{crt,key}`, à monter dans le
|
||||
> conteneur avec `LIDAR_SSL_CERTFILE` / `LIDAR_SSL_KEYFILE` (le chemin
|
||||
> `serve-webapp.sh` le fait automatiquement). Le téléphone accepte alors
|
||||
> l'avertissement « certificat non fiable » une fois.
|
||||
|
||||
## Mise à jour
|
||||
|
||||
Avec `serve-webapp.sh`, une seule commande (`git pull`, rebuild de l'image,
|
||||
@ -200,7 +245,7 @@ redémarrage) :
|
||||
./serve-webapp.sh update
|
||||
```
|
||||
|
||||
Sinon, sur le Pi, après un `git pull` (ou rsync du code) :
|
||||
Sinon, sur le Pi, après un `git pull` :
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.webapp.yml up -d --build # rebuild + redémarrage
|
||||
@ -212,15 +257,14 @@ chaque lancement ; il suffit de relancer la commande. Le cache de tuiles
|
||||
|
||||
## Dépannage
|
||||
|
||||
- **État d'une sync** : `curl http://<ip-pi>:8973/api/sync` → `running`,
|
||||
`phase` (`sync` puis `index`) et `error` (dernière erreur, ex. fin de
|
||||
journal rsync en cas d'échec). Les logs du conteneur :
|
||||
- **État d'un rebuild** : `curl http://<ip-pi>:8973/api/sync` → `running`,
|
||||
`phase` (`index`) et `error` (dernière erreur). Les logs du conteneur :
|
||||
`docker logs lidar-webapp` (ou `docker compose -f docker-compose.webapp.yml
|
||||
logs -f webapp`).
|
||||
- **`Permission denied (publickey)` pendant la sync** : refaire
|
||||
`ssh-copy-id lidar@<ip-machine>` et une connexion manuelle pour
|
||||
renseigner `known_hosts` ; vérifier que `~/.ssh` est monté dans le
|
||||
conteneur (automatique avec `run.sh`, à décommenter en compose).
|
||||
- **`Permission denied (publickey)` en SSH** : refaire
|
||||
`ssh-copy-id lidar@<ip-machine>` et une connexion manuelle pour renseigner
|
||||
`known_hosts` ; vérifier que `~/.ssh` est monté dans le conteneur
|
||||
(automatique avec `run.sh`, à décommenter en compose).
|
||||
- **Boutons de génération masqués / `403` sur `/api/generate`** : l'IP du
|
||||
client n'est dans aucun des réseaux de `LIDAR_REGEN_CIDR` (défaut :
|
||||
localhost + plages privées). Adapter la variable ou la vider pour lever
|
||||
@ -244,11 +288,10 @@ chaque lancement ; il suffit de relancer la commande. Le cache de tuiles
|
||||
à la machine de traitement, qui télécharge les dalles IGN puis les traite.
|
||||
La file de génération (progression tuile par tuile) est lue depuis la
|
||||
machine distante en direct.
|
||||
- À la fin du run, le navigateur appelle `/api/sync` : rsync ramène les
|
||||
images, le Pi régénère vignettes/sous-tuiles/index.html, puis recharge la
|
||||
carte. Le bouton ↻ relance le même cycle à tout moment. Avec
|
||||
`LIDAR_AUTO_SYNC_SECONDS`, le conteneur webapp seul maintient aussi son
|
||||
cache périodiquement (utile quand personne ne consulte la carte).
|
||||
- À la fin du run, le navigateur appelle `/api/sync` : les images produites
|
||||
sont servies à la demande depuis la machine de traitement, le Pi régénère
|
||||
vignettes/sous-tuiles/index.html, puis recharge la carte. Le bouton ↻
|
||||
relance le même cycle à tout moment.
|
||||
- Sans machine de traitement configurée, `./run.sh --serve-webapp` sert la
|
||||
carte en lecture seule depuis `output/` (cache figé, aucun traitement
|
||||
possible depuis l'interface).
|
||||
@ -266,7 +309,7 @@ chaque lancement ; il suffit de relancer la commande. Le cache de tuiles
|
||||
## Références
|
||||
|
||||
- `lidar_pipeline/webapp.py` : proxy distant (`LIDAR_GENERATION_URL`),
|
||||
`/api/sync`, cache local périodique (`LIDAR_AUTO_SYNC_SECONDS`), jeton
|
||||
`/api/sync` (rebuild de l'index), cache local à la demande, jeton
|
||||
`LIDAR_API_TOKEN`/`LIDAR_REMOTE_TOKEN`, restriction des générations au
|
||||
réseau local (`LIDAR_REGEN_CIDR`).
|
||||
- `lidar_pipeline/index.py` : vignettes/index sans GDAL (pyproj ou repli
|
||||
|
||||
Reference in New Issue
Block a user