Table of Contents

Introduction

Slackware basics

Slackware Linux [1] is one of the oldest distributions still active these days. It follows the KISS principle [2] and it is the ideal distribution for people who love to dig into how stuff works. Most of the system is managed by bash scripts, so anybody can read the source code and figure out what it does behind the scenes. We will leverage this a lot in this article to demystify the installation procedure and how we can use it to install Slackware in a folder.

A traditional installation requires downloading the ISO images from a mirror and copying the content on a USB drive or on a CD-ROM. The content is also available directly from the mirror. We can connect from the browser to https://slackware.uk/slackware or https://slackware.nl/slackware for example, or we can inspect the repository with rsync from the terminal:

rsync rsync://slackware.nl/mirrors/slackware/
rsync rsync://slackware.uk/slackware/

In general rsync [3] is used to copy files and folders, but if you run the command without the destination it will list the content of the destination. To view the content of the latest version (Slackware64 15.0) run:

$ rsync rsync://slackware.uk/slackware/slackware64-15.0/
-rw-r--r--          5,767 2022/02/02 22:44:45 ANNOUNCE.15.0
-rw-r--r--         16,609 2022/03/30 19:03:58 CHANGES_AND_HINTS.TXT
-rw-r--r--      1,270,610 2025/04/09 19:06:34 CHECKSUMS.md5
-rw-r--r--            195 2025/04/09 19:06:34 CHECKSUMS.md5.asc
-rw-r--r--         17,976 1994/06/10 02:28:08 COPYING
-rw-r--r--         35,147 2007/06/30 04:21:00 COPYING3
-rw-r--r--         19,573 2016/06/23 20:08:55 COPYRIGHT.TXT
-rw-r--r--            616 2006/10/02 04:37:30 CRYPTO_NOTICE.TXT
-rw-r--r--      2,209,648 2025/04/09 19:03:06 ChangeLog.txt
-rw-r--r--      1,666,089 2025/04/09 19:06:10 FILELIST.TXT
-rw-r--r--          1,572 2012/08/29 18:27:33 GPG-KEY
-rw-r--r--        864,745 2022/02/02 08:25:12 PACKAGES.TXT
-rw-r--r--          8,034 2022/02/02 03:36:30 README.TXT
-rw-r--r--          3,635 2022/02/02 08:11:27 README.initrd
-rw-r--r--         34,162 2022/01/30 20:35:44 README_CRYPT.TXT
-rw-r--r--          8,754 2022/03/30 19:05:35 README_LVM.TXT
-rw-r--r--         19,658 2013/06/18 04:34:43 README_RAID.TXT
-rw-r--r--          7,928 2018/07/19 06:33:44 README_UEFI.TXT
-rw-r--r--          7,613 2022/02/03 04:38:00 RELEASE_NOTES
-rw-r--r--         13,855 2008/12/08 18:13:18 SPEAKUP_DOCS.TXT
-rw-r--r--         17,294 2008/12/08 18:13:22 SPEAK_INSTALL.TXT
-rw-r--r--         57,187 2022/02/01 19:37:50 Slackware-HOWTO
-rw-r--r--          8,700 2022/01/26 05:44:38 UPGRADE.TXT
drwxr-xr-x          4,096 2013/03/20 22:17:54 EFI
drwxr-xr-x          4,096 2025/04/03 22:41:35 extra
drwxr-xr-x          4,096 2022/02/02 08:21:36 isolinux
drwxr-xr-x          4,096 2022/02/02 08:11:26 kernels
drwxr-xr-x          4,096 2023/08/04 20:22:55 pasture
drwxr-xr-x          4,096 2025/04/09 19:06:10 patches
drwxr-xr-x          4,096 2022/02/02 08:25:18 slackware64
drwxr-xr-x          4,096 2023/06/29 19:39:21 source
drwxr-xr-x          4,096 2024/10/30 20:45:03 testing
drwxr-xr-x          4,096 2022/02/02 08:21:41 usb-and-pxe-installers

In the form of text files we find lots of useful pieces of information. To download the main install documentation run rsync rsync://slackware.uk/slackware/slackware64-15.0/Slackware-HOWTO . (the dot is the destination so the file Slackware-HOWTO will be copied to your current directory).

We are particularly interested in:

  • slackware64-15.0/isolinux/initrd.img: because it contains the installation scripts
  • the subfolders of slackware64-15.0/slackware64 since they contain the precompiled packages of the distribution organized in disk sets [4].
$ rsync rsync://slackware.uk/slackware/slackware64-15.0/slackware64
-rw-r--r--        337,498 2022/02/02 08:25:18 CHECKSUMS.md5
-rw-r--r--            163 2022/02/02 08:25:18 CHECKSUMS.md5.asc
-rw-r--r--        418,557 2022/02/02 08:24:22 FILE_LIST
-rw-r--r--      4,199,768 2022/02/02 08:24:33 MANIFEST.bz2
lrwxrwxrwx             15 2009/08/23 23:34:15 PACKAGES.TXT
drwxr-xr-x         24,576 2022/02/02 08:24:10 a
drwxr-xr-x         20,480 2022/02/02 04:20:08 ap
drwxr-xr-x         12,288 2022/02/02 08:24:22 d
drwxr-xr-x          4,096 2021/03/26 03:11:14 e
drwxr-xr-x          4,096 2016/04/01 21:41:08 f
drwxr-xr-x          4,096 2022/02/02 08:24:19 k
drwxr-xr-x         69,632 2022/02/01 08:29:42 kde
drwxr-xr-x         73,728 2022/02/02 04:20:16 l
drwxr-xr-x         28,672 2022/02/01 04:47:27 n
drwxr-xr-x          4,096 2021/10/10 22:22:41 t
drwxr-xr-x          4,096 2021/11/06 20:26:50 tcl
drwxr-xr-x         65,536 2022/02/01 04:47:25 x
drwxr-xr-x         12,288 2022/01/29 19:26:34 xap
drwxr-xr-x         12,288 2022/01/06 20:35:32 xfce
drwxr-xr-x          4,096 2021/02/15 19:33:55 y

The folder a contains the mandatory packages and the file slackware64-15.0/slackware64/a/tagfile where every package in a is associated with a tag: REQ for “Required”, ADD for “Additional” and OPT for “Optional.

A Slackware package is a compressed Tar archive containing the relevant files plus a folder with metadata and a shell script to perform post-install operations. The binary package is generated by a source package available in slackware64-15.0/source. Each source package contains the Slackbuild script (a shell script with a name ending with *.SlackBuild) where all the instructions to compile source code and create the binary package are specified.

We can install a package by manually extracting the files from the archive and running the post-install script or we can use the command installpkg from Slackware’s package manager pkgtools. Once more notice that installpkg is only a shell script.

$ rsync rsync://slackware.uk/slackware/slackware64-15.0/slackware64/a/pkgtools-15.0-noarch-42.txz .
$ cat pkgtools-15.0-noarch-42.txz | tar Jt                   
./                                                                                    
install/                                                                              
install/doinst.sh                          
install/slack-desc                                                                    
sbin/                                                                                 
sbin/explodepkg                            
sbin/installpkg                                                                       
sbin/makepkg                              
sbin/pkgdiff                                                                          
sbin/pkgtool                             
sbin/removepkg                                                                        
sbin/upgradepkg                            
usr/                                                                                  
usr/man/                                                                              
usr/man/de/
...

During the installation installpkg will extract the content of the package to the main filesystem (i.e. sbin/explodepkg will be installed in /sbin/explodepkg, etc) and then it runs the file install/doinst.sh to perform post-install actions (e.g. create symbolic links or change ownerships of files, etc).

Since pkgtools does not manage dependencies by design, this simple approach is good enough to manage all the packages in the distribution. The complete list of packages and the files contained in each package can be found by inspecting the files slackware64-15.0/PACKAGES.TXT and slackware64-15.0/FILELIST.TXT.

In case you want to perform a selection of packages to install, you can install the desired package and then use ldd to check if all dependencies are satisfied:

$ rsync rsync://slackware.uk/slackware/slackware64-15.0/slackware64/n/wpa_supplicant-2.10-x86_64-1.txz .
$ installpkg wpa_supplicant-2.10-x86_64-1.txz
$ ldd $(which wpa_supplicant)
        libssl.so.3 => /usr/lib/libssl.so.3 (0x7fac75a49000)
        libcrypto.so.3 => /usr/lib/libcrypto.so.3 (0x7fac755fd000)
        libdbus-1.so.3 => Not Found
$ rsync rsync://slackware.uk/slackware/slackware64-15.0/slackware64/a/dbus-1.12.20-x86_64-5.txz .
$ installpkg dbus-1.12.20-x86_64-5.txz
$ ldd `which wpa_supplicant`
        libssl.so.3 => /usr/lib/libssl.so.3 (0x7fc941157000)
        libcrypto.so.3 => /usr/lib/libcrypto.so.3 (0x7fc940d0b000)
        libdbus-1.so.3 => /usr/lib/libdbus-1.so.3 (0x7fc940cc6000)

In Slackware 12.2 they have introduced another tool to automate searching, downloading and upgrading packages: slackpkg:

slackpkg update gpg
slackpkg update
slackpkg upgrade-all

slackpkg search MPlayer
slackpkg install MPlayer

Install in a chroot jail

I am currently running Fedora Linux [5] and my goal is to:

  • install a minimal installation of Slackware64 15.0 in a folder
  • run chroot into the folder
  • use pkgtools and slackpkg to manage packages

Investigate the main installer to see if/how installpkg is used

The regular installation’s steps are:

  • copy the ISO image to a USB key
  • boot the PC from USB
  • create a partition
  • run setup to open the main installer

I assume setup is a shell script that collects some information from the user and then runs installpkg to perform the installation. If my guess is correct, we can extract the archive initrd.img and read the script to check how installpkg is used. Then we can use the acquired knowledge to run installpkg in a similar way for setting up the new chroot environment.

# copy the initramfs from the installer
rsync rsync://slackware.uk/slackware/slackware64-15.0/isolinux/initrd.img .

# create an empty folder and extract the content of initrd.img
mkdir initrd
cd initrd
cat ../initrd.img |xz -c -d | cpio -i

# find the path of the script "setup"
find . -name setup -type f
# the previous command print: ./usr/lib/setup/setup

Open ./usr/lib/setup/setup with your favorite text editor and search for the word “install”. After a few matches we reach the interesting part:

  # Do the package install:
  if [ -r $TMP/SeTCDdev ]; then # only try to remount media if it's a CD/DVD
    slackinstall --device `cat $TMP/SeTCDdev` --promptmode $MODE --srcpath `cat $TMP/SeTDS` --mountpoint /var/log/mount --target $T_PX --series $SERIES
  elif [ -r $TMP/SeTremotesvr ]; then
    slackinstall --device noremount --promptmode $MODE --srcpath `cat $TMP/SeTDS` --mountpoint /var/log/mount --target $T_PX --series $SERIES --net `cat $TMP/SeTremotesvr`
  else
    slackinstall --device noremount --promptmode $MODE --srcpath `cat $TMP/SeTDS` --mountpoint /var/log/mount --target $T_PX --series $SERIES
  fi
  # Run ldconfig on the newly installed system:
  if [ -x $T_PX/sbin/ldconfig ]; then
    $T_PX/sbin/ldconfig -r $T_PX
  fi

In the fragment of the script above, we see the actual install is performed by another script called slackinstall. I left also the next if statement because probably we will also need to perform ldconfig -r $CHROOTDIR to fix the symbolic links of the installed libraries.

Let’s proceed with our investigation and look for the script slackinstall in the same folder where we extracted the initramfs: find . -name slackinstall -type f. Open ./usr/lib/setup/slackinstall with a text editor and check the relevant part below:

    # Install the package series:
    for package in $SRCPATH/$series/*.t?z ; do
      if [ "$MODE" = "full" ]; then # install the package
        [ "x$REMOTESVR" != "x" ] && get_pkg $series $(basename $package) '-q'
        installpkg -root $ROOTDIR -infobox -priority ADD $package
        ERROR=$?
      elif [ "$MODE" = "terse" ]; then # install the package with terse description
        [ "x$REMOTESVR" != "x" ] && get_pkg $series $(basename $package) '-q'
        installpkg -root $ROOTDIR -terse -priority ADD $package
        ERROR=$?

We finally find the install procedure is looping through all the packages in a disk set and run installpkg –root $ROOTDIR to install it. The options -infobox and -terse controls the verbosity of the messages printed during the installation and -priority ADD overrides the priority defined in the tagfile. Feel free to search for the script installpkg in the current folder and run it without parameters to print the usage, or open the script with the text editor to confirm what we just said.

Use installpkg to set up the chroot environment

Let’s create a folder that I will use as a workspace and download the disk set a from Slackware repository (excluding the kernel, sysvinit and the other files that are not Slackware packages but are in the same folder):

mkdir installslack
cd installslack/
rsync -a 'rsync://slackware.uk/slackware/slackware64-15.0/slackware64/a' --exclude 'sysvinit-[0-9]*' --exclude 'kernel*' --include '*.txz' --exclude 'a/*' .

Tip: if you are unsure how to use rsync, try to run the command without the destination (last dot in my command) and then add all the options to –exclude and –include until you see the list of files you desire to download. The rerun the same command with the destination to start the actual download.

In our command we use -a to download recursively all the content of disk set a (plus a few other useful options) and we run a combination of filters (--exclude and --include) to download all the packages except the kernel modules and other useless files. The order of the parameters is important.

We can now proceed with the installation :

export INSTLOCKDIR=/dev/shm/run/lock/pkgtools
mkdir -p $INSTLOCKDIR

CHROOTDIR=slack15min
mkdir $CHROOTDIR
for i in a/*; do
    installpkg --root $CHROOTDIR --terse $i
fi
ldconfig -r $CHROOTDIR

To have our chroot working properly it is useful to mount /etc/resolv.conf (for insternet access in the chroot) and /dev, /proc, /sys. When we exit from the chroot, we should remember to unmount this stuff. To limit the manual steps, let’s create the following script:

#!/bin/bash

if [ -z "$1" ]; then
    echo "Uasge: $0 <chroot_dir>"
    exit -1
fi

CHROOTDIR=$1
for i in etc/resolv.conf dev proc sys; do
    mount --bind $i $CHROOTDIR/$i
done

chroot $CHROOTDIR /bin/bash

for i in etc/resolv.conf dev proc sys; do
    umount $CHROOTDIR/$i
done

Save the script with name chroot_helper.sh and run it:

chmod 755 chroot_helper.sh
./chroot_helper.sh slack15min

Type exit to exit from the chroot environment and then check with df -h to confirm there is nothing still mounted in $CHROOTDIR.

The Whole POC

You might have noticed a couple of unclear things:

  1. What is the environment variable INSTLOCKDIR?
  2. There is no slackpkg in our chroot environment
  3. I have excluded the package sysvinit-3.01-x86_64-1.txz but not sysvinit-functions-8.53-x86_64-5.txz and sysvinit-scripts-15.0-noarch-8.txz

To better investigate the behavior of installpkg I tried to install the packages with an unprivileged user. Then I checked the logs to see any potential errors and I found:

  • The script was trying to create the folder /run/lock/pkgtools. The value of this folder can be overwritten by an environment variable called $INSTLOCKDIR. So in my script I created a temporary folder.
  • slackpkg is not an essential package so it is in the disk set ap. It also depends on wget-1 and ca-certificates. Check the list of packages in the next section if you want to set up a chroot including this package.
  • The post-install script of the package sysvinit was trying to run init, but if we investigate install/doinst.sh in the package the installer does not run it:
# Notice we use an absolute path below, rather than usr/bin/last.  This is because
# we're testing to see if we are on the bootdisk, which will not have /usr/bin/last.
# If we aren't, we will signal init to restart using the new binary.
# The presence of "/etc/slack-installer" is under consideration as a better test.
if [ -x /usr/bin/last -a ! -r /etc/slack-installer ]; then
  /sbin/init u
fi
  • Other errors are related to running chmod in the post-install script install/doinst.sh. This command is not dangerous but requires root privileges.

Install Slackware in a system with Secure Boot enabled

I discussed how to have a dual boot-system Windows-Linux in this article and we spoke about the chain signed Shim -> signed Grub -> signed kernel (and modules).

We said only the mainstream distributions (like Fedora or Ububtu) sign the bootloader and the kernel, so it looks like we need extra manual steps to install Slackware for example. We all know different OSes are called Linux distributions (most of them are also GNU/Linux [6]) because they all share the Linux kernel (and most of them share also the GNU userland - check Chimera Linux [7] if you don’t know any non-GNU distro). What happens if I try to use a kernel from one distro and all the rest of the software from another one?

If it works, I probably can skip to figure out how to sign Slackware kernel and bootloader and simply use the base provided by Fedora.

My requirements for this POC (Proof Of Concept) are:

  • I want to install a minimal set of packages from Slackware Linux
  • The base system must include wpa_supplicant [8] and slackpkg to be able to connect to the Wifi network and install other packages
  • use Grub and the kernel from Fedora so it will work with Secure Boot out of the box

Since the ISO images of Slackware don’t contain a signed bootloader and kernel I need a trick to even run the installation. Similar to what we did here, we can:

  • take our Windows laptop with Secure Boot enabled
  • run Fedora Linux Live
  • shrink the main partition to create space for our new Slackware
  • install the OS in chroot
  • configure the new OS
  • install and configure the bootloader

The only difference here is that we will install Slackware instead of Fedora in the chroot jail.

If we inspect the content of the packages kernel-huge, kernel-generic, kernel-modules and kernel-firmware we find out the installation of these packages reduces to copying the folders:

  • /boot/vmlinuz
  • /lib/modules
  • /lib/firmware

The other challenge I had was to figure out which packages are required as a dependency of wpa_supplicant and slackpkg since they are not part of the base system. To help myself in this mission I installed the packages in the chroot and then with ldd and trying to run the software I was able to complete my lisy without too much trouble.

This is the list of packages I had in my working directory:

./
├── a
│   ├── aaa_base-15.0-x86_64-3.txz
│   ├── aaa_glibc-solibs-2.33-x86_64-5.txz
│   ├── aaa_libraries-15.0-x86_64-19.txz
│   ├── aaa_terminfo-6.3-x86_64-1.txz
│   ├── acl-2.3.1-x86_64-1.txz
│   ├── acpid-2.0.33-x86_64-1.txz
│   ├── attr-2.5.1-x86_64-1.txz
│   ├── bash-5.1.016-x86_64-1.txz
│   ├── bin-11.1-x86_64-5.txz
│   ├── btrfs-progs-5.16-x86_64-1.txz
│   ├── bzip2-1.0.8-x86_64-3.txz
│   ├── coreutils-9.0-x86_64-3.txz
│   ├── cpio-2.13-x86_64-3.txz
│   ├── cpufrequtils-008-x86_64-4.txz
│   ├── cracklib-2.9.7-x86_64-3.txz
│   ├── cryptsetup-2.4.3-x86_64-1.txz
│   ├── dbus-1.12.20-x86_64-5.txz
│   ├── dcron-4.5-x86_64-11.txz
│   ├── dialog-1.3_20211214-x86_64-1.txz
│   ├── dosfstools-4.2-x86_64-2.txz
│   ├── e2fsprogs-1.46.5-x86_64-1.txz
│   ├── ed-1.17-x86_64-3.txz
│   ├── efibootmgr-20191011_e8ce9fe-x86_64-4.txz
│   ├── efivar-20201015_cff88dd-x86_64-1.txz
│   ├── elilo-3.16-x86_64-12.txz
│   ├── elogind-246.10-x86_64-1.txz
│   ├── elvis-2.2_0-x86_64-8.txz
│   ├── eudev-3.2.11-x86_64-1.txz
│   ├── exfatprogs-1.1.3-x86_64-1.txz
│   ├── f2fs-tools-1.14.0-x86_64-3.txz
│   ├── file-5.41-x86_64-1.txz
│   ├── findutils-4.8.0-x86_64-3.txz
│   ├── floppy-5.5-x86_64-4.txz
│   ├── gawk-5.1.1-x86_64-1.txz
│   ├── genpower-1.0.5-x86_64-5.txz
│   ├── gettext-0.21-x86_64-3.txz
│   ├── glibc-zoneinfo-2021e-noarch-1.txz
│   ├── gpm-1.20.7-x86_64-9.txz
│   ├── gptfdisk-1.0.8-x86_64-1.txz
│   ├── grep-3.7-x86_64-1.txz
│   ├── gzip-1.11-x86_64-1.txz
│   ├── haveged-1.9.17-x86_64-1.txz
│   ├── hdparm-9.63-x86_64-1.txz
│   ├── hostname-3.23-x86_64-3.txz
│   ├── hwdata-0.355-noarch-1.txz
│   ├── infozip-6.0-x86_64-7.txz
│   ├── inih-53-x86_64-2.txz
│   ├── inotify-tools-3.20.11.0-x86_64-3.txz
│   ├── jfsutils-1.1.15-x86_64-4.txz
│   ├── kbd-1.15.3-x86_64-6.txz
│   ├── kmod-29-x86_64-1.txz
│   ├── lbzip2-2.5-x86_64-4.txz
│   ├── less-590-x86_64-1.txz
│   ├── lhasa-0.3.1-x86_64-3.txz
│   ├── libblockdev-2.26-x86_64-3.txz
│   ├── libbytesize-2.6-x86_64-3.txz
│   ├── libcgroup-0.41-x86_64-10.txz
│   ├── libgudev-237-x86_64-1.txz
│   ├── libpwquality-1.4.4-x86_64-6.txz
│   ├── lilo-24.2-x86_64-12.txz
│   ├── logrotate-3.18.1-x86_64-1.txz
│   ├── lrzip-0.641-x86_64-1.txz
│   ├── lvm2-2.03.13-x86_64-1.txz
│   ├── lzip-1.22-x86_64-3.txz
│   ├── lzlib-1.13-x86_64-1.txz
│   ├── mcelog-180-x86_64-1.txz
│   ├── mdadm-4.2-x86_64-1.txz
│   ├── minicom-2.8-x86_64-3.txz
│   ├── mkinitrd-1.4.11-x86_64-28.txz
│   ├── mt-st-1.4-x86_64-3.txz
│   ├── mtx-1.3.12-x86_64-4.txz
│   ├── ncompress-5.0-x86_64-2.txz
│   ├── ndctl-71.1-x86_64-4.txz
│   ├── ntfs-3g-2021.8.22-x86_64-1.txz
│   ├── nvi-1.81.6-x86_64-3.txz
│   ├── openssl-solibs-1.1.1m-x86_64-1.txz
│   ├── os-prober-1.79-x86_64-1.txz
│   ├── pam-1.5.2-x86_64-1.txz
│   ├── patch-2.7.6-x86_64-5.txz
│   ├── pciutils-3.7.0-x86_64-3.txz
│   ├── pcmciautils-018-x86_64-4.txz
│   ├── pkgtools-15.0-noarch-42.txz
│   ├── plzip-1.10-x86_64-1.txz
│   ├── procps-ng-3.3.17-x86_64-2.txz
│   ├── quota-4.06-x86_64-3.txz
│   ├── reiserfsprogs-3.6.27-x86_64-4.txz
│   ├── rpm2tgz-1.2.2-x86_64-6.txz
│   ├── sdparm-1.12-x86_64-2.txz
│   ├── sed-4.8-x86_64-3.txz
│   ├── shadow-4.8.1-x86_64-12.txz
│   ├── sharutils-4.15.2-x86_64-4.txz
│   ├── smartmontools-7.2-x86_64-4.txz
│   ├── splitvt-1.6.6-x86_64-5.txz
│   ├── sysfsutils-2.1.0-x86_64-4.txz
│   ├── sysklogd-2.3.0-x86_64-1.txz
│   ├── syslinux-4.07-x86_64-4.txz
│   ├── sysvinit-functions-8.53-x86_64-5.txz
│   ├── sysvinit-scripts-15.0-noarch-8.txz
│   ├── tar-1.34-x86_64-1.txz
│   ├── tcsh-6.23.02-x86_64-1.txz
│   ├── time-1.9-x86_64-4.txz
│   ├── tree-1.8.0-x86_64-3.txz
│   ├── udisks-1.0.5-x86_64-10.txz
│   ├── udisks2-2.9.4-x86_64-1.txz
│   ├── unarj-265-x86_64-4.txz
│   ├── upower-0.99.13-x86_64-1.txz
│   ├── usb_modeswitch-2.6.1-x86_64-3.txz
│   ├── usbutils-014-x86_64-1.txz
│   ├── util-linux-2.37.3-x86_64-1.txz
│   ├── volume_key-0.3.12-x86_64-5.txz
│   ├── which-2.21-x86_64-4.txz
│   ├── xfsprogs-5.13.0-x86_64-1.txz
│   ├── xz-5.2.5-x86_64-3.txz
│   ├── zerofree-1.1.1-x86_64-3.txz
│   └── zoo-2.10_22-x86_64-4.txz
├── install_in_chroot
│   ├── ca-certificates-20211216-noarch-1.txz
│   ├── devs-2.3.1-noarch-25.txz
│   ├── dhcpcd-9.4.1-x86_64-1.txz
│   ├── etc-15.0-x86_64-17.txz
│   ├── libnl-1.1.4-x86_64-5.txz
│   ├── libnl3-3.5.0-x86_64-3.txz
│   ├── libunistring-0.9.10-x86_64-3.txz
│   ├── mlocate-0.26-x86_64-4.txz
│   ├── ncurses-6.3-x86_64-1.txz
│   ├── net-tools-20181103_0eebece-x86_64-3.txz
│   ├── openssl-1.1.1m-x86_64-1.txz
│   ├── slackpkg-15.0.10-noarch-1.txz
│   ├── sysvinit-3.01-x86_64-1.txz
│   ├── utempter-1.2.0-x86_64-3.txz
│   ├── wget-1.21.2-x86_64-1.txz
│   └── wpa_supplicant-2.10-x86_64-1.txz
├── installpkg
└── setup_slackware_in_chroot.sh

In the main folder I have:

  • the script installpkg which is exactly what I have extracted from the Slackware package pkgtools
  • the script setup_slackware_in_chroot.sh which is my POC where I run the installation and basic setup of the new system
  • the folder a and install_in_chroot that contains Slackware packages; I have divided the packages into two groups so I can install the base system using installpkg --root $CHROOTDIR -terse a/* and then copy the remaining packages in install_in_chroot and run the installation of those in my chroot environment

Keep in mind this is just a POC, so the code has many points of improvement for readability, removing hard-coded paths, etc. The content of setup_slackware_in_chroot.sh is:

#!/bin/bash -ex

SCRIPTPATH=$(realpath $0)
SCRIPTDIR=$(dirname $SCRIPTPATH)
DESTDIR=/root/fed2
CACHEDIR=tmp/.packages.cache

export INSTLOCKDIR=/dev/shm/run/lock/pkgtools
mkdir -p $INSTLOCKDIR
bash $SCRIPTDIR/installpkg  --terse  --root $DESTDIR  $SCRIPTDIR/a/*

mkdir -p $DESTDIR/$CACHEDIR
cp $SCRIPTDIR/install_in_chroot/* $DESTDIR/$CACHEDIR
ldconfig -r $DESTDIR

rm -rf $DESTDIR/lib/firmware
cp -r /lib/firmware /lib/modules $DESTDIR/lib
cp /boot/vmlinuz $DESTDIR/boot

touch         $DESTDIR/root/installchroot.sh
chmod 755     $DESTDIR/root/installchroot.sh
cat <<EOF > $DESTDIR/root/installchroot.sh
#!/bin/bash

set -x
set -e 
export PATH=\$PATH:/bin:/sbin

installpkg  --terse  /$CACHEDIR/*.t?z
rm -rf /$CACHEDIR

#find /lib /lib64 -type f > /tmp/lib_before.txt
#ldconfig    # my test showed this is not necessary here
#find /lib /lib64 -type f > /tmp/lib_after.txt

mkinitrd -c \
    -k \$(/bin/ls /lib/modules) \
    -m nvme:ext4:exfat:vfat:squashfs:loop \
    -r /dev/disk/by-label/fed2 \
    -f ext4

echo 'LABEL=fed2  / ext4  rw,relatime  0 1' > /etc/fstab
EOF

for i in dev sys proc run; do
    mount --bind /$i $DESTDIR/$i
done

# avoid triggering /sbin/init in chroot
touch  $DESTDIR/etc/slack-installer
chroot $DESTDIR /root/installchroot.sh
rm $DESTDIR/etc/slack-installer

for i in dev sys proc run; do
    umount $DESTDIR/$i
done

The script should be simple enough to follow, but just to give a brief explanation:

  • I have a partition with an ext4 filesystem with the label fed2 where I want to install my new Slackware (I will call it the target partition)
  • DESTDIR is the folder where I have mounted the target partition
  • CACHEDIR is a folder in the chroot environment where I copy the second set of packages that will be installed inside the new chroot jail
  • I have a ramfs mounted under /dev/shm so the INSTLOCKDIR will be cleared automatically after reboot
  • the packages in folder a get installed from the main system
  • then the packages in install_in_chroot are copied to $CACHEDIR
  • ldconfig is executed to create symbolic links in the library installed in $DESTDIR (most of them are in $DESTDIR/{lib,lib64}
  • firmware, kernel modules and kernel image are copied from Fedora
  • a script called installchroot.sh is created in the new environment (this script will take care of the second part of the installation)
  • the folders dev, sys, proc and run are mounted also inside the new chroot jail
  • the script installchroot.sh is invoked in the chroot: install the remaining packages, create the new initrd, create /etc/fstab referring to the new filesystem with the label
  • then the script unmuount dev, sys, proc and run

Proceed to install and to configure the bootloader following the article “Dual-boot Windows Linux in 2024” and reboot.

I was glad to see the new system is working fine, I can connect to the internet (with wpa_supplicant, wpa_passphrase and dhcpcd) and install new packages either manually or using slackpkg.

I tried to install the other disk sets and run Xfce. All works fine except for the audio card. With dmesg I can see it fails when loading a kernel module related to the hda codec. I haven’t solved the issue yet and I didn’t expect it to happen since all the other devices are working fine and the same kernel module (with the same firmware) works perfectly under Fedora (we copied the files from Fedora so they are exactly the same).

Validation of the POC with Alpine Linux

I have successfully tested the idea of installing the userland of a distribution with the kernel of another one also using the combination Fedora kernel + Alpine Linux [9] userland. The procedure at a high level is the same as we followed for Slackware, but in this case we are luckier because the chroot installation for Alpine is documented in its Wiki [10].

#!/bin/bash

# Assume the target partition is formatted with ext4 and mounted in
# the folder ./fed2

chroot_dir=fed2

wget https://dl-cdn.alpinelinux.org/alpine/v3.21/main/x86_64/apk-tools-static-2.14.6-r3.apk
cat apk-tools-static-2.14.6-r3.apk | tar zx sbin/apk.static
mv sbin/apk.static .

./apk.static -X https://dl-cdn.alpinelinux.org/alpine/v3.21/main \
    -U --allow-untrusted -p ./${chroot_dir} --initdb \
    add alpine-base

mknod -m 666 ${chroot_dir}/dev/full c 1 7
mknod -m 666 ${chroot_dir}/dev/ptmx c 5 2
mknod -m 644 ${chroot_dir}/dev/random c 1 8
mknod -m 644 ${chroot_dir}/dev/urandom c 1 9
mknod -m 666 ${chroot_dir}/dev/zero c 1 5
mknod -m 666 ${chroot_dir}/dev/tty c 5 0

echo https://dl-cdn.alpinelinux.org/alpine/v3.21/main      >  ${chroot_dir}/etc/apk/repositories
echo https://dl-cdn.alpinelinux.org/alpine/v3.21/community >  ${chroot_dir}/etc/apk/repositories

echo 'LABEL=fed2      /               ext4    rw,relatime     0 1' > ${chroot_dir}/etc/fstab

mkdir -p ${chroot_dir}/boot
cp /boot/vmlinuz ${chroot_dir}/boot
cp -r /lib/modules /lib/firmware/ ${chroot_dir}/lib/
lsmod | awk '{print $1}'|tail -n +2 >> ${chroot_dir}/etc/modules

touch ${chroot_dir}/root/firstconfig.sh
chmod a+x ${chroot_dir}/root/firstconfig.sh
cat <<"EOF" > ${chroot_dir}/root/firstconfig.sh
#!/bin/sh

export PATH=/bin:/sbin:/usr/bin:/usr/sbin:$PATH

rc-update add devfs sysinit
rc-update add dmesg sysinit
rc-update add mdev sysinit
rc-update add hwclock boot
rc-update add modules boot
rc-update add sysctl boot
rc-update add hostname boot
rc-update add bootmisc boot
rc-update add syslog boot
rc-update add mount-ro shutdown
rc-update add killprocs shutdown
rc-update add savecache shutdown

apk update
apk add mkinitfs wpa_supplicant
mkinitfs
EOF

mount -o bind /dev ${chroot_dir}/dev
mount -t proc none ${chroot_dir}/proc
mount -o bind /sys ${chroot_dir}/sys

# chroot ${chroot_dir} /bin/ash -l
chroot ${chroot_dir} /root/firstconfig.sh

umount ${chroot_dir}/dev ${chroot_dir}/proc ${chroot_dir}/sys

echo "Please configure the bootloader and restart the system"

Check this article to configure the bootloader.

Funny enough we have the same issue with the audio card.

Conclusions

In this article we saw how powerful it is to have a simple system and play around with it to have fun and overcome issues.

In particular we reviewed the basics of Slackware Linux, we saw how we can install it in a chroot jail and how we can use this strategy to install a new system. We found also an interesting way of performing a custom installation on a system when Secure Boot is enabled.

My next step for this project will be to generalize the script so it can be useful to anybody who wants to install Slackware in a chroot environment or even in a laptop without disabling Secure Boot.

References

[1] http://www.slackware.com/

[2] https://docs.slackware.com/slackware:philosophy

[3] https://rsync.samba.org/

[4] Slackware Book - https://www.slackbook.org/html/book.html

[5] https://fedoraproject.org/spins

[6] https://www.gnu.org/

[7] https://chimera-linux.org/about/#alternative-userland

[8] https://w1.fi/wpa_supplicant/

[9] https://alpinelinux.org/about/

[10] https://wiki.alpinelinux.org/wiki/Alpine_Linux_in_a_chroot