case study snapd on centos

6 minute read Published:

building snapd on centos in 10 minutes

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:

  • git to get the source code from Github
  • golang to build the Go parts of snapd
  • autoconf, automake, pkg-config, make and gcc to 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-devel for some XFS-specific quota header files
  • glib2-devel to build the test suite that uses g_test_... (for make check)
  • libseccomp-devel for the seccomp part of the sandbox
  • systemd-devel to get udev header and pkg-config files
  • glibc-static to link the static shutdown helper (not needed here)
  • python-docutils to convert .rst files into manual pages
  • indent to check if all the C code is formatted uniformly (for make 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.

comments powered by Disqus