Installation

disk image — alpha
disk.img
UEFI only — x86_64 — x86-64-v3+
sha256  e2a0601c016f31eac794627cfeb99cc16bf6763e591d0004bf6b7f8234d15d21
↓ disk.img
03

Installation

krypt/sh ships as a UEFI-bootable disk image disk.img. Write it to a USB drive and boot it — you get a live shell with networking, package tools, and everything needed to install the system. Type setup-help at any time for a quick reference.

Note: The disk image is UEFI only. krypt/sh does not ship GRUB or syslinux. If you install to a spare partition on an existing system, you can chainload it from your existing bootloader as long as /etc/fstab is correct.

Write the image

Download: dl.krypt.sh/disk.img. For help, join #krypt/sh on Libera.Chat.

# verify checksum
$ sha256sum disk.img
e2a0601c016f31eac794627cfeb99cc16bf6763e591d0004bf6b7f8234d15d21  disk.img
# write to USB
$ dd if=disk.img of=/dev/sdX bs=4M status=progress

Boot the USB drive from your UEFI firmware. You will land at a root shell.

Network

# Ethernet starts automatically
# WiFi (built-in Ralink/Realtek)
# wpa_passphrase "SSID" "password" > /tmp/wpa.conf
# wpa_supplicant -B -i wlan0 -c /tmp/wpa.conf
# dhcpcd wlan0

Partition and mount

# fdisk /dev/sdX
# Create a GPT label, an EFI system partition, and a root partition
# mkfs.fat -F32 /dev/sdX1
# mkfs.ext4 /dev/sdX2
# mount /dev/sdX2 /mnt
# mkdir -p /mnt/boot/efi
# mount /dev/sdX1 /mnt/boot/efi

Install packages

# Create the filesystem skeleton
# setup-filesystem /mnt
# Install core system + build toolchain
# install --target /mnt core devel

The install script fetches pre-built binary packages from rsync://krypt.sh/bulk and installs them with addpkg.

core — the base system (~57 packages):

acl attr bash bzip2 coreutils dash-shell dhcpcd diffutils dosfstools e2fsprogs efibootmgr efivar file findutils gmp grep gzip iproute2 kmod libcap libelf libmnl libnl libressl libseccomp lz4 mawk mkpkg musl ncurses openresolv openvi patch pcre2 pkgtools popt procps readline revdep rsync runit sed shadow signify-openbsd tar pkg tzdata util-linux wget wpa_supplicant xxhash xz zlib zstd

devel — LLVM toolchain and build tools:

llvm-toolchain=(llvm clang compiler-rt libunwind lld libcxx) rust gcc-compat cmake python3 make meson samurai pkgconf autoconf automake libtool m4 perl

Generate fstab and chroot

# genfstab /mnt > /mnt/etc/fstab
# cat /mnt/etc/fstab
# enter-chroot /mnt

Configure the system

# passwd root
# echo myhostname > /etc/hostname
# ln -sf /usr/share/zoneinfo/Region/City /etc/localtime

Boot with EFISTUB

krypt/sh boots the kernel directly via UEFI — no bootloader required. Copy the kernel to the EFI system partition and create a boot entry:

# cp /boot/vmlinuz-X.Y.Z /boot/efi/vmlinuz-X.Y.Z.efi
# efibootmgr -c -d /dev/sdX -p 1 \
    -L 'krypt/sh X.Y.Z' \
    -l '\vmlinuz-X.Y.Z.efi' \
    -u 'root=/dev/sdXn rw quiet net.ifnames=0'
Existing bootloader: If you installed krypt/sh to a spare partition alongside another distribution, you can skip EFISTUB and add an entry to your existing GRUB configuration instead. As long as /etc/fstab is correct, grub-mkconfig or os-prober from the host system can detect and boot it.
07

Kernel

The kernel is installed as part of the linux group during installation. The kernel image lands at /boot/vmlinuz-X.Y.Z and modules go into /lib/modules/X.Y.Z.

Updating the kernel

After building or installing a new kernel version, copy it to the EFI system partition and create a new boot entry:

# cp /boot/vmlinuz-X.Y.Z /boot/efi/vmlinuz-X.Y.Z.efi
# efibootmgr -c -d /dev/sdX -p 1 \
    -L 'krypt/sh X.Y.Z' \
    -l '\vmlinuz-X.Y.Z.efi' \
    -u 'root=/dev/sdXn rw quiet net.ifnames=0'
# Optionally remove old entries
# efibootmgr
# efibootmgr -b XXXX -B

Since krypt/sh uses EFISTUB directly, each kernel version gets its own EFI boot entry. You can keep multiple versions and select between them from the UEFI firmware boot menu — no bootloader configuration needed.

Building a custom kernel

krypt/sh ships a default kernel via the linux port, but building a custom kernel is straightforward. Download the sources, copy the running config as a starting point, and build with LLVM:

# cd /usr/src
# tar xf linux-X.Y.Z.tar.xz
# cd linux-X.Y.Z
# Start from the running config
# zcat /proc/config.gz > .config
# make LLVM=1 olddefconfig
# Customize
# make LLVM=1 menuconfig
# Build
# make LLVM=1 -j$(nproc)
# make LLVM=1 modules_install
# cp arch/x86/boot/bzImage /boot/vmlinuz-X.Y.Z
LLVM=1 tells the kernel build system to use clang, lld, and LLVM tools for the entire build. This is the only supported method on krypt/sh since GCC is not available.

Loading modules

krypt/sh boots without an initramfs — there is no dracut, mkinitramfs, or initial ramdisk of any kind. The kernel mounts the root filesystem directly. This means any kernel modules your hardware needs at boot must either be compiled into the kernel (=y) or loaded early from /etc/rc.modules.

The /etc/rc.modules script is executed at boot and is the place to modprobe drivers that are built as modules (=m) rather than built-in. A typical setup:

#!/bin/sh
modprobe iwlmvm
modprobe iwlwifi
modprobe amdgpu
Must be executable. The script will not run unless you set the execute bit: chmod +x /etc/rc.modules. If you add new hardware or enable new module-only drivers, add the corresponding modprobe line here.

Since there is no initramfs, drivers that are critical for reaching the root filesystem — your storage controller, filesystem driver, and root disk encryption if used — must be built into the kernel with =y, not as modules. If they are only modules, the kernel cannot mount root and will panic. A safe rule of thumb:

Driver typeRecommendation
NVMe / AHCI / SCSIBuilt-in (=y) — needed to mount root
ext4 / XFS / btrfsBuilt-in (=y) — your root filesystem
dm-crypt / LUKSBuilt-in (=y) — if using encryption
GPU (amdgpu, i915)Module (=m) — loaded via rc.modules
WiFi (iwlwifi, ath)Module (=m) — loaded via rc.modules
BluetoothModule (=m) — loaded via rc.modules
Sound (snd-hda)Module (=m) — loaded via rc.modules
USB HID / inputBuilt-in (=y) — keyboard/mouse at boot

To check what modules are currently loaded on a running system, use lsmod. To see which module handles a specific device, use lspci -k or lsusb -t.

EFISTUB configuration

krypt/sh boots the kernel directly from UEFI firmware without a bootloader. The following options must be enabled for EFISTUB to work:

# Required for EFISTUB boot
CONFIG_EFI=y
CONFIG_EFI_STUB=y
CONFIG_EFI_MIXED=y
# EFI filesystem access
CONFIG_EFIVAR_FS=y
CONFIG_EFI_VARS=y
# EFI framebuffer (console before GPU driver loads)
CONFIG_FB_EFI=y
CONFIG_FRAMEBUFFER_CONSOLE=y
# GPT partition table support
CONFIG_EFI_PARTITION=y

Without CONFIG_EFI_STUB=y, the kernel image cannot be loaded directly by the UEFI firmware and you would need a bootloader like GRUB or systemd-boot. The EFI_MIXED option allows a 64-bit kernel to boot on 32-bit EFI firmware, which some older machines have.

Security & sandboxing

These options enable the kernel features that sandboxing tools, browsers (Firefox, Chromium), and container runtimes depend on. They are strongly recommended for any system running untrusted code:

# Seccomp — syscall filtering (required by browsers, containers)
CONFIG_SECCOMP=y
CONFIG_SECCOMP_FILTER=y
# User namespaces — unprivileged sandboxing (Flatpak, Chromium)
CONFIG_USER_NS=y
# PID, network, mount namespaces — process isolation
CONFIG_PID_NS=y
CONFIG_NET_NS=y
CONFIG_UTS_NS=y
CONFIG_IPC_NS=y
# Landlock — unprivileged filesystem sandboxing (kernel 5.13+)
CONFIG_SECURITY_LANDLOCK=y
# Yama — ptrace scope restrictions
CONFIG_SECURITY_YAMA=y
# Kernel hardening
CONFIG_RANDOMIZE_BASE=y
CONFIG_RANDOMIZE_MEMORY=y
CONFIG_STACKPROTECTOR=y
CONFIG_STACKPROTECTOR_STRONG=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_FORTIFY_SOURCE=y
Browsers need seccomp. Both Firefox and Chromium will refuse to start or will run without sandboxing if CONFIG_SECCOMP_FILTER=y is missing. This is the single most important security option on a desktop system.

Cgroups & containers

If you plan to run containers, lightweight VMs, or resource-limited services, enable cgroups v2 and the relevant controllers:

# Cgroups v2 (unified hierarchy)
CONFIG_CGROUPS=y
CONFIG_CGROUP_V2=y
# Resource controllers
CONFIG_MEMCG=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_BPF=y
# Overlay filesystem (container image layers)
CONFIG_OVERLAY_FS=y
# Virtual ethernet pairs (container networking)
CONFIG_VETH=y
CONFIG_BRIDGE=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y

To boot with cgroups v2 as default, add cgroup_no_v1=all systemd.unified_cgroup_hierarchy=1 to your kernel command line in the efibootmgr -u parameters. Since krypt/sh uses runit (not systemd), only the cgroup_no_v1=all part is strictly needed.

11

Encryption (LUKS2)

krypt/sh uses LUKS2 via cryptsetup for full disk encryption. The stack is: cryptsetupdevice-mapperargon2 (key derivation). No initramfs — the kernel must have dm-crypt built in.

Setting up LUKS2

# Format a partition with LUKS2 + argon2id KDF
# cryptsetup luksFormat --type luks2 --pbkdf argon2id /dev/nvme0n1p7
# Open the container
# cryptsetup open /dev/nvme0n1p7 cryptroot
# Format the plaintext device
# mkfs.ext4 /dev/mapper/cryptroot
# Mount and install as usual
# mount /dev/mapper/cryptroot /mnt

Opening at boot

Without an initramfs, LUKS volumes must be opened by a boot script before the root filesystem is mounted — or, for non-root volumes, by a runit service early in the boot sequence.

#!/bin/sh
cryptsetup open /dev/nvme0n1p7 whonix-gw
cryptsetup open /dev/nvme0n1p8 whonix-ws
cryptsetup open /dev/nvme0n1p9 fedora
Root partition encryption requires the kernel to have CONFIG_DM_CRYPT=y built in — not as a module. If dm-crypt is a module (=m), the kernel cannot open the LUKS container before mounting root and will panic.

The example above prompts for a passphrase for each volume separately. For systems with many encrypted partitions there is a cleaner pattern: dedicate one small partition as a keys partition. Open it with a single passphrase, mount it, then open every other volume using a keyfile read from inside it. Once all volumes are open, unmount and close the keys partition. By the time runit stage 2 starts, the keys partition is gone from the device mapper — no keyfiles are reachable from a running shell, even as root. You type one password at boot and all volumes open automatically from that point. The implementation belongs in /etc/boot.d/ as a stage 1 script alongside an /etc/crypttab that maps each volume name to its device and keyfile path. Adapt the logic to your own partition layout — do not copy it verbatim from any example.

Kernel requirements

# Device mapper core
CONFIG_BLK_DEV_DM=y
# dm-crypt — LUKS encryption
CONFIG_DM_CRYPT=y
# Crypto algorithms
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_XTS=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_ARGON2=y

LLVM musl libc libressl Independent