Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Docker 31.10.2026 · 11 min Lesezeit

SparkyFitness selbst hosten: Ernährung und Training per Docker

SparkyFitness ist eine selbst gehostete Ernährungs- und Fitness-App für Familien. Die Anleitung zeigt die Installation mit Docker Compose und gepinnten Images, das Admin-Konto, das Schließen der offenen Registrierung, eine Sicherung mit echtem Restore nach Totalverlust und das Update von 1.10.0 auf 1.11.0. Dazu: was die nichtkommerzielle Lizenz bedeutet.

Geprüft am 31.10.2026 · für SparkyFitness 1.11.0

Mit KI erstellt – redaktionelle Prüfung ausstehend

WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Titelbild zur Anleitung: SparkyFitness mit Docker Compose selbst hosten, Ernährung, Training und Backup

SparkyFitness ist eine selbst gehostete Alternative zu Diensten wie MyFitnessPal: Ernährungstagebuch, Training, Wasser, Körperwerte und Gesundheitsdaten liegen auf dem eigenen Server statt bei einem Anbieter. Das Projekt von CodeWithCJ hat auf GitHub rund 6.600 Sterne, Version 1.10.0 war in dieser Woche eines der meistdiskutierten Projekte in r/selfhosted, am 30.10.2026 folgte Version 1.11.0. Diese Anleitung zeigt die Installation mit Docker Compose und festen Image-Tags, das Admin-Konto, das Schließen der Registrierung, ein Backup mit echtem Restore nach Totalverlust und das Update von 1.10.0 auf 1.11.0. Alle Befehle und Ausgaben stammen aus einem Testlauf auf einem Debian-12-Host mit Docker.

Voraussetzungen

Sie brauchen einen Linux-Server oder eine VM mit Docker Engine und Docker Compose Plugin. Wie Sie das auf Debian 12 oder Ubuntu 24.04 einrichten, beschreibt die Grundlage zu Docker Compose unter Linux. Als Richtwert genügen 2 CPU-Kerne, 2 GB freier Arbeitsspeicher und 5 GB Speicherplatz für Images, Datenbank und Sicherungen. Für den Zugriff von unterwegs und für Passkeys gehört eine eigene Subdomain mit HTTPS über einen Reverse Proxy dazu. Dazu kommt ein Sicherungsziel außerhalb des Servers.

EckdatenWert
Imagescodewithcj/sparkyfitness_server:v1.11.0, codewithcj/sparkyfitness:v1.11.0, postgres:18.3-alpine
Port3004 auf dem Host, Nginx im Container auf 80; der Server lauscht intern auf 3010
Volumes./postgresql (Datenbank), ./uploads (Bilder), ./backup (App-Sicherungen)
Pflicht-EnvSPARKY_FITNESS_DB_PASSWORD, SPARKY_FITNESS_API_ENCRYPTION_KEY, BETTER_AUTH_SECRET, SPARKY_FITNESS_FRONTEND_URL
LizenzEigene Lizenz, nur nichtkommerzielle Nutzung

Schritt 1: Projektordner anlegen und Compose-Datei pinnen

Das Projekt liefert eine fertige Compose-Datei mit drei Diensten. Laden Sie sie vom Release-Tag statt vom Hauptzweig, damit Datei und Images zueinander passen. Die Vorlage verweist auf latest; ersetzen Sie das durch die Versionsnummer. So entscheiden Sie selbst, wann ein Update mit Datenbankmigrationen kommt.

mkdir -p /opt/sparkyfitness && cd /opt/sparkyfitness
curl -L -o docker-compose.yml https://raw.githubusercontent.com/CodeWithCJ/SparkyFitness/v1.11.0/docker/docker-compose.prod.yml
curl -L -o .env https://raw.githubusercontent.com/CodeWithCJ/SparkyFitness/v1.11.0/docker/.env.example
sed -i 's#codewithcj/sparkyfitness_server:latest#codewithcj/sparkyfitness_server:v1.11.0#; s#codewithcj/sparkyfitness:latest#codewithcj/sparkyfitness:v1.11.0#' docker-compose.yml
grep -n 'image:' docker-compose.yml

Die Datenbank nutzt postgres:18.3-alpine und bindet den Ordner ./postgresql korrekt nach /var/lib/postgresql ein. Ab PostgreSQL 18 ist das der richtige Pfad; ältere Vorlagen anderer Projekte mit /var/lib/postgresql/data passen nicht mehr. Der Datenbankdienst hat einen Healthcheck mit pg_isready, und der Server startet erst, wenn dieser grün ist. Mehr dazu: Docker Compose absichern.

Verifizieren: grep -n 'image:' zeigt zwei Zeilen mit :v1.11.0 und eine mit postgres:18.3-alpine.

Schritt 2: Geheimnisse in der .env setzen

Vier Werte müssen Sie selbst setzen. Der API-Schlüssel muss genau 64 Hex-Zeichen haben, das Auth-Geheimnis ist Base64. BETTER_AUTH_SECRET signiert die Sitzungen und verschlüsselt gespeicherte 2FA-Geheimnisse; laut Projektdokumentation sperrt ein späterer Wechsel alle Nutzer mit 2FA dauerhaft aus. Die .env gehört deshalb in jede Sicherung.

sed -i "s#^SPARKY_FITNESS_DB_PASSWORD=.*#SPARKY_FITNESS_DB_PASSWORD=$(openssl rand -hex 16)#" .env
sed -i "s#^SPARKY_FITNESS_API_ENCRYPTION_KEY=.*#SPARKY_FITNESS_API_ENCRYPTION_KEY=$(openssl rand -hex 32)#" .env
sed -i "s#^BETTER_AUTH_SECRET=.*#BETTER_AUTH_SECRET=$(openssl rand -base64 32)#" .env
chmod 600 .env

Tragen Sie anschließend von Hand die Adresse ein, unter der Sie die App wirklich öffnen, sowie Zeitzone und Admin-Adresse:

SPARKY_FITNESS_FRONTEND_URL=https://fitness.example.de
TZ=Europe/Berlin
SPARKY_FITNESS_ADMIN_EMAIL=admin@example.de
SPARKY_FITNESS_DISABLE_SIGNUP=false

Beginnt die Frontend-URL mit https, setzt SparkyFitness das Sitzungs-Cookie als __Secure-sparky.session_token mit Secure-Flag. Hinter einem HTTPS-Proxy funktionierte die Anmeldung im Test ohne weitere Einstellungen. TZ bestimmt, welchem Kalendertag ein Eintrag zugeordnet wird. Läuft vor SparkyFitness ein eigener Reverse Proxy, empfiehlt die .env.example zusätzlich SPARKY_FITNESS_TRUSTED_PROXY_HOPS=2, damit Ratenbegrenzung und Protokolle die echte Client-IP sehen.

Verifizieren: grep -c changeme .env liefert 0. Bleibt ein Platzhalter stehen, verweigert der Server den Start (siehe Troubleshooting).

Schritt 3: Stack starten

docker compose pull && docker compose up -d
docker compose ps
curl -s http://localhost:3004/api/version/current

Beim ersten Start legt der Server das Schema an und spielt alle Migrationen ein, in Version 1.10.0 waren es 287, in 1.11.0 sind es 293. Im Test antwortete die Versionsabfrage etwa 15 Sekunden nach dem Start. Außerdem legt er die Datenbankrolle sparky_app an, unter der die App arbeitet.

sparkyfitness-db        Up 26 seconds (healthy)
sparkyfitness-frontend  Up 10 seconds (healthy)
sparkyfitness-server    Up 10 seconds (healthy)
{"version":"1.11.0"}

Verifizieren: Alle drei Dienste stehen auf healthy, die Versionsabfrage liefert 1.11.0. Im Log steht SparkyFitnessServer listening on port 3010 (docker compose logs sparkyfitness-server).

Schritt 4: Admin-Konto anlegen und Registrierung schließen

Öffnen Sie die Frontend-URL und registrieren Sie das erste Konto mit der Adresse aus SPARKY_FITNESS_ADMIN_EMAIL. Ohne diese Variable wird laut Dokumentation das erste registrierte Konto Admin. Ein Einrichtungsassistent fragt danach Daten für den Grundumsatz ab; Skip überspringt ihn. Die Oberfläche war im Test englisch.

SparkyFitness Tagebuch-Ansicht mit Kalorienziel, Nährwertübersicht und Wasserzähler
Die Tagesübersicht nach dem Login: Kalorienziel, Makronährstoffe und Wasser auf einen Blick.

Die Admin-Variable wirkt bei jedem Start. Im Test wurde die Rolle des Admins in der Datenbank auf user zurückgesetzt; nach docker compose restart sparkyfitness-server stand sie wieder auf admin. Rechte entziehen Sie also nur zusammen mit der Variable.

Wichtig für Familien- und Firmeninstanzen: Nach dem ersten Konto bleibt die Registrierung offen. Im Test legte ein zweiter, anonymer Aufruf sofort ein weiteres Konto mit der Rolle user an. Haben alle Familienmitglieder ein Konto, schließen Sie die Registrierung:

sed -i 's/^SPARKY_FITNESS_DISABLE_SIGNUP=.*/SPARKY_FITNESS_DISABLE_SIGNUP=true/' .env
docker compose up -d
docker compose exec sparkyfitness-db psql -U sparky -d sparkyfitness_db -c 'select email, role from public."user"'

Ein neuer Registrierungsversuch scheiterte danach mit HTTP 400 und der Meldung Signups are currently disabled by the administrator., im Log stand [AUTH] Blocking signup: SPARKY_FITNESS_DISABLE_SIGNUP is true. Bestehende Sitzungen blieben gültig. Normale Konten erreichen die Admin-Funktionen nicht: Der Aufruf der Backup-Liste lieferte für das zweite Konto HTTP 403 mit Admin access required.

Verifizieren: Die SQL-Abfrage zeigt Ihr Konto mit admin, ein Registrierungsversuch im privaten Browserfenster endet mit der genannten Meldung.

Schritt 5: Ersten Eintrag erfassen

Unter Foods legen Sie eigene Lebensmittel mit Nährwerten pro Portion an, im Tagebuch ordnen Sie sie einer Mahlzeit zu. Für den Test diente ein eigenes Lebensmittel „Marker Haferflocken S-EDV“ mit 372 kcal pro 100 g als Prüfwert, eingetragen mit 80 g zum Frühstück. SparkyFitness rechnete daraus 298 kcal, 10,8 g Eiweiß, 47 g Kohlenhydrate und 5,6 g Fett und zog den Wert vom Tagesziel ab.

Frühstücksbereich in SparkyFitness mit dem Testlebensmittel und berechneten Nährwerten
Der Testeintrag im Frühstück: 80 g mit automatisch umgerechneten Nährwerten.

Externe Lebensmitteldatenbanken und KI-Dienste richtet der Admin unter Admin ein. Sie senden Anfragen an Dritte; prüfen Sie vorher, welche Daten den Server verlassen.

Verifizieren: Der Eintrag erscheint im Tagebuch, und die Abfrage select food_name, quantity, unit, calories from food_entries; in der Datenbank zeigt ihn.

Schritt 6: Sicherung anlegen

SparkyFitness hat eine eingebaute Sicherung unter Admin > Backup Settings. Zeitgesteuerte Sicherungen sind ab Werk ausgeschaltet. Run Manual Backup Now erzeugte im Test ein Archiv sparkyfitness_full_backup_<Zeitstempel>.tar.gz im Ordner ./backup mit einem SQL-Dump und einem Archiv der Uploads. Die Oberfläche weist selbst darauf hin, dass die Funktion neu ist und nicht die einzige Sicherung sein soll.

Backup Settings in der Admin-Oberfläche von SparkyFitness mit manuellem Backup und Restore
Admin > Backup Settings: Zeitplan, letzter Status, manuelles Backup und Restore-Upload.

Unabhängig davon sichern Sie Datenbank, Uploads und .env mit eigenen Mitteln. Das Dump-Format von pg_dump -Fc ist kompakt und lässt sich gezielt zurückspielen:

mkdir -p sicherung
docker compose exec -T sparkyfitness-db pg_dump -U sparky -d sparkyfitness_db -Fc > sicherung/sparkyfitness.dump
tar czf sicherung/uploads.tar.gz uploads
cp .env sicherung/env.bak

Das Skript db_backup.sh im Repository sichert nur das Schema (--schema-only), keine Daten. Kopieren Sie den Ordner sicherung auf ein anderes System.

Verifizieren: docker compose exec -T sparkyfitness-db pg_restore -l < sicherung/sparkyfitness.dump | grep -c 'TABLE DATA' zählt die gesicherten Tabellen, im Test 127.

Schritt 7: Wiederherstellen nach Totalverlust

Der Test simulierte den Totalverlust: Stack herunterfahren, Ordner postgresql, uploads und backup löschen, nur die Datenbank neu starten. Danach enthielt das Schema public keine einzige Tabelle. Der naheliegende Restore scheiterte:

pg_restore: error: could not execute query: ERROR:  role "sparky_app" does not exist
Command was: GRANT USAGE ON SCHEMA auth TO sparky_app;

Der Dump enthält Berechtigungen für die App-Rolle, aber nicht die Rolle selbst, denn Rollen gehören zum Datenbankcluster. Legen Sie sie vor dem Einspielen an. Ein Passwort ist nicht nötig, der Server setzt es beim Start selbst:

docker compose down
docker compose up -d sparkyfitness-db
docker compose exec -T sparkyfitness-db dropdb -U sparky --maintenance-db=postgres sparkyfitness_db
docker compose exec -T sparkyfitness-db createdb -U sparky --maintenance-db=postgres sparkyfitness_db
docker compose exec -T sparkyfitness-db psql -U sparky -d postgres -c "CREATE ROLE sparky_app LOGIN"
docker compose exec -T sparkyfitness-db pg_restore -U sparky -d sparkyfitness_db --exit-on-error < sicherung/sparkyfitness.dump
tar xzf sicherung/uploads.tar.gz && chown -R 1000:1000 uploads
docker compose up -d

Im Test lief pg_restore danach mit Exit-Code 0 durch. Der Server meldete beim Start Role "sparky_app" exists but the configured password does not authenticate; updating it. und lief danach normal. Testeintrag, beide Konten und die Admin-Rolle waren zurück, und weil BETTER_AUTH_SECRET aus der gesicherten .env stammte, blieb sogar die alte Browsersitzung gültig.

Verifizieren: Die Abfrage auf food_entries zeigt den Prüfeintrag, die Anmeldung mit dem bisherigen Konto funktioniert.

Schritt 8: Update von 1.10.0 auf 1.11.0

Der Test begann bewusst mit Version 1.10.0, um den Update-Weg zu prüfen. Sichern Sie wie in Schritt 6, ändern Sie dann die beiden Tags und ziehen Sie die neuen Images:

sed -i 's#sparkyfitness_server:v1.10.0#sparkyfitness_server:v1.11.0#; s#codewithcj/sparkyfitness:v1.10.0#codewithcj/sparkyfitness:v1.11.0#' docker-compose.yml
docker compose pull && docker compose up -d
docker compose logs sparkyfitness-server | grep 'Applying migration'

Compose erstellte Server und Frontend neu, die Datenbank lief weiter. Der Server spielte sechs neue Migrationen ein, darunter Tabellen für Laborwerte und einen Wetteranbieter für GPS-Aktivitäten. Testeintrag und Sitzungen blieben erhalten, das Image-Label org.opencontainers.image.version zeigte v1.11.0. Laut Release Notes können verbleibende Kalorien bei adaptiven Zielen danach niedriger ausfallen, weil doppelt angerechnete Aktivitätskalorien entfallen. Statt automatischer Updates empfiehlt sich hier eine Benachrichtigung, etwa mit Diun.

Verifizieren: curl -s http://localhost:3004/api/version/current liefert {"version":"1.11.0"}, die Fußzeile der Oberfläche zeigt SparkyFitness v1.11.0.

Grenzen: Lizenz und Einsatz

SparkyFitness steht nicht unter einer Open-Source-Lizenz, sondern unter einer eigenen Lizenz des Autors. Sie erlaubt Nutzung, Änderung und Weitergabe ausschließlich für nichtkommerzielle Zwecke, also privat, in der Ausbildung oder in gemeinnützigen Projekten ohne Einnahmen. Jede Nutzung in einem Produkt, Dienst oder Projekt mit kommerziellem Vorteil braucht eine vorherige schriftliche Erlaubnis. Abgeleitete Werke müssen unter denselben Bedingungen bleiben, und bei einem Verstoß endet die Lizenz automatisch. Für Unternehmen, etwa im betrieblichen Gesundheitsmanagement, ist das ohne Absprache mit dem Autor ein Ausschlusskriterium; für den Familienserver zu Hause ist es unproblematisch.

Gesundheitsdaten sind besonders schutzwürdig: nur mit HTTPS betreiben, Registrierung schließen, regelmäßig sichern.

Troubleshooting

Alle drei Fehlerbilder wurden im Test absichtlich ausgelöst. In jedem Fall startete der Server-Container in einer Schleife neu (Restarting (1)), und das Frontend lieferte HTTP 502.

UrsacheMeldung im Server-LogLösung
BETTER_AUTH_SECRET leerFATAL: Missing mandatory env vars: BETTER_AUTH_SECRETWert aus der Sicherung der .env eintragen, nicht neu erzeugen
Platzhalter in der .env stehen gelassenFATAL: Placeholder values in env vars: SPARKY_FITNESS_API_ENCRYPTION_KEYSchlüssel mit openssl rand -hex 32 erzeugen
Falsches DatenbankpasswortFailed to apply database migrations: error: password authentication failed for user "sparky"Ursprüngliches Passwort wiederherstellen
Restore ohne App-Rollerole "sparky_app" does not exist (von pg_restore)Rolle vor dem Restore anlegen, siehe Schritt 7

Das Datenbankpasswort liest PostgreSQL nur bei der ersten Initialisierung. Ein späteres Ändern in der .env wirkt deshalb nicht auf die Datenbank, sondern sperrt nur den Server aus. Ändern Sie es mit ALTER ROLE in PostgreSQL und erst danach in der .env.

Häufige Fragen

Darf ich SparkyFitness in meiner Firma einsetzen?

Nur mit schriftlicher Erlaubnis des Autors. Die Lizenz erlaubt ausschließlich nichtkommerzielle Nutzung.

Wird beim Update die Datenbank automatisch angepasst?

Ja. Der Server spielt beim Start fehlende Migrationen ein, im Test sechs Stück beim Wechsel von 1.10.0 auf 1.11.0. Eine Sicherung vorher bleibt Pflicht, denn ein Zurück auf die alte Version ist nur über den Restore möglich.

Reicht die eingebaute Sicherung?

Sie ist eine gute Ergänzung, aber das Projekt rät selbst zu zusätzlichen, unabhängigen Sicherungen. Zur Wiederherstellung brauchen Sie in jedem Fall auch die .env mit BETTER_AUTH_SECRET und dem API-Schlüssel.

Fazit

SparkyFitness läuft mit der offiziellen Compose-Datei schnell und sauber, wenn Sie die Images pinnen und die Geheimnisse sorgfältig setzen. Die Preflight-Prüfung verhindert den Start mit Platzhaltern, die Fehlermeldungen sind eindeutig. Zwei Dinge sollten Sie wissen: Die Registrierung bleibt nach dem ersten Konto offen, und ein pg_dump lässt sich erst zurückspielen, wenn die Rolle sparky_app existiert. Für den Haushalt ist die App damit ein solides Tagebuch, beruflich bremst die nichtkommerzielle Lizenz.

Weiterführende Anleitungen und Quellen

SparkyFitnessDocker ComposeSelfhostingErnährungstagebuchFitness-TrackerPostgreSQLBackup