305 lines
12 KiB
Markdown
305 lines
12 KiB
Markdown
# RustProxy unified package builder
|
||
|
||
Jeden kontener buildera buduje z jednego commita RustProxy:
|
||
|
||
- 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`.
|
||
|
||
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. Gałąź Linux i gałąź OPNsense są budowane oraz publikowane niezależnie, więc błąd testów Linux nie blokuje pakietu FreeBSD.
|
||
|
||
## Szybki start
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
nano .env
|
||
./start.sh
|
||
```
|
||
|
||
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
|
||
```
|
||
|
||
Dla `http://` bez portu `start.sh` dopisze domyślny port. Dla `https://` zakładany jest zewnętrzny reverse proxy/TLS.
|
||
|
||
Domyślne lokalne porty:
|
||
|
||
```text
|
||
APT/RPM: 18765 -> nginx :8080
|
||
OPNsense: 18766 -> nginx :8081
|
||
```
|
||
|
||
Przykładowo reverse proxy może kierować:
|
||
|
||
```text
|
||
packages.example.net -> http://builder:18765
|
||
opn-rustproxy.linuxiarz.pl -> http://builder:18766
|
||
```
|
||
|
||
## Pipeline
|
||
|
||
```text
|
||
Git RustProxy
|
||
|
|
||
wspólny checkout
|
||
/ \
|
||
/ \
|
||
Linux branch OPNsense branch
|
||
cargo test izolowana kopia źródła
|
||
cargo build poprawki FreeBSD
|
||
DEB + RPM cross-build FreeBSD
|
||
APT + DNF os-rustproxy.pkg
|
||
| |
|
||
v v
|
||
publikacja Linux publikacja OPNsense
|
||
```
|
||
|
||
`cargo test` należy tylko do gałęzi Linux. Jeśli testy nie przejdą, DEB/RPM nie są publikowane, ale builder nadal uruchamia cross-build FreeBSD i może opublikować repo OPNsense. Stan jest śledzony osobno w `last_linux_commit` i `last_opnsense_commit`, więc kolejny cykl ponawia tylko brakującą gałąź.
|
||
|
||
## 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
|
||
|
||
Najważniejsze zmienne:
|
||
|
||
```env
|
||
SOURCE_REPO=https://git.linuxiarz.pl/gru/RustProxy.git
|
||
SOURCE_BRANCH=master
|
||
|
||
REPOSITORY_URL=http://192.168.1.100
|
||
HTTP_PORT=18765
|
||
|
||
OPNSENSE_REPOSITORY_URL=https://opn-rustproxy.linuxiarz.pl
|
||
OPNSENSE_HTTP_PORT=18766
|
||
|
||
POLL_INTERVAL=300
|
||
PACKAGE_RELEASE=auto
|
||
MAX_GLIBC_VERSION=2.34
|
||
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
|
||
```
|
||
|
||
`RUN_LINUX_TESTS=1` jest domyślne. Testy są bramką tylko dla DEB/RPM i nie wpływają na gałąź OPNsense. Ustaw `0`, jeśli chcesz całkowicie pominąć testy Linux.
|
||
|
||
`OPNSENSE_RETENTION=10` zachowuje ostatnie 10 wersji pakietu dla danej serii/architektury OPNsense. `0` wyłącza usuwanie starych wersji.
|
||
|
||
## Automatyczny Rust toolchain podczas budowania
|
||
|
||
Builder sprawdza `rust-version` w `Cargo.toml` **pobranego commita** i opcjonalny
|
||
`rust-toolchain.toml`/`rust-toolchain` przed kompilacją każdej gałęzi.
|
||
|
||
- **Linux DEB/RPM:** używa istniejącego `stable`; wywołuje `rustup` tylko,
|
||
gdy brakuje toolchainu albo wersja jest starsza od wymaganej przez projekt.
|
||
- **FreeBSD/OPNsense:** `FREEBSD_RUST_TOOLCHAIN` pozostaje bazowym toolchainem.
|
||
Gdy jest starszy od `rust-version`, builder automatycznie dobiera wersję
|
||
minimalną projektu oraz doinstalowuje target `x86_64-unknown-freebsd`.
|
||
- Jeśli projekt przypina konkretny toolchain, builder **respektuje pin**.
|
||
Sprzeczny pin i `rust-version` powodują czytelny błąd zamiast cichej zmiany.
|
||
- Testy i build danej gałęzi używają tego samego wybranego toolchainu.
|
||
- Aktualizacja nie zmienia globalnego `rustup default`, systemowych pakietów
|
||
ani wersji już opublikowanych pakietów RustProxy.
|
||
- Toolchainy pobrane w trakcie działania są w warstwie kontenera
|
||
(`/opt/rustup`); po **odtworzeniu kontenera** mogą wymagać ponownego pobrania.
|
||
Cache Cargo w `data/cargo` pozostaje trwały.
|
||
- Jeśli pobranie toolchainu lub kompilacja się nie powiedzie, dany kanał
|
||
nie zostaje opublikowany; pozostały kanał builder obsługuje niezależnie.
|
||
|
||
Działanie nie wymaga nowej opcji w `.env`. Uruchom `./start.sh`, żeby
|
||
przebudować obraz z nowym skryptem. Aktualizacje toolchainu na podstawie
|
||
źródeł będą potem automatyczne przy kolejnych buildach.
|
||
|
||
## FreeBSD cross-build
|
||
|
||
Obraz buildera pobiera i weryfikuje `base.txz` dla `FREEBSD_RELEASE`, a następnie używa:
|
||
|
||
```text
|
||
/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/
|
||
```
|
||
|
||
## OPNsense: autostart i sprawdzanie aktualizacji aplikacji
|
||
|
||
W **Services -> RustProxy** zaznacz **Enabled** i naciśnij **Apply**. Pakiet
|
||
instaluje wykonywalny syshook w
|
||
`/usr/local/etc/rc.syshook.d/start/50-rustproxy.start`. Po restarcie systemu,
|
||
gdy sieć już działa, hook odświeża konfigurację z OPNsense i uruchamia usługę
|
||
tylko wtedy, gdy jest włączona. Powtórny start nie tworzy drugiego procesu.
|
||
|
||
Pole **Update check interval (seconds)** steruje argumentem RustProxy
|
||
`--update-check-interval-secs`. Domyślnie `3600` (godzina); dopuszczalny zakres
|
||
to `60`–`604800` sekund. Wartość nie dotyczy `POLL_INTERVAL` buildera,
|
||
który nadal odpowiada wyłącznie za sprawdzanie repozytorium kodu.
|
||
|
||
Sprawdzenie po restarcie OPNsense:
|
||
|
||
```sh
|
||
ls -l /usr/local/etc/rc.syshook.d/start/50-rustproxy.start
|
||
configctl rustproxy status
|
||
cat /var/run/rustproxy/command.txt
|
||
```
|
||
|
||
W `command.txt` powinien wystąpić aktualnie ustawiony parametr
|
||
`--update-check-interval-secs <liczba>`. Jeśli usługa nie wystartuje, sprawdź
|
||
`/var/log/rustproxy/rustproxy.log` oraz uruchom ręcznie:
|
||
|
||
```sh
|
||
configctl template reload OPNsense/RustProxy
|
||
configctl rustproxy start
|
||
```
|
||
|
||
Zmiana wtyczki zwiększa tylko `OPNSENSE_PACKAGING_REVISION` do `3`.
|
||
Rewizja pakowania Linux (`PACKAGING_REVISION=2`) pozostaje bez zmian.
|
||
|
||
## Rotacja logów RustProxy
|
||
|
||
- **DEB/RPM:** builder zawsze umieszcza `packaging/rustproxy.logrotate` w `/etc/logrotate.d/rustproxy` (nFPM: `config|noreplace`). Logrotate jest zależnością obu pakietów. Reguła obejmuje `/var/log/rustproxy/*.jsonl`, `*.log` i `vhosts/*.jsonl`, z rotacją codzienną lub po przekroczeniu 100 MiB, 14 archiwami, gzip z opóźnioną kompresją, `copytruncate` oraz `su rustproxy rustproxy`.
|
||
- **OPNsense/FreeBSD PKG:** pakiet dostarcza `/usr/local/etc/newsyslog.conf.d/rustproxy.conf` dla tych samych ścieżek; `newsyslog` wykonuje rotację codziennie lub przy rozmiarze 100 MiB, przechowuje 14 archiwów, pomija puste pliki i używa gzip z niekompresowanym najnowszym archiwum. Plik `*.log` jest ponownie otwierany przez `daemon(8)` po `SIGHUP` (opcja `-H` w skrypcie rc.d). OPNsense uruchamia usługę jako `root`, dlatego `newsyslog` używa `root:wheel`.
|
||
|
||
**Uwaga FreeBSD:** `newsyslog` działa przez zmianę nazwy pliku, nie ma `copytruncate`. Pliki JSONL i inne logi otwarte bezpośrednio przez aplikację muszą być przez nią ponownie otwierane po rotacji. W przeciwnym razie proces może pisać do poprzedniego (przeniesionego) pliku; zachowanie nie jest identyczne z Linux. Reguły są instalowane, ale na działającym OPNsense należy zweryfikować sposób otwierania plików przez RustProxy.
|
||
|
||
Poprzednia zmiana rotacji logów ustawiła `PACKAGING_REVISION=2`. `check-and-build.sh` sprawdza osobno rewizję pakowania Linux i OPNsense; nowa wersja samej wtyczki przebudowuje **tylko OPNsense**, nawet przy niezmienionym SHA aplikacji. Rewizja pakietu PKG zwiększy się automatycznie. W przypadku zmiany rewizji Linux analogicznie odświeżane są DEB/RPM. Konfiguracja w `/etc/logrotate.d/rustproxy` jest oznaczona jako `noreplace`, więc lokalna wersja zmodyfikowana przez administratora może zostać zachowana (zależnie od menedżera pakietów).
|
||
|
||
Kontrola po zainstalowaniu:
|
||
|
||
```sh
|
||
# DEB / RPM (nie wykonuje rotacji)
|
||
logrotate -d /etc/logrotate.d/rustproxy
|
||
|
||
# OPNsense (nie wykonuje rotacji)
|
||
newsyslog -n -v -f /usr/local/etc/newsyslog.conf.d/rustproxy.conf
|
||
```
|
||
|
||
Pakietowe testy integracyjne (lokalnie, bez budowy aplikacji):
|
||
|
||
```sh
|
||
./tests/log-rotation.sh
|
||
```
|
||
|
||
## Dane
|
||
|
||
```text
|
||
data/
|
||
├── aptly/
|
||
├── cargo/
|
||
├── packages/
|
||
│ ├── deb/
|
||
│ └── rpm/x86_64/
|
||
├── repository/
|
||
│ ├── current -> releases/<build>
|
||
│ ├── apt -> current/apt
|
||
│ ├── rpm -> current/rpm
|
||
│ ├── opnsense -> current/opnsense
|
||
│ └── releases/
|
||
├── state/
|
||
└── work/
|
||
```
|
||
|
||
Każda publikacja tworzy nowy snapshot `repository/releases/...` i atomowo przełącza `current`. Przy publikacji Linux poprzedni katalog OPNsense jest zachowywany, a przy publikacji OPNsense zachowywane są aktualne APT/RPM. Dzięki temu obie gałęzie są niezależne, ale nginx nadal serwuje jeden spójny snapshot katalogu.
|
||
|
||
## HTTP i logi
|
||
|
||
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
|
||
```
|
||
|
||
## Testy statyczne
|
||
|
||
```bash
|
||
./tests/static.sh
|
||
./tests/check-rustproxy-source.sh /sciezka/do/RustProxy
|
||
```
|
||
|
||
## Klucz GPG
|
||
|
||
`./start.sh` generuje trwały klucz GPG przy pierwszym uruchomieniu. Katalogu `gpg/` nie należy usuwać po publikacji APT/RPM.
|
||
|
||
## Migracja ze starszego buildera Linux-only
|
||
|
||
Builder używa osobnych stanów:
|
||
|
||
```text
|
||
data/state/last_linux_commit
|
||
data/state/last_opnsense_commit
|
||
```
|
||
|
||
Jeżeli istnieje starsze `last_commit` oraz poprawne APT/RPM dla tego SHA, zostanie ono potraktowane jako stan gałęzi Linux. Brak repo OPNsense uruchomi wyłącznie gałąź OPNsense. Po udanym OPNsense kolejny cykl nie będzie ponownie kompilował FreeBSD, nawet jeśli testy Linux nadal nie przechodzą.
|
||
|
||
## FreeBSD patch version detection
|
||
|
||
The OPNsense branch reuses the Cargo package `VERSION` already detected by the main build pipeline. If `apply-freebsd-patches.sh` is run manually, it falls back to `RUST_PROXY_PYTHON` (`/usr/bin/python3.11`) so Rocky Linux 9's default Python 3.9 does not cause a missing `tomllib` error.
|
||
|
||
### Czyszczenie cache Cargo
|
||
|
||
Po **udanym opublikowaniu pakietów** każdej gałęzi (Linux/OPNsense) builder
|
||
usuwa `target/**/incremental` i `target/debug`, a także pliki starsze
|
||
niż 30 dni z `target/release/deps` oraz
|
||
`target/x86_64-unknown-freebsd/release/deps`. Zachowuje aktualne artefakty
|
||
release, fingerprinty oraz cache zależności, więc kolejne buildy nie startują
|
||
od zera. Starsze usunięte zależności mogą wymagać pojedynczej rekompilacji.
|
||
|
||
Ustawienia środowiskowe: `CLEAN_TARGET_AFTER_BUILD=0` wyłącza czyszczenie;
|
||
`TARGET_CACHE_MAX_AGE_DAYS=30` określa wiek nieużywanych plików.
|
||
|