Install Slackware in a chroot from any distro
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:
- What is the environment variable INSTLOCKDIR?
- There is no
slackpkg
in our chroot environment - 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
[2] https://docs.slackware.com/slackware:philosophy
[4] Slackware Book - https://www.slackbook.org/html/book.html
[5] https://fedoraproject.org/spins
[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