Last updated: March 22, 2026

Fitness trackers collect some of the most sensitive personal data: your heart rate, sleep patterns, menstrual cycle, workout locations, and daily activity levels. Fitbit/Google, Garmin Connect, and Strava sell or expose this data. This guide covers open-source alternatives that keep your biometric data under your control.

Why Commercial Fitness Apps Are Dangerous

Gadgetbridge (Android. Open Source)

Gadgetbridge uses fitness wearables without any manufacturer app or cloud sync. All data stays on your device.

Setup:

  1. Install from F-Droid
  2. Enable Bluetooth → Pair your device in Gadgetbridge
  3. Never install the manufacturer app

Export data for analysis:

import sqlite3
import pandas as pd

conn = sqlite3.connect('gadgetbridge.db')

steps = pd.read_sql_query("""
    SELECT DATE(TIMESTAMP/1000, 'unixepoch') as date,
           SUM(STEPS) as total_steps
    FROM MI_BAND_ACTIVITY_SAMPLE
    GROUP BY date
    ORDER BY date DESC
    LIMIT 30
""", conn)

print(steps.to_string())

OpenTracks (Android. Open Source)

Records GPS-based activities with no cloud sync:

Traccar Self-Hosted GPS Server

Install Traccar
curl -o traccar.zip https://www.traccar.org/download/traccar-linux-64.zip
unzip traccar.zip && sudo ./traccar.run
sudo systemctl enable --now traccar
Open at http://localhost:8082

Use the Traccar Client app (on F-Droid) to send GPS data to your own server instead of any commercial platform.

Manual Logging Script

#!/bin/bash
fitlog.sh. simple local fitness log

LOG="$HOME/.fitness/log.csv"
mkdir -p "$HOME/.fitness"

if [ ! -f "$LOG" ]; then
    echo "date,activity,duration_min,distance_km,notes" > "$LOG"
fi

DATE=$(date +%Y-%m-%d)
read -p "Activity (run/cycle/walk/swim): " ACTIVITY
read -p "Duration (minutes): " DURATION
read -p "Distance (km, optional): " DISTANCE
read -p "Notes: " NOTES

echo "${DATE},${ACTIVITY},${DURATION},${DISTANCE:-},${NOTES}" >> "$LOG"
echo "Logged: $ACTIVITY on $DATE"

Device Recommendations for Privacy

Device Privacy Pairing Cloud Required
PineTime Gadgetbridge + InfiniTime No
Xiaomi Mi Band 7/8 Gadgetbridge No
Amazfit Band 5/7 Gadgetbridge No
Bangle.js 2 Gadgetbridge No
Fitbit (any) None (cloud-only) Yes
Apple Watch Apple Health (local) Optional

PineTime is fully open hardware with open-source firmware. the most privacy-respecting option, though more limited in features than commercial devices.

Privacy Analysis - What Each App Collects

Fitbit (Google):

Garmin Connect:

Strava:

Apple Health:

Gadgetbridge - Complete Setup Guide

Gadgetbridge is a single Android app that replaces all manufacturer fitness apps. After setup, delete the original app completely.

Full Installation Steps

1. Install F-Droid (the privacy-respecting app store)
Download from f-droid.org on your Android device

2. In F-Droid, search for "Gadgetbridge"
Install the latest version

3. Enable Bluetooth and ensure your wearable is nearby
The app will prompt you to pair during first run

4. DO NOT install the manufacturer's app (Mi Fit, Amazfit, Garmin)
Gadgetbridge handles all communication

5. Verify no network access (on Android 12+):
adb shell dumpsys package nodomain.freeyourgadget.gadgetbridge | grep "INTERNET\|NETWORK"
Should show nothing or "false"

Export All Fitness Data for Personal Analysis

Gadgetbridge stores data in SQLite. Extract it for analysis:

Database location
/sdcard/Android/data/nodomain.freeyourgadget.gadgetbridge/files/gadgetbridge.db

Via adb
adb pull /sdcard/Android/data/nodomain.freeyourgadget.gadgetbridge/files/gadgetbridge.db

Analyze with Python
python3 -c "
import sqlite3
import pandas as pd

conn = sqlite3.connect('gadgetbridge.db')

List available tables
tables = conn.execute(\"SELECT name FROM sqlite_master WHERE type='table'\").fetchall()
print('Available tables:', [t[0] for t in tables])

Steps last 30 days
steps = pd.read_sql_query('''
    SELECT DATE(TIMESTAMP/1000, \"unixepoch\") as date,
           SUM(STEPS) as steps
    FROM MI_BAND_ACTIVITY_SAMPLE
    WHERE TIMESTAMP > strftime(\"%s\", \"now\", \"-30 days\") * 1000
    GROUP BY date
    ORDER BY date DESC
''', conn)

print('\\nSteps (last 30 days):')
print(steps)

Export to CSV
steps.to_csv('steps_30days.csv', index=False)
"

This gives you full data ownership for personal analytics.

Self-Hosted Fitness Data Server

For advanced users, store fitness data on your own server:

Option 1 - Traccar (tracks GPS, shows location history)
wget https://www.traccar.org/download/traccar-linux-64.zip
unzip traccar-linux-64.zip
sudo ./traccar.run install

Access at http://localhost:8082
Add device UUID from Traccar Client app on your phone

Option 2 - Immich (photo-based activity tracking)
Docker-based photo storage with timeline view
Pairs well with OpenTracks (exports GPX files)

OpenTracks exports to GPX, which can be imported to your self-hosted server for long-term storage and analysis.

Wearable Selection Strategy

If you own Xiaomi Mi Band 7/8 or Amazfit:

If you own Fitbit/Apple Watch/Samsung Galaxy Watch:

If buying a new device:

Monthly Privacy Audit

Once per month, verify your setup:

1. Confirm no fitness app has internet permission
adb shell pm list packages | grep -i "fit\|health\|activity\|garmin\|strava"
For each result, check:
adb shell dumpsys package [PACKAGE_NAME] | grep "android.permission.INTERNET"

2. Confirm Gadgetbridge still has zero network access
adb shell dumpsys package nodomain.freeyourgadget.gadgetbridge | grep "INTERNET"

3. Check device storage for synced data
adb shell "find /sdcard -type f -name '*fitness*' -o -name '*activity*' -o -name '*health*' 2>/dev/null" | head -20

4. Review Gadgetbridge data export
Weekly export to encrypted USB backup

Related Reading


Built by theluckystrike. More at zovo.one