# π« PulseBase
**Your fitness data. Your server. Your rules.**
A privacy-first, self-hosted dashboard that turns your Garmin & Libre data
into ML-grade health insights β running entirely on your own machine.






[Quickstart](#-quickstart) Β· [Features](#-whats-inside) Β· [Docs](#-documentation) Β· [Security](#-security-at-a-glance)
---
> *Your Garmin data lives in someone else's cloud.*
> *Your sleep, your heart rate, your recovery β measured by a watch on **your** wrist,
> then rented back to you behind a login you don't control.*
**PulseBase takes it back.**
One `make up`, and every heartbeat syncs to a dashboard on **your** server β with the kind
of ML insights Garmin never surfaces, optional continuous glucose alongside it, and passwords
that are **never stored**. No cloud. No subscription. No data broker in the middle.
> π **Self-hosted by design.** PulseBase runs entirely on hardware you control. Your health
> data never leaves your server, and Garmin/LibreLinkUp passwords are wiped from memory the
> moment a token is obtained.
---
## β¨ Why PulseBase
- π **Privacy by architecture, not by promise** β runs entirely on your machine. Garmin and
LibreLinkUp passwords are wiped from memory the moment a token is obtained; only a
Fernet-encrypted token is ever persisted.
- π§ **Insights, not just charts** β anomaly detection, sleepβHRV correlation, a Random Forest
readiness model, body-battery clustering and more turn raw samples into "what does this *mean*?"
- π©Ί **Honest about its own limits** β every metric ships an EN 62366-inspired disclosure:
intended use, limitations, time horizon, evidence level. No black-box scores.
- 𧬠**More than Garmin shows you** β energy triptych (physical / autonomic / cognitive),
ACWR, training monotony, running economy, SpOβ trends, and an optional epilepsy seizure diary
with a rule-based risk indicator.
- π³ **One command to run it** β Docker Compose, self-service registration, multi-user. No admin.
---
## π¦ What's inside
### Data sync
- Automatic Garmin Connect sync (activities, sleep, HRV, body battery, stress)
- Optional continuous glucose via LibreLinkUp (Libre 3, every 5 min)
### The dashboard
- Slate/Emerald instrument-panel UI β tabbed (Training / Verlauf / Erholung), dark + light mode (WCAG 2.1 AA, axe-getestet in beiden Themes)
- Unified *Tagesstatus* hero: Oura-style readiness arc with HRV/sleep/pulse contributors,
energy triptych (Physisch / Autonom / Kognitiv), vitals strip
- Time navigation (β β) across all charts β browse any historical period
- Activity detail pages with GPS map (Leaflet), HR/pace/elevation/cadence charts
### The intelligence
- ML insights with dedicated detail pages: anomaly detection (resting HR + SpOβ + stress
Z-score), sleepβHRV Pearson correlation, Random Forest readiness, body-battery K-Means
patterns, ACWR, training monotony, running economy, sleep consistency, SpOβ trend, and more
- π / π item-level feedback on every ML insight
- Metrics overview (`/metrics`) β all 21 metrics as tiles with colour-coded evidence badges
(Meta-Analysis / Replicated / Model), each linked to a searchable `/help` methodology page
### Built for real use
- Central settings page (Garmin + LibreLinkUp in one place), self-service registration
- DSGVO/GDPR data export + account deletion, accessibility statement (BFSG)
- Optional epilepsy seizure diary with rule-based risk indicator (6 biomarker heuristics)
---
## π Quickstart
Two deployment modes:
| Mode | Command | Reverse proxy / TLS | Reachable |
|------|---------|---------------------|-----------|
| **Home** (default) | `make up` | [homelab-gateway](https://github.com/gerfru/homelab-gateway) (Caddy, Tailscale) | Tailnet only |
| **Public SaaS** | `make up-public` | bundled Caddy + Let's Encrypt | public internet |
```bash
cp env/.env.example env/.env # HOST_IP / DB admin
cp env/.env.app.example env/.env.app # DB roles + FERNET_KEY β make gen-secrets
cp env/.env.api.example env/.env.api # SESSION_SECRET (β₯32 chars) + APP_BASE_URL
cp env/.env.sync.example env/.env.sync
cp env/.env.ml.example env/.env.ml
make up # home: build + start behind homelab-gateway (proxy network)
# β https://your-domain.com/register
# β https://your-domain.com/garmin/link
make trigger-sync # pull your Garmin data now (no rebuild β runs within a minute)
# β https://your-domain.com/dashboard
```
**Running a homelab?** Start [homelab-gateway](https://github.com/gerfru/homelab-gateway) first,
then `make up`.
**Going public (self-hosted SaaS)?** Bundled Caddy gets you automatic HTTPS on a public
domain β `cp env/.env.public.example env/.env.public`, set `PUBLIC_DOMAIN` + `ACME_EMAIL`,
then `make up-public`. Full runbook: **[docs/deployment-public.md](docs/deployment-public.md)**.
β Full walkthrough: **[docs/setup.md](docs/setup.md)**
---
## π Documentation
Pick your depth:
| | |
|---|---|
| π§ **[ELI5](docs/eli5.md)** | The whole system explained like you're five |
| π **[Setup Guide](docs/setup.md)** | Complete installation walkthrough |
| βοΈ **[Configuration](docs/configuration.md)** | Every env var, per service |
| π οΈ **[Developer Guide](docs/development.md)** | Local dev, tests, CI/CD β and the full `make` command reference |
| ποΈ **[Architecture](docs/architecture.md)** | Services, data paths, network setup |
| ποΈ **[Database](docs/database.md)** | Schema, hypertables, real column names |
| π **[API Reference](docs/api.md)** | Every endpoint with request/response format |
| π€ **[ML Deep Dive](docs/ml-deep-dive.md)** | Algorithms, formulas, thresholds, training pipeline |
| β‘ **[Energy Metrics](docs/energy-metrics.md)** | The physical / autonomic / cognitive scores in detail |
| π **[Security](docs/security.md)** | Threat model, auth layers, crypto, headers |
| ποΈ **[Production Hardening](docs/production-hardening.md)** | Going live: secrets, backups, monitoring |
| π **[External Services](docs/external-services.md)** | Let's Encrypt, Sentry, Uptime Kuma setup |
| π§ **[Design Decisions](docs/design-decisions.md)** | Why no Grafana, no ORM, no JWT, Caddy everywhere |
| π **[ADRs](docs/adr/)** | Architecture Decision Records |
---
## π Security at a glance
Self-hosting your health data only helps if the app itself is hard to break into. PulseBase
ships with rate-limited auth + account lockout, email verification, CSRF protection, bcrypt
password hashing, signed httpOnly session cookies, Fernet-encrypted Garmin/Libre tokens,
least-privilege per-service DB roles, a strict nonce-based CSP, and SAST/SCA/container scanning
in CI (bandit Β· semgrep Β· pip-audit Β· Trivy).
β Full threat model and controls: **[docs/security.md](docs/security.md)**
---
## π§± Stack
FastAPI Β· TimescaleDB (PostgreSQL 16) Β· Docker Compose Β· Chart.js Β· scikit-learn Β· Tailwind CSS
Three services β `api` (dashboard), `sync-service` (Garmin/Libre ingest), `ml-service`
(analytics) β behind a reverse proxy. No Grafana, no ORM, no JWT, no framework on the frontend.
See **[Design Decisions](docs/design-decisions.md)** for the why.
---
Built for people who'd rather own their health data than rent it back.