Privacy Tools Guide

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])

# Example: 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

Built by theluckystrike — More at zovo.one