https://guix.gnu.org/feeds/blog/shepherd.atomGNU Guix — Blog — shepherdfeed author nameGNU Guixhttps://guix.gnu.org/static/base/img/icon.png2020-08-14T21:45:03Zhttps://guix.gnu.org/blog/2020/gnu-shepherd-user-services/GNU Shepherd user servicesEfraim Flashner2020-05-17T20:00:00Z2020-05-17T20:00:00Z One of the things which sets Guix apart from other GNU/Linux
distributions is that it uses GNU
Shepherd instead of the now
ubiquitous systemd. A side effect of this is that user systemd units do
not work on Guix System. Love, hate or extremely ambivalent toward
systemd, this means that users cannot rely on already written systemd
unit files for their regular user-level services. There are a couple of benefits to using GNU Shepherd, and not all of
them are due to it already being installed on Guix. Becoming comfortable
with using Shepherd and understanding how to write and edit Shepherd
service…<p>One of the things which sets Guix apart from other GNU/Linux
distributions is that it uses <a href="https://www.gnu.org/software/shepherd/">GNU
Shepherd</a> instead of the now
ubiquitous systemd. A side effect of this is that user systemd units do
not work on Guix System. Love, hate or extremely ambivalent toward
systemd, this means that users cannot rely on already written systemd
unit files for their regular user-level services.</p><p>There are a couple of benefits to using GNU Shepherd, and not all of
them are due to it already being installed on Guix. Becoming comfortable
with using Shepherd and understanding how to write and edit Shepherd
service configurations makes the transition from other GNU/Linux
distributions to Guix System easier. More complex services with their
own logic tree, using the full power of <a href="https://www.gnu.org/software/guile/">GNU
Guile</a>, are also possible. This
means you can have one service that behaves differently if it's running
on a different system or architecture without needing to call out to
shell scripts or using minimally different service definitions.</p><p>The GNU Shepherd manual
<a href="https://www.gnu.org/software/shepherd/manual/html_node/Jump-Start.html#index-Configuration-file">suggests</a>
putting all the services inside a
monolithic <code>init.scm</code> file, located by default at
<code>$XDG_CONFIG_DIR/shepherd/init.scm</code>. While this does make it easy to keep
everything in one place, it does create one glaring issue: any changes
to the file mean that all the services need to be stopped and restarted
in order for any changes to take place.</p><p>Luckily there's a nice function called <code>scandir</code> hiding in <a href="https://www.gnu.org/software/guile/manual/html_node/File-Tree-Walk.html#index-scandir"><code>ice-9 ftw</code></a>
which returns a list of all files in a specified directory (with options
for narrowing down the list or sorting it). This means that our <code>init.scm</code>
can contain a minimum of code and all actual services can be loaded from
individual files.</p><p>First the minimal <code>init.scm</code>:</p><pre><code class="language-scheme">(use-modules (shepherd service)
((ice-9 ftw) #:select (scandir)))
;; Load all the files in the directory 'init.d' with a suffix '.scm'.
(for-each
(lambda (file)
(load (string-append "init.d/" file)))
(scandir (string-append (dirname (current-filename)) "/init.d")
(lambda (file)
(string-suffix? ".scm" file))))
;; Send shepherd into the background
(action 'shepherd 'daemonize)</code></pre><p>Let's take a sample service for running syncthing, as defined in
<code>$XDG_CONFIG_DIR/shepherd/init.d/syncthing.scm</code>:</p><pre><code class="language-scheme">(define syncthing
(make <service>
#:provides '(syncthing)
#:docstring "Run `syncthing' without calling the browser"
#:start (make-forkexec-constructor
'("syncthing" "-no-browser")
#:log-file (string-append (getenv "HOME")
"/log/syncthing.log"))
#:stop (make-kill-destructor)
#:respawn? #t))
(register-services syncthing)
(start syncthing)</code></pre><p>As with any other shepherd service it is defined and registered, and in
this case it will start automatically. When the file is loaded by
shepherd after being discovered by scandir everything works exactly as
though the service definition were located directly inside the <code>init.scm</code>.</p><p>Now lets make a change. Since syncthing already has a <code>-logfile</code> flag and
it has built-in log rotation that sounds better than using shepherd's
<code>#:log-file</code> option. First we'll make our changes to the service:</p><pre><code class="language-scheme">(define syncthing
(make <service>
#:provides '(syncthing)
#:docstring "Run `syncthing' without calling the browser"
#:start (make-forkexec-constructor
'("syncthing" "-no-browser"
"-logflags=3" ; prefix with date & time
"-logfile=/home/user/log/syncthing.log"))
#:stop (make-kill-destructor)
#:respawn? #t))
(register-services syncthing)
(start syncthing)</code></pre><p>Now we stop syncthing:</p><pre><code class="language-sh">$ herd stop syncthing</code></pre><p>And we load the new service:</p><pre><code class="language-sh">$ herd load root ~/.config/shepherd/init.d/syncthing.scm</code></pre><p>This allows for quickly iterating on services without needing to stop
all the services! Let's take a look at another service:</p><pre><code class="language-scheme">(define fccache
(make <service>
#:provides '(fccache)
#:docstring "Run 'fc-cache -frv'"
#:start (make-forkexec-constructor
'("guix" "environment" "--ad-hoc" "fontconfig" "--"
"fc-cache" "-frv")
#:log-file (string-append (getenv "HOME")
"/log/fccache.log"))
#:one-shot? #t))
(register-services fccache)</code></pre><p>In this example I want to refresh my font cache but I don't want to
actually install fontconfig either system-wide or in my profile.</p><pre><code class="language-sh">$ which fc-cache
which: no fc-cache in (/home/user/.config/guix/current/bin:/home/user/.guix-profile/bin:/home/user/.guix-profile/sbin:/run/setuid-programs:/run/current-system/profile/bin:/run/current-system/profile/sbin)
$ herd start fccache
Service fccache has been started.</code></pre><p>Of course we can import other modules and leverage the code already
written there. In this case, instead of using the string "guix
environment --ad-hoc fontutils -- fc-cache -frv" let's use the <code>guix environment</code> function already available in <code>guix scripts environment</code>:</p><pre><code class="language-scheme">(use-modules (guix scripts environment))
(define fccache
(make <service>
#:provides '(fccache)
#:docstring "Run 'fc-cache -frv'"
#:start (lambda () ; Don't run immediately when registered!
(guix-environment "--ad-hoc" "fontconfig" "--" "fc-cache" "-frv"))
#:one-shot? #t))
(register-services fccache)</code></pre><pre><code class="language-sh">$ herd load root ~/.config/shepherd/init.d/fccache.scm
Loading /home/user/.config/shepherd/init.d/fccache.scm.
$ herd start fccache
/gnu/store/hbqlzgd8hcf6ndcmx7q7miqrsxb4dmkk-gs-fonts-8.11/share/fonts: caching, new cache contents: 0 fonts, 1 dirs
/gnu/store/hbqlzgd8hcf6ndcmx7q7miqrsxb4dmkk-gs-fonts-8.11/share/fonts/type1: caching, new cache contents: 0 fonts, 1 dirs
/gnu/store/hbqlzgd8hcf6ndcmx7q7miqrsxb4dmkk-gs-fonts-8.11/share/fonts/type1/ghostscript: caching, new cache contents: 35 fonts, 0 dirs
/home/user/.guix-profile/share/fonts: caching, new cache contents: 0 fonts, 7 dirs
/home/user/.guix-profile/share/fonts/opentype: caching, new cache contents: 8 fonts, 0 dirs
/home/user/.guix-profile/share/fonts/otf: caching, new cache contents: 12 fonts, 0 dirs
/home/user/.guix-profile/share/fonts/terminus: caching, new cache contents: 18 fonts, 0 dirs
/home/user/.guix-profile/share/fonts/truetype: caching, new cache contents: 58 fonts, 0 dirs
/home/user/.guix-profile/share/fonts/ttf: caching, new cache contents: 12 fonts, 0 dirs
/home/user/.guix-profile/share/fonts/type1: caching, new cache contents: 0 fonts, 1 dirs
/home/user/.guix-profile/share/fonts/type1/ghostscript: caching, new cache contents: 35 fonts, 0 dirs
/home/user/.guix-profile/share/fonts/woff: caching, new cache contents: 1 fonts, 0 dirs
/run/current-system/profile/share/fonts: skipping, no such directory
/home/user/.local/share/fonts: skipping, no such directory
/home/user/.fonts: skipping, no such directory
/gnu/store/hbqlzgd8hcf6ndcmx7q7miqrsxb4dmkk-gs-fonts-8.11/share/fonts/type1: skipping, looped directory detected
/home/user/.guix-profile/share/fonts/opentype: skipping, looped directory detected
/home/user/.guix-profile/share/fonts/otf: skipping, looped directory detected
/home/user/.guix-profile/share/fonts/terminus: skipping, looped directory detected
/home/user/.guix-profile/share/fonts/truetype: skipping, looped directory detected
/home/user/.guix-profile/share/fonts/ttf: skipping, looped directory detected
/home/user/.guix-profile/share/fonts/type1: skipping, looped directory detected
/home/user/.guix-profile/share/fonts/woff: skipping, looped directory detected
/gnu/store/hbqlzgd8hcf6ndcmx7q7miqrsxb4dmkk-gs-fonts-8.11/share/fonts/type1/ghostscript: skipping, looped directory detected
/home/user/.guix-profile/share/fonts/type1/ghostscript: skipping, looped directory detected
/var/cache/fontconfig: not cleaning unwritable cache directory
/home/user/.cache/fontconfig: cleaning cache directory
/home/user/.fontconfig: not cleaning non-existent cache directory
fc-cache: succeeded
herd: exception caught while executing 'start' on service 'fccache':
Throw to key `quit' with args `(0)'.</code></pre><p>The problem with this approach is that <code>guix-environment</code> returns the
<a href="https://git.savannah.gnu.org/cgit/guix.git/tree/guix/scripts/environment.scm?h=v1.1.0#n771">exit
code</a>
of the programs it calls and <code>#:start</code> expects a
<a href="https://www.gnu.org/software/shepherd/manual/html_node/Slots-of-services.html#index-Starting-a-service-1"><code>constructor</code></a>
to return <code>#t</code> or <code>#f</code> so there's some work to be done here.</p><p>This was just a quick peek into what's possible with GNU Shepherd when
run as a user. Next time we'll take a look at integrating
<a href="https://www.gnu.org/software/mcron/">mcron</a> to replicate some of
systemd's timer functionality.</p><h4>About GNU Guix</h4><p><a href="https://guix.gnu.org">GNU Guix</a> is a transactional package
manager and an advanced distribution of the GNU system that <a href="https://www.gnu.org/distros/free-system-distribution-guidelines.html">respects
user
freedom</a>.
Guix can be used on top of any system running the kernel Linux, or it
can be used as a standalone operating system distribution for i686,
x86_64, ARMv7, and AArch64 machines.</p><p>In addition to standard package management features, Guix supports
transactional upgrades and roll-backs, unprivileged package management,
per-user profiles, and garbage collection. When used as a standalone
GNU/Linux distribution, Guix offers a declarative, stateless approach to
operating system configuration management. Guix is highly customizable
and hackable through <a href="https://www.gnu.org/software/guile">Guile</a>
programming interfaces and extensions to the
<a href="http://schemers.org">Scheme</a> language.</p>https://guix.gnu.org/blog/2017/running-system-services-in-containers/Running system services in containersLudovic Courtès2017-04-14T14:45:00Z2017-04-14T14:45:00Z At FOSDEM, in the awesome
Guile track , I
briefly demoed a new experimental GuixSD feature as part my
talk on system services :
the ability to run system services in containers or “sandboxes”. This
post discusses the rationale, status, and implementation of this
feature. The problem Our computers run many programs that talk to the Internet, and the
Internet is an unsafe place as we all know—with states and assorted
organizations
collecting “zero-day exploits”
to exploit them as they see fit. One of the big tasks of operating
system distributions has been to keep track of known software
vulnerabilities and patch…<p>At FOSDEM, in the awesome
<a href="https://fosdem.org/2017/schedule/track/gnu_guile/">Guile track</a>, I
briefly demoed a new experimental GuixSD feature as part my
<a href="https://fosdem.org/2017/schedule/event/composingsystemservicesinguixsd/">talk on system services</a>:
the ability to run system services in containers or “sandboxes”. This
post discusses the rationale, status, and implementation of this
feature.</p><h4>The problem</h4><p>Our computers run many programs that talk to the Internet, and the
Internet is an unsafe place as we all know—with states and assorted
organizations
<a href="https://www.wired.com/2014/04/obama-zero-day/">collecting “zero-day exploits”</a>
to exploit them as they see fit. One of the big tasks of operating
system distributions has been to keep track of known software
vulnerabilities and patch their packages as soon as possible.</p><p>When we look closer, many vulnerabilities out there can be exploited
because of a combination of two major weaknesses of GNU/Linux and
similar Unix-like operating systems: lack of memory-safety in the C
language family, and
<a href="https://en.wikipedia.org/wiki/Ambient_authority">ambient authority</a> in
the operating system itself. The former leads to a huge class of bugs
that become security issues: buffer overflows, use-after-free, and so
on. The latter makes them more exploitable because processes have
access to many resources beyond those they really need.</p><p>Security-sensitive software is now increasingly written in memory-safe
languages, as is the case for Guix and GuixSD. Projects that have been
using C are even considering a complete rewrite,
<a href="https://lists.torproject.org/pipermail/tor-dev/2017-March/012088.html">as is the case for Tor</a>.
Of course the switch away from memory-unsafe languages won’t happen
overnight, but it’s good to see a consensus emerging.</p><p>The operating system side of things is less bright. Although the
<a href="https://en.wikipedia.org/wiki/Principle_of_least_authority">principle of least authority (POLA)</a>
has been well-known in operating system circles for a long time, it
remains foreign to Unix and GNU/Linux. Processes run with the full
authority of their user. On top of that, until recent changes to the
Linux kernel, resources were global and there was essentially a single
view of the file system, of the process hierarchy, and so on. So when a
remote-code-execution vulnerability affects a system service—like
<a href="https://bugs.bitlbee.org/ticket/1281">in the BitlBee instant messaging gateway (CVE-2016-10188)</a>
running on my laptop—an attacker could potentially do a lot on your
machine.</p><p>Fortunately, many daemons have built-in mechanisms to work around this
operating system defect. For instance,
<a href="https://github.com/bitlbee/bitlbee/blob/master/unix.c#L155">BitlBee</a>,
and
<a href="https://gitweb.torproject.org/tor.git/tree/src/or/config.c#n1338">Tor</a>
can be told to switch to a separate unprivileged user,
<a href="https://github.com/lathiat/avahi/blob/master/avahi-daemon/chroot.c"><code>avahi-daemon</code></a>
and
<a href="https://github.com/ntp-project/ntp/blob/stable/ntpd/ntpd.c#L1000"><code>ntpd</code></a>
can do that and also change root. These techniques do reduce the
privileges of those processes, but they are still imperfect and <em>ad
hoc</em>.</p><h4>Increasing process isolation with containers</h4><p>The optimal solution to this problem would be to honor POLA in the first
place. As an example, the venerable GNU/Hurd is a
<a href="https://en.wikipedia.org/wiki/Capability-based_security">capability-based operating system</a>.
Thus, GNU/Hurd has supported fine-grained virtualization from the start:
a newly-created process can be given a capability to its own <code>proc</code>
server (which implements the POSIX notion of processes), to a specific
TCP/IP server, etc. In addition, its POSIX personality offers
interesting extensions, such as the fact that processes run with the
authority of
<a href="https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/mach/hurd/getuid.c;h=ff95fd58b8a9819fd0525d42ed8c3d85dbb6cb99;hb=HEAD#l42"><em>zero</em></a>
or more UIDs. For instance, the Hurd’s
<a href="https://git.savannah.gnu.org/cgit/hurd/hurd.git/tree/utils/login.c"><code>login</code> program</a>
starts off with zero UIDs and gains a UID when someone has been
authenticated.</p><p>Back to GNU/Linux,
<a href="http://man7.org/linux/man-pages/man7/namespaces.7.html">“namespaces”</a>
have been introduced as a way to retrofit per-process views of the
system resources, and thus improve isolation among processes. Each
process can run in a separate namespace and thus have a different view
of the file system, process tree, and so on (a process running in
separate namespaces is often referred to as a “container”, although that
term is sometimes used to denote much larger tooling and practices built
around namespaces.) Why not use that to better isolate system services?</p><p>Apparently this idea has been floating around. systemd has been
<a href="https://lwn.net/Articles/706025/">considering to extend its “unit files”</a>
to include directives instructing systemd to run daemons in separate
namespaces. GuixSD uses
<a href="https://www.gnu.org/software/shepherd">the Shepherd</a> instead of
systemd, but running system services in separate namespaces is something
we had been considering for a while.</p><p>In fact, adding the ability to run system services in containers was a
low-hanging fruit: we already had
<a href="https://www.gnu.org/software/guix/news/container-provisioning-with-guix.html"><code>call-with-container</code></a>
to run code in containers, so all we needed to do was to
<a href="https://git.savannah.gnu.org/cgit/guix.git/commit/?id=63302a4e55241a41eab4c21d7af9fbd0d5817459">provide a containerized service starter</a>
that uses <code>call-with-container</code>.</p><p>The Shepherd itself remains unaware of namespaces, it simply ends up
calling
<a href="https://git.savannah.gnu.org/cgit/guix.git/tree/gnu/build/shepherd.scm#n108"><code>make-forkexec-constructor/container</code></a>
instead of
<a href="https://www.gnu.org/software/shepherd/manual/en/html_node/Service-De_002d-and-Constructors.html#index-make_002dforkexec_002dconstructor"><code>make-forkexec-constructor</code></a>
and that’s it. The changes to the service definitions of
<a href="https://git.savannah.gnu.org/cgit/guix.git/commit/?id=a062b6ca99ad61c9df473fe49a93d69f9698c59d">BitlBee</a>
and
<a href="https://git.savannah.gnu.org/cgit/guix.git/commit/?id=ee295346ce81c276ffb4ee34cc6f5b134b415097">Tor</a>
are minimal. The end result, for Tor, looks like this:</p><pre><code class="language-scheme">(let ((torrc (tor-configuration->torrc config)))
(with-imported-modules (source-module-closure
'((gnu build shepherd)
(gnu system file-systems)))
(list (shepherd-service
(provision '(tor))
(requirement '(user-processes loopback syslogd))
(modules '((gnu build shepherd)
(gnu system file-systems)))
(start #~(make-forkexec-constructor/container
(list #$(file-append tor "/bin/tor") "-f" #$torrc)
#:mappings (list (file-system-mapping
(source "/var/lib/tor")
(target source)
(writable? #t))
(file-system-mapping
(source "/dev/log") ;for syslog
(target source)))))
(stop #~(make-kill-destructor))
(documentation "Run the Tor anonymous network overlay.")))))</code></pre><p>The
<a href="https://www.gnu.org/software/guix/manual/en/html_node/G_002dExpressions.html#index-with_002dimported_002dmodules"><code>with-imported-modules</code></a>
form above instructs Guix to <em>import</em> our <code>(gnu build shepherd)</code>
library, which provides <code>make-forkexec-constructor/container</code>, into
PID 1. The <code>start</code> method of the service specifies the command to start
the daemon, as well as file systems to map in its mount name space
(“bind mounts”). Here all we need is write access to <code>/var/lib/tor</code> and
to <code>/dev/log</code> (for logging <em>via</em> syslogd). In addition to these two
mappings, <code>make-forkexec-constructor/container</code> automatically adds
<code>/gnu/store</code> and a bunch of files in <code>/etc</code> as we will see below.</p><h4>Containerized services in action</h4><p>So what do these containerized services look like when they’re running?
When we run
<a href="https://www.gnu.org/software/shepherd/manual/en/html_node/Invoking-herd.html"><code>herd status bitblee</code></a>,
disappointingly, we don’t see anything special:</p><pre><code>charlie@guixsd ~$ sudo herd status bitlbee
Status of bitlbee:
It is started.
Running value is 487.
It is enabled.
Provides (bitlbee).
Requires (user-processes networking).
Conflicts with ().
Will be respawned.
charlie@guixsd ~$ ps -f 487
UID PID PPID C STIME TTY STAT TIME CMD
bitlbee 487 1 0 Apr11 ? Ss 0:00 /gnu/store/pm05bfywrj2k699qbxpjjqfyfk3grz2i-bitlbee-3.5.1/sbin/bitlbee -n -F -u bitlbee -c /gnu/store/y4jfxya56i1hl9z0a2h4hdar2wm</code></pre><p>Again this is because the Shepherd has no idea what a namespace is, so
it just displays the daemon’s PID in the global namespace, <code>487</code>. The
process is running as user <code>bitlbee</code>, as requested by the <code>-u bitlbee</code>
command-line option.</p><p>We can invoke
<a href="http://man7.org/linux/man-pages/man1/nsenter.1.html"><code>nsenter</code></a> and
take a look at what the BitlBee process “sees” in its namespace:</p><pre><code>charlie@guixsd ~$ sudo nsenter -t 487 -m -p -i -u $(readlink -f $(type -P bash))
root@guixsd /# echo /*
/dev /etc /gnu /proc /tmp /var
root@guixsd /# echo /proc/[0-9]*
/proc/1 /proc/5
root@guixsd /# read line < /proc/1/cmdline
root@guixsd /# echo $line
/gnu/store/pm05bfywrj2k699qbxpjjqfyfk3grz2i-bitlbee-3.5.1/sbin/bitlbee-n-F-ubitlbee-c/gnu/store/y4jfxya56i1hl9z0a2h4hdar2wmivgbl-bitlbee.conf
root@guixsd /# echo /etc/*
/etc/hosts /etc/nsswitch.conf /etc/passwd /etc/resolv.conf /etc/services
root@guixsd /# echo /var/*
/var/lib /var/run
root@guixsd /# echo /var/lib/*
/var/lib/bitlbee
root@guixsd /# echo /var/run/*
/var/run/bitlbee.pid /var/run/nscd</code></pre><p>There’s no <code>/home</code> and generally very little in BitlBee’s mount
namespace. Notably, the namespace lacks <code>/run/setuid-programs</code>, which
is where
<a href="https://www.gnu.org/software/guix/manual/en/html_node/Setuid-Programs.html">setuid programs</a>
live in GuixSD. Its <code>/etc</code> directory contains the minimal set of files
needed for proper operation rather than the complete <code>/etc</code> of the host.
<code>/var</code> contains nothing but BitlBee’s own state files, as well as the
socket to libc’s name service cache daemon (<code>nscd</code>), which runs in the
host system and performs name lookups on behalf of applications.</p><p>As can be seen in <code>/proc</code>, there’s only a couple of processes in there
and “PID 1” in that namespace is the <code>bitlbee</code> daemon. Finally, the
<code>/tmp</code> directory is a private tmpfs:</p><pre><code>root@guixsd /# : > /tmp/hello-bitlbee
root@guixsd /# echo /tmp/*
/tmp/hello-bitlbee
root@guixsd /# exit
charlie@guixsd ~$ ls /tmp/*bitlbee
ls: cannot access '/tmp/*bitlbee': No such file or directory</code></pre><p>Our <code>bitlbee</code> process runs in a separate mount, PID, and IPC namespace,
but it runs in the global user namespace. The reason for this is that
we want the <code>-u bitlbee</code> option (which instructs <code>bitlbee</code> to setuid to
an unprivileged user at startup) to work as expected. It also shares
the network namespace because obviously it needs to access the network.</p><p>A nice side-effect of these fully-specified execution environments for
services is that it makes them more likely to behave in a reproducible
fashion across machines—just like fully-specified build environments
<a href="https://www.gnu.org/software/guix/news/reproducible-builds-a-means-to-an-end.html">help achieve reproducible builds</a>.</p><h4>Conclusion</h4><p>GuixSD <code>master</code> and its upcoming release include this feature and a
couple of containerized services, and it works like a charm! Yet, there
are still open questions as to the way forward.</p><p>First, we only looked at “simple” services so far, with simple static
file system mappings. Good candidates for increased isolation are HTTP
servers such as NGINX. However, for these, it’s more difficult to
determine the set of file system mappings that must be made. GuixSD has
the advantage that it knows
<a href="https://www.gnu.org/software/guix/manual/en/html_node/Web-Services.html">how NGINX is configured</a>
and could potentially derive file system mappings from that information.
Getting it right may be trickier than it seems, though, so this is
something we’ll have to investigate.</p><p>Another open question is how the service isolation work should be split
between the distro, the init system, and the upstream service author.
Authors of daemons already do part of the work <em>via</em> <code>setuid</code> and
sometimes <code>chroot</code>. Going beyond that would often hamper portability
(the namespace interface is specific to the kernel Linux) or even
functionality if the daemon ends up lacking access to resources it
needs.</p><p>The init system alone also lacks information to decide what goes into
the namespaces of the service. For instance, neither the upstream
author nor the init system “knows” whether the distro is running <code>nscd</code>
and thus they cannot tell whether the <code>nscd</code> socket should be
bind-mounted in the service’s namespace. A similar issue is that of
D-Bus policy files discussed in
<a href="https://lwn.net/Articles/706025/">this LWN article</a>. Moving D-Bus
functionality into the init system itself to solve this problem, as the
article suggests, seems questionable, notably because it would add more
code to this critical process. Instead, on GuixSD, a service author can
make the right policy files available in the sandbox; in fact, GuixSD
already knows which policy files are needed thanks to its service
framework so we might even be able to automate it.</p><p>At this point it seems that tight integration between the distro and the
init system is the best way to precisely define system service
sandboxes. GuixSD’s
<a href="https://www.gnu.org/software/guix/manual/en/html_node/Using-the-Configuration-System.html#System-Services">declarative approach to system services</a>
along with tight Shepherd integration help a lot here, but it remains to
be seen how difficult it is to create sandboxes for complex system
services such as NGINX.</p><h4>About GNU Guix</h4><p><a href="https://www.gnu.org/software/guix">GNU Guix</a> is a transactional package
manager for the GNU system. The Guix System Distribution or GuixSD is
an advanced distribution of the GNU system that relies on GNU Guix and
<a href="https://www.gnu.org/distros/free-system-distribution-guidelines.html">respects the user's
freedom</a>.</p><p>In addition to standard package management features, Guix supports
transactional upgrades and roll-backs, unprivileged package management,
per-user profiles, and garbage collection. Guix uses low-level
mechanisms from the Nix package manager, except that packages are
defined as native <a href="https://www.gnu.org/software/guile">Guile</a> modules,
using extensions to the <a href="http://schemers.org">Scheme</a> language. GuixSD
offers a declarative approach to operating system configuration
management, and is highly customizable and hackable.</p><p>GuixSD can be used on an i686 or x86_64 machine. It is also possible to
use Guix on top of an already installed GNU/Linux system, including on
mips64el, armv7, and aarch64.</p>