Packagefs: Instant, Reversible Package Activation Without Unpacking
How Haiku packagefs presents HPKG contents, preserves writable shine-through directories, activates consistent states, and enables rollback.
Haiku installs most software as HPKG files that remain intact in a packages directory. packagefs mounts at an installation location and presents the union of activated package contents as an ordinary directory hierarchy. Programs see /boot/system/bin, libraries, applications, and data, while the packaged files still live inside their HPKG containers rather than as separately extracted copies.
This architecture makes activation and rollback state-oriented, but “instant” should not be taken literally as zero work. The package daemon resolves dependencies, validates a transaction, moves package files, handles writable-file policy, records activation state, and asks packagefs to update the view. The important distinction is that it does not overwrite thousands of package-owned paths one by one.
HPKG is an archive plus package metadata
Haiku’s package-building documentation describes HPKG as an archive with a separate metadata section. A .PackageInfo definition supplies name, version, architecture, summary, description, provider and dependency information, conflicts/replacements, licenses, URLs, and writable-file declarations. package and HaikuPorter produce the final file.
Package metadata is not optional decoration. The solver uses provides, requires, conflicts, supplements, and architecture to select a consistent set. An archive whose files can be read may still be ineligible for activation because dependencies are missing or it conflicts with installed providers.
HPKG contents are compressed and indexed for packagefs access. Applications should not depend on the archive’s internal ordering. Package Kit APIs and command-line tools provide supported inspection and extraction; packagefs provides the installed read view.
Signatures, repository trust, and transport verification belong to the package-management security model above packagefs. A file-system mount can expose bytes but does not decide whether a repository is trustworthy. Administrators should use configured repositories and inspect provenance rather than installing arbitrary HPKG files solely because the format parses.
Packagefs presents a union at each installation location
Haiku’s infrastructure documentation identifies two main installation locations: /boot/system for system-wide software and /boot/home/config for user software. A packagefs instance mounted at each location virtually extracts and merges the packages from its packages subdirectory.
If several packages contribute different entries to the same directory, the directory view combines them. File collisions and dependency/provider rules must be resolved by the package-management transaction; the union is not permission for unpredictable last-writer behavior. Packaging tools should prevent unrelated packages from claiming the same path.
The presented package content is read-only. Editing /boot/system/bin/tool in place is not a supported patch because that path belongs to an immutable HPKG. Build a new package, use the designated non-packaged hierarchy for deliberate local software, or change the source and redeploy through package management.
Read-only package data protects ownership clarity: removing one package removes exactly the entries it contributed without consulting a separate per-file installation database. It does not protect runtime settings, user documents, or other writable data outside the packages.
Shine-through directories remain writable
A normal mount hides the underlying directory. packagefs specially exposes shine-through directories from the BFS volume alongside package contents. Official infrastructure documentation lists packages, settings, cache, var, and non-packaged among these writable areas.
packages must remain writable so software can be added or removed. settings, cache, and var provide persistent mutable state. non-packaged is the escape hatch for traditionally installed local files that are intentionally outside HPKG ownership.
Applications must choose the right category. User preferences belong in settings, disposable derived data in cache, changing service state/log-like data under the designated variable hierarchy, and user documents in user locations. Writing beside the executable will fail or encourage unsafe workarounds.
A package can declare global writable files and update policy. The build documentation describes choices such as keeping an old modified file or automatically merging defaults. These declarations bridge immutable defaults with mutable system configuration, but packagers must test upgrades from real older versions and preserve user changes according to the declared policy.
package_daemon validates activation
The package daemon watches installation package directories and performs activation/deactivation after checking dependencies and conflicts. Package managers such as pkgman and HaikuDepot resolve/download choices, then contact the daemon through Package Kit infrastructure for the system change.
For a managed transaction, new packages are prepared in an administrative transaction directory. The daemon moves new files into place, moves obsolete files into an old-state directory, applies writable-file actions, and requests packagefs activation changes. If consistency cannot be achieved, it should leave the active system unchanged rather than expose a knowingly broken dependency set.
Manual placement of an HPKG into a packages directory still passes through daemon observation and consistency policy. It is not equivalent to bypassing dependency checking forever. Use package-manager commands for normal installation because they can find missing providers and present solutions.
Activation may require services or applications to restart before they load new libraries or add-ons. packagefs changing the visible file tree cannot replace code already mapped into a running team. Reboot or service restart requirements are package-specific operational facts, not proof activation failed.
Activated state and rollback
The package daemon records the last consistent activation set in packages/administrative/activated-packages. At mount, packagefs uses that list. The documentation notes a fallback to all packages in the directory if the file is missing or unusable, after which the daemon checks state.
Old package states are stored under the administrative hierarchy when transactions replace packages. The Haiku boot loader can select an earlier system state before the current userland starts. This makes rollback useful even when a new driver or library prevents a normal desktop boot.
Rollback selects package state; it does not rewind user data, settings, BFS, firmware, or files in non-packaged directories. If an application migrated its data incompatibly after the update, returning to old binaries may not restore usability. Back up data before risky upgrades.
Historical package files consume disk space and may be pruned. Do not advertise rollback as permanent version control. Confirm the desired state is listed in the loader before relying on it, and keep independent backups for disaster recovery.
Package links stabilize dependencies
Software can be installed at system or user scope, and compatible dependency versions may differ. Haiku generates package-link directories under /boot/system/package-links (also exposed through /packages) for each installed package. Links identify the package itself, its settings location, and resolved dependencies.
These stable link paths let a built package refer to its own installation location and the providers selected by the solver without hardcoding whether each dependency came from system or user scope. Changing a compatible provider can update the link relationship while the packaged executable path remains stable.
Package links are generated infrastructure, not a directory applications should edit. Diagnose a wrong link through package metadata and solver state. Manually replacing it can create a view inconsistent with activation records and will not survive the next transaction.
Runtime loader behavior and shared-object sonames add another compatibility layer. A dependency being linked does not make an ABI-compatible library. Packages must declare correct version constraints and library provides so resolution matches what binaries require.
Failure modes are different, not eliminated
Packagefs avoids partial extraction into package-owned paths, but package transactions can still fail from a full disk, corrupt HPKG, interrupted administrative move, dependency conflict, or writable-file migration. Recovery begins with administrative state and daemon logs, not manual deletion from the virtual /boot/system view.
A corrupt package can prevent files from appearing or make a state unbootable. Select an older loader state or disable the component, preserve logs, and use package tools to remove/reinstall the file. Verify storage health if package corruption recurs.
Shadowing matters: user-installed content may override or supplement system content according to installation-location rules. Report both scopes when diagnosing “the wrong binary” or library. A package visible in a directory is not proof that the intended provider won every resolution.
Non-packaged files trade convenience for unmanaged responsibility. The solver cannot track their provides/requires as HPKG metadata, and removal is not state rollback. Keep local exceptions minimal, documented, and separated under non-packaged rather than modifying package-owned paths.
Packaging applications correctly
Install immutable executables, libraries, add-ons, documentation, and default resources into the package image. Declare every runtime dependency and provided command/library, architecture, licenses, and conflicts. Put mutable settings and cache paths in the correct writable locations or writable-file declarations.
Test clean install, upgrade from the previous release, downgrade/rollback, uninstall, user-scope versus system-scope installation, dependency replacement, low disk space, and service restart. Verify that uninstall leaves user data by policy but removes every package-owned visible entry.
Use pkgman/HaikuDepot and Package Kit APIs rather than scripting file moves as a custom installer. A separate updater that overwrites its own executable fights packagefs immutability and bypasses repository/dependency state.
Packagefs is valuable because installed software becomes a declarative set of immutable package inputs plus explicit writable state. It reduces file-level installation ambiguity and enables bootable historical states. Its guarantees remain only as strong as package metadata, dependency resolution, writable migrations, and operational testing.
Related:
- Haiku’s Package Management System Goes Live
- Fixing Package Conflicts and Broken Dependencies in Haiku
Sources: