OwnTracks Recorder: location history in plain files
Store and access data published by OwnTracks apps
At a glance
- What is it?
- The OwnTracks Recorder is a small compiled C program that takes location updates from the OwnTracks phone apps over MQTT or HTTP, stores them as plain files, and serves them back through a REST API, a WebSocket and a command line tool called ocat. It needs no database, and the build is a set of feature switches you choose at compile time.
- Who is it for?
- Adopt the OwnTracks Recorder if you run the OwnTracks apps and want your own history rather than a hosted service, especially on hardware that cannot spare a database.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 45 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Location history without a database
The OwnTracks Recorder is a lightweight program for storing and accessing location data published via MQTT, or over HTTP, by the OwnTracks apps. It is a compiled program which is easy to install and operate even on low-end hardware, and it does not require an external database.
Those three properties together are the design. The OwnTracks apps on iOS and Android publish a location update when something changes, and the question is where those updates accumulate. A hosted service is one answer. The Recorder is the other: your own machine, your own storage, and no database process to keep alive.
The store is described as a bunch of plain files on the file system, and the storage layout is documented separately in doc/STORE.md, with doc/DESIGN.md covering the program design and doc/HOOKS.md the Lua hooks. The fact that there are three separate design documents for a program of this size tells you how much thought went into the format, because a file format you have to keep for years is a commitment.
The primary language is C, the default branch is master, and the repository is not archived. The last push was on 2026-09-08, the same day as the 1.0.4 release, with 1.0.3 in August 2026 and 1.0.2 before it.
The recorder and the ocat utility
There are two main components, and they divide the work cleanly.
The Recorder obtains the data, either by subscribing to an MQTT broker and reading the messages the OwnTracks apps publish, or by listening on HTTP for OwnTracks-type JSON messages posted to its HTTP server. It stores the data in a particular fashion into what the project calls the store, which is basically a bunch of plain files on the file system. It then serves the data back: static pages, a REST API you use to request data from the store, and a WebSocket server.
The built-in examples matter, because they show what the API is for. A table of last locations is available, and there is a live map which updates over the Recorder's WebSocket interface when location publishes arrive. Maps with last points or tracks are served using the GeoJSON the Recorder produces.
The second component is ocat, a command-line utility that reads the stored data in a variety of formats. Its subcommands in the table of contents are the practical API for scripting: list users and devices, show the last position reported by a user, and show what the last four reported positions were.
The project also explains its own lineage. The Recorder was developed as a one-stop solution to storing location data published by the OwnTracks apps and retrieving it, and the previous offerings, m2s and o2s which was also known as Pista, still work, but the project believes the Recorder is best suited to most environments.
The topics attached to the repository match that split: geolocation, http, jpdup, json, mqtt, owntracks and websockets.
The Makefile is a list of decisions you have to make
The Makefile is the clearest description of what the program can and cannot do, because every feature is a switch you set before you compile.
WITH_MQTT adds the Mosquitto client and its flags, and it is the switch that decides whether the Recorder can subscribe to a broker at all. WITH_HTTP adds mongoose.o and http.o to the build, and mongoose is the embedded web server that provides the static pages, the REST API and the WebSocket endpoint, so a build without it is a store and a command line tool with no server. WITH_LUA adds hooks.o and pulls in the Lua library, and when it is off the Makefile links the maths library instead, so the Lua hook system is a compile-time feature rather than a plugin you can load later. WITH_ENCRYPT links libsodium, which is what provides the encryption of stored data.
Then there are the smaller ones. WITH_PING adds the ability to check reachability, WITH_KILL adds a way to terminate the process, and WITH_TOURS adds support for tours, which needs a UUID library, and on Linux that means libuuid, with Debian needing uuid-dev and RHEL or CentOS needing libuuid-devel.
WITH_TZ is the one with a database behind it. It adds zonedetect.o to both the recorder and ocat builds and passes the location of the timezone database through TZDATADB, which is how the recorder knows the zone of a point rather than only its coordinates.
The build also pulls in libconfig for the configuration file, libcurl for the HTTP client, liblmdb for the LMDB database option, and pthreads. The compiler flags are -Wall with IPv6 support enabled, and the JSON_INDENT switch decides whether the stored JSON is indented.
The config.mk.in file is the template for these settings, which is how a packager turns them into a build.
Installing from packages, Docker or source
There are three routes, and the README is candid about which ones to expect to work.
Ready-to-run packages are provided for a limited number of platforms on the project's own package repository at repo.owntracks.org, and a Docker image is published on Docker Hub as owntracks/recorder. The caveat about the packages is that they might depend on libmosquitto1 from the Mosquitto project, and that the project typically does not build packages for distributions which have been superseded upstream. Debian 10, 11 and 12 are all in the no-longer-built list, with the advice to compile from source or take older versions from the package repository. Debian 13 Trixie is the one with instructions:
curl --no-progress-meter https://raw.githubusercontent.com/owntracks/recorder/master/etc/repo-v2.owntracks.org.gpg.key | sudo tee /etc/apt/trusted.gpg.d/owntracks.asc
sudo apt update
sudo apt install ot-recorderThe Docker image is pulled with docker pull owntracks/recorder, and the usage is documented in the project booklet. The one warning is specific and worth knowing: the Recorder is not recommended in a Docker container in HTTP mode because of the difficulty of configuring Friends.
The packages also ship a systemd unit in /usr/share/doc/ot-recorder/ot-recorder.service, which you install with install -m444 into /etc/systemd/system, then enable and start with systemctl enable ot-recorder and systemctl start ot-recorder. The prerequisite is a configuration file with the settings you require.
Setuid, certificates and who can read what
One paragraph in the installing section is the operational detail most people will miss, and it has consequences for how you deploy this.
The binaries, ocat and ot-recorder, from the packages run setuid to the user owntracks so that they work for all users of the system. The consequence, stated in the same paragraph, is that certificate files you provide must therefore also be readable by the user owntracks.
That is a small sentence with a real effect. If you supply your own TLS certificate for the HTTP server, or a CA bundle for verifying a backend, and you set its permissions to be readable only by root, the Recorder will not be able to read it, and the failure will look like a connection problem rather than a permissions problem.
The setuid design also explains why the packages exist in the form they do. A location store is readable by every user of the machine if the process runs as that user, which is not a sensible default for a file holding everyone's movements, so the daemon runs as a dedicated account and the tools elevate themselves to read the store.
The rest of the security surface is in the README's later sections. There is a views section, which covers view JSON and authentication, an encryption section for the stored data, and a browser API keys section for the case where a browser is talking to the API directly. The authentication part is what a reverse proxy in front of the Recorder is expected to enforce, and the two reverse proxy sections cover nginx and Apache.
Reverse geo, Lua hooks and the friends model
Three subsystems are worth singling out, because they are where the Recorder does work that a plain store would not.
Reverse geo is the feature that turns a coordinate into a place name. The source tree has geo.c, geohash.c and zonedetect.c for it, and the documentation has sections for the precision setting, which is what controls how precise the lookup is, and for the geo cache, which is what stops the recorder from asking the same question repeatedly. There is also a tip about overriding the reverse geo precision, which suggests the default is deliberately conservative.
Lua hooks are the extension point, and they are compile-time as well as runtime. The hooks system is documented in doc/HOOKS.md, and the Makefile's WITH_LUA switch adds the interpreter to the build. A hook lets you run your own code when a message arrives, which is how you would forward a location to something else or trigger an action on arrival.
The friends model is what the HTTP mode exists for. The table of contents has a section on friends in HTTP mode, and the browser API keys section is about a browser talking to the API. The privacy shape of this is worth understanding before you enable it, because it is the one place where the Recorder shares location with other people, and it is the reason the documentation warns against running it in a container in HTTP mode.
The remaining sections of the table of contents are the smaller ones: monitoring, the tips and tricks including gatewaying HTTP to MQTT, and the advanced topics around the LMDB database and its topic2tid, keys and friends tables.
Editorial conclusion
Adopt the OwnTracks Recorder if you run the OwnTracks apps and want your own history rather than a hosted service, especially on hardware that cannot spare a database. Do not adopt it if you need friends and location sharing, because the documentation says not to run the Recorder in a Docker container in HTTP mode because of the difficulty of configuring Friends, and do not skip the setuid detail, since the packaged binaries run as the owntracks user and that affects which files you can read. Before you start, choose your compile-time features, since MQTT, HTTP, Lua hooks, encryption and timezone support are all switched on in the Makefile, and read doc/STORE.md, which explains the on-disk layout you will be backing up.
Frequently asked questions
What does the OwnTracks Recorder do?
It stores and serves location data published by the OwnTracks apps. It subscribes to an MQTT broker or accepts OwnTracks-type JSON over HTTP POST, stores the updates as plain files on the file system, and serves them back through static pages, a REST API and a WebSocket, with a live map and a table of last locations. It needs no external database.
What is ocat in the OwnTracks Recorder?
ocat is the command line utility that reads the stored data in a variety of formats. Its subcommands include listing the users and devices, showing the last position reported by a user and showing the last four reported positions, which is what you use for scripting against the store.
Which features does the OwnTracks Recorder build let me choose?
The Makefile has switches for MQTT, HTTP, Lua hooks, encryption with libsodium, timezone detection, tours, ping and a kill option, plus switches for the JSON indentation and the timezone database path. MQTT and HTTP are what decide whether the Recorder can subscribe and whether it serves a web interface at all.
What does the setuid behaviour of the OwnTracks Recorder packages mean?
The packaged ocat and ot-recorder binaries run setuid to the user owntracks so they work for all users of the system. The practical consequence, stated in the same paragraph, is that any certificate files you provide must also be readable by that user.
Is the OwnTracks Recorder available for Docker?
Yes, as owntracks/recorder on Docker Hub, with the usage documented in the project booklet. The documentation does not recommend running the Recorder in a container in HTTP mode, because of the difficulty of configuring Friends in that setup.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/owntracks-recorder)Was this useful?