release · August 29, 2026

unroot 1.0.5: A Rootfs That Behaves Like a Real Root

unroot 1.0.1 through 1.0.5 make entered rootfses behave like real roots, introduce reversible file injections, and speed up and harden archive transport.

Since the unroot 1.0.0 announcement, five rapid releases have shipped: 1.0.1, 1.0.2, 1.0.3, 1.0.4, and 1.0.5. The theme across all of them: making an entered rootfs feel like a real system, and making rootfs transport faster and safer.

A Rootfs That Behaves Like a Real Root

The most visible change: an entered rootfs now appears as / in its own mount table. Package managers and other tools expect the conventional root mount entry, and unroot now provides it. (#33)

Alongside that, a set of small changes that add up to a big difference in day-to-day usability:

  • Colors and ncurses apps just work — $TERM is now preserved inside the rootfs by default.
  • lscpu and htop work — /sys is recursively bind-mounted read-only, exposing the information these tools need without exposing writable sysfs control files.

1.0.5 closes a regression from 1.0.4 so the root mount behaves consistently even when paths traverse top-level directories like /etc/../proc. (#36)

File Injections: Host State That Never Ships

The most interesting new capability is the file injection framework, which is what makes the /etc/mtab and name-resolution fixes possible. An entered rootfs needs some of your host's state to be usable — working DNS, resolvable hostnames, a live mount table — but that state is specific to your machine, and it should never end up in a rootfs archive you distribute.

Injections solve exactly that. When unroot unpack creates a managed rootfs, it installs three named injections by default: writable copies of the host's /etc/resolv.conf and /etc/hosts, and an /etc/mtab symlink pointing at the namespace's live /proc/self/mounts. Before replacing any destination, unroot preserves the rootfs's original file, symlink, or absence. You can edit the injected copies freely while working in the rootfs, and when you pack the rootfs, each live injected file is excluded and its preserved original is substituted back in — so your host's DNS configuration, hostname entries, and generated mount-table link never leak into the portable archive. (#34)

You can see the active injections at any time:

List the active injections in a rootfs
$ unroot inject list ~/rootfs
NAME            DESTINATION                 OWNER       MODE    ORIGINAL  CURRENT
resolv.conf     /etc/resolv.conf            0:0         0644    regular   present
hosts           /etc/hosts                  0:0         0644    absent    present
mtab            /etc/mtab                   0:0         0777    symlink   symlink

The framework is fully manageable, not just a fixed set of defaults:

  • unroot inject add registers built-ins by name or custom items as SOURCE[:DESTINATION[:UID:GID:MODE]] — for example, injecting your host's /etc/localtime into a rootfs.
  • unroot inject remove and unroot inject clear restore the preserved originals (or remove the live copy when the destination was originally absent).
  • unroot unpack --inject=-hosts,-mtab (or --inject=-* to disable all defaults) keeps rootfs creation predictable; add or alter injections afterward with the inject action.

It's a small feature with a long tail: any file you want live in the rootfs but portable in the archive is now a one-line injection.

Faster, Safer Archive Transport

unroot's pack and unpack now use libarchive through the sibling unroot-util host helper, removing the dependency on a locally-installed GNU tar and eliminating a whole class of bugs. Parallel xz compression is enabled by default, and interactive archive operations now display compact, terminal-aware progress with throughput in MiB/s.

Metadata safety got a full pass:

  • Source builds now check at build time that libarchive supports POSIX ACLs and extended attributes, closing a gap that could cause silent metadata loss. (#32)
  • unpack performs a pre-flight scan of the archive; when it finds ACLs or xattrs, it verifies the destination filesystem can store them before extraction begins, and aborts cleanly if not. Use --force if reduced fidelity is acceptable.
  • pack and unpack take one self-cleaning exclusive lock per rootfs, so archive reads and writes can't overlap on the same tree. A competing command fails immediately; process exit releases the lock with no stale file left behind. (#27)

Usability and Safety

  • unroot enter --single ROOT enters unmanaged, single-owner rootfs trees without needing subordinate UID/GID allocations. The standalone single command was removed to reduce confusion. (#4, #12)
  • --map-ro SOURCE is now shorthand for --map-ro SOURCE:SOURCE when the host and container paths match. (#5)
  • Commands receive a sensible default PATH focused on the rootfs; use --no-default-env for a completely empty environment. (#3)
  • /dev is more complete — /dev/full, standard stream links, and proper PTY support, so shell process substitution and interactive tools work without exposing the host's entire /dev tree. (#2)
  • New inspect host and inspect archive actions expose runtime capabilities and archive facts. (#21)
  • enter rejects paths that resolve to the host /, and OCI images are explicitly rejected until support lands. (#25)

One packaging note: GitHub release downloads no longer include standalone unroot binaries. A functional installation needs both the static unroot engine and its host-linked unroot-util helper, so use a prebuilt distro package or build from source.

Get unroot

Download unroot 1.0.5 from the GitHub release page — distro packages for Debian, Ubuntu, Fedora, and Enterprise Linux are available, along with static binaries and a source archive. Visit the unroot project page for documentation and usage examples.

Report issues on the GitHub issue tracker.