Installation &
Partitioning
A comprehensive deep dive into every decision you make before Debian boots for the first time. The primary target is Debian 13 trixie on amd64 — normal 64-bit Intel/AMD PC-class laptops, desktops, servers, and VMs — while many storage concepts also apply to other Debian architectures. It covers which ISO to use and why, netinstall vs full media, BIOS vs UEFI boot, MBR vs GPT partition tables, filesystem choices, swap strategy, LVM architecture, and LUKS encryption.
Understanding Debian ISO Types
Before you type a single command, you must choose which Debian ISO to download. This is not a trivial choice — each image implies a different installation method, network requirement, hardware support level, and result. Getting it wrong means a failed install or hours of troubleshooting. The table below focuses on the common image types most administrators normally encounter; Debian also publishes specialist netboot, jigdo, BitTorrent, source, and architecture-specific artifacts.
As of this document revision, Debian's current stable release is Debian 13 "trixie". Debian 12 "bookworm" is oldstable. Use trixie media and trixie repository names for new installations unless you intentionally need oldstable for compatibility testing or a controlled legacy environment.
This document is written primarily for Debian 13 trixie amd64 installations on normal 64-bit Intel/AMD PC-class systems. The partitioning, LVM, RAID, filesystem, swap, and LUKS concepts are broadly useful, but image filenames, bootloader paths, firmware behavior, and installer details can differ on non-amd64 architectures. For ARM, POWER, IBM Z, RISC-V, or other targets, verify the matching Debian installation manual for that architecture.
| Image Type | Download Size | Offline Install? | Desktop Included? | Best For |
|---|---|---|---|---|
| netinst | ~700–800 MB | Needs network for normal full install | Via network | Servers & most installs — the recommended default |
| Netboot / PXE files | Small kernel + initrd | ✗ Needs network | Via network | Automated installs, server racks, remote provisioning — not a normal ISO image |
| DVD-1 | ~3.7 GB | ✓ Base system + common pkgs | Desktop tasks available | Air-gapped installs, slow internet |
| DVD-2, DVD-3, … DVD-N | ~3.7 GB each | ✓ Extended offline packages | More packages, not a substitute for a full mirror | Not a direct download for amd64/arm64 — obtain via jigdo or BitTorrent only (see §03). Optional, non-bootable supplements. |
| Live Standard | ~1 GB+ | ✓ Live environment | No full desktop environment | Hardware testing, rescue, try before install |
| Live GNOME/KDE/Xfce | ~2–3 GB | ✓ | Yes (specific Desktop Environment / DE) | Desktop users who want to preview that desktop environment |
| Cloud images (qcow2/ova) | ~400–600 MB | Pre-installed OS image | No desktop by default | VM / cloud deployments — boot directly, no installer |
netinst means network install. It is a small Debian installer ISO, roughly 700–800 MB, that contains the installer, the minimal software needed to install a very basic system, and the tools needed to connect to Debian mirrors. It is not a complete offline installer for a normal server or desktop: after you boot it, configure networking, and choose a mirror, Debian fetches the remaining selected packages such as desktop environments, SSH server, standard utilities, updates, and many task packages from the network. For servers and most normal installs with internet access, this is usually the cleanest default because it installs only what you choose and pulls current packages from the repositories.
Netboot means the machine starts the Debian Installer from the network instead of from a USB stick or DVD. PXE means Preboot eXecution Environment, the common PC firmware method for network booting. In a PXE-style setup, firmware obtains network settings, downloads the installer kernel and initrd from a provisioning server, and then continues the installation using Debian mirrors, a preseed file, or local infrastructure. This is excellent for automated server deployment but unnecessary for a normal one-machine manual install.
Air-gapped means the machine or network is intentionally isolated from the internet and other untrusted networks. In Debian installation terms, an air-gapped install is one where the installer cannot reach Debian mirrors during installation. DVD-1 is useful in that situation because it carries the installer plus many common packages on the media itself. A laptop with Wi-Fi temporarily turned off is only a disconnected system; a true air-gapped environment is normally a deliberate security boundary, such as a restricted lab, secure production network, or offline server segment.
DE means Desktop Environment. In Linux, a desktop environment is the complete graphical user interface you see after login: panels, menus, application launcher, window manager, file manager, settings tools, terminal, and default desktop applications. GNOME, KDE Plasma, and Xfce are different desktop environments. A Debian live image labeled GNOME boots into GNOME; a KDE image boots into KDE Plasma; an Xfce image boots into Xfce.
Live Standard is a Debian live image that boots into a temporary Debian system directly from USB or DVD, but without a full graphical desktop environment such as GNOME, KDE Plasma, or Xfce. It is useful for hardware testing, system rescue, partition inspection, file recovery, and trying Debian without installing it to the hard disk. It is smaller than full desktop live images because it does not include a complete desktop stack.
Cloud images are ready-made Debian virtual machine disk images, not installer ISOs. Formats such as qcow2 are commonly used with KVM/QEMU, Proxmox, and OpenStack, while ova is commonly used for importing virtual appliances into virtualization platforms. Debian is already installed inside the image, so you import or attach the disk image and boot it directly. These images are best for VM templates, cloud instances, and automated deployments, not normal manual laptop or bare-metal server installation.
Starting with Debian 12 and continuing in Debian 13, official Debian installer images can include packages from the non-free-firmware component. The old advice to hunt for separate unofficial non-free firmware installer images is obsolete for normal Debian 13 installs. The installer detects firmware requested by drivers, installs matching firmware packages when available on the media, and configures APT so those firmware packages continue receiving updates. If a specific firmware blob is still missing, provide it on a FAT-formatted USB stick in the root directory or in a /firmware directory.
Architecture Selection
Debian supports several official CPU architectures. For almost all PC-class modern hardware, you want amd64 (the 64-bit x86 standard, used by Intel and AMD CPUs). The other architectures you might actually encounter:
| Architecture | Use Case | Notes |
|---|---|---|
| amd64 | 64-bit Intel/AMD desktops, servers, laptops | Default for almost all PC-class hardware. |
| arm64 | 64-bit ARM servers, SBCs, Apple Silicon VMs, cloud ARM | First-class release architecture. |
| armhf | 32-bit ARMv7 devices with hardware floating-point support | Supported in Debian 13, but use arm64 instead if the hardware supports 64-bit ARM. |
| ppc64el | IBM POWER little-endian systems | Mostly enterprise and virtualization use. |
| s390x | IBM Z / LinuxONE mainframes | Mainframe/server deployments. |
| riscv64 | 64-bit little-endian RISC-V systems | Officially supported for the first time in Debian 13. |
| i386 | 32-bit userland on amd64 only | No Debian 13 installer or official kernel for standalone i386 systems; retained for legacy 32-bit userland on amd64 through multiarch or chroots. Use amd64 for real installations wherever possible. |
| armel | Limited upgrade-only ARM EABI cases | No new-install Debian 13 installer; Debian 13 is the last-release / legacy path only. |
armhf is Debian's ARM hard-float architecture for older 32-bit ARMv7 devices that have hardware floating-point support, such as some embedded boards, single-board computers, routers, NAS devices, and legacy ARM appliances. The hard-float part means the CPU can perform floating-point math in hardware instead of relying only on slower software emulation. Use armhf only when the device is genuinely 32-bit ARMv7 and supported by Debian. If the hardware can run 64-bit ARM, choose arm64 instead because it is the modern ARM architecture and is generally the better long-term choice.
i386 is Debian's old 32-bit x86 architecture name. In Debian 13, it is no longer a normal installable operating-system architecture for old 32-bit PCs: there is no Debian 13 i386 installer and no official standalone i386 kernel path. Its remaining purpose is compatibility on a 64-bit amd64 Debian system, where you may install selected i386 libraries or run an i386 userland through multiarch, a chroot, or similar compatibility setup. For a real PC/server installation, choose amd64.Existing systems currently running Debian i386 should be checked for 64-bit CPU support. If the CPU supports x86-64 / long mode, reinstall using Debian amd64. If the CPU is genuinely 32-bit-only, it cannot run Debian amd64 and should normally be retired or kept on an older supported/controlled legacy path.
armel is Debian's older ARM EABI architecture for legacy 32-bit ARM systems. In Debian 13, it is not a normal fresh-install target: there is no new-install Debian 13 installer for armel systems. The practical path is limited to upgrading an existing supported armel system, and Debian 13 is the final/legacy release path for this architecture. For new ARM deployments, prefer arm64; for supported older 32-bit ARMv7 hardware, use armhf where appropriate.
Netinstall — How It Actually Works
The netinstall image (netinst) is the workhorse of Debian
deployments. On Debian 13, expect roughly 700–800 MB for common
architecture netinst images, with the exact size varying by architecture and point-release
build. It contains the installer itself, the packages needed to install a very basic system,
and the tooling to reach the Debian mirrors. A minimal base installation can be bootstrapped
from the image, but a normal server or desktop installation relies on the network for the
remaining selected packages, updates, desktop tasks, SSH server, and many standard utilities.
With netinst, you typically download debian-13.x.x-amd64-netinst.iso, write it to USB, boot it, configure the network, select a nearby mirror such as deb.debian.org, and then install only the package sets you choose. For a lean server, that often means selecting SSH server and standard system utilities, while leaving desktop environments unchecked.
What the Netinstall Image Contains
- 1debian-installer (d-i) — the installer binary and all its modules (partman, anna, base-installer, etc.)
- 2Linux kernel + initrd — a specific kernel version to boot the installer (not the final installed kernel)
- 3Base debootstrap packages — the minimal base system: libc, dpkg, apt, coreutils, essential utilities, and typically closer to roughly 100–150 binary packages before optional tasks are added. A tasksel "standard system utilities" install can push the installed package count into the ~250+ range.
- 4Network drivers — a broad set of kernel modules for Ethernet and (for firmware images) Wi-Fi, loaded to reach the mirror
- 5Anna (ANother Network Archive) — Debian's installer package fetcher, used to pull additional installer components (modules for RAID, LVM, crypto, etc.) from the mirror at install time
The Netinstall Flow: Step by Step
The sequence below follows the normal Debian 13 graphical Debian Installer (d-i) netinst path shown by the installer screens. It intentionally describes the screen order and installer modules without embedding screenshots, so the section remains a compact operational flow rather than a screen gallery.
nic-modules-...-amd64-di provides installer-stage network interface drivers. This appears before network configuration because the installer must first load the modules needed to detect and operate the network hardware.sudo. The installer then sets up the clock and, when networking is available, may retrieve time from a network time server.deb.debian.org is usually the safest general-purpose default when it is offered or manually entered. With netinst, a reachable mirror is important for desktop tasks, SSH server, standard utilities, updates, and packages not present on the media.The kernel is the core of Linux. The initrd or initramfs is a small temporary early-boot environment loaded with the kernel. It contains the drivers and scripts needed before the real root filesystem is mounted, such as LUKS unlock support, mdadm assembly, LVM activation, and storage drivers. Once the real root filesystem is available, normal userspace takes over.
Pressing e at the installer boot menu and adding priority=low to
the kernel command line, or selecting "Advanced options → Expert install",
exposes every installer question including: kernel parameters, specific mirror paths, HTTP
proxy configuration, partitioning tool selection (partman vs cfdisk), and manual package
selection outside of tasksel. Expert mode is useful for unusual installs, but many custom
disk layouts can still be built from the normal Manual partitioning screen.
Continuing Installation Through Serial Console or SSH
For servers without a local monitor, Debian Installer can be operated through a serial console or, after initial network setup, through SSH using the network-console component. These methods still require an initial control path, such as a physical serial connection, IPMI/iDRAC/iLO remote console, a VM console, or PXE/preseed automation.
For a serial-console install, add console=ttyS0,115200n8 to the installer
kernel parameters. Debian recommends placing serial console parameters after
--- when you want them copied into the installed system's bootloader
configuration where supported. The text frontend can also be useful for serial installs:
DEBIAN_FRONTEND=text.
install DEBIAN_FRONTEND=text --- console=ttyS0,115200n8
For an SSH-based installer session, first configure networking and load the
network-console installer component. In Advanced/Expert or medium-priority
installs, this can be selected from Load installer components from installation
media as network-console: Continue installation remotely using SSH.
Alternatively, PXE/preseed automation can load this component automatically. After the
component starts, the installer asks for a temporary installer SSH password and displays
connection instructions and the SSH fingerprint. You then connect from another machine as
the installer user and continue the installation remotely.
ssh -l installer <installer-ip-or-hostname>
Serial console can control the installer from the boot stage if the firmware, BMC, VM, or
physical serial path exposes the boot menu. SSH network-console is different: it normally
becomes available only after the installer has booted, networking has been configured, and
the network-console component has been loaded. For a completely unattended
headless start, use PXE/netboot with preseeding.
Full DVD & Live Images
DVD Images
Debian's DVD images are essentially a local mirror burned to disc. DVD images contain the installer plus a package pool. DVD-1 contains many commonly installed packages, but it is not a complete Debian mirror and the exact package set varies by release and image. The installer uses the DVD as its primary package source and falls back to the network for packages not present on the media.
DVD-1 is useful when the target machine has no usable internet connection during installation, such as a true air-gapped environment or a site with very slow or unreliable internet. It can install the base system and many common packages directly from the ISO. If the machine does have normal internet access, netinst is usually better because it downloads fresher packages from Debian mirrors instead of relying only on the package snapshot included on the DVD.
The full Debian package archive is spread across a numbered set of images
— DVD-1, DVD-2, DVD-3, and so on. The exact count varies by release,
architecture, and image type, and the full set is much larger than most users need. However, on the official
cdimage.debian.org HTTP directories only DVD-1 is usually published as a ready-to-use
.iso file for the common architectures (amd64, arm64). This is why, when you
visit the download pages, it looks like "there is only one DVD." The remaining images (DVD-2,
DVD-3, …) are real but are not served as direct ISO downloads — they are
obtained only via jigdo or BitTorrent (covered just below).
Debian states this directly: the extra images are non-bootable, entirely optional, and if you
have a reasonable internet connection you are better off pulling those packages from a normal
mirror than downloading whole DVDs.
- Many desktop/task packages offline
- Standard server packages
- Common admin and development packages
- Works for many installs without internet
- Additional desktop and library packages
- Extended dev libraries
- Non-bootable, optional supplements
- No direct ISO download for amd64/arm64
- Rarely needed — only true air-gap, broad-package installs
On servers, netinstall is almost always better than DVD even with slow
internet. The DVD image is a snapshot of packages as of the point-release build date; a netinstall
pulls current packages from the mirror, meaning your installed system is closer to current immediately after installation.
With DVD, you immediately need to run apt upgrade after install, downloading
months of security updates anyway.
How the Extra DVDs Are Actually Distributed
For the complete numbered DVD set, Debian's reliable method is jigdo; plain HTTP mirrors normally prioritize the first installer image and may not carry every extra DVD for every architecture. There
are three realistic ways to obtain extra package media. The normal current-release tree is
cdimage.debian.org/debian-cd/current/<arch>/, with sibling directories such as
iso-dvd/, jigdo-dvd/, and bt-dvd/:
| Method | Directory / Tool | What You Get | When To Use |
|---|---|---|---|
| Direct ISO | iso-dvd/ |
DVD-1 only (ready .iso) |
Normal installs; nearly everyone stops here |
| jigdo | jigdo-dvd/ + jigdo-lite |
Any DVD-N, including the complete set | The intended way to get the full set |
| BitTorrent | bt-dvd/ (.torrent files) |
Individual DVD images where torrent files and seeders are available; not the guaranteed complete-set method | When a specific extra image is well-seeded |
jigdo (Jigsaw Download) reconstructs a DVD image locally instead of
transferring a 3.7 GB ISO wholesale. You download a small .jigdo template plus a
.template file, and jigdo-lite then fetches the individual
.deb packages from any ordinary Debian mirror and assembles them into a
byte-for-byte identical ISO. This is why Debian does not bother hosting the full ISO set
directly — jigdo lets mirrors serve the same content from the package pool they already carry,
saving enormous amounts of disk space. It is also the only method that reliably yields
the entire set for every architecture.
A typical jigdo reconstruction of, say, DVD-3 looks like this. The package name is jigdo-file; it provides the jigdo-lite command.
sudo apt update
sudo apt install jigdo-file
jigdo-lite https://cdimage.debian.org/debian-cd/current/amd64/jigdo-dvd/debian-13.5.0-amd64-DVD-3.jigdo
# When prompted for a mirror, accept the default or supply a fast local mirror,
# e.g. https://deb.debian.org/debian/
# jigdo-lite downloads the .debs and assembles debian-13.5.0-amd64-DVD-3.iso
# If the point release has advanced, replace 13.5.0 with the current filename shown in that directory.
DVD-3 is only an example of reconstructing an extra package disc. For installation media, normally use DVD-1 because the first image in the set starts the Debian Installer. DVD-2, DVD-3, and later images are non-bootable optional supplements containing extra packages.
For almost every reader, you do not need DVD-2 or beyond at all. If the
machine has any internet access, install from netinst (or DVD-1) and let APT
pull the rest from a mirror — you get current, security-patched packages instead of a stale
release-day snapshot. The numbered DVD set only makes sense for a genuinely air-gapped
machine that also needs a broad, unpredictable range of packages offline. Even then, building a
proper local partial mirror (e.g. with apt-mirror or
debmirror) is usually cleaner than juggling many DVD images.
Live Images
Live images boot a fully running Debian system from the USB/DVD without touching your disk. They serve two purposes: hardware testing (does Debian see your GPU, Wi-Fi, etc.?) and installation (live images include the Calamares graphical installer). Key differences from the installer-based approach:
- +Graphical, point-and-click install via Calamares — more familiar to users coming from Ubuntu
- +Hardware validation before committing — you can browse the web, check if Wi-Fi works, verify GPU acceleration before installing
- −Less control over partitioning — Calamares's partitioner is simpler than d-i's partman; advanced layouts (LVM, LUKS) are harder to configure
- −Desktop environment (DE) is fixed — the GNOME live image installs GNOME; you cannot switch during install without removing/re-adding packages later
- −Snapshot packages — same staleness issue as DVD; packages are frozen at build time
Use the live image for hardware compatibility testing before committing to an install. If everything works in the live session, proceed with the netinstall image for the actual installation — you get more installer control and fresh packages.
Writing the ISO to USB
Debian ISOs are isohybrid — they are simultaneously a valid ISO 9660
filesystem and a valid disk image. This means you can write them directly to a USB drive
with dd (or equivalent), without any special USB-creation tool.
# Linux — write ISO directly to USB (replace sdX with your USB device)
# DANGER: this destroys all data on the target device — verify with lsblk first
lsblk # identify your USB device (e.g., /dev/sdb)
sudo dd if=debian-13.5.0-amd64-netinst.iso \
of=/dev/sdb \
bs=4M \
status=progress \
conv=fsync
# macOS equivalent
diskutil list # find your disk (e.g., disk2)
diskutil unmountDisk /dev/disk2
sudo dd if=debian-13.5.0-amd64-netinst.iso of=/dev/rdisk2 bs=4m
# Verify ISO checksum BEFORE writing (use SHA512SUMS from debian.org)
sha512sum -c SHA512SUMS --ignore-missing
Download SHA512SUMS and its detached signature from the same Debian image directory. First verify the signature on the checksum file, then verify the ISO hash. Debian publishes signed checksum files beside official installation and live images; do not trust an ISO simply because the filename looks correct.
# Debian/Ubuntu systems normally include Debian signing keys in debian-archive-keyring.
# If verification says "No public key", import the current Debian CD signing key using Debian's ISO verification page.
gpg --verify SHA512SUMS.sign SHA512SUMS
sha512sum -c SHA512SUMS --ignore-missing
What These Verification Commands Do
These two commands work together. First, gpg --verify proves that Debian signed the checksum file. Then, sha512sum -c proves that your downloaded ISO exactly matches one of the signed checksums. In short: GPG verifies the checksum file; SHA-512 verifies the ISO file.
These two commands verify two different things. The gpg command verifies the
authenticity of Debian's checksum file. The sha512sum command
verifies the integrity of the ISO file you downloaded. Use them together:
first prove that the checksum list is really from Debian, then prove that your local ISO
matches the checksum in that trusted list.
| Command | What It Checks | Why It Matters |
|---|---|---|
gpg --verify SHA512SUMS.sign SHA512SUMS |
Checks the detached OpenPGP signature file SHA512SUMS.sign against the checksum file SHA512SUMS. |
Confirms that the checksum file was signed by the expected Debian CD/image signing key and was not silently modified. |
sha512sum -c SHA512SUMS --ignore-missing |
Calculates the SHA-512 hash of local files listed in SHA512SUMS and compares each result with Debian's published value. |
Confirms that the downloaded ISO is byte-for-byte intact and not corrupted or replaced. The --ignore-missing option skips ISO files listed in SHA512SUMS that you did not download. |
The trust chain is: Debian signs SHA512SUMS → GPG verifies that signature → sha512sum verifies your ISO against the trusted checksum file. Signature verification proves who published the checksum list; checksum verification proves whether your downloaded ISO matches that list.
BIOS vs UEFI — What Actually Differs
The firmware that initializes your hardware before the OS loads — historically called BIOS (Basic Input/Output System), now largely replaced by UEFI (Unified Extensible Firmware Interface) — fundamentally changes how Debian is installed, where the bootloader lives, and what partition table you must use. Getting this wrong produces an unbootable system.
- Reads MBR (first 512 bytes of disk)
- Executes code at offset 0 of MBR
- Bootloader (GRUB) lives in MBR gap
- No concept of boot entries or EFI vars
- Works with both MBR and GPT partition tables
- Legacy BIOS can also boot GPT when GRUB has a BIOS Boot Partition
- No Secure Boot capability
- Reads EFI System Partition (ESP) — a FAT32 partition
- Loads
.efiexecutables (e.g.,grubx64.efi) - Boot entries stored in NVRAM (persistent)
- Normally paired with GPT and an EFI System Partition
- Supports disks > 2 TB bootable
- Supports Secure Boot (cryptographic chain of trust)
- Can run in CSM/legacy mode (emulates BIOS)
How to Tell Which Mode Your System Uses
# If /sys/firmware/efi exists, you booted in UEFI mode
ls /sys/firmware/efi # exists → UEFI; "No such file" → BIOS/legacy
# Also check the installer's boot menu — UEFI installs show UEFI explicitly
# In a running system:
efibootmgr -v # shows EFI boot entries; fails gracefully if BIOS
[ -d /sys/firmware/efi ] && echo UEFI || echo BIOS
UEFI Boot Flow in Detail
gdisk show this partition type as EF00. On Debian amd64, the selected EFI program is commonly \EFI\debian\shimx64.efi when Secure Boot is used, or \EFI\debian\grubx64.efi when GRUB is loaded directly. The firmware loads and starts that EFI executable.EFI/debian/grub.cfg may act as a small hand-off file, while the main generated boot menu is normally /boot/grub/grub.cfg. GRUB finds the selected linux and initrd/initramfs entries, loads them into memory, and starts the kernel with the boot command.systemd runs as PID 1.Many UEFI systems include a CSM that emulates legacy BIOS behavior. This lets you boot old operating systems or bootloaders. Disable CSM in UEFI settings for all new Debian installs — running GRUB in BIOS mode on UEFI hardware works but prevents Secure Boot, can cause confusing boot issues, and can install BIOS-mode GRUB by mistake and create confusing boot behavior on systems that should be native UEFI. If your system supports UEFI, use it natively.
Secure Boot on Debian
Secure Boot is a UEFI feature that cryptographically verifies every piece of code in the boot chain — from the bootloader to the kernel — before executing it. Only code signed with keys trusted by the firmware is allowed to run. Debian has supported Secure Boot since Debian 10 (Buster).
The Debian Secure Boot Chain
- 1UEFI firmware enforces Secure Boot using keys stored in firmware databasessuch as
dbanddbx. On typical PC systems, the allowed-signature database includes a Microsoft UEFI CA / Microsoft third-party UEFI CA certificate used to validate third-party bootloaders.. - 2shim (
shim-signedpackage) — a small Microsoft-signed UEFI binary. UEFI loadsshimx64.efi; shim then validates Debian-signed boot components using its built-in trusted certificate database and firmware trust databases. Debian’sshim-signedpackage is explicitly described as a Microsoft-signed Secure Boot chain-loading bootloader that can verify other UEFI binaries against firmware databases or a built-in signature database. - 3GRUB EFI binary (
grub-efi-amd64-signed) — signed by the Debian UEFI CA and intended to be used byshim-signed. This matches Debian’s package description forgrub-efi-amd64-signed. - 4Linux kernel (
linux-image-amd64) — thelinux-image-amd64meta-package depends on the current signed Debian kernel package for amd64, and Debian’s kernel handbook states that Debian signs the kernel image on amd64 and arm64 to support UEFI Secure Boot. - 5DKMS / out-of-tree modules — locally built third-party modules such as NVIDIA, VirtualBox, ZFS or vendor drivers are not automatically trusted under Secure Boot. They must be signed by a trusted key, commonly a Machine Owner Key enrolled through MOK, or Secure Boot enforcement must be disabled. Debian's kernel handbook states that with UEFI Secure Boot enabled, the Debian packaged kernel normally only allows modules signed by a trusted key to be loaded.
DKMS means Dynamic Kernel Module Support: it rebuilds external kernel modules when the kernel changes. With Secure Boot enabled, locally built modules are not trusted automatically. Some Debian DKMS package workflows may prompt you to enroll a local Machine Owner Key, or you may create and enroll one yourself with mokutil --import. On the next reboot, shim's MOK manager asks you to confirm enrollment. If the module is not signed by an enrolled key, the kernel will refuse to load it under Secure Boot. The enrolled key persists in shim’s MOK database, stored as UEFI firmware variables/NVRAM; it is separate from the firmware’s normal Secure Boot db
# Check if Secure Boot is currently enabled
mokutil --sb-state # SecureBoot enabled / disabled
# List enrolled MOKs
mokutil --list-enrolled
# Enroll a custom key for DKMS modules
openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -out MOK.der \
-outform DER -days 36500 -subj "/CN=My DKMS signing key/" -nodes
mokutil --import MOK.der # prompts for a one-time password
# reboot → MOK manager appears → enroll → reboot again
systemd-boot as a UEFI-Only Alternative
GRUB remains the normal Debian Installer bootloader path on amd64 and is still the most broadly useful
choice for deployments involving mixed BIOS/UEFI support, encrypted boot layouts, RAID, LVM, multi-boot detection, and rescue-oriented administration.
On simple modern UEFI-only systems, however, Debian also provides systemd-boot, a
small UEFI boot manager. It reads Boot Loader Specification entries from the EFI System
Partition or where used, the XBOOTLDR partition and it does not use GRUB's generated grub.cfg workflow.
| Bootloader | Strengths | Administrative Cautions |
|---|---|---|
| GRUB | Default installer path; mature support for complex Debian storage stacks, encrypted boot flows, BIOS systems, UEFI systems, and multi-boot detection. | update-grub regenerates configuration but does not by itself reinstall EFI binaries to every ESP. |
systemd-boot | Simple UEFI-only boot manager; Debian package integration installs it to the ESP; works naturally with Boot Loader Specification entries and Unified Kernel Image workflows. | Not the normal d-i default; requires deliberate post-install design, especially for encrypted root, snapshots, multiple ESPs, Secure Boot signing policy, and rollback testing. |
# Inspect boot-loader state on a UEFI system
bootctl status
bootctl list
# Debian integration package path; use only after planning the boot layout
apt install systemd-boot
bootctl status # verify ESP, loader state, and EFI variables
# Manual/recovery path when not relying on package integration
bootctl install
bootctl update
On Debian trixie, the systemd-boot package is the Debian integration point and is intended to configure and install systemd-boot to the ESP. The explicit bootctl install command remains important for manual builds, recovery work, verification, and non-standard layouts. In both cases, verify the result with bootctl status, bootctl list, and a real reboot test before depending on it.
Use systemd-boot when you intentionally want a UEFI-only, Boot Loader Specification based workflow and have tested kernel updates, initrd/UKI generation, Secure Boot signing, and rollback. Use GRUB for the default Debian path and for heterogeneous or more complex storage/boot scenarios.
MBR vs GPT — Partition Table Formats
Before you can create any partition, you need a partition table — a data structure at the very beginning of the disk that describes where each partition starts and ends. There are two standards: MBR (Master Boot Record, the legacy format) and GPT (GUID Partition Table, the modern standard). This choice has permanent consequences.
- Max 4 primary partition entries
- Workaround: one of the four entries can be an extended partition, with logical partitions inside
- MBR partition addressing limit: about 2 TiB with 512-byte logical sectors
- Single copy of the partition table — no GPT-style backup header or backup partition-entry array
- Legacy BIOS boot code can be stored in the MBR bootstrap area
- Compatible with legacy BIOS boot
- UEFI standardizes GPT, though some firmware can boot an ESP on MBR/removable media; use GPT + ESP for native Debian UEFI installs
- Up to 128 partition entries by default on common Linux/UEFI layouts
- No primary/extended/logical partition distinction
- Max addressable size: about 8 ZiB with 512-byte logical sectors; larger with bigger sectors
- Redundant: GPT has primary metadata near the start of the disk and backup metadata at the end
- CRC32 checksums cover GPT headers and the partition entry array
- Standard and strongly recommended for native UEFI boot
- Each partition has a type GUID and a unique partition GUID
MBR Extended & Logical Partitions Explained
MBR's 4-partition limit was a real constraint in the 1980s, so a workaround was invented: one of the four primary partition slots can be designated as an "extended partition", which acts as a container. Inside it you can create arbitrarily many logical partitions (sda5, sda6, …). However:
- !Logical partitions can be moved or resized with suitable tools, but the extended/logical structure is more fragile and easier to damage than GPT
- !The extended partition structure is a linked list — if the extended partition's metadata is corrupted, all logical partitions inside are inaccessible
- !LVM eliminates the need for logical partitions entirely on modern systems
GPT Protective MBR
GPT disks contain a protective MBR — a fake MBR record that declares the
entire disk as a single partition of type 0xEE (GPT protective). This prevents
old tools that don't understand GPT from overwriting the GPT data thinking the disk is
empty. If you open a GPT disk in a legacy fdisk, it will warn you about the
protective MBR.
BIOS-GPT Boot
When using GPT with legacy BIOS (not UEFI), GRUB needs a special
BIOS Boot Partition — a small (~1 MiB) partition with type code
EF02 in gdisk, or the bios_grub flag in
parted. GRUB writes its core image there because a GPT disk does not provide
the same reliable post-MBR embedding area that old MBR layouts often did. This partition has no filesystem and no mount point, but it is still visible in Linux storage inspection tools such as lsblk and in partitioning tools such as parted and gdisk.
Use GPT for all new installations on modern UEFI-capable hardware. The only reason to use MBR is to boot on genuine legacy hardware with no UEFI, or when adding Debian to an existing MBR multi-boot system. For UEFI systems, GPT plus a proper EFI System Partition is the safest and standard Debian layout for native UEFI boot.
Sector Size and Partition Alignment
A disk is divided into small addressable blocks called sectors. Older disks traditionally exposed 512-byte sectors, but many modern HDDs, SSDs, and NVMe devices work more naturally with 4096-byte sectors. Linux therefore needs to know two related values: the logical sector size, which is the sector size the operating system sees, and the physical sector size, which is the storage device's real internal sector or block granularity.
| Term | Meaning | Practical Impact |
|---|---|---|
512e |
512-byte logical sectors exposed to the operating system, but 4096-byte physical sectors internally. | Common compatibility mode. Misaligned writes can force extra read-modify-write work inside the disk. If partitions are not aligned with the disk’s real physical sector boundaries, the disk may need to read old data, merge it with the new data, and then write a full physical sector back, instead of just writing directly. |
4Kn |
4096-byte logical sectors exposed directly to the operating system. | Native 4K-sector operation. Older operating systems or old tools may not support it properly. |
| NVMe namespace format | An NVMe namespace may support more than one low-level block-size format. | Most Debian installs do not require changing this, but the reported logical and physical sizes should still be checked on important systems. |
Partition alignment means starting partitions at offsets that match the device's internal block boundaries. If a partition starts at a poor offset, filesystem blocks may straddle physical sectors. On 4K-sector media this can make a simple write touch more physical blocks than necessary, causing extra internal read-modify-write behavior and reducing performance.
A modern disk may pretend to Linux that it has 512-byte sectors while actually writing data internally in 4096-byte chunks. Debian and modern partitioning tools normally avoid problems by starting partitions at clean 1 MiB boundaries. That 1 MiB starting point lines up safely with both 512-byte and 4096-byte sector sizes.
Debian's normal installer and modern partitioning tools generally align newly created partitions
on MiB boundaries. This is a safe default for 512-byte, 512e, and 4K-sector
media because 1 MiB equals 1,048,576 bytes, which divides cleanly by
both common sector sizes:
# 1 MiB alignment math
1 MiB = 1,048,576 bytes
1,048,576 / 512 = 2048 sectors
1,048,576 / 4096 = 256 sectors
This is why many modern partition tables show the first normal partition beginning at sector
2048 on disks that report 512-byte logical sectors. Sector 2048
multiplied by 512 bytes equals exactly 1 MiB. By contrast, very old layouts that begin at
sector 63 are cylinder-era layouts and should not be copied onto modern SSD,
NVMe, or 4K-sector disks without correction.
# Show logical sector size, physical sector size, and I/O alignment hints
lsblk -o NAME,TYPE,SIZE,LOG-SEC,PHY-SEC,MIN-IO,OPT-IO,MODEL
# Show partition start/end positions in sectors
sudo parted /dev/nvme0n1 unit s print
# Show partition positions in MiB-friendly form
sudo parted /dev/nvme0n1 unit MiB print
# Verify parted's optimal alignment view for partition number 1
sudo parted /dev/nvme0n1 align-check optimal 1
For hand-built layouts, start normal partitions on 1 MiB boundaries unless a vendor, SAN, RAID controller, or storage-array policy explicitly requires something else. Debian Installer, parted, gdisk, and other modern tools normally do this automatically for new layouts, but manual scripts, old templates, and cloned partition tables should still be verified.
Be careful when cloning old disks or reusing legacy partitioning scripts. A cloned filesystem can carry forward an old sector-63 or otherwise misaligned layout even when the target disk is a modern SSD, NVMe device, or 4K-sector disk. After cloning, check the partition start sectors and run an alignment check before treating the layout as production-ready.
Partition Layouts — From Minimal to Production
A mount point is the directory where a filesystem appears inside Linux's single directory tree. For example, if a partition is mounted at /home, files stored under /home are written to that partition. The partition itself is a block device such as /dev/sda3 or /dev/nvme0n1p3; the mount point is the directory where users and programs access its contents.
Layout 1: Minimal (UEFI + GPT)
The absolute minimum for a working UEFI Debian system. Suitable for VMs, lab systems, simple bare-metal installs, or single-purpose appliances where simplicity is preferred over flexibility.
| Partition | Size | FS | Mount | Type Code | Notes |
|---|---|---|---|---|---|
| /dev/sda1 | 512 MB | FAT32 | /boot/efi | EF00 | EFI System Partition — required for UEFI |
| /dev/sda2 | All remaining | ext4 | / | 8300 | Root filesystem — everything lives here |
A swap file inside the root filesystem is valid and often simpler than a swap partition. On ext4 this is straightforward: create a preallocated file, protect it with mode 0600, run mkswap, then enable it with swapon. On btrfs, swap files are supported only with restrictions: the filesystem must be suitable for swapfile use, the file must be preallocated, must be no-CoW/no-compression, and the subvolume containing an active swapfile cannot be snapshotted. On Debian 13-era btrfs-progs, prefer btrfs filesystem mkswapfile --size 4G /swapfile instead of a generic fallocate recipe. Add the final swapfile path to /etc/fstab to persist, and configure resume separately if you need hibernation.
On Btrfs, a swapfile must be created as no-CoW before its extents are allocated. Do not create a normal file and later run chattr +C expecting existing extents to become valid for swap. Prefer btrfs filesystem mkswapfile on Debian 13-era systems; for a manual layout, create a dedicated non-snapshotted swap subvolume or directory, set chattr +C before creating the file, disable compression for that path, then run mkswap and swapon.
Dual-Boot and Coexistence Partitioning
When Debian must coexist with Windows or another Linux distribution, the goal changes from "create a clean layout" to "reuse what must be reused and avoid overwriting foreign boot or recovery partitions." Do not use a whole-disk guided layout on a disk containing an operating system you intend to keep.
| Existing Item | Safe Debian Handling | Do Not Do |
|---|---|---|
| Existing EFI System Partition | Mount it at /boot/efi; normally reuse it without formatting. | Do not create a second random ESP or format the Windows/vendor ESP unless you intentionally wiped the whole disk. |
| Windows MSR / recovery partitions | Leave them unmounted and unchanged. | Do not assign Linux filesystems or mount points to them. |
| Windows data partition | Shrink it from Windows Disk Management before booting the Debian installer when possible. | Do not shrink a hibernated, BitLocker-locked, or unclean NTFS volume from Linux. |
| Other Linux partitions | Identify by filesystem, UUID, label, size, and mount history before reusing. | Do not format an unfamiliar ext4/xfs/btrfs partition because it "looks Linux-like." |
| Free space | Create Debian root, optional swap, LVM, or LUKS partitions only inside confirmed free space. | Do not rely on device order alone; verify disk model, size, and partition numbers. |
For dual boot, choose Manual partitioning. The critical screen is the final write-confirmation summary: existing ESP, Windows, vendor recovery, and foreign Linux partitions should normally show "do not format" unless your written plan explicitly says otherwise.
Dual-boot systems often show a time shift after switching operating systems because Debian/Linux normally treats the hardware RTC as UTC, while Windows commonly treats it as local time. Prefer fixing Windows to use UTC by setting RealTimeIsUniversal to 1. The Linux-side workaround is sudo timedatectl set-local-rtc 1 --adjust-system-clock, but systemd warns that local RTC mode is less robust around time-zone and daylight-saving changes.
# Windows, run from an elevated Command Prompt
reg add HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation /v RealTimeIsUniversal /t REG_DWORD /d 1 /f
# Debian-side fallback when Windows cannot be changed
timedatectl
sudo timedatectl set-local-rtc 1 --adjust-system-clock
Layout 2: Traditional Server (UEFI + GPT)
Separating /boot from root allows the root filesystem to be on an encrypted
or LVM volume while the bootloader remains unencrypted. Separate /home and
/var isolate user data and log growth from the system.
| Mount | Size | Filesystem | Rationale |
|---|---|---|---|
| /boot/efi (ESP) | 512 MB | FAT32 | UEFI bootloader; 512 MB is generous but future-proof |
| /boot | 1 GB | ext4 | Kernels + initrds; 1 GB is a practical modern minimum and usually holds several kernel/initrd sets; monitor free space after kernel upgrades. |
| / | 20–30 GB | ext4 or xfs | OS and all packages; 20 GB is comfortable for most servers |
| /var | 20 GB+ | ext4 or xfs | Logs, databases, mail, package cache; grows unpredictably |
| /home | Remainder | ext4 or xfs | User data; isolating prevents home from filling root |
| swap | Workload-based | swap | Use at least RAM size only when hibernation is required; otherwise a smaller 4–8 GB swap area is often enough for ordinary servers. |
Layout 3: LVM over LUKS (Recommended for Laptops & Sensitive Servers)
A strong default design for laptops and many sensitive systems where full-disk-style encryption is required. One LUKS-encrypted volume contains the entire LVM Volume Group; you type one passphrase at boot and all partitions are unlocked.
The Debian Installer's standard encrypted-LVM workflow leaves /boot unencrypted. GRUB must read the kernel and initramfs before Linux can unlock the root filesystem. GRUB has cryptodisk support, but Debian Installer does not natively build a fully encrypted-/boot setup; it requires manual design and careful testing. In a normal LUKS+LVM install, keep /boot unencrypted and protect sensitive data by encrypting the root, home, var, and swap volumes.
Why Separate /var and /tmp?
Separating /var is the single most impactful partition decision for server
stability. Log rotation failures, database growth, package caches, container layers,
and mail/database spools all write to /var. If /var fills the
root filesystem, package management and daemons can fail in hard-to-debug ways. If a
separate /var fills, recovery is usually cleaner because the root filesystem
remains writable.
In Debian 13, /tmp defaults to a tmpfs backed by memory, with a default maximum of up to 50% of RAM. This improves temporary-file performance but can surprise administrators who place large files in /tmp. For workloads needing very large temporary files, override tmp.mount or define a persistent /tmp partition in /etc/fstab.
# Limit Debian 13's tmpfs-backed /tmp to 2 GiB
systemctl edit tmp.mount
# Add:
[Mount]
Options=mode=1777,nosuid,nodev,size=2G
systemctl daemon-reload
# Prefer rebooting to apply this safely; restarting tmp.mount can disrupt programs using /tmp.
systemctl restart tmp.mount # only when you know /tmp is not busy
Choosing a Filesystem
| Filesystem | Consistency Model | Max File Size | Max Vol Size | Best For | Avoid If |
|---|---|---|---|---|---|
| ext4 | Journaled; ordered mode is the normal default | 16 TiB | 1 EiB | Default choice. Well-tested, excellent fsck tooling, broad support | Need snapshots or transparent compression |
| xfs | Metadata journaling | 8 EiB | 8 EiB | Large files, high-throughput storage, /var with databases |
Very small filesystems (<300 MB); volumes you expect to shrink routinely |
| btrfs | Copy-on-Write transactional design, not a traditional journal | 16 EiB | 16 EiB | Snapshots, subvolumes, transparent compression, send/receive | Heavy random-write production databases; swap files on Linux kernels older than 5.0; improperly configured swap files |
| FAT32 | Non-journaled | 4 GiB minus 1 byte | Common practical limit: 2 TiB with 512-byte sectors | ESP (/boot/efi) for UEFI boot |
General Linux filesystems, permissions, logs, databases, or anything requiring Unix ownership/mode semantics |
| tmpfs | Volatile virtual-memory filesystem; RAM and, if available, swap-backed | Mount-size / virtual-memory limited | Mount-size / virtual-memory limited | /tmp, /run — volatile, fast temporary storage |
Anything needing persistence across reboots |
This table lists the filesystem choices a Debian administrator commonly selects from the normal Debian Installer or from standard Linux formatting workflows: ext4, XFS, Btrfs, FAT32 for the ESP, and tmpfs for volatile mounts. ZFS is real filesystem technology, but on Debian/Linux it is normally provided through OpenZFS packages from contrib and is not the default Debian Installer filesystem path. Treat ZFS as an advanced storage-platform choice, usually configured after the base system is installed or through a deliberate root-on-ZFS procedure, not as another simple formatting option beside ext4 and XFS.
XFS is a strong choice for large, active filesystems, but do not choose it for a volume you expect to shrink routinely. XFS is normally grown online with xfs_growfs. Although newer XFS tooling documents limited shrink behavior, shrinking XFS is still not a normal, general-purpose Debian administration workflow. For predictable recovery and resizing, plan LVM free space carefully; if a substantial shrink is required, the safest operational method remains backup, recreate the filesystem at the smaller size, and restore.
ext4 Mount Options Worth Knowing
# Conservative ext4 fstab entry for root
UUID=xxxx-xxxx / ext4 defaults,noatime,errors=remount-ro 0 1
# noatime — avoid access-time updates on reads; useful on busy systems
# discard — online TRIM; usually prefer periodic fstrim.timer instead
# errors=remount-ro — remount root read-only if ext4 detects serious errors
# data=ordered — default journal mode: data is written before metadata
# data=writeback — fastest but risk of stale data after crash (not recommended for /)
# Final two fstab fields:
# 0 — dump backup flag; 0 disables the legacy dump utility
# 1 — fsck pass number; 1 means check the root filesystem first
# Use 2 for other local filesystems that should be checked after root
# Use 0 for swap, tmpfs, network filesystems, bind mounts, and filesystems to skip fsck
In an /etc/fstab line, the last two fields are not mount options. The fifth field is the legacy dump backup flag; 0 means do not include this filesystem in dump backups, which is the normal modern value. The sixth field is the fsck pass number; 1 means check the root filesystem first during boot-time filesystem checks. Other local filesystems such as /home or /var normally use 2. Swap, tmpfs, network filesystems, bind mounts, and filesystems you intentionally do not want checked use 0.
btrfs Subvolumes for Snapshots
This section applies only when you deliberately choose btrfs as the filesystem. If the system uses ext4, you can skip the btrfs-specific commands here. On btrfs, a single filesystem can contain multiple subvolumes. A subvolume is an internal filesystem section that can be mounted separately and snapshotted independently, without creating a separate disk partition for each mount point.
With ext4, administrators often create separate real partitions for /, /home, and /var. With btrfs, you can instead create subvolumes inside one btrfs filesystem. Common names such as @, @home, @var, and @snapshots are naming conventions, not special Linux commands. They simply mean: @ is mounted as the root filesystem, @home as /home, @var as /var, and @snapshots as the snapshot storage location.
# Typical btrfs subvolume layout
@ → mounted as /
@home → mounted as /home
@var → mounted as /var
@snapshots → mounted as /.snapshots
The main reason to use this structure is snapshot control. For example, before a risky upgrade, you can snapshot the root subvolume @. If the upgrade breaks the system, a correctly configured btrfs snapshot workflow can help you roll back the operating system while keeping other subvolumes such as @home separate. Snapshots are useful restore points, but they are not a replacement for external backups.
btrfs normally uses Copy-on-Write (CoW). Instead of overwriting data blocks directly, btrfs writes changed data elsewhere and updates metadata to point to the new version. This helps with snapshots and consistency, but it can increase fragmentation and write overhead for heavy random-write workloads such as PostgreSQL, MariaDB/MySQL, and virtual machine disk images. For database directories on btrfs, disable CoW before the database creates files.
# btrfs only: disable CoW on a newly-created database directory before data is written
findmnt -no FSTYPE -T /var/lib/postgresql # verify this is btrfs first
mkdir -p /var/lib/postgresql # create the directory if missing
chattr +C /var/lib/postgresql # disable btrfs CoW for future files
# +C affects only files created after the attribute is set.
# Existing database files are not retroactively converted.
# This is btrfs-specific; ext4 has no btrfs-style CoW to disable.
| Command | Meaning |
|---|---|
findmnt -no FSTYPE -T /var/lib/postgresql | Checks which filesystem contains the target directory. Use chattr +C for this purpose only when the result is btrfs. |
mkdir -p /var/lib/postgresql | Creates the PostgreSQL data directory if it does not already exist. |
chattr +C /var/lib/postgresql | Sets the btrfs no-CoW attribute on the directory so new files created inside it avoid btrfs Copy-on-Write behavior. |
SSD TRIM Recommendation
SSDs and NVMe drives need a way to learn which blocks are no longer used by the filesystem. The command that communicates this information is called TRIM. When files are deleted, Linux removes them from the filesystem, but the SSD may not immediately know that the underlying blocks can be erased and reused internally. TRIM tells the drive: these blocks are unused now.
| Method | How It Works | Recommendation |
|---|---|---|
fstrim.timer | Runs TRIM periodically through systemd, normally as a batched maintenance task. | Preferred default for most Debian SSD/NVMe systems. |
discard mount option | Sends discard/TRIM operations immediately as files are deleted or blocks are freed. | Use only when you have a measured need for online discard. |
For normal Debian systems on SSD or NVMe storage, enable fstrim.timer and avoid adding discard to every /etc/fstab entry. Periodic TRIM batches cleanup work and usually avoids the synchronous overhead that immediate discard can add to delete/write-heavy workloads.
# Check whether periodic TRIM is active
systemctl status fstrim.timer
# Enable periodic TRIM now and at future boots
sudo systemctl enable --now fstrim.timer
# Normal ext4 root example: no discard option by default
UUID=xxxx-xxxx / ext4 defaults,noatime,errors=remount-ro 0 1
Synchronous discard overhead means the filesystem may have to wait while the storage device processes immediate discard/TRIM operations. That can make some file deletion or block-freeing operations slower. fstrim.timer usually avoids this by doing the cleanup later in a batch. Use discard only for a workload or storage stack where immediate TRIM has been tested and shown to help.
Btrfs Subvolumes and ZFS Pools: Different Storage Designs
This section compares two advanced Copy-on-Write storage designs that administrators often discuss together: Btrfs subvolumes and ZFS pools. They are not parts of the same technology. Btrfs is a Linux filesystem with subvolumes inside a Btrfs filesystem. ZFS, normally used on Debian/Linux through OpenZFS, is a separate storage platform that creates pools, datasets, and zvols.
Use the earlier Choosing a Filesystem section for ordinary Debian Installer choices such as ext4, XFS, Btrfs, FAT32 for the ESP, and tmpfs. Use this section when you are designing snapshot-oriented or pool-oriented storage and need to understand how Btrfs subvolumes and ZFS pools differ.
Btrfs subvolumes: separate trees inside one Btrfs filesystem
Btrfs is a Linux Copy-on-Write filesystem. A Btrfs subvolume is a separate file and directory tree inside one Btrfs filesystem. It can be mounted separately, snapshotted independently, renamed, and used as a rollback or send/receive boundary. A subvolume looks somewhat like a directory, but it has Btrfs-specific behavior and is not the same thing as a partition, LVM logical volume, or separate block device.
| Subvolume | Typical Mount | Purpose |
|---|---|---|
@ | / | Root filesystem subvolume used by many snapshot and rollback examples. |
@home | /home | Keeps user data outside normal root rollback workflows. |
@var | /var | Optional boundary for logs, caches, databases, package state, and application data. |
@snapshots | /.snapshots or tool-specific path | Dedicated location for snapshot-management tools when your workflow expects it. |
@log | /var/log | Optional boundary when logs should not be rolled back with the operating system. |
@, @home, @var, and similar names are conventions. They are common because snapshot tools, rollback examples, and administrator notes often use them, but Btrfs itself does not require those exact names. Document the chosen layout in /etc/fstab comments or site build notes.
Btrfs subvolumes share the space of the containing Btrfs filesystem unless quotas/qgroups are deliberately configured. They are useful for mount boundaries and snapshot boundaries, but they do not automatically provide the same hard space isolation as separate partitions or LVM logical volumes. Snapshots are also not backups; they are local Copy-on-Write references that can be lost with the same filesystem or storage device.
Btrfs layout blueprint
| Layer | Example | Purpose |
|---|---|---|
| ESP | /dev/sda1 → FAT32 at /boot/efi | UEFI boot files; keep outside Btrfs. |
Optional /boot | /dev/sda2 → ext4 at /boot | Simplifies GRUB and initramfs handling, especially with encryption. |
| Optional LUKS | /dev/sda3 → cryptroot | Encryption boundary below the Btrfs filesystem when full-disk encryption is required. |
| Btrfs filesystem | @, @home, @var, @snapshots | Subvolumes provide mount and snapshot boundaries without creating separate block devices. |
| Mount policy | compress=zstd, deliberate noatime, documented snapshot policy | Compression and snapshots should be chosen intentionally and tested. |
# Example Btrfs subvolume creation after mounting the new filesystem at /mnt
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@var
btrfs subvolume create /mnt/@snapshots
# Inspect subvolumes and Btrfs allocation
btrfs subvolume list /
btrfs filesystem usage /
ZFS pools: OpenZFS storage platform and filesystem provider
ZFS is filesystem technology, but it is not just a simple filesystem format like ext4. On Debian/Linux it is normally provided by OpenZFS. ZFS combines storage-pool management, RAID-like redundancy, checksumming, Copy-on-Write snapshots, compression, quotas, replication, and optional native encryption into one platform.
Instead of formatting one partition directly as ext4 or XFS, ZFS groups one or more disks or partitions into a pool, usually called a zpool. A pool is built from one or more vdevs. Inside the pool, administrators create datasets, which are mountable ZFS filesystems with their own properties, or zvols, which are block volumes for VM disks, iSCSI/LUN-style storage, and other special-purpose block-device workflows.
# Simplified ZFS hierarchy
disk(s) -> vdev(s) -> zpool -> dataset / zvol
ZFS datasets are filesystems, so it is correct to call ZFS filesystem technology. However, on Debian/Linux, OpenZFS is packaged through contrib and normally requires deliberate package, kernel-module, initramfs, Secure Boot, and recovery planning. That is why this guide does not present ZFS as a normal Debian Installer filesystem choice beside ext4, XFS, and Btrfs. For most Debian installations, keep / on ext4, XFS, or Btrfs unless you have a tested root-on-ZFS procedure; use ZFS mainly when you intentionally want a pool-oriented data-storage design.
A Debian system can use several storage technologies at the same time: FAT32 for /boot/efi, ext4 or XFS for /, Btrfs for a snapshot-oriented root filesystem, and a separate ZFS pool mounted at /srv, /data, /tank, or /backup. Coexistence means separate mount points or separate storage areas. It does not mean ZFS must be used with Btrfs, and it does not mean a ZFS dataset should normally be formatted again as ext4, XFS, or Btrfs.
Where ZFS fits on Debian
| Use Case | Where It Fits | Recommendation |
|---|---|---|
| Data pool | Large storage under /srv, /data, /tank, or application-specific mount points. | Good practical Debian use case when checksums, compression, scrubs, snapshots, replication, or multi-disk redundancy are required. |
| Backup or replication target | Backup server, NAS-style storage, lab archive, or off-host replication destination. | Strong fit because ZFS snapshots and zfs send/zfs receive support versioned replication naturally. |
| Virtualization storage | VM image storage, Proxmox-style storage designs, or zvol-backed VM disks. | Useful, but tune recordsize, volblocksize, sync policy, snapshots, and backup workflow deliberately. |
| Root filesystem | / itself on a ZFS pool. | Advanced on Debian. Confirm contrib/backports policy, DKMS module handling, Secure Boot signing, initramfs support, bootloader support, and rescue procedure first. |
| Simple laptop or small VM | Single-disk general-purpose installation. | Usually prefer ext4, XFS, or Btrfs from the normal installer path unless ZFS features are specifically required. |
ZFS layout blueprint
| Layer | Example | Purpose |
|---|---|---|
| ESP and boot strategy | Separate ESP, usually with a conventional bootloader path | Root-on-ZFS requires deliberate boot planning; data-only ZFS is simpler. |
| ZFS vdevs | Whole disks, mirrored disks, RAIDZ vdevs, or documented partitions | Defines redundancy, failure domain, replacement behavior, and expansion limits. |
| Zpool | tank, rpool, backup | Shared storage pool from which datasets and zvols are created. |
| Datasets | tank/data, tank/home, tank/backups | Mountable ZFS filesystems with independent properties, snapshots, quotas, and reservations. |
| Zvols | tank/vm01 | Block volumes for VM disks, iSCSI/LUN-style use, or special-purpose block-device workflows. |
| Policy | Compression, snapshots, scrub schedule, replication, encryption, and DKMS/Secure Boot handling | Operational policy is part of the storage design. |
# ZFS: inspect pools and datasets when OpenZFS is intentionally installed
zpool status
zpool list
zfs list
Btrfs subvolumes vs ZFS pools: direct comparison
| Topic | Btrfs Subvolumes | ZFS Pools / Datasets |
|---|---|---|
| Basic unit | Subvolumes are independent file trees inside one Btrfs filesystem. | A zpool is built from vdevs; datasets inside the pool are mountable ZFS filesystems. |
| Normal Debian role | Can be selected as a filesystem and then manually structured with subvolumes. | Normally installed and managed deliberately through OpenZFS packages; not the standard Debian Installer filesystem path. |
| Space model | Subvolumes share the containing filesystem unless quotas/qgroups are configured. | Datasets share pool space but can have quotas and reservations. |
| Snapshot model | Snapshots are Btrfs subvolumes with initial contents from another subvolume. | Snapshots are dataset or zvol snapshots managed with ZFS tooling. |
| Layering | Often used above a partition or LUKS device; may reduce the need for many partitions or LVs. | Often replaces the RAID/LVM/filesystem split with vdevs, pools, datasets, and zvols. |
| Encryption | Use LUKS underneath for full-disk or filesystem-level encryption design. | ZFS has native dataset encryption, but Debian boot, key handling, and recovery design still need planning. |
| Best practical fit | Snapshot-oriented Linux root filesystems, desktops, laptops, and systems needing subvolume-level rollback design. | Data pools, backup targets, NAS-style storage, replication workflows, and advanced storage platforms. |
| Production caution | Plan swap, database CoW behavior, snapshot retention, quotas, scrub/maintenance, and restore testing. | Plan vdev layout, stable disk identifiers, scrubs, replication, module updates, Secure Boot signing, and degraded-device recovery. |
Do not stack Btrfs and ZFS together for the same ordinary storage area just because both support snapshots. Choose the storage design deliberately: traditional mdadm/LUKS/LVM/ext4 or XFS, Btrfs with subvolumes, or ZFS with pools and datasets. Whichever design you choose, document the layout and test backup, restore, and degraded-device recovery before depending on it.
Device Names, UUIDs, PARTUUIDs, and /etc/fstab
A correct partition layout is not complete until the system can reliably find it at boot.
Linux kernel device names such as /dev/sda, /dev/sdb, and
/dev/nvme0n1 are discovery-order names, not permanent
identities. They describe the order in which the kernel discovered storage during this
particular boot. That order can change after adding or removing disks, moving a disk to
another controller port, changing BIOS/UEFI storage mode, updating firmware, altering a VM's
virtual-disk order, attaching USB storage, or changing a storage appliance presentation.
For one-time interactive work, raw names such as /dev/sda2 are convenient. For
persistent configuration, they are fragile. Use stable identifiers in /etc/fstab,
/etc/crypttab, initramfs configuration, and bootloader configuration whenever
possible. The normal Debian rule is simple: use UUID= for mounted filesystems
and swap; use PARTUUID= only when you need to identify the partition itself
before a filesystem is involved.
There are several identity layers. The disk or namespace is the block device. The partition table gives partitions identities such as PARTUUID and PARTLABEL. The filesystem or swap area created inside a partition has its own UUID and optional LABEL. LUKS, LVM, and mdadm add mapping layers on top. Good system configuration references the most stable layer that matches the job.
| Identifier | Example | Best Use | Notes |
|---|---|---|---|
| UUID | UUID=... | Filesystems and swap | Stored inside the filesystem superblock or swap header. This is the most common and safest choice for /etc/fstab. Reformatting the filesystem normally creates a new UUID. |
| PARTUUID | PARTUUID=... | Raw partitions before filesystems | Stored in partition-table metadata. It identifies the partition entry itself, not the filesystem inside it. Useful for bootloaders, kernel root= arguments, embedded systems, and special pre-filesystem cases. |
| LABEL | LABEL=rootfs | Human-readable admin setups | Convenient for simple systems, rescue media, and lab environments. Labels are not guaranteed unique unless you manage them carefully. |
| PARTLABEL | PARTLABEL=root-part | GPT partition naming | Human-readable partition-table label. Useful for documentation and automation, but still requires uniqueness discipline. |
| /dev/disk/by-id | /dev/disk/by-id/nvme-... | Whole disks and device-level references | Usually based on hardware identifiers such as model, serial, WWN, or NVMe EUI/NGUID. Prefer this when you must refer to a physical disk rather than a filesystem. |
| /dev/mapper | /dev/mapper/vg-root | LVM, LUKS, and dm-crypt mapped devices | Readable and common. Safe when names are stable, but renaming VGs, LVs, or crypt mappings requires updating references and rebuilding initramfs. |
| /dev/sdX | /dev/sda2 | Temporary commands only | Good for immediate commands after checking lsblk. Avoid in persistent configuration because the letter can change. |
UUID vs PARTUUID in Practice
UUID= and PARTUUID= are often confused because both look like long
hexadecimal identifiers. They identify different things. A filesystem UUID belongs to the
filesystem or swap signature. A partition UUID belongs to the partition table entry. If you
delete and recreate the filesystem but keep the partition entry, the PARTUUID may
stay the same while the filesystem UUID changes. If you delete and recreate the
partition, the PARTUUID changes even if you later restore a filesystem backup.
| Question | Use UUID | Use PARTUUID |
|---|---|---|
Mount root, /home, /var, or swap in /etc/fstab | Yes | Usually no |
| Refer to a partition before Linux knows the filesystem | No | Yes |
| Bootloader or kernel argument needs a raw partition reference | Sometimes | Often useful |
| Filesystem may be recreated during maintenance | Changes after reformat | May survive if the same partition entry remains |
| Partition may be deleted/recreated | May survive only if filesystem is restored exactly | Changes |
For normal Debian installations, write /etc/fstab with filesystem UUID= values. Use PARTUUID= deliberately when the partition itself matters, such as bootloader configuration, unusual initramfs workflows, appliance images, or systems where no filesystem UUID exists yet.
Discovering Persistent Identifiers
Use lsblk for a readable tree view and blkid for exact identifiers.
On systems with multiple disks, also inspect /dev/disk/by-id/ because it exposes
stable device symlinks based on hardware or virtual-disk identity. This is especially useful
before partitioning or when building RAID, LUKS, or LVM layouts.
# Readable topology with persistent identifiers
lsblk -o NAME,SIZE,TYPE,FSTYPE,LABEL,UUID,PARTUUID,MOUNTPOINTS
# Exact block-device metadata, useful for copy/paste into config files
blkid
blkid /dev/sda2
blkid /dev/nvme0n1p2
# Stable disk identity symlinks
ls -l /dev/disk/by-id/
ls -l /dev/disk/by-uuid/
ls -l /dev/disk/by-partuuid/
| Command | What It Shows | Why You Use It |
|---|---|---|
lsblk -o ... | Block-device tree, filesystem type, labels, UUIDs, PARTUUIDs, and mount points. | Best first command because it shows parent-child relationships: disk → partition → LUKS/LVM → filesystem. |
blkid | Filesystem, swap, LUKS, RAID, and partition identifiers in a compact format. | Good source for exact UUID= and PARTUUID= values. |
/dev/disk/by-id/ | Symlinks named from device identifiers such as serial numbers, WWNs, or virtual-disk IDs. | Useful for selecting the correct physical disk before destructive partitioning. |
/dev/disk/by-uuid/ | Symlinks named after filesystem or swap UUIDs. | Equivalent source for values commonly used in /etc/fstab. |
/dev/disk/by-partuuid/ | Symlinks named after partition UUIDs. | Useful when partition identity matters more than filesystem identity. |
How /etc/fstab Is Structured
Each non-comment line in /etc/fstab has six fields. The first four decide
what gets mounted, where it gets mounted, as what filesystem type,
and with which options. The final two fields are not mount options: they control the
legacy dump backup flag and boot-time filesystem-check order.
| Field | Name | Example | Meaning |
|---|---|---|---|
| 1 | Device specification | UUID=aaaa-bbbb | What to mount. Prefer UUID=, LABEL=, PARTUUID=, or a stable mapper path instead of raw /dev/sdX. |
| 2 | Mount point | /home | Where it appears in the filesystem tree. Swap uses none. |
| 3 | Filesystem type | ext4, xfs, vfat, swap | The filesystem driver or special type. |
| 4 | Mount options | defaults,noatime | Comma-separated options. No spaces inside the option list. |
| 5 | dump flag | 0 | Legacy backup field. Modern Debian systems almost always use 0. |
| 6 | fsck pass number | 1, 2, or 0 | 1 is normally root; 2 is other local filesystems to check later; 0 means skip automatic fsck for this entry. |
# Example /etc/fstab using UUIDs
UUID=aaaa-bbbb / ext4 defaults,noatime,errors=remount-ro 0 1
UUID=cccc-dddd /home ext4 defaults,noatime 0 2
UUID=dddd-eeee /var xfs defaults,noatime 0 0
UUID=eeee-ffff none swap sw 0 0
UUID=1111-2222 /boot/efi vfat umask=0077 0 1
# Meaning of the last field:
# 1 = check early, normally root; installer-created ESP entries may also use this
# 2 = check after root, normally other ext4 local filesystems
# 0 = do not run boot-time fsck for this entry
The short placeholders above (aaaa-bbbb, xxxx-xxxx, and similar) are shortened only for readability and column alignment. Real identifiers do not look alike across types. A FAT32 filesystem such as the ESP uses a short volume ID of the form 1234-ABCD (eight hexadecimal digits with a dash). An ext4, xfs, swap, or LUKS identifier is instead a full 36-character UUID such as 123e4567-e89b-12d3-a456-426614174000. Always copy the exact value from blkid, lsblk, or /dev/disk/by-uuid/ rather than typing a placeholder by hand.
Do not blindly copy fsck pass numbers between filesystem types. Ext4 root normally uses 0 1; other ext4 filesystems normally use 0 2. Swap uses 0 0. XFS commonly uses 0 0 because it is journal-recovered at mount time and is not checked by a traditional boot-time fsck pass. For the ESP, many installer-generated examples use 0 1; if writing by hand, follow your distribution's generated style and verify with findmnt --verify.
What the Example Entries Mean
| Entry | Meaning |
|---|---|
UUID=aaaa-bbbb / ext4 ... 0 1 | Mount the ext4 filesystem with that UUID as root. errors=remount-ro tells ext4 to remount root read-only after serious filesystem errors. The final 1 makes it the first filesystem check target. |
UUID=cccc-dddd /home ext4 ... 0 2 | Mount a separate ext4 home filesystem after root. The final 2 means it is eligible for checking after the root filesystem. |
UUID=eeee-ffff none swap sw 0 0 | Enable the swap area with that swap UUID. Swap has no mount point, so the second field is conventionally none. |
UUID=1111-2222 /boot/efi vfat umask=0077 0 1 | Mount the EFI System Partition at /boot/efi. umask=0077 restricts access so ordinary users cannot browse EFI boot files. |
LVM, LUKS, and fstab References
With LVM and LUKS, keep the layers separate. /etc/crypttab unlocks encrypted
block devices. LVM then activates volume groups and logical volumes. /etc/fstab
mounts the filesystems that exist after those layers are available. In other words,
do not put the LUKS container UUID in /etc/fstab for root; put the filesystem UUID
of the unlocked filesystem or the logical volume that contains it.
# Get the LUKS container UUID for /etc/crypttab
cryptsetup luksUUID /dev/nvme0n1p3
# Example /etc/crypttab: name encrypted-device keyfile options
cryptlvm UUID=12345678-1111-2222-3333-abcdefabcdef none luks
# Get filesystem UUIDs after opening LUKS and activating LVM
blkid /dev/mapper/vg--debian-root
blkid /dev/mapper/vg--debian-home
# Example /etc/fstab then refers to the filesystem UUIDs
UUID=aaaa-bbbb / ext4 defaults,noatime,errors=remount-ro 0 1
UUID=cccc-dddd /home ext4 defaults,noatime 0 2
Paths such as /dev/mapper/vg--debian-root are readable and widely used, but they depend on the chosen VG/LV names. If you rename a volume group, logical volume, or LUKS mapping, update /etc/fstab, /etc/crypttab, bootloader configuration if needed, and rebuild the initramfs with update-initramfs -u -k all.
Validating /etc/fstab Safely
A broken /etc/fstab can stop the system during boot or drop it into emergency
mode. After editing it, validate syntax and test mounts before rebooting. Be especially
careful on remote servers: a bad network mount, missing disk, or typo in the root entry can
turn a simple edit into a console-recovery job.
The fifth fstab field is the legacy dump backup flag and is normally 0 on modern Debian systems. The sixth field is more operationally important: it controls filesystem-check ordering. Use 1 for the root filesystem, 2 for normal local filesystems that should be checked after root, and 0 for entries that should not be checked. A wrong pass number on unavailable or misidentified storage can turn a boot into an emergency-mode recovery task.
# Always keep a quick rollback copy
sudo cp /etc/fstab /etc/fstab.bak
# Edit fstab, then ask findmnt to check parsing and libmount usability
sudoedit /etc/fstab
findmnt --verify --verbose
# systemd reads fstab through generators; reload after editing
sudo systemctl daemon-reload
# Mount everything not already mounted and not marked noauto
sudo mount -av
# Confirm final state
findmnt
swapon --show
| Validation Step | What It Catches | What It Does Not Fully Prove |
|---|---|---|
findmnt --verify | /etc/fstab parsing/usability issues, missing mount-point directories, duplicate targets, and some unsupported or currently unresolvable entries. | It does not perform a full block-layer, disk-health, RAID, LUKS, or LVM audit, and it does not replace a real mount -av test after edits. |
systemctl daemon-reload | Forces systemd to regenerate its view of mount units after fstab changes. | It does not mount anything by itself. |
mount -av | Attempts to mount all applicable entries and prints what it is doing. | It may not fully retest already-mounted root, boot, or special early-boot mounts. |
swapon --show | Confirms swap entries are active. | It does not validate hibernation resume configuration. |
On a remote production server, do not reboot immediately after editing /etc/fstab. Keep a root shell open, check the file with findmnt --verify --verbose, run mount -av, check journalctl -p warning..alert -b if needed, and make sure you have out-of-band console access before testing a reboot.
NVMe names include both a controller number and a namespace number. /dev/nvme0n1 means NVMe controller 0, namespace 1. /dev/nvme0n1p1 means partition 1 inside that namespace. The important point is that n1 is not a partition; it is the block device exported by the NVMe controller. The p1, p2, and later suffixes are the partitions created inside that namespace.
NVMe Path Syntax Key
Use this quick decoder before running destructive CLI partitioning commands such as
parted, fdisk, mkfs, cryptsetup,
pvcreate, or mdadm. The namespace component is part of the
disk-like block device name; the final pN suffix is the partition number.
/dev/nvme0n1p2
│ │ └─ p2 = Partition 2 (the logical slice)
│ └── n1 = Namespace 1 (the logical block device layout)
└────── nvme0 = Controller 0 (the physical M.2 / PCIe slot)
When targeting an NVMe partition, do not stop at /dev/nvme0n1 unless you intentionally mean the whole namespace. For example, /dev/nvme0n1p2 targets partition 2, while /dev/nvme0n1 targets the entire disk-like namespace and can destroy every partition inside it.
What an NVMe Namespace Means
An NVMe namespace is a logical storage area exposed by an NVMe controller to the operating system as a block device. In everyday terms, it behaves like a disk. Most consumer NVMe SSDs expose only one namespace, so you normally see one device such as /dev/nvme0n1. Some enterprise SSDs, NVMe-over-Fabrics systems, and storage appliances can expose several namespaces from the same physical device or storage subsystem. Linux then shows them as separate block devices, for example /dev/nvme0n1, /dev/nvme0n2, and /dev/nvme0n3.
| Layer | Example | Meaning |
|---|---|---|
| Controller | nvme0 | The NVMe controller instance detected by Linux. One physical NVMe SSD normally has one controller, but advanced NVMe subsystems may expose more complex controller relationships. |
| Namespace | nvme0n1 | A logical block device exported by that controller. Treat it like a disk from Linux's point of view. |
| Partition | nvme0n1p1 | A normal partition created inside the namespace, such as an ESP, /boot, root filesystem, LVM PV, or swap partition. |
Namespaces vs Partitions — They Are Different Layers
Namespaces are not simply "NVMe partitions." A partition is created by the operating system inside a block device using a partition table such as GPT or MBR. A namespace is created and presented by the NVMe device, controller, or storage subsystem before the OS partitioning layer. After Linux sees a namespace as a block device, you can still put a GPT partition table on it and create ordinary partitions inside it.
NVMe was designed not only for simple laptop SSDs but also for enterprise storage, virtualization, and multi-controller storage systems. Namespaces let one NVMe subsystem expose multiple independent logical block devices. Those namespaces can be allocated, attached, detached, resized, formatted, or assigned to hosts/controllers in ways that are useful for storage isolation, multi-tenant environments, appliances, and NVMe-over-Fabrics deployments. Normal Debian partitioning still happens inside the namespace after Linux sees it as a disk.
For ordinary desktops, laptops, and small servers, expect one namespace per NVMe drive and partition it normally: for example, /dev/nvme0n1p1 for the ESP, /dev/nvme0n1p2 for /boot, and /dev/nvme0n1p3 for root, LVM, or LUKS. For enterprise hardware, do not assume one physical NVMe device equals one Linux disk. Always inspect the actual topology with lsblk, nvme list if nvme-cli is installed, and persistent identifiers under /dev/disk/by-id/.
# Inspect NVMe disks, namespaces, and partitions from Linux
lsblk -o NAME,MODEL,SERIAL,WWN,SIZE,TYPE,FSTYPE,MOUNTPOINTS
ls -l /dev/disk/by-id/ | grep nvme
# Optional, if nvme-cli is installed
nvme list
nvme id-ns /dev/nvme0n1
Do not use raw names such as /dev/nvme0n1p3 in long-term configuration unless you have a specific reason. Controller discovery order can change after firmware updates, PCIe slot changes, BIOS/UEFI setting changes, virtualization changes, or storage appliance reconfiguration. Prefer UUID= for filesystems and swap in /etc/fstab, PARTUUID= for partition-level references, and stable /dev/disk/by-id/ paths when a device-level reference is needed.
Software RAID with mdadm
Debian Installer can create Linux software RAID arrays through partman-md.
Under the hood this uses mdadm, the standard Linux tool for managing
md devices. An mdadm array combines multiple block devices — normally
partitions on separate disks — and presents them to Linux as a new block device such as
/dev/md0, /dev/md1, or /dev/md/root. You then place a
filesystem, LVM Physical Volume, or LUKS container on top of that md device.
RAID improves availability: the system may continue running when a disk fails. It does not protect against accidental deletion, filesystem corruption, bad application writes, ransomware, theft, fire, controller bugs, administrator error, or site loss. Production RAID must be paired with tested backups, monitoring, SMART health checks, and documented recovery procedures.
Where RAID Fits in the Storage Stack
Software RAID works below the filesystem layer. The usual Debian mental model is:
physical disks contain RAID member partitions; mdadm assembles those members into
/dev/md* arrays; higher layers such as LUKS, LVM, and filesystems sit above
the array. This is why you normally format or mount the md device, not the individual
member partitions.
| Layer | Example | Purpose |
|---|---|---|
| Physical disks | /dev/sda, /dev/sdb | The actual drives. Use matching size and performance where possible. |
| RAID member partitions | /dev/sda2, /dev/sdb2 | Partitions marked for Linux RAID; each member contributes storage to the array. |
| mdadm array | /dev/md0 | The redundant or striped block device assembled from the members. |
| Upper layer | ext4, xfs, LVM, LUKS | The layer the system actually mounts, encrypts, or allocates from. |
For servers, a common clean layout is disk partitions → mdadm RAID → LVM → filesystems. For encrypted servers, use disk partitions → mdadm RAID → LUKS → LVM → filesystems when you want one encrypted container per array. Avoid inventing unusual layer orders unless you have tested boot, recovery, degraded operation, and replacement procedures.
ext4, xfs, swap; mounted as /, /var, /homevg0-root, vg0-var, vg0-home, vg0-swapvg0pvcreate /dev/mapper/crypt_raid/dev/mapper/crypt_raid; one passphrase unlocks the array-backed container/dev/md0 assembled from RAID member partitions/dev/nvme0n1p2, /dev/nvme1n1p2, /dev/sda2, /dev/sdb2For the common encrypted-RAID server layout, assemble the RAID array first and place one LUKS container on the mdadm device, then create LVM inside that unlocked container. This usually means typing one decryption passphrase at boot for that array, instead of managing a separate LUKS unlock prompt for every individual physical disk or RAID member.
RAID Levels Explained
| Level | Minimum Disks | Survives Failure? | Usable Capacity | Best Use | Main Risk |
|---|---|---|---|---|---|
| RAID0 | 2 | No | Sum of member sizes | Scratch space, disposable build/cache data, temporary high-throughput workloads. | Any member loss destroys the whole array. |
| RAID1 | 2 | 1 disk in a normal two-way mirror; more in larger mirrors | Size of smallest member | Boot devices, small servers, simple mirrored storage, reliable degraded boot. | Capacity efficiency is 50% with two disks. |
| RAID5 | 3 | 1 disk | (N-1) × smallest member | Read-heavy storage where capacity matters more than write performance. | Long rebuilds on large disks; array is exposed during rebuild. |
| RAID6 | 4 | 2 disks | (N-2) × smallest member | Larger capacity arrays where dual-parity protection is worth the write penalty. | Slower small random writes; rebuilds still stress all disks. |
| RAID10 | 2 in mdadm; 4+ for conventional production RAID10 | Depends on layout and which disks fail | Total member capacity divided by copy count; commonly about 50% | Databases, VM storage, busy application servers, mixed read/write workloads. | Failure tolerance depends on layout; conventional RAID10 usually needs more disks. |
RAID0 — Striping Without Redundancy
RAID0 splits data across disks in stripes. This can improve throughput, but there is no
redundancy at all. If one disk fails, the filesystem sees missing pieces of almost every
file. Use RAID0 only for data you can recreate: scratch directories, render caches,
temporary build trees, or benchmark environments. Do not use it for /,
/home, databases, or production data.
RAID1 — Mirroring
RAID1 writes the same data to each member. Reads may be served from either disk, and the system can usually continue after one disk fails. RAID1 is the safest simple choice for boot-critical filesystems because GRUB, initramfs, and mdadm degraded-boot behavior are easier to reason about than parity RAID. For two-disk servers, RAID1 is normally the practical default.
RAID5 and RAID6 — Distributed Parity
RAID5 and RAID6 spread parity information across the member disks. RAID5 can rebuild after one failed disk; RAID6 can rebuild after two failed disks. They are capacity-efficient for read-heavy storage, but writes are more expensive because parity must be updated. With very large disks, rebuilds can take many hours or days and read every surviving member heavily. During that window, RAID5 has no remaining redundancy. RAID6 is safer for large arrays, but it still requires backups and monitoring.
RAID10 — Mirrored Stripes
RAID10 combines mirroring and striping. In Linux mdadm, RAID10 is more flexible than old hardware-RAID terminology: it can use near, far, or offset copy layouts, and the minimum active device count is the number of data copies. The normal production mental model, however, is still four or more disks with two copies. In that conventional layout, RAID10 gives better random I/O behavior than RAID5/6 and rebuilds are usually less punishing because only the failed mirror relationship must be reconstructed. It is often the best mdadm level for VM storage, databases, and general-purpose production servers when disk count allows. With the common two-copy layout, usable capacity is roughly half of the raw member capacity.
RAID capacity is limited by the smallest member. If you combine a 2 TB disk and a 4 TB disk in a two-disk RAID1, the usable mirrored capacity is about 2 TB. The extra space on the larger disk is not useful to that array unless deliberately partitioned for another purpose.
Recommended Boot Layout with RAID
On UEFI systems, each bootable disk should normally have its own EFI System Partition.
ESPs are FAT filesystems, not mdadm arrays. Install the bootloader to every disk that
should be independently bootable, and keep the ESP contents synchronized after GRUB,
shim, or kernel-related updates. Put /boot on RAID1 if you want
kernel/initramfs redundancy. Avoid RAID5/6/10 for /boot unless you have
tested your exact GRUB support path, degraded boot path, and recovery procedure.
| Partition | Disk 1 | Disk 2 | RAID? | Notes |
|---|---|---|---|---|
| ESP | /dev/sda1 | /dev/sdb1 | No | Separate FAT32 ESP on each disk; mount one at /boot/efi and synchronize the other. |
| /boot members | /dev/sda2 | /dev/sdb2 | RAID1 | Creates /dev/md0, formatted ext4 and mounted as /boot. |
| system/data members | /dev/sda3 | /dev/sdb3 | RAID1 or RAID10/5/6 | Creates the array used for LUKS, LVM, root, var, home, VM storage, or data. |
Multiple ESPs are not automatically mirrored by mdadm. A manual copy is acceptable for a one-time repair, but production systems should use an idempotent synchronization script triggered after bootloader, shim, kernel, or initramfs updates. For GRUB-based systems this is commonly implemented with a local package-manager hook, dpkg trigger, or systemd service/path unit that runs rsync -a --delete /boot/efi/EFI/ /mnt/esp2/EFI/ after the secondary ESP is mounted. The automation must be tested by booting each disk from firmware, not merely by checking that files copied successfully.
Creating RAID in Debian Installer
In Manual partitioning, create matching partitions on each disk first. For RAID member partitions, choose Use as: physical volume for RAID. Then select Configure software RAID, create the md device, choose the RAID level, select active devices and any spare devices, and return to the partitioner. The new md device then appears as a normal disk-like target. Format it directly, or use it as a Physical Volume for LVM or as a LUKS encrypted volume.
- 1Create identical partition layouts on each disk: ESP, RAID member for
/boot, and RAID member for the main system/data array. - 2Mark member partitions for RAID in partman. Do not format individual member partitions with ext4/xfs.
- 3Create md devices with partman-md: for example RAID1 for
/bootand RAID1/10/6 for data. - 4Build upper layers on the md device: create LUKS, LVM, filesystems, or swap on
/dev/md*, not on the raw member partitions. - 5Install bootloader to all bootable disks and test booting from each disk before treating the server as production-ready.
For a simple two-disk Debian server: create two ESPs, create RAID1 for /boot, create RAID1 for the main system area, then put LVM on the main md device. This gives straightforward redundancy, simple degraded boot behavior, and flexible logical-volume sizing.
Command-Line mdadm Examples
The Debian Installer normally handles this interactively, but knowing the equivalent
commands makes recovery and verification much easier. Replace device names with the actual
member partitions from your system and verify with lsblk before running any
destructive command.
# Example: create a RAID1 array for /boot from two RAID member partitions
mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sda2 /dev/sdb2
mkfs.ext4 /dev/md0
# Example: create a RAID1 array for an LVM-backed system area
mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sda3 /dev/sdb3
pvcreate /dev/md1
vgcreate vg-debian /dev/md1
# Example: create a four-disk RAID10 data array
mdadm --create /dev/md10 --level=10 --raid-devices=4 /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sde1
mkfs.xfs /dev/md10
# Save array metadata for boot-time assembly - review before editing
cp -a /etc/mdadm/mdadm.conf /etc/mdadm/mdadm.conf.bak.$(date +%Y%m%d-%H%M%S)
mdadm --detail --scan > /root/mdadm.scan
grep '^ARRAY' /etc/mdadm/mdadm.conf
less /root/mdadm.scan
# Merge only the reviewed ARRAY lines that are missing or intentionally changed.
# Do not blindly append duplicate ARRAY records.
editor /etc/mdadm/mdadm.conf
update-initramfs -u -k all
# Monitor arrays after installation
cat /proc/mdstat
mdadm --detail /dev/md0
mdadm --detail /dev/md1
# Optional: install/sync a second ESP after mounting it at /mnt/esp2
mkdir -p /mnt/esp2
mount /dev/sdb1 /mnt/esp2
cp -a /boot/efi/EFI /mnt/esp2/
grub-install --target=x86_64-efi --efi-directory=/mnt/esp2 --bootloader-id=debian --recheck --no-nvram
# --no-nvram copies EFI files without creating a new firmware boot entry.
# For independent UEFI boot, create/test a firmware entry for the secondary ESP,
# or install/test a removable fallback path, then boot-test with each disk selected.
The initramfs must know how to assemble arrays needed for root, /boot, or LVM activation. After changing mdadm array definitions, review the generated ARRAY lines, remove stale or duplicate records, preserve intentional DEVICE, HOMEHOST, AUTO, policy, and monitoring settings, then rebuild the initramfs with update-initramfs -u -k all. Otherwise, the array may exist but not assemble early enough during boot, or it may assemble under an unexpected name.
Monitoring, Scrubbing, and Failure Handling
A RAID array that silently degrades is dangerous because the next disk failure may become data loss. Monitoring is not optional. Configure mdadm mail or alerting, check SMART data, and periodically scrub arrays so latent read errors are found while redundancy still exists.
| Task | Command / File | Purpose |
|---|---|---|
| Check live array state | cat /proc/mdstat | Shows active arrays, rebuild progress, failed members, and sync/check status. |
| Detailed array info | mdadm --detail /dev/md0 | Shows RAID level, UUID, member state, events, failed devices, and spare devices. |
| Persistent config | /etc/mdadm/mdadm.conf | Stores array identity for reliable assembly, especially during early boot. |
| Alert destination | MAILADDR admin@example.com | Set in mdadm.conf so mdadm can notify about failures if mail delivery is configured. |
| SMART health | smartctl -a /dev/sdX | Checks the physical disk, not just the md device. |
| Array scrub/check | echo check > /sys/block/md0/md/sync_action | Forces a consistency check; useful for finding latent disk/media errors. |
# Watch RAID status during rebuild or resync
watch -n 2 cat /proc/mdstat
# Start a manual consistency check on md0
echo check | sudo tee /sys/block/md0/md/sync_action
# Show mismatch count after a check
cat /sys/block/md0/md/mismatch_cnt
# Stop an active check or resync only when you intentionally need to
echo idle | sudo tee /sys/block/md0/md/sync_action
Replacing a Failed Disk
Disk replacement is a procedure, not just a command. Identify the failed physical disk, confirm serial numbers, remove the failed member from the array, replace the hardware, recreate the partition layout on the new disk, add the new member, and monitor the rebuild. On UEFI systems, recreate and synchronize the replacement disk's ESP as well.
# 1. Identify failed members and physical disks
cat /proc/mdstat
mdadm --detail /dev/md0
lsblk -o NAME,SIZE,MODEL,SERIAL,TYPE,FSTYPE,MOUNTPOINTS
# 2. Mark/remove a failed member if mdadm has not already done so
mdadm /dev/md0 --fail /dev/sdb2
mdadm /dev/md0 --remove /dev/sdb2
# 3. After replacing the disk, copy the partition layout carefully
# GPT example: copy partition table from good disk sda to new disk sdb, then randomize GUIDs
sgdisk --replicate=/dev/sdb /dev/sda
sgdisk --randomize-guids /dev/sdb
# 4. Add the replacement partition back to the array and monitor rebuild
mdadm /dev/md0 --add /dev/sdb2
watch -n 2 cat /proc/mdstat
Never copy partition tables or run destructive commands until you have positively identified the replacement disk by model, serial number, slot, and size. Accidentally partitioning the surviving good disk is a common way to turn a degraded array into an outage.
Practical RAID Planning Rules
- 1Use RAID1 for boot-critical filesystems. It is simple, robust, and easiest to recover when one disk is missing.
- 2Use RAID10 for busy VM/database storage when disk count allows. It usually gives better rebuild behavior and random I/O performance than RAID5/6.
- 3Be cautious with RAID5 on large disks. A single failure leaves no redundancy during rebuild, and rebuilds stress every surviving member.
- 4Prefer RAID6 over RAID5 for large capacity arrays when you need parity RAID. Dual parity is usually worth the write penalty for larger disks.
- 5Keep hot spares only when they match the failure model. A spare can reduce time spent degraded, but it is not a backup and does not replace monitoring.
- 6Test degraded boot. A RAID design is incomplete until you have confirmed the machine can boot with each boot disk absent or disabled.
Swap: Sizing & Strategy
Swap is secondary storage used by the Linux kernel under memory pressure and for suspend-to-disk hibernation. It is not a replacement for adequate RAM: sustained swapping to a slow disk can make a system effectively unusable. The right swap size depends on RAM size, workload, hibernation requirements, storage speed, whether zswap or zram is used, and how much emergency headroom the system needs.
| Scenario | Planning Default | Rationale |
|---|---|---|
| RAM ≤ 2 GB | RAM × 2 | Small RAM; swap provides headroom for spikes and reduces abrupt OOM failures. |
| RAM 4–8 GB | RAM × 1 | Balanced general-purpose default; also convenient when hibernation may be needed. |
| RAM 16–32 GB | 4–8 GB without hibernation | Large RAM rarely needs large emergency swap; hibernation still requires a much larger swap target. |
| RAM > 32 GB server | 4–16 GB, workload-dependent | Small swap can absorb transient pressure; sustained swap thrashing usually means the workload needs more RAM or tuning. |
| Hibernate required | Swap sized for the suspend image; swap ≥ RAM is safest | The image normally depends on memory that must actually be preserved, but swap at least equal to RAM remains the conservative planning rule. |
| SSD-only system | zswap + small backing swap | zswap compresses swap pages in RAM before they reach the SSD when possible, reducing swap I/O and write pressure. |
| Non-hibernating zram system | zram, optionally with small disk swap | Useful for low-memory systems, desktops, small VMs, and flash-storage systems, but not a hibernation target. |
Hibernation requires enough swap to store the suspend image and a correctly configured resume target in the initramfs/boot configuration. The image is based on memory that must actually be preserved, not necessarily the full physical RAM size, but swap ≥ RAM remains the safest planning rule. A swap partition is simpler for hibernation than a swap file, especially on encrypted or btrfs systems.
RAM-based swap tables are planning defaults, not universal laws. Database servers, virtualization hosts, desktops, laptops, containers, and embedded systems can need different swap behavior. Use monitoring data, workload behavior, hibernation requirements, and storage performance to finalize the size.
zswap — Compressed Swap Cache
zswap is a Linux kernel feature that acts as a compressed cache for swap pages in RAM. When the kernel is about to swap out a page, zswap tries to compress it and store it in a dynamically allocated RAM-based pool. If zswap cannot store the page, or if compressed pages are later evicted from the pool, the data is written to the backing swap device. This can reduce swap I/O and may reduce SSD write pressure, at the cost of CPU time and RAM used for the compressed pool.
# Enable zswap (add to GRUB_CMDLINE_LINUX in /etc/default/grub)
GRUB_CMDLINE_LINUX="zswap.enabled=1 zswap.compressor=lz4 zswap.max_pool_percent=20"
# Then update grub:
update-grub
# Check zswap parameters and stats at runtime
grep '' /sys/module/zswap/parameters/*
grep '' /sys/kernel/debug/zswap/*
The GRUB kernel-command-line method is still valid and is usually the clearest persistent configuration on Debian. At runtime, zswap is controlled through /sys/module/zswap/parameters/. On systems where zswap is loaded as a module rather than built into the kernel, an /etc/modprobe.d/zswap.conf file can set module parameters. This is not a sysctl interface.
zswap is not a standalone swap device. It is a compressed cache in front of an existing swap device or swap file. If there is no active backing swap, zswap has nothing useful to cache.
zram — RAM-Compressed Swap Device
zram creates compressed RAM-backed block devices, commonly used as swap devices. It can improve behavior on low-memory systems and reduce writes to slow or flash-based storage. For non-hibernating desktops, laptops, small VMs, and light servers, zram may reduce or remove the need for disk-backed swap, but this is workload-dependent. It does not provide suspend-to-disk hibernation storage, and it should not be treated as the same kind of emergency capacity as real disk swap.
apt install zram-tools
# Edit /etc/default/zramswap to set ALGO=lz4 and PERCENT=50
systemctl restart zramswap
swapon --show # should show /dev/zram0
Tuning swappiness
The vm.swappiness kernel parameter controls how strongly the kernel balances
reclaiming anonymous memory against reclaiming file-backed page cache. It accepts values
from 0 to 200, and the default is usually 60. Lower
values are common for latency-sensitive servers or database systems where disk swap is
expensive. Higher values can make sense with zram, zswap, or very fast swap devices, but
tune this from observed workload behavior rather than copying a single universal value.
# Temporary (lost on reboot)
sysctl vm.swappiness=10
# Permanent on Debian 13: create /etc/sysctl.d/99-local-swap.conf
vm.swappiness = 10 # lower tendency to reclaim anonymous memory into swap
vm.vfs_cache_pressure = 50 # reclaim inode/dentry cache less aggressively
sysctl --system
vm.vfs_cache_pressure is related to memory reclaim but is not a swap setting. It controls how aggressively the kernel reclaims dentry and inode caches. Lowering it can help metadata-heavy workloads keep filesystem caches longer, but very low values can waste memory and should be tested rather than applied blindly.
LVM — Logical Volume Manager
LVM is a layer of abstraction between physical storage (disks, partitions, RAID arrays, or encrypted block devices) and the filesystems that sit on top. It lets you create flexible virtual block devices called Logical Volumes, grow supported filesystems online, move data between Physical Volumes, create snapshots, and aggregate storage into a common pool. Not every LVM operation is online or risk-free: filesystem shrinking requires special care and usually requires the filesystem to be unmounted, and snapshot/thin-pool usage must be monitored.
Three-Layer Architecture
20G
80G
8G
30G
100G
38G
- PVPhysical Volume — any block device (partition, whole disk, RAID device, LUKS container) initialized with
pvcreate. LVM subdivides it into fixed-size Physical Extents (PEs) (default: 4 MiB each). - VGVolume Group — one or more PVs pooled together into a single storage reservoir. Think of it as a disk you invent. Created with
vgcreate. All free PEs across all member PVs are available to allocate. - LVLogical Volume — a slice of a VG, allocated in Logical Extents (same size as PEs). You create a filesystem on an LV and mount it. LVs do not need to be contiguous and can span multiple PVs transparently.
Key LVM Features
Online Resize
You can grow a Logical Volume (and its filesystem) while it is mounted and in use — no downtime required. Shrinking requires unmounting first (and is riskier; always backup first). ext4 supports both grow and shrink; xfs only supports growing.
Snapshots
LVM creates instant snapshots using Copy-on-Write (CoW). A snapshot holds only the changed blocks since the snapshot was taken, making them space-efficient for backup workflows. Snapshots are not a substitute for backups — they live on the same physical disk and will be lost if the disk fails.
Thin Provisioning
Thin pools allow you to create LVs whose total allocated size exceeds the actual physical storage. A thin LV that reports 100 GB to the OS may only consume 20 GB of real space until data is actually written. Useful for VMs and containers where actual usage is much less than nominal size. Requires monitoring to prevent the pool from filling, which causes writes to fail.
LVM thin provisioning depends on the kernel's device-mapper thin-pool target, normally exposed by the dm_thin_pool module, and the user-space recovery/check tooling in thin-provisioning-tools. Install it on systems that use thin pools so thin_check, thin_repair, thin_dump, and thin_restore are available during maintenance and recovery.
Do not run thin_repair directly against live, mounted, or active thin-pool metadata. Repair work must be done against inactive metadata or a metadata copy, normally through the LVM-supported lvconvert --repair workflow or a documented recovery procedure. Running repair tools on metadata that the kernel is still updating can permanently corrupt the pool and all thin LVs that depend on it.
Striping & Mirroring
LVM can stripe data across multiple PVs for throughput, and it also supports mirrored or
RAID-style logical volumes. For production redundancy, choose the RAID layer deliberately.
mdadm is common for Linux software RAID below LVM, while LVM RAID/mirror
layouts are also valid when you want redundancy managed inside LVM itself. Hardware RAID is
a separate design choice and should be evaluated based on controller reliability,
monitoring, cache protection, replacement workflow, and recovery requirements.
Building an LVM Layout from Scratch
This walkthrough shows how to build a simple LVM-backed Debian layout using command-line
tools. It is conceptually the same storage model created by Debian Installer when you choose
guided LVM, but the installer uses its own partman-driven workflow and does not
necessarily run these exact commands in this exact form.
Run these commands only from a root shell, a Debian Installer shell, rescue media, or with sudo. pvcreate, mkfs, and mkswap overwrite storage metadata and can destroy existing data immediately. Verify the target devices with lsblk -f, blkid, or parted -l before continuing.
This example builds the LVM-backed operating-system volumes only: /, /home, /var, and swap. On UEFI systems, the EFI System Partition must exist outside LVM because firmware reads it directly. A separate non-LVM /boot partition is optional on many plain LVM systems, but may be required or operationally simpler for some encryption, RAID, recovery, or bootloader designs.
Step 1: Create the Physical Volume
# Assume /dev/sda3 is a partition you've already created with fdisk/gdisk/parted
# GPT type code 8e00 in gdisk means Linux LVM
# On MBR/msdos partition tables, the equivalent historical type is 0x8e
pvcreate /dev/sda3
# → Physical volume "/dev/sda3" successfully created
pvdisplay # show detailed PV info
pvs # summary of all PVs
LVM can use a partition, a whole disk, a software RAID device, or a LUKS mapping as a Physical Volume. For installation documentation and mixed-use disks, a dedicated partition such as /dev/sda3 or /dev/sdb1 is clearer and safer. Use a whole disk such as /dev/sdb only when the entire device is intentionally dedicated to LVM and has no other partitioning role.
Step 2: Create the Volume Group
vgcreate vg-debian /dev/sda3
# To add a second dedicated LVM partition to the same VG:
pvcreate /dev/sdb1
vgextend vg-debian /dev/sdb1
vgdisplay vg-debian # shows total and free PE count
vgs # one-line summary
Step 3: Create Logical Volumes
# Create fixed-size LVs
lvcreate -L 20G -n root vg-debian
lvcreate -L 8G -n swap vg-debian
lvcreate -L 30G -n var vg-debian
lvcreate -l 100%FREE -n home vg-debian # use all remaining free extents
lvs # list all LVs
lvdisplay # detailed LV information
# LV device paths are available in both forms:
# /dev/vg-debian/root
# /dev/mapper/vg--debian-root
# In /dev/mapper names, hyphens from VG/LV names are escaped as doubled hyphens.
-L creates an LV with a human size such as 20G. -l allocates by logical extents, which is why -l 100%FREE means “consume all currently free extents in this VG.” Do not use 100%FREE casually on production systems if you want unallocated VG space for future growth, snapshots, or emergency expansion.
Step 4: Create Filesystems and Swap
mkfs.ext4 -L root /dev/vg-debian/root
mkfs.ext4 -L home /dev/vg-debian/home
mkfs.ext4 -L var /dev/vg-debian/var
mkswap -L swap /dev/vg-debian/swap
# Confirm filesystem and swap UUIDs
blkid /dev/vg-debian/root
blkid /dev/vg-debian/home
blkid /dev/vg-debian/var
blkid /dev/vg-debian/swap
Step 5: Mount the Layout for Installation or Testing
# Mount the new root filesystem under /mnt
mount /dev/vg-debian/root /mnt
# Create and mount separate mount points
mkdir -p /mnt/home /mnt/var
mount /dev/vg-debian/home /mnt/home
mount /dev/vg-debian/var /mnt/var
# Enable swap immediately for the current booted environment
swapon /dev/vg-debian/swap
# Confirm the active layout
findmnt /mnt
findmnt /mnt/home
findmnt /mnt/var
swapon --show
Step 6: Add Persistent /etc/fstab Entries
Prefer UUID= entries in /etc/fstab for normal filesystems and swap.
LVM device names such as /dev/mapper/vg--debian-root are valid, but UUIDs are
usually clearer for long-term administration because they refer to the filesystem or swap
signature rather than only the current device-mapper path.
# Example /etc/fstab lines after replacing the placeholders with real blkid values
UUID=<root-uuid> / ext4 defaults 0 1
UUID=<home-uuid> /home ext4 defaults 0 2
UUID=<var-uuid> /var ext4 defaults 0 2
UUID=<swap-uuid> none swap sw 0 0
For a Debian system whose root filesystem lives on LVM, the installed system must include LVM userspace and initramfs support so early boot can activate the VG before mounting /. Debian Installer handles this automatically for guided/manual LVM installs. In manual rescue or chroot-based builds, ensure lvm2 is installed and rebuild the initramfs after storage changes when needed.
LVM Day-2 Operations
LVM day-2 work normally means growing volumes, occasionally shrinking carefully, taking short-lived snapshots, moving data away from a disk, or renaming volume groups after cloning. The safe rule is: resize the storage layer and the filesystem layer in the correct order, verify free space first, and treat shrink, rollback, and disk-replacement operations as change-controlled maintenance.
Inspecting LVM State Before Changes
# Inventory the LVM stack before making changes
pvs
vgs
lvs -a -o lv_name,vg_name,lv_size,segtype,origin,data_percent,metadata_percent,devices
# Show the mounted filesystem and type for the target path
findmnt -no SOURCE,FSTYPE,SIZE,USED,AVAIL,TARGET /home
Extending a Logical Volume Online
# Grow the LV by 10 GiB
lvextend -L +10G /dev/vg-debian/home
# Grow the filesystem to fill the new LV space (ext4, online grow)
resize2fs /dev/vg-debian/home
# For XFS: grow the mounted filesystem
xfs_growfs /home # mount point is the normal, clear form
# One-liner: extend LV and resize a supported filesystem in one command
lvextend -L +10G --resizefs /dev/vg-debian/home
# Short form: lvextend -r -L +10G /dev/vg-debian/home
When growing a filesystem on LVM, first grow the logical volume, then grow the filesystem. lvextend --resizefs combines both steps for filesystems supported by LVM's resize helper. ext4 can normally be grown while mounted. XFS must be mounted to grow and is grown with xfs_growfs.
Shrinking an ext4 Logical Volume
# EXT4 EXAMPLE ONLY. Do not use this workflow for XFS.
# Always take a verified backup first.
umount /home
e2fsck -f /dev/vg-debian/home
# Conservative manual method: shrink filesystem smaller than final LV size
resize2fs /dev/vg-debian/home 49G
lvreduce -L 50G /dev/vg-debian/home
resize2fs /dev/vg-debian/home # grow ext4 back to fill the 50G LV
e2fsck -f /dev/vg-debian/home
mount /home
# Alternative: instead of the manual resize2fs/lvreduce sequence above,
# let LVM resize the filesystem and LV together after unmount + fsck.
lvreduce --resizefs -L 50G /dev/vg-debian/home
Shrinking is the dangerous direction. lvreduce removes logical extents; data is lost if the filesystem still uses the removed area. For ext4, shrink the filesystem first, then shrink the LV, or use lvreduce --resizefs after a backup and filesystem check. XFS cannot be shrunk in place; for a smaller XFS filesystem, back up, recreate at the smaller size, and restore.
Taking an LVM Snapshot
# Create a classic copy-on-write snapshot of the root LV
# The 5G size is snapshot COW space, not the size of the origin LV.
lvcreate -L 5G -s -n root-snap /dev/vg-debian/root
# Mount snapshot read-only to browse or back up
mkdir -p /mnt/snap
mount -o ro /dev/vg-debian/root-snap /mnt/snap
# For an XFS snapshot of a currently mounted origin, use: mount -o ro,nouuid ...
# Monitor snapshot space while it exists
lvs -a -o lv_name,origin,lv_size,data_percent,metadata_percent,segtype
# Remove snapshot when done
umount /mnt/snap
lvremove /dev/vg-debian/root-snap
# Rollback (revert origin to snapshot state) - DESTRUCTIVE
# For a non-root LV: unmount the origin and snapshot first, then merge.
lvconvert --merge /dev/vg-debian/data-snap
# For the root LV: merge is normally queued and completed on next activation/reboot.
lvconvert --merge /dev/vg-debian/root-snap
reboot
A classic LVM snapshot is a temporary same-storage restore point. It depends on the original LV and the same VG. If the origin disk fails, the snapshot fails with it. If the snapshot's copy-on-write space fills while the origin changes, the snapshot can become unusable. Keep snapshots short-lived, monitor their usage with lvs, and quiesce or stop databases before relying on a snapshot for consistent application-level backup.
An active root LV cannot simply be unmounted from the running system. When lvconvert --merge targets a snapshot whose origin is active, LVM defers the merge until the origin is next activated, which for the root filesystem normally means the next boot/initramfs activation. Confirm that the initramfs contains the required LVM tooling before relying on this rollback path.
Moving a PV out of a VG (Disk Replacement)
# Prepare the replacement disk or partition, then add it to the VG
# Use /dev/sdc1 if you partition disks; whole-disk PVs such as /dev/sdc are also possible.
pvcreate /dev/sdc1
vgextend vg-debian /dev/sdc1
# Confirm the VG has enough room, then move extents off the old PV
pvs -o pv_name,vg_name,pv_size,pv_free,pv_used
pvmove /dev/sda3 # live migration; can be slow and I/O heavy
# Remove old PV from VG and wipe the LVM label from it
vgreduce vg-debian /dev/sda3
pvremove /dev/sda3
pvmove is an online LVM data-migration tool, not a substitute for backups or RAID. If the old disk is already failing, complete backups and redundancy matter more than a clean live move. On LUKS-over-disk layouts, the PV may be a decrypted mapper device rather than the raw disk partition.
Renaming VG/LV (e.g., after cloning a VM)
vgrename vg-debian vg-production
lvrename vg-production root root-prod
# Update references to the old /dev/mapper or /dev/VG/LV names, then rebuild boot files.
nano /etc/fstab
nano /etc/crypttab # only if encryption mappings or names changed
update-initramfs -u -k all
update-grub
# Verify before rebooting
findmnt --verify
lsblk -f
lvs
Renaming a VG or LV that contains /, /boot, /var, or swap can break the next boot if /etc/fstab, /etc/crypttab, the initramfs, and GRUB still reference the old names. For root-volume renames, prefer a maintenance window or rescue environment and verify the boot path before rebooting.
Debian Installer (d-i) Partitioning Screens Explained
This section explains the partitioning screens of the classic Debian Installer, commonly abbreviated d-i. It does not document every installer screen from boot menu to reboot. Earlier installer stages such as language, location, keyboard, network, hostname, user setup, mirror selection, proxy configuration, tasksel, GRUB installation, and final reboot are summarized in the netinstall flow section. The detailed screen-by-screen material here begins when d-i reaches Partition disks.
Which Installer These Screens Belong To
d-i means Debian Installer: Debian's classic installer framework. These screens are used by the normal netinst image, the installer on DVD-1, the text installer, and the graphical Debian Installer frontend. The graphical frontend looks different, but it drives the same underlying installer workflow. This is separate from the Calamares installer used by Debian Live desktop images.
| Install Path | Uses d-i partman? | What This Means |
|---|---|---|
| netinst ISO | Yes | Uses Debian Installer and its partman partitioning system. |
| DVD-1 installer ISO | Yes | Uses the same Debian Installer workflow, with packages available from the DVD and optionally the network. |
| Graphical install option | Yes | Different user interface, same d-i backend and same partitioning concepts. |
| Live GNOME/KDE/Xfce images | No | These normally use Calamares, a different installer with a simpler desktop-oriented partitioner. |
The d-i Partitioning Workflow
The partitioning component of Debian Installer is called partman. It is the tool that presents disks, free space, guided partitioning recipes, manual partitioning, LVM setup, software RAID setup, encrypted-volume setup, filesystem selection, mount-point assignment, and the final confirmation screen that writes changes to disk.
| Screen / Menu Item | Purpose | Risk Level |
|---|---|---|
| Partition disks | Main entry point for guided or manual disk layout. | High |
| Guided partitioning | Lets d-i create a standard layout automatically. | High, because it can erase a disk. |
| Manual | Lets you create, edit, format, and mount each partition yourself. | High, but most flexible. |
| Configure software RAID | Creates mdadm arrays from partitions marked for RAID use. | High |
| Configure encrypted volumes | Creates LUKS encrypted containers. | High |
| Configure the Logical Volume Manager | Creates LVM physical volumes, volume groups, and logical volumes. | High |
| Finish partitioning and write changes to disk | Final commit point. After this, partition tables and filesystems are written. | Critical |
Before the final write changes to disk confirmation, most non-LVM choices are still just installer state. After you confirm, d-i writes partition tables, formats filesystems, initializes swap, creates LVM/RAID/LUKS layers where selected, and can destroy existing data on the selected disks.
Guided LVM and encrypted LVM have an earlier destructive confirmation. While LVM is being set up, the installer must write at least some partition-table changes to the selected disk. After that LVM setup confirmation, those changes are no longer just a preview, even though there is still a later final confirmation for formatting filesystems and completing the partitioning plan.
Partitioning Mode Selection Screen
When d-i reaches the Partition disks step, it offers several partitioning modes. Understanding what each actually does helps you choose the correct path before any destructive write is committed.
| Mode | What It Does | Best For |
|---|---|---|
| Guided — use entire disk | Wipes the selected disk and creates the required boot partitions plus root and swap according to the selected guided scheme. No LVM layer is created. | VMs, quick testing, single-purpose servers |
| Guided — use entire disk and set up LVM | Wipes the selected disk, creates the required boot partitions, and places the main Linux filesystems inside an LVM volume group. On UEFI systems this includes an ESP; guided LVM also creates a separate /boot. |
Most server deployments where future resizing is useful |
| Guided — use entire disk and set up encrypted LVM | Creates the same broad structure as guided LVM, but places the LVM volume group inside a LUKS encrypted container. | Laptops, portable systems, and sensitive-data environments |
| Manual | Gives full control: create partitions, choose filesystems, set mount points, assign flags, create LVM, create RAID, create encryption, and decide exactly what is formatted. | Custom layouts, multi-boot, advanced storage configurations |
Guided LVM: What the Installer Screens Mean
When you choose Guided - use entire disk and set up LVM, Debian Installer does not immediately show a fixed partition table. It first asks a few guided questions, then shows the resulting partition/LVM layout in the partition overview screen.
- 1Select the target disk: choose the disk that will be erased and used for Debian.
- 2Select the partitioning scheme: choose whether Debian should keep all files under
/, create a separate/home, or create separate filesystems such as/home,/var, and/tmp. - 3Choose how much disk space to use for LVM: the installer normally offers the maximum available space. Using less than the maximum leaves unallocated free space that can be assigned later.
- 4Review the partition overview: this screen shows the real result: boot partitions outside LVM, the LVM physical volume, and the logical volumes inside the volume group.
- 5Write changes to disk: the final confirmation screen lists the partitions and logical volumes that will be created or formatted.
The installer screen that says All files in one partition, Separate /home partition, or Separate /home, /var, and /tmp partitions is choosing a guided recipe. With LVM, those choices usually control which logical volumes are created inside the LVM volume group. They are not always separate physical disk partitions.
Common Guided LVM Results by Boot Mode
| Boot Mode / Partition Table | Typical Disk-Level Layout | Plain-English Meaning |
|---|---|---|
| UEFI + GPT | /dev/sda1 ESP, /dev/sda2 /boot, /dev/sda3 LVM PV |
This is the normal modern UEFI layout. The EFI System Partition is mounted at
/boot/efi, /boot is a separate Linux filesystem, and the
remaining large partition is initialized as an LVM physical volume.
|
| BIOS + MBR | /dev/sda1 /boot, /dev/sda5 LVM PV |
There is no EFI System Partition. Because MBR logical partitions start at number
5, the LVM physical volume may appear as /dev/sda5, not
/dev/sda3.
|
| BIOS + GPT | Tiny BIOS Boot Partition, separate /boot, LVM PV |
GRUB needs a tiny BIOS Boot Partition on GPT disks when booting in legacy BIOS mode.
This partition has no filesystem and no mount point. A separate /boot
partition and an LVM physical volume are then created after it.
|
What the Guided Recipe Changes Inside LVM
| Installer Recipe | Typical Logical Volumes Inside the VG | Plain-English Meaning |
|---|---|---|
| All files in one partition | root, swap_1 |
Creates one main filesystem mounted as / plus swap. Directories such as
/home, /var, and /tmp remain normal directories
inside /.
|
Separate /home partition |
root, home, swap_1 |
Creates a separate logical volume for user home directories and mounts it at
/home.
|
Separate /home, /var, and /tmp partitions |
root, home, var, tmp, swap_1 |
Creates separate logical volumes for user data, variable data/logs, temporary files,
the root filesystem, and swap. In the installer overview, these appear as LVM logical
volumes such as LV home, LV root, LV var,
LV tmp, and LV swap_1.
|
Separate /var and /srv, swap < 1GB |
root, var, srv, small swap |
Server-oriented recipe that separates variable data and service data. The exact sizes depend on disk size and the installer recipe. |
| Small-disk (< 10GB) partitioning scheme | Compact root and swap layout | Designed for very small disks. Do not use it for normal modern servers or VMs unless disk space is genuinely constrained. |
Do not memorize /dev/sda1, /dev/sda2, and /dev/sda3
as fixed names. On NVMe disks, names look like /dev/nvme0n1p1,
/dev/nvme0n1p2, and /dev/nvme0n1p3. On BIOS/MBR installs,
the LVM physical volume may be a logical partition such as /dev/sda5.
Always trust the installer overview screen for the actual layout.
The installer's automatic LV sizes are conservative and recipe-dependent. It may allocate a root LV that is too small for workloads such as Docker, databases, build tools, large logs, or application data. After choosing Guided — use entire disk and set up LVM, review the proposed LVs before confirming. If the sizes are not suitable, go back and adjust them from Manual mode, or build the LVM layout manually from the start. LVs can often be extended later with lvextend, but sizing them sensibly during installation is cleaner.
Manual Partitioning in the Installer (partman)
The Debian installer's manual partitioning tool is called partman. It is text-based but fully capable. Here is the sequence for building an LVM layout from scratch in Manual mode.
sda), choose "Create new empty partition table", select GPT. This wipes any existing layout.vg-debian) → select the LVM PV you just created. Then create LVs: root, home, var, swap.Using fdisk, gdisk, and parted from the Command Line
If you are installing via debootstrap or need to partition from a rescue environment, choose the partitioning tool deliberately. All three can be valid, but they optimize for different workflows:
| Tool | Best Use | Strengths | Cautions |
|---|---|---|---|
fdisk | Interactive general-purpose partitioning | Available almost everywhere; modern util-linux fdisk handles GPT as well as MBR. | Less ideal for scripted installs; older tutorials may assume MBR-only behavior. |
gdisk | Interactive GPT-focused work and MBR-to-GPT conversion/recovery | Excellent for GPT type codes such as EF00, EF02, 8E00, GPT metadata repair, protective MBR handling, and careful conversion of legacy MBR layouts to GPT. | Not the normal tool for maintaining an MBR disk as MBR. Opening an MBR disk in gdisk is usually a conversion/recovery workflow, so quit without writing if you did not intend to create GPT metadata. |
parted | Scripted or rescue-environment partitioning | Works well with non-interactive commands, MiB/GiB alignment, and installer/debootstrap automation. | Syntax is less forgiving; always print and verify the resulting layout. |
# Using parted — creates GPT table with ESP + /boot + LVM partition
parted -s /dev/sda mklabel gpt
parted -s /dev/sda mkpart ESP fat32 1MiB 513MiB
parted -s /dev/sda set 1 esp on
parted -s /dev/sda mkpart boot ext4 513MiB 1537MiB
parted -s /dev/sda mkpart lvm ext4 1537MiB 100%
parted -s /dev/sda set 3 lvm on
# Check result
parted /dev/sda print
# Format ESP and /boot
mkfs.fat -F32 -n EFI /dev/sda1
mkfs.ext4 -L boot /dev/sda2
# Then proceed with pvcreate / vgcreate / lvcreate as shown in §14
In parted mkpart lvm ext4 ..., the ext4 token is only a partition-type hint used while creating the partition entry. It does not create an ext4 filesystem on the LVM partition. The real filesystem is created later on the logical volume with tools such as mkfs.ext4 or mkfs.xfs.
systemd-repart — Declarative GPT Partition Management
systemd-repart is available in Debian 13 and provides a declarative way to
create, grow, and label GPT partitions using repart.d/*.conf files. It currently
targets GPT partition tables and is most useful for image-based systems, appliances, cloud/VM
images, and repeatable deployments where a small image should grow or add partitions on first
boot. It is not a replacement for learning manual partitioning: it is
intentionally incremental and normally grows existing partitions or adds new ones rather than
shrinking, deleting, or moving data. Also keep the layer boundary clear: growing a partition is
not always the same as growing the filesystem inside it.
| Use Case | Good Fit? | Reason |
|---|---|---|
| Golden VM image that expands root on first boot | Yes | Configuration-driven and repeatable; pair partition growth with GrowFileSystem= or systemd-growfs when the filesystem itself must grow. |
| Installer-style one-off laptop partitioning | Usually no | Debian Installer partman is simpler and safer for interactive installs. |
| A/B root layouts or appliance images | Yes | Can define discoverable GPT partition types and labels. |
| Resizing/shuffling an existing complex server layout | No | It does not behave like a general-purpose partition editor. |
# Install the tool if it is not already present
apt install systemd-repart
# Dry-run against a block device or image before applying
systemd-repart --dry-run=yes --empty=allow /dev/sdX
# Configuration lives in repart.d definition directories
ls -d /etc/repart.d /run/repart.d /usr/local/lib/repart.d /usr/lib/repart.d 2>/dev/null
systemd-repart primarily changes the partition table: it can create new partitions and grow existing matching partitions. If a grown partition contains an existing filesystem, the filesystem may need a separate grow step. Use GrowFileSystem= in the partition definition, or pair the layout with systemd-growfs or another filesystem-specific grow mechanism where appropriate.
Use systemd-repart --dry-run=yes and test on throwaway disks or images first. Declarative partitioning is powerful precisely because it can mutate partition tables automatically during boot or provisioning.
Full Disk Encryption with LUKS
LUKS (Linux Unified Key Setup) is the standard Linux format for encrypted
block devices. It is not a filesystem and it is not a mount point. A LUKS container must first
be unlocked into a /dev/mapper/... device. Only after that can Linux see the
filesystem, swap area, LVM physical volume, or other storage layer inside it.
/etc/crypttab opens encrypted block devices. /etc/fstab mounts filesystems or activates swap. A crypttab line alone never mounts a filesystem, and an fstab line cannot work until the encrypted device and any LVM layer underneath it exist.
The Layer Order
Read every LUKS layout from the physical device upward. Each layer depends on the layer below it. When a device name is missing, troubleshoot from the bottom upward instead of re-running creation commands.
/home, /var, /srv/securedata/dev/vg-cryptdata/datavg-cryptdata/dev/mapper/cryptdata/dev/sdb1 or persistent /dev/disk/by-id/...| Layer | Created / Managed By | Example | Common Mistake |
|---|---|---|---|
| Raw disk or partition | Partitioning tool | /dev/sdb1 | Using /dev/sda or /dev/sdb blindly after device order changes. |
| LUKS container | cryptsetup luksFormat | LUKS UUID from cryptsetup luksUUID /dev/sdb1 | Putting the LUKS UUID in /etc/fstab instead of /etc/crypttab. |
| Unlocked mapper | cryptsetup open or systemd-cryptsetup | /dev/mapper/cryptdata | Expecting it to exist before the LUKS passphrase has been supplied. |
| LVM inside LUKS | pvcreate, vgcreate, lvcreate | /dev/vg-cryptdata/data | Looking for an LV before the LUKS mapper is open and LVM has been activated. |
| Filesystem | mkfs.ext4, mkfs.xfs, etc. | Filesystem UUID from blkid | Creating crypttab but forgetting the matching fstab mount entry. |
| Mount point | /etc/fstab or manual mount | /srv/securedata, /chome | Relying on the desktop file manager's dynamic /media/user/... path. |
Choose the Correct Implementation Path First
| Scenario | Recommended Path | Notes |
|---|---|---|
| New laptop or server where root, home, var, tmp, and swap should be encrypted | Use Debian Installer: Guided - use entire disk and set up encrypted LVM. | This is the normal full-disk-style encryption path. The installer creates the LUKS container, LVM volumes, filesystems, crypttab, fstab, initramfs configuration, and bootloader integration. |
| Extra encrypted data disk after Debian is already installed | Create a secondary LUKS volume manually, then add both /etc/crypttab and /etc/fstab. | This is the safest manual example for administrators. It is not the same as converting the installed root filesystem to encryption. |
| Existing LUKS disk temporarily opened for rescue or data copy | Use cryptsetup open, mount manually, then unmount and close. | Temporary access does not persist across reboot unless you configure crypttab and fstab. |
| Post-install conversion of an existing unencrypted root filesystem | Treat as an advanced migration project, not a beginner procedure. | Requires full backups, rescue media, reinstall/migration planning, initramfs and bootloader work, and rollback testing. |
Boot Compatibility: Plain /boot vs Encrypted /boot
The critical boot question is whether GRUB must unlock the encrypted device itself. In the
normal Debian encrypted-LVM layout, the EFI System Partition and /boot remain
unencrypted. GRUB reads the kernel and initramfs from plaintext /boot, then the
initramfs unlocks the encrypted root stack. This keeps LUKS2 with modern cryptsetup defaults
suitable for the encrypted root container.
| Layout | Boot Impact | Recommendation |
|---|---|---|
Plain ESP + plaintext /boot + encrypted root/LVM | GRUB does not need to unlock the root LUKS container. The initramfs handles the passphrase prompt and unlock. | Recommended for normal Debian installations. |
Encrypted /boot | GRUB must understand the LUKS metadata and key derivation before Linux starts. | Avoid unless you are deliberately designing and testing a custom boot stack. GRUB support is more restrictive than Linux cryptsetup support. |
| Detached header, TPM2-only unlock, remote key service, or custom PBKDF tuning | Boot and recovery behavior become site-specific. | Document the design, keep recovery passphrases, test rescue boot, and back up LUKS headers. |
GRUB must load the kernel and initramfs before Linux can unlock the root filesystem. The Debian Installer's normal encrypted-LVM workflow therefore leaves /boot unencrypted and encrypts the operating-system data below it. This is the practical default for laptops, desktops, VMs, and many servers.
LUKS1 vs LUKS2
| Feature | LUKS1 | LUKS2 |
|---|---|---|
| Current use | Legacy format, still useful for some GRUB-unlocked boot designs. | Modern default for ordinary Debian LUKS containers. |
| Key derivation | PBKDF2 only. | Supports PBKDF2, Argon2i, and Argon2id; current cryptsetup defaults commonly use Argon2-based passphrase keyslots. |
| Metadata | Older fixed-format metadata and smaller keyslot area. | JSON metadata, redundant metadata areas, tokens, and more flexible keyslot handling. |
| GRUB consideration | Most predictable when GRUB itself must unlock the encrypted volume. | Linux can unlock normal LUKS2 volumes, but GRUB has narrower support, especially around Argon2-based keyslots. |
cryptsetup luksFormat initializes a new encrypted container and destroys the previous contents of the selected block device. Use it only when creating a new encrypted volume on the correct target. For an existing encrypted system, use cryptsetup open and inspect the existing layout instead.
Path 1: New Install Using Debian Installer Encrypted LVM
For a real full-disk-style Debian installation, this is the recommended path. Let the installer create the encrypted storage stack instead of trying to retrofit root encryption after the OS is already installed.
/boot, and a LUKS container containing the LVM volume group./var, /tmp, /home, and swap may be cleaner. All of these logical volumes live inside the encrypted LUKS container when using encrypted LVM.lsblk -f, cat /etc/crypttab, cat /etc/fstab, pvs, vgs, and lvs. You should see the raw encrypted partition, an unlocked mapper, LVM inside that mapper, and mounted filesystems above the LVM logical volumes.# Post-install inspection on an encrypted-LVM system
lsblk -f
cat /etc/crypttab
cat /etc/fstab
pvs
vgs
lvs
Path 2: Secondary Encrypted Data Volume, Filesystem Directly Inside LUKS
This is for an extra data volume such as /srv/securedata or /chome,
not for the root filesystem. The sequence is: identify the target, create LUKS, open LUKS,
create the filesystem, mount it, then configure crypttab and fstab.
Step 0: Install the required packages
apt update
apt install cryptsetup cryptsetup-bin systemd-cryptsetup
On Debian 13, do not assume the systemd cryptsetup unit is present just because cryptsetup is installed. If systemctl start systemd-cryptsetup@name.service says the unit is not found, install systemd-cryptsetup and run systemctl daemon-reload.
Step 1: Identify the correct target device
# Inspect carefully before destructive commands
lsblk -o NAME,SIZE,TYPE,FSTYPE,FSVER,LABEL,UUID,MOUNTPOINTS
blkid
ls -l /dev/disk/by-id/
Use a partition such as /dev/sdb1 in documentation and mixed-use disks. A whole
disk such as /dev/sdb is valid only when the entire device is intentionally
dedicated to this encrypted volume. Device letters can change across boots, so use UUIDs or
/dev/disk/by-id/ names in persistent configuration.
Step 2: Create and open the LUKS container
# DANGER: destroys existing contents of /dev/sdb1
cryptsetup luksFormat /dev/sdb1
# Open it as /dev/mapper/cryptdata
cryptsetup open /dev/sdb1 cryptdata
# Confirm the mapper exists
lsblk -f
cryptsetup status cryptdata
Step 3: Create the filesystem inside the unlocked mapper
mkfs.ext4 -L securedata /dev/mapper/cryptdata
mkdir -p /srv/securedata
mount /dev/mapper/cryptdata /srv/securedata
df -h /srv/securedata
Step 4: Get the two different UUIDs
# LUKS container UUID: use this in /etc/crypttab
cryptsetup luksUUID /dev/sdb1
# Filesystem UUID: use this in /etc/fstab
blkid /dev/mapper/cryptdata
lsblk -f
Step 5: Configure automatic unlock and mount
# /etc/crypttab: name encrypted-source key-file options
cryptdata UUID=<LUKS-container-UUID> none luks,nofail
# /etc/fstab: mount the filesystem that appears after unlock
UUID=<filesystem-UUID-inside-cryptdata> /srv/securedata ext4 defaults,nofail,x-systemd.device-timeout=30s 0 2
Use nofail for optional data volumes so a missing disk or failed passphrase does
not trap the machine in emergency mode. Omit nofail only when the volume is a
required dependency and boot should fail loudly if it is unavailable.
Step 6: Test before rebooting
systemctl daemon-reload
# If the mapper is already open, this may say it is already active; that is fine.
systemctl start systemd-cryptsetup@cryptdata.service
mount -av
findmnt /srv/securedata
df -h /srv/securedata
If systemctl start systemd-cryptsetup@cryptdata.service reports Unit ... not found, the crypttab line may be correct but the systemd cryptsetup integration is missing. Install systemd-cryptsetup, reload systemd, and test again.
Path 3: Secondary Encrypted Data Volume with LVM Inside LUKS
Use this when the encrypted data volume should contain one or more LVM logical volumes. The sequence changes only after the LUKS mapper is open: create the LVM PV/VG/LV inside the mapper, then put the filesystem on the LV.
apt install cryptsetup cryptsetup-bin systemd-cryptsetup lvm2
# DANGER: destroys existing contents of /dev/sdb1
cryptsetup luksFormat /dev/sdb1
cryptsetup open /dev/sdb1 cryptlvm
# Build LVM inside the unlocked LUKS mapper
pvcreate /dev/mapper/cryptlvm
vgcreate vg-cryptdata /dev/mapper/cryptlvm
lvcreate -l 100%FREE -n data vg-cryptdata
# Create filesystem on the LV, not on the raw LUKS partition
mkfs.ext4 -L securedata /dev/vg-cryptdata/data
mkdir -p /srv/securedata
mount /dev/vg-cryptdata/data /srv/securedata
Use lowercase -l 100%FREE when allocating by extents. Uppercase -L is for fixed sizes such as 50G. If the command fails, do not guess by re-running destructive setup commands; inspect with pvs, vgs, and lvs.
Persistent configuration for LVM inside LUKS
# LUKS UUID for /etc/crypttab
cryptsetup luksUUID /dev/sdb1
# Filesystem UUID for /etc/fstab
blkid /dev/vg-cryptdata/data
# /etc/crypttab
cryptlvm UUID=<LUKS-container-UUID> none luks,nofail
# /etc/fstab
UUID=<filesystem-UUID-on-LV> /srv/securedata ext4 defaults,nofail,x-systemd.device-timeout=30s 0 2
The mapper path for an LVM LV escapes hyphens. For a volume group named
vg-cryptdata and an LV named data, the readable path is
/dev/vg-cryptdata/data and the equivalent mapper path is
/dev/mapper/vg--cryptdata-data. Both refer to the same LV. The path will not exist
until the LUKS container is open and the VG is active.
# Test the stack without rebooting
systemctl daemon-reload
systemctl start systemd-cryptsetup@cryptlvm.service
vgchange -ay vg-cryptdata
mount -av
lsblk -f
findmnt /srv/securedata
Temporary Manual Access to an Existing LUKS Volume
Use this when the volume already exists and you only need access for rescue, inspection, or a one-time copy. This does not configure automatic boot behavior.
# Inspect first
lsblk -f
blkid
# Open existing LUKS filesystem
cryptsetup open /dev/sdb1 cryptdata
mkdir -p /mnt/securedata
mount /dev/mapper/cryptdata /mnt/securedata
# Or, if it contains LVM
cryptsetup open /dev/sdb1 cryptlvm
vgscan
vgchange -ay
lvs
mount /dev/vg-name/lv-name /mnt/securedata
# Clean shutdown of temporary access
umount /mnt/securedata
vgchange -an vg-name # only if you activated LVM manually
cryptsetup close cryptdata # or cryptlvm
Graphical file managers usually mount removable or manually unlocked volumes under dynamic user-session paths such as /media/<user>/<label-or-uuid>. That is normal for interactive desktop use. For a stable server-style path such as /srv/securedata or /chome, create the mount point yourself and define it in /etc/fstab.
Root on LVM Inside LUKS: Configuration and Rescue Model
When the encrypted volume contains the root filesystem, the unlock must happen before the real
root filesystem is mounted. That means /etc/crypttab must be represented in the
initramfs, LVM must be available in early boot if root is on LVM, and the bootloader must point
to a valid kernel and initramfs on /boot.
# Packages normally needed for manual encrypted-root repair/design
apt install cryptsetup cryptsetup-bin cryptsetup-initramfs lvm2 initramfs-tools
# /etc/crypttab: root container opened in early boot
cryptlvm UUID=<LUKS-container-UUID> none luks
# /etc/fstab: filesystems inside the unlocked LVM stack
UUID=<root-filesystem-UUID> / ext4 errors=remount-ro 0 1
UUID=<home-filesystem-UUID> /home ext4 defaults 0 2
UUID=<swap-UUID> none swap sw 0 0
# After changing root/early-boot crypto configuration
update-initramfs -u -k all
update-grub
Rebuild the initramfs after changing encrypted root, encrypted /usr, resume swap, or any mapping that must exist before the real root filesystem is mounted. For a normal secondary data volume unlocked after root is mounted, rebuilding initramfs is normally not required; run systemctl daemon-reload and test mount -av instead.
LUKS Header Backup: Do This After Formatting
The LUKS header contains the metadata and encrypted keyslots needed to unlock the volume. If the header is destroyed, the encrypted payload is normally unrecoverable even if the data blocks are intact. Back it up after formatting and after major keyslot changes. Protect the backup like a secret: with a header backup and a valid passphrase, an attacker can attempt to unlock the data.
cryptsetup luksHeaderBackup /dev/sdb1 --header-backup-file luks-sdb1-header.img
# Restore only to the intended original LUKS device, and only when you are certain.
cryptsetup luksHeaderRestore /dev/sdb1 --header-backup-file luks-sdb1-header.img
Adding a Key File for a Secondary Volume
A key file can avoid an interactive passphrase prompt for an extra encrypted data volume. This
example assumes root is already mounted before the secondary volume is unlocked. Do not reuse
this pattern blindly for encrypted root: a key file stored under /root is not
available until after root has already been unlocked.
install -d -m 0700 /root/luks-keys
dd if=/dev/urandom of=/root/luks-keys/cryptdata.key bs=512 count=1
chmod 0400 /root/luks-keys/cryptdata.key
cryptsetup luksAddKey /dev/sdb1 /root/luks-keys/cryptdata.key
cryptsetup luksDump /dev/sdb1
# /etc/crypttab for the secondary volume
cryptdata UUID=<LUKS-container-UUID> /root/luks-keys/cryptdata.key luks,nofail
TPM2 Auto-Unlock
TPM2 means Trusted Platform Module 2.0. It can seal an unlock secret to measured boot state. Treat TPM2 unlock as an advanced convenience or hardening feature, not as a replacement for a recovery passphrase. Test after firmware, Secure Boot, shim, GRUB, kernel, and initramfs updates.
apt install systemd-cryptsetup cryptsetup-initramfs
systemd-cryptenroll --tpm2-device=auto /dev/sdb1
# Example crypttab option
cryptdata UUID=<LUKS-container-UUID> none luks,tpm2-device=auto,nofail
Discard / TRIM on Encrypted SSDs
Adding discard to the fourth field of /etc/crypttab allows TRIM to pass
through dm-crypt. This may help SSD maintenance, but it can reveal allocation patterns such as
which areas of the encrypted device are unused. Decide deliberately.
cryptdata UUID=<LUKS-container-UUID> none luks,nofail,discard
Changing a LUKS Passphrase Safely
# Add a new passphrase to a free keyslot
cryptsetup luksAddKey /dev/sdb1
# Test before removing anything
cryptsetup open --test-passphrase /dev/sdb1
cryptsetup luksDump /dev/sdb1
# Remove an old slot only after the new passphrase is confirmed
cryptsetup luksKillSlot /dev/sdb1 0
Prefer luksAddKey, test the new passphrase, and only then remove the old keyslot. Avoid deleting the only known-good unlock method.
Recovering from a Broken LUKS Boot or Mount Configuration
If boot fails after adding an encrypted volume, the usual causes are a wrong UUID, a missing
systemd-cryptsetup package, a mapper-name mismatch, an fstab line for
a mapper that never appears, or an optional volume configured as a hard boot requirement.
If the system boots but the encrypted volume is not open
cat /etc/crypttab
cat /etc/fstab
dpkg -l | grep -E 'cryptsetup|systemd'
apt-cache policy systemd-cryptsetup cryptsetup cryptsetup-bin cryptsetup-initramfs
systemctl daemon-reload
systemctl status systemd-cryptsetup@cryptdata.service --no-pager
# Manual open proves whether the LUKS header/passphrase is valid
cryptsetup open /dev/disk/by-uuid/<LUKS-container-UUID> cryptdata
lsblk -f
mount -av
If emergency mode is caused by an optional encrypted volume
mount -o remount,rw /
nano /etc/crypttab # fix or temporarily comment the optional volume
nano /etc/fstab # fix or temporarily comment the matching mount
systemctl daemon-reload
findmnt --verify --verbose
mount -av
reboot
If encrypted root will not unlock or mount
# Boot Debian installer/live/rescue media, then identify devices
lsblk -f
blkid
# Open the root LUKS container and activate LVM if used
cryptsetup open /dev/sda3 cryptlvm
vgchange -ay
# Mount the installed system; adjust names to your layout
mount /dev/vg-debian/root /mnt
mount /dev/sda2 /mnt/boot # if /boot is separate
mount /dev/sda1 /mnt/boot/efi # if UEFI ESP exists
# Chroot and repair
for i in /dev /dev/pts /proc /sys /run; do mount --bind $i /mnt$i; done
chroot /mnt /bin/bash
nano /etc/crypttab
nano /etc/fstab
apt install cryptsetup cryptsetup-bin cryptsetup-initramfs lvm2
update-initramfs -u -k all
update-grub
exit
umount -R /mnt
reboot
First Boot Checklist
The installer finishes, the system reboots. The first boot is not just a login test: it is the moment to confirm that the boot path, package sources, storage stack, network, time, and maintenance timers are correct before the machine becomes a workstation or server.
cat /etc/os-release
[ -d /sys/firmware/efi ] && echo UEFI || echo BIOS
bootctl status # useful on UEFI systems; may say systemd-boot is not installed
mokutil --sb-state # install mokutil first if the command is missing
mokutil --list-enrolled # shows enrolled Machine Owner Keys, if any
Confirm that the installed system is the intended Debian release and that it booted in the same firmware mode you planned during installation. mokutil is relevant only on Secure Boot-capable UEFI systems; on BIOS systems or UEFI systems without Secure Boot, it is not part of the normal boot validation path.
Do not run mokutil --import as a generic first-boot step. Use it only when you have a real public key file and you need the kernel to trust locally built or third-party modules under Secure Boot, such as NVIDIA, VirtualBox, ZFS, or vendor DKMS drivers. The private key signs the module; the public key is enrolled with MOK.
# Only when you need locally built DKMS modules under Secure Boot:
mokutil --import MOK.der # prompts for a one-time enrollment password
# reboot immediately; in MOK Manager choose Enroll MOK - View Key - Continue - Yes - password - Reboot
After running mokutil --import MOK.der, the key is only staged; it is not enrolled yet. Reboot and watch for shim's text-mode MOK Manager screen before Debian starts. Select Enroll MOK, use View Key to verify the expected key, continue, confirm with Yes, enter the one-time password, and reboot. After Debian starts again, confirm the result with mokutil --list-enrolled and verify affected modules with lsmod, modinfo <module-name>, dmesg, or journalctl -k.
grep -R '^deb ' /etc/apt/sources.list /etc/apt/sources.list.d/*.list 2>/dev/null
cat /etc/apt/sources.list.d/*.sources 2>/dev/null
Debian 13 systems may use Deb822-style .sources files under /etc/apt/sources.list.d/. Classic one-line .list files still work, but do not configure the same repository twice in both formats. For a normal Debian 13 installation, pin the codename trixie rather than the moving alias stable.
Preferred Deb822-style example
Types: deb
URIs: http://deb.debian.org/debian
Suites: trixie trixie-updates
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb
URIs: http://deb.debian.org/debian-security
Suites: trixie-security
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Classic one-line equivalent
deb [signed-by=/usr/share/keyrings/debian-archive-keyring.gpg] http://deb.debian.org/debian trixie main contrib non-free non-free-firmware
deb [signed-by=/usr/share/keyrings/debian-archive-keyring.gpg] http://deb.debian.org/debian trixie-updates main contrib non-free non-free-firmware
deb [signed-by=/usr/share/keyrings/debian-archive-keyring.gpg] http://deb.debian.org/debian-security trixie-security main contrib non-free non-free-firmware
main is the fully free Debian archive component. contrib, non-free, and non-free-firmware are needed only when your system requires packages from those components, most commonly firmware. If non-free firmware was installed during installation, make sure non-free-firmware remains enabled so firmware updates are available.
apt update
apt list --upgradable
apt full-upgrade
reboot # recommended if a kernel, systemd, libc, firmware, or driver package changed
Avoid adding -y to the first manual full-upgrade in documentation. The first upgrade is where you want to see removals, held packages, service restarts, and configuration-file prompts before accepting them.
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS,UUID
blkid
findmnt
findmnt --verify --verbose # checks fstab syntax/usability from libmount's point of view
df -hT
swapon --show
findmnt /tmp
cat /etc/fstab
Confirm that every intended mount point is present, that UUIDs match the installed system, that swap is active when configured, and that the root filesystem has enough free space. On Debian 13, a normal systemd-based installation stores /tmp on tmpfs by default unless overridden by /etc/fstab or by masking tmp.mount.
findmnt --verify checks /etc/fstab parsing and mount usability. It is not a full hardware audit and should not be treated as proof that every intended disk, UUID, LUKS mapping, LVM device, RAID member, or filesystem is healthy. Pair it with lsblk, blkid, df, and the storage-layer tools below.
# LUKS / encrypted volumes
dpkg -l cryptsetup systemd-cryptsetup
cat /etc/crypttab
lsblk -o NAME,TYPE,FSTYPE,MOUNTPOINTS,UUID
cryptsetup status <mapping-name>
# LVM
pvs
vgs
lvs -a -o +devices
# Software RAID
cat /proc/mdstat
mdadm --detail /dev/md0
mdadm --detail --scan
If the system uses encrypted filesystems, confirm that systemd-cryptsetup is installed and that /etc/crypttab uses the intended mapping names, UUIDs, and options. If you edit /etc/crypttab, storage drivers, LVM configuration, RAID configuration, or anything needed before root is mounted, rebuild the initramfs and reboot-test while you still have console or rescue access.
update-initramfs -u -k all
reboot
# UEFI firmware entries
efibootmgr -v
# GRUB systems
grep -E 'menuentry|submenu' /boot/grub/grub.cfg
ls /boot/efi/EFI/debian # UEFI GRUB files on the ESP, if using Debian's normal UEFI GRUB path
# systemd-boot systems, if intentionally used
bootctl status
find /boot /boot/efi -maxdepth 5 -path '*/loader/entries/*' -type f 2>/dev/null
Important: update-grub regenerates /boot/grub/grub.cfg. It does not reinstall the EFI binary to the EFI System Partition. Use grub-install when the EFI binary, fallback path, NVRAM entry, or secondary ESP must be installed or repaired.
hostnamectl
ip addr
ip route
resolvectl status # on systemd-resolved systems; otherwise inspect /etc/resolv.conf
timedatectl
systemctl --failed
journalctl -b -p warning..alert
Servers should have the intended hostname, stable network configuration, correct default route, DNS resolution, synchronized time, and no failed systemd units before they are handed over to production use.
apt install unattended-upgrades apt-listchanges
dpkg-reconfigure --priority=low unattended-upgrades
systemctl status unattended-upgrades
systemctl enable --now fstrim.timer
systemctl status fstrim.timer
unattended-upgrades can install security updates automatically. fstrim.timer performs periodic discard/TRIM on SSD/NVMe-backed filesystems that support it. For production servers, also decide whether unattended reboots are allowed or whether reboots must be handled by your maintenance process.
dmesg -T | grep -Ei 'firmware|microcode|error|fail|nvme|ata|scsi|i/o'
lspci -k
lsusb
apt install smartmontools
smartctl -a /dev/sda # SATA/SAS example
smartctl -a /dev/nvme0 # NVMe controller example
smartctl -t short /dev/sda
Replace device names with the real disks from lsblk. On RAID controllers, USB bridges, and some virtual disks, SMART access may require controller-specific options or may be unavailable from the guest OS.
Complete Reference Cheatsheet
Decision Tree: Which ISO?
| Situation | Use This Image |
|---|---|
| Server install, have internet | Official netinst — current stable image, with firmware support included where available |
| Desktop install, have internet | Official netinst or Live image if you want to test hardware first |
| Air-gapped install, need desktop packages offline | DVD-1; use jigdo or a local mirror for broad offline package coverage |
| Want to test hardware first | Live image → then install via netinst |
| VM / cloud (no installer needed) | Cloud image (qcow2 / .ova) |
Decision Tree: MBR or GPT?
| Situation | Use |
|---|---|
| UEFI firmware (any modern PC/server) | GPT — standard Debian layout for native UEFI boot |
| Pure legacy BIOS hardware | MBR or GPT + BIOS Boot Partition |
| Disk > 2 TiB | GPT — MBR has a practical 2 TiB limit on normal 512-byte-sector disks; use GPT for large disks and modern UEFI installs |
| Adding Debian to existing MBR dual-boot | MBR — match what's already there |
Partition Type Codes (gdisk)
| Code | Partition Type | When to Use |
|---|---|---|
| EF00 | EFI System Partition | ESP / /boot/efi on UEFI systems |
| EF02 | BIOS Boot Partition | Holds GRUB's core image on BIOS + GPT systems; no filesystem and no mount point |
| 8300 | Linux filesystem | /boot, /, /home, etc. |
| 8309 | Linux LUKS | LUKS/dm-crypt encrypted container |
| 8200 | Linux swap | Dedicated swap partition |
| 8E00 | Linux LVM | Physical Volume for LVM |
| FD00 | Linux RAID | mdadm RAID member |
Essential LVM Commands
| Operation | Command |
|---|---|
| List all PVs/VGs/LVs | pvs && vgs && lvs |
| Show free space in VG | vgs vg-name -o vg_name,vg_size,vg_free |
| Extend LV + fs (ext4) | lvextend -L +10G --resizefs /dev/vg/lv |
| Extend LV + fs (XFS) | lvextend -L +10G /dev/vg/lv && xfs_growfs /mountpoint |
| Create snapshot | lvcreate -L 5G -s -n snap /dev/vg/lv |
| Remove snapshot | lvremove /dev/vg/snap |
| Add new disk to VG | pvcreate /dev/sdX && vgextend vg-name /dev/sdX |
| Migrate data off a PV | pvmove /dev/sdX |
Essential LUKS Commands
| Operation | Command |
|---|---|
| Format as LUKS2 | cryptsetup luksFormat --type luks2 /dev/sdX |
| Open container | cryptsetup open /dev/sdX name |
| Close container | cryptsetup close name |
| Show header info | cryptsetup luksDump /dev/sdX |
| Add key slot (passphrase) | cryptsetup luksAddKey /dev/sdX |
| Add key slot (key file) | cryptsetup luksAddKey /dev/sdX /path/to/keyfile |
| Remove key slot | cryptsetup luksKillSlot /dev/sdX N |
| Enroll TPM2 | systemd-cryptenroll --tpm2-device=auto /dev/sdX |
| After early-boot LUKS/LVM change | update-initramfs -u -k all && update-grub — needed for encrypted root, encrypted /usr, resume swap, or mappings required before root mounts |
Bootloader, Initramfs, and High-Risk Recovery Commands
| Operation | Command / Reminder |
|---|---|
| Regenerate GRUB config | update-grub — updates /boot/grub/grub.cfg; it does not reinstall EFI binaries to the ESP |
| Reinstall GRUB when repairing boot files | Use grub-install when the EFI binary, fallback path, NVRAM boot entry, BIOS boot image, or secondary ESP must be installed or repaired |
| Copy GPT layout to replacement RAID disk | sgdisk --replicate=/dev/sdb /dev/sda — /dev/sdb is the destination/replacement disk and /dev/sda is the source/good disk; reversing them can destroy the surviving layout |
| Randomize copied GPT GUIDs | sgdisk --randomize-guids /dev/sdb — run this on the replacement disk after cloning the partition table |
Minimum Partition Sizes
| Partition | Absolute Minimum | Recommended | Notes |
|---|---|---|---|
| ESP | 100 MB | 512 MB | FAT32; larger accommodates multiple OS EFI dirs |
| /boot | 768 MB | 1–2 GB | Kernel and initrd payloads are larger in Debian 13; old 200–512 MB /boot sizes from legacy guides are now too tight for comfortable multi-kernel retention. |
| / (root) | 5 GB | 20–30 GB | More if running Docker, build tools, many packages |
| /var | 3 GB | 20 GB+ | Grows with logs, databases, apt cache, Docker layers |
| /home | 1 GB | Remainder | As large as user data requires |
| swap | 512 MB | RAM × 1 if hibernating; otherwise workload-dependent | Hibernation needs enough swap for the suspend image; swap ≥ RAM is the conservative sizing rule. |
1) Always use the release codename (trixie) in APT source files, never the moving alias (stable).
2) On new installs, use GPT unless you have a specific legacy compatibility reason not to.
3) Use LVM on any system where storage requirements might change — the cost of setting it up is trivial compared to the pain of resizing raw partitions later.
No comments:
Post a Comment