Newer
Older
@cindex pinning, channels
@cindex replicating Guix
@cindex reproducibility, of Guix
The @command{guix pull --list-generations} output above shows precisely which
commits were used to build this instance of Guix. We can thus replicate it,
say, on another machine, by providing a channel specification in
@file{~/.config/guix/channels.scm} that is ``pinned'' to these commits:
;; Deploy specific commits of my channels of interest.
(list (channel
(name 'guix)
(url "https://git.savannah.gnu.org/git/guix.git")
(commit "6298c3ffd9654d3231a6f25390b056483e8f407c"))
(channel
(name 'variant-packages)
(url "https://example.org/variant-packages.git")
(commit "dd3df5e2c8818760a8fc0bd699e55d3b69fef2bb")))
@end lisp
Taylan Ulrich Bayırlı/Kammer
committed
The @command{guix describe --format=channels} command can even generate this
list of channels directly (@pxref{Invoking guix describe}). The resulting
file can be used with the -C options of @command{guix pull}
(@pxref{Invoking guix pull}) or @command{guix time-machine}
(@pxref{Invoking guix time-machine}).
Taylan Ulrich Bayırlı/Kammer
committed
At this point the two machines run the @emph{exact same Guix}, with access to
the @emph{exact same packages}. The output of @command{guix build gimp} on
one machine will be exactly the same, bit for bit, as the output of the same
command on the other machine. It also means both machines have access to all
the source code of Guix and, transitively, to all the source code of every
package it defines.
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
This gives you super powers, allowing you to track the provenance of binary
artifacts with very fine grain, and to reproduce software environments at
will---some sort of ``meta reproducibility'' capabilities, if you will.
@xref{Inferiors}, for another way to take advantage of these super powers.
@node Channel Authentication
@section Channel Authentication
@anchor{channel-authentication}
@cindex authentication, of channel code
The @command{guix pull} and @command{guix time-machine} commands
@dfn{authenticate} the code retrieved from channels: they make sure each
commit that is fetched is signed by an authorized developer. The goal
is to protect from unauthorized modifications to the channel that would
lead users to run malicious code.
As a user, you must provide a @dfn{channel introduction} in your
channels file so that Guix knows how to authenticate its first commit.
A channel specification, including its introduction, looks something
along these lines:
@lisp
(channel
(name 'some-channel)
(url "https://example.org/some-channel.git")
(introduction
(make-channel-introduction
"6f0d8cc0d88abb59c324b2990bfee2876016bb86"
(openpgp-fingerprint
"CABB A931 C0FF EEC6 900D 0CFB 090B 1199 3D9A EBB5"))))
@end lisp
The specification above shows the name and URL of the channel. The call
to @code{make-channel-introduction} above specifies that authentication
of this channel starts at commit @code{6f0d8cc@dots{}}, which is signed
by the OpenPGP key with fingerprint @code{CABB A931@dots{}}.
For the main channel, called @code{guix}, you automatically get that
information from your Guix installation. For other channels, include
the channel introduction provided by the channel authors in your
@file{channels.scm} file. Make sure you retrieve the channel
introduction from a trusted source since that is the root of your trust.
If you're curious about the authentication mechanics, read on!
@node Creating a Channel
@section Creating a Channel
@cindex personal packages (channels)
@cindex channels, for personal packages
Let's say you have a bunch of custom package variants or personal packages
that you think would make little sense to contribute to the Guix project, but
would like to have these packages transparently available to you at the
command line. You would first write modules containing those package
definitions (@pxref{Package Modules}), maintain them in a Git repository, and
then you and anyone else can use it as an additional channel to get packages
from. Neat, no?
@c What follows stems from discussions at
@c <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22629#134> as well as
@c earlier discussions on guix-devel@gnu.org.
@quotation Warning
Before you, dear user, shout---``woow this is @emph{soooo coool}!''---and
publish your personal channel to the world, we would like to share a few words
of caution:
@itemize
@item
Before publishing a channel, please consider contributing your package
definitions to Guix proper (@pxref{Contributing}). Guix as a project is open
to free software of all sorts, and packages in Guix proper are readily
available to all Guix users and benefit from the project's quality assurance
process.
@item
When you maintain package definitions outside Guix, we, Guix developers,
consider that @emph{the compatibility burden is on you}. Remember that
package modules and package definitions are just Scheme code that uses various
programming interfaces (APIs). We want to remain free to change these APIs to
keep improving Guix, possibly in ways that break your channel. We never
change APIs gratuitously, but we will @emph{not} commit to freezing APIs
either.
@item
Corollary: if you're using an external channel and that channel breaks, please
@emph{report the issue to the channel authors}, not to the Guix project.
@end itemize
You've been warned! Having said this, we believe external channels are a
practical way to exert your freedom to augment Guix' package collection and to
share your improvements, which are basic tenets of
@uref{https://www.gnu.org/philosophy/free-sw.html, free software}. Please
email us at @email{guix-devel@@gnu.org} if you'd like to discuss this.
@end quotation
To create a channel, create a Git repository containing your own package
modules and make it available. The repository can contain anything, but a
useful channel will contain Guile modules that export packages. Once you
start using a channel, Guix will behave as if the root directory of that
channel's Git repository has been added to the Guile load path (@pxref{Load
Paths,,, guile, GNU Guile Reference Manual}). For example, if your channel
contains a file at @file{my-packages/my-tools.scm} that defines a Guile
module, then the module will be available under the name @code{(my-packages
my-tools)}, and you will be able to use it like any other module
(@pxref{Modules,,, guile, GNU Guile Reference Manual}).
As a channel author, consider bundling authentication material with your
channel so that users can authenticate it. @xref{Channel
Authentication}, and @ref{Specifying Channel Authorizations}, for info
on how to do it.
@node Package Modules in a Sub-directory
@section Package Modules in a Sub-directory
@cindex subdirectory, channels
As a channel author, you may want to keep your channel modules in a
sub-directory. If your modules are in the sub-directory @file{guix}, you must
add a meta-data file @file{.guix-channel} that contains:
@lisp
(channel
(version 0)
(directory "guix"))
@end lisp
@node Declaring Channel Dependencies
@section Declaring Channel Dependencies
@cindex dependencies, channels
@cindex meta-data, channels
Channel authors may decide to augment a package collection provided by other
channels. They can declare their channel to be dependent on other channels in
a meta-data file @file{.guix-channel}, which is to be placed in the root of
the channel repository.
The meta-data file should contain a simple S-expression like this:
@lisp
(channel
(version 0)
(dependencies
(channel
(name 'some-collection)
(url "https://example.org/first-collection.git")
;; The 'introduction' bit below is optional: you would
;; provide it for dependencies that can be authenticated.
(introduction
(channel-introduction
(version 0)
(commit "a8883b58dc82e167c96506cf05095f37c2c2c6cd")
(signer "CABB A931 C0FF EEC6 900D 0CFB 090B 1199 3D9A EBB5"))))
(channel
(name 'some-other-collection)
(url "https://example.org/second-collection.git")
(branch "testing"))))
@end lisp
In the above example this channel is declared to depend on two other channels,
which will both be fetched automatically. The modules provided by the channel
will be compiled in an environment where the modules of all these declared
channels are available.
For the sake of reliability and maintainability, you should avoid dependencies
on channels that you don't control, and you should aim to keep the number of
dependencies to a minimum.
@node Specifying Channel Authorizations
@section Specifying Channel Authorizations
@cindex channel authorizations
@anchor{channel-authorizations}
As we saw above, Guix ensures the source code it pulls from channels
comes from authorized developers. As a channel author, you need to
specify the list of authorized developers in the
@file{.guix-authorizations} file in the channel's Git repository. The
authentication rule is simple: each commit must be signed by a key
listed in the @file{.guix-authorizations} file of its parent
commit(s)@footnote{Git commits form a @dfn{directed acyclic graph}
(DAG). Each commit can have zero or more parents; ``regular'' commits
have one parent and merge commits have two parent commits. Read
@uref{https://eagain.net/articles/git-for-computer-scientists/, @i{Git
for Computer Scientists}} for a great overview.} The
@file{.guix-authorizations} file looks like this:
@lisp
;; Example '.guix-authorizations' file.
(authorizations
(version 0) ;current file format version
(("AD17 A21E F8AE D8F1 CC02 DBD9 F8AE D8F1 765C 61E3"
(name "alice"))
("2A39 3FFF 68F4 EF7A 3D29 12AF 68F4 EF7A 22FB B2D5"
(name "bob"))
("CABB A931 C0FF EEC6 900D 0CFB 090B 1199 3D9A EBB5"
(name "charlie"))))
@end lisp
Each fingerprint is followed by optional key/value pairs, as in the
example above. Currently these key/value pairs are ignored.
This authentication rule creates a chicken-and-egg issue: how do we
authenticate the first commit? Related to that: how do we deal with
channels whose repository history contains unsigned commits and lack
@file{.guix-authorizations}? And how do we fork existing channels?
@cindex channel introduction
Channel introductions answer these questions by describing the first
commit of a channel that should be authenticated. The first time a
channel is fetched with @command{guix pull} or @command{guix
time-machine}, the command looks up the introductory commit and verifies
that it is signed by the specified OpenPGP key. From then on, it
authenticates commits according to the rule above.
Additionally, your channel must provide all the OpenPGP keys that were
ever mentioned in @file{.guix-authorizations}, stored as @file{.key}
files, which can be either binary or ``ASCII-armored''. By default,
those @file{.key} files are searched for in the branch named
@code{keyring} but you can specify a different branch name in
@code{.guix-channel} like so:
@lisp
(channel
(version 0)
(keyring-reference "my-keyring-branch"))
@end lisp
To summarize, as the author of a channel, there are three things you have
to do to allow users to authenticate your code:
@enumerate
@item
Export the OpenPGP keys of past and present committers with @command{gpg
--export} and store them in @file{.key} files, by default in a branch
named @code{keyring} (we recommend making it an @dfn{orphan branch}).
@item
Introduce an initial @file{.guix-authorizations} in the channel's
repository. Do that in a signed commit (@pxref{Commit Access}, for
information on how to sign Git commits.)
@item
Advertise the channel introduction, for instance on your channel's web
page. The channel introduction, as we saw above, is the commit/key
pair---i.e., the commit that introduced @file{.guix-authorizations}, and
the fingerprint of the OpenPGP used to sign it.
@end enumerate
Before pushing to your public Git repository, you can run @command{guix
git-authenticate} to verify that you did sign all the commits you are
about to push with an authorized key:
@example
guix git authenticate @var{commit} @var{signer}
@end example
@noindent
where @var{commit} and @var{signer} are your channel introduction.
@xref{Invoking guix git authenticate}, for details.
Publishing a signed channel requires discipline: any mistake, such as an
unsigned commit or a commit signed by an unauthorized key, will prevent
users from pulling from your channel---well, that's the whole point of
authentication! Pay attention to merges in particular: merge commits
are considered authentic if and only if they are signed by a key present
in the @file{.guix-authorizations} file of @emph{both} branches.
@node Primary URL
@section Primary URL
@cindex primary URL, channels
Channel authors can indicate the primary URL of their channel's Git
repository in the @file{.guix-channel} file, like so:
@lisp
(channel
(version 0)
(url "https://example.org/guix.git"))
@end lisp
This allows @command{guix pull} to determine whether it is pulling code
from a mirror of the channel; when that is the case, it warns the user
that the mirror might be stale and displays the primary URL. That way,
users cannot be tricked into fetching code from a stale mirror that does
not receive security updates.
This feature only makes sense for authenticated repositories, such as
the official @code{guix} channel, for which @command{guix pull} ensures
the code it fetches is authentic.
@node Writing Channel News
@section Writing Channel News
@cindex news, for channels
Channel authors may occasionally want to communicate to their users
information about important changes in the channel. You'd send them all
an email, but that's not convenient.
Instead, channels can provide a @dfn{news file}; when the channel users
run @command{guix pull}, that news file is automatically read and
@command{guix pull --news} can display the announcements that correspond
to the new commits that have been pulled, if any.
To do that, channel authors must first declare the name of the news file
in their @file{.guix-channel} file:
@lisp
(channel
(version 0)
(news-file "etc/news.txt"))
@end lisp
The news file itself, @file{etc/news.txt} in this example, must look
something like this:
@lisp
(channel-news
(version 0)
(entry (tag "the-bug-fix")
(title (en "Fixed terrible bug")
(fr "Oh la la"))
(body (en "@@emph@{Good news@}! It's fixed!")
(eo "Certe ĝi pli bone funkcias nun!")))
(entry (commit "bdcabe815cd28144a2d2b4bc3c5057b051fa9906")
(title (en "Added a great package")
(ca "Què vol dir guix?"))
(body (en "Don't miss the @@code@{hello@} package!"))))
@end lisp
While the news file is using the Scheme syntax, avoid naming it with a
@file{.scm} extension or else it will get picked up when building the
channel and yield an error since it is not a valid module.
Alternatively, you can move the channel module to a subdirectory and
store the news file in another directory.
The file consists of a list of @dfn{news entries}. Each entry is
associated with a commit or tag: it describes changes made in this
commit, possibly in preceding commits as well. Users see entries only
the first time they obtain the commit the entry refers to.
The @code{title} field should be a one-line summary while @code{body}
can be arbitrarily long, and both can contain Texinfo markup
(@pxref{Overview,,, texinfo, GNU Texinfo}). Both the title and body are
a list of language tag/message tuples, which allows @command{guix pull}
to display news in the language that corresponds to the user's locale.
If you want to translate news using a gettext-based workflow, you can
extract translatable strings with @command{xgettext} (@pxref{xgettext
Invocation,,, gettext, GNU Gettext Utilities}). For example, assuming
you write news entries in English first, the command below creates a PO
file containing the strings to translate:
xgettext -o news.po -l scheme -ken etc/news.txt
To sum up, yes, you could use your channel as a blog. But beware, this
is @emph{not quite} what your users might expect.
@c *********************************************************************
@node Development
@chapter Development
@cindex software development
If you are a software developer, Guix provides tools that you should find
helpful---independently of the language you're developing in. This is what
this chapter is about.
The @command{guix environment} command provides a convenient way to set up
@dfn{development environments} containing all the dependencies and tools
necessary to work on the software package of your choice. The @command{guix
pack} command allows you to create @dfn{application bundles} that can be
easily distributed to users who do not run Guix.
* Invoking guix environment:: Setting up development environments.
* Invoking guix pack:: Creating software bundles.
* The GCC toolchain:: Working with languages supported by GCC.
* Invoking guix git authenticate:: Authenticating Git repositories.
@end menu
@node Invoking guix environment
@section Invoking @command{guix environment}
@cindex reproducible build environments
@cindex development environments
@cindex @command{guix environment}
@cindex environment, package build environment
The purpose of @command{guix environment} is to assist hackers in
creating reproducible development environments without polluting their
package profile. The @command{guix environment} tool takes one or more
packages, builds all of their inputs, and creates a shell
environment to use them.
@example
guix environment @var{options} @var{package}@dots{}
@end example
The following example spawns a new shell set up for the development of
GNU@tie{}Guile:
@example
guix environment guile
@end example
If the needed dependencies are not built yet, @command{guix environment}
automatically builds them. The environment of the new shell is an
augmented version of the environment that @command{guix environment} was
run in. It contains the necessary search paths for building the given
package added to the existing environment variables. To create
a ``pure'' environment, in which the original environment variables have
been unset, use the @option{--pure} option@footnote{Users sometimes
wrongfully augment environment variables such as @env{PATH} in their
@file{~/.bashrc} file. As a consequence, when @command{guix
environment} launches it, Bash may read @file{~/.bashrc}, thereby
introducing ``impurities'' in these environment variables. It is an
error to define such environment variables in @file{.bashrc}; instead,
they should be defined in @file{.bash_profile}, which is sourced only by
log-in shells. @xref{Bash Startup Files,,, bash, The GNU Bash Reference
Manual}, for details on Bash start-up files.}.
@command{guix environment} defines the @env{GUIX_ENVIRONMENT}
variable in the shell it spawns; its value is the file name of the
profile of this environment. This allows users to, say, define a
specific prompt for development environments in their @file{.bashrc}
(@pxref{Bash Startup Files,,, bash, The GNU Bash Reference Manual}):
@example
if [ -n "$GUIX_ENVIRONMENT" ]
then
export PS1="\u@@\h \w [dev]\$ "
fi
@end example
@noindent
...@: or to browse the profile:
@example
$ ls "$GUIX_ENVIRONMENT/bin"
@end example
Additionally, more than one package may be specified, in which case the
union of the inputs for the given packages are used. For example, the
command below spawns a shell where all of the dependencies of both Guile
and Emacs are available:
guix environment guile emacs
@end example
Sometimes an interactive shell session is not desired. An arbitrary
command may be invoked by placing the @code{--} token to separate the
command from the rest of the arguments:
@example
guix environment guile -- make -j4
@end example
In other situations, it is more convenient to specify the list of
packages needed in the environment. For example, the following command
runs @command{python} from an environment containing Python@tie{}2.7 and
NumPy:
@example
guix environment --ad-hoc python2-numpy python-2.7 -- python
@end example
Furthermore, one might want the dependencies of a package and also some
additional packages that are not build-time or runtime dependencies, but
are useful when developing nonetheless. Because of this, the
@option{--ad-hoc} flag is positional. Packages appearing before
@option{--ad-hoc} are interpreted as packages whose dependencies will be
added to the environment. Packages appearing after are interpreted as
packages that will be added to the environment directly. For example,
the following command creates a Guix development environment that
additionally includes Git and strace:
Danny Milosavljevic
committed
guix environment --pure guix --ad-hoc git strace
Sometimes it is desirable to isolate the environment as much as
possible, for maximal purity and reproducibility. In particular, when
using Guix on a host distro that is not Guix System, it is desirable to
prevent access to @file{/usr/bin} and other system-wide resources from
the development environment. For example, the following command spawns
a Guile REPL in a ``container'' where only the store and the current
working directory are mounted:
@example
guix environment --ad-hoc --container guile -- guile
@end example
The @option{--container} option requires Linux-libre 3.19 or newer.
@cindex certificates
Another typical use case for containers is to run security-sensitive
applications such as a web browser. To run Eolie, we must expose and
share some files and directories; we include @code{nss-certs} and expose
@file{/etc/ssl/certs/} for HTTPS authentication; finally we preserve the
@env{DISPLAY} environment variable since containerized graphical
applications won't display without it.
@example
guix environment --preserve='^DISPLAY$' --container --network \
--expose=/etc/machine-id \
--expose=/etc/ssl/certs/ \
--share=$HOME/.local/share/eolie/=$HOME/.local/share/eolie/ \
--ad-hoc eolie nss-certs dbus -- eolie
@end example
The available options are summarized below.
@table @code
@item --root=@var{file}
@itemx -r @var{file}
@cindex persistent environment
@cindex garbage collector root, for environments
Make @var{file} a symlink to the profile for this environment, and
register it as a garbage collector root.
This is useful if you want to protect your environment from garbage
collection, to make it ``persistent''.
When this option is omitted, the environment is protected from garbage
collection only for the duration of the @command{guix environment}
session. This means that next time you recreate the same environment,
you could have to rebuild or re-download packages. @xref{Invoking guix
gc}, for more on GC roots.
@item --expression=@var{expr}
@itemx -e @var{expr}
Create an environment for the package or list of packages that
@var{expr} evaluates to.
@example
guix environment -e '(@@ (gnu packages maths) petsc-openmpi)'
@end example
starts a shell with the environment for this specific variant of the
PETSc package.
@example
guix environment --ad-hoc -e '(@@ (gnu) %base-packages)'
@end example
starts a shell with all the base system packages available.
The above commands only use the default output of the given packages.
To select other outputs, two element tuples can be specified:
@example
guix environment --ad-hoc -e '(list (@@ (gnu packages bash) bash) "include")'
@end example
@item --load=@var{file}
@itemx -l @var{file}
Create an environment for the package or list of packages that the code
within @var{file} evaluates to.
As an example, @var{file} might contain a definition like this
(@pxref{Defining Packages}):
@verbatiminclude environment-gdb.scm
@item --manifest=@var{file}
@itemx -m @var{file}
Create an environment for the packages contained in the manifest object
returned by the Scheme code in @var{file}. This option can be repeated
several times, in which case the manifests are concatenated.
This is similar to the same-named option in @command{guix package}
(@pxref{profile-manifest, @option{--manifest}}) and uses the same
manifest files.
@item --ad-hoc
Include all specified packages in the resulting environment, as if an
@i{ad hoc} package were defined with them as inputs. This option is
useful for quickly creating an environment without having to write a
package expression to contain the desired inputs.
guix environment --ad-hoc guile guile-sdl -- guile
@end example
runs @command{guile} in an environment where Guile and Guile-SDL are
available.
Note that this example implicitly asks for the default output of
@code{guile} and @code{guile-sdl}, but it is possible to ask for a
specific output---e.g., @code{glib:bin} asks for the @code{bin} output
of @code{glib} (@pxref{Packages with Multiple Outputs}).
This option may be composed with the default behavior of @command{guix
environment}. Packages appearing before @option{--ad-hoc} are
interpreted as packages whose dependencies will be added to the
environment, the default behavior. Packages appearing after are
interpreted as packages that will be added to the environment directly.
Unset existing environment variables when building the new environment, except
those specified with @option{--preserve} (see below). This has the effect of
creating an environment in which search paths only contain package inputs.
@item --preserve=@var{regexp}
@itemx -E @var{regexp}
When used alongside @option{--pure}, preserve the environment variables
matching @var{regexp}---in other words, put them on a ``white list'' of
environment variables that must be preserved. This option can be repeated
several times.
guix environment --pure --preserve=^SLURM --ad-hoc openmpi @dots{} \
-- mpirun @dots{}
@end example
This example runs @command{mpirun} in a context where the only environment
variables defined are @env{PATH}, environment variables whose name starts
with @samp{SLURM}, as well as the usual ``precious'' variables (@env{HOME},
@item --search-paths
Display the environment variable definitions that make up the
environment.
@item --system=@var{system}
@itemx -s @var{system}
Attempt to build for @var{system}---e.g., @code{i686-linux}.
@item --container
@itemx -C
@cindex container
Run @var{command} within an isolated container. The current working
directory outside the container is mapped inside the container.
Additionally, unless overridden with @option{--user}, a dummy home
directory is created that matches the current user's home directory, and
@file{/etc/passwd} is configured accordingly.
The spawned process runs as the current user outside the container. Inside
the container, it has the same UID and GID as the current user, unless
@item --network
@itemx -N
For containers, share the network namespace with the host system.
Containers created without this flag only have access to the loopback
device.
@item --link-profile
@itemx -P
For containers, link the environment profile to @file{~/.guix-profile}
Ludovic Courtès
committed
within the container and set @code{GUIX_ENVIRONMENT} to that.
This is equivalent to making @file{~/.guix-profile} a symlink to the
actual profile within the container.
Linking will fail and abort the environment if the directory already
exists, which will certainly be the case if @command{guix environment}
was invoked in the user's home directory.
Certain packages are configured to look in @file{~/.guix-profile} for
configuration files and data;@footnote{For example, the
@code{fontconfig} package inspects @file{~/.guix-profile/share/fonts}
for additional fonts.} @option{--link-profile} allows these programs to
behave as expected within the environment.
@item --user=@var{user}
@itemx -u @var{user}
For containers, use the username @var{user} in place of the current
user. The generated @file{/etc/passwd} entry within the container will
contain the name @var{user}, the home directory will be
@file{/home/@var{user}}, and no user GECOS data will be copied. Furthermore,
the UID and GID inside the container are 1000. @var{user}
Additionally, any shared or exposed path (see @option{--share} and
@option{--expose} respectively) whose target is within the current user's
home directory will be remapped relative to @file{/home/USER}; this
includes the automatic mapping of the current working directory.
@example
# will expose paths as /home/foo/wd, /home/foo/test, and /home/foo/target
cd $HOME/wd
guix environment --container --user=foo \
--expose=$HOME/test \
--expose=/tmp/target=$HOME/target
@end example
While this will limit the leaking of user identity through home paths
and each of the user fields, this is only one useful component of a
broader privacy/anonymity solution---not one in and of itself.
@item --no-cwd
For containers, the default behavior is to share the current working
directory with the isolated container and immediately change to that
directory within the container. If this is undesirable,
@option{--no-cwd} will cause the current working directory to @emph{not}
be automatically shared and will change to the user's home directory
within the container instead. See also @option{--user}.
@item --expose=@var{source}[=@var{target}]
@itemx --share=@var{source}[=@var{target}]
For containers, @option{--expose} (resp. @option{--share}) exposes the
file system @var{source} from the host system as the read-only
(resp. writable) file system @var{target} within the container. If
@var{target} is not specified, @var{source} is used as the target mount
point in the container.
The example below spawns a Guile REPL in a container in which the user's
home directory is accessible read-only via the @file{/exchange}
directory:
@example
guix environment --container --expose=$HOME=/exchange --ad-hoc guile -- guile
@end example
@command{guix environment}
also supports all of the common build options that @command{guix
build} supports (@pxref{Common Build Options}) as well as package
transformation options (@pxref{Package Transformation Options}).
@node Invoking guix pack
@section Invoking @command{guix pack}
Occasionally you want to pass software to people who are not (yet!)
lucky enough to be using Guix. You'd tell them to run @command{guix
package -i @var{something}}, but that's not possible in this case. This
is where @command{guix pack} comes in.
@quotation Note
If you are looking for ways to exchange binaries among machines that
already run Guix, @pxref{Invoking guix copy}, @ref{Invoking guix
publish}, and @ref{Invoking guix archive}.
@end quotation
@cindex pack
@cindex bundle
@cindex application bundle
@cindex software bundle
The @command{guix pack} command creates a shrink-wrapped @dfn{pack} or
@dfn{software bundle}: it creates a tarball or some other archive
containing the binaries of the software you're interested in, and all
its dependencies. The resulting archive can be used on any machine that
does not have Guix, and people can run the exact same binaries as those
you have with Guix. The pack itself is created in a bit-reproducible
fashion, so anyone can verify that it really contains the build results
that you pretend to be shipping.
For example, to create a bundle containing Guile, Emacs, Geiser, and all
their dependencies, you can run:
@example
$ guix pack guile emacs geiser
@dots{}
/gnu/store/@dots{}-pack.tar.gz
@end example
The result here is a tarball containing a @file{/gnu/store} directory
with all the relevant packages. The resulting tarball contains a
@dfn{profile} with the three packages of interest; the profile is the
same as would be created by @command{guix package -i}. It is this
mechanism that is used to create Guix's own standalone binary tarball
(@pxref{Binary Installation}).
Users of this pack would have to run
@file{/gnu/store/@dots{}-profile/bin/guile} to run Guile, which you may
find inconvenient. To work around it, you can create, say, a
@file{/opt/gnu/bin} symlink to the profile:
@example
guix pack -S /opt/gnu/bin=bin guile emacs geiser
@end example
@noindent
That way, users can happily type @file{/opt/gnu/bin/guile} and enjoy.
@cindex relocatable binaries, with @command{guix pack}
What if the recipient of your pack does not have root privileges on
their machine, and thus cannot unpack it in the root file system? In
that case, you will want to use the @option{--relocatable} option (see
below). This option produces @dfn{relocatable binaries}, meaning they
they can be placed anywhere in the file system hierarchy: in the example
above, users can unpack your tarball in their home directory and
directly run @file{./opt/gnu/bin/guile}.
@cindex Docker, build an image with guix pack
Alternatively, you can produce a pack in the Docker image format using
the following command:
guix pack -f docker -S /bin=bin guile guile-readline
@noindent
The result is a tarball that can be passed to the @command{docker load}
command, followed by @code{docker run}:
@example
docker load < @var{file}
docker run -ti guile-guile-readline /bin/guile
@end example
@noindent
where @var{file} is the image returned by @var{guix pack}, and
@code{guile-guile-readline} is its ``image tag''. See the
@uref{https://docs.docker.com/engine/reference/commandline/load/, Docker
documentation} for more information.
@cindex Singularity, build an image with guix pack
@cindex SquashFS, build an image with guix pack
Yet another option is to produce a SquashFS image with the following
command:
guix pack -f squashfs bash guile emacs geiser
@end example
@noindent
The result is a SquashFS file system image that can either be mounted or
directly be used as a file system container image with the
@uref{https://www.sylabs.io/docs/, Singularity container execution
environment}, using commands like @command{singularity shell} or
@command{singularity exec}.
Several command-line options allow you to customize your pack:
@table @code
@item --format=@var{format}
@itemx -f @var{format}
Produce a pack in the given @var{format}.
@table @code
@item tarball
This is the default format. It produces a tarball containing all the
specified binaries and symlinks.
@item docker
This produces a tarball that follows the
@uref{https://github.com/docker/docker/blob/master/image/spec/v1.2.md,
Docker Image Specification}. The ``repository name'' as it appears in
the output of the @command{docker images} command is computed from
package names passed on the command line or in the manifest file.
@item squashfs
This produces a SquashFS image containing all the specified binaries and
symlinks, as well as empty mount points for virtual file systems like
procfs.
@quotation Note
Singularity @emph{requires} you to provide @file{/bin/sh} in the image.
For that reason, @command{guix pack -f squashfs} always implies @code{-S
/bin=bin}. Thus, your @command{guix pack} invocation must always start
with something like:
@example
guix pack -f squashfs bash @dots{}
@end example
If you forget the @code{bash} (or similar) package, @command{singularity
run} and @command{singularity exec} will fail with an unhelpful ``no
such file or directory'' message.
@end quotation
@cindex relocatable binaries
@item --relocatable
@itemx -R
Produce @dfn{relocatable binaries}---i.e., binaries that can be placed
anywhere in the file system hierarchy and run from there.
When this option is passed once, the resulting binaries require support for
@dfn{user namespaces} in the kernel Linux; when passed
@emph{twice}@footnote{Here's a trick to memorize it: @code{-RR}, which adds
PRoot support, can be thought of as the abbreviation of ``Really
Relocatable''. Neat, isn't it?}, relocatable binaries fall to back to
other techniques if user namespaces are unavailable, and essentially
work anywhere---see below for the implications.
For example, if you create a pack containing Bash with:
guix pack -RR -S /mybin=bin bash
@noindent
...@: you can copy that pack to a machine that lacks Guix, and from your
home directory as a normal user, run:
@example
tar xf pack.tar.gz
./mybin/sh
@end example
@noindent
In that shell, if you type @code{ls /gnu/store}, you'll notice that
@file{/gnu/store} shows up and contains all the dependencies of
@code{bash}, even though the machine actually lacks @file{/gnu/store}
altogether! That is probably the simplest way to deploy Guix-built
software on a non-Guix machine.
@quotation Note
By default, relocatable binaries rely on the @dfn{user namespace} feature of
the kernel Linux, which allows unprivileged users to mount or change root.
Old versions of Linux did not support it, and some GNU/Linux distributions
turn it off.
To produce relocatable binaries that work even in the absence of user
namespaces, pass @option{--relocatable} or @option{-R} @emph{twice}. In that
case, binaries will try user namespace support and fall back to another
@dfn{execution engine} if user namespaces are not supported. The
following execution engines are supported:
@table @code
@item default
Try user namespaces and fall back to PRoot if user namespaces are not
supported (see below).
@item performance
Try user namespaces and fall back to Fakechroot if user namespaces are
not supported (see below).
@item userns
Run the program through user namespaces and abort if they are not
supported.
@item proot
Run through PRoot. The @uref{https://proot-me.github.io/, PRoot} program
provides the necessary
support for file system virtualization. It achieves that by using the
@code{ptrace} system call on the running program. This approach has the
advantage to work without requiring special kernel support, but it incurs
run-time overhead every time a system call is made.
@item fakechroot
Run through Fakechroot. @uref{https://github.com/dex4er/fakechroot/,
Fakechroot} virtualizes file system accesses by intercepting calls to C
library functions such as @code{open}, @code{stat}, @code{exec}, and so
on. Unlike PRoot, it incurs very little overhead. However, it does not
always work: for example, some file system accesses made from within the
C library are not intercepted, and file system accesses made @i{via}
direct syscalls are not intercepted either, leading to erratic behavior.
@end table
@vindex GUIX_EXECUTION_ENGINE
When running a wrapped program, you can explicitly request one of the
execution engines listed above by setting the
@env{GUIX_EXECUTION_ENGINE} environment variable accordingly.