Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung IT-Branche 05.07.2026 · 10 min Lesezeit

Firefly III mit Docker installieren: Self-Hosted Finanzverwaltung mit doppelter Buchführung

Firefly III 6.7 per Docker Compose installieren: doppelte Buchführung, Budgets und Kategorien selbst hosten. Die Anleitung führt von der .env-Datei über den MariaDB-Healthcheck und den Cron-Container bis zu Update und Backup.

Geprüft am 30.09.2026 · für firefly-iii 6.7.6

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

Aufgeräumter Schreibtisch im Homeoffice mit Laptop, Sparschwein und Kaffeetasse als Symbol für private Finanzverwaltung

Firefly III (AGPL-3.0) ist eine selbst gehostete Finanzverwaltung mit doppelter Buchführung, Budgets, Kategorien, Tags, Berichten und REST-API. Die Daten bleiben auf Ihrem eigenen Server. Die Anwendung läuft als PHP/Laravel-Stack hinter integriertem Nginx im Container und benötigt drei Dienste: die Kern-App, eine MariaDB-Datenbank und einen schlanken Alpine-Cron-Container für automatische Aufgaben. Diese Anleitung richtet sich an Privatpersonen, Freelancer und KMU-Admins, die ihre Finanzdaten nicht in einen Cloud-Dienst geben wollen.

Voraussetzungen

  1. Docker Engine >= 24.x und das Docker Compose Plugin >= 2.x (Befehl: docker compose) sind installiert – wie das geht, erklärt die Grundanleitung Docker und Docker Compose auf Linux installieren.
  2. Linux-Host, VM oder NAS mit Docker-Unterstützung (Ubuntu/Debian, Proxmox-LXC, Synology DSM 7.x). Unterstützte Architekturen: linux/amd64 und linux/arm64. Auf älteren Raspberry-Pi-Modellen mit arm/v7 funktioniert das aktuelle Image nicht mehr.
  3. 1 CPU-Kern, mindestens 1 GB RAM (im Test belegten die drei Container zusammen rund 350 MB), empfohlen 2 GB; mindestens 2 GB freier Speicherplatz für Images und Daten.
  4. Internetzugang für den Image-Pull beim ersten Start.
  5. Optional, aber empfohlen: ein vorgelagerter Reverse Proxy (Traefik, Caddy, Nginx Proxy Manager) für HTTPS. Wie Sie Traefik einrichten, beschreibt Traefik als Docker-Reverse-Proxy mit automatischem HTTPS.

Schritt 1: Projektordner anlegen

Legen Sie einen eigenen Ordner für den Stack an. Alle Konfigurationsdateien landen hier; Docker-Volumes werden separat von Docker verwaltet.

mkdir -p /opt/firefly-iii
cd /opt/firefly-iii

Alle folgenden Befehle setzen voraus, dass Sie sich in diesem Verzeichnis befinden.

Verifizieren: pwd zeigt /opt/firefly-iii, ls gibt ein leeres Verzeichnis ohne Fehler zurück.

Schritt 2: APP_KEY generieren

Der APP_KEY ist der Kern der Verschlüsselung: Er schützt Sessions und sensible Daten in der Datenbank. Erzeugen Sie ihn einmalig vor dem ersten Start und bewahren Sie ihn sicher auf. Wer ihn nachträglich ändert, verliert den Zugang zu allen verschlüsselten Einträgen.

# 32 zufällige Zeichen ohne Sonderzeichen generieren (Linux/macOS):
head /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9' | head -c 32 && echo

Die Ausgabe sieht beispielsweise so aus:

xK9mQpLrTvZwAjNbCfHdEuYsOiGe7X4n

Führen Sie den Befehl ein zweites Mal aus: Den zweiten Wert brauchen Sie als STATIC_CRON_TOKEN, der ebenfalls exakt 32 Zeichen lang sein muss. Beide Werte tragen Sie im nächsten Schritt in die .env ein. Sichern Sie den APP_KEY in einem Passwortmanager, etwa in Vaultwarden: eigener Passwortmanager mit Docker.

Verifizieren: Der Befehl liefert exakt 32 Zeichen ohne Leerzeichen oder Zeilenumbruch. Prüfen Sie das mit echo -n 'WERT' | wc -c, die Ausgabe muss 32 lauten.

Schritt 3: Umgebungsdateien anlegen

Firefly III trennt App-Konfiguration (.env) und Datenbankzugangsdaten (.db.env) sauber in zwei Dateien. Die Root-Zugangsdaten der Datenbank landen so nicht in der App-Umgebung.

.env – App-Konfiguration

# -------------------------------------------------------
# Firefly III – App-Konfiguration
# -------------------------------------------------------

# Pflicht: 32-Zeichen-Zufallsstring, NIEMALS nachträglich ändern!
APP_KEY=xK9mQpLrTvZwAjNbCfHdEuYsOiGe7X4n

APP_ENV=production

# Muss der tatsächlichen Aufruf-URL entsprechen (inkl. Port, falls nicht 80/443)
APP_URL=http://localhost

# Datenbank
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=firefly
DB_USERNAME=firefly
# Identisch mit MYSQL_PASSWORD in .db.env!
DB_PASSWORD=SICHERES_PASSWORT_AENDERN

# Cron-Token: exakt 32 Zeichen (zweiter Wert aus Schritt 2)
STATIC_CRON_TOKEN=Rw7TzQ2mXbN4kLpV9sHdC3fJ8gYtA6uE

# Zeitzone
TZ=Europe/Berlin

# Deutsch als Standard-UI
DEFAULT_LANGUAGE=de_DE
DEFAULT_LOCALE=de_DE

# Admin-E-Mail für Fehlermeldungen
SITE_OWNER=admin@example.com

# Hinter Reverse Proxy: CSRF-Fehler vermeiden
# TRUSTED_PROXIES=**

# Log-Einstellungen (optional)
LOG_CHANNEL=stack
APP_LOG_LEVEL=notice

.db.env – Datenbankzugangsdaten

# -------------------------------------------------------
# MariaDB – Datenbankzugangsdaten
# -------------------------------------------------------
MYSQL_ROOT_PASSWORD=SICHERES_ROOT_PASSWORT_AENDERN
MYSQL_DATABASE=firefly
MYSQL_USER=firefly
# Identisch mit DB_PASSWORD in .env!
MYSQL_PASSWORD=SICHERES_PASSWORT_AENDERN

Ersetzen Sie beide SICHERES_PASSWORT_AENDERN-Platzhalter durch dasselbe sichere Passwort. Ein Mismatch zwischen DB_PASSWORD und MYSQL_PASSWORD ist der häufigste Fehler und führt zu einem sofortigen Verbindungsfehler der App.

Verifizieren:

ls -la /opt/firefly-iii/
# Erwartet: .env und .db.env vorhanden
grep DB_PASSWORD .env
grep MYSQL_PASSWORD .db.env
# Beide Zeilen müssen das identische Passwort zeigen

Schritt 4: compose.yaml anlegen

Der Stack besteht aus drei Diensten: app (Firefly III Core), db (MariaDB) und cron (Alpine-Cron für automatische Tasks). Anders als die offizielle Beispieldatei enthält diese Fassung einen Healthcheck auf MariaDB: Der App-Container startet erst, wenn die Datenbank bereit ist.

EigenschaftWert
Image (stabil)fireflyiii/core:latest (Stand September 2026: v6.7.6)
Stabiler Pinfireflyiii/core:version-6.7.6
Architekturenlinux/amd64, linux/arm64 (kein arm/v7)
Interner Port8080 (HTTP)
Host-Port (Standard)80 → 8080
Image-Größeca. 335 MB (komprimiert)
DatenbankMariaDB LTS (Standard), PostgreSQL 16 (Alternative)
LizenzGNU AGPL-3.0
VolumeContainer-PfadInhalt
firefly_iii_upload/var/www/html/storage/uploadHochgeladene Belege und Anhänge
firefly_iii_db/var/lib/mysqlMariaDB-Datenbankdaten
services:
  app:
    image: fireflyiii/core:latest
    container_name: firefly_iii_core
    hostname: app
    restart: unless-stopped
    volumes:
      - firefly_iii_upload:/var/www/html/storage/upload
    env_file:
      - .env
    ports:
      - "80:8080"
    networks:
      - firefly_iii
    depends_on:
      db:
        condition: service_healthy

  db:
    image: mariadb:lts
    container_name: firefly_iii_db
    hostname: db
    restart: unless-stopped
    env_file:
      - .db.env
    volumes:
      - firefly_iii_db:/var/lib/mysql
    networks:
      - firefly_iii
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 20s
      timeout: 5s
      retries: 10
      start_period: 30s

  cron:
    image: alpine
    container_name: firefly_iii_cron
    restart: unless-stopped
    env_file:
      - .env
    command: >
      sh -c "apk add --no-cache tzdata &&
      (ln -sf /usr/share/zoneinfo/$$TZ /etc/localtime || true) &&
      echo '0 3 * * * wget -qO- http://app:8080/api/v1/cron/$$STATIC_CRON_TOKEN; echo' | crontab - &&
      crond -f -L /dev/stdout"
    networks:
      - firefly_iii
    depends_on:
      - app

volumes:
  firefly_iii_upload:
  firefly_iii_db:

networks:
  firefly_iii:
    driver: bridge

Wer den Image-Tag pinnen möchte, ersetzt fireflyiii/core:latest durch fireflyiii/core:version-6.7.6 und spielt Updates dann manuell via docker compose pull ein. Mehr zu Docker-Netzwerken und Volumes erklärt Docker-Netzwerke und Volumes richtig nutzen.

Verifizieren:

docker compose config
# Erwartet: Validierte Compose-Konfiguration ohne Fehler
# Keine "invalid" oder "unknown" Warnungen in der Ausgabe

Schritt 5: Stack starten

Beim ersten Start lädt Docker die drei Images herunter (zusammen ca. 440 MB komprimiert), startet MariaDB, wartet auf dessen Healthcheck und führt dann automatisch alle Datenbankmigrationen durch.

docker compose up -d

Nach dem Pull vergehen 30 bis 60 Sekunden, bis MariaDB als „healthy“ gilt. Danach führt der App-Container Migrationen und Integritätsprüfungen aus, auf schwacher Hardware (1 CPU-Kern) dauert das zwei bis drei Minuten.

Verifizieren:

docker compose ps
# Erwartete Ausgabe (alle drei Container):
# NAME                   IMAGE                    STATUS
# firefly_iii_core       fireflyiii/core:latest   Up X seconds (healthy)
# firefly_iii_db         mariadb:lts              Up X seconds (healthy)
# firefly_iii_cron       alpine                   Up X seconds

# App-Logs auf Migrationsfehler prüfen:
docker compose logs app --tail=50
# Erwartet gegen Ende: "NOTICE: ready to handle connections"

# HTTP-Check:
curl -I http://localhost
# Erwartet: HTTP/1.1 302 Found (Redirect zur Login-/Registrierungsseite)

Schritt 6: Ersteinrichtung im Browser

Rufen Sie http://localhost (oder den konfigurierten Host und Port) im Browser auf. Über „Registrieren“ legen Sie das erste Konto an. Das erste registrierte Konto erhält die Rolle „owner“ (Administrator), registrieren Sie sich deshalb sofort selbst.

Nach der Registrierung führt ein kurzer Assistent durch das erste Konto. Empfohlene erste Schritte:

  1. Unter Konten → Vermögenskonten Ihre Bankkonten, Kreditkarten und Bargeld anlegen.
  2. Unter Budgets monatliche Ausgabegrenzen definieren (z. B. Lebensmittel, Mobilität, Freizeit).
  3. Unter Kategorien thematische Felder für Transaktionen erstellen.
  4. Einstellungen → Profil: Sprache auf „Deutsch“ prüfen, sie sollte bereits per DEFAULT_LANGUAGE=de_DE gesetzt sein.

Verifizieren: Nach der Registrierung erscheint der Einrichtungsassistent ohne Fehlerseite, die Oberfläche ist deutsch. In den Logs taucht kein 500 Internal Server Error auf:

docker compose logs app --tail=20
# Keine Zeile mit "ERROR" oder "500"

Schritt 7: HTTPS mit Reverse Proxy einrichten (empfohlen)

Firefly III selbst terminiert kein TLS, diese Aufgabe übernimmt ein vorgelagerter Reverse Proxy. Traefik, Caddy oder Nginx Proxy Manager eignen sich alle gleichermaßen.

Sobald ein Reverse Proxy davor sitzt, müssen zwei Variablen in der .env angepasst werden:

APP_URL=https://firefly.ihre-domain.de
TRUSTED_PROXIES=**

Danach den Stack neu starten:

docker compose up -d

Wie Sie Caddy mit automatischem HTTPS-Zertifikat einrichten, erklärt Caddy als Reverse Proxy einrichten ausführlich.

Verifizieren:

curl -I https://firefly.ihre-domain.de
# Erwartet: HTTP/2 302 oder HTTP/2 200
# Kein "SSL_ERROR_RX_RECORD_TOO_LONG"
docker compose logs app --tail=20
# Keine "419 Page Expired" oder CSRF-Fehler in den Logs

Schritt 8: Updates und Backup

Update durchführen

Datenbankmigrationen laufen beim Container-Start automatisch. Legen Sie vor jedem Update trotzdem ein Datenbank-Backup an. Aktuelle MariaDB-Images enthalten nur noch mariadb-dump, der alte Befehl mysqldump fehlt. Das Passwort liest der Befehl aus der Container-Umgebung, es landet so nicht in der Shell-History:

# Backup vor dem Update
docker exec firefly_iii_db sh -c 'mariadb-dump -u firefly -p"$MYSQL_PASSWORD" --single-transaction firefly' > backup_$(date +%Y%m%d).sql

# Update durchführen
docker compose pull
docker compose up -d --force-recreate

Volumes sichern

Named Volumes gehen bei docker compose down -v unwiderruflich verloren, führen Sie den Befehl nie ohne Backup aus. Eine robuste Strategie für Offsite-Backups beschreibt 3-2-1-Backup-Strategie umsetzen. Für automatisierte Datenbank-Dumps hilft MySQL & PostgreSQL Backup automatisieren mit cron.

Verifizieren:

docker compose ps
# Alle drei Container zeigen "Up" mit aktuellem Timestamp
docker compose logs app --tail=20
# Keine Migrationsfehler, Eintrag "ready to handle connections" vorhanden
grep -c 'CREATE TABLE' backup_*.sql
# Erwartet: eine Zahl deutlich über 0 (im Test 81)

Troubleshooting / Typische Fehler

  1. SQLSTATE[HY000] [1045] Access denied for user 'firefly': DB_PASSWORD in .env und MYSQL_PASSWORD in .db.env stimmen nicht überein. Beide auf denselben Wert setzen. Wurde die Datenbank bereits initialisiert, muss das Passwort auch in MariaDB selbst geändert werden – oder die Volumes werden gelöscht und neu initialisiert.
  2. 419 Page Expired beim Login: CSRF-Fehler hinter einem Reverse Proxy. Lösung: TRUSTED_PROXIES=** in .env setzen, danach docker compose up -d.
  3. Redirect-Schleife oder falsche Links in E-Mails: APP_URL stimmt nicht mit der tatsächlichen Aufruf-URL überein. Vollständige URL inkl. Schema und Port angeben (z. B. https://firefly.example.com), danach docker compose up -d.
  4. Cron-Container läuft, aber Wiederkehr-Buchungen erscheinen nicht: STATIC_CRON_TOKEN prüfen – er muss exakt 32 Zeichen haben und in .env gesetzt sein. Cron läuft täglich um 03:00 Uhr; für einen sofortigen Test: docker exec firefly_iii_cron wget -qO- http://app:8080/api/v1/cron/TOKEN.
  5. App-Container startet und hält sofort wieder an, Migrations-Fehler in den Logs: MariaDB war noch nicht bereit. Mit condition: service_healthy tritt das nicht auf. Andernfalls in docker compose logs db auf „ready for connections“ warten, dann docker compose restart app.
  6. Fehler auf arm/v7 (ältere Raspberry Pi): Das aktuelle Image unterstützt kein linux/arm/v7 mehr. Wechseln Sie auf arm64-Hardware oder ein 64-Bit-Betriebssystem.
  7. APP_KEY nachträglich geändert: Alle Sessions werden ungültig, verschlüsselte Daten sind nicht mehr lesbar. Den ursprünglichen Key aus dem Backup wiederherstellen – es gibt keinen anderen Weg.

Häufige Fragen

Kann ich PostgreSQL statt MariaDB verwenden?

Ja, PostgreSQL ist offiziell unterstützt. In .env DB_CONNECTION=pgsql und DB_PORT=5432 setzen. In .db.env die MYSQL_*-Variablen durch POSTGRES_PASSWORD, POSTGRES_DB und POSTGRES_USER ersetzen. In compose.yaml das Image auf postgres:16 und den Volume-Mount auf /var/lib/postgresql/data ändern (ab postgres:18 lautet der Mount /var/lib/postgresql).

Wie richte ich den Datenimport ein (CSV, Banking)?

Firefly III selbst importiert keine Daten direkt – dafür gibt es den separaten Container fireflyiii/data-importer. Dieser wird als eigener Dienst im Stack ergänzt und kommuniziert per API (Token aus den Firefly-III-Einstellungen) mit der Kern-App. Unterstützte Dateiformate: CSV, CAMT.052 und CAMT.053. Kontoabrufe laufen über Drittanbieter wie GoCardless (ehemals Nordigen). Die Sprache des Data Importers steuert dessen eigene Variable FALLBACK_LOCALE, Firefly III selbst nutzt DEFAULT_LOCALE.

Wie aktiviere ich die deutsche Benutzeroberfläche?

In .env die Zeilen DEFAULT_LANGUAGE=de_DE und DEFAULT_LOCALE=de_DE setzen (in der Beispiel-Konfiguration oben bereits enthalten). Nach docker compose up -d ist die Oberfläche deutsch. Jeder Benutzer kann die Sprache in seinen Einstellungen ändern.

Was tun, wenn ich den APP_KEY verloren habe?

Ohne den originalen APP_KEY sind verschlüsselte Daten verloren. Läuft die Instanz noch, zeigt docker exec firefly_iii_core env | grep APP_KEY den aktiven Key. Sonst bleibt nur ein Neuanfang mit neuen Volumes.

Was kostet Firefly III im Betrieb?

Die Software ist kostenlos (GNU AGPL-3.0), Kosten entstehen nur für Strom und Hardware. Wer eine veränderte Fassung als Dienst für andere anbietet, muss deren Quellcode offenlegen (AGPL).

Fazit

Firefly III ist aktiv gepflegt und eignet sich für alle, die ihre Finanzen lokal und ohne Abo verwalten möchten. Der Stack mit drei Containern ist in etwa 30 Minuten aufgesetzt. Die doppelte Buchführung erfordert anfangs mehr Einarbeitung als ein einfaches Haushaltsbuch, liefert dafür nachvollziehbare Berichte und eine REST-API für eigene Automatisierungen. Freelancer profitieren von Budgets, Kategorien und dem optionalen Data Importer mit CAMT-Unterstützung. Entscheidend für den Dauerbetrieb sind regelmäßige Backups und ein sicher aufbewahrter APP_KEY.

Weiterführende Anleitungen und Quellen

  1. Docker und Docker Compose auf Linux installieren – die Self-Hosting-Grundlage
  2. Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten
  3. Caddy als Reverse Proxy mit automatischem HTTPS
  4. Vaultwarden: eigener Passwortmanager mit Docker und SQLite-Backup
  5. 3-2-1-Backup-Strategie umsetzen: Anleitung mit Restic, USB-Disk und S3-Cloud
  6. MySQL & PostgreSQL Backup automatisieren mit cron: mysqldump, pg_dump und rclone

Offizielle Quellen: Firefly III Docker-Installationsdokumentation, Firefly III Docker-Repository auf GitHub, fireflyiii/core auf Docker Hub.