[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

01/02: website: Add post about guix shell fhs option.

From: Ludovic Courtès
Subject: 01/02: website: Add post about guix shell fhs option.
Date: Fri, 6 Jan 2023 06:59:26 -0500 (EST)

civodul pushed a commit to branch master
in repository guix-artwork.

commit cd01aa11e320270de3e82007c56ec4d3eee4b6fc
Author: John Kehayias <>
AuthorDate: Fri Dec 16 02:22:17 2022 -0500

    website: Add post about guix shell fhs option.
    * website/posts/ New file.
    website/static/blog/img/guix-shell-fhs.gif: New file.
    Signed-off-by: Ludovic Courtès <>
 website/posts/            | 255 +++++++++++++++++++++++++++++
 website/static/blog/img/guix-shell-fhs.gif | Bin 0 -> 306976 bytes
 2 files changed, 255 insertions(+)

diff --git a/website/posts/ b/website/posts/
new file mode 100644
index 0000000..dd2b13c
--- /dev/null
+++ b/website/posts/
@@ -0,0 +1,255 @@
+title: The Filesystem Hierarchy Standard Comes to Guix Containers
+date: 2023-01-04 15:00
+author: John Kehayias
+tags: Software development, Containers
+GNU Guix is different from most other GNU/Linux distributions and perhaps 
nowhere is that
+more obvious than the organization of the filesystem: Guix does not conform to 
+[Filesystem Hierarchy 
Standard]( (FHS). In
+practical terms, this means there is no global `/lib` containing libraries, 
+containing binaries,¹ and so on. This is very much at the core of how Guix 
works and some
+of the convenient features, like per-user installation of programs (different 
+for instance) and a declarative system configuration where the system is 
determined from a
+configuration file.
+However, this also leads to a difference in how many pieces of software expect 
their world
+to look like, relying on finding a library in `/lib` or an external tool in 
`/bin`. When
+these are hard coded and not overcome with appropriate build options, we patch 
code to
+refer to absolute paths in the store, like
+`/gnu/store/hrgqa7m498wfavq4awai3xz86ifkjxdr-grep-3.6/bin/grep`, to keep 
+consistently contained within the store.
+It all works great and is thanks to the hard work of everyone that has 
contributed to
+Guix. But what if we need a more FHS-like environment for developing, testing, 
or running
+a piece of software?
+To that end, we've [recently
 (available in [Guix 
+a new option for [`guix
+(previously called [`guix
+`--emulate-fhs` (or `-F`). This option is used in conjunction with the
(or `-C`)
+option which creates an isolated, you guessed it, container. The new 
+option will set up an environment in the container that follows FHS 
expectations, so that
+libraries are visible in `/lib` in the container, as an example.
+Here is a very simple example:
+$ guix shell --container --emulate-fhs coreutils -- ls /bin | head
+$ guix shell --container --emulate-fhs coreutils -- ls /lib | head
+Contrast that with `/bin` on a Guix system:
+$ ls /bin -l
+total 4
+lrwxrwxrwx 1 root root  61 Dec 12 09:57 sh -> \
+    /gnu/store/d99ykvj3axzzidygsmdmzxah4lvxd6hw-bash-5.1.8/bin/sh*
+and `/lib`
+$ ls /lib
+ls: cannot access '/lib': No such file or directory
+Or, if you like to see it more in motion, here's a gif (courtesy of Ludovic 
+![An animated gif showing the above 'guix shell' 
+Additionally, for the more technically-minded, the [`glibc` used in this
+will read from a global cache in `/etc/` contrary to the [behavior 
+otherwise. This can help ensure that libraries are found when querying the ld 
cache or
+using the output of `ldconfig -p`, for example.
+There are several uses that spring to mind for such a container in Guix. For 
+or those aspiring to hack on a project, this is a helpful tool when needing to 
emulate a
+different (non-Guix) environment. For example, one could use this to more 
easily follow
+build instructions meant for a general distribution, say when a Guix package 
is not (yet)
+available or easy to write immediately.
+Another usage is to be able to use tools that don't really fit into Guix's 
model, like
+ones that use pre-built binaries. There are many reasons why this is not ideal 
and Guix
+strives to replace or supplement such tools, but practically speaking they can 
be hard to
+avoid entirely. The FHS container helps bridge this gap, providing an isolated 
+reproducible environment as needed.
+Users not interested in development will also find the FHS container useful. 
For example,
+there may be software that is free and conforms to the [Free System 
(FSDG) Guix
+follows, yet is not feasible to be
+[packaged]( by our 
+JavaScript and particularly [Electron]( 
applications are not
+yet packaged for Guix due to the
+[difficulties]( of 
a properly
+source-based and bootstrapable approach in this ecosystem.
+As a more interesting example for this last point, let's dive right into a big 
one: the
+popular [VSCodium]( editor. This is a 
+licensed]( build of 
+VS Code editor. This is based on Electron and pre-built 
+are available. [Downloading]( 
and making the
+AppImage executable (with a `chmod +x`), we can run it in a container with
+guix shell --container --network --emulate-fhs \
+    --development ungoogled-chromium gcc:lib \
+    --preserve='^DISPLAY$' --preserve='^XAUTHORITY$' --expose=$XAUTHORITY \
+    --preserve='^DBUS_' --expose=/var/run/dbus \
+    --expose=/sys/dev --expose=/sys/devices --expose=/dev/dri \
+    -- ./VSCodium- 
+The second line is a handy cheat to get lots of libraries often needed for 
+applications (development inputs of the package `ungoogled-chromium`) though 
it can be
+overkill if the AppImage does actually bundle everything (they don't!). The 
next line is
+for display on the host's X server, the one after for DBus communication, and 
+exposing some of the host hardware for rendering. This last part may be 
different on
+different hardware. That should do it, at least to see basic functionality of 
+Note that we can't run an AppImage without the `--appimage-extract-and-run` 
option as it
+will want to use 
[FUSE]( to
+mount the image which is not possible from the container.²
+The FHS container is also useful to be able to run the exact same binary as 
anyone else,
+as you might want to for privacy reasons with the [Tor
+Browser]( While there is a long-standing [set of
+patches]( to build the Tor Browser from 
source, with a
+container we can run the official build directly. After
+[downloading](, checking the
+[signature](, and
+[unpacking](, we can launch the 
Tor Browser
+from the root of the unpacked directory with:
+guix shell --container --network --emulate-fhs \
+    --preserve='^DISPLAY$' --preserve='^XAUTHORITY$' --expose=$XAUTHORITY \
+    alsa-lib bash coreutils dbus-glib file gcc:lib \
+    grep gtk+ libcxx pciutils sed \
+    -- ./start-tor-browser.desktop -v
+Here we've used a more minimal set of package inputs, rather than the 
+trick above. Usually this is found through some trial and error, looking at 
log output,
+maybe tracing, and sometimes from documentation. Though documentation of 
needed packages
+often has some assumptions on what is already available on typical systems. 
(Thanks to Jim
+Newsome for pointing out this example on the [guix-devel mailing
+Another example is to get the latest nightly builds of 
[Rust](, via [`rustup`](
+$ mkdir ~/temphome
+$ guix shell --network --container --emulate-fhs \
+    bash coreutils curl grep nss-certs gcc:lib gcc-toolchain \
+    pkg-config glib cairo atk pango@1.48.10 gdk-pixbuf gtk+ git \
+    --share=$HOME/temphome=$HOME
+~/temphome [env]$ curl --proto '=https' --tlsv1.2 -sSf <> 
| sh
+First we created a `~/temphome` directory to use as `$HOME` in the container 
and then
+included a bunch of libraries in the container for the next example.
+This will proceed without problem and we'll see
+info: downloading installer
+Welcome to Rust!
+This will download and install the official compiler for the Rust
+programming language, and its package manager, Cargo.
+Rust is installed now. Great!
+To get started you may need to restart your current shell.
+This would reload your PATH environment variable to include
+Cargo's bin directory ($HOME/.cargo/bin).
+To configure your current shell, run:
+source "$HOME/.cargo/env"
+After updating the shells environment as instructed, we can see it all worked
+~/temphome [env]$ rustc --version
+rustc 1.65.0 (897e37553 2022-11-02)
+as Guix's current Rust is at 1.61.0 and we didn't even include Rust in the
+container, of course.
+Finally, we can build a Rust project of desktop widgets, [ElKowars wacky 
+(eww)](, following [their
+directions]( Ultimately this uses just the 
standard `cargo
+build --release` and builds after downloading all the needed libraries.
+~/temphome/eww [env]$ git clone
+~/temphome/eww [env]$ cd eww
+~/temphome/eww [env]$ cargo build --release
+info: syncing channel updates for 'nightly-2022-08-27-x86_64-unknown-linux-gnu'
+info: latest update on 2022-08-27, rust version 1.65.0-nightly (c07a8b4e0 
+Finished release [optimized] target(s) in 2m 06s
+With this being a fresh container, you will need to make some directories that 
+exist, like `~/.config` and `~/.cache` in this case. For basic display 
support, it is
+enough to add `--preserve='^DISPLAY$' --preserve='^XAUTHORITY$' 
--expose=$XAUTHORITY` to
+the container launch options and run the first example widget in the
+As we can see, with containers more generally we have to provide the right 
inputs and
+options as the environment is completely specified at creation. Once you want 
to run
+something that needs hardware from the host or to access host files, the 
container becomes
+increasingly porous for more functionality. This is certainly a trade-off, but 
one which
+we have agency with a container we wouldn't get otherwise.
+The FHS option provides another option to make a container in Guix to produce 
+environments, even those with a vastly different philosophy of the root 
filesystem! This
+is one more tool in the Guix toolbox for controlled and reproducible 
environments that
+also let's us do some things we couldn't (easily) do otherwise.
+##### Notes
+¹ Other than a symlink for `sh` from the `bash`
+package, for compatibility reasons.
+² Actually, one can use `flatpak-spawn` from
+[`flatpak-xdg-utils`]( to launch 
+on the host and get the AppImage to mount itself. However, it is not visible 
from the same
+container. Or, we can use a normal [mounting
+outside of the container to inspect the contents, but AppImages will have an 
offset. We
+can use the FHS container option to get this offset and then mount in one line 
with `mount
+VSCodium- <mountpoint> -o offset=$(guix 
+--container --emulate-fhs zlib -- 
diff --git a/website/static/blog/img/guix-shell-fhs.gif 
new file mode 100644
index 0000000..352caec
Binary files /dev/null and b/website/static/blog/img/guix-shell-fhs.gif differ

reply via email to

[Prev in Thread] Current Thread [Next in Thread]