No description
- Python 44.6%
- HTML 26.1%
- CSS 16.5%
- JavaScript 12.1%
- Dockerfile 0.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .forgejo/workflows | ||
| backend | ||
| frontend | ||
| sdk | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| README.md | ||
| requirements.txt | ||
📡 App Beacon
Lightweight, self-hosted anonymous telemetry hub for tracking unique installs of your apps.
Features
- Anonymous — UUID install IDs, no personal data, no IP logging
- Opt-in — users explicitly enable telemetry in each app
- Transparent — apps show exactly what's collected; dashboard is public
- Filterable dashboard — filter by app, OS, architecture, runtime, container
- Custom data — apps can send app-specific key-value data (JSON blob)
- Drop-in SDK — single Python file to integrate into any app
- Self-hosted — your data stays on your server
Quick Start
docker compose up -d
Visit http://localhost:8485 for the dashboard.
What Gets Collected
| Field | Example | Description |
|---|---|---|
| Install ID | a1b2c3d4-... |
Random UUID, generated once per install |
| App Name | stl-hoarder |
Which app sent the ping |
| App Version | 1.0.0 |
Version of the app |
| OS | Linux |
Operating system |
| OS Version | 6.12.54-Unraid |
OS kernel/release |
| Architecture | x86_64 |
CPU architecture |
| Runtime | Python |
Language runtime |
| Runtime Version | 3.12.1 |
Runtime version |
| Container | Docker |
Container runtime (if detected) |
| Custom Data | {"providers": 2} |
Optional app-specific data (JSON) |
What's NOT Collected
- ❌ IP addresses or location
- ❌ Usernames, passwords, or API keys
- ❌ File names or personal data
- ❌ Usage patterns or behavior tracking
Integrating an App
1. Copy the SDK
Copy sdk/beacon_client.py into your app.
2. Add the ping call
from beacon_client import beacon_ping
# On app startup:
beacon_ping(
beacon_url="https://beacon.yourdomain.com",
app_name="your-app",
app_version="1.0.0",
enabled=user_opted_in, # From your app's settings/toggle
custom_data={ # Optional
"providers_active": 2,
"total_downloads": 47,
},
)
3. Add a telemetry toggle to your app's UI
📊 Anonymous Telemetry (opt-in)
We collect:
✓ App name and version
✓ Install ID (random, not tied to you)
✓ OS and runtime (e.g. "Linux x86_64, Docker, Python 3.12")
✓ App-specific stats (e.g. number of providers configured)
We never collect:
✗ IP addresses or location
✗ Usernames, passwords, or API keys
✗ File names or personal data
The SDK includes a COLLECTED_DATA dict you can use to render this in your UI:
from beacon_client import COLLECTED_DATA
# COLLECTED_DATA["fields"] — list of {name, description}
# COLLECTED_DATA["not_collected"] — list of strings
API
POST /api/ping
Submit a telemetry ping.
{
"install_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"app_name": "stl-hoarder",
"app_version": "1.0.0",
"os": "Linux",
"os_version": "6.12.54-Unraid",
"architecture": "x86_64",
"runtime": "Python",
"runtime_version": "3.12.1",
"container": "Docker",
"custom_data": {
"providers_active": 2,
"auto_refresh_enabled": true
}
}
Optional: set BEACON_API_KEY env var to require Authorization: Bearer <key> header.
GET /api/stats
Dashboard data with optional query filters:
?app_name=stl-hoarder?os=Linux?runtime=Python?container=Docker?architecture=x86_64
Filters can be combined.
GET /api/filters
Returns unique values for all filter fields (for populating dropdowns).
GET /health
Health check endpoint.
Configuration
| Variable | Default | Description |
|---|---|---|
BEACON_PORT |
8080 |
Server port |
BEACON_DATA_DIR |
/data |
Database directory |
BEACON_API_KEY |
(empty) | Optional API key for ping submissions |
BEACON_BUILD_HASH |
dev |
Build hash for footer |
How It Works
- App starts → SDK generates a UUID (stored in
.beacon_idfile, persists across restarts) - SDK detects environment (OS, arch, container, runtime) automatically
- Sends a single POST to
/api/pingin a background thread (never blocks the app) - Hub stores/updates the install record (deduped by install_id + app_name)
- Dashboard shows aggregated stats with real-time filtering