Meshtastic And Owntracks To Kick Your Google Habit

I have an admission to make. I have a Google addiction. Not the normal addiction — I have a problem with Google Maps, and the timeline feature. I know, I’m giving my location data to Google, who does who-knows-what-all with it. But it’s convenient to have an easy way to share location with my wife, and very useful to track my business related travel for each month. What we could really use is a self-hosted, open source system to track locations and display location history. And for bonus points, let’s include some extra features, like the ability to track vehicles, kids, and pets that aren’t carrying a dedicated Internet connection.

You can read the title — you know where we’re going with this. We’re setting up an Owntracks service, and then tying it to Meshtastic for off-Internet usability. The backbone that makes this work is MQTT, a network message bus that has really found its niche in the Home Assistant project among others. It’s a simple protocol, where clients send brief messages labeled by topic, and can also subscribe to specific topics. For this little endeavor we’ll use the Mosquito MQTT broker.

One of the nice things about MQTT is that the messages are all text strings, and often take the form of JSON. When trying to get two applications to talking using a shared MQTT server, there may need to be a bit of translation. One application may label a field latitude, and the other shortens it to lat. The glue code to put these together is often known as an MQTT translator, or sometimes an MQTT bridge. This is a program that listens to a given topic, ingests each message, and sends it back to the MQTT server in a different format and topic name.

The last piece is Owntracks, which has a recorder project, which pulls locations from the MQTT server, and stores it locally. Then there’s Owntracks Frontend, which is a much nicer user interface, with some nice features like viewing movement a day at a time.

Getting started

So up first, pick a machine to host the service. We’ll use Docker-compose to build our mini-cluster of services. A Linux machine is a great choice, though it should be possible to run on Windows through either Docker desktop, or WSL. But if you go that route, you’re a bit on your own. You’ll need Docker and docker-compose, with the Docker service running — ideally set to autostart via systemd. And reminder, you’ll probably need to add your user to the “docker” group, with sudo gpasswd -a $USER docker.

Now just a quick note: I’m going to describe the process of setting this up from scratch. At the end of this article there will be a link to a Github repository, where you can grab nearly everything all at once.
It’ll help to read through the details at least once, to understand what we’re building, so hang in there.

We start by creating a folder in /etc, called owntracks-meshtastic. In that folder, we want to create a directory called mosquitto, and then create the mosquitto configuration file. We want to add two lines to that file, instructing our MQTT server to listen on port 1883, and to accept unauthenticated connections.

sudo mkdir /etc/owntracks-meshtastic
cd /etc/owntracks-meshtastic
sudo mkdir mosquitto
sudo touch mosquitto/mosquitto.conf
echo "allow_anonymous true" | sudo tee -a mosquitto/mosquitto.conf
echo "listener 1883" | sudo tee -a mosquitto/mosquitto.conf

With the configuration file in place, it’s time to start on our docker-compose.yml file, using sudo nano /etc/owntracks-meshtastic/docker-compose.yml. A docker compose file is really pretty simple once you break it down into parts. We start with a services heading, and under that will be a block for each docker service we want to run. Each block starts with a service name, and includes the Docker image itself, what files and folders we want to map into the Docker image, and what ports to expose. For Mosquitto, we just need the configuration file and a pair of ports for sending MQTT data.

services:
  mosquitto:
    image: eclipse-mosquitto
    volumes:
      - /etc/owntracks-meshtastic/mosquitto:/mosquitto/config
    ports:
      - 1883:1883
      - 9001:9001

Once that file is saved, we start a test-run by running a simple docker-compose up. This should download the Mosquitto docker image and start it up. Then we can use a simple client like MQTT Explorer to make sure that we’re actually running. If your OS has any firewalls in place, this is the time to add an MQTT exception to the firewall. Once you’re ready to go back to working on configuration, use Ctrl+c and run docker-compose down

First Real Data

We have enough of our system in place to start sending some real data. For this we need a Meshtastic node to work as a base station. This will need to be a device that can connect to the network, likely over wifi. There are several great options, like a Heltec LoRa32 v3, the Lilygo T-Beam (ideally the one with the SX1262 LoRa chip), or the Station G1 for the increased transmit power. Regardless of which device we choose, we need to connect it to wifi to enable communication with our new MQTT service.

That’s most easily done through the Android or iOS app, through radio configuration, network, and setting the WiFi SSID and PSK. Then it’s on to MQTT Config, to turn on “MQTT Enabled”. Set the “MQTT Server Address” to the machine running Mosquitto, blank out “MQTT Username” and “MQTT Password”, and finally turn on “JSON output enabled”. The device will reboot, and should start sending data to the MQTT server. In MQTT Explorer, we’re looking for the “msh” topic. Note: When running Meshtastic firmware versions 2.2.19 or later, the default MQTT root has changed, to include your region code. Either set the default back to “msh” or update the topic below to match.

Once that’s flowing, it’s time to add the next step, Meshtastic-bridge. We’ll start with creating the config file, sudo nano /etc/owntracks-meshtastic/config.yaml. We need to inform Meshtastic-bridge which server to use, and then set up a pipeline to convert the Meshtastic data to the MQTT format that Owntracks expects. You’ll need to update the server IP and populate the tid_table with your Meshtastic node IDs, which can be found using meshtastic --nodes.

mqtt_servers:
  - name: external
    server: YOURSERVERIP
    port: 1883
    topic: msh/2/json/#
    pipelines:
      owntrack:
      - owntracks_plugin:
          log_level: debug
          server_name: external
          tid_table:
            "!a56f7c45": ["Meshenger", "MS"]

Next we’re going to clone the meshtastic-bridge repository right into this folder, using sudo git clone https://github.com/jp-bennett/meshtastic-bridge. From there we add another service to our docker-compose.yml file to build a Docker image from that repository. We also pass our config file through as a Docker volume. Again use sudo nano /etc/owntracks-meshtastic/docker-compose.yml:

services:
  mosquitto:
    image: eclipse-mosquitto
    volumes:
      - /etc/owntracks-meshtastic/mosquitto:/mosquitto/config
    ports:
      - 1883:1883
      - 9001:9001
  meshtastic-bridge:
    build:
      context: /etc/owntracks-meshtastic/meshtastic-bridge
      dockerfile: Dockerfile
    volumes:
      - /etc/owntracks-meshtastic/config.yaml:/code/config.yaml

Map it!

Believe it or not, we’re nearly done. Up next is adding the Owntracks-recorder Docker image to our compose file. First, we need to create a data directory, using sudo mkdir store. Then it’s just a matter of adding the owntracks-recorder service to our docker-compose.yml and updating the IP address to our server IP again. Once again, use sudo nano /etc/owntracks-meshtastic/docker-compose.yml

services:
  mosquitto:
    image: eclipse-mosquitto
    volumes:
      - /etc/owntracks-meshtastic/mosquitto:/mosquitto/config
    ports:
      - 1883:1883
      - 9001:9001
  meshtastic-bridge:
    build:
      context: /etc/owntracks-meshtastic/meshtastic-bridge
      dockerfile: Dockerfile
    volumes:
      - /etc/owntracks-meshtastic/config.yaml:/code/config.yaml
  owntracks-recorder:
    image: owntracks/recorder
    volumes:
      - /etc/owntracks-meshtastic/store:/store
    ports:
      - 8083:8083
    environment:
      - OTR_HOST=YOURSEVERIP

From there, you should be able to pull up your owntracks instance at http://YOURSERVERADDRESS:8083. Once your Meshtastic node broadcasts a location, it should show up in the table of known nodes, and be visible on the map. Now as cool as this is, you may notice that it’s a bit bare-bones.

There’s one more piece to wire in, and that’s the Owntracks-frontend interface. This is the fancy single-page site that shows location history, heat maps, and more. And it’s pretty easy to add to our setup. Just add it to the bottom of your docker-compose.yml using sudo nano /etc/owntracks-meshtastic/docker-compose.yml, making the final file look like this:

services:
  mosquitto:
    image: eclipse-mosquitto
    volumes:
      - /etc/owntracks-meshtastic/mosquitto:/mosquitto/config
    ports:
      - 1883:1883
      - 9001:9001
  meshtastic-bridge:
    build:
      context: /etc/owntracks-meshtastic/meshtastic-bridge
      dockerfile: Dockerfile
    volumes:
      - /etc/owntracks-meshtastic/config.yaml:/code/config.yaml
  owntracks-recorder:
    image: owntracks/recorder
    volumes:
      - /etc/owntracks-meshtastic/store:/store
    ports:
      - 8083:8083
    environment:
      - OTR_HOST=YOURSEVERIP
  owntracks-frontend:
    image: owntracks/frontend
    ports:
      - 80:80
    environment:
      - SERVER_HOST=YOURSEVERIP
      - SERVER_PORT=8083

And that’s it! Run docker-compose up -d to start your miniature swarm of docker instances, and watch your Meshtastic devices populate the map with live data! No dependency on Internet, no sending your location data to Google, it’s just open source data collection goodness. And if you want some added goodies, there is an Owntracks mobile app that can connect directly to your own backend. That app pushes and pulls live location data, ideally over a VPN for security.

Now you may want to set this to run automatically, and there’s a systemd service for that. You’ll just need to save the following with sudo nano /etc/systemd/system/docker-compose-owntracks.service:

# /etc/systemd/system/docker-compose-owntracks.service
# https://stackoverflow.com/questions/43671482/how-to-run-docker-compose-up-d-at-system-start-up

[Unit]
Description=Docker Compose Owntracks Service
Requires=docker.service
After=docker.service
StartLimitIntervalSec=60

[Service]
WorkingDirectory=/etc/owntracks-meshtastic
ExecStart=/docker-compose up
ExecStop=docker-compose down
TimeoutStartSec=0
Restart=on-failure
StartLimitBurst=3

[Install]
WantedBy=multi-user.target

With that in place, you can use sudo systemctl enable docker-compose-owntracks --now to start and enable the whole service.

Now that’s a lot of work. So as promised, we have a quicker way to do it. The whole thing is available as a single repository. All that needs to be done after running the following command is to change the server IP, fill out the tid-table, and deploy the systemd service file.

sudo git clone https://github.com/jp-bennett/owntracks-meshtastic --recurse-submodules /etc/owntracks-meshtastic/

That’s Meshtastic, MQTT, and Owntracks all rolled up into your own location tracking service. Let us know if you follow the instructions and set this up for yourself. And look forward to the third part in this series, how to use Meshtastic to extend your projects with a wireless, encrypted serial connection.

20 thoughts on “Meshtastic And Owntracks To Kick Your Google Habit

  1. I don’t understand why Meshtastic comes in play. If I’m using location emitting devices that are all connected to my home server, is there any value to a non-internet communication mesh like Meshtastic?

    1. It propagates the location data even if Internet is down, or you hit a zone without cell service. A Meshtastic node with a GPS chip is also far cheaper than a full cell phone with a cellular plan.

      1. That assumes there are nearby open meshtastic nodes that will backhaul your data. LoRa is fantastic for hacking in your local neighborhood but it can’t compare to cell phone coverage.

        The writer wanted this to replace Google maps for business travel. I guarantee you aren’t going to be passing open meshtastic nodes every two miles while driving. Not to mention that mountains and dense buildings that block cell also block LoRa.

      2. That requires a network of meshtastic nodes that are extremely rare. The author’s premise was to replace Google tracking but meshtastic and Lora are completely different. Meshtastic+Lora+ Gps only let’s you track stuff around your yard and neighborhood.

        1. Just a couple days ago, I took a trip with the vehicle containing a Meshtastic node. Owntracks recorded a location point 18 miles away from my home base. It’s a little better than just your yard, with a bit of work.

          1. That’s a little unfair isn’t it? From a mountain top to a boat. Based on some experiments I ran using meshtastic in Atlanta,1 KM is a much more reasonable maximum range.

    2. Meshtastic nodes can bee cheap and need nothing but the other nodes and the “Mesh” for communication. Most usecases are therefore in areas with no cell coverage or, when trying to stay independent.
      Like in this example when you want noone to have your data.

  2. So… you are saving your own traffic data and doing so on your own server privately?

    Ok. Cool I guess. Here’s a pic of where I’ve been, kind of like taking selfies while stuck in traffic?

    The most useful thing IMOP regarding cloud based mapping though is the real-time traffic notifications and automatic re-routing. What Waze accomplished and Google purchased by using it’s users’ locations to get the current traffic speed of most busy stretches of road… it’s so much better than what can be accomplished in a world of full privacy.

    I’ve toyed with the idea of a nav app that uses random, anonymized IDs and a P2P network to achieve something similar without the privacy issues nor requiring a centralized service to own your data.

    I have nowhere near enough time on my hands to start coding that though and I’m not sure how one would popularize it to get enough users to make it work without making a ton of money from it to pay an advertising service, which would probably require compromising the privacy and selling the data. Nor do I expect it would work quite as well, especially at the beginning of the trip when it is still looking for other hosts but.. maybe…

  3. It would be a really nice additional feature to add community nodes to the meshtastic environment so that you could send messages let’s say to a specific person that would be personal like point to point and also have devices like pet tracking and other things upload your data through community nodes. Amateur radio operators get to use something called aprs but it’s you know reserved to people who go through the rigmarole of getting licensed which in a country like mine is extraordinarily difficult and there is no third party exam preparation materials and the clubs that do exist are extremely insular and unwelcoming to the foreigners or even immigrants as the cases with me. People could just establish nodes that allow others to pass data through there there are their nodes. Basically setting up an off grid Communications Network that can be both private and community oriented so that you can get like coverage in your entire area or city or Little village or wherever you live without having to use the internet necessarily digest jumping from people’s individual nodes through hopping. I’m not exactly sure how you can set that up so that people could securely share their meshing capabilities with others and therefore everyone could benefit from widespread coverage. But it would be a really cool added feature to the environment. Granted I’m not going to give up on my attempt to get license here but I had to recently reschedule my initial test due to the fact that the club I joined from the very beginning but very discreetly had no intention ever welcoming me into there dying club which is sad because it has a hundred year old history and I was the youngest person there and I’m not that young.

    Everywhere else everywhere else the hobby is growing a little bit and is benefiting from the convergence of the maker community and computer technology as well as people’s interest in satellites and space including balancing digital messages through satellites and even dedicated to your stationary satellites like the one put up by the director of telecommunications I think of the UAE who is a amateur radio operator and funded a geostationary amateur radio satellite. My goal has been to pass the test to use the satellite and I noticed that the test that I need to pass which is called an hb9 you had better have a pretty strong background electronic engineering if you have any chance of passing that test which kind of flies in the face of the whole idea of amateur radio and again just exemplifies the very sad but true growing tend to abilify immigrants in this current nationality culture right wing version of this country where if they read their own history every single one of them is an immigrant unless you were born and three small little cantones way back many hundreds and hundreds of years ago .

  4. This looks a little nicer than my method of tracking my phone: use GPS Logger (from f-droid store, works well with GrapheneOS) to SFTP a file with location data to a directory on my home server Pi.

  5. Is anyone using the network formerly known as Helium for any of this kind of stuff? I don’t see or hear much about it aside from some blathering about crypto and mining, but wasn’t that NOT the actual point?

    1. I thought Helium was fascinating, actually doing something useful with cryptocurrency. But that ecosystem has crashed. Turns out Helium was falsely claiming a couple of big customers. And for all the millions being invested, the Helium network was actually making under $10,000 in real money a month. As a result, we get nice LoRa antennas by the pallet for peanuts, as the crypto-disillusioned dump their stock.

  6. I hate that everything has to be a server now hosted somewhere. Nothing is offline-first.

    Why can’t my phone just record my location into daily/hourly .gpx file which get synchronized whatever way I want (dropbox/syncthing/rsync/OneDrive) and then when I open the frontend app it would just parse the files and show them on the map?

  7. Sort of like openstreetmap ?

    I mean there are offroad trail hiking GPS apps where you download the trail map / or state map and only require a GPS signal to draw your position on that map.

    Meshtastic seems like an interesting way to handle an alternative to text messaging.

  8. This is cool and all but would you be able to use it having the median skill level of a computer / phone user of today? Every time someone severs themselves from the mainstream information hurricane, they create a little tornado that has a serious barrier to entry for newcomers/

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.