Skip to content

Store and access data published by OwnTracks apps within PostgreSQL/MySQL/Sqlite

License

Notifications You must be signed in to change notification settings

hrshadhin/ot-recorder

Repository files navigation

OwnTracks Recorder

build gosec codecov Go Report Card

Store and access data published by OwnTracks apps in (PostgreSQL, MySQL or Sqlite) via REST API. Self-hosted and Google-free location tracking system.

Architecture

architecture of ot-recorder

Index

System requirements

  • OwnTracks app (Android / iOS)
  • PostgreSQL / MySQL / MariaDB / Sqlite
  • Optional
    • Domain for public access
    • Reverse Proxy(NGINX/HA/Caddy) for TLS, HTTPS
    • Grafana visualization

Getting started

Create Database and Users

For sqlite no need to create database or user.

  • Create database owntracks
  • Create a user for application(read/write)
  • Create a user for grafana(read only)

Configuration

  • create a config.yml file or copy from _doc/config.yml
  • customize the config
    app:
      env: production
      host: localhost
      port: 8000
      read_timeout: 2s
      write_timeout: 5s
      idle_timeout: 3s
      context_timeout: 2s
      data_path: ./data # for sqlite | value must be /persist for docker
      time_zone: 'Asia/Dhaka'
      debug: false
    
    hook:
    telegram:
      secret_token: secret # webhook secret_token
      chat_id: -123 # group chat id
    
    # For PostgreSQL
    database:
      type: postgres
      host: localhost
      port: 5432
      name: owntracks
      username: dev
      password: dev
      ssl_mode: disable
      max_open_conn: 1
      max_idle_conn: 1
      max_life_time: 10s
      debug: false
    
    # For MySQL or MariaDB
    #database:
    #  type: mysql
    #  host: localhost
    #  port: 3306
    #  name: owntracks
    #  username: dev
    #  password: dev
    #  max_open_conn: 1
    #  max_idle_conn: 1
    #  max_life_time: 10s
    #  debug: false
    
    # For Sqlite
    #database:
    # type: sqlite
    # name: owntracks
    # max_open_conn: 1
    # max_idle_conn: 1
    # max_life_time: 10s
    # debug: false
  • NGINX config (Optional) here

Deploy OwnTracks Recorder

Using Systemd.d service

  • Download the binary from release page or build from source Check here
  • Move binary mv ot-recorder /usr/local/bin/ot-recorder
  • It's assumed that your config file is located under /opt/owntracks-recorder
  • Place this owntracks-recorder.service file into /etc/systemd/system
    [Unit]
    Description=Owntracks Recorder server
    Requires=network.target
    After=network.target
    
    [Service]
    Type=simple
    WorkingDirectory=/opt/owntracks-recorder
    ExecReload=/bin/kill -HUP $MAINPID
    ExecStart=/usr/local/bin/ot-recorder --config /opt/owntracks-recorder/config.yml serve
    
    Restart=always
    RestartSec=3
    
    [Install]
    WantedBy=multi-user.target
    
    Then run sudo systemctl enable owntracks-recorder.service Finally run sudo systemctl start owntracks-recorder.service to start and check status by running sudo systemctl status owntracks-recorder.service

Using Docker

  • Docker compose
    # persistance data directory for sqlite
    mkdir data
    sudo chown -R 1000:1000 data
    # _deploy/docker-compose.yml
    version: "3.5"
    
    services:
      owntracks-recorder:
        image: hrshadhin/ot-recorder
        container_name: owntracks-recorder
        restart: unless-stopped
        volumes:
          - ${PWD}/config.yml:/app/config.yml
          - ${PWD}/data:/persist # only for sqlite
        ports:
          - "8000:8000"
        environment:
          - TZ=Asia/Dhaka
    # run container in background
    docker-compose up -d
    
    # run migrations
    docker-compose exec owntracks-recorder /app/ot-recorder migrate up
  • Docker CLI
    # run container in background
    docker run --name owntracks-recorder -p 8000:8000 \
        -v $(pwd)/config.yml:/app/config.yml \
        -v $(pwd)/data:/persist \
        hrshadhin/ot-recorder:latest
    
    # run migrations
    docker exec owntracks-recorder /app/ot-recorder migrate up

Ansible

Setup Mobile APP

  • Install app here
  • Configure APP
    mode: HTTP
    
    endpoint:
    http://host[:port]/api/v1/ping #HTTP
    OR
    https://host[:port]/api/v1/ping # HTTPS/TLS
    OR
    http[s]://[user[:password]@]host[:port]/api/v1/ping # If basic auth enabled
    
    username: dev # <= 20 letter
    password: dev # set it, if basic auth enabled and endpoint dont have auth info
    device: phone # <= 20 letter
    trackingid: t1 # <= 2 letter

Grafana Integration

  • GeoMap Panel grafan-dashboard
  • Queries
    -- Location pings
    SELECT
      to_timestamp(created_at) as "time", lat, lon,
      acc as accuracy, vel as velocity
    FROM locations
    WHERE
      $__unixEpochFilter(created_at)
    ORDER BY created_at
    
    -- Battery Level
    SELECT
      created_at as time, batt
    FROM locations
    WHERE
      $__unixEpochFilter(created_at)
    ORDER BY created_at
    
    -- Velocity
    SELECT
      created_at as time, vel
    FROM locations
    WHERE
      $__unixEpochFilter(created_at)
    ORDER BY created_at
    
    -- Last Location
    SELECT
      to_timestamp(created_at) as "time",
      lat, lon, acc as accuracy, vel as velocity
    FROM locations
    ORDER BY created_at DESC
    LIMIT 1
  • Dashboard Json

Telegram Integration

Create Bot

  • search @BotFather bot and start
  • type /newbot and follow bot instructions
  • Copy bot token and keep it for later use
  • type /setprivacy and Enable it
  • type setcommands to set commands to the bot
    loc - Get user last location
    location - Get user last location
    help - For a list of commands
    

Create Group

  • Create group and add bot to this group and other members if needed
  • Now got to @BotFather and disable bot setting, so no one can add this bot to other groups
  • type /setjoingroups and Disable it
  • send a dummy message to the bot /my_id @my_bot
  • go to following url: https://api.telegram.org/botXXX:YYYY/getUpdates and replace XXX:YYYY with your bot token
  • Look for "chat":{"id":-zzzzzzzzzz, | -zzzzzzzzzz is your chat_id (with the negative sign)
  • Testing: You can test sending a message to the group with a curl:
    curl -X POST "https://api.telegram.org/botXXX:YYYY/sendMessage" -d "chat_id=-zzzzzzzzzz&text=my sample text"

If you miss step 4, there would be no update for the group you are looking for

Configure webhook

  • Set webhook to the bot
      CURL -X GET https://api.telegram.org/botXXX:YYYY/setWebhook?url=https://[host]:[port]/hooks/telegram&secret_token=SSSSZZZSSSS
    • Replace XXX:YYYY with your bot token
    • Replace [host] & [port] with ip or domain
    • Replace SSSSZZZSSSS with secret_token. This token is different from your bot token.

Configure OT-recorder

  • Go to your config.yml file
  • Add secret_token & chat_id in hooks -> telegram section
  • Now restart ot-recorder server

Test Message

  • Go to your telegram group
  • Type /loc <username>
  • Examples
    /loc @username
    /location @username
    /location username
    /loc@your_bot_name username
    /location@your_bot_name @username
    /help

Development

  • Copy config file mv _doc/config ./ to root directory and change it
  • Local
    make build # build binary
    make version # check binary
    make serve # run the application
    make migrate-up
    make test-unit
    make test-integration # default sqlite
    make test-integration-mysql
    make test-integration-pgsql
    make help # Get all make command
  • Docker
      make docker-build
      make docker-run
      # migrate
      make docker-migrate
  • Visit http://localhost:8000
  • Stop CTRL + C
  • About OwnTracks

API

  • Location Ping
  • User Last Location
  • Telegram Hook for user last location

Docs