🔒 Repository is read-only – file editing is disabled.

pag

git clone https://git.paganlinux.eu/pag.git
Files (6) · main
6 / 6 1 5
Name Size Last change
pag-lang/ 4 dni temu
.gitignore 28 B 4 dni temu
pag 0.2 KB 4 dni temu
README-EN.md 0.0 KB 4 dni temu
README.md 0.0 KB 4 dni temu
REAFME-EN.md 0.0 KB 4 dni temu
No matching files
README.md PL | EN

pag – PaganOS Package Manager

Version Platform

Package manager for PaganOS. Atomic installation (staging → rename), GPG signature verification with fingerprint pinning, per-file SHA256, full transaction rollback, hooks and triggers, and support for immutable systems with deployments.

Diagrams in this README are rendered with Mermaid – supported by the git.paganlinux.eu portal (and GitHub/Gitea).

pag --version        # client version (e.g. pag 3.3.20)
pag                  # full help (command list)
pag --help           # same as above

Table of contents


Quick start

# Refresh repository indexes (and see what is pending an update)
sudo pag sync

# Install / remove
sudo pag install firefox gimp
sudo pag remove gimp

# Update packages only…
sudo pag update
# …or the whole system: packages + kernel / initramfs / GRUB
sudo pag upgrade

# Base baked into the ISO vs. the repository (full rolling)
pag base                       # what comes from the image, what pag manages
sudo pag base adopt            # adopt the base from the repo (--dry-run = preview)

# Verify the integrity of all files
sudo pag verify --deep

How it works

pag install flow

graph TD
    A["pag install pkg"] --> B["Dependency resolution (DFS + provides)"]
    B --> C{"Missing dependencies?"}
    C -->|yes| C1["Error – abort"]
    C -->|no| D["ABI verification (so-name)"]
    D --> E["Pre-flight: free space + RW mount"]
    E --> F["flock + database snapshot"]
    F --> G["Parallel package download"]
    G --> H["GPG + package SHA256 verification"]
    H --> I["Staging: extract + per-file sums"]
    I --> J["Atomic rename of files into the system"]
    J --> K["pre/post-install hooks"]
    K --> L["Write to SQLite + transaction history"]
    L --> M{"PAG_IMMUTABLE=1?"}
    M -->|yes| N["New deployment + GRUB entries"]
    M -->|no| O["ldconfig + triggers"]
    H -->|error| R["Rollback of the whole transaction"]
    I -->|error| R
    J -->|error| R
    R --> S["Restore database and files"]

Key properties:

  • Atomicity – files first go to staging on the same partition as /, then are moved with rename() (no half-install).
  • Transactionality – if any package fails, the whole transaction is rolled back (installed.json, files, backups).
  • File sharing – a file owned by two packages is not removed when one of them is removed (only the database entry is removed).

Trust chain

graph TD
    A["repo.json + repo.json.asc"] --> B["GPG: VALIDSIG line"]
    B --> C["Repo fingerprint pinning (TOFU → pin)"]
    C --> D["Package index"]
    D --> E["package .pag + .asc"]
    E --> F["GPG: signature matches repo pin"]
    F --> G["Whole-package SHA256"]
    G --> H["Safe extraction (anti-traversal)"]
    H --> I["sums.json: per-file SHA256"]
    I --> J["Strip SUID bit"]
    J --> K["Install"]
    F -->|"missing / bad signature"| X["Reject package"]
    G -->|"SHA256 mismatch"| X
    H -->|"traversal / symlink escape"| X
  • First use of a key = TOFU, afterwards the fingerprint is pinned (pag key-trust / pag key-untrust).
  • Verification is fail-closed: missing/bad signature = no installation (override only with PAG_INSECURE=1, build/dev only).
  • pag self-update goes through the same path: GPG → SHA256 → syntax check → atomic client replacement.

Immutable system

With PAG_IMMUTABLE=1, installation does not mutate /; it creates a new deployment. Rollback is just switching the active symlink.

graph TD
    R["/"] --> D["/.deployments"]
    D --> A["active → 20260723T120000"]
    D --> D1["20260723T120000 (new)"]
    D --> D2["20260722T090000 (previous)"]
    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 (and other SHARED_PATHS) are shared between deployments – they are not duplicated.
  • /boot shares the kernel and initramfs, saving space per deployment.
  • Rollback from the bootloader: each deployment has its own GRUB entry (pag grub-update).

Rollback

graph TD
    T["Transaction"] --> OK{"Success?"}
    OK -->|yes| H["History + snapshot + file journal"]
    OK -->|no| RB["Automatic transaction rollback"]
    H --> R["pag rollback"]
    R --> R1["Restore installed.json from snapshot"]
    R --> R2["Remove new files from the journal"]
    R --> R3["Restore overwritten files from backup"]
    R --> R4["Clean up empty directories"]
    RB --> R1
    RB --> R2
    RB --> R3

pag history shows recent transactions (including executed hooks), and pag rollback reverts the last successful transaction with a snapshot.


Rolling – base baked into the ISO

The PaganOS image is built from sources (glibc, gcc, GTK, XFCE, kernel…). pag did not install them, so they are not in its database (/var/lib/pag/installed.json) – and since it does not know them, pag upgrade will not update them. The image files are not untouchable though: pag install <name> overwrites them (a backup is kept for pag rollback).

To make the system fully rolling, tell pag what the image base is:

pag base              # report: how many image packages pag manages, how many can
                      # be adopted from the repo, which stay at the image version
sudo pag base adopt   # adopt the base from the repo (--dry-run = preview only)

After pag base adopt the image packages become ordinary repo packages, so the next sudo pag upgrade updates the whole system. The list of base packages comes from a manifest baked into the image: /usr/share/pag/base.json (name + version; the builder appends an entry for every package it builds). Builder names are mapped onto repo names (e.g. gtkgtk3, libX11xorg-libx11); names with no repo counterpart are reported as staying at the image version.


Commands

BASICS

Command Description
pag install <pkg>... Install packages (together with dependencies)
pag install -f <pkg>... Force reinstall (even the same version) – restores files, empty directories and hooks
pag remove <pkg>... Remove packages
pag update Update packages to newer versions
pag sync Refresh repository indexes + show how many packages await update
pag upgrade System update: packages + kernel / initramfs / GRUB
pag list List packages available in the repository
pag list --installed List installed packages
pag search <query> Search packages in the repo (+ Flathub)
pag info <pkg> Package details (version, dependencies, size, signature)
pag files <pkg> List files owned by a package
pag verify Verify the integrity of installed files
pag verify --deep Full per-file SHA256 verification
pag clean Clear the download cache
pag stats System statistics (package count, size, cache…)
pag download <pkg>... Download packages to cache (offline mode)

Smart search: pag <name> (any unknown command) searches the repo and Flathub and suggests names – e.g. pag firefox will find the package.

SECURITY / GPG KEYS

Command Description
pag key-add <url\|file> Import a repository GPG key
pag key-list List trusted keys
pag key-remove <id> Remove a key
pag key-trust <repo> Pin the repo key fingerprint (TOFU disabled)
pag key-untrust <repo> Forget the fingerprint (back to TOFU)
pag key-trusted List pinned repo fingerprints

ADVANCED

Command Description
pag why <pkg> Why a package is installed (who depends on it)
pag autoremove Remove orphaned dependencies
pag remove-orphans Remove orphaned dependencies (alias)
pag pin <pkg> [version] Pin a package to a version (block updates)
pag unpin <pkg> Unpin
pag pinned List pinned packages
pag history Transaction history
pag rollback Revert the last transaction (restore files from backup)
pag repo-add <url> [name] Add a repository (drop-in in /etc/pag/repos/)
pag repo-list List configured repositories
pag sbom export [spdx\|cyclonedx] Export an SBOM manifest of all installed components
pag self-update Update the pag client itself (GPG signature + SHA256 + syntax, atomically)

ROLLING (BASE FROM THE IMAGE)

Command Description
pag base Report: image packages – managed by pag / adoptable from repo / no counterpart
pag base adopt Adopts the base packages from the repo (replaces image files, backup for pag rollback); --dry-run = preview
pag base adopt <pkg>... Adopts only the given base packages

FLATPAK

Command Description
pag flatpak [<query>] Search and install from Flathub
pag flatpak search <query> Search Flathub
pag flatpak install <id> Install a flatpak
pag flatpak remove <id> Remove a flatpak
pag flatpak list List installed flatpaks
pag flatpak update Update all flatpaks
pag flatpak info <id> Flatpak details

Installation as root forces the system scope (--system), so the application is visible to all users, not just root.

IMMUTABLE SYSTEM (PAG_IMMUTABLE=1)

Command Description
pag deploy-list List deployments
pag deploy-rollback Switch to the previous deployment
pag deploy-cleanup [N] Remove old deployments (keep N, default 3)
pag initramfs-update Rebuild initramfs
pag grub-update Regenerate GRUB entries for all deployments

Environment variables

Variable Meaning
PAG_ROOT Alternative operation root (tests/chroot); default /
PAG_IMMUTABLE=1 Immutable mode – installation creates a new deployment
PAG_YES=1 Automatic confirmation (same as -y / --yes)
PAG_INSECURE=1 Disables the HTTPS requirement and fail-closed GPG (build/dev only!)
PAG_NO_HOOKS=1 Skip hooks and triggers
PAG_HOOK_TIMEOUT Hook timeout in seconds (default 60)
PAG_LANG_DIR Directory with translation files (pl.json, en.json)
PAG_LANG_NO_FILES=1 Ignore translation files (export built-ins)
PAG_ROOT_DEVICE / PAG_GRUB_ROOT Explicit root= for GRUB (ISO/IMG build)
PAG_IN_CHROOT=1 Force chroot mode when detecting the root device

Paths and files

Path Purpose
/var/lib/pag/ State database: installed.json, files.db, world, pinned.json, history.json, pag.lock, hooks/
/var/lib/pag/files.db SQLite: file owners + SHA256 sums
/var/cache/pag/ Downloaded package cache
/var/cache/pag/repos/ Repository index cache (JSON + ETag + timestamp)
/etc/pag/repos.conf and /etc/pag/repos/*.conf Repositories (drop-in)
/etc/pag/trusted.json Pinned repo key fingerprints
/etc/pag/gpg/ Isolated GPG keyring
/etc/pag/triggers/*.json Custom triggers
/etc/pag/lang/, /usr/share/pag/lang/ Translations (files override built-ins)
/var/log/pag/audit.log Audit: hooks, self-update
/.pag_staging Staging (same partition as / – no EXDEV)
/.deployments/ Deployments (immutable mode)

Package format

A .pag package is an archive containing:

metadata.json   – name, version, release, dependencies, provides/requires (so-name)
data.tar.xz      – system files + sums.json (per-file SHA256)
hooks/           – optional: pre-install, post-install, pre-remove, post-remove

Installation is verified per file against sums.json, and extraction is protected against directory traversal and escape via malicious symlinks.


Hooks and triggers

Hooks run as root (like apt/pacman), in a restricted environment:

  • pre-install, post-install, pre-remove, post-remove
  • clean env: PATH, HOME=/root, LANG/LC_ALL=C.UTF-8, PKG_NAME, PKG_VERSION, PKG_ACTION, PKG_HOOK_API=1
  • timeout (PAG_HOOK_TIMEOUT), optional disable (PAG_NO_HOOKS=1), entries in /var/log/pag/audit.log and in the transaction history

You install code you trust – hooks have full privileges.

Triggers run once per transaction, when matching paths were touched (only if the given binary exists):

Trigger Paths Command
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 …

You can add your own triggers as /etc/pag/triggers/*.json.


/etc configuration – .pacnew / .pacsave

The /etc directory is shared between deployments (it is not reverted by deploy-rollback). To avoid losing user changes:

  • Updating a configuration file that the user modified: the new version is written as <file>.pacnew, and the user's file is kept.
  • Removing a package with a modified configuration file: the file becomes <file>.pacsave instead of being deleted.

The comparison uses the SHA256 sum recorded at install time.


Examples

# Install and updates
sudo pag install firefox gimp
sudo pag update                # packages only
sudo pag upgrade               # packages + kernel/initramfs/GRUB
sudo pag sync                  # refresh indexes + update info

# Repair a package (missing files/directories, e.g. /etc/pulse/default.pa.d)
sudo pag install -f pulseaudio

# Application icons after installing an icon theme (cache built automatically)
sudo pag install papirus-icon-theme

# Security
sudo pag key-add https://repo.paganlinux.eu/stable/paganos.asc
sudo pag key-trust https://repo.paganlinux.eu/stable/
sudo pag verify --deep

# Dependencies and package provenance
sudo pag why libjpeg-turbo
sudo pag autoremove

# SBOM for audit / compliance
sudo pag sbom export cyclonedx > sbom.json

# Revert the last transaction
sudo pag rollback

Troubleshooting

Symptom Solution
"Another pag instance is running" Another pag process is active (flock lock). Wait or check pgrep -af pag.
"Cannot refresh the index" The repo cache is read-only for a regular user – run as root: sudo pag sync.
"Invalid signature / missing signature" Import the key: sudo pag key-add <url>, then verify sudo pag key-trusted.
Missing files/directories after install sudo pag install -f <pkg> (restores files, empty directories and hooks).
System does not boot after grub-update Set the root device explicitly: PAG_ROOT_DEVICE=/dev/sda2 sudo pag grub-update.
Flatpak app not visible in the menu Add /var/lib/flatpak/exports/share to XDG_DATA_DIRS and log in again.

Install and update

# On a running PaganOS, pag is in the base repository:
sudo pag install pag          # install from the repository
sudo pag self-update          # update the client itself (signed)

# pag is also managed by the package manager – after a new version is
# published in the repo:
sudo pag update
sudo pag upgrade

License

PaganOS / pag – an open source project. See the distribution repository for details.

About

commits45
branches1
Contributors6
Issues1
Default branchmain