Skip to main content

Utilities for carving out root filesystems/filesystem layers from Gentoo Linux systems

Project description

Egatrop

Installing

Ideally, through use of uv, it's a matter of running uv tool install egatrop.

What is it

Utilities for running the Gentoo Portage system, in a sense, "in reverse". It's something like Nix's nix-copy-closure but for Gentoo.

That is, given an existing Gentoo system, create the dependency tree as it is for that particular system for some package or set of packages. Then it can either show you that dependency tree, or export the files installed by those packages to somewhere (some new root filesystem, for instance).

You can use the resulting filesystem tree as a container layer, or for making an initrd, or a rescue disk, or ...

What good does that do

Suppose you'd want to setup some minimal container root filesystem, with only postgresql-18, bash and busybox installed. And you want to have it be based on Gentoo, with its excellent customization system — say in this instance you want to leave out PostgreSQL's JIT so as not to end up shipping llvm in your container filesystem, and perhaps you're applying some custom patches on top of it.

Debian-based distros have debootstrap. Arch Linux has pacstrap. Gentoo has nothing like that, because there is no canonical setup; customizability is the whole point of Gentoo, so we'll first have to create a Gentoo system that contains PostgreSQL and other things we need, cooked to perfection.

Creating that Gentoo system is not the issue. Create a chroot, do the usual. Let's consider that done. But we don't want to ship that whole system, as it contains way way more than the minimally needed — it'll contain the Gentoo build system itself (including a whole compiler toolchain), some version of Python used for running emerge, it'll contain all the package definitions, etc. etc. None of that stuff is needed for running PostgreSQL. In our container we don't want the Gentoo base system, or any build-time dependency. We want something akin to Nix's nix-copy-closure, but for Gentoo.

quickpkg can't do that, because it doesn't follow dependencies.

Using emerge --emptytree --buildpkg and then extracting from the resultant packages won't achieve the goal either, as it will pull in the whole build chain and Gentoo system.

But with the egreme utility in this package, we can pull it off!

Dive right in

If you want to dive right in, just run egreme --help and take it from there. But a bit of reading on might save befuddlement later.

Example usages

Using the graph: A look at the dependency tree

Here's the dependency tree of the package set app-shells/bash + sys-apps/coreutils of some minimized Gentoo installation.

We specify the graph subcommand, as we just want to see the dependency graph for now.

We specify app-shells/bash and sys-apps/coreutils as positional arguments. They get resolved to the concrete versions as installed on that system. We could have passed those concrete specifications instead if we'd preferred.

As we're not operating on our root Gentoo system, but rather on a mimimized system created in a chroot, we have to specify where to find the package database for that chroot using --dbpath.

$ egreme graph app-shells/bash sys-apps/coreutils --dbpath /var/lib/machines/my-gentoo-chroot/var/db/pkg
=app-shells/bash-5.3_p9-r1:0
    =sys-libs/ncurses-6.5_p20250802:0/6
        =sys-libs/glibc-2.42-r5:2.2
            =net-dns/libidn2-2.3.8:0/2
                =dev-libs/libunistring-1.3:0/5
    =virtual/libintl-0-r2:0
    =sys-libs/readline-8.3_p3:0/8
=sys-apps/coreutils-9.9-r12:0
    =sys-apps/acl-2.3.2-r3:0
        =sys-apps/attr-2.5.2-r1:0
    =dev-libs/openssl-3.5.5-r2:0/3

One thing to note is that the dependency tree is not exhaustive: in this example, on this system, both bash and coreutils depend on ncurses, but with the above incantation ncurses is not repeated under coreutils. To see a dependency tree expanded like that, with full attribution, there are other tools (eg emerge --tree --pretend). Here we do incremental dependency attribution only.

Exporting the closure

We were promised something akin to Nix's nix-copy-closure, but for Gentoo. So how do we copy out the dependency tree? As follows, with the clone subcommand:

$ mkdir /dev/shm/outfs
$ egreme.py clone app-shells/bash --infs /var/lib/machines/my-gentoo-chroot --dbpath /var/lib/machines/my-gentoo-chroot/var/db/pkg --outfs /dev/shm/outfs
Cloning =app-shells/bash-5.3_p9-r1:0
Cloning =sys-libs/ncurses-6.5_p20250802:0/6
Cloning =sys-libs/glibc-2.42-r5:2.2
Cloning =net-dns/libidn2-2.3.8:0/2
Cloning =dev-libs/libunistring-1.3:0/5
Cloning =virtual/libintl-0-r2:0
Cloning =sys-libs/readline-8.3_p3:0/8

The directory /dev/shm/outfs now contains the bare minimum for running bash. Obviously this can be a varying amount of software, depending on the choices made when setting up the mother filesystem (at /var/lib/machines/my-gentoo-chroot).

Look into egreme --help to see some options one might want to use for the clone operation.

Working with "cuts"

Let's look at a deptree for just dev-db/postgresql:18 on some system, of which the first part happens to look like this:

$ egreme graph dev-db/postgresql:18
=dev-db/postgresql-18.3:18
    =app-eselect/eselect-postgresql-2.4-r1:0
        =app-admin/eselect-1.4.31:0
            =sys-apps/coreutils-9.9-r12:0
                =sys-apps/acl-2.3.2-r3:0
                    =sys-apps/attr-2.5.2-r1:0
                        =sys-libs/glibc-2.42-r5:2.2
                            =net-dns/libidn2-2.3.8:0/2
                                =dev-libs/libunistring-1.3:0/5
(following 73 lines omitted for brevity)

While Gentoo has app-eselect/eselect-postgresql as a runtime dependency of PostgreSQL, seasoned users may know that actually, that's just a utility for setting some symlinks. In some cases one might not need it, but it does come with a bit of baggage here. Can we leave it out? Yes. For that we can supply a "cut" positional argument to specify that we don't want that package (nor any of its exclusive dependencies). The incantation will become some variant of:

egreme graph dev-db/postgresql:18 --cut app-eselect/eselect-postgresql

Specify as many cuts as you wish as positional arguments.

Working with "furcations"

Sometimes, a dependency can be fulfilled in several ways. Suppose we want to create a container that runs net-misc/mosh. Mosh requires an ssh, but that requirement can be fulfilled with either net-misc/openssh or net-misc/dropbear. Installation of either of those fullfills the virtual/ssh package on which net-misc/mosh concretely depends. Here's an (abbreviated) depgraph, for net-misc/mosh, of a system that has it plus the two SSH implementations installed:

$ egreme graph net-misc/mosh
=net-misc/mosh-1.4.0-r1:0
    [...]
    =virtual/ssh-0-r2:0
        AtomFurcation@299628531972363860: net-misc/dropbear | virtual/openssh
            =net-misc/dropbear-2025.89:0
                [...]
            =virtual/openssh-0-r1:0
                =net-misc/openssh-10.2_p1:0
                    [...]

The deptree includes both paths. Isn't that a problem? Yes, as we'll find out when we ask to export the packages:

$ egreme clone net-misc/mosh --outfs /dev/shm/my-container-layer
Furcation 299628531972363860: via =net-misc/mosh-1.4.0-r1:0
	furcates: False	deps: 66	pkg: =net-misc/dropbear-2025.89:0
	furcates: False	deps: 65	pkg: =virtual/openssh-0-r1:0

Unresolved furcations present. Please supply furcdirs.

Egreme will exit nonzero and tells you to direct which way you want to go at this fork (furcation) in the road.

The output lists furcations, with a stable unique ID for each, together with some info about whether a specific path furcates further onward, and the total dependencies for each path. Of course, for choosing which path to take it's important to look at each dependency tree by itself to judge which one has the smallest installed size, if that is the criterion. Here openssh may have 1 fewer dependency, yet perhaps the dependencies are much larger than dropbear's. The dependency count is thus just an indication.

Expliciting the choice is easy. Here we'll go with dropbear, and use the furcation ID from the above output together with that choice as a positional argument after --furcdirs. This works for all subcommands (be it clone, graph, or furcations).

We can check whether we resolved all furcations by trying to list any remaining using the furcations command:

$ egreme furcations net-misc/mosh --furcdirs 299628531972363860:net-misc/dropbear

No output — no news is good news, we've resolved all furcations and should be able to use the clone command now (supplying this furcation directive, of course).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

egatrop-0.0.1.tar.gz (17.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

egatrop-0.0.1-py3-none-any.whl (19.4 kB view details)

Uploaded Python 3

File details

Details for the file egatrop-0.0.1.tar.gz.

File metadata

  • Download URL: egatrop-0.0.1.tar.gz
  • Upload date:
  • Size: 17.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Gentoo","version":"2.18","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for egatrop-0.0.1.tar.gz
Algorithm Hash digest
SHA256 e1f41b8905fd0fc40224068940cc151a9666e36b4de00105ee0f64428a9f6cfd
MD5 69b057d8f4fa8ae32eadcfa241d8e86a
BLAKE2b-256 3d03673ae29bb4efaa8c67c6f9f6c0ae1514690902914ecbb26cd129cc9a4d80

See more details on using hashes here.

File details

Details for the file egatrop-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: egatrop-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 19.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Gentoo","version":"2.18","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for egatrop-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d6c6f7ef65eb0680644ec8c0181d25fe85717fb5f13bbfc6eff373a2c2245ed8
MD5 d3d5931087aced2e0e4486047b6e2c3b
BLAKE2b-256 4508773c63c68b78dfef23fa0f66f9ba830d4fd4ec03775c8af69ccb4c0488ee

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page