Commit b4263ae
2
plików
+409
dodanych
-410
usuniętych
@@ -0,0 +1,409 @@
1
+# pag – PaganOS Package Manager
2
+
3
+[](https://git.paganlinux.eu/pag)
4
+[](https://paganlinux.eu)
5
+
6
+Package manager for [PaganOS](https://paganlinux.eu). Atomic installation
7
+(staging → rename), GPG signature verification with fingerprint pinning,
8
+per-file SHA256, full transaction rollback, hooks and triggers, and support for
9
+immutable systems with deployments.
10
+
11
+Diagrams in this README are rendered with Mermaid – supported by the
12
+`git.paganlinux.eu` portal (and GitHub/Gitea).
13
+
14
+```bash
15
+pag --version # client version (e.g. pag 3.3.20)
16
+pag # full help (command list)
17
+pag --help # same as above
18
+```
19
+
20
+---
21
+
22
+## Table of contents
23
+
24
+- [Quick start](#quick-start)
25
+- [How it works](#how-it-works)
26
+ - [`pag install` flow](#pag-install-flow)
27
+ - [Trust chain](#trust-chain)
28
+ - [Immutable system](#immutable-system)
29
+ - [Rollback](#rollback)
30
+- [Commands](#commands)
31
+- [Environment variables](#environment-variables)
32
+- [Paths and files](#paths-and-files)
33
+- [Package format](#package-format)
34
+- [Hooks and triggers](#hooks-and-triggers)
35
+- [`/etc` configuration – `.pacnew` / `.pacsave`](#etc-configuration--pacnew--pacsave)
36
+- [Examples](#examples)
37
+- [Troubleshooting](#troubleshooting)
38
+- [Install and update](#install-and-update)
39
+- [License](#license)
40
+
41
+---
42
+
43
+## Quick start
44
+
45
+```bash
46
+# Refresh repository indexes (and see what is pending an update)
47
+sudo pag sync
48
+
49
+# Install / remove
50
+sudo pag install firefox gimp
51
+sudo pag remove gimp
52
+
53
+# Update packages only…
54
+sudo pag update
55
+# …or the whole system: packages + kernel / initramfs / GRUB
56
+sudo pag upgrade
57
+
58
+# Verify the integrity of all files
59
+sudo pag verify --deep
60
+```
61
+
62
+---
63
+
64
+## How it works
65
+
66
+### `pag install` flow
67
+
68
+```mermaid
69
+graph TD
70
+ A["pag install pkg"] --> B["Dependency resolution (DFS + provides)"]
71
+ B --> C{"Missing dependencies?"}
72
+ C -->|yes| C1["Error – abort"]
73
+ C -->|no| D["ABI verification (so-name)"]
74
+ D --> E["Pre-flight: free space + RW mount"]
75
+ E --> F["flock + database snapshot"]
76
+ F --> G["Parallel package download"]
77
+ G --> H["GPG + package SHA256 verification"]
78
+ H --> I["Staging: extract + per-file sums"]
79
+ I --> J["Atomic rename of files into the system"]
80
+ J --> K["pre/post-install hooks"]
81
+ K --> L["Write to SQLite + transaction history"]
82
+ L --> M{"PAG_IMMUTABLE=1?"}
83
+ M -->|yes| N["New deployment + GRUB entries"]
84
+ M -->|no| O["ldconfig + triggers"]
85
+ H -->|error| R["Rollback of the whole transaction"]
86
+ I -->|error| R
87
+ J -->|error| R
88
+ R --> S["Restore database and files"]
89
+```
90
+
91
+Key properties:
92
+
93
+- **Atomicity** – files first go to staging on the same partition as `/`, then
94
+ are moved with `rename()` (no half-install).
95
+- **Transactionality** – if any package fails, the whole transaction is rolled
96
+ back (`installed.json`, files, backups).
97
+- **File sharing** – a file owned by two packages is not removed when one of
98
+ them is removed (only the database entry is removed).
99
+
100
+### Trust chain
101
+
102
+```mermaid
103
+graph TD
104
+ A["repo.json + repo.json.asc"] --> B["GPG: VALIDSIG line"]
105
+ B --> C["Repo fingerprint pinning (TOFU → pin)"]
106
+ C --> D["Package index"]
107
+ D --> E["package .pag + .asc"]
108
+ E --> F["GPG: signature matches repo pin"]
109
+ F --> G["Whole-package SHA256"]
110
+ G --> H["Safe extraction (anti-traversal)"]
111
+ H --> I["sums.json: per-file SHA256"]
112
+ I --> J["Strip SUID bit"]
113
+ J --> K["Install"]
114
+ F -->|"missing / bad signature"| X["Reject package"]
115
+ G -->|"SHA256 mismatch"| X
116
+ H -->|"traversal / symlink escape"| X
117
+```
118
+
119
+- First use of a key = **TOFU**, afterwards the fingerprint is **pinned**
120
+ (`pag key-trust` / `pag key-untrust`).
121
+- Verification is **fail-closed**: missing/bad signature = no installation
122
+ (override only with `PAG_INSECURE=1`, build/dev only).
123
+- `pag self-update` goes through the same path: GPG → SHA256 → syntax check →
124
+ atomic client replacement.
125
+
126
+### Immutable system
127
+
128
+With `PAG_IMMUTABLE=1`, installation does not mutate `/`; it creates a new
129
+deployment. Rollback is just switching the `active` symlink.
130
+
131
+```mermaid
132
+graph TD
133
+ R["/"] --> D["/.deployments"]
134
+ D --> A["active → 20260723T120000"]
135
+ D --> D1["20260723T120000 (new)"]
136
+ D --> D2["20260722T090000 (previous)"]
137
+ D1 --> U["usr/ bin/ lib/ – system"]
138
+ D1 --> S1["var → /var"]
139
+ D1 --> S2["etc → /etc"]
140
+ D1 --> S3["home → /home"]
141
+ D1 --> S4["boot → /boot"]
142
+ D2 -.->|"deploy-rollback"| A
143
+```
144
+
145
+- `/var`, `/etc`, `/home`, `/boot` (and other `SHARED_PATHS`) are **shared**
146
+ between deployments – they are not duplicated.
147
+- `/boot` shares the kernel and initramfs, saving space per deployment.
148
+- Rollback from the bootloader: each deployment has its own GRUB entry
149
+ (`pag grub-update`).
150
+
151
+### Rollback
152
+
153
+```mermaid
154
+graph TD
155
+ T["Transaction"] --> OK{"Success?"}
156
+ OK -->|yes| H["History + snapshot + file journal"]
157
+ OK -->|no| RB["Automatic transaction rollback"]
158
+ H --> R["pag rollback"]
159
+ R --> R1["Restore installed.json from snapshot"]
160
+ R --> R2["Remove new files from the journal"]
161
+ R --> R3["Restore overwritten files from backup"]
162
+ R --> R4["Clean up empty directories"]
163
+ RB --> R1
164
+ RB --> R2
165
+ RB --> R3
166
+```
167
+
168
+`pag history` shows recent transactions (including executed hooks), and
169
+`pag rollback` reverts the **last successful** transaction with a snapshot.
170
+
171
+---
172
+
173
+## Commands
174
+
175
+### BASICS
176
+
177
+| Command | Description |
178
+|---|---|
179
+| `pag install <pkg>...` | Install packages (together with dependencies) |
180
+| `pag install -f <pkg>...` | **Force reinstall** (even the same version) – restores files, empty directories and hooks |
181
+| `pag remove <pkg>...` | Remove packages |
182
+| `pag update` | Update **packages** to newer versions |
183
+| `pag sync` | Refresh repository indexes + show how many packages await update |
184
+| `pag upgrade` | **System** update: packages + kernel / initramfs / GRUB |
185
+| `pag list` | List packages available in the repository |
186
+| `pag list --installed` | List installed packages |
187
+| `pag search <query>` | Search packages in the repo (+ Flathub) |
188
+| `pag info <pkg>` | Package details (version, dependencies, size, signature) |
189
+| `pag files <pkg>` | List files owned by a package |
190
+| `pag verify` | Verify the integrity of installed files |
191
+| `pag verify --deep` | Full per-file SHA256 verification |
192
+| `pag clean` | Clear the download cache |
193
+| `pag stats` | System statistics (package count, size, cache…) |
194
+| `pag download <pkg>...` | Download packages to cache (offline mode) |
195
+
196
+**Smart search:** `pag <name>` (any unknown command) searches the repo and
197
+Flathub and suggests names – e.g. `pag firefox` will find the package.
198
+
199
+### SECURITY / GPG KEYS
200
+
201
+| Command | Description |
202
+|---|---|
203
+| `pag key-add <url\|file>` | Import a repository GPG key |
204
+| `pag key-list` | List trusted keys |
205
+| `pag key-remove <id>` | Remove a key |
206
+| `pag key-trust <repo>` | Pin the repo key fingerprint (TOFU disabled) |
207
+| `pag key-untrust <repo>` | Forget the fingerprint (back to TOFU) |
208
+| `pag key-trusted` | List pinned repo fingerprints |
209
+
210
+### ADVANCED
211
+
212
+| Command | Description |
213
+|---|---|
214
+| `pag why <pkg>` | Why a package is installed (who depends on it) |
215
+| `pag autoremove` | Remove orphaned dependencies |
216
+| `pag remove-orphans` | Remove orphaned dependencies (alias) |
217
+| `pag pin <pkg> [version]` | Pin a package to a version (block updates) |
218
+| `pag unpin <pkg>` | Unpin |
219
+| `pag pinned` | List pinned packages |
220
+| `pag history` | Transaction history |
221
+| `pag rollback` | Revert the **last** transaction (restore files from backup) |
222
+| `pag repo-add <url> [name]` | Add a repository (drop-in in `/etc/pag/repos/`) |
223
+| `pag repo-list` | List configured repositories |
224
+| `pag sbom export [spdx\|cyclonedx]` | Export an SBOM manifest of all installed components |
225
+| `pag self-update` | Update the `pag` client itself (GPG signature + SHA256 + syntax, atomically) |
226
+
227
+### FLATPAK
228
+
229
+| Command | Description |
230
+|---|---|
231
+| `pag flatpak [<query>]` | Search and install from Flathub |
232
+| `pag flatpak search <query>` | Search Flathub |
233
+| `pag flatpak install <id>` | Install a flatpak |
234
+| `pag flatpak remove <id>` | Remove a flatpak |
235
+| `pag flatpak list` | List installed flatpaks |
236
+| `pag flatpak update` | Update all flatpaks |
237
+| `pag flatpak info <id>` | Flatpak details |
238
+
239
+> Installation as root forces the **system** scope (`--system`), so the
240
+> application is visible to all users, not just root.
241
+
242
+### IMMUTABLE SYSTEM (`PAG_IMMUTABLE=1`)
243
+
244
+| Command | Description |
245
+|---|---|
246
+| `pag deploy-list` | List deployments |
247
+| `pag deploy-rollback` | Switch to the previous deployment |
248
+| `pag deploy-cleanup [N]` | Remove old deployments (keep N, default 3) |
249
+| `pag initramfs-update` | Rebuild initramfs |
250
+| `pag grub-update` | Regenerate GRUB entries for all deployments |
251
+
252
+---
253
+
254
+## Environment variables
255
+
256
+| Variable | Meaning |
257
+|---|---|
258
+| `PAG_ROOT` | Alternative operation root (tests/chroot); default `/` |
259
+| `PAG_IMMUTABLE=1` | Immutable mode – installation creates a new deployment |
260
+| `PAG_YES=1` | Automatic confirmation (same as `-y` / `--yes`) |
261
+| `PAG_INSECURE=1` | Disables the HTTPS requirement and fail-closed GPG (**build/dev only!**) |
262
+| `PAG_NO_HOOKS=1` | Skip hooks and triggers |
263
+| `PAG_HOOK_TIMEOUT` | Hook timeout in seconds (default `60`) |
264
+| `PAG_LANG_DIR` | Directory with translation files (`pl.json`, `en.json`) |
265
+| `PAG_LANG_NO_FILES=1` | Ignore translation files (export built-ins) |
266
+| `PAG_ROOT_DEVICE` / `PAG_GRUB_ROOT` | Explicit `root=` for GRUB (ISO/IMG build) |
267
+| `PAG_IN_CHROOT=1` | Force chroot mode when detecting the root device |
268
+
269
+---
270
+
271
+## Paths and files
272
+
273
+| Path | Purpose |
274
+|---|---|
275
+| `/var/lib/pag/` | State database: `installed.json`, `files.db`, `world`, `pinned.json`, `history.json`, `pag.lock`, `hooks/` |
276
+| `/var/lib/pag/files.db` | SQLite: file owners + SHA256 sums |
277
+| `/var/cache/pag/` | Downloaded package cache |
278
+| `/var/cache/pag/repos/` | Repository index cache (JSON + ETag + timestamp) |
279
+| `/etc/pag/repos.conf` and `/etc/pag/repos/*.conf` | Repositories (drop-in) |
280
+| `/etc/pag/trusted.json` | Pinned repo key fingerprints |
281
+| `/etc/pag/gpg/` | Isolated GPG keyring |
282
+| `/etc/pag/triggers/*.json` | Custom triggers |
283
+| `/etc/pag/lang/`, `/usr/share/pag/lang/` | Translations (files override built-ins) |
284
+| `/var/log/pag/audit.log` | Audit: hooks, self-update |
285
+| `/.pag_staging` | Staging (same partition as `/` – no `EXDEV`) |
286
+| `/.deployments/` | Deployments (immutable mode) |
287
+
288
+---
289
+
290
+## Package format
291
+
292
+A `.pag` package is an archive containing:
293
+
294
+```
295
+metadata.json – name, version, release, dependencies, provides/requires (so-name)
296
+data.tar.xz – system files + sums.json (per-file SHA256)
297
+hooks/ – optional: pre-install, post-install, pre-remove, post-remove
298
+```
299
+
300
+Installation is **verified per file** against `sums.json`, and extraction is
301
+protected against *directory traversal* and escape via malicious symlinks.
302
+
303
+---
304
+
305
+## Hooks and triggers
306
+
307
+**Hooks** run as `root` (like apt/pacman), in a restricted environment:
308
+
309
+- `pre-install`, `post-install`, `pre-remove`, `post-remove`
310
+- clean env: `PATH`, `HOME=/root`, `LANG/LC_ALL=C.UTF-8`, `PKG_NAME`,
311
+ `PKG_VERSION`, `PKG_ACTION`, `PKG_HOOK_API=1`
312
+- timeout (`PAG_HOOK_TIMEOUT`), optional disable (`PAG_NO_HOOKS=1`), entries in
313
+ `/var/log/pag/audit.log` and in the transaction history
314
+
315
+You install code you trust – hooks have full privileges.
316
+
317
+**Triggers** run **once per transaction**, when matching paths were touched
318
+(only if the given binary exists):
319
+
320
+| Trigger | Paths | Command |
321
+|---|---|---|
322
+| `font-cache` | `/usr/share/fonts/`, `/usr/local/share/fonts/` | `fc-cache -fs` |
323
+| `glib-schemas` | `/usr/share/glib-2.0/schemas/` | `glib-compile-schemas …` |
324
+| `desktop-database` | `/usr/share/applications/` | `update-desktop-database -q …` |
325
+| `mime-database` | `/usr/share/mime/` | `update-mime-database …` |
326
+
327
+You can add your own triggers as `/etc/pag/triggers/*.json`.
328
+
329
+---
330
+
331
+## `/etc` configuration – `.pacnew` / `.pacsave`
332
+
333
+The `/etc` directory is shared between deployments (it is not reverted by
334
+`deploy-rollback`). To avoid losing user changes:
335
+
336
+- **Updating** a configuration file that the user modified: the new version is
337
+ written as `<file>.pacnew`, and the user's file **is kept**.
338
+- **Removing** a package with a modified configuration file: the file becomes
339
+ `<file>.pacsave` instead of being deleted.
340
+
341
+The comparison uses the SHA256 sum recorded at install time.
342
+
343
+---
344
+
345
+## Examples
346
+
347
+```bash
348
+# Install and updates
349
+sudo pag install firefox gimp
350
+sudo pag update # packages only
351
+sudo pag upgrade # packages + kernel/initramfs/GRUB
352
+sudo pag sync # refresh indexes + update info
353
+
354
+# Repair a package (missing files/directories, e.g. /etc/pulse/default.pa.d)
355
+sudo pag install -f pulseaudio
356
+
357
+# Application icons after installing an icon theme (cache built automatically)
358
+sudo pag install papirus-icon-theme
359
+
360
+# Security
361
+sudo pag key-add https://repo.paganlinux.eu/stable/paganos.asc
362
+sudo pag key-trust https://repo.paganlinux.eu/stable/
363
+sudo pag verify --deep
364
+
365
+# Dependencies and package provenance
366
+sudo pag why libjpeg-turbo
367
+sudo pag autoremove
368
+
369
+# SBOM for audit / compliance
370
+sudo pag sbom export cyclonedx > sbom.json
371
+
372
+# Revert the last transaction
373
+sudo pag rollback
374
+```
375
+
376
+---
377
+
378
+## Troubleshooting
379
+
380
+| Symptom | Solution |
381
+|---|---|
382
+| "Another pag instance is running" | Another `pag` process is active (`flock` lock). Wait or check `pgrep -af pag`. |
383
+| "Cannot refresh the index" | The repo cache is read-only for a regular user – run as root: `sudo pag sync`. |
384
+| "Invalid signature / missing signature" | Import the key: `sudo pag key-add <url>`, then verify `sudo pag key-trusted`. |
385
+| Missing files/directories after install | `sudo pag install -f <pkg>` (restores files, empty directories and hooks). |
386
+| System does not boot after `grub-update` | Set the root device explicitly: `PAG_ROOT_DEVICE=/dev/sda2 sudo pag grub-update`. |
387
+| Flatpak app not visible in the menu | Add `/var/lib/flatpak/exports/share` to `XDG_DATA_DIRS` and log in again. |
388
+
389
+---
390
+
391
+## Install and update
392
+
393
+```bash
394
+# On a running PaganOS, pag is in the base repository:
395
+sudo pag install pag # install from the repository
396
+sudo pag self-update # update the client itself (signed)
397
+
398
+# pag is also managed by the package manager – after a new version is
399
+# published in the repo:
400
+sudo pag update
401
+sudo pag upgrade
402
+```
403
+
404
+---
405
+
406
+## License
407
+
408
+PaganOS / pag – an open source project. See the distribution repository for
409
+details.
0
410
deleted file mode 100644
@@ -1,410 +0,0 @@
1
-# pag – PaganOS Package Manager
2
-
3
-[](https://git.paganlinux.eu/pag)
4
-[](https://paganlinux.eu)
5
-
6
-Menedżer pakietów dla [PaganOS](https://paganlinux.eu). Instalacja atomowa
7
-(staging → rename), weryfikacja podpisów GPG z pinningiem fingerprintu, SHA256
8
-per-plik, pełny rollback transakcji, hooki i triggery oraz wsparcie systemów
9
-immutable z wdrożeniami (deployments).
10
-
11
-Diagramy w tym README renderuje Mermaid – obsługiwany przez portal
12
-`git.paganlinux.eu` (oraz GitHub/Gitea).
13
-
14
-```bash
15
-pag --version # wersja klienta (np. pag 3.3.20)
16
-pag # pełna pomoc (lista komend)
17
-pag --help # to samo co wyżej
18
-```
19
-
20
-
21
-## Spis treści
22
-
23
-- [Szybki start](#szybki-start)
24
-- [Jak to działa](#jak-to-działa)
25
- - [Przepływ `pag install`](#przepływ-pag-install)
26
- - [Łańcuch zaufania](#łańcuch-zaufania)
27
- - [System immutable](#system-immutable)
28
- - [Rollback](#rollback)
29
-- [Komendy](#komendy)
30
-- [Zmienne środowiskowe](#zmienne-środowiskowe)
31
-- [Ścieżki i pliki](#ścieżki-i-pliki)
32
-- [Format pakietu](#format-pakietu)
33
-- [Hooki i triggery](#hooki-i-triggery)
34
-- [Konfiguracja `/etc` – `.pacnew` / `.pacsave`](#konfiguracja-etc--pacnew--pacsave)
35
-- [Przykłady](#przykłady)
36
-- [Diagnostyka](#diagnostyka)
37
-- [Instalacja i aktualizacja](#instalacja-i-aktualizacja)
38
-- [Licencja](#licencja)
39
-
40
-
41
-## Szybki start
42
-
43
-```bash
44
-# Odśwież indeksy repozytoriów (i zobacz, co czeka na aktualizację)
45
-sudo pag sync
46
-
47
-# Instaluj / usuwaj
48
-sudo pag install firefox gimp
49
-sudo pag remove gimp
50
-
51
-# Aktualizuj same pakiety…
52
-sudo pag update
53
-# …albo cały system: pakiety + kernel / initramfs / GRUB
54
-sudo pag upgrade
55
-
56
-# Sprawdź integralność wszystkich plików
57
-sudo pag verify --deep
58
-```
59
-
60
-
61
-## Jak to działa
62
-
63
-### Przepływ `pag install`
64
-
65
-```mermaid
66
-graph TD
67
- A["pag install pkg"] --> B["Rozwiązanie zależności (DFS + provides)"]
68
- B --> C{"Brakujące zależności?"}
69
- C -->|tak| C1["Błąd – przerwij"]
70
- C -->|nie| D["Weryfikacja ABI (so-name)"]
71
- D --> E["Pre-flight: wolne miejsce + montowanie RW"]
72
- E --> F["Blokada flock + migawka bazy"]
73
- F --> G["Równoległe pobieranie paczek"]
74
- G --> H["Weryfikacja GPG + SHA256 paczki"]
75
- H --> I["Staging: rozpakowanie + sumy per-plik"]
76
- I --> J["Atomowy rename plików do systemu"]
77
- J --> K["Hooki pre/post-install"]
78
- K --> L["Zapis do SQLite + historia transakcji"]
79
- L --> M{"PAG_IMMUTABLE=1?"}
80
- M -->|tak| N["Nowy deployment + wpisy GRUB"]
81
- M -->|nie| O["ldconfig + triggery"]
82
- H -->|błąd| R["Rollback całej transakcji"]
83
- I -->|błąd| R
84
- J -->|błąd| R
85
- R --> S["Przywrócenie bazy i plików"]
86
-```
87
-
88
-Kluczowe własności:
89
-
90
-- **Atomowość** – pliki trafiają najpierw do staging na tej samej partycji co
91
- `/`, potem są przenoszone `rename()` (bez pół-instalacji).
92
-- **Transakcyjność** – jeśli którykolwiek pakiet zawiedzie, cała transakcja jest
93
- cofana (`installed.json`, pliki, backupy).
94
-- **Współdzielenie plików** – plik należący do dwóch pakietów nie jest usuwany
95
- przy usunięciu jednego z nich (usuwany jest tylko wpis w bazie).
96
-
97
-### Łańcuch zaufania
98
-
99
-```mermaid
100
-graph TD
101
- A["repo.json + repo.json.asc"] --> B["GPG: linia VALIDSIG"]
102
- B --> C["Pinning fingerprintu repo (TOFU → pin)"]
103
- C --> D["Indeks pakietów"]
104
- D --> E["pakiet .pag + .asc"]
105
- E --> F["GPG: podpis zgodny z pinem repo"]
106
- F --> G["SHA256 całej paczki"]
107
- G --> H["Bezpieczne rozpakowanie (anty-traversal)"]
108
- H --> I["sums.json: SHA256 per plik"]
109
- I --> J["Zdjęcie bitu SUID"]
110
- J --> K["Instalacja"]
111
- F -->|"brak / zły podpis"| X["Odrzuć paczkę"]
112
- G -->|"niezgodny SHA256"| X
113
- H -->|"traversal / escape przez symlink"| X
114
-```
115
-
116
-- Pierwsze użycie klucza = **TOFU**, potem fingerprint jest **przypinany**
117
- (`pag key-trust` / `pag key-untrust`).
118
-- Weryfikacja jest **fail-closed**: brak/zły podpis = brak instalacji
119
- (obejście tylko przez `PAG_INSECURE=1`, wyłącznie build/dev).
120
-- `pag self-update` przechodzi tę samą ścieżkę: GPG → SHA256 → kontrola
121
- składni → atomowa podmiana klienta.
122
-
123
-### System immutable
124
-
125
-Przy `PAG_IMMUTABLE=1` instalacja nie mutuje `/`, lecz tworzy nowy deployment;
126
-rollback to przełączenie symlinku `active`.
127
-
128
-```mermaid
129
-graph TD
130
- R["/"] --> D["/.deployments"]
131
- D --> A["active → 20260723T120000"]
132
- D --> D1["20260723T120000 (nowy)"]
133
- D --> D2["20260722T090000 (poprzedni)"]
134
- D1 --> U["usr/ bin/ lib/ – system"]
135
- D1 --> S1["var → /var"]
136
- D1 --> S2["etc → /etc"]
137
- D1 --> S3["home → /home"]
138
- D1 --> S4["boot → /boot"]
139
- D2 -.->|"deploy-rollback"| A
140
-```
141
-
142
-- `/var`, `/etc`, `/home`, `/boot` (i inne z listy `SHARED_PATHS`) są
143
- **współdzielone** między deploymentami – nie duplikują się.
144
-- `/boot` współdzieli jądro i initramfs, oszczędzając miejsce na każdym
145
- deploymentcie.
146
-- Rollback z poziomu bootloadera: każdy deployment ma własny wpis GRUB
147
- (`pag grub-update`).
148
-
149
-### Rollback
150
-
151
-```mermaid
152
-graph TD
153
- T["Transakcja"] --> OK{"Sukces?"}
154
- OK -->|tak| H["Historia + migawka + journal plików"]
155
- OK -->|nie| RB["Automatyczny rollback transakcji"]
156
- H --> R["pag rollback"]
157
- R --> R1["Przywróć installed.json z migawki"]
158
- R --> R2["Usuń nowe pliki z journalu"]
159
- R --> R3["Przywróć nadpisane pliki z backupu"]
160
- R --> R4["Posprzątaj puste katalogi"]
161
- RB --> R1
162
- RB --> R2
163
- RB --> R3
164
-```
165
-
166
-`pag history` pokazuje ostatnie transakcje (wraz z wykonanymi hookami), a
167
-`pag rollback` cofa **ostatnią udaną** transakcję z migawką.
168
-
169
-
170
-## Komendy
171
-
172
-### PODSTAWY
173
-
174
-| Komenda | Opis |
175
-|---|---|
176
-| `pag install <pkg>...` | Instaluje pakiety (razem z zależnościami) |
177
-| `pag install -f <pkg>...` | **Wymusza reinstalację** (nawet tej samej wersji) – odtwarza pliki, puste katalogi i hooki |
178
-| `pag remove <pkg>...` | Usuwa pakiety |
179
-| `pag update` | Aktualizuje **pakiety** do nowszych wersji |
180
-| `pag sync` | Odświeża indeksy repozytoriów + pokazuje, ile pakietów czeka na aktualizację |
181
-| `pag upgrade` | Aktualizacja **systemu**: pakiety + kernel / initramfs / GRUB |
182
-| `pag list` | Lista pakietów dostępnych w repozytorium |
183
-| `pag list --installed` | Lista zainstalowanych pakietów |
184
-| `pag search <query>` | Szukaj pakietów w repo (+ Flathub) |
185
-| `pag info <pkg>` | Szczegóły pakietu (wersja, zależności, rozmiar, podpis) |
186
-| `pag files <pkg>` | Lista plików należących do pakietu |
187
-| `pag verify` | Weryfikacja integralności zainstalowanych plików |
188
-| `pag verify --deep` | Pełna weryfikacja SHA256 per-plik |
189
-| `pag clean` | Czyści cache pobierania |
190
-| `pag stats` | Statystyki systemu (liczba pakietów, rozmiar, cache…) |
191
-| `pag download <pkg>...` | Pobiera pakiety do cache (tryb offline) |
192
-
193
-**Smart search:** `pag <nazwa>` (dowolna nieznana komenda) przeszukuje repo
194
-i Flathub oraz podpowiada nazwy – np. `pag firefox` znajdzie pakiet.
195
-
196
-### BEZPIECZEŃSTWO / KLUCZE GPG
197
-
198
-| Komenda | Opis |
199
-|---|---|
200
-| `pag key-add <url\|plik>` | Importuje klucz GPG repozytorium |
201
-| `pag key-list` | Lista zaufanych kluczy |
202
-| `pag key-remove <id>` | Usuwa klucz |
203
-| `pag key-trust <repo>` | Przypina fingerprint klucza repo (TOFU wyłączone) |
204
-| `pag key-untrust <repo>` | Zapomina fingerprint (powrót do TOFU) |
205
-| `pag key-trusted` | Lista przypiętych fingerprintów repo |
206
-
207
-### ZAAWANSOWANE
208
-
209
-| Komenda | Opis |
210
-|---|---|
211
-| `pag why <pkg>` | Dlaczego pakiet jest zainstalowany (kto go zależy) |
212
-| `pag autoremove` | Usuwa osierocone zależności |
213
-| `pag remove-orphans` | Usuwa osierocone zależności (alias) |
214
-| `pag pin <pkg> [wersja]` | Przypina pakiet do wersji (blokada aktualizacji) |
215
-| `pag unpin <pkg>` | Zdejmuje przypięcie |
216
-| `pag pinned` | Lista przypiętych pakietów |
217
-| `pag history` | Historia transakcji |
218
-| `pag rollback` | Cofa **ostatnią** transakcję (przywraca pliki z backupu) |
219
-| `pag repo-add <url> [nazwa]` | Dodaje repozytorium (drop-in w `/etc/pag/repos/`) |
220
-| `pag repo-list` | Lista skonfigurowanych repozytoriów |
221
-| `pag sbom export [spdx\|cyclonedx]` | Eksportuje manifest SBOM wszystkich zainstalowanych komponentów |
222
-| `pag self-update` | Aktualizuje samego klienta `pag` (podpis GPG + SHA256 + składnia, atomowo) |
223
-
224
-### FLATPAK
225
-
226
-| Komenda | Opis |
227
-|---|---|
228
-| `pag flatpak [<query>]` | Szukaj i instaluj z Flathub |
229
-| `pag flatpak search <query>` | Szukaj na Flathub |
230
-| `pag flatpak install <id>` | Instaluje flatpak |
231
-| `pag flatpak remove <id>` | Usuwa flatpak |
232
-| `pag flatpak list` | Lista zainstalowanych flatpaków |
233
-| `pag flatpak update` | Aktualizuje wszystkie flatpaki |
234
-| `pag flatpak info <id>` | Szczegóły flatpaka |
235
-
236
-> Instalacja jako root wymusza zakres **systemowy** (`--system`), dzięki czemu
237
-> aplikacja jest widoczna dla wszystkich użytkowników, a nie tylko dla roota.
238
-
239
-### SYSTEM IMMUTABLE (`PAG_IMMUTABLE=1`)
240
-
241
-| Komenda | Opis |
242
-|---|---|
243
-| `pag deploy-list` | Lista wdrożeń (deployments) |
244
-| `pag deploy-rollback` | Przełącza na poprzednie wdrożenie |
245
-| `pag deploy-cleanup [N]` | Usuwa stare wdrożenia (zachowuje N, domyślnie 3) |
246
-| `pag initramfs-update` | Przebudowuje initramfs |
247
-| `pag grub-update` | Regeneruje wpisy GRUB dla wszystkich wdrożeń |
248
-
249
-
250
-## Zmienne środowiskowe
251
-
252
-| Zmienna | Znaczenie |
253
-|---|---|
254
-| `PAG_ROOT` | Alternatywny root operacji (testy/chroot); domyślnie `/` |
255
-| `PAG_IMMUTABLE=1` | Tryb immutable – instalacja tworzy nowy deployment |
256
-| `PAG_YES=1` | Automatyczne potwierdzenie (to samo co `-y` / `--yes`) |
257
-| `PAG_INSECURE=1` | Wyłącza wymóg HTTPS i fail-closed GPG (**tylko build/dev!**) |
258
-| `PAG_NO_HOOKS=1` | Pomija hooki i triggery |
259
-| `PAG_HOOK_TIMEOUT` | Timeout hooka w sekundach (domyślnie `60`) |
260
-| `PAG_LANG_DIR` | Katalog z plikami tłumaczeń (`pl.json`, `en.json`) |
261
-| `PAG_LANG_NO_FILES=1` | Ignoruje pliki tłumaczeń (eksport wbudowanych) |
262
-| `PAG_ROOT_DEVICE` / `PAG_GRUB_ROOT` | Jawny `root=` dla GRUB (build ISO/IMG) |
263
-| `PAG_IN_CHROOT=1` | Wymusza tryb chroot przy wykrywaniu urządzenia root |
264
-
265
-
266
-## Ścieżki i pliki
267
-
268
-| Ścieżka | Przeznaczenie |
269
-|---|---|
270
-| `/var/lib/pag/` | Baza stanu: `installed.json`, `files.db`, `world`, `pinned.json`, `history.json`, `pag.lock`, `hooks/` |
271
-| `/var/lib/pag/files.db` | SQLite: właściciele plików + sumy SHA256 |
272
-| `/var/cache/pag/` | Cache pobranych pakietów |
273
-| `/var/cache/pag/repos/` | Cache indeksów repozytoriów (JSON + ETag + znacznik czasu) |
274
-| `/etc/pag/repos.conf` i `/etc/pag/repos/*.conf` | Repozytoria (drop-in) |
275
-| `/etc/pag/trusted.json` | Przypięte fingerprinty kluczy repo |
276
-| `/etc/pag/gpg/` | Izolowany keyring GPG |
277
-| `/etc/pag/triggers/*.json` | Własne triggery |
278
-| `/etc/pag/lang/`, `/usr/share/pag/lang/` | Tłumaczenia (pliki nadpisują wbudowane) |
279
-| `/var/log/pag/audit.log` | Audyt: hooki, self-update |
280
-| `/.pag_staging` | Staging (ta sama partycja co `/` – brak `EXDEV`) |
281
-| `/.deployments/` | Wdrożenia (tryb immutable) |
282
-
283
-
284
-## Format pakietu
285
-
286
-Pakiet `.pag` to archiwum zawierające:
287
-
288
-```
289
-metadata.json – nazwa, wersja, release, zależności, provides/requires (so-name)
290
-data.tar.xz – pliki systemu + sums.json (SHA256 per plik)
291
-hooks/ – opcjonalne: pre-install, post-install, pre-remove, post-remove
292
-```
293
-
294
-Instalacja jest **weryfikowana per-plik** względem `sums.json`, a rozpakowanie
295
-chroni przed *directory traversal* i ucieczką przez złośliwe symlinki.
296
-
297
-
298
-## Hooki i triggery
299
-
300
-**Hooki** uruchamiane są jako `root` (jak w apt/pacman), w ograniczonym
301
-środowisku:
302
-
303
-- `pre-install`, `post-install`, `pre-remove`, `post-remove`
304
-- czyste env: `PATH`, `HOME=/root`, `LANG/LC_ALL=C.UTF-8`, `PKG_NAME`,
305
- `PKG_VERSION`, `PKG_ACTION`, `PKG_HOOK_API=1`
306
-- timeout (`PAG_HOOK_TIMEOUT`), możliwość wyłączenia (`PAG_NO_HOOKS=1`),
307
- wpisy w `/var/log/pag/audit.log` i w historii transakcji
308
-
309
-Instalujesz kod, któremu ufasz – hooki mają pełne uprawnienia.
310
-
311
-**Triggery** uruchamiane są **raz na transakcję**, gdy dotknięto pasujących
312
-ścieżek (tylko jeśli dana binarka istnieje):
313
-
314
-| Trigger | Ścieżki | Komenda |
315
-|---|---|---|
316
-| `font-cache` | `/usr/share/fonts/`, `/usr/local/share/fonts/` | `fc-cache -fs` |
317
-| `glib-schemas` | `/usr/share/glib-2.0/schemas/` | `glib-compile-schemas …` |
318
-| `desktop-database` | `/usr/share/applications/` | `update-desktop-database -q …` |
319
-| `mime-database` | `/usr/share/mime/` | `update-mime-database …` |
320
-
321
-Własne triggery dodasz jako `/etc/pag/triggers/*.json`.
322
-
323
-
324
-## Konfiguracja `/etc` – `.pacnew` / `.pacsave`
325
-
326
-Katalog `/etc` jest współdzielony między wdrożeniami (nie cofa się przy
327
-`deploy-rollback`). Aby nie tracić zmian użytkownika:
328
-
329
-- **Aktualizacja** pliku konfiguracyjnego, który użytkownik zmodyfikował:
330
- nowa wersja trafia jako `<plik>.pacnew`, a plik użytkownika **zostaje**.
331
-- **Usunięcie** pakietu ze zmodyfikowanym plikiem konfiguracyjnym: plik trafia
332
- jako `<plik>.pacsave` zamiast zostać skasowany.
333
-
334
-Porównanie odbywa się względem sumy SHA256 z chwili instalacji.
335
-
336
-
337
-## Przykłady
338
-
339
-```bash
340
-# Instalacja i aktualizacje
341
-sudo pag install firefox gimp
342
-sudo pag update # same pakiety
343
-sudo pag upgrade # pakiety + kernel/initramfs/GRUB
344
-sudo pag sync # odśwież indeksy + info o aktualizacjach
345
-
346
-# Naprawa pakietu (brakujące pliki/katalogi, np. /etc/pulse/default.pa.d)
347
-sudo pag install -f pulseaudio
348
-
349
-# Ikony aplikacji po instalacji motywu (cache budowany automatycznie)
350
-sudo pag install papirus-icon-theme
351
-
352
-# Bezpieczeństwo
353
-sudo pag key-add https://repo.paganlinux.eu/stable/paganos.asc
354
-sudo pag key-trust https://repo.paganlinux.eu/stable/
355
-sudo pag verify --deep
356
-
357
-# Zależności i pochodzenie pakietów
358
-sudo pag why libjpeg-turbo
359
-sudo pag autoremove
360
-
361
-# SBOM dla audytu / compliance
362
-sudo pag sbom export cyclonedx > sbom.json
363
-
364
-# Cofnij ostatnią transakcję
365
-sudo pag rollback
366
-```
367
-
368
-
369
-## Diagnostyka
370
-
371
-| Objaw | Rozwiązanie |
372
-|---|---|
373
-| „Inna instancja pag jest uruchomiona” | Działa inny proces `pag` (blokada `flock`). Poczekaj lub sprawdź `pgrep -af pag`. |
374
-| „Nie można odświeżyć indeksu” | Cache repo jest tylko-do-odczytu dla zwykłego usera – uruchom jako root: `sudo pag sync`. |
375
-| „Nieprawidłowy podpis / brak podpisu” | Zaimportuj klucz: `sudo pag key-add <url>`, potem zweryfikuj `sudo pag key-trusted`. |
376
-| Brakujące pliki/katalogi po instalacji | `sudo pag install -f <pkg>` (odtwarza pliki, puste katalogi i hooki). |
377
-| System nie bootuje po `grub-update` | Ustaw jawnie urządzenie root: `PAG_ROOT_DEVICE=/dev/sda2 sudo pag grub-update`. |
378
-| Aplikacja z Flathuba niewidoczna w menu | Dodaj `/var/lib/flatpak/exports/share` do `XDG_DATA_DIRS` i zaloguj się ponownie. |
379
-
380
-
381
-## Instalacja i aktualizacja
382
-
383
-```bash
384
-# Na działającym PaganOS pag jest w repo bazowym:
385
-sudo pag install pag # instalacja z repozytorium
386
-sudo pag self-update # aktualizacja samego klienta (podpisana)
387
-
388
-# pag jest też zarządzany przez menedżera pakietów – po publikacji nowej
389
-# wersji w repo:
390
-sudo pag update
391
-sudo pag upgrade
392
-```
393
-
394
-
395
-## Licencja
396
-
397
-PaganOS / pag – projekt open source. Szczegóły w repozytorium dystrybucji.