Skip to main content

lsupg Static Builds With GHC 9 (Part 3)

I made some time to work on lsupg yesterday. My plan was to first reconfigure the project to use benz0li/ghc-musl images from Docker Hub, but I unfortunately ran into issues immediately.

As described in my blog entry on Testing GHC Versions, my goal is to maintain Haskell software to work with five years of GHC, boot libraries, and Cabal versions. In practice, I test against the latest release of each GHC minor version, so I currently try to test (at least) the following GHC versions.

GHC Version Release Date Cabal Version
8.6.5 2019-04-23 2.4
8.8.4 2020-07-15 3.0
8.10.7 2021-08-27 3.2
9.0.2 2021-12-25 3.4
9.2.8 2023-05-26 3.6
9.4.8 2023-11-10 3.8
9.6.5 2024-04-16 3.10
9.8.2 2024-02-23 3.10.2.0

I have been using utdemir/ghc-musl to build lsupg static executables. The oldest supported GHC version is GHC 8.8.4, so this is also the oldest version that lsupg supports. The oldest supported GHC version is the same in benz0li/ghc-musl.

Attempting to build a static executable using Stack and GHC 8.8.4, the build failed before compilation because groupadd is not found. Stack uses this to manage permissions, so that the ownership of files created within the container match the ownership of the project files in the host system. This command is provided by the shadow package. Checking the source, I confirmed which builds include this package. The images for GHC versions 8.8.4, 8.10.7, and 9.0.2 are problematic for me.

GHC Version shadow
8.8.4
8.10.1
8.10.4
8.10.5
8.10.6
8.10.7
9.0.1
9.0.2
9.2.1
9.2.2
9.2.3
9.2.4
9.2.5
9.2.6
9.2.7
9.2.8 Installed
9.4.1
9.4.2
9.4.3
9.4.4
9.4.5
9.4.6 Installed
9.4.7 Installed
9.4.8 Installed
9.6.1
9.6.2 Installed
9.6.3 Installed
9.6.4 Installed
9.6.5 Installed
9.8.1 Installed

To fix this missing shadow package issue, the package needs to be added so that the image works with Stack. Adding packages is a common need, as developers need to add packages that are required to build their applications. For example, an application that needs to work with PNG files may require the libpng-static package.

There are a few ways to do this. One option is to build new images from scratch, using edited versions of benz0li/ghc-musl Dockerfiles. As noted in my previous blog entry, however, I have had issues with building benz0li/ghc-musl images locally. Even if I can figure out a way to resolve these issues, building GHC is costly in terms of resources and time. Another option is to create new images on top of the existing images, so that GHC does not need to be rebuilt. Note that installing packages when running an existing image is not an option when using Stack.

This reminded me of a much more significant issue, however. Security is a major concern with static executables because libraries are included in the executables. When using dynamically linked executables, upgrading a library to fix a security vulnerability generally fixes the vulnerability for all of the dynamically linked executables that use the library. Static executables, on the other hand, must be rebuilt using the new libraries. In general, a static build should use the latest (compatible) version of Alpine, with all installed packages updated to the latest versions available.

As documented in SECURITY.md, only the image for the latest version of GHC is updated with security updates. The (other) images on Docker Hub are therefore not suitable for use when security is a concern. For images that use the most recent Alpine version, it is possible to create new images that upgrade the installed packages. For images that use older Alpine versions, however, new images need to be built from scratch.

Supporting five years of dependencies and worrying about security for lsupg may seem a bit silly. One of my goals for the project, however, is to use it as a public project for developing and testing such things. I have worked on proprietary projects where these things are taken very seriously. Some companies have very strict security requirements! lsupg allows me to work on this in public, which makes it easier to collaborate with others as well as provides information to anybody else who may need to do something similar.