Déployer (ou pas) une instance geovisio/Panoramax

Bonjour,

Nouvel utilisateur de Panoramax après l’acquisition d’une Gopro Max par ma collectivité (Vienne Condrieu Agglomération - Sud de Lyon), c’est avec grand intérêt que je suis tombé sur ce fil et vu qu’il était possible d’installer Geovisio Cli sous Docker. L’upload des photos en ligne de commande est super efficace.

En explorant un peu plus ce fil, je lis qu’il est possible de monter une instance Panoramax, notamment via docker compose et cette stack docker-compose-full.yml : offers everything (Website, API, database, Keycloak and blurring API).

Curieux, j’ai commencé à bidouiller sur un docker en local via la documentation mais j’ai encore plus d’interrogations !

Quel intérêt de monter ce genre d’instance ?

Est-ce que ces briques logicielles sous container Docker permettent de monter un serveur sous Geovisio et de visionner ces acquisitions en local ?

Je rencontre pas mal de soucis à monter cette stack via docker-compose-full.yml surtout au niveau de l’authentification. Je n’ai pas encore réussi à faire fonctionner le container website avec l’authentification Keycloack. Je rencontre une erreur 500 sur le container Keycloack (je n’ai pas l’erreur sous la main à l’heure où j’écris ce message mais je ne manquerai pas de vous la partager).

Je débute avec la containerisation via Docker et j’avoue ne pas comprendre la présence de la déclaration image et build dans le même service :

api:
    image: geovisio/api:latest
    build:
        context: ..
        dockerfile: Dockerfile
        cache_from:
        - registry.gitlab.com/geovisio/api:build_cache

Bref, j’ai un peu de mal à cerner les tenants et aboutissants de la mise en instance d’un serveur Panoramax via le Gitlab et si vous pouviez m’éclairer, ce serait top !

Dans l’attente de vos éclaircissements,

Fabien

1 Like

Une organisation (collectivité, entreprise, asso), voire un particulier peut déployer une instance geovisio pour ses besoins et son usage propre.

Il y a déjà des instance de ce type déployées soit pour exploiter des prisesede vues qui ne peuvent pas être rendues publiques (intérieurs de bâtiments ou sites non ouverts au publics, voire sensibles) ou pour toute autre raison (pas envie de partager ses prises de vues).

Une collectivité par exemple peut aussi ne pas vouloir se mettre en dépendance d’un service externe et déployer son instance pour en avoir la totale maîtrise.

C’est tout à fait ça, c’est le but.

Merci Christian pour ces réponses !

C’est ce qu’il me semblait mais ce n’était pas encore assez explicite dans la doc et les liens que j’avais exploité (pour ma part).

Pour le coup, je n’avais pas pensé à prendre des photos en intérieur. Pour la gestion techniques de nos bâtiments, cela peut être une plus-value intéressante à mettre en place.

J’en profite pour savoir s’il y a des personnes qui ont mis en place une instance Geovisio en interne et si elles veulent partager leurs bonnes pratiques et recettes ?

Merci pour cette éclairage.

Le but c’est aussi de répartir la charge de l’hébergement sur plein de petits/moyens acteurs car personne n’est en capacité d’héberger toutes les photos prises sur le territoire. C’est en Po qu’on parle de mémoire.

D’accord, oui, j’imagine bien qu’il faut stocker toutes ces photos quelques parts !

Du coup, c’est ici qu’on parle de la fédération d’instances Panoramax afin de mutualiser toutes les prises de vue ?

L’aboutissement de la réflexion sur la fédération a donnée cet échange :

et surtout :

https://api.panoramax.xyz

Je gère deux instances, une ancienne de “démo”, publique, et une privée avec des photos indoor.
En résumé, pour l’instance privée, je l’ai installée avant que la partie authentification existe, et je gère les imports de photo directement depuis le serveur, en ligne de commande. J’ai un reverse proxy devant, sur lequel j’ai une authentification basique (avec https://nginxproxymanager.com/)

Je suis loin d’être admin sys ou devops, ce qui fait que c’est certainement perfectible. Je me suis moi aussi un peu cassé les dents sur la partie Keycloack, et comme l’instance était déjà fonctionnelle je n’ai pas creusé beaucoup plus.

Ca me fait me dire qu’une petite visio technique pour montrer les bonnes pratiques pour installer et gérer une instance, ça pourrait étre intéressant, non ?

Ok, je vais persévérer dans mes tests, je vais bien m’en sortir.

Une visio technique est une très bonne idée :+1:

Je reviens vers vous avec mon soucis au niveau de la connexion via le container auth.

Lorsque j’accède à mon container website sur l’url local http://localhost:3000/ et que je veux me connecter ou créer un utilisateur :

J’accède à la page de connexion de Keycloack :
image

Lorsque je valide, je rencontre une erreur 500. Si je crée un utilisateur, celui-ci est bien ajouté dans le realm Geovision de Keycloack mais impossible de me connecter via l’API : http://localhost:5000/api/auth/redirect?state=gbgmrlnnRKcgVTlvZ8woe6VTV5Gf9W&session_state=3c987281-5673-4ea3-b192-771cf749c2fd&code=ca0df1fa-5a2c-47ec-a036-665e49869ff8.3c987281-5673-4ea3-b192-771cf749c2fd.d365fe1b-c06e-4edd-9523-9dfc89ddc43f

Qui correspond à cette erreur dans le log du container auth :

2023-11-09 14:53:59,345 WARN  [org.keycloak.events] (executor-thread-1) type=CODE_TO_TOKEN_ERROR, realmId=08d2cdee-0ab0-40fa-91ff-0bf960316677, clientId=geovisio, userId=null, ipAddress=172.21.0.1, error=invalid_client_credentials, grant_type=authorization_code

Et à cette erreur dans le container api :

2023-11-09 16:08:42,273 [waitress-3][ERROR] geovisio: Exception on /api/auth/redirect [GET]
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2190, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1486, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.9/site-packages/flask_cors/extension.py", line 165, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1484, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1469, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "/opt/360app/geovisio/web/auth.py", line 55, in auth
    tokenResponse = utils.auth.oauth_provider.client.authorize_access_token()
  File "/usr/local/lib/python3.9/site-packages/authlib/integrations/flask_client/apps.py", line 101, in authorize_access_token
    token = self.fetch_access_token(**params, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/authlib/integrations/base_client/sync_app.py", line 342, in fetch_access_token
    token = client.fetch_token(token_endpoint, **params)
  File "/usr/local/lib/python3.9/site-packages/authlib/oauth2/client.py", line 207, in fetch_token
2023-11-09 16:08:42,273 [waitress-3][ERROR] geovisio: Exception on /api/auth/redirect [GET]
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2190, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1486, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.9/site-packages/flask_cors/extension.py", line 165, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1484, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1469, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "/opt/360app/geovisio/web/auth.py", line 55, in auth
    tokenResponse = utils.auth.oauth_provider.client.authorize_access_token()
  File "/usr/local/lib/python3.9/site-packages/authlib/integrations/flask_client/apps.py", line 101, in authorize_access_token
    token = self.fetch_access_token(**params, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/authlib/integrations/base_client/sync_app.py", line 342, in fetch_access_token
    token = client.fetch_token(token_endpoint, **params)
  File "/usr/local/lib/python3.9/site-packages/authlib/oauth2/client.py", line 207, in fetch_token
    return self._fetch_token(
  File "/usr/local/lib/python3.9/site-packages/authlib/oauth2/client.py", line 364, in _fetch_token
    return self.parse_response_token(resp)
  File "/usr/local/lib/python3.9/site-packages/authlib/oauth2/client.py", line 340, in parse_response_token
    raise self.oauth_error_class(
authlib.integrations.base_client.errors.OAuthError: unauthorized_client: Invalid client or Invalid client credentials
    return self._fetch_token(
  File "/usr/local/lib/python3.9/site-packages/authlib/oauth2/client.py", line 364, in _fetch_token
    return self.parse_response_token(resp)
  File "/usr/local/lib/python3.9/site-packages/authlib/oauth2/client.py", line 340, in parse_response_token
    raise self.oauth_error_class(
authlib.integrations.base_client.errors.OAuthError: unauthorized_client: Invalid client or Invalid client credentials

Voilà, je sèche pour le moment. Peut-être un souci à la redirection :thinking:

Si quelqu’un a une idée !!

Je me réponds à moi-même !

En fait, je n’avais pas mis le même secret pour les 2 variables d’environnement du container API et AUTH pour ces variables :
GEOVISIO_CLIENT_SECRET: what_a_secret
OAUTH_CLIENT_SECRET: what_a_secret

Il faut que ce soit la même clé pour que Keycloack identifie bien quel client essaie de se connecter via l’API.

services:
  auth:
    command: start-dev --import-realm
    environment:
      GEOVISIO_BASE_URL: http://localhost:5000
      GEOVISIO_CLIENT_SECRET: what_a_secret
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: password
      KEYCLOAK_FRONTEND_URL: http://localhost:5000/api/auth/login
      KC_HTTP_PORT: 8182
    healthcheck:
      test: curl --fail http://localhost:8182/realms/geovisio
      timeout: 5s
      interval: 5s
      retries: 5
      start_period: 60s
    image: quay.io/keycloak/keycloak:20.0.1
    ports:
      - 8182:8182
    volumes:
      - ./keycloak-realm.json:/opt/keycloak/data/import/geovisio_realm.json

  api:
    image: geovisio/api:latest
    build:
      context: ..
      dockerfile: Dockerfile
      cache_from:
        - registry.gitlab.com/geovisio/api:build_cache
    command:
    - api
    depends_on:
      auth:
        condition: service_healthy
      db:
        condition: service_healthy
    environment:
      OAUTH_CLIENT_ID: geovisio
      OAUTH_CLIENT_SECRET: what_a_secret
      DB_URL: postgres://gvs:gvspwd@db/geovisio
      OAUTH_OIDC_URL: http://localhost:8182/realms/geovisio
      OAUTH_PROVIDER: oidc
      FLASK_SECRET_KEY: a_very_secret_key_never_to_be_used_in_production
      API_FORCE_AUTH_ON_UPLOAD: True
      API_BLUR_URL: http://localhost:5500
      PICTURE_PROCESS_THREADS_LIMIT: 0
      PICTURE_PROCESS_DERIVATES_STRATEGY: PREPROCESS
      FS_URL: /data/360app
    ports:
      - 5000:5000
    volumes:
      - pic_data:/data/360app
    extra_hosts:
      - "localhost:host-gateway"

Je commence à bien identifier qui fait quoi, j’avance pas mal !
Dès que c’est un peu stable, j’essaie de tout compiler dans un github pour ma doc perso et pour partager à la communauté.

Bonne soirée

1 Like

Du coup, je m’interroge sur votre méthode d’acquisition des photos en intérieur. Quid la géolocalisation des photos ?

J’ai essayé avec la GoPro Max mais elle n’a pas été capable d’identifier la géolocalisation et de la stocker en exif sur les photos.

Comment procéder vous ?

Encore Merci

On géolocalise à la main, avec le “support layer” de Josm.

J’en parle brièvement dans cette vidéo, et j’en ferai un épisode dédié dans la série gestion des photos dans Josm

1 Like

Merci, je vais regarder ça de plus près !

Je suis dispo si vous voulez qu’on discute déploiement d’une instance.