lionbackup open-source backup client (Go)
  • PHP 48.3%
  • Shell 24.9%
  • Dockerfile 18.8%
  • Makefile 8%
Find a file
lionbackup bot 77b92d2218
Some checks failed
build-client / build (push) Failing after 2s
Sync client source from lionking (3f146d97)
2026-07-09 08:07:17 +02:00
.forgejo/workflows Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
.github Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
docker Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
docs Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
server Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
.dockerignore Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
.editorconfig Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
.gitignore Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
Caddyfile Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
CHANGELOG.md Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
CONTRIBUTING.md Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
docker-compose.yml Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
Dockerfile Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
go.mod Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
go.sum Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
LICENSE Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
lionbackup.yaml.example Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
Makefile Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
openapi.yaml Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
README.md Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
SECURITY.md Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
test_lionbackup.sh Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00
VERSION Sync client source from lionking (3f146d97) 2026-07-09 08:07:17 +02:00

lionbackup-client

License: MIT Go

Ein einziges Go-Binary mit vier Modi: Schlüssel erzeugen, lokal verschlüsseln, hochladen, wiederherstellen.

Aufruf Was passiert
--generate-key / --keygen Post-Quantum-Schlüsselpaar erzeugen und beenden
--compress-only / --encrypt-only Quellen verschlüsseln (.lbk), nicht hochladen
--autotune Kompressionsverfahren vergleichen und das optimale empfehlen
(kein Modus) Verschlüsseln + Chunk-Upload an genau einen Server (Ziele aus environment, mit Failover)
--restore <file_id> Datei holen, prüfen, entschlüsseln, entpacken
--list Auf den Servern verfügbare Backups auflisten

--help gibt den vollständigen Hilfetext aus. Weitere Flags: --key-name, --output, --target, --quiet, --verbose, --debug, --progress-bar.

Weitere Dokumentation:

Datei-Format: explizite Hybrid-Verschlüsselung

.lbk-Datei:
┌──────────────────────────────────────────────────────────┐
│ "LIONBKP1" │ ver │ hdrLen │  age-verschlüsselter Header  │   asymmetrisch (KEM)
├──────────────────────────────────────────────────────────┤
│            32-Byte-DEK  │  JSON-Metadaten                │   ← nur DEK ist asym
├──────────────────────────────────────────────────────────┤
│ Chunk 0 │ Chunk 1 │ … │ Chunk N (isLast)                 │   symmetrisch (DEM)
└──────────────────────────────────────────────────────────┘
                                                       Chunk = [len|nonce|ciphertext+tag]
  • KEM: age (X25519 + ChaCha20-Poly1305) verschlüsselt ausschließlich einen frisch erzeugten 32-Byte-DEK und einen JSON-Metadaten-Block.
  • DEM: XChaCha20-Poly1305, 64 KiB Klartext-Chunks, je 24-Byte-Nonce zufällig. AAD pro Chunk = chunk_index (uint64 BE) || isLast (1 byte) — damit kippen Reordering- und Truncation-Versuche als AEAD-Fehler aus.

Der private Schlüssel sieht nur den DEK, niemals direkt die Nutzdaten.

Kompression (vor der Verschlüsselung)

compression_method in der Config:

Methode Threads Hinweis
ZSTD multi-threaded bestes Verhältnis Tempo/Rate, empfohlen
GZIP multi-threaded (pgzip) breit kompatibel, Standard-gzip-Format
LZMA2 / XZ single-threaded höchste Rate, aber langsam

Die Parallelität nutzt runtime.NumCPU() Kerne. Beim Restore wird die Methode automatisch am Magic der dekomprimierten Daten erkannt (gzip 1f 8b, zstd 28 b5 2f fd, xz fd 37 7a 58 5a 00) — die Metadaten werden dafür nicht benötigt.

  1. Die Zielserver ergeben sich aus der Zielumgebung (environment + storagezone, siehe unten). Die Liste wird beim Start zufällig permutiert (Lastverteilung über viele Clients).
  2. Beim Backup wird lazy genau ein Server gewählt: der erste der (zufällig sortierten) Liste, der GET /health mit 200 beantwortet, wird zum aktiven Server. Die übrigen Server werden dabei nicht geprüft. Übersprungen wird ein Kandidat bei jeder Fehlerklasse (dns:no such host, net:dial, timeout, http_5xx/4xx).
  3. Die Datei wird an genau diesen einen Server übertragen. Fällt er während der Übertragung aus, wird der nächste Server geprüft (Failover) und die Datei dort vollständig (in Chunks) neu übertragen.
  4. Existiert kein erreichbarer Server (z. B. weil keiner der Hostnamen auflöst), bricht der Client mit einer klaren Fehlermeldung ab (Exit ≠ 0).
  5. Beim Restore/--list werden die Server abgefragt, bis die gesuchte Datei gefunden ist bzw. der Katalog steht (eine Datei liegt clientseitig auf genau einem Server, da die Replikation serverseitig erfolgt).

Zielserver: environment & storagezone

Die Backup-/Restore-Ziele werden aus der Config abgeleitet:

environment Ziele Transport
localhost http://localhost:8080, :8081, :8082 HTTP (kein TLS)
dev / test / prod c0..c49.<storagezone>.<environment>.lionbackup.cloud HTTPS
  • environment ist weglassbar; Default ist prod.
  • Für dev/test/prod wird storagezone im Format <ISO-Land><Region>-<AZ> benötigt, z. B. de01-1c0.de01-1.dev.lionbackup.cloud, it02-7c32.it02-7.prod.lionbackup.cloud.
  • Der Ländercode muss ein europäischer ISO-3166-Alpha-2-Code sein (de, it, fr, es, …); andernfalls bricht der Client mit Fehler ab.
  • localhost zielt auf das lokale Test-Compose (drei Server hinter Caddy, unverschlüsselt) — siehe docs/test-server-compose.md.
  • Per CLI überschreibbar: --environment dev --zone de01-1.
  • Optionaler Override: eine explizite servers:-Liste in der Config hat Vorrang.

Sicherheit & Verfügbarkeit

  • Post-Quantum-Schlüssel: Neue Schlüssel sind ML-KEM-768 + X25519 (Hybrid). Bestehende X25519-Schlüssel funktionieren weiter.
  • Authentifizierung: token wird als Authorization: Bearer gesendet; der Server erzwingt es bei Start mit AUTH_TOKEN. /health bleibt offen.
  • Transport: dev/test/prod nur über HTTPS; localhost über HTTP.
  • Upload-Ziel & Failover: Jede Datei wird an genau einen Server übertragen. Fällt dieser während der Übertragung aus, wechselt der Client auf den nächsten gesunden Server und überträgt die Datei dort vollständig (in Chunks) neu. Die Replikation über mehrere Standorte erfolgt serverseitig.

Details im Sicherheitskonzept docs/security-concept.md, Bedienung in docs/user-guide.md.

Server-API (OpenAPI)

Das Gegenstück (Storage-Server) ist OpenAPI-3.1-kompatibel. Die vollständige Spezifikation liegt unter openapi.yaml und wird vom Server zusätzlich unter GET /openapi.yaml ausgeliefert (ohne Token abrufbar). Sie beschreibt alle Endpunkte: /health, /upload, /list, /status/{file_id}, /download/{file_id} samt Auth, Schemata und Response-Headern. Damit lassen sich Clients, Mock-Server und Tests generieren.

Optimale Kompression finden (--autotune)

lionbackup-client --autotune --config lionbackup.yaml

Führt für jede Quelle alle Verfahren (ZSTD, GZIP, LZMA2) einmal aus und gibt eine Vergleichstabelle aus Ausgabegröße, Kompressionsrate, Laufzeit und Durchsatz plus eine Empfehlung (bestes Verhältnis aus Größe und Zeit). Es findet weder Verschlüsselung noch Upload statt.

Bestandteile

.
├── cmd/lionbackup-client/   # Client (Go): main.go, keys_pq.go, keys_legacy.go
├── server/                  # PHP-Mock-Server (Test) + Dockerfile + Spec-Kopie
├── docs/                    # Sicherheitskonzept, Benutzerdoku, Compose- & Release-Doku
├── openapi.yaml             # kanonische OpenAPI-3.1-Spezifikation
├── Caddyfile                # Reverse-Proxy fürs Test-Compose (8080/8081/8082, HTTP)
├── docker-compose.yml       # NUR Client-Entwicklung: c0/c1/c2 + Caddy + Build-Profile
├── go.mod
├── lionbackup.yaml.example
├── Makefile
└── .github/workflows/       # ci.yml (Tests) + release.yml (Linux/Windows-Releases)

Lokal testen (Test-Compose)

Hinweis: Das Compose-Setup ist ein Mock-Server nur für die Client-Entwicklung nicht der echte lionbackup-Server. Details und Disclaimer: docs/test-server-compose.md.

# Drei Mock-Backends (c0/c1/c2) hinter Caddy starten; Caddy bietet 8080/8081/8082 (HTTP)
docker compose --profile server up -d --build
curl http://localhost:8080/health     # -> {"status":"ok","server":"c0"}

# Client bauen (oder via 'make build')
docker compose --profile build up build-linux
BIN=./dist/linux/lionbackup-client

# E2E-Test
./test_lionbackup.sh

Passende Client-Config: environment: localhost (zielt auf die drei lokalen HTTP-Server). Beispiel siehe docs/test-server-compose.md.

DNS-/Failover-Verhalten

  • Nicht auflösbare Hosts: In dev/test/prod existieren nur die real bereitgestellten cN-Hostnamen. Bei der Backup-Serverwahl werden die (zufällig sortierten) Kandidaten der Reihe nach geprüft, bis einer gesund ist; nicht auflösbare Hosts (dns:no such host) werden dabei übersprungen. Existiert kein erreichbarer Server, bricht der Client klar ab (Exit ≠ 0).
  • Ausfall im Betrieb: Im lokalen Setup lässt sich Failover testen, indem man ein Backend stoppt (docker compose stop c1) oder es über die Marker-Datei uploads/c1/.unhealthy auf /health 503 zwingt.

Config-Beispiel

Siehe lionbackup.yaml.example. Die Zielserver ergeben sich aus environment/storagezone (siehe oben); eine explizite servers:-Liste ist als Override möglich.

Pfad-Validierung

  • Auf Linux: Quellpfade dürfen kein \ und kein C:-Prefix enthalten.
  • Auf Windows: müssen Windows-Format haben.
  • Beim Restore: tar-Einträge mit .. oder absoluten Pfaden werden abgewiesen, Symlinks außerhalb --target werden übersprungen.

Build ohne go.sum

Das Repo enthält bewusst keine go.sum. Der Docker-Build nutzt -mod=mod und ergänzt die Hashes zur Build-Zeit. Für reproduzierbare Builds einmalig lokal:

go mod tidy && git add go.sum

Versionen & Sicherheit (Stand Juni 2026)

Aktuell gepinnte Versionen:

Komponente Version
Go (Build-Image) 1.26
filippo.io/age v1.3.1
github.com/klauspost/compress (zstd) v1.18.6
github.com/klauspost/pgzip v1.2.6
github.com/ulikunitz/xz v0.5.15
go.yaml.in/yaml/v3 v3.0.4
golang.org/x/crypto v0.52.0
PHP (Server-Image) 8.4

Hinweise:

  • ulikunitz/xz wurde wegen CVE-2025-58058 (DoS beim Dekomprimieren, behoben in v0.5.14) auf v0.5.15 gehoben.
  • gopkg.in/yaml.v3 ist archiviert; ersetzt durch den gepflegten Fork go.yaml.in/yaml/v3.
  • age v1.3 bietet einen Post-Quantum-HybridRecipient (ML-KEM-768 + X25519). Da nur der DEK gewrappt wird, lässt sich das ohne Formatänderung am Body nachrüsten.

Vor jedem Release empfohlen:

go mod tidy
go build ./...
go vet ./...
govulncheck ./...      # Schwachstellen-Scan gegen die Go-Vuln-DB

Releases

Versionierung nach SemVer, Start bei 0.1.0. Ein Tag vX.Y.Z löst den Workflow .github/workflows/release.yml aus, der den Client für Linux (amd64, arm64) und Windows (amd64) baut, die Versionsnummer einbrennt und die Artefakte samt SHA-256-Summen an ein GitHub-Release hängt:

git tag -a v0.1.0 -m "lionbackup-client 0.1.0"
git push origin v0.1.0

lionbackup-client --version gibt die eingebrannte Version aus. Details: docs/releasing.md.

Mitwirken

Siehe CONTRIBUTING.md. Kurz:

go mod tidy
make check        # gofmt, vet, spec-check, php-lint
make test

Sicherheitslücken bitte vertraulich melden siehe SECURITY.md.

Lizenz

MIT © 2026 lionbackup authors. Den Copyright-Inhaber vor der Veröffentlichung anpassen.