0 Votes

Dawarich

Version 2.1 par john le 2026/09/20 00:01

Historique de localisation auto-hébergé, alternative à Google Timeline. Le géocodage inverse (adresse et nom des lieux) est assuré par une instance Photon locale, sans service externe ni limite de requêtes.

Architecture

ConteneurRôle
dawarich_appApplication web (Rails)
dawarich_sidekiqTâches de fond : imports, détection des visites, géocodage
dawarich_dbPostgreSQL + PostGIS
dawarich_redisFile de tâches
photonGéocodage inverse, stack séparée

Dawarich et Photon communiquent par le réseau proxy, sur lequel se trouve aussi SWAG.

Variables d'environnement

À définir dans l'onglet « Environment variables » de la stack Portainer :

VariableValeur
POSTGRES_USERUtilisateur de la base
POSTGRES_PASSWORDMot de passe de la base
POSTGRES_DBNom de la base
APPLICATION_HOSTSNom de domaine d'accès
SECRET_KEY_BASEClé générée avec openssl rand -hex 64

Stack Dawarich

name: dawarich

networks:
 dawarich:
 proxy:
   external: true

services:
 dawarich_redis:
   image: redis:7.4-alpine
   container_name: dawarich_redis
   command: >
     redis-server
     --save 900 1
     --save 300 10
     --appendonly no
   networks:
      - dawarich
   volumes:
      - dawarich_shared:/data
   restart: always
   healthcheck:
     test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
     interval: 10s
     retries: 5
     start_period: 30s
     timeout: 10s

 dawarich_db:
   image: postgis/postgis:17-3.5-alpine
   shm_size: 1G
   container_name: dawarich_db
   volumes:
      - dawarich_db_data:/var/lib/postgresql/data
      - dawarich_shared:/var/shared
   networks:
      - dawarich
   environment:
     POSTGRES_USER: ${POSTGRES_USER}
     POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
     POSTGRES_DB: ${POSTGRES_DB}
   restart: always
   healthcheck:
     test: [ "CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}" ]
     interval: 10s
     retries: 5
     start_period: 30s
     timeout: 10s

 dawarich_app:
   image: freikin/dawarich:latest
   container_name: dawarich_app
   volumes:
      - dawarich_public:/var/app/public
      - dawarich_watched:/var/app/tmp/imports/watched
      - dawarich_storage:/var/app/storage
      - dawarich_db_data:/dawarich_db_data
   networks:
      - dawarich
      - proxy
   ports:
      - "3001:3000"
   stdin_open: true
   tty: true
   entrypoint: web-entrypoint.sh
   command: ['bin/rails', 'server', '-p', '3000', '-b', '::']
   restart: unless-stopped
   environment:
     RAILS_ENV: production
     REDIS_URL: redis://dawarich_redis:6379
     DATABASE_HOST: dawarich_db
     DATABASE_PORT: 5432
     DATABASE_USERNAME: ${POSTGRES_USER}
     DATABASE_PASSWORD: ${POSTGRES_PASSWORD}
     DATABASE_NAME: ${POSTGRES_DB}
     APPLICATION_HOSTS: ${APPLICATION_HOSTS}
     TIME_ZONE: Europe/Paris
     APPLICATION_PROTOCOL: https
     PROMETHEUS_EXPORTER_ENABLED: "false"
     SECRET_KEY_BASE: ${SECRET_KEY_BASE}
     RAILS_LOG_TO_STDOUT: "true"
     SELF_HOSTED: "true"
     STORE_GEODATA: "true"
     PHOTON_API_HOST: photon:2322
     PHOTON_API_USE_HTTPS: "false"
   logging:
     driver: "json-file"
     options:
       max-size: 100m
       max-file: "5"
   healthcheck:
     test: [ "CMD-SHELL", "wget -qO - --header='X-Forwarded-Proto: https' http://127.0.0.1:3000/api/v1/health | grep -q '\"status\"\\s*:\\s*\"ok\"'" ]
     interval: 10s
     retries: 30
     start_period: 30s
     timeout: 10s
   depends_on:
     dawarich_db:
       condition: service_healthy
       restart: true
     dawarich_redis:
       condition: service_healthy
       restart: true
   deploy:
     resources:
       limits:
         cpus: "0.50"
         memory: 4G

 dawarich_sidekiq:
   image: freikin/dawarich:latest
   container_name: dawarich_sidekiq
   volumes:
      - dawarich_public:/var/app/public
      - dawarich_watched:/var/app/tmp/imports/watched
      - dawarich_storage:/var/app/storage
   networks:
      - dawarich
      - proxy
   stdin_open: true
   tty: true
   entrypoint: sidekiq-entrypoint.sh
   command: ['sidekiq']
   restart: on-failure
   environment:
     RAILS_ENV: production
     REDIS_URL: redis://dawarich_redis:6379
     DATABASE_HOST: dawarich_db
     DATABASE_PORT: 5432
     DATABASE_USERNAME: ${POSTGRES_USER}
     DATABASE_PASSWORD: ${POSTGRES_PASSWORD}
     DATABASE_NAME: ${POSTGRES_DB}
     APPLICATION_HOSTS: ${APPLICATION_HOSTS}
     BACKGROUND_PROCESSING_CONCURRENCY: "5"
     APPLICATION_PROTOCOL: https
     PROMETHEUS_EXPORTER_ENABLED: "false"
     SECRET_KEY_BASE: ${SECRET_KEY_BASE}
     RAILS_LOG_TO_STDOUT: "true"
     SELF_HOSTED: "true"
     STORE_GEODATA: "true"
     PHOTON_API_HOST: photon:2322
     PHOTON_API_USE_HTTPS: "false"
   logging:
     driver: "json-file"
     options:
       max-size: 100m
       max-file: "5"
   healthcheck:
     test: [ "CMD-SHELL", "pgrep -f sidekiq" ]
     interval: 10s
     retries: 30
     start_period: 30s
     timeout: 10s
   depends_on:
     dawarich_db:
       condition: service_healthy
       restart: true
     dawarich_redis:
       condition: service_healthy
       restart: true
     dawarich_app:
       condition: service_healthy
       restart: true

volumes:
 dawarich_db_data:
 dawarich_shared:
 dawarich_public:
 dawarich_watched:
 dawarich_storage:

Points particuliers :

  • Port hôte 3001 : le 3000 est déjà pris sur le serveur.
  • L'en-tête X-Forwarded-Proto: https du healthcheck est indispensable avec APPLICATION_PROTOCOL: https, sinon sidekiq ne démarre jamais (voir Dépannage).
  • PHOTON_API_HOST et PHOTON_API_USE_HTTPS doivent être présents sur app et sidekiq.

Stack Photon

name: photon

networks:
 proxy:
   external: true

services:
 photon:
   image: rtuszik/photon-docker:latest
   container_name: photon
   environment:
     REGION: europe
     UPDATE_STRATEGY: SEQUENTIAL
     UPDATE_INTERVAL: 720h
     LOG_LEVEL: INFO
   volumes:
      - photon_data:/photon/data
   networks:
      - proxy
   ports:
      - "2322:2322"
   restart: unless-stopped

volumes:
 photon_data:
  • Région europe : environ 29 Go à télécharger, 47 Go une fois extraits. Compter une heure avant que l'API réponde au premier démarrage.
  • L'index se met à jour seul tous les 30 jours (UPDATE_INTERVAL).
  • Les données Photon ne sont pas sauvegardées : elles se retéléchargent.

Accès

Publié par SWAG sur un sous-domaine, avec un proxy-conf écrit à la main (SWAG n'en fournit pas pour Dawarich) : voir l'exemple commenté sur la page Reverse proxy.

Pas d'Authelia : l'accès est protégé par l'identifiant de Dawarich. Les chemins /api (applications mobiles de suivi) et /cable (mises à jour en direct) ont chacun leur bloc location.

Import de l'historique

  • Source fiable : les fichiers JSON exportés directement depuis l'application Google Maps du téléphone.
  • L'archive Google Takeout ne contient plus la Timeline : seulement des métadonnées de photos, qui créent un point par photo. Ne pas l'importer.

Console Rails

docker exec -it dawarich_app bin/rails console

Utile pour les opérations en masse ; exemples dans Dépannage.

Lieux et tags

  • Un tag s'applique à un lieu, jamais à un point ni à une zone.
  • Le rayon d'un tag est un rayon de confidentialité : les points qu'il contient sont masqués dans les exports et les vues publiques.

Sauvegarde

Les données sont dans des volumes Docker nommés, hors du dossier sauvegardé. Seul le dump SQL de dawarich_db les protège : il doit figurer dans la boucle PostgreSQL du script de Sauvegarde.