HANDBOOK FOR CRUX 3.7 1. Preface 2.1. What is CRUX? 2.2. Why use CRUX? 2.3. License 2.3.1. Packages 2.3.2. Build Scripts 2.3.3. NO WARRANTY 3. Installing CRUX 3.1. Supported Hardware / Requirements 3.2. Installing From Optical Medium or Removable Flash Drive 3.2.1. Installing a Bootloader 3.2.1.1. GRUB, in UEFI boot mode: 3.2.1.2. GRUB, in legacy (non-UEFI) boot mode: 3.2.1.3. SYSLINUX, in UEFI boot mode: 3.2.1.4. SYSLINUX, in legacy (non-UEFI) boot mode: 3.3. Upgrading From Optical Medium or Removable Flash Drive 4. Configuration 4.1. Initialization Scripts 4.1.1. Runlevels 4.1.2. Layout 4.1.3. Configuration Variables in /etc/rc.conf 4.2. Generating locales 4.3. Network Configuration 4.4. Passwords and User Environment 4.5. Upgrading the Kernel 5. The Package System 5.1. Introduction 5.2. Using the Package System 5.2.1. Installing a Package 5.2.2. Upgrading a Package 5.2.3. Removing a Package 5.2.4. Querying the Package Database 5.3. Package Management Frontend: prt-get 5.3.1. Functionality 5.3.2. Configuring prt-get 5.3.2.1. /etc/prt-get.conf 5.3.2.2. /etc/prt-get.aliases 5.4. Creating Packages 5.5. Adjusting/Configuring the Package Build Process 5.6. Package Guidelines 5.6.1. General 5.6.2. Directories 5.6.3. Remove Junk Files 5.6.4. Pkgfile Variables 5.6.5. Pkgfile Header 6. The Ports System 6.1. Introduction 6.1.1. What is a Port? 6.1.2. What is the Ports System? 6.1.3. Port collections 6.1.3.1. The official collections 'core', 'opt', 'xorg' and 'compat-32' 6.1.3.2. The user contributed collection 'contrib' 6.1.3.3. The individual collections from CRUX users 6.2. Using the Ports System 6.2.1. Synchronizing Your Local Ports Structure 6.2.2. Listing Local Ports 6.2.3. Listing Version Differences 6.2.4. Building and Installing Packages 6.2.5. Enabling the 'contrib' collection 6.2.6. Enabling the 'compat-32' collection 6.2.7. Additional tools 6.2.7.1. Building ports as unprivileged user 6.2.7.2. Useful scripts 7. Appendix 7.1. Troubleshooting 7.2. Writing a grub config file by hand 7.3. EFI Stub installation notes 7.4. Notes on Initramfs 1. Preface Per Lidén wrote this handbook. RobertMcMeekin converted it to DocBook, the CRUX team made a Wiki version. Numerous others have given feedback and improvement suggestions. 2. Introduction 2.1. What is CRUX? CRUX is a lightweight Linux distribution for the x86-64 architecture targeted at experienced Linux users. The primary focus of this distribution is "keep it simple", which it reflects in a simple tar.gz-based package system, BSD-style initscripts, and a relatively small collection of trimmed packages. The secondary focus is utilization of new Linux features and recent tools and libraries. CRUX also has a ports system which makes it easy to install and upgrade applications. 2.2. Why use CRUX? There are many Linux distributions out there these days, so what makes CRUX such an appealing choice to its users? The choice of distribution is a matter of taste, really. Here are a few hints about the tastes and goals of the people behind CRUX. CRUX is made with simplicity in mind from beginning to end. Making it easy to create new and update old packages is essential; updating a package in CRUX is often just a matter of typing sudo prt-get update $MYPKG. The usage of ports helps keep your packages up to date; not the latest bleeding-edge-alpha version, but the latest stable version. Other features include creating packages optimized for your processor, eg. by compiling with -march=x86-64, and avoiding cluttering the filesystem with files you'll never use, eg. /usr/share/doc/*, etc. If you need more information about a specific program, other than information found in the man-page, Google usually knows all about it. Lastly, while the CRUX development team strives to introduce new features as soon as they reach stable status, such innovations are carefully screened to ensure that they work in CRUX without drastic changes to the upstream sources or to the rest of the CRUX system. In short, CRUX might suit you very well if you are: * A somewhat experienced Linux user who wants a clean and solid Linux distribution as the foundation of your installation. * Someone who appreciates the challenge of navigating third-party source trees and figuring out what it takes to compile them. * Someone who has the patience to rebuild large packages on a regular basis. * Someone who enjoys exploring and discussing with other enthusiasts the intricacies of putting together an operating system. Note If you are using CRUX, we highly recommend subscribing to our low-volume mailing list because security updates and updates that need user action are announced there. 2.3. License 2.3.1. Packages Since CRUX is a Linux distribution, it contains software written by a lot of different people. Each software package comes with its own license, chosen by its author(s). To find out how a particular package is licensed, have a look at its source code. 2.3.2. Build Scripts All package build scripts in CRUX (in package categories core, opt, xorg, and compat-32) are Copyright © 2000-2022 by Per Lidén and the CRUX development team and are released under the GNU General Public License. 2.3.3. NO WARRANTY CRUX 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. 3. Installing CRUX 3.1. Supported Hardware / Requirements Packages on the official CRUX ISO image are compiled with optimization for x86-64 (AMD Athlon 64, Intel Core, Intel Atom) or newer processors. Do not try to install it on an i686 (Pentium-Pro, Celeron, Pentium-III) or lower processor, since it simply will not work. A minimum of 2GB system memory is required to install CRUX from a DVD or removable flash drive. It is possible to perform a custom chroot installation with a smaller amount of RAM. The kernel used during installation, i.e. when booting from the CRUX ISO image (El Torito), is compiled with support for most disk controllers. If your hard disk is not recognized after booting from the ISO image (i.e., the output of lsblk only shows the CRUX media), you might find a solution in the CRUX wiki, the mailing lists, or the bug tracker. You could also ask for help on the CRUX IRC channels. For example, the owner of a low-power machine that uses a board soldered memory card as its main disk was able to install CRUX successfully after building an ISO with kernel customized to enable CONFIG_X86_INTEL_LPSS. 3.2. Installing From Optical Medium or Removable Flash Drive Download the CRUX ISO image (crux-3.7.iso). To ensure that the download was successful, examine its checksum. $ shasum -a 256 crux-3.7.iso Compare the output with the file crux-3.7.sha256, which can be found in the same directory as the ISO image on the download site. If the checksums match, the download was successful and you can continue by burning the ISO image to a DVD or writing it to a removable flash drive. * The ISO image is bootable. After making sure that your BIOS gives priority to optical drives or flash drives, just insert the newly-written DVD or removable flash drive and reboot your computer. Press Enter at the boot prompt (you might have to adjust the root= parameter, depending on your hardware configuration). * You will be logged in as root on tty1 (root has no password set). * Create (if necessary) and format the partition(s) you want CRUX to be installed on. Remember the choice you make for the filesystems (especially root)! The driver for your chosen filesystem must be compiled into your Linux kernel, or included on an initramfs. $ fdisk /dev/sd? $ mkfs.???? /dev/sd?? $ mkswap /dev/sd?? Note Please keep in mind that SATA harddisks are usually detected as SCSI devices. The first SATA disk is called /dev/sda instead of /dev/hda. For more information about harddisk naming conventions please refer to the Linux Partition HOWTO. The amount of disk space required depends on how many packages are selected to install. It is recommended to have at least a 5G root partition (CRUX will use about 500MB-1GB, depending on whether you create separate partition for /usr, and other decisions you make in the setup process). The amount of swap space required depends on several factors, including whether you intend to use hibernation or build new packages in RAM. For more information about how memory is handled by modern Linux kernels, please refer to In Defense of Swap. Note: UEFI For UEFI installation a GPT disklabel and an EFI system partition (ESP) are required in most cases. The ESP does not need to be very large (100MiB for example) and should be formatted with a FAT32 filesystem and flagged as bootable. When using UEFI the boot loader/manager will be installed in the ESP rather than the traditional method of installation into the Master Boot Record (MBR). Note: MBR If your BIOS does not support UEFI boot mode (or you have disabled it in favor of legacy MBR mode), then you do not need to create a separate small partition for EFI loaders or kernel images. One large partition for / is enough in such cases, and GRUB should be able to find a Linux kernel saved in the subdirectory /boot. But selecting SYSLINUX for your bootloader will require you to flag as bootable whichever partition contains syslinux.cfg. See Installing a Bootloader below for more details. CRUX supports all the filesystems supported as root filesystems by the Linux kernel: btrfs, ext2, ext3, ext4, JFS, reiserfs and XFS. Further, it is highly recommended to separate the system data from user data, i.e. use a separate partition for /home (and possibly /var) since that will make your life a lot easier the day you want to upgrade, reinstall or remove your system. Note Make sure the appropriate userspace filesystem tools are installed. xfsprogs, btrfs-progs, jfsutils and reiserfsprogs can be found in the opt repository. Note Make sure that any BIOS Virus Protection option is DISABLED as this option may prevent fdisk from writing new partitions correctly. * Mount the partition on which you want to install this distribution. $ mount /dev/sd?? /mnt * If you want the installation to span more than one partition, mount those partitions as well. For example, if you want to have a different partition for /home or /var, then do: $ mkdir /mnt/var $ mount /dev/sd?? /mnt/var * Activate your swap partition(s). $ swapon /dev/sd?? * Type setup to start the package installation script. The script will ask where you mounted your new root partition and which packages you want to install. Select the packages you wish to install; it is recommended to install all the packages from core. Note: UEFI If installing a UEFI system make sure to select the efibootmgr package from the opt collection during the package selection phase. efibootmgr would be installed automatically during dependency resolution if you chose grub2-efi as your boot loader, but it's a good idea to start your CRUX experience paying close attention to the administrative tools you'll be using. Note: initramfs If you plan to build a modular kernel, remember to select the dracut package from the opt collection. After the packages have finished installing, the setup script will display an installation log. Make sure the last line in the log says “0 error(s)”. If you missed or forgot to install certain packages, you can just mount the CRUX installation medium and use pkgadd to install them. Screenshots of setup * Now it's time to compile your kernel and do basic system configuration. The kernel compilation requires that you “chroot” into your new CRUX installation. Note There is a shortcut command for creating the chroot environment: setup-chroot. This will execute all these steps at once. $ mount --bind /dev /mnt/dev $ mount --bind /tmp /mnt/tmp $ mount --bind /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/pts (UEFI only) $ mount --bind /sys/firmware/efi/efivars /mnt/sys/firmware/efi/efivars $ chroot /mnt /bin/bash * Set the root password. $ passwd * Edit /etc/fstab to configure your filesystem(s). Editors vim and nano are available. The fstab installed by the setup script includes the most commonly-used mountpoints (commented out, of course), which can be used as a reference when customizing fstab for your partition scheme. udev reads files in /sys/* and /proc/*. Make sure that those pseudo filesystems are enabled in your kernel configuration and available during system-startup. Also note that udev doesn't automatically mount /dev/pts. Terminal applications such as xterm(1) will not work if you forget to mount it. We highly recommend you check that your fstab contains the following line: # dev> mountpoint> type> options> dump> pass> [..] devpts /dev/pts devpts noexec,nosuid,gid=tty,mode=0620 0 0 * Edit /etc/rc.conf to configure font, keyboard, timezone, hostname and services. See Section "Configuration Variables in /etc/rc.conf" for details about /etc/rc.conf. * Generate locales for your system. See section "Generating locales" for more information. * Edit /etc/rc.d/net, /etc/hosts and /etc/resolv.conf to configure your network (ip-address/gateway/hostname/domain/dns). * Go to /usr/src/linux-5.15.x, configure and compile a new kernel. Note Make sure to include drivers needed to bring up your root filesystem! Unless you also create an initramfs with dracut, these drivers must be built-in and not kernel modules. Look for sections titled "SCSI disk support", "partition types", and "disk controller" when configuring your kernel. For example: * CONFIG_SATA_AHCI=y * CONFIG_BLK_DEV_SD=y * CONFIG_EXT4_FS=y Note The setup program installs a configuration file /usr/src/linux-5.15.55/.config which is a good starting point for a custom kernel, because all needed options, like CONFIG_DEVTMPFS, are enabled. $ cd /usr/src/linux-5.15.55 $ make menuconfig $ make all $ make modules_install $ cp arch/x86/boot/bzImage /boot/vmlinuz-5.15.55 $ cp System.map /boot Note The location /boot is the default path that GRUB will search for kernel images. If you use the kernel's EFI stub as your bootloader, then modify the cp commands to copy the kernel into a more appropriate location, e.g., the subdirectory EFI/BOOT under the mountpoint of the EFI system partition. The SYSLINUX bootloader on UEFI systems will also require a different location for the saved kernel; see SYSLINUX, in UEFI boot mode for the proper cp commands. Note A user-contributed example of a modular kernel configuration has been provided, if you want to boot a kernel that can tell you the exact set of modules needed for your particular hardware, or if you find it too daunting to navigate through the interface of the make menuconfig step. You can find this file, config-5.15.55-modular, under /crux/kernel/contrib on the installation media. 3.2.1. Installing a Bootloader Unless you compiled your kernel to provide an EFI stub and have UEFI boot mode enabled in your BIOS, you will want to install a bootloader on your hard disk. Simple instructions are provided below for four distinct combinations of bootloader and BIOS setting. You are advised to choose one of the following options based on how your BIOS is configured and on how much you value “do-it-yourself” config files. The EFI stub option is presented in the Appendix, if you find it simpler to modify EFI variables rather than configuration files. Note LILO is no longer maintained in the official ports collections. If you were using LILO to boot CRUX 3.6 or earlier, you are advised to replace the boot sector with GRUB or SYSLINUX when upgrading to CRUX 3.7. Note Dual-booting with another operating system is not covered in this handbook. There are more extensive resources for such installations on the SYSLINUX wiki or the GRUB manual. 3.2.1.1. GRUB, in UEFI boot mode: * Install grub2 into the EFI system partition using a command like grub-install /boot/efi (replace /boot/efi with the location of the mounted ESP). * If efibootmgr was selected during the package selection phase, grub-install will automatically create a boot entry and make it active. * Run grub-mkconfig > /boot/grub/grub.cfg, or create a config file by hand. 3.2.1.2. GRUB, in legacy (non-UEFI) boot mode: * Install grub2 into the Master Boot Record using the command grub-install /dev/sd??. * Replace /dev/sd?? with the actual node of the device whose Master Boot Record you want to overwrite, eg., /dev/sda for the first SATA disk. * Run grub-mkconfig > /boot/grub/grub.cfg, or create a config file by hand. * grub-mkconfig's output can be altered by setting variables in a configuration file, /etc/default/grub. This file is NOT created by default and is not required, but is useful for customizing the video resolution and grub menu colors without crafting a grub.cfg by hand. For more information, see the GRUB manual at http://www.gnu.org/software/grub/manual/. 3.2.1.3. SYSLINUX, in UEFI boot mode: * Copy the bootloader code from /usr/share/syslinux to the mounted EFI system partition, specifically the subdirectory EFI/BOOT, which most UEFI implementations will search by default. (In this example the ESP is assumed to be mounted at /boot/efi) $ mkdir -p /boot/efi/EFI/BOOT $ cd /boot/efi/EFI/BOOT $ cp /usr/src/linux-5.15.55/arch/x86/boot/bzImage vmlinuz-5.15.55 $ cp /usr/share/syslinux/efi64/ldlinux.e64 . $ cp /usr/share/syslinux/efi64/syslinux.efi BOOTX64.EFI $ cat < syslinux.cfg DEFAULT CRUX-3.7 PROMPT 1 TIMEOUT 10 LABEL CRUX-3.7 SAY "Now booting into CRUX" KERNEL vmlinuz-5.15.55 APPEND root=/dev/sda2 rw quiet # End of config file EOF * Saving a copy of syslinux.efi to the more generic name BOOTX64.EFI helps avoid the extra step of customizing boot entries with efibootmgr. * If you choose a different mountpoint for the EFI partition, adjust the mkdir and cd commands accordingly (UEFI itself is completely agnostic about mountpoints specified in /etc/fstab). * SYSLINUX interprets relative paths to the kernel in reference to the syslinux.cfg file, but cannot cross filesystem boundaries to find the kernel. Therefore the cp command from the kernel building step is not applicable when SYSLINUX is installed on the EFI mountpoint /boot/efi, and a different target directory appears in the cp commands above. 3.2.1.4. SYSLINUX, in legacy (non-UEFI) boot mode: * Create a syslinux directory on a vfat or ext2/3/4-formatted partition, and populate it with the kernel and bootloader. Assuming that /boot is on a partition marked bootable, you can do: $ mkdir /boot/syslinux $ cd /boot/syslinux $ cp /usr/share/syslinux/ldlinux.c32 . $ extlinux --install /boot/syslinux $ [ -e ../vmlinuz-5.15.55 ] || cp /usr/src/linux-5.15.55/arch/x86/boot/bzImage ../vmlinuz-5.15.55 $ cat < syslinux.cfg DEFAULT CRUX-3.7 PROMPT 1 TIMEOUT 10 LABEL CRUX-3.7 SAY "Now booting into CRUX" KERNEL ../vmlinuz-5.15.55 APPEND root=/dev/sda2 rw quiet # End of config file EOF * Replacing /boot/syslinux in the above commands with /boot/efi/EFI/BOOT will make it easy to toggle between legacy and UEFI boot modes. * SYSLINUX interprets relative paths to the kernel in reference to the syslinux.cfg file, although it cannot cross filesystem boundaries to find the kernel. On a legacy system with no dedicated EFI partition, the cp command from the kernel building step should put the kernel in a reachable path, hence the cp command above does not need to run if the kernel was already copied to the expected place. * Finally, overwrite the contents of the master boot record (MBR) with the binary blob appropriate for your partition type (gptmbr.bin in the case of GPT/GUID partitioning, or mbr.bin in the case of DOS partitioning). $ PTYPE=$(fdisk -l /dev/sda | grep "^Disklabel type" | cut -d " " -f3) $ [ "$PTYPE" = "gpt" ] && BINBLOB=gptmbr.bin || BINBLOB=mbr.bin $ dd bs=440 count=1 conv=notrunc if=/usr/share/syslinux/$BINBLOB of=/dev/sda More information about UEFI and other boot loader/manager options can be found in the CRUX wiki at https://crux.nu/Wiki/UEFI. Remove the CRUX installation media from your computer and reboot from harddisk. 3.3. Upgrading From Optical Medium or Removable Flash Drive Download the CRUX ISO image (crux-3.7.iso). To ensure that the download was successful, examine its checksum. $ shasum -a 256 crux-3.7.iso Compare the output with the file crux-3.7.sha256, which can be found in the same directory as the ISO image on the download site. If the checksums match, the download was successful and you can continue by burning the ISO image to a DVD or writing it to a removable flash drive. * The ISO image is bootable. After making sure that your BIOS gives priority to optical drives or flash drives, just insert the newly-written DVD or removable flash drive and reboot your computer. Press Enter at the boot prompt (you might have to adjust the root= parameter, depending on your hardware configuration). * You will be logged in as root on tty1 (root has no password set). * Mount your CRUX root partition. $ mount /dev/sd?? /mnt * If your installation spans over more than one partition, mount these partitions as well. For example, if you have a different partition for /var, then do: $ mount /dev/sd?? /mnt/var * Activate your swap partition(s). $ swapon /dev/sd?? * Type setup to start the package installation script. The script will ask you where you mounted your root partition and which packages you want to upgrade. * Upgrading packages that were linked to soft dependencies outside core and opt will replace them with packages that were only linked to dependencies in core and opt. You will have to rebuild such packages if you want to retain the functionality of your existing CRUX system. * On the other hand, if it's been a while since you refreshed the ports tree on your existing CRUX system and rebuilt the outdated packages, an upgrade of all packages will save you from trouble (e.g. if some library introduced breaking changes). Note The setup script uses the /etc/pkgadd.conf of the target system to determine which files to upgrade, and which files not to upgrade. The files that are not upgraded are put in /var/lib/pkg/rejected/ (see the section "Upgrading a Package" for advice on how to resolve such file conflicts). When the setup script has upgraded the selected packages an upgrade log will be displayed. Make sure the last line in the log says “0 error(s)”. If you missed/forgot to install certain packages, you can just mount the CRUX installation media and use pkgadd to install them (e.g. pkgadd /mnt/crux/opt/package#1.0-1.pkg.tar.gz). * The already-built kernel from your previous CRUX installation might not be compatible with the newly-upgraded linux-firmware package. To be safe, you're advised to “chroot” into your CRUX installation and compile a fresh kernel from the latest source tree. Note There is a shortcut command for creating the chroot environment: setup-chroot. This will execute all these steps at once. $ mount --bind /dev /mnt/dev $ mount --bind /tmp /mnt/tmp $ mount --bind /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/pts (UEFI only) $ mount --bind /sys/firmware/efi/efivars /mnt/sys/firmware/efi/efivars $ chroot /mnt /bin/bash * Generate locales for your system. See the section Generating locales for more information. * Go to /usr/src/linux-5.15.x, configure and compile a new kernel. See the kernel building step for some reminders of how that is done. * Adjust /etc/fstab to reflect any changes made to your partition scheme since your earlier installation of CRUX. In particular, /var/run should not appear as a mountpoint, since this is now a symlink to /run starting with CRUX 3.7. See the notes about fstab in the previous section for other general recommendations. Finish the upgrade by Installing a Bootloader, and then you should be able to login to your upgraded CRUX system after rebooting. 4. Configuration 4.1. Initialization Scripts 4.1.1. Runlevels The following runlevels are used in CRUX (defined in /etc/inittab). +-------------------------+ |Runlevel| Description | |--------+----------------| |0 |Halt | |--------+----------------| |1 (S) |Single-user Mode| |--------+----------------| |2 |Multi-user Mode | |--------+----------------| |3-5 |(Not used) | |--------+----------------| |6 |Reboot | +-------------------------+ 4.1.2. Layout The initialization scripts used in CRUX follow the BSD-style (as opposed to the SysV-style) and have the following layout. +-------------------------------------------------------------------+ | File | Description | |----------------+--------------------------------------------------| |/etc/rc |System boot script | |----------------+--------------------------------------------------| |/etc/rc.single |Single-user startup script | |----------------+--------------------------------------------------| |/etc/rc.modules |Module initialization script | |----------------+--------------------------------------------------| |/etc/rc.multi |Multi-user startup script | |----------------+--------------------------------------------------| |/etc/rc.local |Local multi-user startup script (empty by default)| |----------------+--------------------------------------------------| |/etc/rc.shutdown|System shutdown script | |----------------+--------------------------------------------------| |/etc/rc.conf |System configuration | |----------------+--------------------------------------------------| |/etc/rc.d/ |Service start/stop script directory | +-------------------------------------------------------------------+ Modify /etc/rc.modules, /etc/rc.local and /etc/rc.conf according to your needs. 4.1.3. Configuration Variables in /etc/rc.conf The following configuration variables are found in /etc/rc.conf. +------------------------------------------------------------------------+ |Variable| Description | |--------+---------------------------------------------------------------| | |Specifies which console font to load at system startup. The | | |contents of this variable will be passed as argument to | |FONT |setfont(1). The available fonts are located in | | |/usr/share/kbd/consolefonts/. | | | | | |Example: FONT=default | |--------+---------------------------------------------------------------| | |Specifies which console keyboard map to load at system startup.| | |The contents of this variable will be passed as argument to | |KEYMAP |loadkeys(1). The available keyboard maps are located in | | |/usr/share/kbd/keymaps/. | | | | | |Example: KEYMAP=sv-latin1 | |--------+---------------------------------------------------------------| | |Specifies the timezone used by the system. The available zone | |TIMEZONE|description files are located in /usr/share/zoneinfo/. | | | | | |Example: TIMEZONE=Europe/Stockholm | |--------+---------------------------------------------------------------| | |Specifies the hostname. | |HOSTNAME| | | |Example: HOSTNAME=pluto | |--------+---------------------------------------------------------------| | |Specifies the system logging daemon(s) to run at startup. | |SYSLOG | | | |Example: SYSLOG=sysklogd | |--------+---------------------------------------------------------------| | |Specifies which services to start at system startup. The | | |services specified in this array must have a matching | | |start/stop script in /etc/rc.d/. When entering multi-user mode | | |the specified scripts will be called in the specified order | |SERVICES|with the argument start. At system shutdown or when entering | | |single-user mode these scripts will be called in the reverse | | |order with the argument stop. | | | | | |Example: SERVICES=(crond lo net sshd) | +------------------------------------------------------------------------+ 4.2. Generating locales Starting with CRUX 2.5, glibc does not contain all possible locales anymore, thus you'll have to generate the locales you need/use. To ensure proper operation of pkgmk, the locale C.UTF-8 is generated as part of the CRUX installation. Any other desired locales must be created by the administrator. The core port glibc provides a script to generate the desired locales based on the configuration file /etc/locale.gen, so you no longer need to run localedef manually. Just open /etc/locale.gen in an editor and uncomment the desired locales, then run /usr/sbin/locale-gen. With the appropriate UPGRADE directives in /etc/pkgadd.conf, you can safely upgrade glibc at a later date without losing your chosen locales; just make sure that the file /etc/locale.gen is protected from being overwritten when performing pkgadd -u. 4.3. Network Configuration The network configuration is found in the service script /etc/rc.d/net. To enable this service you need to add net to the SERVICES array in /etc/rc.conf. By default this service script configures a dynamic IP address. Example: #!/bin/sh # # /etc/rc.d/net: start/stop network interface # # Connection type: "DHCP" or "static" TYPE="DHCP" # For "static" connections, specify your settings here: # To see your available devices run "ip link". DEV=enp11s0 ADDR=192.168.1.100 MASK=24 GW=192.168.1.1 # Optional settings: DHCPOPTS="-h `/bin/hostname` -t 10" case $1 in start) if [ "${TYPE}" = "DHCP" ]; then /sbin/dhcpcd ${DHCPOPTS} else /sbin/ip addr add ${ADDR}/${MASK} dev ${DEV} broadcast + /sbin/ip link set ${DEV} up /sbin/ip route add default via ${GW} fi ;; stop) if [ "${TYPE}" = "DHCP" ]; then /sbin/dhcpcd -x else /sbin/ip route del default /sbin/ip link set ${DEV} down /sbin/ip addr del ${ADDR}/${MASK} dev ${DEV} fi ;; restart) $0 stop $0 start ;; *) echo "Usage: $0 [start|stop|restart]" ;; esac # End of file If you want to configure your system to use a static IP address, specify TYPE=static and the correct interface. You will also need to configure DNS settings in /etc/resolv.conf. Example: #!/bin/sh # # /etc/rc.d/net: start/stop network interface # # Connection type: "DHCP" or "static" TYPE="static" # For "static" connections, specify your settings here: # To see your available devices run "ip link". DEV=enp11s0 ADDR=192.168.1.100 MASK=24 GW=192.168.1.1 # Optional settings: DHCPOPTS="-h `/bin/hostname` -t 10" case $1 in start) if [ "${TYPE}" == "DHCP" ]; then /sbin/dhcpcd ${DHCPOPTS} else /sbin/ip addr add ${ADDR}/${MASK} dev ${DEV} broadcast + /sbin/ip link set ${DEV} up /sbin/ip route add default via ${GW} fi ;; stop) if [ "${TYPE}" == "DHCP" ]; then /sbin/dhcpcd -x else /sbin/ip route del default /sbin/ip link set ${DEV} down /sbin/ip addr del ${ADDR}/${MASK} dev ${DEV} fi ;; restart) $0 stop $0 start ;; *) echo "Usage: $0 [start|stop|restart]" ;; esac # End of file # # /etc/resolv.conf: resolver configuration file # search your internal domain> nameserver your DNS server> # End of file To associate with a WPA2-protected wireless network, you should first create a configuration file for wpa_supplicant to use, then launch wpa_supplicant on that interface. $ wpa_passphrase MYNETWORK MYPASS > /etc/wpa_supplicant-wlan0.conf $ wpa_supplicant -i wlan0 -c /etc/wpa_supplicant-wlan0.conf Replace MYNETWORK with the ssid of your network, MYPASS with its passphrase, and wlan0 with the name of your actual network interface. Run ip link to see the list of all available interfaces. If the wpa_supplicant output indicates a successful authentication, you can background the process and run dhcpcd wlan0 to request an address from the DHCP server. The wpa_supplicant package provides two startup scripts in /etc/rc.d. You might choose to put wlan in the SERVICES array of /etc/rc.conf (replacing net), which will let wpa_supplicant manage all your network interfaces. Another option is to let the net startup script call wpa_supplicant as needed, by copying into /lib/dhcpcd/dhcpcd-hooks/ the example file /usr/share/dhcpcd/hooks/10-wpa_supplicant. 4.4. Passwords and User Environment CRUX uses SHA512 passwords by default. To change the password encryption method set the ENCRYPT_METHOD variable in /etc/login.defs to DES, MD5 or SHA256. Furthermore, when compiling programs that use the crypt(3) function to authenticate users you should make sure that these programs are linked against the libcrypt library (i.e. use -lcrypt when linking) which contains the SHA512 version of the crypt function (this version is backwards compatible and understands DES passwords as well). Also configurable in /etc/login.defs are the settings that govern how useradd(8) behaves when you create a new non-root user, such as CREATE_HOME and USERGROUPS_ENAB. First-time CRUX administrators might be surprised to learn that creating a new user via useradd -m will not automatically populate the home directory with a basic shell startup file, as happens on other Linux distributions whose /etc/skel/ contains their idea of an initial home directory. A new default in CRUX 3.7 is that the value of PATH, for shells that rely on /etc/profile to set this variable, will be the same regardless of UID. This change allows non-root users easy access to any administrative command without having to type its full path (provided they use bash as their shell and are given the appropriate doas/sudo permissions). Users are always free to choose a different shell and manage PATH themselves, but the default behaviour is now less likely to cause confusion. The core packages linux-pam and dumb_runtime_dir, and the contrib package pam_xdg, provide a variety of modules that can be loaded upon logging in. The files in /etc/pam.d govern the association between the type of login (eg., tty, SSH, su, X Display Manager) and the modules that get loaded (eg., pam_env, pam_exec, pam_limits). Some typical situations that can be handled cleanly with PAM modules are listed in the table below. +------------------------------------------------------------------------+ | file in /etc/pam.d | Typical usage | |-----------------------+------------------------------------------------| |pam_dumb_runtime_dir.so|create an XDG_RUNTIME_DIR for applications that | | |conform to the freedesktop.org specification | |-----------------------+------------------------------------------------| |pam_env.so |export some common environment variables, no | | |matter what login shell the user has chosen | |-----------------------+------------------------------------------------| |pam_xdg.so |export the XDG environment variables defined in | | |the freedesktop.org specification | |-----------------------+------------------------------------------------| |pam_limits.so |increase the allowed number of opened files, to | | |ensure proper operation of some games | |-----------------------+------------------------------------------------| |pam_xauth.so |grant another user access to the X display of | | |the logged-in user, so that programs invoked | | |with su can work properly | |-----------------------+------------------------------------------------| |pam_mount.so |automatically mount a LUKS-encrypted home | | |partition after successful authentication | +------------------------------------------------------------------------+ Note The existence of a writable XDG_RUNTIME_DIR is required for proper operation of many desktop applications. A clean CRUX 3.7 installation will place a line in /etc/pam.d/common-session that loads the module pam_dumb_runtime_dir.so to satisfy this requirement. An upgrade to CRUX 3.7 might not do so, depending on your UPGRADE directives in /etc/pkgadd.conf. But any configuration that allows desktop applications to run smoothly on CRUX 3.6 will probably continue working after an upgrade to 3.7. While pam_dumb_runtime_dir has a simple design and restricts itself to the creation of the runtime dir, the 'contrib' collection offers an alternative, pam_xdg, which exports all the environment variables defined in the freedesktop.org specification. You should choose ONE of these two options and edit /etc/pam.d/common-session accordingly. If you find yourself in one of the other situations in the table above, read the man page for the corresponding PAM module to learn how to accomplish the desired configuration. 4.5. Upgrading the Kernel The kernel source, which is found in /usr/src/linux-5.15.x/ is not installed using pkgadd. If you decide to upgrade your kernel you can safely do so by manually replacing the kernel source with a newer version (or unpack the newer source tree somewhere else). This will not make the package database inconsistent (since it's not installed with pkgadd) nor will it affect the kernel headers found in /usr/include/linux and /usr/include/asm since these are not symlinks to the kernel source, but instead contain copies of the headers. 5. The Package System 5.1. Introduction The package system (pkgutils) is made with simplicity in mind, where all packages are plain tar.gz files (i.e. without any kind of meta data). Packages follow the naming convention #-.pkg.tar.gz, where is the name of the program, is the version number of the program, and is the version number of the package. The pkg.tar.gz extension is used (instead of just tar.gz) to indicate that this is not just any tar.gz file, but a tar.gz that is meant to be installed using pkgadd. This helps distinguish packages from other tar.gz files. Note that pkgmk nowadays supports additional compression schemes like bzip2 with the tar.bz2 extension or XZ ending with tar.xz. pkgadd(8), pkgrm(8), pkginfo(8), and pkgmk(8) are the package management utilities. With these utilities you can install, uninstall, inspect, make packages, or query the package database. When a package is installed using pkgadd a new record is added to the package database (stored in /var/lib/pkg/db). The basic package system does not have any kind of dependency checking, thus it will not warn you if you try to build a package that requires libraries or headers from other packages. Your mistake will only be revealed when the pkgmk build function exits with errors. The included prt-get tool, however, can be told to resolve dependencies, if called with prt-get depinst rather than simply prt-get install. The following sections will in describe in short how to use the package utilities. Additional information about these utilities can be found on their respective man pages. 5.2. Using the Package System 5.2.1. Installing a Package Installing a package is done by using pkgadd. This utility requires at least one argument, the package you want to install. Example: $ pkgadd bash#5.0.18-1.pkg.tar.gz When installing a package the package manager will ensure that no existing files are overwritten. If conflicts are found, an error message will be printed and pkgadd will abort without installing the package. The error message will contain the names of the conflicting files. Example: $ pkgadd bash#5.0.18-1.pkg.tar.gz bin/sh usr/man/man1/sh.1.gz pkgadd error: listed file(s) already installed (use -f to ignore and overwrite) No such error message is issued for already-existing directories, since the package database allows a directory to be associated with more than one package. However, the owner/group and permissions of an existing directory will not be changed to match those of the requested package. To force the installation when conflicting files are reported, you can use the option -f (or --force). Example: $ pkgadd -f bash#5.0.18-1.pkg.tar.gz The package system allows a file to be owned by exactly one package. When forcing an installation the ownership of the conflicting files will be transferred to the package that is currently being installed. Warning It is often not a good idea to force the installation unless you really know what you are doing. If a package conflicts with already installed files it could be a sign that the package is broken and installs unexpected files. Use this option with extreme care, preferably not at all. As earlier, the package file itself does not contain any meta data. Instead, the package manager uses the package filename to determine the package name and version. Thus, when installing a package file named bash#5.0.18-1.pkg.tar.gz, the package manager will interpret this as a package named bash at version 5.0.18-1. If pkgadd is unable to interpret the filename (e.g. # is missing or the filename does not end with .pkg.tar.gz) an error message will be printed and pkgadd will abort without installing the package. 5.2.2. Upgrading a Package Upgrading a package is done using pkgadd with the -u option. Example: $ pkgadd -u bash#5.0.18-1.pkg.tar.gz This will replace the previously installed bash package with the new one. If you have not previously installed bash, pkgadd will print an error message. The package system does not care about the version number of the package in that you can “upgrade” version 5.0.18-1 with version 5.0.16-1 (or even with version 5.0.18-1 itself). The installed package will be replaced with the specified package. Upgrading a package is not simply a wrapper for pkgrm followed by pkgadd, because you usually want to preserve your customizations of the config and log files that are owned by the already-installed package. Therefore, pkgadd -u conducts some upgrade-specific checks of the filesystem and the package database to construct what is called a “keep list” (in addition to the “non-install list” which is initialized for every pkgadd transaction). The construction of both lists is governed by the file /etc/pkgadd.conf. /etc/pkgadd.conf can contain rules describing how pkgadd should behave when installing or upgrading any package. A rule is built out of three fragments; event, pattern and action. The event names the kind of operation (INSTALL or UPGRADE) to which this rule will be applied. The pattern is a filename pattern expressed as a regular expression and the action applicable to the INSTALL or UPGRADE event is YES or NO. More than one rule of the same event type is allowed, in which case the first rule will have the lowest priority and the last rule will have the highest priority. Example: # # /etc/pkgadd.conf: pkgadd(8) configuration # UPGRADE ^etc/.*$ NO UPGRADE ^var/log/.*$ NO UPGRADE ^etc/X11/.*$ YES UPGRADE ^etc/X11/xorg.conf$ NO # End of file The above example will cause pkgadd to never upgrade anything in /etc/ or /var/log/ (subdirectories included), except files in /etc/X11/ (subdirectories included), unless it is the file /etc/X11/xorg.conf. The default rule is to upgrade everything, rules in this file are exceptions to that rule. Note A pattern should never contain an initial “/” since you are referring to the files in the package, not the files on the disk. If pkgadd finds that a specific file should not be upgraded, it will install it under /var/lib/pkg/rejected/. Files in this directory are never added to the package database. The user is then free to examine, use and/or remove that file manually. Another option is to use rejmerge. For each rejected file found in /var/lib/pkg/rejected/, rejmerge will display the difference between the installed version and the rejected version. The user can then choose to keep the installed version, upgrade to the rejected version or perform a merge of the two. Example (using the above /etc/pkgadd.conf): $ pkgadd -u ports#1.6-3.pkg.tar.gz pkgadd: rejecting etc/ports/compat-32.pub, keeping existing version pkgadd: rejecting etc/ports/compat-32.rsync.inactive, keeping existing version pkgadd: rejecting etc/ports/contrib.pub, keeping existing version pkgadd: rejecting etc/ports/contrib.rsync.inactive, keeping existing version pkgadd: rejecting etc/ports/core.pub, keeping existing version pkgadd: rejecting etc/ports/core.rsync, keeping existing version pkgadd: rejecting etc/ports/opt.pub, keeping existing version pkgadd: rejecting etc/ports/opt.rsync, keeping existing version pkgadd: rejecting etc/ports/xorg.pub, keeping existing version pkgadd: rejecting etc/ports/xorg.rsync, keeping existing version $ tree -L 3 /var/lib/pkg/rejected/ /var/lib/pkg/rejected etc ports    compat-32.pub    compat-32.rsync.inactive    contrib.pub    contrib.rsync.inactive    core.pub    core.rsync    drivers    opt.pub    opt.rsync    xorg.pub    xorg.rsync If this pkgadd.conf had been in place during an upgrade from CRUX 3.6 to 3.7, and you neglected to check the contents of /var/lib/pkg/rejected/ (either manually or by running rejmerge), then ports -u would synchronize your ports tree with the older branch! Hence you should always pay attention to warnings and errors reported by pkgadd. 5.2.3. Removing a Package Removing a package is done by using pkgrm. This utility requires one argument, the name of the package you want to remove. Example: $ pkgrm bash Warning This will remove all files owned by the package, no questions asked. Think twice before doing it and make sure that you did not misspell the package name since that could remove something completely different (e.g. think about what could happen if you misspelled glib as glibc). 5.2.4. Querying the Package Database Querying the package database is done using pkginfo. This utility has a few options to answer different queries. +------------------------------------------------------------------------+ | Option | Description | |-----------------------+------------------------------------------------| |-i, --installed |List installed packages and their version. | |-----------------------+------------------------------------------------| |-l, --list package|file|List files owned by the specified package or | | |contained in file | |-----------------------+------------------------------------------------| |-o, --owner pattern |List owner(s) of file(s) matching pattern. | +------------------------------------------------------------------------+ Examples: $ pkginfo -i acl 2.3.1-1 alsa-lib 1.2.7.2-1 alsa-utils 1.2.7-1 ...> yasm 1.3.0-2 zip 3.0-2 zlib 1.2.12-1 zstd 1.5.2-1 $ pkginfo -l bash bin/ bin/bash bin/sh etc/ etc/profile usr/ usr/man/ usr/man/man1/ usr/man/man1/bash.1.gz usr/man/man1/sh.1.gz $ pkginfo -l grep#3.7-1.pkg.tar.gz usr/ usr/bin/ usr/bin/egrep usr/bin/fgrep usr/bin/grep usr/man/ usr/man/man1/ usr/man/man1/egrep.1.gz usr/man/man1/fgrep.1.gz usr/man/man1/grep.1.gz $ pkginfo -o bin/ls e2fsprogs usr/bin/lsattr fileutils bin/ls modutils sbin/lsmod 5.3. Package Management Frontend: prt-get In its current form pkgutils does not have a concept of dependency handling. To address this a frontend utility called prt-get was created. It supports dependency handling (with the caveat mentioned below) as well as some overlap with pkgutils features and has been an official part of CRUX for some time. 5.3.1. Functionality Some examples of prt-get's functionality and use are as follows: Listing installed ports: $ prt-get listinst acl alsa-lib alsa-utils [...] $ prt-get listinst -v acl 2.3.1-1 alsa-lib 1.2.7.2-1 alsa-utils 1.2.7-1 [...] Querying information about a port: $ prt-get info acl Name: acl Path: /usr/ports/core Version: 2.3.1 Release: 1 Description: Access Control Lists library URL: http://savannah.nongnu.org/projects/acl Maintainer: CRUX System Team, core-ports at crux dot nu Dependencies: attr Searching for ports by name: $ prt-get search glibc glibc glibc-32 $ prt-get search --regex '(ba|z)sh$' bash zsh Searching for ports by installed file: $ prt-get fsearch gconv Found in /usr/ports/core/glibc: /usr/lib/gconv/ Found in /usr/ports/core/glibc-32: /usr/lib32/gconv/ Searching for ports by words in their descriptions: $ prt-get dsearch shell dash dialog dsh [...] zsh Viewing dependency lists: $ prt-get depends bash -- dependencies ([i] = installed) [i] ncurses [i] readline [i] bash $ prt-get quickdep bash ncurses readline bash $ prt-get deptree bash -- dependencies ([i] = installed, '-->' = seen before) [i] bash [i] readline [i] ncurses Installing ports: $ prt-get install xterm Note The 'install' command does NOT process dependencies and it is usually recommended to use 'depinst' (next) instead! $ prt-get depinst xterm Viewing and updating outdated ports (generally after 'ports -u'): Listing installed ports which are out of date: $prt-get diff Differences between installed packages and ports tree: Port Installed Available in the ports tree inkscape 1.2-1 1.2.1-1 Updating an individual port: $ prt-get update inkscape Updating all installed ports: $ prt-get sysup Note Currently 'update' and 'sysup' do not process new dependencies introduced after the initial installation of a port. To show such additions to the dependency lists of installed ports, you can chain together several invocations of prt-get with one invocation of awk as follows. $ prt-get isinst $(prt-get quickdep $(prt-get quickdiff)) | awk '/not installed/ {print $2}' 5.3.2. Configuring prt-get 5.3.2.1. /etc/prt-get.conf prt-get's main configuration file, '/etc/prt-get.conf', contains options that can be used to change prt-get's behavior. Notably in this file the following options can be configured: prtdir - This option can occur multiple times and specifies a directory with a 'collection' that prt-get should search for ports. By default the 'core', 'opt', and 'xorg' collections are enabled. The 'compat-32' and 'contrib' collections are disabled by default, see sections "Enabling the 'contrib' collection" and "Enabling the 'compat-32' collection". logfile - This option configures a file for prt-get to log its operation if desired. runscripts - This option configures prt-get to run pre-/post-install scripts if they exist in ports being installed or updated. It is recommended that this be enabled as in many cases if a pre- or post-install script exists in a port, it is required to be run for proper operation. 5.3.2.2. /etc/prt-get.aliases prt-get has a concept of aliases which can be used in a fashion similar to the concept of 'provides' in some other Linux distributions. This file is /etc/prt-get.aliases and contains lines in the following format: postfix: sendmail exim: sendmail qmail: sendmail masqmail: sendmail The above set of aliases indicates that postfix, exim, qmail, and masqmail are all considered sufficient to satisfy a dependency on 'sendmail' in a port. Sometimes the port maintainer will list among the required dependencies a lightweight library, to save on compilation time for the majority of users. If you already have the more powerful library installed, you can use prt-get.aliases to avoid automatic installation of the lightweight alternative. For example, on a system with mozjs91 already built, you would not want prt-get depinst polkit to build duktape as well. This can be accomplished with the following line in prt-get.aliases: mozjs91: duktape Another situation that can be handled with prt-get aliases is when you have a fork of port X in your personal overlay, renamed to describe how it differs from the original port, and port X appears somewhere in the dependency tree of port Y. For example, suppose the Pkgfile for foo explicitly disables qt and hard depends on Xorg, so that prt-get depinst foo on a Wayland-only system would bring in all of Xorg. If you create a custom port of foo that disables Xorg in favor of qt, calling it foo-qt, then by appending foo-qt: foo to /etc/prt-get.aliases you can ensure that prt-get does not try to build all of Xorg when foo shows up in some other port's dependency tree. Note prt-get's alias function does NOT automatically replace ports during an install or depinst operation. If a port depends on 'duktape' and neither 'duktape' nor 'mozjs91' are installed, prt-get will install 'duktape' as listed in the port's dependencies. If 'mozjs91' was installed before the depending port's install or depinst operation, on the other hand, prt-get will consider the dependency satisfied. This is NOT an exhaustive list of all of prt-get's commands, features, and configuration options, merely a starting point. More information can be found in the manual and quick start documentation. 5.4. Creating Packages Creating a package is done using pkgmk. This utility uses a file called Pkgfile, which contains information about the package (such as name, version, etc) and the commands that should be executed in order to compile the package in question. To be more specific, the Pkgfile file is actually a bash(1) script, which defines a number of variables (name, version, release and source) and a function (build). Below is an example of what a Pkgfile file might look like. The example shows how to package the grep(1) utility. Some comments are inserted for explanation. # Specify the name of the package. name=grep # Specify the version of the package. version=3.7 # Specify the package release. release=1 # The source(s) used to build this package. source=(ftp://ftp.ibiblio.org/pub/gnu/$name/$name-$version.tar.gz) # The build() function below will be called by pkgmk when # the listed source files have been unpacked. build() { # The first thing we do is to cd into the source directory. cd $name-$version # Run the configure script with desired arguments. # In this case we want to put grep under /usr/bin and # disable national language support. ./configure --prefix=/usr --disable-nls # Compile. make # Install the files, BUT do not install it under /usr, instead # we redirect all the files to $PKG/usr by setting the DESTDIR # variable. The $PKG variable points to a temporary directory # which will later be made into a tar.gz-file. Note that the # DESTDIR variable is not used by all Makefiles, some use prefix # and others use ROOT, etc. You have to inspect the Makefile in # question to find out. Some Makefiles do not support redirection # at all. In those cases you will have to create a patch for it. make DESTDIR=$PKG install # Remove unwanted files, in this case the info-pages. rm -rf $PKG/usr/info } In reality you do not include all those comments, thus the real Pkgfile for grep(1) looks like this: # Description: GNU grep, egrep and fgrep # URL: http://www.gnu.org/software/grep/grep.html # Maintainer: Per Lid�n, per at fukt dot bth dot se name=grep version=3.7 release=1 source=(ftp://ftp.ibiblio.org/pub/gnu/$name/$name-$version.tar.gz) build() { cd $name-$version ./configure --prefix=/usr --disable-nls make make DESTDIR=$PKG install rm -rf $PKG/usr/info } Note The build() function in the example above is just an example of how grep is built. The contents of the function can differ significantly if the program is built in some other way, e.g. does not use autoconf. When the build() function has been executed, the $PKG directory will be made into a package named #-.pkg.tar.gz. Before the package creation is completed, pkgmk will check the contents of the package against the .footprint file. If this file does not exist, it will be created and the test will be skipped. The .footprint file will contain a list of all files that should be in the package if the build was successful or a list of all the files that were installed in $PKG (if the .footprint did not already exist). If there is a mismatch the test will fail and an error message will be printed. You should not write the .footprint file by hand. Instead, when a package has been upgraded and you need to update the contents of the .footprint file you simply do pkgmk -uf. This test ensures that a rebuild of the package turned out as expected. If the package built without errors it's time to install it by using pkgadd and try it out. I highly recommend looking at the Pkgfile in another package(s), since looking at examples is a great way to learn. Note Please see the Package Guidelines for additional recommendations regarding Pkgfile variables (name, version, release, build) and the footprint. 5.5. Adjusting/Configuring the Package Build Process Many settings pertaining to the package build process can be adjusted by editing the pkgmk(8) configuration file /etc/pkgmk.conf. Some of these configurable settings include: * CFLAGS, CXXFLAGS - these settings control optimization and architecture options for package compiles. It is best NOT to change these unless you absolutely know what you're doing! * PKGMK_SOURCE_MIRRORS - this setting defines locations from which pkgmk will attempt to fetch source archives. If this array only contains mirrors administered by the CRUX team, building a port from your personal collection might result in 404 Not Found errors until all the mirrors are exhausted, and then the source defined in the Pkgfile will be tried. * PKGMK_SOURCE_DIR - this setting defines where pkgmk will store (if downloading) and use source archives when building * PKGMK_PACKAGE_DIR - this setting defines where pkgmk will create package files once the build process is complete * PKGMK_WORK_DIR - this setting defines a work area pkgmk will use to build the package Here are some examples: PKGMK_SOURCE_MIRRORS=(http://fileserver.intranet/crux/sources/) This setting instructs pkgmk to attempt to fetch all source archives from http://fileserver.intranet/crux/sources/ before falling back to the source URL specified in the Pkgfile. Multiple URLS can be separated by spaces. PKGMK_SOURCE_DIR="/usr/ports/srcfiles" This example instructs pkgmk to store and find source archives in /usr/ports/srcfiles. An example benefit of this setup would be the ability to store /usr/ports/srcfiles on an NFS server on your local network for use by multiple crux installations. (PKGMK_PACKAGE_DIR can be set and used the same way. But if NFS is too challenging to set up on your local network and you find it easier to configure an http server instead, pkg-get from the opt collection gives you an alternative mechanism for sharing built packages.) PKGMK_WORK_DIR="/usr/ports/work/$name" This example instructs pkgmk to use /usr/ports/work/$name as a work area for building the specified package. Building the grep package would result in the work area being /usr/ports/work/grep. An alternative would be to use a tmpfs as your work directory. There are a few more settings which can be found in the pkgmk.conf man page. 5.6. Package Guidelines 5.6.1. General * The name of a package should always be lowercase (e.g. name=eterm and not name=Eterm). In case the package is added to the CRUX ports system the exact same name should be use for the name of the directory in the ports structure, i.e. /usr/ports/???/eterm. * Do not combine several separately distributed programs/libraries into one package. Make several packages instead. * The build function should never touch anything outside the work directory, and ideally should not rely on having an internet connection (say, to download sources not listed in the source array). While pkgmk does not currently recognize git urls in the source array, efforts are underway to add this feature, thereby removing the temptation to write a build function that reaches out to the internet for the latest git source tree. Apart from ensuring a consistent mechanism to verify the integrity of sources (signify), the policy of separating 'download' from 'build' allows a user with intermittent internet access to run pkgmk -do in the directory of every outdated package, and then go offline to finish the sysup operation. Language-specific toolchains, like those embraced by rust and python (cargo and pip, respectively), are making this policy more difficult to enforce. You are free to forego CRUX pkgutils and let the ecosystems of the N different languages manage their respective software in separate subdirectories (like python's ~/.local/share/virtualenv or rust's ~/.cargo), at the expense of having to learn N+1 administration suites rather than just the 1 suite of CRUX pkgutils. Every language-specific project that appears in the official repositories represents a hard-won effort by the CRUX team to sustain the historic method of software deployment, in the face of software development trends all heading away from this model. 5.6.2. Directories * In general packages should install files in these directories. Exceptions are of course allowed if there is a good reason. But try to follow the following directory structure as close as possible. +------------------------------------------------------------------------+ | Directory | Description | |------------------+-----------------------------------------------------| |/usr/bin/ |User command/application binaries | |------------------+-----------------------------------------------------| |/usr/sbin/ |System binaries (e.g. daemons) | |------------------+-----------------------------------------------------| |/usr/lib/ |Libraries | |------------------+-----------------------------------------------------| |/usr/include/ |Header files | |------------------+-----------------------------------------------------| |/usr/lib// |Plug-ins, addons, etc | |------------------+-----------------------------------------------------| |/usr/share/man/ |Man pages | |------------------+-----------------------------------------------------| |/usr/share//|Data files | |------------------+-----------------------------------------------------| |/usr/etc// |Configuration files | |------------------+-----------------------------------------------------| |/etc/ |Configuration files for system software (daemons, | | |etc) | +------------------------------------------------------------------------+ * /opt directory is reserved for manually compiled/installed applications. Packages should never place anything there. * /usr/libexec/ is not used in CRUX, thus packages should never install anything there. Use /usr/lib// instead. 5.6.3. Remove Junk Files * Packages should not contain “junk files”. This includes info pages and other online documentation, man pages excluded (e.g. usr/doc/*, README, *.info, *.html, etc). * Files related to NLS (national language support). Ports built using GNU autoconf can be told not to install these files by passing the option --disable-nls. Other compiler toolchains often provide no such option, forcing you to clean up the package footprint by hand. * Useless or obsolete binaries (e.g. /usr/games/banner and /sbin/mkfs.minix). 5.6.4. Pkgfile Variables * Do not add new variables to the Pkgfile. Only in very few cases does this actually improve the readability or the quality of the package. Further, the only variables that are guranteed to work with future versions of pkgmk are name, version, release, and source. Other names could be in conflict with internal variables in pkgmk. * Use the $name and $version variables to make the package easier to update/maintain. For example, source=(http://xyz.org/$name-$version.tar.gz) is better than source=(http://xyz.org/myprog-1.0.3.tar.gz) since the URL will automatically updated when you modify the $version variable. * Remember that source is an array, i.e. always do source=(...) and not source=... * Another array that pkgmk will make use of, if defined, is renames (introduced in CRUX 3.7). This array lets you save the downloaded source tarballs with a more descriptive filename, to avoid filename collisions when using a shared directory for downloads. See the Pkgfile man page for more details. 5.6.5. Pkgfile Header The commented lines at the beginning of a Pkgfile do not affect the operation of pkgmk, but prt-get and other CRUX tools will make use of the information provided there. Four headers of utmost importance are: +------------------------------------------------------------------------+ |Name |Meaning | |-----------+------------------------------------------------------------| |Description|A short description of the package; keep it factual | |-----------+------------------------------------------------------------| |Maintainer |Your full name and e-mail address, obfuscated if you want | |-----------+------------------------------------------------------------| |URL |A webpage with more information on this software package | |-----------+------------------------------------------------------------| |Depends on |A list of dependencies, separated either by spaces or commas| +------------------------------------------------------------------------+ Depends on can be omitted if there are no dependencies. To keep this line short, runtime dependencies in the 'core' collection are omitted, unless they provide a library that is dynamically linked to the built program. See the Pkgfile man page for more details. Two other headers you will often encounter when inspecting Pkgfiles are Optional and Nice to have. None of the official CRUX tools will be affected by the contents of these lines, but maintainers find it helpful to store in Optional the list of “soft” dependencies (libraries that will be linked to the built program, if present during compilation). This header then serves as a reminder of tests that might need to be included in the build() function in order to set the appropriate configure flags. As an end user of official ports, you might find in these headers some clues about: * the additional functionality that can be unlocked, when dependencies beyond the bare minimum are installed before the desired port. * the reason that pkgmk reports a footprint mismatch. * the breakage that might happen if you try to install on your CRUX system a package built on someone else's CRUX system. Example header # Description: CUPS - Common UNIX Printing System # URL: https://openprinting.github.io/cups/ # Maintainer: Juergen Daubert, jue at crux dot nu # Depends on: acl libusb zlib linux-pam # Optional: dbus gnutls 6. The Ports System 6.1. Introduction 6.1.1. What is a Port? A port is a directory containing the files needed for building a package using pkgmk. This means that this directory at least has the files Pkgfile (which is the package build description) and .footprint (which is used for regression testing and contains a list of files this package is expected to contain once it is built). Further, a port directory can contain patches and/or other files needed for building the package. It is important to understand that the actual source code for the package is not necessarily present in port directory. Instead the Pkgfile contains an URL which points to a location where the source can be downloaded. The use of the word port in this context is borrowed from the BSD world, where a port refers to a program that has been ported to a system or platform. The word can sometimes be a bit misleading since most programs require no actual porting to run on CRUX (or on Linux in general). 6.1.2. What is the Ports System? The term Ports System refers to a remote repository containing ports and a client program capable of downloading ports from that repository. The administrator of a CRUX system runs the ports(8) bash script to download ports from the remote repository and place them in /usr/ports/. The ports script uses rsync(1) or httpup(1) or git(1) to do the actual downloading/synchronization. 6.1.3. Port collections CRUX ports are organized in so-called 'collections'. There are three different layers of ports: 6.1.3.1. The official collections 'core', 'opt', 'xorg' and 'compat-32' core, opt, xorg and compat-32 are the four primary collections of CRUX. They're maintained by the CRUX development team which ensures that they're consistent and working well together. The first three are enabled by default. The compat-32 collection is disabled by default and contains 32-bit compatibility ports. 6.1.3.2. The user contributed collection 'contrib' The contrib collection is a collection which is provided by experienced port maintainers: some are part of the CRUX development team, while others are regular users. Its goal is to reduce the number of duplicate ports provided in the individual collections. If you're a seasoned port maintainer, you might even want to join the contrib team. As those ports are not provided officially by the CRUX development team, this collection is disabled by default. 6.1.3.3. The individual collections from CRUX users Using HttpUp or git, every user can publish his or her own ports easily; the only requirement for that is some webspace to upload the ports. Maintaining an HttpUp repository of ports, which you've tested and gotten successfully running, is a simple way to contribute back to the CRUX community. 6.2. Using the Ports System 6.2.1. Synchronizing Your Local Ports Structure When CRUX is installed for the first time the local ports structure (/usr/ports/) is empty. To bring your local ports structure up to date you use the ports utility with the -u option. Example: $ ports -u The -u option means update, and tells ports to contact the ports repository and download new and updated ports. The output from this execution is something like this: Updating file list from crux.nu::ports/crux-3.7/core/ Updating collection ports/crux-3.7/core/ ... Updating file list from crux.nu::ports/crux-3.7/opt/ Updating collection ports/crux-3.7/opt/ ... Updating file list from crux.nu::ports/crux-3.7/xorg/ Updating collection ports/crux-3.7/xorg/ ... Finished successfully The output reveals which files are downloaded, updated and deleted. 6.2.2. Listing Local Ports When the local ports structure has been updated the directory /usr/ports/ will contain at least two collections, core and opt. Under each of these directories you will find ports. You can simply browse around in the directory structure to find out which ports are available. $ cd /usr/ports/core/ $ ls acl/ httpup/ nftables/ attr/ iana-etc/ ninja/ autoconf/ inetutils/ openssh/ automake/ iproute2/ openssl/ bash/ iptables/ patch/ bc/ jansson/ pciutils/ binutils/ jsoncpp/ perl/ bison/ kbd/ pkgconf/ bzip2/ kmod/ pkgutils/ ca-certificates/ less/ ports/ cmake/ libarchive/ procps/ coreutils/ libcap/ prt-get/ cpio/ libdevmapper/ psmisc/ curl/ libedit/ python3/ dash/ libffi/ python3-setuptools/ db/ libgmp/ rc/ dcron/ libmnl/ rdate/ dhcpcd/ libmpc/ readline/ diffutils/ libmpfr/ rhash/ dumb_runtime_dir/ libnftnl/ rsync/ e2fsprogs/ libnghttp2/ sed/ ed/ libnsl/ shadow/ elfutils/ libpcre/ signify/ eudev/ libpcre2/ sqlite3/ exim/ libpipeline/ start-stop-daemon/ expat/ libtirpc/ sudo/ file/ libtool/ sysfsutils/ filesystem/ libusb/ sysklogd/ findutils/ libuv/ sysvinit/ flex/ linux-pam/ tar/ gawk/ lzlib/ time/ gcc/ lzo/ tzdata/ gdbm/ m4/ usbutils/ gettext/ make/ util-linux/ glibc/ man-db/ vim/ glibc-32/ man-pages/ which/ gperf/ meson/ xz/ grep/ mlocate/ zlib/ groff/ mpdecimal/ zstd/ gzip/ nasm/ hdparm/ ncurses/ You can also use ports with the -l option to list all local ports. Example: $ ports -l core/acl core/attr core/autoconf core/automake core/bash core/bc ... If you are looking for a specific package, a command like ports -l | grep sendmail provides a straightforward way to find out if the package is available and if so in which collection it is located. More complicated searches (eg., based on footprint, description, or maintainer) can be performed using prt-get. 6.2.3. Listing Version Differences To find out if the ports structure carries ports that are different (likely newer) compared to the versions currently installed, you can use the option -d. If differences are found (in either 'version' or 'release'), the output from the above command could look something like this: $ ports -d Collection Name Port Installed contrib pipewire 0.3.56-1 0.3.55-1 xorg mesa 22.1.5-1 22.1.4-1 If no version differences were found, i.e. the system is in sync with the ports structure, the output will simply be: $ ports -d No differences found 6.2.4. Building and Installing Packages Once you have found a port that you want to build and install you simply go into the desired port directory and use pkgmk to build it. Example: $ cd /usr/ports/core/gawk $ pkgmk -d The -d option means download missing source files and tells pkgmk to download the source(s) specified in the Pkgfile (in case the source is already downloaded, this option is ignored). When the download is completed the package will be built. If the package was built successfully you can use pkgadd to install or upgrade it. Example: $ pkgadd gawk#3.1.5-3.pkg.tar.gz To make life a bit easier these two steps can be made into one by using the options -i (for install) or -u (for upgrade). Example: $ pkgmk -d -i or $ pkgmk -d -u This will download, build and then install/upgrade the package. Note that the package will only be installed/upgraded if the build is successful. Note If you enable building ports as an unprivileged user and give that user write permissions on the directories for pkgmk {sources, work, packages}, the unprivileged user will be able to create a package but not to exercise the -i and -u options of pkgmk. There are forks of pkgmk that automatically invoke sudo or doas when performing the pkgadd step, but these forks are not part of the official CRUX utilities at this time. 6.2.5. Enabling the 'contrib' collection As previously mentioned, the 'contrib' collection contains useful ports of experienced port maintainers. Since they are not provided by the CRUX development team, you should be slightly more critical with respect to quality and security. However, members with write permissions for 'contrib' are usually well-known and active in the CRUX community. To enable the 'contrib' collection so that ports -u will bring it up to date, just rename its rsync file. $ cd /etc/ports $ mv contrib.rsync.inactive contrib.rsync You will probably also want to let prt-get know about the newly-enabled 'contrib' tree. This can be done by editing /etc/prt-get.conf and uncommenting the line prtdir /usr/ports/contrib (i.e. remove the hashmark in the beginning of the line). After that, it should look like this: ### ### prt-get conf ### # note: the order matters: the package found first is used prtdir /usr/ports/core prtdir /usr/ports/opt # the following line enables the user maintained contrib collection prtdir /usr/ports/contrib Now, run ports -u and you're ready to use the ports from contrib. 6.2.6. Enabling the 'compat-32' collection The 'compat-32' collection contains compatibility ports needed for 32-bit support (32-bit applications running on a 64-bit multilib system). To enable it for ports, do $ cd /etc/ports $ mv compat-32.rsync.inactive compat-32.rsync The 'compat-32' collection is enabled in the same way as the 'contrib' collection (described previously) for usage with prt-get. As with 'contrib', run ports -u and you're ready to use the ports from compat-32. 6.2.7. Additional tools 6.2.7.1. Building ports as unprivileged user Building packages requires root privileges in order to create files with the correct owner and group. This is a security concern because a malicious or badly designed port can run arbitrary commands when its Pkgfile is sourced by the shell. The fakeroot command provides a way to build ports as normal user. Particularly when you build packages from user contributed repositories you are advised to use fakeroot: $ fakeroot pkgmk -d * You can also make prt-get use fakeroot, by modifying the line in prt-get.conf that contains makecommand. This line would allow a non-root user running prt-get to create packages with no footprint mismatches (wrong owner/group), but the installation of these packages (and the running of pre-/post-install scripts) needs additional privileges. * Additional lines in prt-get.conf, defining addcommand and runscriptcommand with sudo or doas, is one way to let prt-get work properly for a non-root user. * Another possibility is to write a sudo or doas configuration that grants permission to run prt-get itself, and then as a non-root user you would always run sudo prt-get rather than prt-get directly. * Read the man pages for prt-get.conf and sudo/doas to learn how these pieces fit together, and choose whichever option you like best. To give extra scrutiny to ports you find outside the official repositories, it helps to restrict yourself to the low-level commands pkgmk and pkgadd rather than the wrapper program prt-get. This practice forces you to be in the directory of the unofficial port, where the Pkgfile source array and build function are more likely to receive your careful attention. 6.2.7.2. Useful scripts Regarding package and ports management there are many tasks which can be done in several steps with the CRUX standard tools introduced above. The opt repository contains a port called prt-utils with many such scripts. Other combinations of low-level tools, using UNIX pipes, command substitution, and text processing utilities, can be found in the bug tracker, the mailing list, and IRC logs. Efforts are underway to bring this diaspora of institutional knowledge into a central place, such as the EXAMPLES section of the most relevant man page. 7. Appendix 7.1. Troubleshooting Many common problems are answered in the FAQ document, so if you experience problems please check whether the CRUX FAQ contains answers to your questions already. If you have further questions, there's a dedicated mailing list for CRUX, and an IRC channel. Actual information about these can be found on the Community page. 7.2. Writing a grub config file by hand If grub-mkconfig does not work (eg., because you saved the kernel image under a non-standard name), a grub.cfg file can be created manually. For more information see the GRUB manual at http://www.gnu.org/software/grub/manual/. A simple example configuration might look like the following: # Display the menu for 10 seconds set timeout=10 # Boot the first entry by default set default=0 # Boot entries follow # Default CRUX boot entry menuentry "CRUX 3.7" { linux (hd0,msdos2)/boot/vmlinuz-5.15.55 root=/dev/sda2 quiet } # Single-user recovery entry menuentry "CRUX 3.7 single-user mode" { linux (hd0,msdos2)/boot/vmlinuz-5.15.55 root=/dev/sda2 quiet single } # Memory test entry menuentry "MemTest86+ 4.20" { linux16 (hd0,msdos2)/boot/memtest86+-4.20.bin } Save the manual configuration file as /boot/grub/grub.cfg. 7.3. EFI Stub installation notes GRUB and SYSLINUX offer the most familiar experience for users coming from LILO. After a one-time interaction with the BIOS and the Master Boot Record, all subsequent updates to the GRUB or SYSLINUX configuration only involve editing a flat-text file. Although with LILO you had to run /sbin/lilo after editing its flat-text config, for GRUB and SYSLINUX you never have to touch the contents of the bootsector or the NVRAM after the initial installation; changes to their flat-text config files are automatically detected. A third way to boot into your CRUX system involves direct interaction with the EFI variables, letting the Linux kernel image provide the required EFI bootloader code. This option has a workflow that might remind you of running /sbin/lilo after building and installing each new kernel. Note: this type of booting only works in UEFI mode, and when your kernel has been built with CONFIG_EFI_STUB=y. Legacy MBR booting is not supported with this method. As with GRUB and SYSLINUX, the kernel has to be told which device to use as a root filesystem. Most modern BIOSes allow you to append options like root=/dev/sda2 to the line that boots the kernel, but some buggy UEFI implementations do not honor such appended options. To be safe, you can customize the boot options during the kernel configuration process (the make menuconfig step), at the expense of making it harder to put the disk in an external enclosure and boot from USB (when you want to travel lightly). If you leave the boot options empty during kernel configuration, and the BIOS does not honor your appended options, you might have to boot from a rescue disk to get back into your system and fix things. * Copy your built kernel to the BOOT subdirectory of the EFI system partition (mounted at /boot/efi). For maximum compatibility, save it with the extension .efi. $ mkdir -p /boot/efi/BOOT $ cd /boot/efi/BOOT $ cp /usr/src/linux-5.15.55/arch/x86/boot/bzImage vmlinuz-5.15.55.efi * Next, create a boot entry telling the BIOS about the kernel image you just saved. $ efibootmgr -c -d /dev/sda -L 'Linux 5.15.55' -l '\BOOT\vmlinuz-5.15.55.efi' -u 'root=/dev/sda2' * Finally, change the boot order so that the newly-created boot entry is the first one tried. Start by finding the number assigned to the newly-created entry, and then use that number to specify the desired boot order. EXAMPLE: $ efibootmgr BootCurrent: 0000 Timeout: 1 seconds BootOrder: 0000,0001 Boot0000* Linux 5.15.26 HD(1,GPT,d5a44413-...,0x800,0x64000)/File(\BOOT\vmlinuz-5.15.26.efi)72006f006f0074... Boot0001* Linux 5.15.55 HD(1,GPT,d5a44413-...,0x800,0x64000)/File(\BOOT\vmlinuz-5.15.55.efi)72006f006f0074... $ efibootmgr -o 0001,0000 As in the UEFI installation of SYSLINUX, the subdirectory EFI/BOOT of the EFI system partition is the default path where the BIOS expects to find a bootloader. This location is more obvious in the efibootmgr commands, since efibootmgr is agnostic about the mountpoint of your EFI system partition. The two most common ways to shorten what looks like an overly-verbose path to the kernel are: * mount your EFI system partition somewhere else (and adjust the mkdir and cd commands as needed). * save your kernel closer to the root of the EFI system partition (and change the efibootmgr invocation as needed). 7.4. Notes on Initramfs A common scenario that prevents the usual practice of booting a slimmed-down kernel containing only the drivers for the root filesystem (and then loading modules to initialize other hardware) is that the root filesystem is not a physical volume, but rather a logical volume inside an encryption layer like LUKS. To handle this situation, you will need to go beyond the kernel building process outlined above, and also create a compressed filesystem image (called an initramfs) that contains the lvm2 and cryptsetup packages (and the drivers for usb input devices, if you chose not to compile them into the kernel). Creating such an initramfs was once an intricate procedure, but tools like dracut make it much simpler these days. If running dracut, and saving the initramfs alongside the kernel in the EFI system partition, had been the only deviations from the usual CRUX installation procedure, then one section of the appendix would suffice to explain how to do full-disk encryption in CRUX. But preparation for this setup begins at the partitioning stage, when you need to call commands from the lvm2 and cryptsetup packages before creating and mounting your filesystems. So this section of the appendix just points to a separate document, where an outline for installing CRUX with full-disk encryption is given from beginning to end. Even if full-disk encryption is not your desired endpoint and you just want to learn more about highly-modular kernel configs, the need for an initramfs is easier to motivate by considering a specific use case like full-disk encryption. Studying the upstream documentation for any unfamiliar command in the linked outline (eg., cryptsetup, pvcreate, or dracut) is an excellent way to distinguish the functions performed at each step of the process. Retrieved from https://crux.nu/Main/Handbook3-7 Page last modified on 2022-08-07 22:00