PREFACE
Zeppe-Lin Handbook.
Because figuring it out yourself is overrated.
This guide provides everything you need to install, configure, and maintain your Zeppe-Lin system.
Build the system you need. This handbook shows you how.
Because nobody else will.
1 INTRODUCTION
1.1 About Zeppe-Lin
Zeppe‑Lin is a lightweight, source‑based GNU/Linux distribution for x86‑64 systems. A fork of CRUX, it emphasizes simplicity, predictability, and maintainable design. It follows UNIX principles: small tools, plain‑text configuration, and explicit behavior. Automation is minimal and visible.
Zeppe‑Lin is designed for users who want full control over their system. Everything can be built, inspected, and maintained from source, ensuring autonomy, transparency, and reproducibility. The system favors practical, reliable behavior over cleverness or unnecessary features.
1.2 Audience
Zeppe‑Lin suits users who:
- Prefer a minimal and predictable environment
- Manage and configure the system via text files
- Build software from source to control dependencies
- Want to fully understand and maintain their system
1.3 Summary
By keeping components small, behavior explicit, and operations visible, Zeppe‑Lin ensures the system is comprehensible, controllable, and practical, while remaining flexible enough to adapt to individual needs.
2 INSTALLATION
2.1 Supported Hardware
Zeppe-Lin Linux supports x86-64 processors (e.g., AMD Athlon 64, Intel Core, Intel Atom). Older architectures, such as i686, are incompatible.
2.2 Boot a Live System
Zeppe-Lin is distributed as a compiled tarball containing a root filesystem. To install it, first boot your computer using a Linux-based “Live CD/DVD/USB” system.
Launch your preferred Live system, open a terminal, and gain root
privileges (e.g., sudo su).
2.3 Disk Partitions and Filesystems
This section describes “UEFI and LVM on LUKS” installation. Additional partitions/filesystems schemes may be added in the future.
2.3.1 UEFI and LVM on LUKS
Set up Zeppe-Lin on a fully encrypted disk (excluding the
bootloader partition for UEFI compatibility) using
dm-crypt with LUKS and an LVM container inside the
encrypted partition.
Important:
Ensure the following tools are available in the Live system:
parted- Create and manage partitions.dosfstools- Format the boot partition as FAT32 (UEFI).cryptsetup- Encrypt partition with LUKS.lvm2- Manage logical volumes inside LUKS.
2.3.1.1 Partition Scheme
Example device: /dev/sda. Replace with your actual
device (e.g., /dev/sdb, /dev/nvme0n1).
| Partition | Filesystem | Size | Description |
|---|---|---|---|
| /dev/sda1 | FAT32 | 512 MiB | boot partition |
| /dev/sda2 | none | remaining space | LUKS container |
Important:
On UEFI systems, the boot partition must be an EFI System Partition (ESP).
A size of 512 MiB is recommended.
2.3.1.2 Create Partitions
Use parted(8) to partition the disk:
# as root
parted -s /dev/sda <<'EOF'
mklabel gpt
mkpart ESP fat32 1MiB 513MiB
set 1 boot on
name 1 efiboot
mkpart primary 513MiB 100%
name 2 luks
quit
EOFEncrypt /dev/sda2 with LUKS and map it:
# as root
cryptsetup luksFormat /dev/sda2
cryptsetup luksOpen /dev/sda2 crypt2.3.1.3 Create LVM Inside LUKS
Create a physical volume and volume group (e.g.,
zpln):
# as root
pvcreate /dev/mapper/crypt
vgcreate zpln /dev/mapper/cryptLogical volume layout:
| Volume name | Filesystem | Size | Description |
|---|---|---|---|
| swap | none | 2 x RAM | swap area |
| root | ext4 | remaining space | root filesystem |
Check RAM size with # free -m. For example, if you
have 4 GiB RAM, a swap of 8 GiB (2 x RAM) is recommended.
Create the logical volumes:
# as root
lvcreate -L 8G -n swap zpln
lvcreate -l 100%FREE -n root zpln2.3.1.4 Create Filesystems and Swap
Format partitions and volumes:
# as root
mkfs.vfat -F32 /dev/sda1
mkfs.ext4 /dev/zpln/root
mkswap /dev/zpln/swap
swapon /dev/zpln/swap2.3.1.5 Mount Partitions
The /mnt directory is used as the default mount point
in this handbook.
Mount the root volume:
# as root
mount /dev/zpln/root /mntMount the boot partition:
# as root
mkdir /mnt/boot
mount /dev/sda1 /mnt/boot2.4 Install Base System
Download, verify, and extract the rootfs tarball to set up your base system.
2.4.1 Download Rootfs Tarball
Download the tarball directly into the /mnt directory
(the default mount point) to avoid using live media RAM.
The current Zeppe-Lin release is published at
https://github.com/zeppe-lin/pkgsrc-core/releases/latest
Identify the release version (e.g., vX.Y), then
download the corresponding rootfs archive and its detached
signature:
# as root
cd /mnt
URL=https://github.com/zeppe-lin/pkgsrc-core/releases/download
VERSION=vX.Y
wget -c ${URL}/${VERSION}/rootfs-${VERSION}-x86_64.tar.xz \
${URL}/${VERSION}/rootfs-${VERSION}-x86_64.tar.xz.sig2.4.2 Verify Downloaded Tarball
The tarball is signed with GPG. For security, verifying its integrity is highly recommended.
Import the public key:
# as root
gpg --keyserver keyserver.ubuntu.com --recv-keys 59ec1986fbd902cfVerify the signature:
# as root
gpg --verify rootfs-${VERSION}-x86_64.tar.xz.sig \
rootfs-${VERSION}-x86_64.tar.xz2.4.3 Extract Rootfs Tarball
Once the rootfs tarball is downloaded and verified, extract its
contents using the following command. Make sure to replace
${VERSION} with the version you downloaded:
# as root
tar --numeric-owner --xattrs --xattrs-include='*' -xpf \
rootfs-${VERSION}-x86_64.tar.xzImportant:
It is critical to use all the specified options to ensure proper extraction. Here’s what each option does:
--numeric-ownerEnsures numeric UIDs and GIDs from the tarball are preserved, avoiding mismatches caused by the UID/GID mappings on the live system.
--xattrs --xattrs-include='*'Preserves filesystem extended attributes, which are used for Linux capabilities (e.g., allowing programs like
ping(8)enhanced privileges without requiringsuid root).
-xpfExtracts (
x), preserves permissions and ownership (p), and uses the specified file (f).
2.5 Chroot Into Base System
Important:
Copy the DNS configuration to ensure network access inside the chroot, which is needed for updates and installing software:
# as root cp /etc/resolv.conf /mnt/etc/resolv.conf
Mount necessary pseudo-filesystems:
# as root
mount -B /dev /mnt/dev
mount -B /tmp /mnt/tmp
mount -B /run /mnt/run
mount -t proc proc /mnt/proc
mount -t sysfs none /mnt/sys
mount -t devpts -o noexec,nosuid,gid=tty,mode=0620 devpts \
/mnt/dev/ptsFor UEFI systems, mount EFI variables:
# as root
mount -B /sys/firmware/efi/efivars /mnt/sys/firmware/efi/efivarsEnter the chroot:
# as root
chroot /mnt /bin/bashSet the SHELL variable to /bin/bash to
ensure tools like vim work properly:
# chrooted, as root
export SHELL=/bin/bash2.6 Configure Base System
Set the root password:
# chrooted, as root
passwd rootEnsure proper ownership and permissions:
# chrooted, as root
chown root:root /
chmod 755 /Generate necessary locales (e.g., en_US):
# chrooted, as root
localedef -i en_US -f UTF-8 en_US.UTF-8Set the system default locale by adding it to
/etc/profile:
export LANG=en_US.UTF-8See Generating Locales for details.
Edit /etc/fstab to configure filesystems (see
fstab(5)). Example for UEFI and LVM on LUKS:
/dev/zpln/root / ext4 defaults,noatime,nodiratime 1 2
/dev/sda1 /boot vfat defaults,noatime,nodiratime 1 2
/dev/zpln/swap swap swap defaults 0 0
Note:
Use
UUID=...or/dev/disk/by-uuid/*instead of/dev/*for better reliability on multi-disk systems. Find UUIDs with:# as root blkid -o value -s UUID <DEVICE>
Edit /etc/rc.conf (see rc.conf(5)) to
configure system settings like console font, keyboard, timezone,
hostname, and services.
Configure network settings in /etc/rc.d/net,
/etc/hosts, and /etc/resolv.conf (see Networking).
2.6.1 Mount Additional Filesystems
Before building and installing additional software, mount additional pseudo-filesystems.
Shared memory (needed by some builds, e.g.,
python3):
# chrooted, as root
mount /dev/shmOptional package build directory (RAM builds):
# chrooted, as root
mount /var/cache/pkgmk/workImportant:
Mount
/var/cache/pkgmk/workonly if enabled in/etc/fstaband you have enough RAM.
2.6.2 Configure Users and Privileges
Add a regular user (set a specific UID now if needed):
# chrooted, as root
useradd --shell /bin/bash \
--create-home \
--groups audio,video,scanner,cdrom,input,users \
--uid 1000 \
--user-group <USERNAME>Set the password:
# chrooted, as root
passwd <USERNAME>To grant administrative privileges (e.g., as Ubuntu does), first
add the user to the wheel group:
# chrooted, as root
usermod -aG wheel <USERNAME>And second, grant the users in the wheel group to be
root via sudo(8) by creating the file
/etc/sudoers.d/00_wheel with the following content:
%wheel ALL=(ALL:ALL) ALL
2.7 Update the Base System
Before building and installing additional packages, it is highly recommended to update the freshly installed Zeppe-Lin system.
2.7.1 Prepare Pkgsrc Collections
Packages’ sources are organized into collections.
Clone the necessary collections, keeping in mind that each depends on the previous one:
# chrooted, as root
cd /usr/src/
URL=https://github.com/zeppe-lin
git clone ${URL}/pkgsrc-core --branch 1.x
git clone ${URL}/pkgsrc-system --branch 1.x
git clone ${URL}/pkgsrc-xorg --branch 1.x
git clone ${URL}/pkgsrc-desktop --branch 1.xImportant:
The
1.xbranch applies to all 1. releases (1.0, 1.1, 1.2, …). When a new major line appears, switch to its branch (e.g.,2.x). Verify your release against the current release or the pkgsrc-core releases page.
Enable the cloned collections in /etc/pkgman.conf. By
default, only pkgsrc-core collection is enabled.
2.7.2 Perform the System Update
Perform a full system update with dependency handling and sorting, and stop if the installation of at least one package fails:
# chrooted, as root
pkgman sysup --deps --depsort --groupMerge any rejected files during update:
# chrooted, as root
rejmergeCheck for broken packages and rebuild as needed:
# chrooted, as root
pkgman update -fr --depsort $(revdep)Here, revdep(1) identifies packages with broken
dependencies, and if any are reported, pkgman update -fr
rebuilds the affected packages.
2.8 Install Essential Packages
Install packages required for a minimal, functional workstation:
# chrooted, as root
pkgman install --deps --group \
cryptsetup e2fsprogs dosfstools grub2 grub2-efi iw gnupg \
lvm2 pinentry wireless-tools wpa-supplicant dhcpcd iputilsThis is a generic setup; users can add any additional packages they require based on their specific needs.
Note:
For network setup and configuration details, see Networking.
If you set up a networking bridge, specify the bridge interface in the
/etc/rc.d/dhcpcdand/or/etc/rc.d/wpa_supplicant.
2.9 Kernel Setup
Two methods are available: build and install a package or compile manually.
2.9.1 Kernel Package
Build and install the packaged Linux kernel:
# chrooted, as root
pkgman install --deps --group --config-append="runscripts no" linuxThe linux package includes a post-install
script that runs mkinitramfs(8) and updates the GRUB
config. This script is disabled here through
--config-append="runscripts no" to run manually
later.
Important:
When you update the
linuxpackage through the package manager, the old kernel and its modules are removed as part of the update process. This can cause issues if the system is still using the old kernel while the new one is being installed. To avoid these problems, it is recommended to lock thelinuxpackage from automatic updates and handle kernel updates separately usingpkgman-update(8). Seepkgman-lock(8)for details.
If you installed the kernel using this method, proceed to Kernel Firmware if your system requires additional firmware, or Initramfs otherwise.
2.9.2 Manual Kernel Compilation
This method suits those wanting a minimal kernel or needing sources for driver building (e.g., Nvidia, VirtualBox).
Important:
Use the kernel version from Zeppe-Lin’s package sources for best compatibility. Other versions might cause issues.
Download sources:
# chrooted, as root
pkgman install -do linux
KV=$(pkgman printf %v --filter=linux)
tar -xvf /var/cache/pkgmk/sources/linux-${KV}.tar.?z -C /usr/src/Apply Zeppe-Lin patches:
# chrooted, as root
cd /usr/src/linux-${KV}
for p in $(pkgman path linux)/*.patch; do
[ -f "$p" ] && patch -Np1 -i "$p"
donevs
Important:
It is highly recommended to perform a dry run to check for errors before applying. To do this, simply add
--dry-runoption to thepatch(1)command within the loop shown above.
Configure kernel (choose one of the following):
Custom Configuration:
Run the menu-based kernel configurator to manually select kernel features:
# chrooted, as root make menuconfigUse Package Defaults:
Apply the default configuration from the package:
# chrooted, as root cp $(pkgman path linux)/x86_64-dotconfig .config make olddefconfigBuild and install:
# chrooted, as root make -j$(nproc) all cp arch/x86/boot/bzImage /boot/vmlinuz-${KV} cp .config /boot/config-${KV} make modules_install
Next steps:
- Firmware needed? Proceed to Kernel Firmware.
- No firmware needed? Go to Initramfs.
2.10 Kernel Firmware
Some hardware (like certain Wi-Fi or graphics cards) needs extra firmware.
Install non-free firmware if required:
# chrooted, as root
pkgman install --deps --group linux-firmwareSkip this if you prefer a completely free software system.
2.11 Initramfs
First, install mkinitramfs:
# chrooted, as root
pkgman install --deps --group mkinitramfsThe /etc/mkinitramfs/config file controls how
mkinitramfs(8) builds the initial ramdisk image used at
boot. It controls which modules, hooks, and settings are included in
the initramfs image.
Here’s an example for UEFI and LVM on LUKS:
# /etc/mkinitramfs/config
hostonly=1 # optional, creates smaller initramfs
compress="gzip --fast"
hooks="eudev luks lvm resume"
root=/dev/zpln/root
root_type=ext4
resume=/dev/zpln/swap
luks_name=crypt
luks_root=/dev/sda2
# End of file.See mkinitramfs.config(5) for more information.
Important:
The
hostonly=1setting creates a smaller initramfs with only necessary modules. If you move the drive to different hardware later, it might not boot.
Note:
For multi-disk systems, using
UUID=...or/dev/disk/by-uuid/*instead of/dev/*in the config can prevent boot issues. Find UUIDs with:# as root blkid -o value -s UUID <DEVICE>
Now, prepare an initramfs. If you installed the Linux kernel
manually, you have already set KV variable to kernel
version. Otherwise, fetch the kernel version from the package
source:
# chrooted, as root
KV=$(pkgman printf %v --filter=linux)Finally, generate the initramfs image:
# chrooted, as root
mkinitramfs -o /boot/initramfs-${KV}.img -k ${KV}2.12 Bootloader
This section covers installing GRUB2 as your bootloader. Support for other bootloaders may be added later.
2.12.1 GRUB2
Create /etc/default/grub with:
# Set the delay before booting:
GRUB_TIMEOUT=3
# Show ZPLN in the GRUB menu:
GRUB_DISTRIBUTOR=ZPLN
# Set kernel parameters (quiet boot, swap for hibernation):
GRUB_CMDLINE_LINUX_DEFAULT="quiet resume=/dev/zpln/swap"Important:
For better reliability on multi-disk systems, use
UUID=...instead of/dev/*for the resume partition.Find the UUID with:
# as root blkid -o value -s UUID <DEVICE>
Next, install GRUB2 on your target drive. Example device:
/dev/sda. Replace with your actual device (e.g.,
/dev/sdb, /dev/nvme0n1).
For UEFI, ensure the EFI System Partition (ESP) is
mounted at /boot/efi inside the chroot. Then install GRUB
with EFI support:
# chrooted, as root
grub-install --target=x86_64-efi --efi-directory=/boot /dev/sdaFor legacy BIOS booting, install GRUB directly to the disk’s MBR:
# chrooted, as root
grub-install --target=i386-pc /dev/sdaFinally, generate the GRUB2 configuration file based on
/etc/default/grub and detected kernels:
# chrooted, as root
grub-mkconfig -o /boot/grub/grub.cfg2.13 Post-installation Tasks
2.13.1 Install Xorg and Drivers
To find video and input drivers, run:
# chrooted, as root
pkgman search -vv xf86-Common video drivers include xorg-xf86-video-intel
(Intel),
xorg-xf86-video-amdgpu/xorg-xf86-video-ati
(AMD), and xorg-xf86-video-nouveau (NVIDIA). For NVIDIA,
the nouveau-firmware is also recommended.
For input, modern drivers like
xorg-xf86-input-libinput and
xorg-xf86-input-evdev are recommended. Legacy options
like xorg-xf86-input-keyboard and
xorg-xf86-input-mouse are also available.
After selecting drivers for your hardware, install
xorg meta-package and additional drivers with:
# chrooted, as root
pkgman install --deps --group xorg [DRIVERS]Replace [DRIVERS] with the ones matching your
system.
2.13.2 Install a Window Manager
Zeppe-Lin focuses on lightweight and efficient window managers rather than complex desktop environments like GNOME or KDE. This approach avoids unnecessary dependencies and simplifies configuration.
Zeppe-Lin provides package sources for several window managers, but users are welcome to choose and contribute package sources for any window manager they prefer.
2.13.2.1 Ratpoison
Currently, the pkgsrc-desktop repository provides the
ratpoison window manager. You can install it with:
# chrooted, as root
pkgman install --deps --group ratpoison2.13.2.2 Unofficial: Window Maker
For users interested in a retro, intuitive window manager, you can
install Window Maker from the unofficial
pkgsrc-wmaker repository.
Warning:
Using unofficial repositories means the packages might not follow the same update schedule or quality standards as the official repositories. Use with caution.
To install Window Maker, first clone the repository:
# chrooted, as root
cd /usr/src
URL=https://github.com/zeppe-lin
git clone ${URL}/pkgsrc-wmaker --branch 1.xImportant:
The
1.xbranch applies to all 1. releases (1.0, 1.1, 1.2, …). When a new major line appears, switch to its branch (e.g.,2.x). Verify your release against the current release or the pkgsrc-core releases page.
Next, you need to tell pkgman(1) about this new
repository by adding the following line to
/etc/pkgman.conf:
pkgsrcdir /usr/src/pkgsrc-wmaker
Then, install it with:
# chrooted, as root
pkgman install --deps --group wmakerOptional meta-packages for Window Maker include
wmaker-dockapps for added functionality and
wmaker-themes for customization.
2.14 Reboot
Exit the chroot:
# chrooted, as root
exitUnmount all filesystems, and reboot:
# as root
cd /
umount -R /mnt
shutdown -r nowThe GRUB menu should appear, allowing you to boot into Zeppe-Lin.
3 UPGRADING
WARNING! THIS SECTION IS UNDER DEVELOPMENT AND CANNOT BE USED AS A MANUAL!
Upgrading Zeppe-Lin requires careful planning. This section outlines methods for updating your system. Follow the steps as presented to ensure a reliable upgrade.
Upgrade methods:
- Quick binary upgrade (core components).
- Full update from sources.
Before starting, read the release notes for the target version and back up important data.
3.1 Release Notes
Read the release notes for the new Zeppe-Lin version. They contain essential details about new features, removed packages, and compatibility issues. The latest release notes you can obtain here.
3.2 Set Release And Sync
Synchronize your local pkgsrc collections to match the new release
branch. Replace 1.x with the specific release you are
upgrading to:
# as root
git -C /usr/src/pkgsrc-core switch 1.x
git -C /usr/src/pkgsrc-system switch 1.x
git -C /usr/src/pkgsrc-xorg switch 1.x
git -C /usr/src/pkgsrc-desktop switch 1.x3.2.1 Binary Upgrade
Use precompiled binary packages for faster core system upgrades, especially to avoid build issues during initial updates.
Important:
Upgrades may cause file conflicts, such as a file being reassigned between packages. To prevent issues, read the release notes for the target Zeppe-Lin version. They detail package changes like removals, merges, or renames that may require manual intervention.
3.2.1.1 Download and Extract binpkgs
Note:
Verify the integrity of the downloaded
binpkgstarball before extracting it. It is signed using the same method as the Zeppe-Lin root filesystem image.
Download the tarball and its signature for your upgrade, replacing
v1.0 with the target version:
URL=https://github.com/zeppe-lin/pkgsrc-core/releases/download
VERSION=v1.0
wget -c ${URL}/${VERSION}/binpkgs-${VERSION}-x86_64.tar.xz{,.sig}Verify the tarball with gpg(1):
gpg --keyserver keyserver.ubuntu.com --recv-keys 59ec1986fbd902cf
gpg --verify binpkgs-${VERSION}-x86_64.tar.xz{.sig,}Extract the tarball after successful verification:
mkdir -p ~/binpkgs
tar -xf binpkgs-${VERSION}-x86_64.tar.xz -C ~/binpkgs3.2.1.2 Upgrade Core Packages
Navigate to the directory and upgrade core packages:
cd ~/binpkgs
# as root, upgrade all upgradeable packages
for p in *.pkg.tar.gz; do
pkgadd -u "$p"
donepkgadd -u upgrades each package. New, non-upgradable
packages will return an error, which the loop skips, ensuring all
upgradeable packages are updated.
3.2.1.3 Install New Core Packages
Install new core packages introduced in the release:
cd ~/binpkgs
# as root, install all new packages
for p in *.pkg.tar.gz; do
pkgadd "$p"
donepkgadd installs each package. Already installed
packages return an error, which the loop skips to ensure all new
packages are installed.
4 PACKAGE MANAGEMENT
4.1 Introduction
Zeppe-Lin’s package management system revolves around packages and
package sources. Low-level tools handle atomic operations like
building and installation, working with individual package sources or
packages as instructed. The high-level tool pkgman
manages the package source collections and orchestrates these
low-level tasks for system-wide software management.
Packages: Compressed archives (e.g.,
tar.gz) containing pre-built software.Package Sources: Files required to create these compressed archives (packages).
To work with packages and package sources, Zeppe-Lin provides:
Low-level tools:
pkgutils: Installs or upgrades, removes, and inspects packages.rejmerge: Assist with upgrade conflicts.pkgmk: Building packages from sources.
Packages built with
pkgmkare installed or upgraded usingpkgutils, and files rejected during upgrades are resolved withrejmerge.High-level tool:
pkgman: Orchestrates package sources, dependencies, and system updates, integratingpkgutilsandpkgmk.
4.2 What is a Package?
A Zeppe-Lin package is a compressed archive (e.g.,
tar.gz) that contains only the software files. It avoids
any kind of embedded metadata, ensuring simplicity and transparency in
its structure.
4.2.1 Package Naming
Zeppe-Lin packages follow a clear naming convention:
name#version-release.pkg.tar.gz
Components:
name– Package name.version– Version number.release– Build revision.
Example:
ed#1.21-1.pkg.tar.gz
The extension .pkg.tar.gz denotes a Zeppe-Lin package.
Other common compression formats like tar.bz2,
tar.xz, and tar.zst are also supported.
4.2.2 Package Database
The package database, located at /var/lib/pkg/db,
tracks installed packages and their contents. Each package entry
follows this format:
<name> # Package name
<version>-<release> # Version and release
<dir>/ # Top-level directory
<dir>/<subdir> # Subdirectory
<dir>/<subdir>/<file> # File within subdirectory
(Blank line) # Separates package entriesExample entry for ed:
ed
1.21-1
bin/
bin/ed
usr/
usr/share/
usr/share/man/
usr/share/man/man1/
usr/share/man/man1/ed.1.gz
(Blank line)Note:
This database enables essential operations like installation (
pkgadd(8)), removal (pkgrm(8)), and inspection (pkginfo(8)).
4.3 Low-level Tools: pkgutils
pkgutils provides the core utilities to handle
packages:
pkgadd(8): Installs or upgrades packages.pkgrm(8): Removes packages.pkginfo(1): Displays package details.
4.3.1 Using pkgutils
4.3.1.1 Installing a Package
Install a package file with pkgadd(8):
# as root
pkgadd bash#5.0.18-1.pkg.tar.gzBy default, pkgadd(8) prevents overwriting existing
files. Use -f or --force to override this
behavior (use with caution!):
# as root
pkgadd -f bash#5.0.18-1.pkg.tar.gz4.3.1.2 Upgrading a Package
Upgrade a package with the -u or
--upgrade option:
# as root
pkgadd -u bash#5.0.18-1.pkg.tar.gzThis replaces the installed package. If the package is not installed, it will return an error. You can even “upgrade” to an older version.
Files that should not be upgraded (based on
/etc/pkgadd.conf) are placed in
/var/lib/pkg/rejected/.
4.3.1.3 Removing a Package
To remove a package, use pkgrm(8) followed by the
package name:
# as root
pkgrm bashCaution:
This command removes all files owned by the package, without prompting. Misspelling the package name may remove something entirely different (e.g.,
glibvs.glibc).
4.3.1.4 Inspecting Packages
Use pkginfo(1) to get information about packages.
List installed packages and versions:
pkginfo -iList files in a package:
pkginfo -l bashList files in a package archive (before installing):
pkginfo -l grep#2.5-1.pkg.tar.gzFind which package owns a file:
pkginfo -o /usr/bin/lsSee pkgadd(8), pkgrm(8), and
pkginfo(1) for details.
4.3.2 Configuring pkgadd
You can customize pkgadd(8) behavior during package
upgrades using /etc/pkgadd.conf. Rules define whether
files should be upgraded or preserved.
4.3.2.1 Rule Format
Each rule in /etc/pkgadd.conf follows this format:
EVENT PATTERN ACTION
EVENT: Currently, onlyUPGRADEis supported.PATTERN: A regular expression matching filenames in the package.ACTION:YESto upgrade files,NOto preserve them.
Rules are processed sequentially, with the last matching rule taking priority.
4.3.2.2 Example
Example /etc/pkgadd.conf entries:
UPGRADE ^etc/.*$ NO
UPGRADE ^var/log/.*$ NO
UPGRADE ^etc/X11/xorg.conf$ YES
These rules will:
- Keep all files in
/etcand its subdirectories. - Keep all files in
/var/logand its subdirectories. - Upgrade
/etc/X11/xorg.confspecifically (overrides the/etcrule).
Caution:
Patterns match filenames inside the package, not full system paths. Do not use
/at the start!
See pkgadd.conf(5) for details.
4.4 Low-level Tools: rejmerge
rejmerge(8) resolves files rejected during upgrades
using pkgadd -u. Rejected files are moved to
/var/lib/pkg/rejected/ for manual handling, while
rejmerge(8) provides a way to manage these files
semi-automatically.
4.4.1 Using rejmerge
If files are present in /var/lib/pkg/rejected,
rejmerge(8) prompts you to decide their fate. For each
file, you can choose:
=======> file
(diff output between installed file and rejected file)
[K]eep [U]pgrade [M]erge [D]iff [S]kip
Legend:
[K]eep: Retain the current file as it is.[U]pgrade: Replace the current file with the new version.[M]erge: Combine changes from the current and new versions.[D]iff: Display differences between the current and new versions.[S]kip: Defer the decision and revisit it later.
See rejmerge(8) for details.
4.4.2 Configuring rejmerge
Configurations for rejmerge(8) can be adjusted in
/etc/rejmerge.conf. Key settings:
rejmerge_diff: Defines how differences are displayed.rejmerge_merge: Controls how files are merged.EDITOR: Specifies the editor for merges.PAGER: Specifies the pager for differences.
4.4.2.1 Example
Use unified, colorized output for differences:
rejmerge_diff() { diff -u --color=always $1 $2 > $3 ; }Use sdiff(1) for merging files:
rejmerge_merge() { sdiff -o $3 $1 $2 ; }See rejmerge.conf(5) for more details.
4.5 Low-level Tools: pkgmk
pkgmk(8) builds Zeppe-Lin packages (compressed
archives) from source files using a Pkgfile. These files,
along with the supporting directory, form a Package
Source – a self-contained unit that includes all files needed
to build and install software.
A Package Source typically contains:
Pkgfile: Defines metadata and build steps..md5sum: Ensures the integrity of downloaded files..footprint: Lists expected files in the final package.
A Package Source is the basic unit of software organization in Zeppe-Lin. While this section introduces Package Sources in the context of building packages, PACKAGE SOURCES AND COLLECTIONS explores their organization into Collections and Repositories for broader software management workflows.
4.5.1 Pkgfile Format
The Pkgfile defines:
name,version,release: Package identity.source: URL to download the software’s source code.build(): Instructions to compile and package the software.
4.5.1.1 Example
name=hello
version=2.12.1
release=1
source=https://ftp.gnu.org/gnu/hello/$name-$version.tar.gz
build() {
cd $name-$version
./configure --prefix=/usr --disable-nls
make
make DESTDIR=$PKG install
rm -rf $PKG/usr/info
}See pkgmk.Pkgfile(5) for details.
4.5.2 Using pkgmk
4.5.2.1 Building a Package
To build a package, create a directory named after the package,
cd into this directory, place the Pkgfile
inside, and run:
fakeroot pkgmk -d -cf /dev/nullfakeroot: Always use to avoid system risks.-d: Downloads missing source files.-cf /dev/null: Ignores/etc/pkgmk.confand uses defaults.
On the first build, pkgmk(8) generates:
.footprint: Tracks package contents..md5sum: Ensures source files integrity.
The final package (e.g., hello#2.12.1-1.pkg.tar.gz)
will be in the current directory.
4.5.3 Configuring pkgmk
Customize pkgmk(8) with /etc/pkgmk.conf.
Key settings:
CFLAGS,CXXFLAGS: Compiler optimization flags.PKGMK_SOURCE_MIRRORS: Backup URLs for source archives.PKGMK_SOURCE_DIR: Directory for source archives.PKGMK_PACKAGE_DIR: Directory for built packages.PKGMK_WORK_DIR: Temporary build directory.
4.5.3.1 Example
Define backup URLs:
PKGMK_SOURCE_MIRRORS="http://fileserver.intranet/sources/
http://mirror2/sources/"Set a unique work directory:
PKGMK_WORK_DIR="/var/cache/pkgmk/work/$name-$$"Using $name (package name) and $$
(process ID) avoids conflicts during simultaneous builds.
Note:
Although unique directories avoid build conflicts,
pkgadd(8)locks the database, so simultaneous installations may fail.
See pkgmk.conf(5) for full options.
4.6 High-level Tool: pkgman
pkgman(1) serves as a versatile interface for managing
Zeppe-Lin’s package ecosystem. Building on tools like
pkgutils and pkgmk, it unifies and
simplifies workflows while supporting a wide range of package
management tasks.
pkgman(1) empowers users to:
- Handle dependencies and system updates efficiently.
- Automate and streamline build processes.
- Extend functionality with dynamic features and workflows.
With its adaptable design, pkgman(1) integrates
seamlessly into diverse system management scenarios, making it an
indispensable tool for maintaining and customizing Zeppe-Lin.
4.6.1 Using pkgman
4.6.1.1 List Installed Packages
List installed packages:
pkgman listInclude versions:
pkgman list -vInclude versions and descriptions:
pkgman list -vv4.6.1.2 Query Package Information
Display detailed package information:
pkgman info aclExample output:
Name: acl
Path: /usr/src/pkgsrc-core
Version: 2.3.1
Release: 1
Description: Access Control List filesystem support
URL: http://savannah.nongnu.org/projects/acl
Dependencies: attr
4.6.1.3 Search Package Sources
Search by name:
pkgman search -vv glibcSearch using regular expressions:
pkgman search -vv --regex '^(glib)c?$'Search by description:
pkgman dsearch -vv archive4.6.1.4 4.6.1.4. Query Dependencies
Show direct dependencies:
pkgman dep vimShow recursive dependencies:
pkgman dep vim --recursiveShow detailed dependency tree:
pkgman dep vim --recursive --tree4.6.1.5 4.6.1.5. Build and Install Packages
Build and install a package with dependencies (recommended):
# as root
pkgman install --deps --group xtermUse --group to stop installation if a dependency
fails. Retry failed installations:
# as root
pkgman install --deps --group --force xterm--force skips already installed packages during the
retry.
4.6.1.6 4.6.1.6. Update Installed Packages
Identify outdated packages:
pkgman diff --deps --fullUpdate a single package:
# as root
pkgman update --deps --group bindUpgrade all packages in the system:
# as root
pkgman sysup --deps --depsort --group4.6.2 Configuring pkgman
pkgman(1) is configured via
/etc/pkgman.conf. Key settings:
pkgsrcdir: Defines directories for package source collections (you can list multiple). Thepkgsrc-corecollection is enabled by default. See Collections for additional collections.Details about
pkgsrcdirand how it is used to configure Collections and Repositories are explored in next chapter: PACKAGE SOURCES AND COLLECTIONS.runscripts: Enablespre-install,post-install,pre-remove, andpost-removescripts during operations. Enable this option.logfile: Specifies the log file forpkgman(8)operations.
See pkgman.conf(5) for more details.
4.7 The Essentials (outro)
This chapter introduced Zeppe-Lin’s tools for managing individual packages and basic system updates.
In the next chapter, Collections of
Package Sources are introduced — a modular approach
to organizing and managing software — with pkgman serving
as the central orchestration tool.
5 PACKAGE SOURCES AND COLLECTIONS
5.1 Introduction
Zeppe-Lin organizes software sources into three key components:
Package Sources: Self-contained directories that include all files and instructions needed to build and install software. These are the foundation of Zeppe-Lin’s software management.
Collections: Logical groupings of Package Sources, organized by purpose (e.g., core, system tools, desktop applications). Collections simplify software organization and provide modularity.
Repositories: Distributed storage systems that host one or more Collections. Repositories enable versioning, collaboration, and synchronization across systems.
These components provide a structured approach to building,
managing, and distributing software on Zeppe-Lin. Tools like
pkgmk(8) and pkgman(1) are used to interact
with these components, supporting workflows such as dependency
management, package building, and system updates.
5.2 Organizing Package Sources
5.2.1 Package Source: The Core Unit
In Zeppe-Lin, a Package Source is the fundamental unit for building software. Each one represents a single application, library, or utility, organized as a directory with all the necessary files to build and install the software.
Essential files include:
Pkgfile: The main build script. It defines the package’s metadata (name, version, dependencies) and includes the steps for downloading, compiling, and packaging the software usingpkgmk(8).See
pkgmk.Pkgfile(5)for details..md5sum: This file contains checksums for verifying the integrity of downloaded source files. It ensures that the files have not been altered or corrupted during transfer.See
pkgmk.md5sum(5)for details..footprint: Used for build verification, it lists the files expected in the final package. This helps maintain consistency in builds.See
pkgmk.footprint(5)for details.
Some Package Sources may include additional files to support custom builds or configurations:
.32bit: Flag file to trigger 32-bit build mode inpkgmk(8).See
pkgmk.32bit(5)for details..nostrip: Exceptions for stripping executable binaries and libraries.See
pkgmk.nostrip(5)for details.Patch files (
*.patch): Modify the source code before building.Configuration files for scheduled tasks (
cron.*): Useful for automating processes.Scripts for managing services (
rc.*): Enable or disable services automatically.See
rc.d(7)for details.PAM configuration files (
pam.*): Handle user authentication.
Together, these files create a self-contained environment for building and managing software.
5.2.2 Collections
Collections are logical groupings of Package Sources. A Collection is simply a directory containing multiple Package Sources with a shared purpose, like system utilities or desktop applications.
Example Collection structure:
Collection (e.g., pkgsrc-core)
|
|-- acl/ (Package Source)
| |-- Pkgfile
| |-- .md5sum
| `-- .footprint
|
|-- bash/ (Package Source)
| |-- Pkgfile
| |-- .md5sum
| `-- .footprint
|
`-- ... (more Package Sources)
This logical organization enables modular software management. Instead of dealing with individual packages in isolation, Collections provide a structured approach to grouping and managing related sets of software.
Common Collections in Zeppe-Lin:
pkgsrc-core: Core packages for a minimal system.pkgsrc-system: Utilities and system-specific tools.pkgsrc-xorg: X Window System and related tools.pkgsrc-desktop: Desktop applications.
These Collections form the foundation of Zeppe-Lin’s software ecosystem, allowing users to selectively enable the software they need.
5.2.3 Repositories: Distributing and Versioning Collections
Collections are organized into Repositories, hosted on systems like Git. It’s important to note that while a repository can contain multiple collections, Zeppe-Lin’s official repositories adopt a strategy where each repository primarily focuses on a single collection. This design choice is driven by the benefits of allowing users to selectively clone only the collections they need. Repositories provide:
Versioning: Branches manage package sources for specific Zeppe-Lin releases (e.g.,
1.x,2.x), ensuring compatibility.Distribution: Users can clone repositories to access collections and package sources.
The official Zeppe-Lin repositories, following this one-collection-per-repository approach, include:
pkgsrc-core.git: Core packages for a minimal system.pkgsrc-system.git: Utilities and system-specific tools.pkgsrc-xorg.git: X Window System and related tools.pkgsrc-desktop.git: Desktop applications.
Repositories ensure that collections are both modular and manageable, allowing users to selectively clone only the collections they need.
5.3 Managing Package Sources
5.3.1 Setting Up Collections
To access software for installation in Zeppe-Lin, download the
official package source collections and enable them for
pkgman(1).
5.3.1.1 Syncing Official Repositories
Clone the repositories from the Zeppe-Lin GitHub account:
# as root
cd /usr/src/
URL=https://github.com/zeppe-lin
git clone ${URL}/pkgsrc-core --branch 1.x
git clone ${URL}/pkgsrc-system --branch 1.x
git clone ${URL}/pkgsrc-xorg --branch 1.x
git clone ${URL}/pkgsrc-desktop --branch 1.xImportant:
The
1.xbranch applies to all 1. releases (1.0, 1.1, 1.2, …). When a new major line appears, switch to its branch (e.g.,2.x). Verify your release against the current release or the pkgsrc-core releases page.
5.3.1.2 Enabling Collections in pkgman.conf
Edit /etc/pkgman.conf to enable package sources
collections. For example:
pkgsrcdir /usr/src/pkgsrc-core
pkgsrcdir /usr/src/pkgsrc-system
pkgsrcdir /usr/src/pkgsrc-xorg
pkgsrcdir /usr/src/pkgsrc-desktop
For detailed configuration options, see
pkgman.conf(5).
5.3.1.3 Verify Your Setup
Confirm that pkgman(1) recognizes the collections:
pkgman list --allThis lists all package sources from enabled collections.
5.3.2 Exploring and Installing Packages
With collections enabled, you can explore and install packages
using pkgman(1).
5.3.2.1 Listing Available Packages
List all package sources:
pkgman list --allExample output:
-- list ([i] = installed)
[i] acl
[i] bash
[ ] vim
[ ] zathura
...
Legend:
[i]: The package is already installed.[ ]: The package is available but not installed.
To display the full path of each package source (helpful for
identifying which collection a package belongs to), use the
--path option:
pkgman list --all --pathExample output:
[i] /usr/src/pkgsrc-core/acl
[ ] /usr/src/pkgsrc-system/vim
5.3.2.2 Searching for Packages
If you’re looking for specific software, use the
search command. For example, to search for packages
related to alsa:
$ pkgman search alsa
-- search ([i] = installed)
[ ] alsa-lib
[ ] alsa-ucm-conf
[i] alsa-utils
The output indicates which packages are installed and available.
For a detailed search that includes versions, descriptions, and
collection paths, add the -vv and --path
options:
$ pkgman search -vv --path alsa
-- search ([i] = installed)
[ ] /usr/src/pkgsrc-system/alsa-lib 1.2.15.1-1: ALSA libraries
[ ] /usr/src/pkgsrc-system/alsa-ucm-conf 1.2.15.1-1: ALSA Use Case Manager configuration
[i] /usr/src/pkgsrc-system/alsa-utils 1.2.15.1-1: Utilities for the ALSA
5.3.2.3 Building and Installing Packages
Build and install a package with dependencies:
# as root
pkgman install --deps --group <package_name>Example:
# as root
pkgman install --deps --group vimBuild and install multiple packages:
# as root
pkgman install --deps --group vim zathuraFor verbose output (show building process on stdout):
# as root
pkgman install -vv --deps --group vim zathuraDry run:
# as root
pkgman install -vv --test --deps --group vim zathuraTip:
Use
pkgman searchto locate package names.
Run pkgman install --help or see
pkgman-install(8) for information about all installation
options.
5.3.3 Keeping Your System Up-to-Date
Maintaining your Zeppe-Lin system involves two primary tasks:
- Sync your Repositories regularly to stay up-to-date.
- Updating installed packages to their latest versions.
5.3.3.1 Synchronizing Local Collections
Regularly sync local collections with remote repositories using
git pull:
# as root
git -C /usr/src/pkgsrc-core pull
git -C /usr/src/pkgsrc-system pull
git -C /usr/src/pkgsrc-xorg pull
git -C /usr/src/pkgsrc-desktop pullInclude unofficial collections if applicable.
Automate Syncing: Set up a cron job with crond(8):
# Weekly sync at 3:00 AM on Sundays
0 3 * * 0 run-one git -C /usr/src/pkgsrc-core pull -q
0 3 * * 0 run-one git -C /usr/src/pkgsrc-system pull -q
0 3 * * 0 run-one git -C /usr/src/pkgsrc-xorg pull -q
0 3 * * 0 run-one git -C /usr/src/pkgsrc-desktop pull -q
Important:
Ensure
run-onepackage frompkgsrc-corecollection is installed.
5.3.3.2 Checking for Package Updates
Once the local collections are synced, identify outdated packages
with pkgman diff:
pkgman diff --deps --fullExample output:
-- Differences between installed packages and packages sources tree
Package Installed Available
feh 3.7.2-1 3.7.2-2
screen 4.9.0-1 5.0.0-1
...
-- Packages not found in the packages sources tree
Package Installed Required by
libncurses 6.2-1 vim
Review this output to determine which packages need updates. Packages in the “not found” section may have been removed from the collection or installed manually from other sources.
5.3.3.3 Updating Packages
To upgrade the system, start by downloading all required source files. This ensures the upgrade won’t be interrupted by missing files.
# as root
pkgman sysup -doOnce the sources are downloaded, upgrade the packages with proper dependency handling and ordering:
# as root
pkgman sysup --deps --depsort --groupOptions explained:
--deps
Include all dependencies of the packages in the update process.--depsort
Sort packages by dependency order before updating.--group
Update all packages in order, stopping immediately if the update of any package fails. Useful for updating dependent packages sequentially.
5.3.3.4 Updating Specific Packages
Update individual packages with pkgman update. For
example:
# as root
pkgman update --deps --depsort --group screen fehThis command updates only the specified packages while resolving their dependencies.
5.3.4 Advanced Package Management
5.3.4.1 Detecting Broken Dependencies with revdep(1)
revdep(1) checks installed packages for missing or
incorrect shared libraries. Use it to verify system stability and
identify packages needing a rebuild after updates.
Check system-wide for broken libraries:
revdepRebuild affected packages:
# as root
pkgman update -fr $(revdep)Inspect a specific package:
revdep -p bashRun revdep regularly after updates or repository syncs
to ensure all packages remain functional.
See revdep(1) and revdep.d(5) for more
information.
5.3.4.2 Ignoring Packages During Updates
Prevent updates to specific packages during system upgrades with
--ignore. Example:
# as root
pkgman sysup --deps --depsort --group --ignore=linux,linux-firmwareRegularly revisit ignored packages to avoid security risks and dependency conflicts.
5.3.4.3 Locking Packages
Lock a package to prevent upgrades indefinitely:
# as root
pkgman lock linuxUnlock a package to resume updates:
# as root
pkgman unlock linuxLocked packages are useful for maintaining specific software versions critical to workflows.
See pkgman-lock(8), pkgman-unlock(8), and
pkgman-list-locked(1) for more information.
5.3.4.4 Handling Lower Available Versions
Occasionally, a package source may revert to a lower version than
the one installed on your system. This often happens when maintainers
roll back to a stable release after issues with a newer version. By
default, pkgman does not prioritize installed versions
over available ones.
To override this behavior, enable the preferhigher
option:
# as root
pkgman --config-set="preferhigher yes" sysup --deps --depsortThis ensures pkgman retains the higher installed
version during upgrades. Use this feature cautiously, as higher
versions might be less stable or unsupported.
5.3.4.5 Practical Considerations
Regularly review ignored and locked packages for security and compatibility.
Avoid using
preferhigherwithout understanding the implications of using potentially unstable software.Check dependency trees carefully to prevent system breakages.
5.4 Extending Software Sources
5.4.1 Adding a Local Collection
This section explains how to create custom collections. A local collection allows you to add new packages that are not available in the official repositories.
5.4.1.1 Creating the Collection Directory
Create your local collection directory in /usr/src,
alongside official Zeppe-Lin collections. Using directories with
broader read permissions ensures that unprivileged users like
pkgmk can access the collection.
Example:
# as root
cd /usr/src
mkdir mynewcollection5.4.1.2 Enabling the Collection in pkgman.conf
Add your collection to /etc/pkgman.conf. List it above
official collections to give it search priority:
pkgsrcdir /usr/src/mynewcollection
pkgsrcdir /usr/src/pkgsrc-core
pkgsrcdir /usr/src/pkgsrc-system
pkgsrcdir /usr/src/pkgsrc-xorg
Save the file and proceed to verify the setup.
5.4.1.3 Verifying the Collection Setup
Verify that pkgman(1) recognizes your collection:
pkgman dumpconfigCheck the “Packages sources directories” section for your collection:
Packages sources directories: <n>
/usr/src/mynewcollection <-- here
/usr/src/pkgsrc-core
/usr/src/pkgsrc-system
/usr/src/pkgsrc-xorg
...
If it appears, the setup is complete, and you can start adding package sources.
5.4.2 Creating Custom Packages
After setting up your local collection, the next step is to add a
package source. This involves creating a directory for the package and
writing a Pkgfile with build instructions and
metadata.
5.4.2.1 Creating the Package Directory
Create a subdirectory for the new package in your local collection.
Ensure the directory name matches the package name in the
Pkgfile:
# mkdir /usr/src/mynewcollection/hello
# cd /usr/src/mynewcollection/hello
Important:
Naming consistency is critical. A mismatch between the directory name and
namein thePkgfilecause build error.
5.4.2.2 Writing the Pkgfile
The Pkgfile serves two purposes:
- Provides build instructions for
pkgmk(8). - Supplies metadata for
pkgman(1)to enable dependency resolution, search, and queries.
Example Pkgfile:
# Description: Example package based on GNU hello
# URL: https://www.gnu.org/software/hello/
# Depends on: glibc
name=hello
version=2.12.1
release=1
source=https://ftp.gnu.org/gnu/hello/$name-$version.tar.gz
build() {
cd $name-$version
./configure --prefix=/usr --disable-nls
make V=1
make DESTDIR=$PKG install
rm -rf $PKG/usr/share/info
}5.4.2.3 Key Metadata Headers for pkgman
Include these headers in the Pkgfile for optimal
integration with pkgman(1):
# Description
Brief summary of the package.# URL
Link to official documentation or website.# Depends on
List of dependencies.pkgman(1)resolves and installs these automatically.
Important:
Without these headers,pkgman(1)cannot display metadata or resolve dependencies.
5.4.2.4 Verifying the Package Source
Verify your package metadata with:
$ pkgman info hello
Name: hello
Path: /usr/src/mynewcollection/hello
Version: 2.12.1
Release: 1
Description: Example package based on GNU hello
URL: https://www.gnu.org/software/hello/
Depends on: glibc
If metadata is missing, review the Pkgfile for
errors.
5.4.3 Building and Installing Custom Packages
After creating a custom package source, the next step is to build
and install the package using pkgman(1) and
pkgmk(8), addressing any potential permission issues.
5.4.3.1 Building the Package
Build your custom package with:
# as root
pkgman install -vv --deps helloThis command:
- Downloads source files if not cached.
- Builds the package using
pkgmk(8). - Installs the package with
pkgadd(8).
Note:
Warnings about missing
.md5sumand.footprintfiles like/usr/bin/pkgmk: ... cannot create .md5sum: Permission deniedoccur because packages are built with the unprivilegedpkgmkuser, which has not write permissions in/usr/src/mynewcollection.
5.4.3.2 Resolving Permissions for Build Files
There are at least two options to resolve permissions case.
Manually Updating Files.
Navigate to the package directory and generate the files:
# as root cd /usr/src/mynewcollection/hello pkgmk -um # Update .md5sum pkgmk -uf # Update .footprintAdjusting Permissions.
Grant write access to
pkgmkusingsetfacl(1):# as root setfacl -m u:pkgmk:rwx /usr/src/mynewcollection/helloRebuild the package afterward:
# as root pkgman update -fr hello
5.4.3.3 Verifying Generated Files
After addressing warnings, confirm the presence of required files:
$ ls -l /usr/src/mynewcollection/hello
-rw-r--r-- 1 pkgmk pkgmk 251 .footprint
-rw-r--r-- 1 pkgmk pkgmk 54 .md5sum
-rw-r--r-- 1 root root 359 Pkgfile
5.4.3.4 Verifying the Installation
Ensure the package is installed on your system:
$ pkgman isinst hello
package 'hello' is installed
Run:
$ hello
Hello, world!
5.4.4 Building Packages from Bleeding-Edge Sources
Some packages need to be built directly from version control systems (VCS) like Git or Subversion, instead of fixed release archives. This section outlines two approaches: a stable approach and a bleeding-edge approach.
5.4.4.1 Stable Commit Approach
For production, pinning to a specific commit ensures consistent builds. Example:
# Description: Ratpoison window manager
# URL: https://www.nongnu.org/ratpoison/
# Depends on: xorg-server
name=ratpoison
version=1.4.9-db94d49 # Release + commit hash
release=1
# Custom function to fetch or clone git repository
download_git() {
if [ -d $PKGMK_SOURCE_DIR/$name ]; then
git -C $PKGMK_SOURCE_DIR/$name fetch --depth=1
git -C $PKGMK_SOURCE_DIR/$name clean -f
git -C $PKGMK_SOURCE_DIR/$name reset --hard origin/$2
else
git -C $PKGMK_SOURCE_DIR clone --depth=1 $1 -b $2 $name
fi
cp -r $PKGMK_SOURCE_DIR/$name $PKGMK_WORK_DIR/src/$name
}
build() {
download_git https://git.savannah.nongnu.org/git/ratpoison.git master
cd ratpoison
git checkout ${version#*-} # Pin commit 'db94d49'
./configure --prefix=/usr
make V=1
make DESTDIR=$PKG install
}Pinning builds guarantees stability and shields against upstream changes.
5.4.4.2 Bleeding-Edge Approach
For testing, dynamically set the version to the current date
(YYYYMMDD) to track upstream changes. Example:
# Description: Ruby interpreter (bleeding-edge)
# URL: http://www.ruby-lang.org
# Depends on: gdbm libgmp openssl zlib libffi libyaml
name=ruby-scm
version=$(date +%Y%m%d) # Version updates daily to track build date
release=1
download_git() {
if [ -d $PKGMK_SOURCE_DIR/$name ]; then
git -C $PKGMK_SOURCE_DIR/$name fetch --depth=1
git -C $PKGMK_SOURCE_DIR/$name clean -f
git -C $PKGMK_SOURCE_DIR/$name reset --hard origin/$2
else
git -C $PKGMK_SOURCE_DIR clone --depth=1 $1 -b $2 $name
fi
cp -r $PKGMK_SOURCE_DIR/$name $PKGMK_WORK_DIR/src/$name
}
build() {
download_git https://github.com/ruby/ruby master
cd ruby-scm
./configure --prefix=/usr
make V=1
make DESTDIR=$PKG install
}“Daily Updates”: If the installed version is
outdated, pkgman(1) flags it during
pkgman diff, prompting updates:
pkgman diffExpected output:
-- Differences between installed packages and packages sources tree
ruby-scm 20250216-1 20250401-1
This approach is ideal for development but unsuitable for production environments.
5.4.4.3 Subversion Repository Download Function
For Subversion-based builds, use a download function like this:
download_svn() {
if [ -d $PKGMK_SOURCE_DIR/$name ]; then
svn cleanup $PKGMK_SOURCE_DIR/$name
svn up $PKGMK_SOURCE_DIR/$name
else
svn co $1 $PKGMK_SOURCE_DIR/$name
fi
cp -r $PKGMK_SOURCE_DIR/$name $PKGMK_WORK_DIR/src/$name
}Example usage in a Pkgfile:
download_svn https://svn.project.org/svn/program/trunkAdd subversion to dependencies for compatibility.
Unlike git, which resides in pkgsrc-core,
subversion requires explicit declaration.
5.4.4.4 Best Practices
- Use pinned commits or snapshots for stability in production.
- Reserve bleeding-edge builds for testing and development.
- Include download functions (
download_gitordownload_svn) directly inPkgfilefor portability.
5.5 Tips and Best Practices
5.5.1 Renicing Builds
Package builds can reduce system responsiveness due to high CPU and
I/O usage. Mitigate this by adjusting process priorities using
nice(1) and ionice(1):
nice(1): Lowers CPU priority (higher number = lower priority).ionice(1): Adjusts I/O priority (class 2, priority 6 is commonly used).
Update the makecommand in
/etc/pkgman.conf:
makecommand sudo -H -u pkgmk nice -n10 ionice -c2 -n6 fakeroot pkgmk
Explanation:
nice -n10: Reduces CPU priority (10 = relatively low).ionice -c2 -n6: Reduces I/O priority (class 2, priority 6).
These changes help the build process interfere less with interactive tasks, improving system responsiveness.
5.5.2 RAM Builds for Faster Package Compilation
Using RAM for temporary build files (tmpfs) can
significantly speed up package compilation in Zeppe-Lin.
5.5.2.1 Enable RAM Builds in Zeppe-Lin
Uncomment this line in
/etc/fstab:pkgmk /var/cache/pkgmk/work tmpfs size=<SIZE>,uid=<UID>,defaults 0 0Replace
SIZE(e.g.,16G). TheUIDfor thepkgmkuser is preconfigured.Mount
tmpfs:# as root mount pkgmkRemove
-pipefromCFLAGSandCXXFLAGSin/etc/pkgmk.conf.
5.5.2.2 RAM Build Configuration (Educational)
For users interested in customizing the setup:
Creating a dedicated build user:
# as root useradd -b /var/cache/ -m -s /bin/false -U pkgmkSetting up build directories and assigning ownership:
# as root mkdir -p /var/cache/pkgmk/{sources,packages,work} chown -R pkgmk:pkgmk /var/cache/pkgmk/{sources,packages,work}Configuring
tmpfsin/etc/fstab:pkgmk /var/cache/pkgmk/work tmpfs size=<SIZE>,uid=<UID>,defaults 0 0Setting the work directory in
/etc/pkgmk.conf:PKGMK_WORK_DIR="/var/cache/pkgmk/work/$name"Removing
-pipefromCFLAGSandCXXFLAGSin/etc/pkgmk.conf.
5.5.3 Unprivileged Builds in Zeppe-Lin
Zeppe-Lin builds packages as an unprivileged user (typically
pkgmk) by default. This secure and modular setup isolates
the build process to mitigate risks. If you are using
Zeppe-Lin, these steps are already configured out of the box.
There is no need to repeat them.
However, this guide is provided for educational purposes, to show how it was achieved, or for users wanting to adapt this approach for other distributions or customizations.
Create a Dedicated Build User. A restricted user is used to perform package builds securely:
# as root useradd -b /var/cache/ -m -s /bin/false -U pkgmkThis creates a user and group named
pkgmkwith limited shell access.Set Up Build Directories. Directories for sources, packages, and temporary files are created and assigned ownership to the
pkgmkuser:# as root mkdir -p /var/cache/pkgmk/{sources,packages,work} chown -R pkgmk:pkgmk /var/cache/pkgmk/{sources,packages,work}Configure
pkgmk. In/etc/pkgmk.conf, the paths for these directories are defined:PKGMK_SOURCE_DIR="/var/cache/pkgmk/sources" PKGMK_PACKAGE_DIR="/var/cache/pkgmk/packages" PKGMK_WORK_DIR="/var/cache/pkgmk/work/$name-$$"Integrate
pkgman. In/etc/pkgman.conf, themakecommandvariable is updated to runpkgmk(8)as the unprivilegedpkgmkuser viasudo(8)andfakeroot(1):makecommand sudo -H -u pkgmk fakeroot pkgmk
This structure ensures package builds are securely isolated while remaining flexible for adaptations.
6 CONFIGURATION
6.1 Generating Locales
In Zeppe-Lin, glibc package includes a minimal set of
locales by default, with C.UTF-8 generated for
compatibility with pkgmk(8). To create additional
locales, replace en_US with your desired locale and
run:
# as root
localedef -i en_US -f UTF-8 en_US.UTF-8Set the system default locale by adding it to
/etc/profile:
export LANG=en_US.UTF-8This ensures consistent locale settings across your system.
6.2 System Initialization and Configuration
Zeppe-Lin uses a lightweight BSD-style init system to manage
startup, services, and shutdown. This system relies on shell scripts
located in /etc and /etc/rc.d, offering an
efficient and flexible way to control processes.
6.2.1 System States (Runlevels)
Runlevels define the operating state of the system, such as
halting, rebooting, or normal operation. Zeppe-Lin’s runlevels are
configured in /etc/inittab:
| Runlevel | State | Purpose |
|---|---|---|
| 0 | Halt | Shut down the system completely |
| 1 (S) | Single-User Mode | Maintenance mode with minimal setup |
| 2 | Multi-User Mode | Full system operation with multiple users |
| 3-5 | Unused | Reserved for custom use |
| 6 | Reboot | Restart the system |
By default, Zeppe-Lin boots into multi-user mode (runlevel 2), which enables all services and user access. Single-user mode (runlevel 1 or S) is ideal for system maintenance, providing a minimal environment.
6.2.2 Core Init Scripts
Zeppe-Lin’s init system uses the following scripts to manage system processes:
| File/Directory | Purpose |
|---|---|
| /etc/rc | Main system boot script, invoked by init(8) |
| /etc/rc.modules | Kernel module initialization, invoked by /etc/rc |
| /etc/rc.single | Single-user mode script for maintenance tasks |
| /etc/rc.multi | Multi-user mode script for normal operation |
| /etc/rc.local | Custom commands executed after /etc/rc.multi during
normal boot |
| /etc/rc.d | Directory containing scripts to control individual services |
| /etc/rc.shutdown | Script invoked by shutdown(8) to gracefully stop
services |
Customize system behavior by modifying /etc/rc.local
for personal commands or /etc/rc.modules to load specific
kernel modules.
See rc(8) for details.
6.2.3 Configuring Runlevels and Init Behavior
The /etc/inittab file determines actions for each
runlevel. Each entry follows this format:
id:runlevel:action:command
Key Components:
id: Unique entry identifier.runlevel: Runlevels the command applies to.action: Specifies when the command runs (e.g., on boot, shutdown).command: The script or program to execute.
Example /etc/inittab Configuration:
# Set default runlevel to multi-user mode
id:2:initdefault:
# Core startup scripts
rc::sysinit:/etc/rc # Main boot script
rs:S1:wait:/etc/rc.single # Single-user mode startup
rm:2:wait:/etc/rc.multi # Multi-user mode startup
rd:06:wait:/etc/rc.shutdown # Graceful shutdown
# Virtual console login prompts
c1:2:respawn:/sbin/agetty --noclear 38400 tty1 linux
c2:2:respawn:/sbin/agetty 38400 tty2 linuxThis configuration ensures a smooth startup, runtime, and shutdown
process. See inittab(5) for configuration details.
6.2.4 Configuring System Behavior (/etc/rc.conf)
The /etc/rc.conf file centralizes system configuration
settings, such as hostname, timezone, and services. Example:
HOSTNAME="myhostname"
TIMEZONE="Europe/Berlin"
SERVICES="lo crond sshd"Services listed in SERVICES correspond to scripts in
/etc/rc.d/, which are started by
/etc/rc.multi and stopped by
/etc/rc.shutdown (in reverse order).
See rc.conf(5) for additional configuration
settings.
6.2.5 Service Control Scripts (/etc/rc.d/)
The /etc/rc.d/ directory contains individual scripts
to manage services. Each script supports commands like:
start: Activate the service.stop: Terminates the service.restart: Stop and then start the service.status: Check if the service is running.
Example usage:
# as root
/etc/rc.d/sshd start
/etc/rc.d/sshd statusSee rc.d(7) for more information.
6.2.6 Kernel Module Management (/etc/rc.modules)
The /etc/rc.modules script is used to initialize
kernel modules at boot. It begins by running
/sbin/depmod -a to refresh the module dependency map,
ensuring correct load order.
After this, rc.modules delegates to the standalone
modules-load(8) utility. This utility reads configuration
files from the following directories:
/etc/modules-load.d— administrator overrides/run/modules-load.d— runtime configuration/lib/modules-load.d— vendor defaults
Files must end with .conf and contain one module name
per line. Empty lines and lines beginning with # are
ignored. An empty or comment-only file in
/etc/modules-load.d disables vendor or runtime lists of
the same name.
Example configuration file
/etc/modules-load.d/virtio.conf:
# Load virtio drivers at boot
virtio-net
virtio-blkNote:
For the design reasoning behindmodules-loadand its configuration directories, see RATIONALE.md in the source tree.
For modules requiring parameters, configure them in
/etc/modprobe.d/ for persistent management.
For example, to set options for the snd_hda_intel module,
create /etc/modprobe.d/snd_hda_intel.conf:
# Example: limit snd_hda_intel probing to a specific device
# (probe_mask is hardware-dependent; 8 is only an example)
options snd_hda_intel probe_mask=8This ensures parameters are automatically applied whenever the module is loaded, avoiding manual specification and following best practice.
Custom one-off module commands may still be added directly to
/etc/rc.modules after the modules-load call,
e.g.:
# Example: load loopback block device support at boot
/sbin/modprobe loop
# Example: force-load Intel HDA sound driver at boot
# (normally auto-loaded; shown here for illustration)
/sbin/modprobe snd_hda_intelThe /etc/rc.modules script itself is invoked by
/etc/rc during the boot process.
6.2.7 Custom Startup Commands (/etc/rc.local)
User-defined actions are added to /etc/rc.local,
executed as last step of a normal boot (invoked by
/etc/rc.multi). Example:
# Start a monitoring app
/usr/bin/my_monitoring_app &6.2.8 From Boot to Login: System Startup Sequence
Here’s the sequence from power-up to login. It differs slightly
with or without initramfs.
6.2.8.1 Without Initramfs
- Power On: System starts.
- Bootloader: Loads the kernel into memory.
- Kernel starts: Initializes hardware and memory.
/sbin/initstarts: The first user-space process (PID 1)./etc/inittabis read:initgets its instructions./etc/rcruns: The main boot script executes.- Runlevel is set: The default runlevel (usually 2) is chosen.
/etc/rc.multistarts services: Services from/etc/rc.confare launched./etc/rc.localruns: Your custom commands are executed.- Login prompts: The system is ready for you.
6.2.8.2 With Initramfs
- Power On: System starts.
- Bootloader: Loads kernel and initramfs into memory.
- Kernel starts: Initializes basic hardware.
initramfsmounts: A temporary root filesystem in RAM./initfrominitramfsruns: Performs early setup (e.g., storage drivers).- Real root mounts: Your main filesystem is mounted.
- Root is switched: System moves from initramfs to your real root.
/sbin/initon real root starts: The init process from your main system.- (Steps 5-10 from Without Initramfs follow).
6.2.9 Minimal Mode (Single-User Mode)
Runlevel 1 or S boots the system
with a minimal setup for maintenance. It runs
/etc/rc.single, providing a root shell for
troubleshooting.
6.2.10 Graceful Shutdown Procedure
When shutting down or rebooting, /etc/rc.shutdown is
invoked to stop services, unmount filesystems, and safely power off
the system.
6.3 Networking
6.3.1 Hostname Configuration
The hostname identifies your system on the network.
To set it temporarily, use:
# as root
hostname <new_hostname>For a permanent setting, edit /etc/rc.conf and
set:
HOSTNAME='<new_hostname>'For proper network function, edit /etc/hosts and add
your hostname to the loopback lines:
127.0.0.1 localhost <new_hostname>
::1 localhost <new_hostname>
This ensures your system recognizes its own name.
6.3.2 Static Address
To configure a static IP, edit /etc/rc.d/net. Set the
network interface, IP, subnet mask, and gateway. For example:
DEV=enp11s0
ADDR=192.168.1.100
MASK=24
GW=192.168.1.1Set DNS in /etc/resolv.conf:
search <your internal domain>
nameserver <your DNS server>
Start, stop or restart the service via:
# as root
/etc/rc.d/net [start|stop|restart]Important:
To auto-start service at boot, add
netto theSERVICESline in/etc/rc.conf.
6.3.3 Dynamic Address
To get an IP address automatically via DHCP, install the
dhcpcd package and edit /etc/rc.d/dhcpcd to
specify the network interface (e.g., enp5s0):
DEV=enp5s0Start, stop, or restart the service via:
# as root
/etc/rc.d/dhcpcd [start|stop|restart]Check dhcpcd’s README for potential issues:
pkgman readme dhcpcdImportant:
To auto-start service at boot, add
dhcpcdto theSERVICESline in/etc/rc.conf.
6.3.4 Wireless Network
Ensure the wireless interface isn’t blocked. Use
rfkill(8):
rfkill list
# as root
rfkill unblock <ID|TYPE>Install the wpa-supplicant package and edit
/etc/rc.d/wpa_supplicant to set the wireless
interface:
DEV=wlp1s0Update /etc/wpa_supplicant.conf based on your network
settings. Common security configurations follow.
6.3.4.1 WPA-PSK (Pre-Shared Key)
Generate a key with wpa_passphrase(8):
wpa_passphrase <MYSSID> <PASSPHRASE>Example /etc/wpa_supplicant.conf:
network={
ssid="YOUR_NETWORK_NAME"
psk="THE_GENERATED_KEY"
}
6.3.4.2 WPA-EAP (Enterprise)
Generate a password hash:
echo -n <PASSPHRASE> | iconv -t utf16le | openssl md4Example /etc/wpa_supplicant.conf:
network={
ssid="YOUR_NETWORK_NAME"
key_mgmt=WPA-EAP
identity="YOUR_USERNAME"
password=hash:<YOUR_PASSWORD_HASH>
}
6.3.4.3 WEP
Example /etc/wpa_supplicant.conf for WEP:
network={
ssid="YOUR_NETWORK_NAME"
key_mgmt=NONE
wep_key0="YOUR_WEP_KEY"
wep_tx_keyidx=0
auth_alg=SHARED
}
For automatic IP, ensure the wireless interface is set in
/etc/rc.d/dhcpcd. Start the services:
# as root
/etc/rc.d/wpa_supplicant start
/etc/rc.d/dhcpcd startImportant:
To auto-start service at boot, add
wpa_supplicant(anddhcpcdif using dynamic IP) to theSERVICESline in/etc/rc.conf.
6.4 Time and Date Configuration
6.4.1 Timezone Setup
Select your timezone from /usr/share/zoneinfo (e.g.,
Europe/Berlin).
Set the timezone immediately:
# as root
ln -sfn /usr/share/zoneinfo/Europe/Berlin /etc/localtimeTo make it persistent, add the timezone to
/etc/rc.conf:
TIMEZONE="Europe/Berlin"6.4.2 System Clock Setup
Manually set the system clock using the
MMDDhhmmYYYY.ss format:
# as root
# Example: March 27, 05:35, 2025
date 032705352025.00Important:
Manual configuration is temporary. Use NTP for continuous synchronization (described next).
6.4.3 Network Time Protocol (NTP) Configuration
Note:
Accurate time via NTP is crucial for time-sensitive things like OTP.
Use an NTP client, such as chrony, to synchronize the
system clock.
After installing chrony, start, stop, or restart the
service via:
# as root
/etc/rc.d/chrony [start|stop|restart]Important:
To enable automatic startup, add
chronyto theSERVICESline in/etc/rc.conf.
6.5 User Authentication and Environment
This section explains Zeppe-Lin’s approach to user authentication, environment setup, and PAM (Pluggable Authentication Modules).
6.5.1 Password Management
Zeppe-Lin uses libxcrypt to provide the
crypt(3) API for password hashing.
The default hash algorithm is SHA-512, ensuring strong security. Legacy algorithms (MD5, traditional DES) are supported for compatibility, but their use is discouraged.
Programs that authenticate users via crypt(3) must
link against libxcrypt (-lcrypt).
System-wide password policies are defined in
/etc/login.defs. Key parameters include:
PASS_MAX_DAYS— Maximum password age.PASS_MIN_DAYS— Minimum password age.PASS_WARN_AGE— Days before expiration to warn users.
Use passwd(1) to set or change user passwords. SHA-512
is recommended for all accounts.
6.5.2 User Environment
User accounts are created via useradd(8) according to
/etc/login.defs.
Home directories created with useradd -m are empty by
default. To provide default files, use /etc/skel.
The default shell PATH is defined in
/etc/profile:
/sbin:/usr/sbin:/bin:/usr/binThis allows access to administrative commands without specifying full paths.
6.5.3 Pluggable Authentication Modules (PAM)
Zeppe-Lin uses PAM for authentication, session management, and resource control.
PAM configuration files are located in /etc/pam.d.
Each file corresponds to a specific service (e.g., login,
su, sshd). Key modules included:
pam_dumb_runtime_dir.so
CreatesXDG_RUNTIME_DIRon login. Required for Wayland, PipeWire, and other XDG-compliant environments.pam_env.so
Exports environment variables from/etc/security/pam_env.confand/etc/environment, enabling system-wide settings for users.pam_limits.so
Enforces resource limits (max processes, open files) defined in/etc/security/limits.conf.
For advanced configurations, consult module-specific man pages
(e.g., pam_dumb_runtime_dir(8), pam_env(8),
pam_limits(8), pam_exec(8)).
7 APPENDICES
7.1 Appendix A: Licensing & Legal
This appendix summarizes the licensing and legal terms applicable to Zeppe-Lin, including software components, build scripts, website content, and artwork.
7.1.1 Software & Packages
Zeppe-Lin is composed entirely of free and open-source software obtained from publicly available upstream projects.
Each package retains its original upstream license (including GPL, BSD, MIT, Apache, and others). Zeppe-Lin does not relicense, restrict, or replace upstream licensing terms.
The distributed root filesystem and any binary packages are built from these sources without the inclusion of proprietary software. Patches applied during the build process are limited to correctness, portability, or security fixes and do not alter licensing conditions.
Redistribution and use of binaries are governed solely by the licenses of the upstream projects from which they originate.
7.1.2 Build Scripts
Build scripts and related tooling are derived from CRUX and extended by the Zeppe-Lin project.
- © 2000-2021 Per Lidén and the CRUX Team
- © 2022-2026 Alexandr Savca and Zeppe-Lin Team
These scripts are licensed under the GNU General Public License version 3 or later (GPLv3+).
7.1.3 Website & Artwork
Website content and visual assets, including documentation text, branding, and release artwork, are maintained by the Zeppe-Lin project.
- © 2022-2026 Alexandr Savca and Zeppe-Lin Team
This material is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License (CC-BY-SA 3.0).
This license applies only to website content and artwork. Source code, packages, and build scripts are governed by their respective licenses.
Artwork repository: https://github.com/zeppe-lin/artwork
Website repository: https://github.com/zeppe-lin/zeppe-lin.github.io/
7.1.4 Disclaimer
Zeppe-Lin is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Use it at YOUR OWN RISK.
7.2 Appendix B: Troubleshooting
This appendix collects solutions to common issues in Zeppe‑Lin. Topics are grouped by area for easier navigation.
7.2.1 dhcpcd Networking Issues
7.2.1.1 Overview
Covers common problems with dhcpcd, including carrier
loss, client ID mismatches, and noncompliant routers. Edit
/etc/dhcpcd/dhcpcd.conf to apply fixes.
7.2.1.2 Carrier Lost
If dhcpcd logs show messages like:
dhcpcd[852]: enp0s31f6: carrier lost
or
dhcpcd[852]: enp0s31f6: waiting for carrier
dhcpcd[852]: carrier acquired
dhcpcd[852]: soliciting an IPv6 router
dhcpcd[852]: no global addresses for default route
dhcpcd[852]: timed out
You may try adding the following options to
/etc/dhcpcd/dhcpcd.conf:
nolink # Ignore carrier status messages (for buggy drivers)
noipv6 # Disable IPv6 router advertisements7.2.1.3 Client ID Issues
If your DHCPv4 network filters Client IDs by MAC address, change:
duid
To:
clientid
This forces dhcpcd to use the hardware MAC address for
DHCPv4, avoiding issues with RFC4361-style identifiers. See RFC 4361 for
details.
7.2.1.4 Noncompliant Routers
Some routers reject requests unless you comment out:
require dhcp_server_identifier
This is safe unless you have multiple DHCP servers on the same network. See Microsoft Technet for background.
7.2.1.5 Quick Summary
Use
nolinkandnoipv6to handle carrier loss.Switch from
duidtoclientidfor DHCPv4 MAC-based networks.Comment out
require dhcp_server_identifierfor noncompliant routers.
7.3 Appendix C: Frequently Asked Questions
This appendix collects common questions about Zeppe‑Lin. Questions are grouped by topic for easier navigation.
7.3.1 General
Why is the distribution named Zeppe-Lin?
The name is a deliberate nod to classic UNIX culture and the early era of Linux experimentation. It reflects the project’s appreciation for engineering craft, simplicity, and a certain irreverent independence.
The name carries no technical meaning and should not be over-interpreted.
Or, if you prefer, you can consider it our “Whole Lotta Love” for Linux and GNU — just renamed!
Is Zeppe-Lin a fork of another distribution?
Yes. Zeppe‑Lin is a fork of CRUX, a lightweight, source‑based Linux distribution.
It inherits CRUX’s minimalist philosophy and tooling, but evolves them independently, with its own design decisions and policies.
What makes Zeppe-Lin different from CRUX or KISS Linux?
Zeppe-Lin focuses on practical minimalism rather than extreme reduction or strict preservation of legacy behavior.
Compared to CRUX, Zeppe-Lin actively refactors core tooling instead of keeping it unchanged for compatibility’s sake. Package management, build utilities, and system tools are reorganized for clarity, consistency, and long-term maintainability.
Compared to KISS Linux, Zeppe-Lin favors clear structure and explicit behavior over minimal code size. It is willing to use more capable implementations when they improve correctness, auditability, or usability.
Across the system, Zeppe-Lin generally favors:
- POSIX-compliant sh(1p) instead of Bash
- Explicit configuration over implicit behavior
- Manual pages as a primary interface
- Removal of obsolete or redundant mechanisms
- Readable, structured implementations rather than ad-hoc scripts
Zeppe-Lin does not aim to be the smallest possible system. It aims to remain understandable and controllable as it evolves.
Is Zeppe-Lin suitable for beginners?
No. Zeppe-Lin assumes prior Linux experience. Users are expected to be comfortable with the command line, manual configuration, and building software from source.
It is not designed to be beginner-friendly, automated, or “hands-off”.
7.3.2 Installation
I can’t find the Zeppe‑Lin installation CD/DVD. Did I miss something?
No installation media exists. Zeppe-Lin is installed using a minimal root filesystem tarball. Installation is performed from a live environment of your choice.
Why is there no installer?
An installer would obscure system layout and behavior behind automation.
Zeppe-Lin intentionally exposes system setup so users understand what is installed, how it is configured, and why it works. This approach aligns with the project’s emphasis on clarity and control.
7.3.3 Configuration
Does Zeppe-Lin use systemd?
No. Zeppe-Lin uses a traditional, script-based init system.
Service management is explicit and readable, and does not rely on a monolithic service manager.
7.3.4 Packages and Features
Where is the package or feature I need?
Zeppe-Lin is community-driven. If a package or feature is missing, users are encouraged to add it.
Follow the packaging(7) guidelines and submit a pull
request to the appropriate repository.
The system evolves through user contributions rather than centralized curation.
Why are some familiar CRUX tools missing or replaced?
Some tools were removed or replaced because their original design goals no longer aligned with Zeppe-Lin’s direction.
When this happens, replacements are chosen to be simpler, more explicit, or easier to maintain. Each major tool includes documentation explaining its design and differences.
7.3.5 Maintenance
How often does Zeppe-Lin release new versions?
Zeppe-Lin follows a semi-rolling release model.
The toolchain (compiler, libc, and related components) is kept stable for extended periods. Userland packages evolve on top of this stable base.
When accumulated changes make the existing toolchain a limiting factor, the toolchain is updated, userland is rebuilt and polished, and a new major version is released.
Between major releases, minor versions (e.g., v1.1, v1.2) are published when enough non-toolchain changes accumulate to justify a new root filesystem.
There is no fixed schedule. Releases happen when they are ready.
Is Zeppe-Lin stable?
Zeppe-Lin prioritizes correctness and predictability over rapid change.
While it is source-based and expects user involvement, care is taken to avoid unnecessary breakage, especially within a stable toolchain cycle.
Important packaging changes, required manual interventions, and security updates are announced on the zeppe-lin@freelists.org mailing list. Users are strongly encouraged to subscribe and follow these notices.
7.3.6 Support and Community
How can I report bugs or issues?
See Appendix D: Reporting Issues. Report issues in the repository corresponding to the affected component (packages, tools, website, or artwork). Include version, logs, steps to reproduce, and any relevant local modifications.
Can I contribute?
Yes. Contributions can include:
- New packages or updates to existing ones
- Tool improvements or bug fixes
- Documentation enhancements
- Artwork or visual identity improvements
Follow repository guidelines, and submit a pull request to the appropriate repository.
7.3.7 Philosophy
Is Zeppe-Lin trying to compete with other distributions?
No. Zeppe-Lin exists to satisfy its own design goals and the needs of its users.
It does not aim to replace other distributions or appeal to a broad audience.
7.4 Appendix D: Reporting Issues
This appendix explains how to report problems with Zeppe‑Lin. Clear, well-structured reports help the team respond efficiently.
7.4.1 Where to Report
Submit issues in the repository that corresponds to the type of problem:
Package-related problems
Open an issue in the relevantpkgsrc-*repository.Tool issues
Report in the specific tool repository, e.g.,pkgman,pkgmk,pkgutils,rejmerge,revdep.Website or documentation
Report in thezeppe-lin.github.iorepository.Artwork or visual assets
Report in theartworkrepository.Upstream software bugs
Report directly to the upstream project, not in Zeppe-Lin repos, unless it affects packaging.
You can subscribe to or report via mailing list:
General user discussion / small issues:
zeppe-lin@freelists.orgDevelopment, commits, tool updates:
zeppe-lin-dev@freelists.org
7.4.2 What to Include
Provide as much relevant information as possible:
- Zeppe-Lin version or snapshot
- Clear description of the problem
- Steps to reproduce
- Relevant error messages, logs, or outputs
- Local modifications that may affect behavior
7.4.3 Reporting Guidelines
- Verify that the issue is reproducible before reporting.
- Search existing issues to avoid duplicates.
- Keep reports factual, concise, and structured.
- Do not assume the cause unless you have evidence.
- Reference related issues, commits, or upstream bugs where applicable.
Tip:
Well-prepared reports get faster responses and make troubleshooting easier for both users and developers.