Table of Contents

Introduction

In this article we are going to review the basics of Slackware Linux and then we will dig into the installation procedure. We will explore its internal working and develop the required knowledge useful to understand the tricks behind the magic and to customize the installation. We will see a couple of options to install Slaware in chroot, how to make it work when Secure Boot is enabled and how to install it on a partition from any running distribution.

If you are interested only in a quick way to install Slackware in a chroot environment, or in another partition from a running distribution, feel free to skip directly to this section.

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 goals are:

  • performing a minimal installation of Slackware64 15.0 in a folder named slack15min
  • being able to run chroot slack15min
  • using pkgtools and slackpkg to manage packages in slack15min

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. Then 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.

Notes

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:

  • Errors related to running chmod in the post-install script install/doinst.sh of some packages. This command is not dangerous but requires root privileges.
  • The script installpkg try 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 these packages.
  • 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

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 following:

  • /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). After a while I had time to investigate the issue and I eventually found a solution. Check “Fixes for mixing the kernel and userland from different distributions” for details.

Alternative way to install Slackware in chroot

Investigating the internals of Slackware installation is funny and rewarding, but sometimes we don’t have the time for this and just want a quick solution to install Slackware in a chroot.

The idea is to double-stack two chroot environments. Since the regular installation runs the script setup from the initrd of the installation media, we can extract the content of the initramfs, chroot into it and execute setup following the regular installation wizard. This solution works out of the box if you are installing in a different partition on the disk, but you need to create a file and associate it with a loopback device if your goal is to have a chroot environment (the file can be in /dev/shm so it lives only for the time of the installation). The script setup will mount the loop device (or the partition) in the folder mnt in the initrd, so if you wish to install in a chroot, remember to unmount the loop device from another shell (the setup script will not notice it):

# create a file to act as a partition (skip this step if you have a real partition you want to use)
fallocate -s 100M mytempfile
losetup -f mytempfile

# 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
cat initrd.img |xz -c -d | cpio -i -D initrd

./chroot_helper.sh initrd
setup    # this is inside the chroot
# now follow the installation wizard
# if you want a chroot install, rememeber to selct the loop device
# and unmount the folder *initrd/mnt* from another shell as soon as
# it gets mounted.
# After install, skip the installation of the bootloader in the wizard
exit

If we plan to use Fedora’s kernel for Secure Boot, we need to remember to uninstall (or exclude in the first place) the kernel and related packages and then copy the desired ones from Fedora (or from the running system). The chroot environment is under initrd/mnt

./chroot_helper.sh initrd
chroot /mnt
removepkg kernel-firmware kernel-generic kernel-headers kernel-huge kernel-modules
exit
exit

rm -rf initrd/mnt/lib/modules
rm -rf initrd/mnt/lib/firmware
cp -r /lib/{modules,firmware} initrd/mnt/lib

mount| grep -q -F initrd/mnt
[ $? -eq 0 ] && umount initrd/mnt

The idea presented in this paragraph can potentially work for any other distribution (useful especially to cope with a lack of official documentation).

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/