# Dawarich

Stores and maps your location history, as a self-hosted alternative to Google Timeline.

- Replaces: [Google Timeline](https://openlogs.fyi/alternatives/google-timeline)
- Summary: Paid location history services, such as Google Timeline.
- Stack: Ruby (language), Redis (database)
- Deployment: docker_compose
- License: AGPL-3.0 (osi) [source](https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/LICENSE)
- Business model: unknown. The README at the pinned commit does not state a business model, so it stays unknown. ([source](https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/README.md), read 2026-10-22)
- Difficulty: medium. 4 services (1 database or broker: redis), 7 volume mounts, no env values to set, no elevated host access. Heuristic score 5 of 11: medium.
- Requirements: not stated
- Repository: [Freika/dawarich](https://github.com/Freika/dawarich)

## Install

1. Docker with the Compose plugin ([source](https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/docker/docker-compose.yml))

   ```text
   A host with Docker and the Docker Compose plugin. This entry runs from a compose file.
   ```

2. Save the compose file as docker-compose.yml ([source](https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/docker/docker-compose.yml))

   ```yaml
   # full list of environment variables with descriptions can be found in the documentation:
   # https://dawarich.app/docs/self-hosting/environment-variables/
   
   networks:
     dawarich:
   
   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
       # image: imresamu/postgis:17-3.5-alpine # If you're on ARM architecture, use this image instead
       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}
         POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password}
         POSTGRES_DB: ${POSTGRES_DB:-dawarich_development}
       restart: always
       healthcheck:
         test: [ "CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-dawarich_development}" ]
         interval: 10s
         retries: 5
         start_period: 30s
         timeout: 10s
       # command: postgres -c config_file=/etc/postgresql/postgresql.conf # Use custom config, uncomment if you want to use a custom config
   
     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
       ports:
         - "${DAWARICH_APP_PORT:-3000}:3000"
       stdin_open: true
       tty: true
       entrypoint: web-entrypoint.sh
       command: ['bin/rails', 'server', '-p', '3000', '-b', '::']
       restart: unless-stopped
       environment:
         RAILS_ENV: ${RAILS_ENV:-production}
         ### To run under a non-root user, set PUID/PGID here (do NOT use `user:`).
         # PUID: ${PUID:-1000}
         # PGID: ${PGID:-1000}
         REDIS_URL: ${REDIS_URL:-redis://dawarich_redis:6379}
         DATABASE_HOST: ${DATABASE_HOST:-dawarich_db}
         DATABASE_PORT: ${DATABASE_PORT:-5432}
         DATABASE_USERNAME: ${DATABASE_USERNAME:-postgres}
         DATABASE_PASSWORD: ${DATABASE_PASSWORD:-password}
         DATABASE_NAME: ${DATABASE_NAME:-dawarich_development}
         APPLICATION_HOSTS: ${APPLICATION_HOSTS:-localhost,::1,127.0.0.1}
         TIME_ZONE: ${TIME_ZONE:-Europe/London}
         APPLICATION_PROTOCOL: ${APPLICATION_PROTOCOL:-http}
         PROMETHEUS_EXPORTER_ENABLED: ${PROMETHEUS_EXPORTER_ENABLED:-false}
         SECRET_KEY_BASE: ${SECRET_KEY_BASE:-"CHANGE_ME"}
         RAILS_LOG_TO_STDOUT: ${RAILS_LOG_TO_STDOUT:-true}
         SELF_HOSTED: ${SELF_HOSTED:-true}
         STORE_GEODATA: ${STORE_GEODATA:-true}
         # One preloaded Puma worker is plenty for a household instance and
         # halves idle memory. Raise for busier instances.
         WEB_CONCURRENCY: ${WEB_CONCURRENCY:-1}
         ### OTP encryption keys are required if you want to use 2FA
         # OTP_ENCRYPTION_PRIMARY_KEY: ${OTP_ENCRYPTION_PRIMARY_KEY:-}
         # OTP_ENCRYPTION_DETERMINISTIC_KEY: ${OTP_ENCRYPTION_DETERMINISTIC_KEY:-}
         # OTP_ENCRYPTION_KEY_DERIVATION_SALT: ${OTP_ENCRYPTION_KEY_DERIVATION_SALT:-}
       logging:
         driver: "json-file"
         options:
           max-size: ${LOG_MAX_SIZE:-100m}
           max-file: ${LOG_MAX_FILE:-5}
       healthcheck:
         test: [ "CMD-SHELL", "wget -qO - 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: ${APP_CPU_LIMIT:-0.50}
             memory: ${APP_MEMORY_LIMIT:-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
       stdin_open: true
       tty: true
       entrypoint: sidekiq-entrypoint.sh
       command: ['sidekiq']
       restart: unless-stopped
       environment:
         RAILS_ENV: ${RAILS_ENV:-production}
         ### To run under a non-root user, set PUID/PGID here (do NOT use `user:`).
         # PUID: ${PUID:-1000}
         # PGID: ${PGID:-1000}
         REDIS_URL: ${REDIS_URL:-redis://dawarich_redis:6379}
         DATABASE_HOST: ${DATABASE_HOST:-dawarich_db}
         DATABASE_PORT: ${DATABASE_PORT:-5432}
         DATABASE_USERNAME: ${DATABASE_USERNAME:-postgres}
         DATABASE_PASSWORD: ${DATABASE_PASSWORD:-password}
         DATABASE_NAME: ${DATABASE_NAME:-dawarich_development}
         APPLICATION_HOSTS: ${APPLICATION_HOSTS:-localhost,::1,127.0.0.1}
         # 3 job threads keep idle memory and DB connections low; raise
         # temporarily for large imports.
         BACKGROUND_PROCESSING_CONCURRENCY: ${BACKGROUND_PROCESSING_CONCURRENCY:-3}
         APPLICATION_PROTOCOL: ${APPLICATION_PROTOCOL:-http}
         PROMETHEUS_EXPORTER_ENABLED: ${PROMETHEUS_EXPORTER_ENABLED:-false}
         SECRET_KEY_BASE: ${SECRET_KEY_BASE:-"CHANGE_ME"}
         RAILS_LOG_TO_STDOUT: ${RAILS_LOG_TO_STDOUT:-true}
         SELF_HOSTED: ${SELF_HOSTED:-true}
         STORE_GEODATA: ${STORE_GEODATA:-true}
         ### OTP encryption keys are required if you want to use 2FA
         # OTP_ENCRYPTION_PRIMARY_KEY: ${OTP_ENCRYPTION_PRIMARY_KEY:-}
         # OTP_ENCRYPTION_DETERMINISTIC_KEY: ${OTP_ENCRYPTION_DETERMINISTIC_KEY:-}
         # OTP_ENCRYPTION_KEY_DERIVATION_SALT: ${OTP_ENCRYPTION_KEY_DERIVATION_SALT:-}
       logging:
         driver: "json-file"
         options:
           max-size: ${LOG_MAX_SIZE:-100m}
           max-file: ${LOG_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:
   ```

3. Set the values the compose file needs ([source](https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/docker/docker-compose.yml))

   ```text
   Replace the placeholder values listed under Gotchas.
   ```

4. Start it ([source](https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/docker/docker-compose.yml))

   ```bash
   docker compose up -d
   ```

5. Open the app ([source](https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/docker/docker-compose.yml))

   ```text
   Open http://localhost:3000. The compose file publishes host port 3000 for the dawarich_app service.
   ```

Compose file check: config_ok on 2026-10-22.

## Gotchas and maintenance

### Gotchas

- Some images use the latest tag or no tag: Images without a pinned version: dawarich_app: freikin/dawarich:latest, dawarich_sidekiq: freikin/dawarich:latest. A later pull can get a different version. ([source](https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/docker/docker-compose.yml), checked 2026-10-22)
- The compose file has placeholder values: Placeholder values: POSTGRES_PASSWORD is "password" (dawarich_db), DATABASE_PASSWORD is "password" (dawarich_app), SECRET_KEY_BASE is ""CHANGE_ME"" (dawarich_app), DATABASE_PASSWORD is "password" (dawarich_sidekiq), SECRET_KEY_BASE is ""CHANGE_ME"" (dawarich_sidekiq). ([source](https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/docker/docker-compose.yml), checked 2026-10-22)
- The compose file publishes host ports: Host ports: 3000 (dawarich_app). A port without a host address listens on all host network interfaces. ([source](https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/docker/docker-compose.yml), checked 2026-10-22)

### Signals

Computed from a GitHub snapshot taken 2026-10-22.

- Open issues and pull requests: 198
- Stars: 10709, forks: 405
- Last push: 2026-10-21 (0 days ago)
- Latest release: 1.16.0 on 2026-10-17 (4 days ago)

## Sources

- [Repository: https://github.com/Freika/dawarich](https://github.com/Freika/dawarich)
- [License: https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/LICENSE](https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/LICENSE)
- [Business model: https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/README.md](https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/README.md)
- [Compose file: https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/docker/docker-compose.yml](https://github.com/Freika/dawarich/blob/2dc26c40dff1f2e4b6c7e22d78ab5a271c0e8957/docker/docker-compose.yml)

---
Canonical: https://openlogs.fyi/tools/dawarich  
Last updated: 2026-10-22
