A guide to running Sabotage for the experienced Linux user.
butch is a collection of small shell scripts, living in
KEEP/bin of this
repo and is usually also installed into /bin of a sabotage system.
it was originally written in C for speed, but was recently replaced with a
pure POSIX shell implementation (the performance-sensitive parts are outsourced
into awk scripts, so at least on an average-speed CPU there's no notable
difference. It's probably slightly slower now on low-end ARM and MIPS CPUs).
It handles package downloads, checksums, builds and dependencies in a
relatively sane manner.
Parallel downloads are automatically enabled if a
jobflow binary is present
on the system (default on a sabotage install).
To see a list of supported commands, execute
butch without arguments.
butch will by default start sixteen download jobs and one build job.
You can influence the number of download jobs with the
If you're behind a super-fast gigabit link, it may make sense to increase this
number considerably, for example to
If your connection is very poor, you may want to set it to only
To make the setting persistent, put it into your
The previous C version of butch used to support multiple build jobs as well,
however that turned out to be very confusing since it was not possible to tell
which package is currently building and we achieve parallel CPU usage anyway
MAKE_THREADS variable (see section
Variables for details).
butch uses the system's
You may also use
curl by exporting
USE_CURL=1. For best results, download
all packages before the install process.
butch defaults to installing built packages into
are then symlinked into a user-definable path, defaulting to
/. Finally, the
package name and
pkgver of its recipe are then written to
/opt path can be overridden by adding the variable
the config file and setting it to the desired value. It must consist of a single
component, for example
/Packages. The staging dir will
always be used inside the filesystem root specified in the used config.
butch may also be used for system configuration, eschewing the package
building features by simply calling
exit 0 at the conclusion of a package
recipe. This will avoid the above package installation procedure.
To completely remove a package:
$ rm -rf /opt/$pkg $ butch unlink $pkg $ sed -i '/$pkg/d' /var/lib/butch.db # ... or edit by hand.
/src is the default path where
butch searches for and builds packages.
/src /src/pkg # package recipes, used by butch /src/KEEP # patches and other files referenced from scripts /src/build # package build directory. Safe to empty from time to time /src/filelists # per-package file lists, referenced by `butch unlink` /src/logs # per-package download and build logs /src/tarballs # upstream package tarballs /src/utils # sabotage utilities and helper scripts
/src/config. It will fail to
start if they are missing. The rest of this directory is optional with caveats.
/src/filelists will break
butch unlink <package> for existing
find . -type f -or -type l > /src/filelists/$packagename.txt from
the installation directory recovers the list.
/src/utils will lose scripts for cross-compilation, writing recipes,
managing chroots and other functionality. Each script contains brief
documentation explaining usage.
There is no issue erasing
It is suggested to clone the upstream repo as
$ git clone git://github.com/sabotage-linux/sabotage /src/sabotage $ rm -rf /src/KEEP /src/pkg $ ln -sf /src/sabotage/KEEP /src/KEEP $ ln -sf /src/sabotage/pkg /src/pkg
You can issue a
git pull in
/src/sabotage to update to the latest version of
recipes and utilities.
[mirrors] [vars] [deps] [build]
butch recipes are plain text files that contain one or more labeled headers
and their associated data. The above four sections are central to an assortment
of different possible recipes. This section details their use.
[mirrors] <url #1> ... <url #n> [vars] filesize=<bytes> sha512=<sha 512 hash> tardir=<directory name the tar extracts to, if it differs from the tar name> tarball=<optionally specified, if needed> pkgver=<package revision>
[vars] are optional, but must be included together as a set.
HTTP(S) is the only valid protocol for
optional directives and are usually omitted.
[vars] section is copied verbatim to the top of these generated scripts and
may contain shell code.
utils/dlinfo script is useful in generating the above sections for you.
[deps] <package #1> ... <package #n> [deps.host] <package #1> ... <package #n> [deps.run] <package #1> ... <package #n>
Any combination of the above three headers may optionally be present.
[deps] is the standard list of dependencies required by the recipe, also
[deps.host] are dependencies required on the host running the compiler.
Doing cross-compilation, one would typically omit to build those for the target.
[deps.run] are requirements to run the package on the target system.
For non-crosscompilation scenarios, butch defaults to build all of the above,
equivalent to specifying
in crosscompilation only to
DEPS=build (see cross-compile config template
[build] <shell instructions to build application>
Shell instructions inside [build] will be performed by butch during
prevent the post-build linking of files. If the
[build] phase calls
butch will not perform any post-build activities at all.
These recipe elements combine with
KEEP/butch_download_template.txt as a
build/dl_package.sh script. They also join
KEEP/butch_template_configure_cached.txt to form
Metapackages containing only a
section are useful.
Sabotage provides environment variables used for scripts and recipes, sourced
/src/config. This section describes them in detail.
stage1 values are provided here, along with a brief description of the variable.
Defines where the
./build-stage0 script builds a chroot.
Selects an architecture to build for. 'i386', 'arm', 'mips' and 'powerpc' are other options.
The C compiler used.
gcc is currently the only compiler tested and supported.
The number of threads to pass to make via the -j flag.
If not set,
./build-stage0 will download and build
butch. On systems lacking a
proper libc, you may need to statically build
butch yourself then specify it with
R=/ # `R` is the system root that butch will link packages into S=/src # `S` is the source directory for `butch` K=/src/KEEP # `K` is a directory of needed files and patches C=/src/tarballs # `C` is the downloaded tarball cache LOGPATH=/src/logs # `LOGPATH` is where everything is logged
Internal paths, useful when writing scripts and recipes. You should leave these all as-is, this is the intended way.
The build template. It creates packages in
optionally supplies a
config.cache file to speed up some from-source
compilation recipes. Review the template to see its configurable options.
The download template. It downloads, tests and unpacks tarballs.
Used during the bootstrap process by scripts to determine the current stage. Leave this alone.
Some packages (at the time of this writing, only
curses), allow multiple
packages to provide the dependency, in
curses case the user has the choice
netbsd-curses (the latter being the default).
To find out which packages allow the choice of alternative providers, run
grep 'deps\..*\..*' pkg/*
To prefer a non-default provider over the default one, add the prefered
option to your
config's DEPS variable like so:
See the wiki page "Bootstrap to HD Image" or
packages that have a different
pkgver tag than the one that's installed
are scheduled for update when you run
butch update opens your editor (set via
EDITOR environment variable, usually
~/.bashrc when using bash) with the list of packages
scheduled for rebuild. you can use the editor to remove packages that you don't
want to rebuild, or change the order of rebuild by moving the line containing
the package name to another position (the package on top of the list is built
first). Once you're satisfied with the list, save it in your editor and quit.
Then the rebuild will start, unless the list is empty.
If you're only interested in seeing which packages would need to be
butch rebuild $(butch outdated) is equivalent to running
without the editor step (i.e. everything gets updated non-interactively).
pkgver tag in the package's
[vars] section is completely independent of
the package's actual version (for example 4.7.4).
pkgver tag means the revision is
It is increased by one whenever a rebuild is necessary.
This is the case when the version of the package was updated, or when one of its
dependencies was updated in a way that requires a rebuild of all users, for
example a soname bump due to API changes in libressl, libpng, etc, but not if
there were only cosmetic changes (for example addition of a description tag).
cryptsetup package, then follow this guide to setup your partitions:
Add appropriate entries in
On startup, Sabotage's
rc.boot will mount them.
By default, Sabotage does not use an initramfs, so if you require an encrypted
root mount, you will have to customize your kernel build to piggyback a small
initramfs to you kernel.
Sabotage does things a bit differently than your usual Linux distribution!
Sabotage does not follow the Filesystem Hierarchy Standard.
For legacy support,
/usr is a symlink to
/sbin is a symlink to
Install software with
--prefix=/ when possible.
The times of a separate root partition are long over.
/local is provided to users, use it wisely.
Software not packaged by Sabotage should not touch stuff outside of
it could break on updates.
/srv/$SERVICE/$VHOST for all server data.
runit as init system, though we use Busybox init to start
We do not use runlevels.
The base system has a few services:
You will find these in
/var/service, which are symlinks to
You can start services with
sv u $SERVICE or take them down with
sv d $SERVICE.
By default, all services in
/var/service start at boot time.
If they have an empty
down file in their directory, you'll have to start them
If you don't want to use a service at all, best remove the symlink to
Find out what's running with
sv s /var/service/*.
Look into the service directories to find out how to add your own services. Note that you must tell them not to daemonize!
For the rest of
runit, refer to the documentation at:
There is no syslog support, services should use
svlogd to log into
svlogd ensure your service script dumps the service's output to
You can inspect the logs by looking at
For example, kernel messages are in
You can look at all logs with
sort /var/log/*/current |less.
For more information, see
Packages can be transfered and installed on another system than the one they
were built on. basically it's sufficient to copy the build host's directory
/opt/packagename to the target's
/opt, (use cp -a to preserve symlinks) and
butch relink packagename on the target.
An entry should be added to
/var/lib/butch.db, so butch knows that it's
already installed (the
pkgver for the second column in the DB can be taken
from the package's
[vars] section - if it is missing put
butch pack packagename and
butch unpack filename automate this
task on the build and target host, respectively.
sv u sshd.
loadkeys, then follow the instructions.
/etc/xinitrc, or copy it to
~/.xinitrcand edit that. There's a commented line suggesting how to change
/bin/Xand enable QEMU or VirtualBox settings, if needed, otherwise your controls won't work!
/etc/wpa_supplicant.conffor WiFi config.
/etc/wpa_connect_action.shfor IP address settings.
sv u wpa_supplicant.
ifconfig eth0 192.168.0.2 netmask 255.255.255.0.
route add default gw 192.168.0.1.
You can put the above into a script which
/etc/rc.local can execute at boot
Wine builds on Sabotage i386. To use it on x86_64, one needs to use packages built on i386 Sabotage.
For example, the following 32-bit packages are required to run simple Delphi programs:
wine musl alsa-lib #for sound support freetype libpng libsm libx11 libxau libxcb libxext libxi libxrender ncurses zlib-dynamic
You can get them off
/opt from a Sabotage i386 image or rootfs.
musl we need
We also need everything from the
wine package and the
lib/.so from all
Make a directory to put the stuff, we use
$ mkdir -p /32bit/lib $ mv musl-i386/lib/libc.so /32bit/lib $ ln -sf /32bit/lib/libc.so /lib/ld-musl-i386.so.1 $ echo "/32bit/lib:/32bit/wine/lib" > /etc/ld-musl-i386.path $ cd /32bit $ tar xf wine.i386.tar.xz $ for p in `cat 32bit-packages.txt`; do tar xf "$p".i386.tar.xz; mv "$p"/lib/* lib/; rm -rf lib/pkgconfig; done $ rm lib/*.a
Now it should be possible to use
/32bit/wine/bin/wine to execute Windows
Here`s a pre-made package that includes the work from the above steps:
http://mirror.wzff.de/sabotage/bin/wine-i386-bundle.tar.xz sha512sum: 2475ac72f62a7d611ab1ca14a6a58428bd07339f81e384bf1bbbd0187b2467c371f79fee9d028149eebd3c6a80999e5676364d1bc8054022f89de8cc66169b84
You only need to create the
ld-musl-i386.so symlink and the entry in
timezones package installs timezone description files into
musl supports timezones via the POSIX
TZ environment variable.
You should set it in your
~/.profile or in
glibc also supports
/etc/localtime, which is a copy or symlink of one of
the zoneinfo files.
Example values for
# Reads `/share/zoneinfo/Europe/Berlin` the first time an app calls localtime(). TZ=Europe/Berlin # Reads `/etc/localtime` the first time an app calls localtime(). # you may want to symlink it to the file for your timezone. TZ=/etc/localtime # Will set the timezone to GMT+2. (POSIX reverses the meaning of +/-) TZ=GMT-2 # Like Europe/Berlin, except it reads no file. # The string is the last "line" from the zoneinfo file. TZ="CET-1CEST,M3.5.0,M10.5.0/3"
rc.boot executes, the system clock is set to the hardware clock using
hwclock -u -s, where
-u stands for UTC.
hwclock -u -r can read the actual hardware clock, adjusted to the users'
If you want to see the actual UTC clock value, set
TZ=UTC and then
hwclock -u -r.
if your hardware clock is off, you can fix it by using
ntpd -dnq -p pool.ntp.org to get the actual time, then write it to BIOS using
hwclock -u -w.
encrypted partitions will be mapped to
/dev/mapper after they're opened.
encrypted partitions require a name, in this example we will use
the partition we want to encrypt will be
initialize the encrypted partition with a passphrase:
$ cryptsetup -y luksFormat /dev/sdb6
enter a passphrase when asked
create the unencrypted mapper device
$ cryptsetup luksOpen /dev/sdb6 crypart
now you can format
/dev/mapper/crypart like an ordinary partition.
$ mkfs.ext4 /dev/mapper/crypart
Finally, mount the partition
$ mount /dev/mapper/crypart /mnt
you should maybe make a copy of the header so you can restore your drive in case of a hardware defect:
$ cryptsetup luksHeaderBackup /dev/sdb6 --header-backup-file=/boot/luks_header.bin
create an entry for the partition in
/etc/crypttab. the file has information
in the comments to assist you. after adding it, the device will be mounted on
the next boot (the passphrase will be asked from the user during boot).