Reviewed-on: #33
mirror-package
Automatisiertes Werkzeug zum Extrahieren, Herunterladen und Spiegeln vorkompilierter Linux-Pakete aus GitHub-Releases in eine selbstgehostete Gitea- / Forgejo-Paket-Registry.
mirror-package überwacht konfigurierte GitHub-Repositories (wie z. B. raspberrypi/rpi-imager oder Heroic-Games-Launcher/HeroicGamesLauncher), identifiziert vorkompilierte Linux-Pakete (.deb, .rpm, .pkg.tar.zst, .pkg.tar.xz, .pkg.tar.gz, .pacman) und veröffentlicht diese anhand von Release-Stabilitätsregeln automatisch in den passenden Distributionen der Gitea-Paket-Registry.
Funktionen
- Unterstützung mehrerer Distributionen:
- Debian / Ubuntu (
.deb) - Fedora / RHEL / openSUSE (
.rpm) - Arch Linux (
.pkg.tar.zst,.pkg.tar.xz,.pkg.tar.gz,.pacman)
- Debian / Ubuntu (
- Distributions-Routing-Regeln:
- Stabile Releases: Debian-Pakete werden sowohl im
stable- als auch imtesting-Debian-Pool veröffentlicht (pool/stable/mainundpool/testing/main); RPM-Pakete unterrpm/stable; Arch-Pakete unterarch/stable. - Pre-Releases: Werden ausschließlich in Testing-Kanälen veröffentlicht: Debian
pool/testing/main, RPMrpm/testingund Archarch/testing.
- Stabile Releases: Debian-Pakete werden sowohl im
- Persistente Konfiguration über
config-ctdra:- Speichert Einstellungen automatisch im Benutzerpfad (
~/.config/mirror-package/config.toml) oder Systempfad (/etc/mirror-package/config.toml). - Das Hinzufügen oder Entfernen von Repositories über die CLI aktualisiert automatisch die Konfigurationsdatei.
- Speichert Einstellungen automatisch im Benutzerpfad (
- Flexible Authentifizierung:
- GitHub-Releases können anonym abgefragt werden (kein Token erforderlich).
- Optionale Unterstützung für GitHub Personal Access Tokens zur Vermeidung von API-Rate-Limits.
- Gitea-Instanz-URL, API-Token und Registry-Owner können per CLI-Flags, Umgebungsvariablen oder Konfigurationsdatei festgelegt werden.
- Diagnose & Dry-Run-Modus:
- Einheitliches Datei- und Konsolen-Logging über
logger-ctdra. --dry-run-Flag zur Simulation von Download- und Upload-Schritten ohne Änderungen an Remote-Systemen vorzunehmen.
- Einheitliches Datei- und Konsolen-Logging über
CLI-Verwendung & Befehle
1. Konfiguration (config)
Richte deine Gitea-Zugangsdaten und das optionale GitHub-Token ein:
# Gitea-Instanz und Registry-Owner konfigurieren
mirror-package config set \
--gitea-url "https://gitea.creative-dragonslayer.de" \
--gitea-token "dein_gitea_api_token" \
--registry-owner "Linuxapps"
# Optional: GitHub-Token für höhere API-Rate-Limits konfigurieren
mirror-package config set --github-token "ghp_xxxxxxxxxxxx"
# Aktuelle Konfiguration anzeigen
mirror-package config show
Zugangsdaten können auch über Umgebungsvariablen (GITEA_URL, GITEA_TOKEN, REGISTRY_OWNER, GITHUB_TOKEN) oder globale CLI-Argumente übergeben werden.
2. Überwachte Repositories verwalten (add, remove, list)
# Repositories zur persistenten Konfiguration hinzufügen
mirror-package add raspberrypi/rpi-imager
mirror-package add Heroic-Games-Launcher/HeroicGamesLauncher
# Repository ohne Synchronisierung von Pre-Releases hinzufügen
mirror-package add some-owner/some-repo --no-prereleases
# Konfigurierte Repositories und deren Sync-Status auflisten
mirror-package list
# Ein Repository entfernen
mirror-package remove raspberrypi/rpi-imager
3. Pakete synchronisieren (sync)
# Alle konfigurierten Repositories synchronisieren (neueste stabile Version und neuestes Pre-Release)
mirror-package sync
# Ein bestimmtes Repository synchronisieren
mirror-package sync raspberrypi/rpi-imager
# Alle historischen Releases eines Repositories synchronisieren
mirror-package sync raspberrypi/rpi-imager --history
# Dry-Run-Test (Simulation ohne Upload)
mirror-package sync --dry-run
Docker & Container-Nutzung
mirror-package wird als minimales, gehärtetes Container-Image in der Gitea Container Registry bereitgestellt.
1. Image-Registry & Tagging-Strategie
- Stabile Releases (
main-Branch):<registry>/<owner>/mirror-package:latest<registry>/<owner>/mirror-package:<version><registry>/<owner>/mirror-package:v<version><registry>/<owner>/mirror-package:<version>.<build_number>
- Testing- & Vorschau-Releases (
testing-Branch):<registry>/<owner>/mirror-package:testing<registry>/<owner>/mirror-package:<version>-preview<registry>/<owner>/mirror-package:<version>-testing<registry>/<owner>/mirror-package:<version>-preview.<build_number><registry>/<owner>/mirror-package:testing-<build_number>- (Hinweis: Der Tag
:latestist strikt dem stabilenmain-Workflow vorbehalten).
2. Persistente Speicherpfade
Um Konfigurationen, Status und Protokolle über Container-Neustarts hinweg beizubehalten, binde folgende Pfade an Host-Verzeichnisse oder Docker-Volumes:
| Container-Pfad | Zweck | Empfohlener Mount-Typ |
|---|---|---|
/home/appuser/.config/mirror-package |
Speichert config.toml (Zugangsdaten & Repo-Liste) |
Host-Verzeichnis / Volume (rw) |
/home/appuser/.local/state/mirror-package |
Persistente Anwendungsprotokolle & Statusdateien | Host-Verzeichnis / Volume (rw) |
/tmp |
Download- & Streaming-Puffer für Paketdateien | tmpfs (RAM / tempfs, rw, noexec) |
3. Sicherheitshärtung
Der Container wurde nach höchsten Sicherheitsstandards aufgebaut:
- Unprivilegierter Benutzer: Läuft als
appuser(UID10001, GID10001), niemals alsroot. - Read-Only Root-Dateisystem: Voll funktionsfähig mit
--read-only/read_only: true. - Keine Capabilities: Sämtliche Linux-Capabilities können sicher entzogen werden (
--cap-drop=ALL). - Keine Rechteausweitung: Erzwingt
no-new-privileges:true. - Minimale Image-Größe: Basiert auf Debian Trixie Slim und enthält nur CA-Zertifikate und notwendige dynamische Bibliotheken (~40 MB).
4. Ausführung über Docker CLI
# Zugangsdaten initialisieren / konfigurieren
docker run --rm \
--name mirror-package \
--read-only \
--cap-drop=ALL \
--security-opt=no-new-privileges:true \
--tmpfs /tmp:rw,noexec,nosuid,size=2G \
-v "./config:/home/appuser/.config/mirror-package" \
-v "./state:/home/appuser/.local/state/mirror-package" \
gitea.creative-dragonslayer.de/linuxapps/mirror-package:latest \
config set \
--gitea-url "https://gitea.creative-dragonslayer.de" \
--gitea-token "dein_token" \
--registry-owner "Linuxapps"
# Repositories hinzufügen
docker run --rm \
--read-only \
--cap-drop=ALL \
--security-opt=no-new-privileges:true \
--tmpfs /tmp:rw,noexec,nosuid,size=2G \
-v "./config:/home/appuser/.config/mirror-package" \
-v "./state:/home/appuser/.local/state/mirror-package" \
gitea.creative-dragonslayer.de/linuxapps/mirror-package:latest \
add raspberrypi/rpi-imager
# Synchronisation ausführen (kann über Cronjob oder Scheduler auf dem Host getriggert werden)
docker run --rm \
--read-only \
--cap-drop=ALL \
--security-opt=no-new-privileges:true \
--tmpfs /tmp:rw,noexec,nosuid,size=2G \
-v "./config:/home/appuser/.config/mirror-package" \
-v "./state:/home/appuser/.local/state/mirror-package" \
gitea.creative-dragonslayer.de/linuxapps/mirror-package:latest \
sync
5. Docker Compose Beispiel (docker-compose.yml)
services:
mirror-package:
image: gitea.creative-dragonslayer.de/linuxapps/mirror-package:latest
container_name: mirror-package
user: "10001:10001"
read_only: true
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
volumes:
- ./config:/home/appuser/.config/mirror-package
- ./state:/home/appuser/.local/state/mirror-package
tmpfs:
- /tmp:rw,noexec,nosuid,size=2G
environment:
- GITEA_URL=https://gitea.creative-dragonslayer.de
- GITEA_TOKEN=dein_gitea_api_token
- REGISTRY_OWNER=Linuxapps
- GITHUB_TOKEN=dein_optionaler_github_pat
- LOG_LEVEL=info
command: ["sync"]
Repository-Struktur
├── .cargo/
│ └── config.toml # Linker- & Cargo-Konfiguration
├── .gitea/
│ └── workflows/
│ ├── main.yaml # CI/CD: Release, Pakete & Container (Stable)
│ ├── testing.yaml # CI/CD: Preview, Pakete & Container (Testing)
│ ├── unit-tests.yaml # CI: cargo test bei PRs gegen testing
│ ├── security-scan.yaml # CI: Trivy & OSV-Scanner
│ ├── trufflehog-scan.yaml # CI: TruffleHog Secret-Scanning
│ └── renovate.yaml # CI: automatisierte Abhängigkeits-Updates (Renovate)
├── scripts/
│ ├── get-build-number.py # Dynamische Ermittlung der Build-/Revisionsnummer
│ └── package-arch.py # Erstellung nativer Arch Linux-Pakete
├── src/
│ ├── main.rs # CLI-Einstiegspunkt & Befehlsausführung
│ ├── lib.rs # Bibliotheks-Wurzel & Modulexporte
│ ├── cli.rs # Clap-CLI-Argumente & Optionen
│ ├── config.rs # config-ctdra Anbindung & Konfigurationsmodelle
│ ├── gitea.rs # Gitea-Paket-Registry Upload-Client
│ ├── github.rs # GitHub-API-Client & Paket-Klassifizierung
│ └── pipeline.rs # End-to-End-Synchronisationspipeline & temporärer Speicher
├── tests/
│ ├── config_tests.rs # Tests für die Konfigurationsverwaltung
│ ├── gitea_tests.rs # Tests für das Gitea-Upload-Routing
│ └── github_tests.rs # Tests für Paket-Klassifizierung & Parsing
├── .dockerignore # Ausschlussregeln für Container-Builds
├── Dockerfile # Gehärtetes, minimales Runtime-Container-Image
├── docker-compose.example.yml # Beispielkonfiguration für Docker Compose
├── Cargo.toml # Projekt-Manifest und Paketierungs-Metadaten
├── renovate.json # Renovate-Konfiguration für automatisierte Abhängigkeits-Updates
├── LICENSE # GPL-3.0-or-later Lizenztext
├── AGENTS.md # Agenten- & Entwickler-Richtlinien
└── README.md # Projektdokumentation
Lokale Entwicklung & Bauen
Voraussetzungen
- Rust & Cargo (Stable Toolchain, Edition 2024 unterstützt)
- Python 3 (für Paketierungsskripte)
Befehle zum Bauen & Testen
# Syntax- und Typprüfung ausführen
cargo check
# Unit-Tests ausführen
cargo test
# Release-Binary kompilieren
cargo build --release
CI/CD & Contributing
- Branch-Flow: Änderungen durchlaufen
dev→testing→main, jeweils per Merge (nie direkt gepusht). - Pull Requests gegen
testinglösen automatischcargo testaus. - Sicherheits-Scans: Trivy & OSV-Scanner laufen bei Push auf
main/testing/devsowie bei jedem Pull Request; TruffleHog läuft bei Push auf jeden Branch (keinbranches-Filter) sowie ebenfalls bei jedem Pull Request. Funde werden als Gitea-Issue gemeldet. - Abhängigkeits-Updates werden automatisiert über Renovate als PRs gegen
devvorgeschlagen.
Lizenz
Dieses Projekt ist unter der GPL-3.0-or-later-Lizenz lizenziert.