Debian
Installation
Boot from the installation media described in Bootable Installation Media. The steps below perform a manual installation using debootstrap with a Btrfs filesystem, multiple subvolumes, a swap file, and hibernation support 1. Start by dropping into a root shell.
Identify the target disk, wipe it, and partition it.
lsblk -p
export DISK="/dev/vda"
apt update && apt install gdisk -y
# Wipe the disk and create a fresh GPT layout
sgdisk -Z $DISK
sgdisk -og $DISK
# Create EFI system partition (1 GiB)
sgdisk -n 1::+1G -t 1:ef00 -c 1:'ESP' $DISK
# Create root partition (rest of the disk)
sgdisk -n 2:: -t 2:8300 -c 2:'LINUX' $DISK
# Format the EFI partition with FAT32 filesystem
mkfs.fat -F32 -n EFI ${DISK}1
# Format the main partition with Btrfs filesystem
mkfs.btrfs -L DEBIAN ${DISK}2
# Verify the filesystem formats
lsblk -po name,size,fstype,fsver,label,uuid $DISK
Create Btrfs subvolumes and mount everything under /mnt.
# Mount the Btrfs root
mount -v ${DISK}2 /mnt
# Create essential subvolumes
btrfs subvolume create /mnt/@ # Root filesystem
btrfs subvolume create /mnt/@home # User home data
btrfs subvolume create /mnt/@opt # Optional software
btrfs subvolume create /mnt/@cache # Cache data
btrfs subvolume create /mnt/@libvirt # Virtual machines
btrfs subvolume create /mnt/@log # Log files
btrfs subvolume create /mnt/@spool # Spool data
btrfs subvolume create /mnt/@tmp # Temporary files
btrfs subvolume create /mnt/@swap # Swap file location
umount -v /mnt
# Define mount options for optimal Btrfs performance
BTRFS_OPTS="defaults,noatime,space_cache=v2,compress=zstd:1"
# Mount the root subvolume
mount -vo $BTRFS_OPTS,subvol=@ ${DISK}2 /mnt
# Create directories for other subvolumes
mkdir -vp /mnt/{home,opt,boot/efi,var/{cache,lib/libvirt,log,spool,tmp,swap}}
# Mount the remaining subvolumes
mount -vo $BTRFS_OPTS,subvol=@home ${DISK}2 /mnt/home
mount -vo $BTRFS_OPTS,subvol=@opt ${DISK}2 /mnt/opt
mount -vo $BTRFS_OPTS,subvol=@cache ${DISK}2 /mnt/var/cache
mount -vo $BTRFS_OPTS,subvol=@libvirt ${DISK}2 /mnt/var/lib/libvirt
mount -vo $BTRFS_OPTS,subvol=@log ${DISK}2 /mnt/var/log
mount -vo $BTRFS_OPTS,subvol=@spool ${DISK}2 /mnt/var/spool
mount -vo $BTRFS_OPTS,subvol=@tmp ${DISK}2 /mnt/var/tmp
# Mount swap subvolume without compression or CoW for reliability
mount -vo defaults,noatime,subvol=@swap ${DISK}2 /mnt/var/swap
# Mount the EFI partition
mount -v ${DISK}1 /mnt/boot/efi
# Verify the mounts
lsblk -po name,size,fstype,uuid,mountpoints $DISK
Install the base system with debootstrap, bind-mount kernel filesystems, and write /etc/fstab.
apt install -y debootstrap
# Install base Debian 13 (Trixie) system into /mnt
debootstrap --arch=amd64 trixie /mnt http://deb.debian.org/debian
# Mount necessary filesystems for the chroot environment
for dir in dev proc sys run; do
mount -v --rbind "/${dir}" "/mnt/${dir}"
mount -v --make-rslave "/mnt/${dir}"
done
# Mount EFI variables (for UEFI systems)
mount -v -t efivarfs efivarfs /mnt/sys/firmware/efi/efivars
# Get UUIDs for Btrfs and EFI partitions
BTRFS_UUID=$(blkid -s UUID -o value ${DISK}2) ; echo $BTRFS_UUID
EFI_UUID=$(blkid -s UUID -o value ${DISK}1) ; echo $EFI_UUID
# Create /etc/fstab inside the target system
cat > /mnt/etc/fstab << EOF
UUID=$BTRFS_UUID / btrfs defaults,noatime,space_cache=v2,compress=zstd:1,subvol=@ 0 0
UUID=$BTRFS_UUID /home btrfs defaults,noatime,space_cache=v2,compress=zstd:1,subvol=@home 0 0
UUID=$BTRFS_UUID /opt btrfs defaults,noatime,space_cache=v2,compress=zstd:1,subvol=@opt 0 0
UUID=$BTRFS_UUID /var/cache btrfs defaults,noatime,space_cache=v2,compress=zstd:1,subvol=@cache 0 0
UUID=$BTRFS_UUID /var/lib/libvirt btrfs defaults,noatime,space_cache=v2,compress=zstd:1,subvol=@libvirt 0 0
UUID=$BTRFS_UUID /var/log btrfs defaults,noatime,space_cache=v2,compress=zstd:1,subvol=@log 0 0
UUID=$BTRFS_UUID /var/spool btrfs defaults,noatime,space_cache=v2,compress=zstd:1,subvol=@spool 0 0
UUID=$BTRFS_UUID /var/tmp btrfs defaults,noatime,space_cache=v2,compress=zstd:1,subvol=@tmp 0 0
UUID=$BTRFS_UUID /var/swap btrfs defaults,noatime,subvol=@swap 0 0
UUID=$EFI_UUID /boot/efi vfat defaults,noatime 0 2
EOF
cat /mnt/etc/fstab
Enter the chroot and configure the system. Everything until exit runs inside the chroot.
# Set the system hostname
echo "computer" > /etc/hostname
# Configure /etc/hosts
cat > /etc/hosts << EOF
127.0.0.1 localhost
127.0.1.1 $(cat /etc/hostname)
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
EOF
# Set the timezone
ln -sf /usr/share/zoneinfo/Europe/London /etc/localtime
# Install and configure locales
apt install -y locales
dpkg-reconfigure locales
# Configure APT sources for Debian 13 (Trixie) with contrib and non-free
cat > /etc/apt/sources.list << EOF
deb http://deb.debian.org/debian trixie main contrib non-free non-free-firmware
deb-src http://deb.debian.org/debian trixie main contrib non-free non-free-firmware
deb http://security.debian.org/debian-security trixie-security main contrib non-free non-free-firmware
deb-src http://security.debian.org/debian-security trixie-security main contrib non-free non-free-firmware
deb http://deb.debian.org/debian trixie-updates main contrib non-free non-free-firmware
deb-src http://deb.debian.org/debian trixie-updates main contrib non-free non-free-firmware
EOF
apt update
# Install kernel, system tools, and essential utilities
apt install -y linux-image-amd64 linux-headers-amd64 \
firmware-linux firmware-linux-nonfree \
grub-efi-amd64 efibootmgr network-manager \
btrfs-progs sudo vim bash-completion
Set up a swap file with hibernation support. Adjust count to 1.5× your RAM size in MiB.
# Prepare swap file — disable CoW and compression, both required for a Btrfs swap file
truncate -s 0 /var/swap/swapfile
chattr +C /var/swap/swapfile
btrfs property set /var/swap compression none
# 12 GB swap for 8 GB RAM (1.5× for hibernation)
dd if=/dev/zero of=/var/swap/swapfile bs=1M count=12288 status=progress
chmod 600 /var/swap/swapfile
mkswap -L SWAP /var/swap/swapfile
# Add swap to fstab and activate it
echo "/var/swap/swapfile none swap defaults 0 0" >> /etc/fstab
swapon /var/swap/swapfile
swapon -v
# Configure GRUB for hibernation
SWAP_OFFSET=$(btrfs inspect-internal map-swapfile -r /var/swap/swapfile)
BTRFS_UUID=$(blkid -s UUID -o value ${DISK}2)
GRUB_CMD="quiet resume=UUID=$BTRFS_UUID resume_offset=$SWAP_OFFSET"
echo "GRUB_CMDLINE_LINUX_DEFAULT=\"$GRUB_CMD\"" >> /etc/default/grub
update-grub
# Configure initramfs for hibernation
cat > /etc/initramfs-tools/conf.d/resume << EOF
RESUME=/var/swap/swapfile
RESUME_OFFSET=$SWAP_OFFSET
EOF
update-initramfs -u -k all
Create a user and install GRUB, then exit the chroot.
useradd -m -G sudo,adm -s /bin/bash -c "User" user
passwd user
id user
grub-install \
--target=x86_64-efi \
--efi-directory=/boot/efi \
--bootloader-id=debian \
--recheck
update-grub
exit
Unmount and reboot into the installed system.
Post Installation
Update the system and install essential packages.
sudo apt update && sudo apt upgrade
sudo apt install neovim build-essential p7zip-full curl git git-lfs btop fastfetch \
unrar libavcodec-extra ttf-mscorefonts-installer ffmpeg ssh network-manager-gnome
Install Miniconda.
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/Miniconda3-latest-Linux-x86_64.sh
bash /tmp/Miniconda3-latest-Linux-x86_64.sh
Set up snapshot support. Create a Btrfs subvolume for Firefox's profile directory so snapshots don't bloat with browser cache.
btrfs subvolume create ~/.mozilla
sudo btrfs subvolume list /
sudo apt install -y snapper btrfs-assistant inotify-tools git make
sudo snapper -c root create-config /
sudo snapper -c home create-config /home
sudo snapper -c root set-config ALLOW_USERS=$USER SYNC_ACL=yes
sudo snapper -c home set-config ALLOW_USERS=$USER SYNC_ACL=yes
sudo snapper list-configs
snapper -c root get-config
snapper -c home get-config
snapper ls
snapper -c home ls
Install grub-btrfs to make GRUB automatically detect Btrfs snapshots as boot entries.
Note
gawk is a required dependency. Without it, grub-btrfs falls back to mawk which fails to extract snapshot UUIDs.
# Set kernel parameters so snapshots boot in overlay mode
sed -i.bkp \
'/^#GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS=/a \
GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS="rd.live.overlay.overlayfs=1"' \
config
sudo make install
sudo systemctl enable --now grub-btrfsd.service
sudo systemctl status snapper-boot.timer
sudo systemctl status snapper-timeline.timer
sudo systemctl status snapper-cleanup.timer
sudo snapper -c home set-config TIMELINE_CREATE=no
Configure the keyboard layout.
sudo apt install kbd console-setup
localectl status
sudo dpkg-reconfigure console-setup
sudo dpkg-reconfigure keyboard-configuration
cat /etc/default/keyboard
Install X11, build dependencies for suckless tools, and fonts.
sudo apt install xserver-xorg xinit
sudo apt install libx11-dev libxft-dev libxinerama-dev
sudo apt install xfonts-terminus fonts-noto-core fonts-noto-cjk fonts-noto-color-emoji fonts-noto-extra fonts-font-awesome
Install dwm, st, and dmenu.
mkdir -p ~/.local/src/
git clone https://git.suckless.org/dwm ~/.local/src/dwm
cd ~/.local/src/dwm && make clean && sudo make install && cd ~
git clone git://git.suckless.org/st ~/.local/src/st
cd ~/.local/src/st && make clean && sudo make install && cd ~
git clone git://git.suckless.org/dmenu ~/.local/src/dmenu
cd ~/.local/src/dmenu && make clean && sudo make install && cd ~
echo "exec dwm" > ~/.xinitrc
Enable audio and Bluetooth.
sudo apt install pipewire pipewire-alsa pipewire-pulse wireplumber
sudo apt install bluez
sudo systemctl enable --now bluetooth
-
https://sysguides.com/install-debian-13-with-btrfs ↩