Yesterday I decided to build snapd for CentOS 7. Originally titled the post
“… in ten minutes” but the process took more like an hour to complete as I
wanted to fix some rough edges I found along the way. One day later the
improvements and bug fixes I had made are merged upstream and I can tell my
story.
Preparations
All of the instructions that follow were done on a stock CentOS 7 installation,
running kernel 3.10.0-514.6.1.el7.x86_64.
Setting up GOPATH
Setting up GOPATH is a mandatory step necessary for working with Go source
code. Go uses the directory designated by this environment variable as a root
of a structure of directories with source code, object files and executables.
Typically this can be set in a shell start-up profile but for the sake of this experiment I just set it in the shell I was using.
export GOPATH=$HOME/go
The actual value doesn’t matter, I use ~/go as a convention but you can pick
something else.
Getting initial dependencies
Side note: I must say that the artwork in Gnome looks beautiful. While I was typing this in another computer the GNOME screen saver had kicked in and locked my session. The backdrop there is stunning!
Let’s install the usual suspects. We will need:
gitto get the source code from Githubgolangto build the Go parts of snapdautoconf,automake,pkg-config,makeandgccto build the C parts of snapd.
As you will see below the list is not complete should be sufficient to allow us
to get started and discover the rest. We can now use yum to install the
packages like this:
sudo yum install git golang autoconf automake pkg-config make gcc
Getting the source code
We cannot just clone the code anywhere. Go enforces a specific structure that
we must follow. The source code is underneath the src subdirectory of
$GOPATH, in a structure that mirrors the URL. Let’s clone the
https://github.com/snapcore/snapd repository into the right spot. We can also
change to that directory so that the rest of the commands are easier to type.
mkdir -p $GOPATH/src/github.com/snapcore
git clone https://github.com/snapcore/snapd $GOPATH/src/github.com/snapcore/snapd
cd $GOPATH/src/github.com/snapcore/snapd
We are now ready to run the get-deps.sh script. This script uses govendor
to download and bundle (vendor) all of the Go dependencies of snapd. It takes a
short while to run and puts everything into the vendor/ subdirectory.
Generating the version string
We are almost ready to build snapd but there’s one more step. We must run
the ./mkversion.sh script to compute the version that will be built into the
snapd executable. The script looks at the git commit identifier, tags and a few
other things.
./mkversion.sh
Generating the C build system
The C parts if snapd are built with autotools. Starting from the top of the
project change to the cmd directory and note the autogen.sh script. The
script generates the configure script and runs it with a set of options
appropriate for the given distribution.
We will now need to install a few extra build dependencies. I iterated by
running autogen.sh and searching for packages with yum search until nothing more was missing.
In the end I got this list:
xfsprogs-develfor some XFS-specific quota header filesglib2-develto build the test suite that usesg_test_...(formake check)libseccomp-develfor the seccomp part of the sandboxsystemd-develto get udev header and pkg-config filesglibc-staticto link the static shutdown helper (not needed here)python-docutilsto convert.rstfiles into manual pagesindentto check if all the C code is formatted uniformly (formake check)
The test suite can also use shellcheck and valgrind and will do so if they
are detected. You don’t have to install them though.
Let’s install all of them and run autogen.sh now:
sudo yum install xfsprogs-devel glib2-devel libseccomp-devel systemd-devel glibc-static python-docutils indent
./autogen.sh
We are now ready to build everything!
Building and installing
This is, by now, pretty easy. We will just use make && sudo make install. If
this were a real package you could follow all the right steps but I want to
show how easy it is to just build and run snapd by hand. I already spoiled the
fun but for the sake of completeness just run this command now:
make && sudo make install
The Go side of snapd is not much harder but it requires somewhat more
hand-holding. Because we have set up $GOPATH earlier we can build and install
everything with just one command.
go install github.com/snapcore/snapd/cmd/{snap,snapd,snap-exec,snapctl}
We’re not done yet, though. You can find that all of those executables got
installed to $GOPATH/bin. From there we need to move them to their correct
locations. For this I’ve decide to use the good, old-fashioned install
tool.
sudo install -m 0755 -o root -g root -D $GOPATH/bin/snap /usr/bin/
sudo install -m 0755 -o root -g root -D $GOPATH/bin/snap-exec /usr/libexec/snapd/
sudo install -m 0755 -o root -g root -D $GOPATH/bin/snapctl /usr/libexec/snapd/
sudo install -m 0755 -o root -g root -D $GOPATH/bin/snapd /usr/libexec/snapd/
The last part is a few miscellaneous files. Bash completion, the systemd unit
for snapd and an info file. The systemd unit has a reference to a Debian-style
lib directory that we can fix with sed.
sudo install -m 0644 -o root -g root -D $GOPATH/src/github.com/snapcore/snapd/data/info /usr/libexec/snapd/
sudo install -m 0644 -o root -g root -D $GOPATH/src/github.com/snapcore/snapd/data/completion/snap /usr/share/bash-completion/completions/
sudo install -m 0644 -o root -g root -D $GOPATH/src/github.com/snapcore/snapd/data/systemd/snapd.socket /lib/systemd/system/
sudo install -m 0644 -o root -g root -D $GOPATH/src/github.com/snapcore/snapd/data/systemd/snapd.service /lib/systemd/system/
sudo sed -i -e 's!/usr/lib/snapd/!/usr/libexec/snapd/!' /lib/systemd/system/snapd.service
I specifically ignored the part that adds /var/lib/snapd/snap/bin to PATH
as well to XDG_DATA_DIRS. This is somewhat thorny and I don’t know where
to do it exactly so that it is “right” (comments welcome!).
To use snaps on command line you will need to add that to your PATH manually.
export PATH=$PATH:/var/lib/snapd/snap/bin
We are now done with the installation.
Getting ready to run
Snapd has just a few runtime dependencies. Apart from systemd itself we need
squashfs-tools and the squashfs module inserted into the kernel. We also
need to start the snapd.socket unit.
sudo yum install squashfs-tools
sudo modprobe squashfs
sudo systemctl start snapd.socket
We’re done! Run snap version, snap list and snap install hello-world to
see for yourself that this is really working.
Trying our some snaps
Use snap install hugo and migrate your blog like I did. Then snap install
krita and paint something nice. You can put your new painting in a document if
you snap install libreoffice. In the evening snap install vlc and watch a
movie with your friends or family. In the end snap install
telegram-sergiusens and ping me to say hi :-)
PS: You may be tempted to try docker and lxd but I think they require quite
a more recent kernel version and thus won’t run on CentOS 7. Snaps cannot fix
that, sorry.