opn
This commit is contained in:
1 parent
cce1081f75
commit
2b8f11ef8c
36 files changed
+1868
-309
No files matched your search
@@ -1,160 +1,159 @@
|
||||
# Rust Package Builder
|
||||
# RustProxy unified package builder
|
||||
|
||||
Minimalny automat Docker, który cyklicznie sprawdza branch Git, buduje projekt Rust i publikuje podpisane repozytoria APT oraz RPM/DNF. Projekt zawiera również mały, utwardzony serwer HTTP udostępniający gotowe repozytorium i stronę z instrukcją instalacji.
|
||||
Jeden kontener buildera buduje z jednego commita RustProxy:
|
||||
|
||||
## Obsługiwane cele
|
||||
- Linux x86_64: DEB + podpisane repo APT,
|
||||
- Linux x86_64: RPM + podpisane repo DNF/YUM,
|
||||
- FreeBSD x86_64: cross-build bez VM FreeBSD,
|
||||
- OPNsense: `os-rustproxy-<version>_<revision>.pkg` + statyczne repo `pkg`.
|
||||
|
||||
- architektura: amd64 / x86_64
|
||||
- Debian 12, Debian 13
|
||||
- Ubuntu 24.04, Ubuntu 26.04
|
||||
- RHEL/Rocky/Alma 9 i 10
|
||||
Nie ma Docker-in-Docker, SCP ani osobnego watchera repo OPNsense. FreeBSD sysroot, clang/lld i Rust target są częścią głównego obrazu buildera. OPNsense dostaje osobny publiczny adres, ale wszystkie artefakty są publikowane jednym atomowym przełączeniem `repository/current`.
|
||||
|
||||
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.service`
|
||||
- `debian/rustproxy.environment`
|
||||
- `debian/rustproxy.logrotate`
|
||||
- `debian/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
|
||||
|
||||
Ustawiasz ręcznie tylko dwie wartości:
|
||||
## Szybki start
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
./start.sh
|
||||
```
|
||||
|
||||
Przykład dla serwera `192.168.1.100`:
|
||||
Minimalnie ustaw:
|
||||
|
||||
```env
|
||||
SOURCE_REPO=https://git.linuxiarz.pl/gru/RustProxy.git
|
||||
REPOSITORY_URL=http://192.168.1.100
|
||||
OPNSENSE_REPOSITORY_URL=https://opn-rustproxy.linuxiarz.pl
|
||||
```
|
||||
|
||||
Następnie:
|
||||
Dla `http://` bez portu `start.sh` dopisze domyślny port. Dla `https://` zakładany jest zewnętrzny reverse proxy/TLS.
|
||||
|
||||
```bash
|
||||
./start.sh
|
||||
```
|
||||
|
||||
Jeżeli w `REPOSITORY_URL` nie podasz portu, `start.sh` automatycznie ustawi `18765` i zapisze efektywny adres, np.:
|
||||
Domyślne lokalne porty:
|
||||
|
||||
```text
|
||||
http://192.168.1.100:18765
|
||||
APT/RPM: 18765 -> nginx :8080
|
||||
OPNsense: 18766 -> nginx :8081
|
||||
```
|
||||
|
||||
Jeżeli chcesz inny port, wystarczy wpisać go bezpośrednio w adresie:
|
||||
|
||||
```env
|
||||
REPOSITORY_URL=http://192.168.1.100:23456
|
||||
```
|
||||
|
||||
Nie trzeba ustawiać osobnego `HTTP_PORT` ręcznie — skrypt pobierze go z adresu. `HTTP_PORT` jest zapisywany pomocniczo do `.env`, aby Compose zachował tę samą konfigurację.
|
||||
|
||||
`start.sh` automatycznie:
|
||||
|
||||
- sprawdza Docker i Docker Compose,
|
||||
- tworzy katalogi `data/` i `gpg/`,
|
||||
- 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 jako `gpg/public-key.asc` oraz fingerprint jako `gpg/fingerprint`,
|
||||
- przy kolejnych uruchomieniach używa tego samego klucza,
|
||||
- uruchamia builder i mikroserwer HTTP,
|
||||
- builder natychmiast sprawdza repozytorium Git i po udanym buildzie publikuje APT oraz RPM/DNF,
|
||||
- strona główna HTTP automatycznie pokazuje instrukcję instalacji i linki do klucza/metadanych.
|
||||
|
||||
Można też uruchomić bez wcześniejszego tworzenia `.env`:
|
||||
|
||||
```bash
|
||||
SOURCE_REPO=https://git.linuxiarz.pl/gru/RustProxy.git \
|
||||
REPOSITORY_URL=http://192.168.1.100 \
|
||||
./start.sh
|
||||
```
|
||||
|
||||
## Mikro HTTP
|
||||
|
||||
Repozytorium jest wystawiane przez osobny kontener `repository-http` oparty o `nginxinc/nginx-unprivileged:stable-alpine-slim`.
|
||||
|
||||
Domyślnie:
|
||||
Przykładowo reverse proxy może kierować:
|
||||
|
||||
```text
|
||||
http://ADRES_SERWERA:18765/
|
||||
packages.example.net -> http://builder:18765
|
||||
opn-rustproxy.linuxiarz.pl -> http://builder:18766
|
||||
```
|
||||
|
||||
Serwer HTTP jest celowo bardzo prosty:
|
||||
|
||||
- działa jako użytkownik nieuprzywilejowany,
|
||||
- kontener ma `cap_drop: ALL`,
|
||||
- ma `no-new-privileges`,
|
||||
- root filesystem jest read-only,
|
||||
- repozytorium jest montowane read-only,
|
||||
- obsługuje wyłącznie `GET` i `HEAD`,
|
||||
- nie pozwala na upload,
|
||||
- nie pokazuje listingów katalogów,
|
||||
- blokuje pliki ukryte,
|
||||
- dodaje podstawowe nagłówki bezpieczeństwa,
|
||||
- posiada `/healthz`,
|
||||
- logi idą do `docker compose logs`.
|
||||
|
||||
Przed pierwszym udanym buildem `/` wyświetla prostą informację, że repozytorium jest inicjalizowane. Po publikacji builder atomowo podmienia stronę na właściwą instrukcję instalacji.
|
||||
|
||||
### HTTPS
|
||||
|
||||
Wbudowany mikroserwer świadomie obsługuje tylko HTTP. Jeżeli `REPOSITORY_URL` zaczyna się od `https://`, zakładane jest, że przed nim stoi zewnętrzny reverse proxy/TLS (np. RustProxy/nginx/Caddy). Sam builder nadal wystawia lokalny HTTP na porcie `18765` lub `HTTP_PORT`.
|
||||
|
||||
Dla kompletnego uruchomienia bez reverse proxy użyj `http://IP_LUB_HOST`.
|
||||
|
||||
## 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 zachowaj co najmniej:
|
||||
## Pipeline
|
||||
|
||||
```text
|
||||
gpg/private-key.asc
|
||||
gpg/public-key.asc
|
||||
gpg/fingerprint
|
||||
data/
|
||||
Git RustProxy
|
||||
|
|
||||
+-> cargo test
|
||||
+-> Linux cargo build
|
||||
| +-> DEB
|
||||
| +-> RPM
|
||||
|
|
||||
+-> izolowana kopia źródła
|
||||
+-> poprawki FreeBSD/OPNsense
|
||||
+-> x86_64-unknown-freebsd
|
||||
+-> os-rustproxy.pkg
|
||||
|
|
||||
+-> APT metadata
|
||||
+-> RPM metadata
|
||||
+-> OPNsense pkg metadata
|
||||
+-> walidacja
|
||||
+-> atomic switch repository/current
|
||||
```
|
||||
|
||||
Jeżeli którykolwiek etap się nie powiedzie, publiczne repozytoria nie są przełączane.
|
||||
|
||||
## OPNsense repo
|
||||
|
||||
Publiczny root `OPNSENSE_REPOSITORY_URL` zawiera m.in.:
|
||||
|
||||
```text
|
||||
/
|
||||
├── meta.conf
|
||||
├── packagesite.pkg
|
||||
├── data.pkg
|
||||
├── RustProxy.conf
|
||||
├── BUILD-INFO.txt
|
||||
├── SHA256
|
||||
├── os-rustproxy-latest.pkg
|
||||
└── 26.7/
|
||||
└── amd64/
|
||||
├── os-rustproxy-0.20.0_123.pkg
|
||||
└── ...
|
||||
```
|
||||
|
||||
`RustProxy.conf` jest generowany automatycznie i wskazuje na `OPNSENSE_REPOSITORY_URL`. Repo OPNsense jest obecnie niesygnowane, zgodnie z wcześniejszym builderem/repo (`signature_type: "none"`). Repo APT/RPM pozostaje podpisane GPG.
|
||||
|
||||
Ręczna konfiguracja na OPNsense:
|
||||
|
||||
```sh
|
||||
mkdir -p /usr/local/etc/pkg/repos
|
||||
fetch -o /usr/local/etc/pkg/repos/RustProxy.conf \
|
||||
https://opn-rustproxy.linuxiarz.pl/RustProxy.conf
|
||||
pkg update -f
|
||||
pkg install os-rustproxy
|
||||
```
|
||||
|
||||
## Konfiguracja
|
||||
|
||||
Wymagane:
|
||||
Najważniejsze zmienne:
|
||||
|
||||
```text
|
||||
SOURCE_REPO
|
||||
REPOSITORY_URL
|
||||
```
|
||||
|
||||
Domyślne / automatyczne:
|
||||
|
||||
```text
|
||||
```env
|
||||
SOURCE_REPO=https://git.linuxiarz.pl/gru/RustProxy.git
|
||||
SOURCE_BRANCH=master
|
||||
POLL_INTERVAL=300
|
||||
|
||||
REPOSITORY_URL=http://192.168.1.100
|
||||
HTTP_PORT=18765
|
||||
REPO_DISTRIBUTION=stable
|
||||
REPO_COMPONENT=main
|
||||
|
||||
OPNSENSE_REPOSITORY_URL=https://opn-rustproxy.linuxiarz.pl
|
||||
OPNSENSE_HTTP_PORT=18766
|
||||
|
||||
POLL_INTERVAL=300
|
||||
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
|
||||
RUN_LINUX_TESTS=1
|
||||
|
||||
OPNSENSE_ABI=26.7
|
||||
OPNSENSE_RETENTION=10
|
||||
FREEBSD_RELEASE=15.1-RELEASE
|
||||
FREEBSD_ABI=FreeBSD:15:amd64
|
||||
FREEBSD_ARCH=freebsd:15:x86:64
|
||||
FREEBSD_RUST_TOOLCHAIN=1.88.0
|
||||
APPLY_FREEBSD_PATCHES=1
|
||||
```
|
||||
|
||||
`GPG_PASSPHRASE_FILE` nie musi istnieć dla automatycznie generowanego klucza bez hasła. `GPG_KEY_ID` może być podany przez ENV; jeśli go brak, builder wybiera pierwszy zaimportowany klucz prywatny.
|
||||
`OPNSENSE_RETENTION=10` zachowuje ostatnie 10 wersji pakietu dla danej serii/architektury OPNsense. `0` wyłącza usuwanie starych wersji.
|
||||
|
||||
## Dane trwałe
|
||||
## FreeBSD cross-build
|
||||
|
||||
Obraz buildera pobiera i weryfikuje `base.txz` dla `FREEBSD_RELEASE`, a następnie używa:
|
||||
|
||||
```text
|
||||
/var/lib/package-builder/
|
||||
/opt/freebsd-sysroot
|
||||
clang / lld / llvm
|
||||
Rust target x86_64-unknown-freebsd
|
||||
```
|
||||
|
||||
Poprawki tylko dla builda OPNsense są w:
|
||||
|
||||
```text
|
||||
opnsense/patches/<wersja-RustProxy>/*.patch
|
||||
```
|
||||
|
||||
Są nakładane na izolowaną kopię źródła. Build Linux nie jest modyfikowany.
|
||||
|
||||
Kod pluginu OPNsense znajduje się w:
|
||||
|
||||
```text
|
||||
opnsense/plugin/
|
||||
```
|
||||
|
||||
## Dane
|
||||
|
||||
```text
|
||||
data/
|
||||
├── aptly/
|
||||
├── cargo/
|
||||
├── packages/
|
||||
@@ -164,69 +163,33 @@ GPG_PASSPHRASE_FILE=/run/secrets/gpg/passphrase
|
||||
│ ├── current -> releases/<build>
|
||||
│ ├── apt -> current/apt
|
||||
│ ├── rpm -> current/rpm
|
||||
│ ├── repo-key.gpg -> current/repo-key.gpg
|
||||
│ ├── index.html -> current/index.html
|
||||
│ ├── opnsense -> current/opnsense
|
||||
│ └── 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.
|
||||
Jeden release zawiera jednocześnie `apt/`, `rpm/` i `opnsense/`. Dzięki temu oba publiczne adresy przechodzą na nową wersję jednocześnie.
|
||||
|
||||
## Publikacja bez uszkodzenia działającego repo
|
||||
## HTTP i logi
|
||||
|
||||
Nowy commit przechodzi kolejno:
|
||||
|
||||
```text
|
||||
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.
|
||||
|
||||
## Podpisy
|
||||
|
||||
- DEB: podpis GPG nFPM (`_gpgorigin`) oraz podpisane `Release.gpg`/`InRelease` przez aptly.
|
||||
- RPM: podpis GPG pakietu nFPM.
|
||||
- RPM metadata: `repodata/repomd.xml.asc`; instrukcja używa `repo_gpgcheck=1` i `gpgcheck=1`.
|
||||
- publiczny klucz: `http(s)://.../repo-key.gpg` jako ASCII-armored OpenPGP, zgodny z `gpg --dearmor` i `rpm --import`.
|
||||
|
||||
## Logi i kontrola
|
||||
Jeden kontener nginx obsługuje oba repozytoria na dwóch lokalnych portach:
|
||||
|
||||
```bash
|
||||
docker compose logs -f rust-package-builder
|
||||
docker compose logs -f repository-http
|
||||
|
||||
curl -f http://127.0.0.1:18765/healthz
|
||||
curl -f http://127.0.0.1:18766/healthz
|
||||
```
|
||||
|
||||
## Test plików dostarczonego RustProxy
|
||||
## Testy statyczne
|
||||
|
||||
```bash
|
||||
./tests/static.sh
|
||||
./tests/check-rustproxy-source.sh /sciezka/do/RustProxy
|
||||
```
|
||||
|
||||
## Własny klucz GPG (opcjonalnie)
|
||||
## Klucz GPG
|
||||
|
||||
Jeżeli zamiast automatycznie generowanego klucza chcesz użyć własnego, umieść go przed pierwszym `./start.sh` jako:
|
||||
|
||||
```text
|
||||
gpg/private-key.asc
|
||||
```
|
||||
|
||||
Przykładowy eksport:
|
||||
|
||||
```bash
|
||||
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`.
|
||||
|
||||
## Rocky Linux 9 / pakiety bazowe
|
||||
|
||||
Dockerfile używa `dnf --allowerasing`, ponieważ obrazy Rocky Linux 9 mogą zawierać `coreutils-single` i `curl-minimal`. Podczas budowy są one zastępowane pełnymi pakietami `coreutils` i `curl`, wymaganymi przez builder.
|
||||
`./start.sh` generuje trwały klucz GPG przy pierwszym uruchomieniu. Katalogu `gpg/` nie należy usuwać po publikacji APT/RPM.
|
||||
Reference in new issue
Block a user