Rust Package Builder
Minimalny kontener, który cyklicznie sprawdza branch Git, buduje projekt Rust i publikuje podpisane repozytoria APT oraz RPM/DNF.
Obsługiwane cele
- architektura: amd64 / x86_64
- Debian 12, Debian 13
- Ubuntu 24.04, Ubuntu 26.04
- RHEL/Rocky/Alma 9 i 10
Obraz buildera bazuje na Rocky Linux 9. Dzięki temu binarka jest budowana na glibc 2.34; builder dodatkowo odrzuca wynik wymagający nowszego symbolu glibc. Ta sama binarka może być pakowana do DEB i RPM dla wymienionych, nowszych systemów x86_64.
RustProxy
Dla dostarczonego RustProxy builder automatycznie używa plików znajdujących się w repozytorium źródłowym:
debian/rustproxy.servicedebian/rustproxy.environmentdebian/rustproxy.logrotatedebian/rustproxy.tmpfiles- logiki
debian/rustproxy.postinst grafana/rustproxy-overview.json
Nie utrzymuje drugiej kopii konfiguracji systemd RustProxy. Wersja i nazwa binarki pochodzą z metadanych Cargo, a nazwa pakietu i maintainer są przejmowane z debian/control, jeśli plik istnieje.
Uruchomienie
Najprostszy wariant wymaga ustawienia tylko dwóch wartości:
cp .env.example .env
# edytuj .env i ustaw SOURCE_REPO oraz REPOSITORY_URL
./start.sh
start.sh automatycznie:
- sprawdza Docker i Docker Compose,
- tworzy katalogi
data/igpg/, - buduje obraz buildera,
- przy pierwszym uruchomieniu generuje trwały klucz GPG RSA 3072 bez hasła,
- zapisuje klucz prywatny jako
gpg/private-key.asc, publiczny jakogpg/public-key.ascoraz fingerprint jakogpg/fingerprint, - przy kolejnych uruchomieniach ponownie używa tego samego klucza,
- uruchamia usługę przez
docker compose up -d, - builder natychmiast sprawdza repozytorium Git i po udanym buildzie publikuje APT oraz RPM/DNF.
Można też uruchomić bez wcześniejszego tworzenia .env:
SOURCE_REPO=https://git.linuxiarz.pl/gru/RustProxy.git \
REPOSITORY_URL=https://packages.linuxiarz.pl \
./start.sh
W takim przypadku start.sh zapisze te dwie wartości do .env.
Publiczny katalog repozytorium:
./data/repository/
Wystaw ten katalog przez nginx/RustProxy/Apache pod adresem z REPOSITORY_URL. Builder celowo nie uruchamia własnego HTTP ani TLS.
RustProxy 0.26.6 wymaga podczas builda Python 3.10+; obraz zawiera Python 3.11 i ustawia RUST_PROXY_PYTHON=/usr/bin/python3.11.
Klucz GPG
Klucz jest generowany tylko wtedy, gdy gpg/private-key.asc nie istnieje. Nie usuwaj katalogu gpg/ po publikacji repozytorium: zmiana klucza spowoduje, że klienci z wcześniej zainstalowanym kluczem przestaną ufać nowym podpisom.
Do backupu wystarczy zachować co najmniej:
gpg/private-key.asc
gpg/public-key.asc
gpg/fingerprint
data/
Konfiguracja
Wymagane:
SOURCE_REPO
REPOSITORY_URL
Domyślne:
SOURCE_BRANCH=master
POLL_INTERVAL=300
REPO_DISTRIBUTION=stable
REPO_COMPONENT=main
PACKAGE_RELEASE=auto
MAX_GLIBC_VERSION=2.34
GPG_PRIVATE_KEY_FILE=/run/secrets/gpg/private-key.asc
GPG_PASSPHRASE_FILE=/run/secrets/gpg/passphrase
GPG_PASSPHRASE_FILE nie musi istnieć dla klucza bez hasła. GPG_KEY_ID może być podany przez ENV; jeśli go brak, builder wybiera pierwszy zaimportowany klucz prywatny.
Dane trwałe
/var/lib/package-builder/
├── aptly/ # baza/pool aptly
├── cargo/ # registry + target cache
├── packages/
│ ├── deb/ # historia zbudowanych DEB
│ └── rpm/x86_64/ # historia zbudowanych RPM
├── repository/
│ ├── current -> releases/<build>
│ ├── apt -> current/apt
│ ├── rpm -> current/rpm
│ ├── repo-key.gpg -> current/repo-key.gpg
│ ├── index.html -> current/index.html
│ └── releases/
├── state/
│ ├── last_commit
│ ├── last_version
│ └── last_package_release
└── work/
Poprzednie wersje pakietów nie są usuwane. Aktualne repozytoria APT i RPM zawierają historię pakietów. Przy PACKAGE_RELEASE=auto nowy commit z niezmienionym Cargo.toml version dostaje kolejną rewizję paczki (-2, -3, ...), więc nie nadpisuje wcześniej opublikowanego artefaktu.
Publikacja bez uszkodzenia działającego repo
Nowy commit przechodzi kolejno:
clone -> cargo build --release -> nFPM DEB/RPM -> podpisy -> aptly -> createrepo_c -> walidacja -> atomic switch
Publiczny symlink repository/current jest podmieniany dopiero na końcu. Błąd kompilacji, pakowania, podpisu lub generowania metadata nie przełącza publicznego repozytorium. last_commit jest zapisywany dopiero po udanej publikacji, więc nieudany commit zostanie ponowiony w następnym cyklu.
Kolejne snapshoty w repository/releases/ używają hardlinków do niezmienionych plików poprzedniego snapshotu, więc zachowanie historii nie oznacza pełnej kopii wszystkich paczek przy każdym buildzie.
Podpisy
- DEB: podpis GPG nFPM (
_gpgorigin) oraz podpisaneRelease.gpg/InReleaseprzez aptly. - RPM: podpis GPG pakietu nFPM.
- RPM metadata:
repodata/repomd.xml.asc; instrukcja używarepo_gpgcheck=1igpgcheck=1. - publiczny klucz:
https://.../repo-key.gpgjako ASCII-armored OpenPGP, zgodny zgpg --dearmorirpm --import.
Test plików dostarczonego RustProxy
./tests/static.sh
./tests/check-rustproxy-source.sh /sciezka/do/RustProxy
HTTP
Builder nie uruchamia serwera HTTP i nie obsługuje TLS. Generuje katalog repository/ oraz prosty index.html z instrukcją instalacji dopasowaną do REPOSITORY_URL i nazwy pakietu.
Własny klucz GPG (opcjonalnie)
Jeżeli zamiast automatycznie generowanego klucza chcesz użyć własnego, umieść go przed pierwszym ./start.sh jako:
gpg/private-key.asc
Przykładowy eksport:
gpg --armor --export-secret-keys YOUR_KEY_ID > gpg/private-key.asc
chmod 600 gpg/private-key.asc
start.sh wykryje istniejący klucz i nie wygeneruje nowego. Klucz prywatny nie jest kopiowany do obrazu. Kontener otrzymuje katalog gpg/ wyłącznie jako read-only mount /run/secrets/gpg.