# pag – PaganOS Package Manager [![Wersja](https://img.shields.io/badge/pag-3.3.20-blue)](https://git.paganlinux.eu/pag) [![Platforma](https://img.shields.io/badge/PaganOS-Linux-success)](https://paganlinux.eu) Menedżer pakietów dla [PaganOS](https://paganlinux.eu). Instalacja atomowa (staging → rename), weryfikacja podpisów GPG z pinningiem fingerprintu, SHA256 per-plik, pełny rollback transakcji, hooki i triggery oraz wsparcie systemów immutable z wdrożeniami (deployments). Diagramy w tym README renderuje Mermaid – obsługiwany przez portal `git.paganlinux.eu` (oraz GitHub/Gitea). ```bash pag --version # wersja klienta (np. pag 3.3.20) pag # pełna pomoc (lista komend) pag --help # to samo co wyżej ``` --- ## Spis treści - [Szybki start](#szybki-start) - [Jak to działa](#jak-to-działa) - [Przepływ `pag install`](#przepływ-pag-install) - [Łańcuch zaufania](#łańcuch-zaufania) - [System immutable](#system-immutable) - [Rollback](#rollback) - [Rolling – baza z obrazu ISO](#rolling--baza-z-obrazu-iso) - [Komendy](#komendy) - [Zmienne środowiskowe](#zmienne-środowiskowe) - [Ścieżki i pliki](#ścieżki-i-pliki) - [Format pakietu](#format-pakietu) - [Hooki i triggery](#hooki-i-triggery) - [Konfiguracja `/etc` – `.pacnew` / `.pacsave`](#konfiguracja-etc--pacnew--pacsave) - [Przykłady](#przykłady) - [Diagnostyka](#diagnostyka) - [Instalacja i aktualizacja](#instalacja-i-aktualizacja) - [Licencja](#licencja) --- ## Szybki start ```bash # Odśwież indeksy repozytoriów (i zobacz, co czeka na aktualizację) sudo pag sync # Instaluj / usuwaj sudo pag install firefox gimp sudo pag remove gimp # Aktualizuj same pakiety… sudo pag update # …albo cały system: pakiety + kernel / initramfs / GRUB sudo pag upgrade # Baza zbudowana w obrazie ISO a repozytorium (pełny rolling) pag base # co jest z obrazu, a czym pag już zarządza sudo pag base adopt # dograj bazę z repo (--dry-run = podgląd) # Sprawdź integralność wszystkich plików sudo pag verify --deep ``` --- ## Jak to działa ### Przepływ `pag install` ```mermaid graph TD A["pag install pkg"] --> B["Rozwiązanie zależności (DFS + provides)"] B --> C{"Brakujące zależności?"} C -->|tak| C1["Błąd – przerwij"] C -->|nie| D["Weryfikacja ABI (so-name)"] D --> E["Pre-flight: wolne miejsce + montowanie RW"] E --> F["Blokada flock + migawka bazy"] F --> G["Równoległe pobieranie paczek"] G --> H["Weryfikacja GPG + SHA256 paczki"] H --> I["Staging: rozpakowanie + sumy per-plik"] I --> J["Atomowy rename plików do systemu"] J --> K["Hooki pre/post-install"] K --> L["Zapis do SQLite + historia transakcji"] L --> M{"PAG_IMMUTABLE=1?"} M -->|tak| N["Nowy deployment + wpisy GRUB"] M -->|nie| O["ldconfig + triggery"] H -->|błąd| R["Rollback całej transakcji"] I -->|błąd| R J -->|błąd| R R --> S["Przywrócenie bazy i plików"] ``` Kluczowe własności: - **Atomowość** – pliki trafiają najpierw do staging na tej samej partycji co `/`, potem są przenoszone `rename()` (bez pół-instalacji). - **Transakcyjność** – jeśli którykolwiek pakiet zawiedzie, cała transakcja jest cofana (`installed.json`, pliki, backupy). - **Współdzielenie plików** – plik należący do dwóch pakietów nie jest usuwany przy usunięciu jednego z nich (usuwany jest tylko wpis w bazie). ### Łańcuch zaufania ```mermaid graph TD A["repo.json + repo.json.asc"] --> B["GPG: linia VALIDSIG"] B --> C["Pinning fingerprintu repo (TOFU → pin)"] C --> D["Indeks pakietów"] D --> E["pakiet .pag + .asc"] E --> F["GPG: podpis zgodny z pinem repo"] F --> G["SHA256 całej paczki"] G --> H["Bezpieczne rozpakowanie (anty-traversal)"] H --> I["sums.json: SHA256 per plik"] I --> J["Zdjęcie bitu SUID"] J --> K["Instalacja"] F -->|"brak / zły podpis"| X["Odrzuć paczkę"] G -->|"niezgodny SHA256"| X H -->|"traversal / escape przez symlink"| X ``` - Pierwsze użycie klucza = **TOFU**, potem fingerprint jest **przypinany** (`pag key-trust` / `pag key-untrust`). - Weryfikacja jest **fail-closed**: brak/zły podpis = brak instalacji (obejście tylko przez `PAG_INSECURE=1`, wyłącznie build/dev). - `pag self-update` przechodzi tę samą ścieżkę: GPG → SHA256 → kontrola składni → atomowa podmiana klienta. ### System immutable Przy `PAG_IMMUTABLE=1` instalacja nie mutuje `/`, lecz tworzy nowy deployment; rollback to przełączenie symlinku `active`. ```mermaid graph TD R["/"] --> D["/.deployments"] D --> A["active → 20260723T120000"] D --> D1["20260723T120000 (nowy)"] D --> D2["20260722T090000 (poprzedni)"] D1 --> U["usr/ bin/ lib/ – system"] D1 --> S1["var → /var"] D1 --> S2["etc → /etc"] D1 --> S3["home → /home"] D1 --> S4["boot → /boot"] D2 -.->|"deploy-rollback"| A ``` - `/var`, `/etc`, `/home`, `/boot` (i inne z listy `SHARED_PATHS`) są **współdzielone** między deploymentami – nie duplikują się. - `/boot` współdzieli jądro i initramfs, oszczędzając miejsce na każdym deploymentcie. - Rollback z poziomu bootloadera: każdy deployment ma własny wpis GRUB (`pag grub-update`). ### Rollback ```mermaid graph TD T["Transakcja"] --> OK{"Sukces?"} OK -->|tak| H["Historia + migawka + journal plików"] OK -->|nie| RB["Automatyczny rollback transakcji"] H --> R["pag rollback"] R --> R1["Przywróć installed.json z migawki"] R --> R2["Usuń nowe pliki z journalu"] R --> R3["Przywróć nadpisane pliki z backupu"] R --> R4["Posprzątaj puste katalogi"] RB --> R1 RB --> R2 RB --> R3 ``` `pag history` pokazuje ostatnie transakcje (wraz z wykonanymi hookami), a `pag rollback` cofa **ostatnią udaną** transakcję z migawką. --- ### Rolling – baza z obrazu ISO Obraz PaganOS jest zbudowany **ze źródeł** (glibc, gcc, GTK, XFCE, jądro…). `pag` ich nie instalował, więc nie ma ich w swojej bazie (`/var/lib/pag/installed.json`) – a skoro ich nie zna, to `pag upgrade` ich **nie zaktualizuje**. Pliki z obrazu nie są jednak nietykalne: `pag install ` je nadpisze (z kopią zapasową dla `pag rollback`). Żeby system był w pełni rolling, trzeba powiedzieć pagowi, co jest bazą obrazu: ```bash pag base # raport: ile pakietów z obrazu pag zarządza, ile da się # zaadoptować z repo i co zostaje w wersji z obrazu sudo pag base adopt # dograj bazę z repo (--dry-run = podgląd, nic nie instaluje) ``` Po `pag base adopt` pakiety z obrazu stają się zwykłymi pakietami z repo, więc kolejne `sudo pag upgrade` aktualizuje **cały** system. Spis pakietów bazy pochodzi z manifestu wypalanego w obrazie: `/usr/share/pag/base.json` (nazwa + wersja; builder dopisuje wpis przy każdym budowanym pakiecie). Nazwy z buildera są mapowane na nazwy z repo (np. `gtk` → `gtk3`, `libX11` → `xorg-libx11`); te bez odpowiednika w repo raport zostawia w wersji z obrazu i mówi o tym wprost. --- ## Komendy ### PODSTAWY | Komenda | Opis | |---|---| | `pag install ...` | Instaluje pakiety (razem z zależnościami) | | `pag install -f ...` | **Wymusza reinstalację** (nawet tej samej wersji) – odtwarza pliki, puste katalogi i hooki | | `pag remove ...` | Usuwa pakiety | | `pag update` | Aktualizuje **pakiety** do nowszych wersji | | `pag sync` | Odświeża indeksy repozytoriów + pokazuje, ile pakietów czeka na aktualizację | | `pag upgrade` | Aktualizacja **systemu**: pakiety + kernel / initramfs / GRUB | | `pag list` | Lista pakietów dostępnych w repozytorium | | `pag list --installed` | Lista zainstalowanych pakietów | | `pag search ` | Szukaj pakietów w repo (+ Flathub) | | `pag info ` | Szczegóły pakietu (wersja, zależności, rozmiar, podpis) | | `pag files ` | Lista plików należących do pakietu | | `pag verify` | Weryfikacja integralności zainstalowanych plików | | `pag verify --deep` | Pełna weryfikacja SHA256 per-plik | | `pag clean` | Czyści cache pobierania | | `pag stats` | Statystyki systemu (liczba pakietów, rozmiar, cache…) | | `pag download ...` | Pobiera pakiety do cache (tryb offline) | **Smart search:** `pag ` (dowolna nieznana komenda) przeszukuje repo i Flathub oraz podpowiada nazwy – np. `pag firefox` znajdzie pakiet. ### BEZPIECZEŃSTWO / KLUCZE GPG | Komenda | Opis | |---|---| | `pag key-add ` | Importuje klucz GPG repozytorium | | `pag key-list` | Lista zaufanych kluczy | | `pag key-remove ` | Usuwa klucz | | `pag key-trust ` | Przypina fingerprint klucza repo (TOFU wyłączone) | | `pag key-untrust ` | Zapomina fingerprint (powrót do TOFU) | | `pag key-trusted` | Lista przypiętych fingerprintów repo | ### ZAAWANSOWANE | Komenda | Opis | |---|---| | `pag why ` | Dlaczego pakiet jest zainstalowany (kto go zależy) | | `pag autoremove` | Usuwa osierocone zależności | | `pag remove-orphans` | Usuwa osierocone zależności (alias) | | `pag pin [wersja]` | Przypina pakiet do wersji (blokada aktualizacji) | | `pag unpin ` | Zdejmuje przypięcie | | `pag pinned` | Lista przypiętych pakietów | | `pag history` | Historia transakcji | | `pag rollback` | Cofa **ostatnią** transakcję (przywraca pliki z backupu) | | `pag repo-add [nazwa]` | Dodaje repozytorium (drop-in w `/etc/pag/repos/`) | | `pag repo-list` | Lista skonfigurowanych repozytoriów | | `pag sbom export [spdx\|cyclonedx]` | Eksportuje manifest SBOM wszystkich zainstalowanych komponentów | | `pag self-update` | Aktualizuje samego klienta `pag` (podpis GPG + SHA256 + składnia, atomowo) | ### ROLLING (BAZA Z OBRAZU) | Komenda | Opis | |---|---| | `pag base` | Raport: pakiety z obrazu ISO – zarządzane przez pag / do adoptowania z repo / bez odpowiednika | | `pag base adopt` | Dogrywa pakiety bazy z repo (zastępuje pliki z obrazu, kopie dla `pag rollback`); `--dry-run` = podgląd | | `pag base adopt ...` | Adoptuje tylko wskazane pakiety bazy | ### FLATPAK | Komenda | Opis | |---|---| | `pag flatpak []` | Szukaj i instaluj z Flathub | | `pag flatpak search ` | Szukaj na Flathub | | `pag flatpak install ` | Instaluje flatpak | | `pag flatpak remove ` | Usuwa flatpak | | `pag flatpak list` | Lista zainstalowanych flatpaków | | `pag flatpak update` | Aktualizuje wszystkie flatpaki | | `pag flatpak info ` | Szczegóły flatpaka | > Instalacja jako root wymusza zakres **systemowy** (`--system`), dzięki czemu > aplikacja jest widoczna dla wszystkich użytkowników, a nie tylko dla roota. ### SYSTEM IMMUTABLE (`PAG_IMMUTABLE=1`) | Komenda | Opis | |---|---| | `pag deploy-list` | Lista wdrożeń (deployments) | | `pag deploy-rollback` | Przełącza na poprzednie wdrożenie | | `pag deploy-cleanup [N]` | Usuwa stare wdrożenia (zachowuje N, domyślnie 3) | | `pag initramfs-update` | Przebudowuje initramfs | | `pag grub-update` | Regeneruje wpisy GRUB dla wszystkich wdrożeń | --- ## Zmienne środowiskowe | Zmienna | Znaczenie | |---|---| | `PAG_ROOT` | Alternatywny root operacji (testy/chroot); domyślnie `/` | | `PAG_IMMUTABLE=1` | Tryb immutable – instalacja tworzy nowy deployment | | `PAG_YES=1` | Automatyczne potwierdzenie (to samo co `-y` / `--yes`) | | `PAG_INSECURE=1` | Wyłącza wymóg HTTPS i fail-closed GPG (**tylko build/dev!**) | | `PAG_NO_HOOKS=1` | Pomija hooki i triggery | | `PAG_HOOK_TIMEOUT` | Timeout hooka w sekundach (domyślnie `60`) | | `PAG_LANG_DIR` | Katalog z plikami tłumaczeń (`pl.json`, `en.json`) | | `PAG_LANG_NO_FILES=1` | Ignoruje pliki tłumaczeń (eksport wbudowanych) | | `PAG_ROOT_DEVICE` / `PAG_GRUB_ROOT` | Jawny `root=` dla GRUB (build ISO/IMG) | | `PAG_IN_CHROOT=1` | Wymusza tryb chroot przy wykrywaniu urządzenia root | --- ## Ścieżki i pliki | Ścieżka | Przeznaczenie | |---|---| | `/var/lib/pag/` | Baza stanu: `installed.json`, `files.db`, `world`, `pinned.json`, `history.json`, `pag.lock`, `hooks/` | | `/var/lib/pag/files.db` | SQLite: właściciele plików + sumy SHA256 | | `/var/cache/pag/` | Cache pobranych pakietów | | `/var/cache/pag/repos/` | Cache indeksów repozytoriów (JSON + ETag + znacznik czasu) | | `/etc/pag/repos.conf` i `/etc/pag/repos/*.conf` | Repozytoria (drop-in) | | `/etc/pag/trusted.json` | Przypięte fingerprinty kluczy repo | | `/etc/pag/gpg/` | Izolowany keyring GPG | | `/etc/pag/triggers/*.json` | Własne triggery | | `/etc/pag/lang/`, `/usr/share/pag/lang/` | Tłumaczenia (pliki nadpisują wbudowane) | | `/var/log/pag/audit.log` | Audyt: hooki, self-update | | `/.pag_staging` | Staging (ta sama partycja co `/` – brak `EXDEV`) | | `/.deployments/` | Wdrożenia (tryb immutable) | --- ## Format pakietu Pakiet `.pag` to archiwum zawierające: ``` metadata.json – nazwa, wersja, release, zależności, provides/requires (so-name) data.tar.xz – pliki systemu + sums.json (SHA256 per plik) hooks/ – opcjonalne: pre-install, post-install, pre-remove, post-remove ``` Instalacja jest **weryfikowana per-plik** względem `sums.json`, a rozpakowanie chroni przed *directory traversal* i ucieczką przez złośliwe symlinki. --- ## Hooki i triggery **Hooki** uruchamiane są jako `root` (jak w apt/pacman), w ograniczonym środowisku: - `pre-install`, `post-install`, `pre-remove`, `post-remove` - czyste env: `PATH`, `HOME=/root`, `LANG/LC_ALL=C.UTF-8`, `PKG_NAME`, `PKG_VERSION`, `PKG_ACTION`, `PKG_HOOK_API=1` - timeout (`PAG_HOOK_TIMEOUT`), możliwość wyłączenia (`PAG_NO_HOOKS=1`), wpisy w `/var/log/pag/audit.log` i w historii transakcji Instalujesz kod, któremu ufasz – hooki mają pełne uprawnienia. **Triggery** uruchamiane są **raz na transakcję**, gdy dotknięto pasujących ścieżek (tylko jeśli dana binarka istnieje): | Trigger | Ścieżki | Komenda | |---|---|---| | `font-cache` | `/usr/share/fonts/`, `/usr/local/share/fonts/` | `fc-cache -fs` | | `glib-schemas` | `/usr/share/glib-2.0/schemas/` | `glib-compile-schemas …` | | `desktop-database` | `/usr/share/applications/` | `update-desktop-database -q …` | | `mime-database` | `/usr/share/mime/` | `update-mime-database …` | Własne triggery dodasz jako `/etc/pag/triggers/*.json`. --- ## Konfiguracja `/etc` – `.pacnew` / `.pacsave` Katalog `/etc` jest współdzielony między wdrożeniami (nie cofa się przy `deploy-rollback`). Aby nie tracić zmian użytkownika: - **Aktualizacja** pliku konfiguracyjnego, który użytkownik zmodyfikował: nowa wersja trafia jako `.pacnew`, a plik użytkownika **zostaje**. - **Usunięcie** pakietu ze zmodyfikowanym plikiem konfiguracyjnym: plik trafia jako `.pacsave` zamiast zostać skasowany. Porównanie odbywa się względem sumy SHA256 z chwili instalacji. --- ## Przykłady ```bash # Instalacja i aktualizacje sudo pag install firefox gimp sudo pag update # same pakiety sudo pag upgrade # pakiety + kernel/initramfs/GRUB sudo pag sync # odśwież indeksy + info o aktualizacjach # Naprawa pakietu (brakujące pliki/katalogi, np. /etc/pulse/default.pa.d) sudo pag install -f pulseaudio # Ikony aplikacji po instalacji motywu (cache budowany automatycznie) sudo pag install papirus-icon-theme # Bezpieczeństwo sudo pag key-add https://repo.paganlinux.eu/stable/paganos.asc sudo pag key-trust https://repo.paganlinux.eu/stable/ sudo pag verify --deep # Zależności i pochodzenie pakietów sudo pag why libjpeg-turbo sudo pag autoremove # SBOM dla audytu / compliance sudo pag sbom export cyclonedx > sbom.json # Cofnij ostatnią transakcję sudo pag rollback ``` --- ## Diagnostyka | Objaw | Rozwiązanie | |---|---| | „Inna instancja pag jest uruchomiona” | Działa inny proces `pag` (blokada `flock`). Poczekaj lub sprawdź `pgrep -af pag`. | | „Nie można odświeżyć indeksu” | Cache repo jest tylko-do-odczytu dla zwykłego usera – uruchom jako root: `sudo pag sync`. | | „Nieprawidłowy podpis / brak podpisu” | Zaimportuj klucz: `sudo pag key-add `, potem zweryfikuj `sudo pag key-trusted`. | | Brakujące pliki/katalogi po instalacji | `sudo pag install -f ` (odtwarza pliki, puste katalogi i hooki). | | System nie bootuje po `grub-update` | Ustaw jawnie urządzenie root: `PAG_ROOT_DEVICE=/dev/sda2 sudo pag grub-update`. | | Aplikacja z Flathuba niewidoczna w menu | Dodaj `/var/lib/flatpak/exports/share` do `XDG_DATA_DIRS` i zaloguj się ponownie. | --- ## Instalacja i aktualizacja ```bash # Na działającym PaganOS pag jest w repo bazowym: sudo pag install pag # instalacja z repozytorium sudo pag self-update # aktualizacja samego klienta (podpisana) # pag jest też zarządzany przez menedżera pakietów – po publikacji nowej # wersji w repo: sudo pag update sudo pag upgrade ``` --- ## Licencja PaganOS / pag – projekt open source. Szczegóły w repozytorium dystrybucji.