A self-hosted location tracking backend for the OwnTracks Android/iOS app. Receives, persists, and visualizes geolocation data via HTTP and MQTT, with a live map UI, real-time WebSocket updates, and a PKI-based certificate management system for secure MQTT TLS.
git clone https://github.com/the-hcma/my-tracks.git
cd my-tracks
./production/scripts/my-tracks-production-container-manager --startOn first run this will:
- Check for Docker or Podman (with platform-specific install hints if missing)
- Generate
.env.productionwith a random secret key - Generate self-signed TLS certificates
- Build the container image from source
- Start the full stack: nginx (TLS termination) + my-tracks (app) + PostgreSQL
- Wait for the health check and print access URLs
Once healthy, visit https://localhost:8443 and create an admin user:
# Create admin user (shown in the startup banner)
docker compose exec my-tracks python manage.py createsuperuserCommon operations:
| Command | Description |
|---|---|
--start |
Start (or restart) the stack; reuses existing config |
--start --freshen-up |
Wipe config and start fresh |
--start --import-sqlite [path] |
Import a local SQLite DB into PostgreSQL |
--stop |
Tear down the stack and volumes |
--security-check |
Run pre-launch security checks (CVE audit, Django hardening) |
See docs/DEPLOYMENT.md for the complete production deployment guide.
- 👥 docs/AGENTS.md - Development agent workflow
- 📘 docs/API.md - Complete API reference
- ⌨️ docs/COMMANDS.md - Command reference
- 🚢 docs/DEPLOYMENT.md - Production deployment guide
- 📖 Documentation Index - Complete guide to all docs
- 📊 docs/PROJECT_SUMMARY.md - Comprehensive project overview
- 📱 docs/PWA.md - Install the web dashboard on a phone or tablet
- 🚀 docs/QUICKSTART.md - Get running in 5 minutes
- ⚙️ docs/SYSTEMD.md - Local systemd user service (persistent dev server)
- OwnTracks HTTP Protocol Support: Full compatibility with OwnTracks JSON format
- Location Data Persistence: Store location data with full context (latitude, longitude, timestamp, accuracy, altitude, velocity, battery, connection type)
- RESTful API: Clean API endpoints for location data with filtering and pagination
- Device Management: Support for multiple devices with unique identification
- Type Safety: Full type hints using Python 3.14+ features
- Modern Python: Uses dataclasses and modern Python idioms
- Admin Interface: Web-based admin for data management
- Live Web Dashboard: Leaflet map with live and historic trails, WebSocket updates
- Progressive Web App: Install the dashboard on a mobile home screen (standalone + globe icon)
- Comprehensive Testing: Full pytest test suite included
- Production Ready: Container and bare-metal deployment guides; Daphne ASGI for WebSockets
For contributing or running locally without Docker:
Requirements: Python 3.14+, uv
git clone https://github.com/the-hcma/my-tracks.git
cd my-tracks
# Install dependencies and run migrations
bash scripts/setup
# Start the dev server (one-off)
./scripts/my-tracks-server
# Or install a persistent systemd user service (recommended for daily use)
~/work/ai/repository-helpers/scripts/setup-serviceFor manual setup, the web UI, PWA install, and the systemd service, see docs/PWA.md, docs/QUICKSTART.md, and docs/SYSTEMD.md.
Configure your OwnTracks app with the following settings:
- Mode: HTTP
- URL:
http://your-server:8080/api/locations/ - Authentication: Use device ID in the payload
MQTT provides real-time location updates, lower battery usage, and bidirectional communication (e.g., sending commands to devices).
Important: my-tracks uses MQTT v3.1.1 (protocol level 4). OwnTracks on Android defaults to MQTT v3.1, which is not supported by the embedded broker.
- Mode: MQTT
- Host: Your server's IP or hostname
- Port:
1883(or the port shown in the web UI) - Client ID: Leave default or set a unique ID
- Username / Password: Leave blank (anonymous access)
OwnTracks on Android defaults to MQTT v3.1 (MQIsdp, protocol level 3).
You must reconfigure it to use v3.1.1 (protocol level 4):
- Create a file on your phone (e.g.,
config.otrc) with:{"_type": "configuration", "mqttProtocolLevel": 4} - Open the file with OwnTracks (tap it in a file manager, share to OwnTracks, or use the import feature in the app)
- The app will apply the configuration and reconnect using v3.1.1
Tip: If you see connections being rejected in the server logs, check for the warning message: "MQTT v3.1 connection detected" — this confirms the protocol level needs to be updated on the device.
Submit location data from OwnTracks client.
Request Body (JSON):
{
"_type": "location",
"lat": 37.7749,
"lon": -122.4194,
"tst": 1234567890,
"acc": 10,
"alt": 50,
"vel": 5,
"batt": 85,
"tid": "AB",
"conn": "w"
}Response: 201 Created
Retrieve location history.
Query Parameters:
device: Filter by device IDstart_date: Filter locations after this date (ISO 8601)end_date: Filter locations before this date (ISO 8601)limit: Maximum number of results (default: 100)
List all registered devices.
my-tracks/
├── manage.py # Management script
├── pyproject.toml # Python dependencies (uv)
├── package.json # Frontend dependencies (pnpm)
├── scripts/
│ └── my-tracks-server # Server startup script
├── config/ # Project configuration directory
│ ├── __init__.py
│ ├── settings.py # Project settings
│ ├── urls.py # URL routing
│ ├── asgi.py # ASGI configuration
│ └── wsgi.py # WSGI configuration
├── app/ # Location tracking app
│ ├── __init__.py
│ ├── admin.py # Admin configuration
│ ├── apps.py # App configuration
│ ├── models.py # Database models
│ ├── serializers.py # DRF serializers
│ ├── views.py # API views
│ ├── urls.py # App URL routing
│ └── migrations/ # Database migrations
└── web_ui/ # Web interface app
├── static/web_ui/
│ ├── ts/ # TypeScript source
│ ├── js/ # Compiled JavaScript
│ └── css/ # Stylesheets
└── templates/web_ui/ # HTML templates
# Python tests
uv run pytest
# With coverage (90% minimum required)
uv run pytest --cov=app --cov-fail-under=90
# TypeScript tests
pnpm run test
# TypeScript linting
pnpm run lintThis project follows PEP 8 guidelines with additional tooling:
# Type checking
uv run pyright
# Import sorting
uv run ruff check --fix app config web_ui && uv run ruff format app config web_ui
# Shell script linting
shellcheck scripts/my-tracks-serverThe recommended deployment path is the container manager script described in Quick Start above. It builds and runs the full stack (nginx + my-tracks + PostgreSQL) with a single command, handles first-time setup automatically, and works on macOS, Linux (Debian/Ubuntu, CentOS/RHEL), and anywhere Docker or Podman is available.
See docs/DEPLOYMENT.md for the complete guide, including TLS configuration, environment variables, and bare-metal (non-container) instructions.
PolyForm Noncommercial License 1.0.0 - See LICENSE for details.
Contributions are welcome! This project uses GitHub Stacked PRs (gh stack) and the GitHub merge queue:
~/work/ai/repository-helpers/scripts/dev/start-development --worktree <stack-name> --no-interactive
cd .worktrees/<stack-name>-wt
gh stack init <stack>/<topic>
# … commit changes …
~/work/ai/repository-helpers/scripts/dev/submit-stackSee .cursor/rules/stacking-tool.mdc (agents),
docs/GH-STACK.md, and
docs/COMMANDS.md.