README.md gelöscht
This commit is contained in:
@@ -1,327 +0,0 @@
|
|||||||
# RPM Mirror Sync
|
|
||||||
|
|
||||||
`sync.sh` spiegelt einzeln benannte Pakete aus Drittanbieter-RPM-Repos in ein
|
|
||||||
lokales Repo, ohne dabei Pakete mitzuspiegeln, die AlmaLinux selbst schon
|
|
||||||
liefert (BaseOS, AppStream, Extras, CRB/"Extras for Enterprise"). Nur die in
|
|
||||||
der YAML-Liste explizit genannten Pakete bekommen AppStream-Metadaten und
|
|
||||||
werden damit in GNOME Software / Discover als installierbar angezeigt.
|
|
||||||
|
|
||||||
## Voraussetzungen (auf dem Server, der das Skript ausführt)
|
|
||||||
|
|
||||||
```
|
|
||||||
dnf install -y dnf-plugins-core createrepo_c python3-pyyaml git
|
|
||||||
```
|
|
||||||
|
|
||||||
Das Skript muss als root laufen (schreibt kurzzeitig eine `.repo`-Datei nach
|
|
||||||
`/etc/yum.repos.d/`).
|
|
||||||
|
|
||||||
## Konfiguration
|
|
||||||
|
|
||||||
Alles über Umgebungsvariablen, z.B. in der systemd-Unit oder im Cron-Job:
|
|
||||||
|
|
||||||
| Variable | Bedeutung | Default |
|
|
||||||
|---------------------|------------------------------------------------------------------|---------|
|
|
||||||
| `SOURCES_GIT_REPO` | Git-Repo mit der YAML-Liste (leer = lokale Datei verwenden) | – |
|
|
||||||
| `SOURCES_GIT_BRANCH` | Branch im Git-Repo | `main` |
|
|
||||||
| `SOURCES_YAML_FILE` | Pfad zur YAML-Datei (im Git-Repo oder lokal) | `sources.yaml` |
|
|
||||||
| `WORK_DIR` | Arbeitsverzeichnis (Downloads, Logs, Zwischenlisten) | `/var/cache/rpm-mirror-sync` |
|
|
||||||
| `REPO_BASE_DIR` | Zielverzeichnis der gespiegelten Repos | `/srv/repo` |
|
|
||||||
| `CLIENT_REPO_DIR` | Wo fertige `.repo`-Dateien für Clients abgelegt werden | `${REPO_BASE_DIR}/client-repos` |
|
|
||||||
| `CLIENT_BASE_URL` | URL, unter der `REPO_BASE_DIR` für Clients erreichbar ist | `http://mirror.example.local/repo` |
|
|
||||||
| `ALMA_REPO_IDS` | repoids der lokalen AlmaLinux-Repos (`dnf repolist`) | `baseos appstream extras crb` |
|
|
||||||
|
|
||||||
**Wichtig:** `ALMA_REPO_IDS` muss zu den tatsächlichen repoids auf dem
|
|
||||||
Server passen (`dnf repolist` prüfen) — sonst funktioniert der
|
|
||||||
Ausschluss-Mechanismus nicht korrekt.
|
|
||||||
|
|
||||||
## Ausführen
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export SOURCES_GIT_REPO=https://git.example.com/infra/rpm-sources.git
|
|
||||||
export CLIENT_BASE_URL=http://repo.internal.example.com/repo
|
|
||||||
./sync.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Danach liegt unter `REPO_BASE_DIR/pkgs/` das eine kombinierte Repo mit allen
|
|
||||||
Paketen aller Quellen (per Webserver auszuliefern) und unter
|
|
||||||
`CLIENT_REPO_DIR/mirror.repo` die eine fertige `.repo`-Datei, die auf die
|
|
||||||
Clients verteilt wird (z.B. via Ansible/Config-Management nach
|
|
||||||
`/etc/yum.repos.d/`).
|
|
||||||
|
|
||||||
Am besten per systemd-Timer (z.B. täglich) statt Cron, damit Logs sauber in
|
|
||||||
`journalctl` landen.
|
|
||||||
|
|
||||||
## Wie der Ausschluss von AlmaLinux-Abhängigkeiten funktioniert
|
|
||||||
|
|
||||||
1. Für jedes Source-Repo wird zunächst abgefragt, welche Pakete *dieses*
|
|
||||||
Repo überhaupt bereitstellt (`dnf repoquery` nur gegen das Source-Repo).
|
|
||||||
2. Anschließend wird die komplette Abhängigkeitskette der gewünschten
|
|
||||||
Pakete aufgelöst — dabei sind sowohl das Source-Repo als auch die
|
|
||||||
lokalen AlmaLinux-Repos aktiv, damit die Auflösung überhaupt gelingt
|
|
||||||
(z.B. wenn ein Paket von `glibc` abhängt).
|
|
||||||
3. Von den heruntergeladenen RPMs wird alles verworfen, was nicht in der
|
|
||||||
Liste aus Schritt 1 steht — also alles, was tatsächlich aus einem
|
|
||||||
AlmaLinux-Repo kam. Übrig bleiben nur RPMs, die es ausschließlich im
|
|
||||||
Drittanbieter-Repo gibt.
|
|
||||||
|
|
||||||
**Wichtig: "übrig bleiben" ist meist mehr als nur die Namen unter
|
|
||||||
`packages:`.** Wenn ein angefordertes Paket von weiteren Drittanbieter-Paketen
|
|
||||||
abhängt, die AlmaLinux nicht bereitstellt (z.B. bei .NET: `dotnet-host`,
|
|
||||||
`dotnet-hostfxr-*`, `dotnet-apphost-pack-*`, `aspnetcore-runtime-*`, ...),
|
|
||||||
werden die zwangsläufig mitgespiegelt — sonst schlägt `dnf install
|
|
||||||
dotnet-sdk-8.0` auf dem Client mit einer fehlenden Abhängigkeit fehl, die
|
|
||||||
nirgendwo sonst verfügbar wäre. Nur echte AlmaLinux-Pakete werden
|
|
||||||
ausgeschlossen, nicht Drittanbieter-Abhängigkeiten. Im Log ist das ab jetzt
|
|
||||||
pro Paket sichtbar:
|
|
||||||
|
|
||||||
```
|
|
||||||
[...] keeping (requested): dotnet-sdk-8.0-8.0.130-1.el10_2.x86_64
|
|
||||||
[...] keeping (dependency): dotnet-host-10.0.11-1.el10_2.x86_64
|
|
||||||
[...] Source 'dotnet': kept 26 package(s) - 6 explicitly requested + 20 pulled-in third-party dependencies (...)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Sonderfall: `baseurl` zeigt auf ein AlmaLinux-eigenes Repo
|
|
||||||
|
|
||||||
`dnf` "sucht" nie selbstständig bei Drittanbietern — es lädt ausschließlich
|
|
||||||
von der URL, die ihr unter `baseurl` eintragt. Zeigt diese URL zufällig auf
|
|
||||||
ein AlmaLinux-eigenes Repo (z.B. `.../AppStream/...`), ist also gar keine
|
|
||||||
externe Quelle im Spiel. Genau das ist bei .NET auf AlmaLinux 10 der Fall:
|
|
||||||
`dotnet-sdk`, `dotnet-runtime`, `dotnet-host` & Co. sind Teil des offiziellen
|
|
||||||
AppStream-Repos (anders als bei älteren Alma-/RHEL-Versionen mit separatem
|
|
||||||
Microsoft-Repo).
|
|
||||||
|
|
||||||
Konsequenz: Die "requested"-Pakete sind hier technisch schon über das
|
|
||||||
normale, auf jedem Client ohnehin aktivierte AppStream-Repo installierbar —
|
|
||||||
der Ausschluss-Mechanismus (Schritt 1-3 oben) erkennt das nicht, weil er nur
|
|
||||||
gegen die *anderen* Alma-Repos (BaseOS, Extras, CRB) vergleicht, nicht gegen
|
|
||||||
die Quelle selbst. Ein normaler Mirror-Lauf würde hier also RPM-Inhalte
|
|
||||||
duplizieren, die AlmaLinux bereits liefert.
|
|
||||||
|
|
||||||
**Für genau diesen Fall gibt es `metadata_only: true`** (pro Quelle in der
|
|
||||||
YAML, siehe `sources.example.yaml`): Es werden **keine RPMs** heruntergeladen,
|
|
||||||
verifiziert oder umsigniert — nur kuratierte AppStream-Metadaten für die
|
|
||||||
gelisteten Paketnamen werden generiert und veröffentlicht. Das tatsächliche
|
|
||||||
Installieren übernimmt `dnf` weiterhin ganz normal über das Repo, das das
|
|
||||||
Paket wirklich bereitstellt (bei AlmaLinux-eigenen Paketen also das
|
|
||||||
Standard-AppStream-Repo, das auf jeder Standardinstallation ohnehin aktiv
|
|
||||||
ist). Der Effekt: Discover zeigt nur eure kuratierte Auswahl statt des
|
|
||||||
kompletten (oft sehr großen) AppStream-Kataloges, ohne dass ihr Inhalte
|
|
||||||
dupliziert, die es schon gibt.
|
|
||||||
|
|
||||||
**Voraussetzung:** Die Clients müssen das Repo, das die Pakete tatsächlich
|
|
||||||
bereitstellt, bereits aktiviert haben — bei Standard-AlmaLinux-Installationen
|
|
||||||
(BaseOS/AppStream/Extras/CRB aktiv) ist das automatisch der Fall.
|
|
||||||
|
|
||||||
Für ein echtes Drittanbieter-Repo (Pakete, die AlmaLinux nirgends hat) lasst
|
|
||||||
ihr `metadata_only` einfach weg (Default: `false`) — dann läuft der volle
|
|
||||||
Mirror-Prozess wie oben beschrieben, inklusive Verifikation und Umsignieren.
|
|
||||||
|
|
||||||
## Umsignieren mit einem eigenen GPG-Key
|
|
||||||
|
|
||||||
Damit eure Clients nicht für jede gespiegelte Quelle einen eigenen GPG-Key
|
|
||||||
importieren müssen, signiert `sync.sh` jedes gespiegelte Paket auf einen
|
|
||||||
einzigen, mirror-eigenen Schlüssel um:
|
|
||||||
|
|
||||||
1. Beim ersten Lauf wird — falls noch keiner unter `GPG_HOME` existiert —
|
|
||||||
einmalig ein GPG-Schlüsselpaar erzeugt (unattended, ohne Passphrase; das
|
|
||||||
ist für automatisierte Repo-Signierung üblich). Der öffentliche Teil wird
|
|
||||||
nach `REPO_BASE_DIR/RPM-GPG-KEY-mirror` exportiert.
|
|
||||||
2. Für jede Quelle wird — sofern `gpgkey:` in der YAML gesetzt ist — das
|
|
||||||
heruntergeladene RPM zunächst gegen den **originalen** Key des Upstream
|
|
||||||
geprüft (`rpmkeys --checksig`). Schlägt die Prüfung fehl, bricht das
|
|
||||||
Skript für diese Quelle ab (kein stillschweigendes Mirroring manipulierter
|
|
||||||
Pakete). Ist kein `gpgkey:` angegeben, wird eine Warnung geloggt und die
|
|
||||||
Prüfung übersprungen.
|
|
||||||
3. Danach wird die ursprüngliche Signatur entfernt und durch eine Signatur
|
|
||||||
mit dem mirror-eigenen Key ersetzt (`rpmsign --resign`).
|
|
||||||
4. Alle generierten Client-`.repo`-Dateien verweisen auf denselben Key
|
|
||||||
(`${CLIENT_BASE_URL}/RPM-GPG-KEY-mirror`) — unabhängig davon, wie viele
|
|
||||||
Quellen gespiegelt werden.
|
|
||||||
|
|
||||||
**`gpgcheck` und `repo_gpgcheck`:** Die generierte `.repo`-Datei setzt beide
|
|
||||||
auf `1`:
|
|
||||||
- `gpgcheck=1` prüft beim Installieren die Signatur **jedes einzelnen RPM**
|
|
||||||
gegen den Mirror-Key.
|
|
||||||
- `repo_gpgcheck=1` prüft zusätzlich die Signatur der **Repo-Metadaten
|
|
||||||
selbst** (`repodata/repomd.xml.asc`, ein detached signature). Ohne das
|
|
||||||
könnte jemand mit Schreibzugriff auf den Webserver/die Leitung
|
|
||||||
theoretisch die Paketliste manipulieren (z.B. ein älteres, verwundbares
|
|
||||||
Paket als aktuell ausgeben oder Einträge entfernen), ohne dass eine
|
|
||||||
einzelne RPM-Signatur berührt würde — `repo_gpgcheck` schließt genau diese
|
|
||||||
Lücke.
|
|
||||||
|
|
||||||
`sync.sh` signiert `repomd.xml` nach jedem Lauf neu (nachdem `createrepo_c`
|
|
||||||
und `modifyrepo_c` fertig sind, da beide die Datei noch verändern) mit
|
|
||||||
demselben Mirror-Key, den auch die Pakete tragen — Clients brauchen also
|
|
||||||
weiterhin nur den einen `RPM-GPG-KEY-mirror`.
|
|
||||||
|
|
||||||
**Wichtig zur Aufbewahrung des privaten Schlüssels:** `GPG_HOME`
|
|
||||||
(Default: `${WORK_DIR}/gnupg`) enthält den privaten Signierschlüssel und darf
|
|
||||||
**niemals** über nginx/den Webserver erreichbar sein — im mitgelieferten
|
|
||||||
Docker-Setup liegt er bewusst auf dem `sync-cache`-Volume, das *nicht* in den
|
|
||||||
`nginx`-Container gemountet wird, nur `repo-data` (die öffentlichen Dateien)
|
|
||||||
ist das. Wer Lesezugriff auf `GPG_HOME` hat, kann Pakete als euer Mirror
|
|
||||||
signieren — entsprechend schützen (Backups, Zugriffsrechte).
|
|
||||||
|
|
||||||
`GPG_HOME` muss auf persistentem Speicher liegen: wird es gelöscht, erzeugt
|
|
||||||
das Skript beim nächsten Lauf einen neuen Schlüssel, und alle Clients müssen
|
|
||||||
den neuen öffentlichen Key erneut importieren.
|
|
||||||
|
|
||||||
### Revocation-Zertifikat
|
|
||||||
|
|
||||||
Da der Mirror-Key mit `expire=never` erzeugt wird, gibt es kein automatisches
|
|
||||||
Ablaufdatum, über das ein kompromittierter Key von selbst "entschärft" würde.
|
|
||||||
Deshalb erzeugt `sync.sh` beim allerersten Lauf zusammen mit dem Schlüssel
|
|
||||||
auch ein **Revocation-Zertifikat** unter `GPG_HOME/revocation-cert.asc` — das
|
|
||||||
ist die einzige Möglichkeit, den Key später für ungültig zu erklären, falls
|
|
||||||
der private Schlüssel jemals kompromittiert wird.
|
|
||||||
|
|
||||||
**Direkt nach dem ersten Start aus dem Container herausholen und offline
|
|
||||||
sichern:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker compose cp syncer:/var/cache/rpm-mirror-sync/gnupg/revocation-cert.asc \
|
|
||||||
./mirror-key-revocation-cert.asc
|
|
||||||
```
|
|
||||||
|
|
||||||
(Pfad anpassen, falls ihr `WORK_DIR`/`GPG_HOME` in `.env` geändert habt.)
|
|
||||||
Das Zertifikat danach an einem Ort außerhalb des Docker-Hosts aufbewahren
|
|
||||||
(Passwort-Safe, Offline-Backup o.ä.) — nicht im selben Ordner wie der
|
|
||||||
private Key selbst, sonst bringt es im Kompromittierungsfall nichts. Das
|
|
||||||
Skript loggt den Hinweis beim ersten Lauf zusätzlich in `sync.log`.
|
|
||||||
|
|
||||||
Kommt der Ernstfall, importiert ihr das Zertifikat auf einer Maschine mit
|
|
||||||
Zugriff auf `GPG_HOME` (`gpg --homedir ... --import mirror-key-revocation-cert.asc`),
|
|
||||||
exportiert den nun als widerrufen markierten Public Key erneut nach
|
|
||||||
`REPO_BASE_DIR/RPM-GPG-KEY-mirror` und verteilt ihn an alle Clients — dnf/rpm
|
|
||||||
lehnen mit einem widerrufenen Schlüssel signierte Pakete danach ab.
|
|
||||||
|
|
||||||
## Wie die Sichtbarkeit in Discover/GNOME Software gesteuert wird
|
|
||||||
|
|
||||||
`createrepo_c` erzeugt Repo-Metadaten für **alle** im Zielverzeichnis
|
|
||||||
liegenden RPMs (nötig, damit `dnf install` Abhängigkeiten auflösen kann).
|
|
||||||
GNOME Software/Discover zeigt aber nur Pakete an, für die es
|
|
||||||
AppStream-Komponenten-Metadaten gibt. Diese werden vom Skript **nur** für
|
|
||||||
die explizit unter `packages:` gelisteten Namen erzeugt (nicht für
|
|
||||||
mitgezogene Abhängigkeiten) und per `modifyrepo_c --mdtype=appstream` in
|
|
||||||
die Repo-Metadaten injiziert.
|
|
||||||
|
|
||||||
**Einschränkung:** Es werden nur "generic" AppStream-Komponenten erzeugt
|
|
||||||
(kein Icon, keine Screenshots, keine `.desktop`-Datei — die liefert das
|
|
||||||
Originalpaket nicht mit). Das reicht, damit ein Paket in Discover
|
|
||||||
installierbar ist und in der Suche auftaucht, aber es erscheint **nicht**
|
|
||||||
auf der kuratierten "Entdecken"-Startseite von GNOME Software — das ist ein
|
|
||||||
Verhalten von GNOME Software/appstreamcli, das sich über Repo-Metadaten
|
|
||||||
allein nicht ändern lässt.
|
|
||||||
|
|
||||||
## Repo auf Clients einbinden
|
|
||||||
|
|
||||||
Alle Quellen landen in **einem einzigen** kombinierten Repo unter
|
|
||||||
`REPO_BASE_DIR/pkgs/` — egal wie viele Einträge eure `sources.yaml` hat.
|
|
||||||
Entsprechend gibt es auch nur **eine** Client-`.repo`-Datei:
|
|
||||||
`CLIENT_REPO_DIR/mirror.repo` (Default: `/srv/repo/client-repos/mirror.repo`,
|
|
||||||
über nginx erreichbar unter `/repo/client-repos/mirror.repo`).
|
|
||||||
|
|
||||||
**Einbinden auf einem Client — ein Kommando, ein Repo:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -fsSL http://<host>:8080/repo/client-repos/mirror.repo \
|
|
||||||
-o /etc/yum.repos.d/rpm-mirror.repo
|
|
||||||
dnf makecache
|
|
||||||
```
|
|
||||||
|
|
||||||
Das war's — egal ob ihr später weitere Quellen zur `sources.yaml`
|
|
||||||
hinzufügt, die Client-Konfiguration bleibt unverändert (`baseurl` und
|
|
||||||
`gpgkey` ändern sich nicht, nur der Inhalt des Repos wächst). Für die
|
|
||||||
Verteilung an viele Clients eignet sich dasselbe `curl`-Kommando in
|
|
||||||
Ansible/Config-Management oder einem Kickstart-Postscript.
|
|
||||||
|
|
||||||
`https://<host>/repo` selbst (ohne `/pkgs/`) ist weiterhin **kein** dnf-Repo,
|
|
||||||
sondern nur ein Verzeichnis-Listing (nginx `autoindex`) — `baseurl` muss auf
|
|
||||||
`/repo/pkgs/` zeigen (das steht schon so in der generierten
|
|
||||||
`mirror.repo`, ihr müsst daran nichts anpassen).
|
|
||||||
|
|
||||||
**Namenskonflikte:** Da jetzt alle Quellen in ein gemeinsames Verzeichnis
|
|
||||||
spiegeln, dürfen zwei Quellen keine RPMs mit demselben Paketnamen aber
|
|
||||||
unterschiedlichem Inhalt liefern (identische NEVRA aus zwei Quellen ist
|
|
||||||
unproblematisch, das ist einfach dasselbe Paket). Achtet bei mehreren
|
|
||||||
Drittanbieter-Repos in einer `sources.yaml` auf eindeutige Paketnamen.
|
|
||||||
|
|
||||||
## Dateien
|
|
||||||
|
|
||||||
- `sync.sh` — Hauptskript
|
|
||||||
- `sync_helpers.py` — YAML-Parsing & AppStream-XML-Generierung (muss im
|
|
||||||
selben Verzeichnis wie `sync.sh` liegen)
|
|
||||||
- `sources.example.yaml` — Beispiel-Quellenliste
|
|
||||||
- `docker-compose.yml`, `.env.example`, `docker/` — Container-Setup (siehe unten)
|
|
||||||
|
|
||||||
## Docker-Setup
|
|
||||||
|
|
||||||
Zwei Container:
|
|
||||||
|
|
||||||
- **syncer** — AlmaLinux 10 Image, führt `sync.sh` beim Start und danach alle
|
|
||||||
`SYNC_INTERVAL_SECONDS` erneut aus (einfache Sleep-Loop, kein Cron/systemd
|
|
||||||
im Container). Schreibt nach `/srv/repo` (benanntes Volume `repo-data`).
|
|
||||||
- **nginx** — liefert `repo-data` read-only unter `http://<host>:${NGINX_PORT}/repo/`
|
|
||||||
mit Directory-Listing aus, inklusive `client-repos/` für die fertigen
|
|
||||||
`.repo`-Dateien.
|
|
||||||
|
|
||||||
### Start
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cp .env.example .env
|
|
||||||
# .env anpassen: mindestens CLIENT_BASE_URL und ALMA_REPO_IDS prüfen
|
|
||||||
docker compose up -d --build
|
|
||||||
docker compose logs -f syncer
|
|
||||||
```
|
|
||||||
|
|
||||||
**`.env` ist die einzige Konfigurationsquelle:** `docker-compose.yml` selbst
|
|
||||||
enthält keine hartkodierten Umgebungsvariablen oder Defaults mehr — beide
|
|
||||||
Container laden alles per `env_file: .env`. Wer etwas ändern will (Pfade,
|
|
||||||
Sync-Intervall, Client-URL, Signier-Identität, Port, ...), bearbeitet
|
|
||||||
ausschließlich `.env` und macht `docker compose up -d`, ohne `docker-compose.yml`
|
|
||||||
anzufassen.
|
|
||||||
|
|
||||||
Danach ist das (eine, kombinierte) Repo erreichbar unter
|
|
||||||
`http://localhost:8080/repo/pkgs/` und die eine Client-`.repo`-Datei unter
|
|
||||||
`http://localhost:8080/repo/client-repos/mirror.repo`.
|
|
||||||
|
|
||||||
### Eigene Quellenliste einbinden
|
|
||||||
|
|
||||||
**Lokale Datei (Standard):** `LOCAL_SOURCES_YAML` in `.env` auf den Pfad
|
|
||||||
eurer echten `sources.yaml` setzen (relativ zum `docker-compose.yml`), z.B.
|
|
||||||
`LOCAL_SOURCES_YAML=./sources.yaml`. Wird read-only nach
|
|
||||||
`/config/sources.yaml` im Container gemountet.
|
|
||||||
|
|
||||||
**Git-Repo statt lokaler Datei:** `SOURCES_GIT_REPO`, `SOURCES_GIT_BRANCH`
|
|
||||||
und `SOURCES_YAML_FILE` (Pfad *innerhalb* des Git-Repos, relativ) in `.env`
|
|
||||||
setzen. Der Bind-Mount aus der lokalen Variante wird dann schlicht ignoriert.
|
|
||||||
|
|
||||||
### Einmaliger Sync statt Dauerlauf
|
|
||||||
|
|
||||||
`RUN_ONCE=true` in `.env` setzen — der `syncer`-Container synct dann einmal
|
|
||||||
und beendet sich, statt in der Schleife zu laufen. Praktisch, wenn ihr den
|
|
||||||
Sync lieber über einen externen Scheduler (Kubernetes CronJob, systemd-Timer
|
|
||||||
mit `docker compose run`, etc.) anstoßen wollt.
|
|
||||||
|
|
||||||
### ALMA_REPO_IDS prüfen
|
|
||||||
|
|
||||||
Die repoids im Container können von einer bare-metal-Installation abweichen.
|
|
||||||
Nach dem ersten Start prüfen:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker compose exec syncer dnf repolist
|
|
||||||
```
|
|
||||||
|
|
||||||
und `ALMA_REPO_IDS` in `.env` entsprechend anpassen, dann
|
|
||||||
`docker compose up -d` erneut ausführen.
|
|
||||||
|
|
||||||
### Persistenz
|
|
||||||
|
|
||||||
- `repo-data` (Volume) — die gespiegelten Repos selbst; das ist auch, was
|
|
||||||
nginx ausliefert.
|
|
||||||
- `sync-cache` (Volume) — Arbeitsverzeichnis von `sync.sh`
|
|
||||||
(`WORK_DIR`, u.a. Logs unter `sync.log`).
|
|
||||||
|
|
||||||
Beide überleben `docker compose down`; erst `docker compose down -v` löscht
|
|
||||||
sie.
|
|
||||||
Reference in New Issue
Block a user