tag:blogger.com,1999:blog-65244634744077506082024-02-08T09:58:02.661-05:00random thoughts of a F/OSS Developer...Reinhard Tartlerhttp://www.blogger.com/profile/04887546547450531798noreply@blogger.comBlogger4125tag:blogger.com,1999:blog-6524463474407750608.post-47081654727868423462020-04-25T08:51:00.000-04:002020-04-25T08:57:43.805-04:00Building Packages with Buildah in Debian<div id="content">
<div id="table-of-contents">
<h2>
<span class="section-number-2">1</span> Building Debian Packages with buildah</h2>
</div>
<div class="outline-2" id="outline-container-orge6260e2">
<div class="outline-text-2" id="text-1">
Building packages in Debian seems to be a solved problem. But is it? At the bottom, installing the <code>dpkg-dev</code> package provides all the basic tools needed. Assuming that you already succeeded with creating the necessary packaging metadata (i.e., <code>debian/changelog</code>, <code>debian/control</code>, <code>debian/copyright</code>, etc., and there are great helper tools for this such ash <code>dh-make</code>, <code>dh-make-golang</code>, etc.,) it should be as simple as invoking the <code>dpkg-buildpackage</code> tool. So what's the big deal here?<br />
<br />
The issue is that <code>dpkg-buildpackage</code> expects to be called with an appropriately setup <b>build context</b>, that is, it needs to be called in an environment that satisfies all build dependencies <b>on the system</b>. Let's say you are building a package for Debian <b>unstable</b> on your Debian <b>stable</b> system (this is the common scenario for the official Debian build machines), you would need your build to link against libraries in <b>unstable</b>, not <b>stable</b>. So how to tell the package build process where to find its dependencies?<br />
<br />
The answer (in Debian and many other Linux distributions) is you do not at all. This is actually a somewhat surprising answer for software developers without a Linux distribution development background<sup><a class="footref" href="https://www.blogger.com/blogger.g?blogID=6524463474407750608#fn.1" id="fnr.1">1</a></sup>. Instead, chroots "simulate" an environment that has all dependencies that we want to build against at the <b>system</b> locations, that is. <code>/usr/lib</code>, etc.<br />
<br />
Chroots are basically full system installations in a subdirectory that includes system and application libraries. In order to use them, a package build needs to use the <code>chroot(2)</code> system call, which is a privileged operation. Also creating these system installations is a somewhat finicky process. In Debian, we have tools that make this process easier, the most popular ones are probably <code>pbuilder(1)</code><sup><a class="footref" href="https://www.blogger.com/blogger.g?blogID=6524463474407750608#fn.2" id="fnr.2">2</a></sup> and <code>sbuild(1)</code><sup><a class="footref" href="https://www.blogger.com/blogger.g?blogID=6524463474407750608#fn.3" id="fnr.3">3</a></sup>. Still, they are somewhat clumsy to use, add significant levels of abstraction in the sense that they do quite a bit of magic behind the scenes to work hide the fact that privileged operations (need root to run <code>chroot(2)</code>, etc.) are required. They are also somewhat brittle, for instance, if a build process is aborted (SIGKILL, or system crash), you may end up with temporary directories and files under userids other than your own that again may require root-privileges to cleanup.<br />
<br />
What if there was an easy way to do all of the above without any process running as root? Enter <b>rootless</b> <b>buildah</b>.<br />
<br />
Modern Linux container technologies allow unprivileged users to "untie" a process from the system (cf. the <code>unshare(2)</code> system call). This means that a regular user may run a process (and its child processes) in an "environment" where system calls behave differently and provide a configurable amount of isolation levels. This article demonstrates a novel build tool <code>buildah</code>, which is:<br />
<ul class="org-ul">
<li>easy to setup build environment from the command line</li>
<li>secure, as no process needs to run as root</li>
<li>simple in architecture, requires no running daemon like for example docker</li>
<li>convenient to use: you can debug your debian/rules interactively</li>
</ul>
Architecturally, <code>buildah</code> is written in golang and compiled as a (mostly) statically linked executable. It builds on top a number of libraries written in golang, including github.com/containers/storage and github.com/containers/image. The overlay functionality is provided by the <code>fuse-overlayfs(1)</code> utility.</div>
<div class="outline-3" id="outline-container-orgb0723c9">
<h3 id="orgb0723c9">
<span class="section-number-3">1.1</span> Preparation:</h3>
<div class="outline-text-3" id="text-1-1">
The Kernel in Debian bullseye (and in buster, and recent Ubuntu kernels to the best of my knowledge) do support usernamespaces, but leave them disabled by default. Here is how to enable them:<br />
<pre class="example" style="border: 1px solid rgb(204, 204, 204); box-shadow: rgb(238, 238, 238) 3px 3px 3px; margin: 1.2em; overflow: auto; padding: 8pt;">echo kernel.unprivileged_userns_clone = 1 | sudo tee -a /etc/sysctl.d/containers.conf
systemctl -p /etc/sysctl.d/containers.conf
</pre>
I have to admit that I'm not entirely sure why the Debian kernels don't enable usernamespaces by default. I've found a reference on stackexchange<sup><a class="footref" href="https://www.blogger.com/blogger.g?blogID=6524463474407750608#fn.4" id="fnr.4">4</a></sup> that claims this disables some "hardening" features in the Debian kernel. I also understand this step is not necessary if you chose to compile and run a vanilla upstream kernel. I'd appreciate a better reference and am happy to update this text.<br />
<pre class="example" style="border: 1px solid rgb(204, 204, 204); box-shadow: rgb(238, 238, 238) 3px 3px 3px; margin: 1.2em; overflow: auto; padding: 8pt;">$ c=$(buildah from docker.io/debian:sid)
Getting image source signatures
Copying blob 2bbc6b8c460d done
Copying config 9b90abe801 done
Writing manifest to image destination
Storing signatures
</pre>
This command downloads the image from docker.io and stores it locally in your home directory. Let's install essential utilities for building Debian packages:<br />
<div class="org-src-container">
<pre class="src src-bash" style="border: 1px solid rgb(204, 204, 204); box-shadow: rgb(238, 238, 238) 3px 3px 3px; margin: 1.2em; overflow: visible; padding: 1.2em 8pt 8pt; position: relative;"><span class="linenr" style="font-size: smaller;">1: </span>buildah run $<span style="color: #c5c8c6;">c</span> apt-get update -qq
<span class="linenr" style="font-size: smaller;">2: </span>buildah run $<span style="color: #c5c8c6;">c</span> apt-get install dpkg-dev -y
<span class="linenr" style="font-size: smaller;">3: </span>buildah config --workingdir /src $<span style="color: #c5c8c6;">c</span>
<span class="linenr" style="font-size: smaller;">4: </span>buildah commit $<span style="color: #c5c8c6;">c</span> dpkg-dev
</pre>
</div>
The command on line 1 and 2 execute the installation of compilers and dpkg development tools such as <code>dpkg-buildpackage</code>, etc. The <code>buildah config</code> command in line 4 arranges that whenever you start a shell in the container, the current working directory in the container is in <code>/src</code>. Don't worry about this location not existing yet, we will make sources from your host system available there. The last command creates an OCI image with the name <code>dpkg-dev</code>. BTW, the name you use for the image in the <code>commit</code> command can be used in podman (but not the "containers"). See <sup><a class="footref" href="https://www.blogger.com/blogger.g?blogID=6524463474407750608#fn.5" id="fnr.5">5</a></sup> and <sup><a class="footref" href="https://www.blogger.com/blogger.g?blogID=6524463474407750608#fn.6" id="fnr.6">6</a></sup> for a comparison between podman and buildah.<br />
<div class="org-src-container">
<pre class="src src-bash" style="border: 1px solid rgb(204, 204, 204); box-shadow: rgb(238, 238, 238) 3px 3px 3px; margin: 1.2em; overflow: visible; padding: 1.2em 8pt 8pt; position: relative;">buildah images -a
</pre>
</div>
This output might look like this:<br />
<pre class="example" style="border: 1px solid rgb(204, 204, 204); box-shadow: rgb(238, 238, 238) 3px 3px 3px; margin: 1.2em; overflow: auto; padding: 8pt;">| REPOSITORY | TAG | IMAGE | ID | CREATED | SIZE | | |
| localhost/dpkg-dev | latest | b85c34f95d3e | 16 | seconds | ago | 406 | MB |
| docker.io/library/debian | sid | 9b90abe801db | 11 | hours | ago | 124 | MB |
</pre>
</div>
</div>
<div class="outline-3" id="outline-container-org73a9ce7">
<h3 id="org73a9ce7">
<span class="section-number-3">1.2</span> Running a package build</h3>
<div class="outline-text-3" id="text-1-2">
Now we have a working container with the reference in the variable <code>$c</code>. To use it conveniently with source packages that I have stored in <code>/srv/scratch/packages/containers</code>, let's introduce a shell alias <code>r</code> like this:<br />
<pre class="example" style="border: 1px solid rgb(204, 204, 204); box-shadow: rgb(238, 238, 238) 3px 3px 3px; margin: 1.2em; overflow: auto; padding: 8pt;">alias r='buildah run --tty -v /srv/scratch/packages/containers:/src $c '
</pre>
This allows you to easily execute commands in that container:<br />
<pre class="example" style="border: 1px solid rgb(204, 204, 204); box-shadow: rgb(238, 238, 238) 3px 3px 3px; margin: 1.2em; overflow: auto; padding: 8pt;">r pwd
r bash
</pre>
The last command will give you an interactive shell that we'll be using for building packages!<br />
<pre class="example" style="border: 1px solid rgb(204, 204, 204); box-shadow: rgb(238, 238, 238) 3px 3px 3px; margin: 1.2em; overflow: auto; padding: 8pt;">siretart@x1:~/scratch/packages/containers/libpod$ r bash
root@x1:/src# cd golang-github-openshift-imagebuilder
root@x1:/src/golang-github-openshift-imagebuilder# dpkg-checkbuilddeps
dpkg-checkbuilddeps: error: Unmet build dependencies: debhelper (>= 11) dh-golang golang-any golang-github-containers-storage-dev (>= 1.11) golang-github-docker-docker-dev (>= 18.09.3+dfsg1) golang-github-fsouza-go-dockerclient-dev golang-glog-dev
root@x1:/src/golang-github-openshift-imagebuilder# apt-get build-dep -y .
Note, using directory '.' to get the build dependencies
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
[...]
root@x1:/src/golang-github-openshift-imagebuilder# dpkg-checkbuilddeps
root@x1:/src/golang-github-openshift-imagebuilder#
</pre>
Now we have a environment that has all build-dependencies available and we are ready to build the package:<br />
<pre class="example" style="border: 1px solid rgb(204, 204, 204); box-shadow: rgb(238, 238, 238) 3px 3px 3px; margin: 1.2em; overflow: auto; padding: 8pt;">root@x1:/src/golang-github-openshift-imagebuilder# dpkg-buildpackage -us -uc -b
</pre>
Assuming the package builds, the package build results are placed in <code>/src</code> inside the container, and are visible at ~/scratch/packages/containers on the host. There you can inspect, extract or even install them. The latter part allows you to interactively rebuild packages against updated dependencies, without the need of setting up an <code>apt</code> archive or similar.</div>
</div>
</div>
<div class="outline-2" id="outline-container-org70c3881">
<h2 id="org70c3881">
<span class="section-number-2">2</span> Availability</h2>
<div class="outline-text-2" id="text-2">
The <code>buildah(1)</code> tool is available in debian/bullseye since 2019-12-17. Since is a golang binary, it only links dynamically against system libraries such as libselinux and libseccomp, which are all available in buster-backports. I'd expect <code>buildah</code> to just work on a debian/buster system as well provided you install those system libraries and possibly the backported Linux kernel.<br />
<br />
Keeping the package at the latest upstream version is challenging because of its fast development pace that picks up new dependencies on golang libraries and new versions of existing libraries with every new upstream release. In general, this requires updating several source packages, and in many cases also uploading new source packages to the Debian archive that need to be processed by the Debian ftp-masters.<br />
<br />
As an exercise, I suggest to install the buildah package from bullseye, 'git clone' the packaging repository from <a href="https://salsa.debian.org/go-team/packages/golang-github-containers-buildah">https://salsa.debian.org/go-team/packages/golang-github-containers-buildah</a> and build the latest version yourself. Note, I would expect the above to even work on a Fedora laptop.<br />
<br />
The Debian packages have not swept into the Ubuntu distributions yet, but I expect them to be included in the Ubuntu 20.10 release. In the mean time, ubuntu users can install the package that are provided by the upstream maintainers in the "Project Atomic" PPA at <a href="https://launchpad.net/~projectatomic/+archive/ubuntu/ppa">https://launchpad.net/~projectatomic/+archive/ubuntu/ppa</a></div>
</div>
<div class="outline-2" id="outline-container-orgc769853">
<h2 id="orgc769853">
<span class="section-number-2">3</span> Related Tools</h2>
<div class="outline-text-2" id="text-3">
The <b>buildah</b> tool is accompanied with two "sister" tools:<br />
<br />
The <b>Skopeo</b> package provides tooling to work with remote images registries. This allows you download, upload images to remote registries, convert container images between different formats. It has been available in Debian since 2020-04-20.<br />
<br />
The <b>podman</b> tool is a 'docker' replacement. It provides a command-line interface that mimics the original <code>docker</code> command to an extend that a user familiar with docker might want to place this in their <code>~/.bashrc</code> file:<br />
<pre class="example" style="border: 1px solid rgb(204, 204, 204); box-shadow: rgb(238, 238, 238) 3px 3px 3px; margin: 1.2em; overflow: auto; padding: 8pt;">alias docker='podman'
</pre>
Unfortunately, at the time of writing podman is still being processed by the ftp-masters since 01-03-2020. At this point, I recommend building the package from our salsa repository at <a href="https://salsa.debian.org/debian/libpod">https://salsa.debian.org/debian/libpod</a></div>
</div>
<div class="outline-2" id="outline-container-org27752f1">
<h2 id="org27752f1">
<span class="section-number-2">4</span> Conclusion</h2>
<div class="outline-text-2" id="text-4">
Building packages in the right build context is a fairly technical issue for which many tools have been written for. They come with different trade-off when it comes to usability. Containers promise a secure alternative to the tried and proven chroot-based approaches, and the buildah makes using this technology very easy to use.<br />
<br />
I'd love to get into a conversation with you on how these tools work for you, and would like to encourage participation and assistance with keeping the complicated software stack up-to-date in Debian (and by extension, in derived distribution such as Ubuntu, etc.).</div>
</div>
<div id="footnotes">
<h2 class="footnotes">
Footnotes:</h2>
<div id="text-footnotes">
<div class="footdef" style="margin-bottom: 1em;">
<sup><a class="footnum" href="https://www.blogger.com/blogger.g?blogID=6524463474407750608#fnr.1" id="fn.1">1</a></sup><br />
<div class="footpara" style="display: inline;">
At my day-job, we build millions of lines of C++ code on Solaris10 and AIX6, where concepts such as "chroots" are restricted to the super user 'root' and is therefore not available to developers, not even through wrappers. Instead, libraries and headers are installed into "refroots", that is, subdirectories that mimic the structure of the "sysroot" directories that are used in the embedded Linux community for cross-compiling packages, and we use Makefiles that set include flags (<code>-I</code> rules and <code>-L</code> flags) to tell the compiler and linker where to look.</div>
</div>
<div class="footdef" style="margin-bottom: 1em;">
<sup><a class="footnum" href="https://www.blogger.com/blogger.g?blogID=6524463474407750608#fnr.2" id="fn.2">2</a></sup><br />
<div class="footpara" style="display: inline;">
<div class="footpara" style="display: inline;">
<a href="http://wiki.debian.org/pbuilder">http://wiki.debian.org/pbuilder</a></div>
</div>
</div>
<div class="footdef" style="margin-bottom: 1em;">
<sup><a class="footnum" href="https://www.blogger.com/blogger.g?blogID=6524463474407750608#fnr.3" id="fn.3">3</a></sup><br />
<div class="footpara" style="display: inline;">
<div class="footpara" style="display: inline;">
<a href="http://wiki.debian.org/sbuild">http://wiki.debian.org/sbuild</a></div>
</div>
</div>
<div class="footdef" style="margin-bottom: 1em;">
<sup><a class="footnum" href="https://www.blogger.com/blogger.g?blogID=6524463474407750608#fnr.4" id="fn.4">4</a></sup><br />
<div class="footpara" style="display: inline;">
<div class="footpara" style="display: inline;">
<a href="https://security.stackexchange.com/questions/209529/what-does-enabling-kernel-unprivileged-userns-clone-do">https://security.stackexchange.com/questions/209529/what-does-enabling-kernel-unprivileged-userns-clone-do</a></div>
</div>
</div>
<div class="footdef" style="margin-bottom: 1em;">
<sup><a class="footnum" href="https://www.blogger.com/blogger.g?blogID=6524463474407750608#fnr.5" id="fn.5">5</a></sup><br />
<div class="footpara" style="display: inline;">
<div class="footpara" style="display: inline;">
<a href="https://developers.redhat.com/blog/2019/02/21/podman-and-buildah-for-docker-users/">https://developers.redhat.com/blog/2019/02/21/podman-and-buildah-for-docker-users/</a></div>
</div>
</div>
<div class="footdef" style="margin-bottom: 1em;">
<sup><a class="footnum" href="https://www.blogger.com/blogger.g?blogID=6524463474407750608#fnr.6" id="fn.6">6</a></sup><br />
<div class="footpara" style="display: inline;">
<div class="footpara" style="display: inline;">
<a href="https://podman.io/blogs/2018/10/31/podman-buildah-relationship.html">https://podman.io/blogs/2018/10/31/podman-buildah-relationship.html</a></div>
</div>
</div>
</div>
</div>
</div>
Reinhard Tartlerhttp://www.blogger.com/profile/04887546547450531798noreply@blogger.com7tag:blogger.com,1999:blog-6524463474407750608.post-46917490139245658492011-05-17T07:19:00.001-04:002011-05-17T07:43:56.821-04:00Mini Server PCsDear Lazyweb,<br />
<br />
Hot or not, which of the following devices is the best? And which of them are actually available for purchase in Europe, preferably from Germany?<br />
<br />
<ul><li>Excito B3: <a href="http://excito.com/bubba/products/technical-specifications.html">http://excito.com/bubba/products/technical-specifications.html</a></li>
<li>D2Plug <a href="http://www.globalscaletechnologies.com/t-d2plugdetails.aspx#extern">http://www.globalscaletechnologies.com/t-d2plugdetails.aspx#extern</a></li>
<li>Lemote Fuloong 6004 Linux mini PC, e.g., here: <a href="http://www.tekmote.nl/epages/61504599.sf/en_GB/?ObjectPath=/Shops/61504599/Products/CFL-006">http://www.tekmote.nl/epages/61504599.sf/en_GB/?ObjectPath=/Shops/61504599/Products/CFL-006</a></li>
</ul><div>Please share your opinions in the comments.</div>Reinhard Tartlerhttp://www.blogger.com/profile/04887546547450531798noreply@blogger.com3tag:blogger.com,1999:blog-6524463474407750608.post-45236071753165175712010-09-26T12:57:00.001-04:002010-09-26T13:08:00.998-04:00How to disable password queries for Package Updates in Ubuntu 10.10Today, I've toyed a bit with policykit in Ubuntu 10.10. It turns out that disabling the password prompt in update-manager and the software center is fairly easy. The following command should do the trick:<br />
<br />
<pre>$ cat <<EOT | sudo tee /etc/polkit-1/localauthority/50-local.d/allow-apt.pkla
[allow-apt]
Identity=unix-group:admin
Action=org.debian.apt.*
ResultAny=no
ResultInactive=yes
ResultActive=yes
EOT
</pre>Reinhard Tartlerhttp://www.blogger.com/profile/04887546547450531798noreply@blogger.com0tag:blogger.com,1999:blog-6524463474407750608.post-47450480671931454382008-10-18T20:40:00.000-04:002008-10-18T20:46:55.559-04:00New web presenceI've now two new homes:<br /><ul><li><a href="http://apollon.tauware.de/"> http://apollon.tauware.de</a></li><li>this blog</li></ul>I finally found some time to move the contents of my old dokuwiki instance to a newer one. Unfortunately, the old <a href="http://www.dokuwiki.org/template:minima">theme</a> is not working with the current dokuwiki version, and I didn't really feel reactivating the blog plugin.<br /><br />I'm however pleased with the new setup. Instead of Apache2, I'm now using lighttpd with mod-fcgi, which uses much less of ressources on my server.Reinhard Tartlerhttp://www.blogger.com/profile/04887546547450531798noreply@blogger.com0