<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>IT Notes - desktop</title><link>https://it-notes.dragas.net/categories/desktop/</link><description>Articles in category desktop</description><atom:link href="https://it-notes.dragas.net/categories/desktop/feed.xml" rel="self"/><language>en</language><lastBuildDate>Mon, 22 Dec 2025 08:43:02 +0000</lastBuildDate><item><title>Installing Void Linux on ZFS with Hibernation Support</title><link>https://it-notes.dragas.net/2025/12/22/void-linux-zfs-hibernation-guide/</link><description>&lt;p&gt;&lt;img src="https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/Void_Linux_logo.svg/960px-Void_Linux_logo.svg.png" alt="Installing Void Linux on ZFS with Hibernation Support"&gt;&lt;/p&gt;&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;FreeBSD continues to make strides in desktop support, but Linux still holds an advantage in hardware compatibility. After running openSUSE Tumbleweed on my mini PC for several months, I decided it was time to switch to a solution I could control more closely. Not because Tumbleweed doesn't work well - it works great! - but I prefer having direct control over what happens on my machine. And I want native ZFS, because I prefer it over btrfs and it allows me to manage snapshots, backups, and rollbacks just as I do on FreeBSD, using the same tools and procedures.&lt;/p&gt;
&lt;p&gt;The choice of &lt;a href="https://voidlinux.org/"&gt;Void Linux&lt;/a&gt; comes from its BSD-like approach: modular and free of unnecessary complexity. This makes it an excellent solution for this type of setup.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://docs.zfsbootmenu.org/"&gt;ZFSBootMenu&lt;/a&gt; is an extremely powerful tool. It provides an experience similar to FreeBSD's boot loader and natively supports ZFS. I strongly recommend reading the documentation and exploring its features, as some of them - like the built-in SSH daemon - can be genuine lifesavers in recovery scenarios.&lt;/p&gt;
&lt;h2&gt;Prerequisites and Audience&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;This guide is not for absolute beginners.&lt;/strong&gt; If you're new to Linux or Unix-like operating systems, you'd be better served by a ready-to-use distribution like &lt;a href="https://www.opensuse.org/"&gt;openSUSE&lt;/a&gt; Leap (or Tumbleweed for a rolling distribution), &lt;a href="https://linuxmint.com/"&gt;Linux Mint&lt;/a&gt;, &lt;a href="https://www.debian.org/"&gt;Debian&lt;/a&gt;, &lt;a href="https://ubuntu.com/"&gt;Ubuntu&lt;/a&gt;, or &lt;a href="https://manjaro.org/"&gt;Manjaro&lt;/a&gt;. The purpose of this article is to demonstrate a stable, upgradeable, and reasonably secure base setup for users already comfortable with system administration. It uses the &lt;strong&gt;glibc&lt;/strong&gt; variant of Void Linux. The &lt;em&gt;&lt;a href="https://docs.voidlinux.org/installation/musl.html"&gt;musl&lt;/a&gt;&lt;/em&gt; version requires different commands, for example for locale generation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use at your own risk.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This guide synthesizes instructions from several sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.zfsbootmenu.org/en/latest/guides/void-linux/uefi.html"&gt;Void Linux (UEFI) from ZFSBootMenu&lt;/a&gt; - which doesn't address swap. Using a zvol for swap (not the best solution) prevents hibernation and resume. Our approach uses a separate encrypted swap partition that enables proper resume.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.voidlinux.org/installation/guides/fde.html"&gt;Void Linux Full Disk Encryption&lt;/a&gt; - excellent for btrfs or ext4, but we want ZFS. We'll borrow the swap configuration approach from here.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://compactbunker.org/p/install-void-linux/"&gt;Install Void Linux with a desktop environment + Flatpaks&lt;/a&gt; - for the desktop portion.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.voidlinux.org/config/graphical-session/gnome.html"&gt;GNOME on Void Linux&lt;/a&gt; - for the GNOME and GDM setup.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/void-linux/void-mklive/blob/master/mkiso.sh"&gt;Void Linux live image builder&lt;/a&gt; - for the XFCE package selection and LightDM configuration used by the official image.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If your setup differs from what's described here (NVMe disk, UEFI boot, Secure Boot disabled), consult the linked guides for explanations and variations.&lt;/p&gt;
&lt;h3&gt;Installation Script (Optional)&lt;/h3&gt;
&lt;p&gt;If you want to reproduce this setup quickly, I maintain a script that automates the procedure described in this guide: disk partitioning, ZFS pool and dataset creation, encrypted swap for hibernation resume, dracut configuration, and ZFSBootMenu EFI setup. It can install KDE Plasma, GNOME, XFCE, or a minimal system without a desktop. KDE remains the default.&lt;/p&gt;
&lt;p&gt;The script is interactive and will ask for the required parameters (target disk, timezone and keymap, passphrases, desktop options). &lt;a href="https://brew.bsd.cafe/stefano/void-zfs-hibernation"&gt;Requirements, usage instructions, and known limitations are documented in the repository README&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That said, I still recommend going through the manual process at least once. Understanding each step is part of the value of this setup, especially when troubleshooting or adapting it to different hardware.&lt;/p&gt;
&lt;h2&gt;Boot Environment&lt;/h2&gt;
&lt;p&gt;Since ZFS isn't supported by the base Void Linux image, we'll use &lt;a href="https://github.com/leahneukirchen/hrmpf/releases"&gt;hrmpf&lt;/a&gt;, an excellent rescue system based on Void Linux that includes ZFS support out of the box.&lt;/p&gt;
&lt;p&gt;After booting, you can either proceed directly or SSH into the machine to continue remotely. I generally prefer SSH since it makes copy-paste operations much easier - especially when dealing with UUIDs and long commands. To enable SSH access, set a root password and allow root login:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Edit &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; and enable:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;PermitRootLogin yes
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Restart the SSH daemon:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;sv restart sshd
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Find the machine's IP address:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;ip addr
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can now connect via SSH from another device.&lt;/p&gt;
&lt;h2&gt;Initial Setup&lt;/h2&gt;
&lt;p&gt;Set up the environment variables and generate a host ID - we need it for ZFS:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;source /etc/os-release
export ID

zgenhostid -f 0x00bab10c
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Disk Configuration&lt;/h2&gt;
&lt;p&gt;Identify your target disk and set up the partition variables. This approach keeps everything consistent and reduces errors:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;# Set the base disk - adjust this to match your system
export DISK=&amp;quot;/dev/nvme0n1&amp;quot;

# For NVMe disks, partitions are named like nvme0n1p1, nvme0n1p2, etc.
# For SATA/SAS disks (sda, sdb), partitions are named sda1, sda2, etc.
# Set the partition separator accordingly:
export PART_SEP=&amp;quot;p&amp;quot;  # Use &amp;quot;p&amp;quot; for NVMe, empty string &amp;quot;&amp;quot; for SATA/SAS

# Define partition numbers
export BOOT_PART=&amp;quot;1&amp;quot;
export SWAP_PART=&amp;quot;2&amp;quot;
export POOL_PART=&amp;quot;3&amp;quot;

# Build full device paths
export BOOT_DEVICE=&amp;quot;${DISK}${PART_SEP}${BOOT_PART}&amp;quot;
export SWAP_DEVICE=&amp;quot;${DISK}${PART_SEP}${SWAP_PART}&amp;quot;
export POOL_DEVICE=&amp;quot;${DISK}${PART_SEP}${POOL_PART}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Verify your configuration before proceeding:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;echo &amp;quot;Boot device: $BOOT_DEVICE&amp;quot;
echo &amp;quot;Swap device: $SWAP_DEVICE&amp;quot;
echo &amp;quot;Pool device: $POOL_DEVICE&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Wipe the Disk&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Warning: This operation will irreversibly destroy all data on the selected disk. Double-check that you've selected the correct disk and be sure to have a complete backup of your system!&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;zpool labelclear -f &amp;quot;$DISK&amp;quot;

wipefs -a &amp;quot;$DISK&amp;quot;
sgdisk --zap-all &amp;quot;$DISK&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Create Partitions&lt;/h2&gt;
&lt;h3&gt;EFI System Partition&lt;/h3&gt;
&lt;p&gt;If you're not using UEFI boot, adapt this procedure following the appropriate guide linked at the beginning of this post:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;sgdisk -n &amp;quot;${BOOT_PART}:1m:+512m&amp;quot; -t &amp;quot;${BOOT_PART}:ef00&amp;quot; &amp;quot;$DISK&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Swap Partition&lt;/h3&gt;
&lt;p&gt;The swap partition should be slightly larger than your RAM to support hibernation. When you hibernate, the entire contents of RAM are written to swap, so you need enough space to hold it all plus some overhead. In this example, I have 16 GB of RAM, so I'm creating an 18 GB swap partition:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;sgdisk -n &amp;quot;${SWAP_PART}:0:+18g&amp;quot; -t &amp;quot;${SWAP_PART}:8200&amp;quot; &amp;quot;$DISK&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;ZFS Pool Partition&lt;/h3&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;sgdisk -n &amp;quot;${POOL_PART}:0:-10m&amp;quot; -t &amp;quot;${POOL_PART}:bf00&amp;quot; &amp;quot;$DISK&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Set Up ZFS Encryption&lt;/h2&gt;
&lt;p&gt;Encrypting the disk is strongly recommended, especially for laptops. Replace &lt;code&gt;SomeKeyphrase&lt;/code&gt; with a strong passphrase that's easy to type. Keep in mind that during early boot, the keyboard layout might default to US, so choose a passphrase that's easy to type on a US keyboard layout:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;echo 'SomeKeyphrase' &amp;gt; /etc/zfs/zroot.key
chmod 000 /etc/zfs/zroot.key
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Create the ZFS Pool&lt;/h2&gt;
&lt;p&gt;Create the pool with conservative, well-tested options:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;zpool create -f -o ashift=12 \
 -O compression=lz4 \
 -O acltype=posixacl \
 -O xattr=sa \
 -O relatime=on \
 -O encryption=aes-256-gcm \
 -O keylocation=file:///etc/zfs/zroot.key \
 -O keyformat=passphrase \
 -o autotrim=on \
 -o compatibility=openzfs-2.2-linux \
 -m none zroot &amp;quot;$POOL_DEVICE&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Create ZFS Datasets&lt;/h2&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;zfs create -o mountpoint=none zroot/ROOT
zfs create -o mountpoint=/ -o canmount=noauto zroot/ROOT/${ID}
zfs create -o mountpoint=/home zroot/home

zpool set bootfs=zroot/ROOT/${ID} zroot
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Export and Reimport for Installation&lt;/h2&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;zpool export zroot
zpool import -N -R /mnt zroot
zfs load-key -L prompt zroot

zfs mount zroot/ROOT/${ID}
zfs mount zroot/home

udevadm trigger
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Install the Base System&lt;/h2&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;XBPS_ARCH=x86_64 xbps-install \
  -S -R https://mirrors.servercentral.com/voidlinux/current \
  -r /mnt base-system
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Copy Host Configuration&lt;/h2&gt;
&lt;p&gt;Copy the files we generated earlier to the new system:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;cp /etc/hostid /mnt/etc
mkdir -p /mnt/etc/zfs
cp /etc/zfs/zroot.key /mnt/etc/zfs
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Configure Encrypted Swap&lt;/h2&gt;
&lt;p&gt;Now we'll set up the encrypted swap partition. This is where the hibernation magic happens - by using a separate LUKS-encrypted partition instead of a ZFS zvol, we can properly resume from hibernation.&lt;/p&gt;
&lt;p&gt;Format the swap partition with LUKS:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;cryptsetup luksFormat --type luks1 &amp;quot;$SWAP_DEVICE&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Open the encrypted partition, create the swap filesystem, and activate it:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;cryptsetup luksOpen &amp;quot;$SWAP_DEVICE&amp;quot; cryptswap
mkswap /dev/mapper/cryptswap
swapon /dev/mapper/cryptswap
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Preserve Variables for Chroot&lt;/h2&gt;
&lt;p&gt;Before entering the chroot, save the disk variables so they remain available inside the new environment:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;cat &amp;lt;&amp;lt; EOF &amp;gt; /mnt/root/disk-vars.sh
export DISK=&amp;quot;$DISK&amp;quot;
export PART_SEP=&amp;quot;$PART_SEP&amp;quot;
export BOOT_PART=&amp;quot;$BOOT_PART&amp;quot;
export SWAP_PART=&amp;quot;$SWAP_PART&amp;quot;
export POOL_PART=&amp;quot;$POOL_PART&amp;quot;
export BOOT_DEVICE=&amp;quot;$BOOT_DEVICE&amp;quot;
export SWAP_DEVICE=&amp;quot;$SWAP_DEVICE&amp;quot;
export POOL_DEVICE=&amp;quot;$POOL_DEVICE&amp;quot;
export ID=&amp;quot;$ID&amp;quot;
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Enter the Chroot Environment&lt;/h2&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;xchroot /mnt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From this point forward, all commands are executed inside the new system.&lt;/p&gt;
&lt;p&gt;First, load the saved variables:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;source /root/disk-vars.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Configure fstab&lt;/h2&gt;
&lt;p&gt;Add the swap entry to &lt;code&gt;/etc/fstab&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;/dev/mapper/cryptswap   none            swap            defaults        0 0
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Set Up Automatic Swap Unlock&lt;/h2&gt;
&lt;p&gt;To avoid entering the swap password separately after unlocking the ZFS pool, we'll create a keyfile stored on the encrypted ZFS dataset. This is secure because the keyfile only becomes accessible after the ZFS pool is unlocked.&lt;/p&gt;
&lt;p&gt;First, install cryptsetup in the new system:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;xbps-install -S cryptsetup
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Generate a random keyfile and add it to the LUKS partition:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;dd bs=1 count=64 if=/dev/urandom of=/boot/volume.key

cryptsetup luksAddKey &amp;quot;$SWAP_DEVICE&amp;quot; /boot/volume.key

chmod 000 /boot/volume.key
chmod -R g-rwx,o-rwx /boot
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Add the keyfile to &lt;code&gt;/etc/crypttab&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;echo &amp;quot;cryptswap   $SWAP_DEVICE   /boot/volume.key   luks,x-initrd.attach&amp;quot; &amp;gt;&amp;gt; /etc/crypttab
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;x-initrd.attach&lt;/code&gt; option is important for hibernation. It tells dracut that this encrypted device must be activated from the initramfs. Without it, dracut's host-only mode may filter the swap entry out of the copy of &lt;code&gt;crypttab&lt;/code&gt; stored in the initramfs.&lt;/p&gt;
&lt;p&gt;Force the crypt module and include the keyfile by creating &lt;code&gt;/etc/dracut.conf.d/10-crypt.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;force_add_dracutmodules+=&amp;quot; crypt &amp;quot;
install_items+=&amp;quot; /boot/volume.key &amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Dracut will include the relevant &lt;code&gt;crypttab&lt;/code&gt; entry because it is marked with &lt;code&gt;x-initrd.attach&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Basic System Configuration&lt;/h2&gt;
&lt;p&gt;Configure keyboard layout and hardware clock. Adjust the keymap and timezone to match your location:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;cat &amp;lt;&amp;lt; EOF &amp;gt;&amp;gt; /etc/rc.conf
KEYMAP=&amp;quot;us&amp;quot;
HARDWARECLOCK=&amp;quot;UTC&amp;quot;
EOF

ln -sf /usr/share/zoneinfo/Europe/Rome /etc/localtime
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Configure locales:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;cat &amp;lt;&amp;lt; EOF &amp;gt;&amp;gt; /etc/default/libc-locales
en_US.UTF-8 UTF-8
en_US ISO-8859-1
EOF

echo &amp;quot;LANG=en_US.UTF-8&amp;quot; &amp;gt; /etc/locale.conf

xbps-reconfigure -f glibc-locales
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Set the root password:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Configure ZFS Boot Support&lt;/h2&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;cat &amp;lt;&amp;lt; EOF &amp;gt; /etc/dracut.conf.d/zol.conf
nofsck=&amp;quot;yes&amp;quot;
add_dracutmodules+=&amp;quot; zfs &amp;quot;
omit_dracutmodules+=&amp;quot; btrfs &amp;quot;
install_items+=&amp;quot; /etc/zfs/zroot.key &amp;quot;
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Install ZFS:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;xbps-install -S zfs
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Configure ZFSBootMenu&lt;/h2&gt;
&lt;p&gt;Set the basic boot properties:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;zfs set org.zfsbootmenu:commandline=&amp;quot;quiet&amp;quot; zroot/ROOT
zfs set org.zfsbootmenu:keysource=&amp;quot;zroot/ROOT/${ID}&amp;quot; zroot
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;The Critical Step: Hibernation Support&lt;/h3&gt;
&lt;p&gt;Now we need to configure hibernation resume. This is the key insight that makes this setup work: normally, the encrypted ZFS root mounts first, and then it unlocks the swap partition. But when resuming from hibernation, the kernel needs to read the hibernation image from swap &lt;em&gt;before&lt;/em&gt; mounting the root filesystem - otherwise, the saved state would be lost.&lt;/p&gt;
&lt;p&gt;To solve this, we store the required kernel parameters in the ZFS dataset properties. ZFSBootMenu passes them to the selected Void Linux kernel and initramfs. Dracut then unlocks the swap partition early, using the keyfile embedded in the initramfs, before attempting to resume the system.&lt;/p&gt;
&lt;p&gt;Get the UUID of your swap partition:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;blkid &amp;quot;$SWAP_DEVICE&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You'll see output like:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;/dev/...: UUID=&amp;quot;xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&amp;quot; TYPE=&amp;quot;crypto_LUKS&amp;quot; PARTUUID=&amp;quot;...&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Store the UUID in a variable for the next step:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;SWAP_UUID=$(blkid -s UUID -o value &amp;quot;$SWAP_DEVICE&amp;quot;)
echo &amp;quot;Swap UUID: $SWAP_UUID&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now set the boot parameters using the captured UUID:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;zfs set org.zfsbootmenu:commandline=&amp;quot;rd.luks.uuid=$SWAP_UUID resume=/dev/mapper/cryptswap&amp;quot; zroot/ROOT/${ID}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Set Up EFI Boot&lt;/h2&gt;
&lt;p&gt;Create and mount the EFI partition:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;mkfs.vfat -F32 &amp;quot;$BOOT_DEVICE&amp;quot;

mkdir -p /boot/efi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Add the EFI partition to &lt;code&gt;/etc/fstab&lt;/code&gt; using its UUID:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;BOOT_UUID=$(blkid -s UUID -o value &amp;quot;$BOOT_DEVICE&amp;quot;)
echo &amp;quot;UUID=$BOOT_UUID    /boot/efi    vfat    defaults    0 0&amp;quot; &amp;gt;&amp;gt; /etc/fstab
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Mount it:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;mount /boot/efi
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Install ZFSBootMenu&lt;/h2&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;xbps-install -S curl

mkdir -p /boot/efi/EFI/ZBM
curl -o /boot/efi/EFI/ZBM/VMLINUZ.EFI -L https://get.zfsbootmenu.org/efi
cp /boot/efi/EFI/ZBM/VMLINUZ.EFI /boot/efi/EFI/ZBM/VMLINUZ-BACKUP.EFI
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Configure the EFI boot entries:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;xbps-install -S efibootmgr

efibootmgr -c -d &amp;quot;$DISK&amp;quot; -p &amp;quot;$BOOT_PART&amp;quot; \
  -L &amp;quot;ZFSBootMenu (Backup)&amp;quot; \
  -l '\EFI\ZBM\VMLINUZ-BACKUP.EFI'

efibootmgr -c -d &amp;quot;$DISK&amp;quot; -p &amp;quot;$BOOT_PART&amp;quot; \
  -L &amp;quot;ZFSBootMenu&amp;quot; \
  -l '\EFI\ZBM\VMLINUZ.EFI'
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Microcode updates&lt;/h3&gt;
&lt;p&gt;Void Linux is modular, so you may need to install additional packages for your specific hardware. For the Intel microcode, you need the non-free repo:
For example:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;# For Intel CPUs
xbps-install -S void-repo-nonfree
xbps-install -S intel-ucode

# For AMD CPUs/GPUs
xbps-install -S linux-firmware-amd
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After installing microcode updates, regenerate the boot images:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;xbps-reconfigure -fa
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Verify that the generated initramfs contains everything required to unlock the swap partition during early boot:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;KERNEL_VERSION=$(ls /lib/modules | sort -V | tail -1)
INITRAMFS=&amp;quot;/boot/initramfs-${KERNEL_VERSION}.img&amp;quot;

lsinitrd -m &amp;quot;$INITRAMFS&amp;quot; | grep -w crypt &amp;gt;/dev/null ||
  { echo &amp;quot;ERROR: crypt module is missing from initramfs&amp;quot;; exit 1; }

lsinitrd &amp;quot;$INITRAMFS&amp;quot; | grep -F 'boot/volume.key' &amp;gt;/dev/null ||
  { echo &amp;quot;ERROR: swap keyfile is missing from initramfs&amp;quot;; exit 1; }

lsinitrd &amp;quot;$INITRAMFS&amp;quot; | grep -F 'etc/crypttab' &amp;gt;/dev/null ||
  { echo &amp;quot;ERROR: crypttab is missing from initramfs&amp;quot;; exit 1; }

echo &amp;quot;LUKS resume support successfully verified in $INITRAMFS&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Choose an Installation Profile&lt;/h2&gt;
&lt;p&gt;At this point, you can keep the system minimal or install KDE Plasma, GNOME, or XFCE. The desktop profiles share the same networking, audio, login management, and user setup; only the desktop packages and display manager differ.&lt;/p&gt;
&lt;h3&gt;Minimal System&lt;/h3&gt;
&lt;p&gt;For a server or a console-only installation, enable &lt;code&gt;dhcpcd&lt;/code&gt; and skip the desktop sections below:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;xbps-install -S dhcpcd
ln -s /etc/sv/dhcpcd /etc/runit/runsvdir/default/
exit
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then continue from &lt;a href="#exit-and-reboot"&gt;Exit and Reboot&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Desktop Installation&lt;/h2&gt;
&lt;h3&gt;Install Core Desktop Packages&lt;/h3&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;xbps-install -S vim nano dbus elogind polkit sudo xorg xorg-fonts xorg-video-drivers xorg-input-drivers dejavu-fonts-ttf terminus-font NetworkManager pipewire alsa-pipewire wireplumber xdg-user-dirs unzip gzip xz 7zip
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Install the Desktop Environment&lt;/h3&gt;
&lt;p&gt;Choose one of the following three options.&lt;/p&gt;
&lt;p&gt;For KDE Plasma:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;xbps-install -S kde-plasma dolphin konsole firefox kdegraphics-thumbnailers ffmpegthumbs vlc ark kwrite discover kf6-purpose
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For GNOME:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;xbps-install -S gnome firefox
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;gnome&lt;/code&gt; package includes GDM. GNOME starts a Wayland session by default, while the Xorg session remains available from the login screen.&lt;/p&gt;
&lt;p&gt;For XFCE:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;xbps-install -S xfce4 lightdm lightdm-gtk-greeter firefox gnome-themes-standard gnome-keyring network-manager-applet gvfs-afc gvfs-mtp gvfs-smb udisks2 xfce4-pulseaudio-plugin

mkdir -p /etc/lightdm
echo xfce &amp;gt; /etc/lightdm/.session
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the same set of integration packages used by Void's XFCE image. XFCE runs as a conventional Xorg session through LightDM.&lt;/p&gt;
&lt;h3&gt;Enable Services&lt;/h3&gt;
&lt;p&gt;Enable the services shared by all three desktop profiles:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;ln -s /etc/sv/dbus /etc/runit/runsvdir/default/
ln -s /etc/sv/elogind /etc/runit/runsvdir/default/
ln -s /etc/sv/polkitd /etc/runit/runsvdir/default/
ln -s /etc/sv/NetworkManager /etc/runit/runsvdir/default/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Disable services that would compete with NetworkManager or &lt;code&gt;elogind&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;rm -f /etc/runit/runsvdir/default/{dhcpcd,wpa_supplicant,wicd,connmand,acpid}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, enable the display manager that belongs to the desktop you installed.&lt;/p&gt;
&lt;p&gt;For KDE Plasma:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;ln -s /etc/sv/sddm /etc/runit/runsvdir/default/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For GNOME:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;ln -s /etc/sv/gdm /etc/runit/runsvdir/default/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For XFCE:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;ln -s /etc/sv/lightdm /etc/runit/runsvdir/default/
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Configure PipeWire Audio&lt;/h3&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;mkdir -p /etc/xdg/autostart
ln -sf /usr/share/applications/pipewire.desktop /etc/xdg/autostart/

mkdir -p /etc/pipewire/pipewire.conf.d
ln -sf /usr/share/examples/wireplumber/10-wireplumber.conf /etc/pipewire/pipewire.conf.d/
ln -sf /usr/share/examples/pipewire/20-pipewire-pulse.conf /etc/pipewire/pipewire.conf.d/

mkdir -p /etc/alsa/conf.d
ln -sf /usr/share/alsa/alsa.conf.d/50-pipewire.conf /etc/alsa/conf.d
ln -sf /usr/share/alsa/alsa.conf.d/99-pipewire-default.conf /etc/alsa/conf.d
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Enable Additional Repositories and Flatpak (Optional)&lt;/h3&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;xbps-install -S void-repo-nonfree void-repo-multilib void-repo-multilib-nonfree

xbps-install -S flatpak
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Create a Regular User and Exit&lt;/h3&gt;
&lt;p&gt;For desktop use, create a non-root user with appropriate group memberships.
Replace &lt;code&gt;username&lt;/code&gt; with your desired username.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;echo '%wheel ALL=(ALL:ALL) ALL' &amp;gt; /etc/sudoers.d/wheel
chmod 440 /etc/sudoers.d/wheel
visudo -cf /etc/sudoers.d/wheel

useradd -m -G video,wheel,plugdev,kvm,audio,network username
passwd username
exit
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Fix NetworkManager's resolv.conf&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;xchroot&lt;/code&gt; will bind mount &lt;code&gt;/etc/resolv.conf&lt;/code&gt; and leave an empty file. NetworkManager won't like it, so let's clean it up:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;umount -l /mnt/etc/resolv.conf 2&amp;gt;/dev/null || true

rm -f /mnt/etc/resolv.conf
ln -s /run/NetworkManager/resolv.conf /mnt/etc/resolv.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Exit and Reboot&lt;/h2&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;umount -n -R /mnt
zpool export zroot
reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Post-Installation&lt;/h2&gt;
&lt;p&gt;If everything went well, after entering your ZFS encryption password, you'll reach the login screen for the desktop you selected:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;KDE Plasma uses SDDM.&lt;/li&gt;
&lt;li&gt;GNOME uses GDM, with Wayland selected by default and Xorg available as an alternative.&lt;/li&gt;
&lt;li&gt;XFCE uses LightDM and Xorg.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The minimal profile boots to a console login and uses &lt;code&gt;dhcpcd&lt;/code&gt; for networking.&lt;/p&gt;
&lt;h2&gt;Testing Hibernation&lt;/h2&gt;
&lt;p&gt;On KDE, GNOME, or XFCE, you can use the desktop's Hibernate action or run:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;loginctl hibernate
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On a minimal installation, use:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;ZZZ -Z
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The system should power off. When you turn it back on, ZFSBootMenu will prompt for the ZFS passphrase and load the selected boot environment. Void's dracut initramfs will then unlock the swap partition, detect the hibernation image, and resume your session exactly where you left off.&lt;/p&gt;
&lt;p&gt;If resume fails, check that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The LUKS UUID in the ZFS commandline property matches your swap partition&lt;/li&gt;
&lt;li&gt;The swap partition is large enough for your RAM&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;crypttab&lt;/code&gt; entry includes &lt;code&gt;x-initrd.attach&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The initramfs contains the crypt module, &lt;code&gt;/boot/volume.key&lt;/code&gt;, and &lt;code&gt;/etc/crypttab&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You now have a fully functional Void Linux system with native ZFS, full disk encryption, and working hibernation. The system is rolling, lightweight, and easy to maintain. Enjoy!&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefano Marinelli</dc:creator><pubDate>Mon, 22 Dec 2025 08:43:02 +0000</pubDate><guid isPermaLink="true">https://it-notes.dragas.net/2025/12/22/void-linux-zfs-hibernation-guide/</guid><category>linux</category><category>desktop</category><category>zfs</category><category>server</category><category>tutorial</category><category>ownyourdata</category><category>voidlinux</category></item><item><title>How to Set Up a Alpine Linux VM Hosting XRDP and XFCE for Secure Remote Desktop Access</title><link>https://it-notes.dragas.net/2024/05/14/How-to-Set-Up-an-Alpine-Linux-VM-Hosting-XRDP-and-XFCE-for-Secure-Remote-Desktop-Access/</link><description>&lt;p&gt;&lt;img src="https://it-notes.dragas.net/featured/alps.webp" alt="How to Set Up a Alpine Linux VM Hosting XRDP and XFCE for Secure Remote Desktop Access"&gt;&lt;/p&gt;&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;A client recently asked if their approach to remote desktop access was correct. They leave their office PC on and connect to it via remote desktop. Their main requirement is to access internal resources via a browser (they use Brave, so the BSDs cannot be currenly used) and they prefer not to use their home computers for security reasons. I can understand their concern – I wouldn’t be comfortable knowing that a home PC (possibly shared with others) could connect to the company VPN and have unrestricted access.&lt;/p&gt;
&lt;h2&gt;Setting Up Alpine Linux on a VM&lt;/h2&gt;
&lt;p&gt;To address this, I downloaded the &lt;a href="https://alpinelinux.org/downloads/"&gt;Alpine Linux Virt ISO from the official site&lt;/a&gt; and installed it on a VM in their office datacenter. They use Proxmox, which made the process quite straightforward. I allocated 20GB of disk space, 4GB of RAM, and 2 CPU cores to the VM. For added security, the installation process allows you to encrypt the disk. Note that if you choose this option, you’ll need to access the virtualizer console to re-enter the password every time the VM restarts.&lt;/p&gt;
&lt;p&gt;During the Alpine installation, create a non-privileged user who will be using the remote desktop we’re about to set up.&lt;/p&gt;
&lt;h2&gt;Initial Configuration&lt;/h2&gt;
&lt;p&gt;Once the installation is complete, you can log in via the console as root or use SSH with the newly created non-privileged user. In the latter case, you’ll first need to switch to the root user:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;su -
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Enable the community repository by uncommenting it in &lt;code&gt;/etc/apk/repositories&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;http://dl-cdn.alpinelinux.org/alpine/v3.20/main
http://dl-cdn.alpinelinux.org/alpine/v3.20/community
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Installing Required Packages&lt;/h2&gt;
&lt;p&gt;Next, install the main packages needed to manage the remote desktop:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;apk add xrdp xorgxrdp xorg-server xfce4 xfce4-terminal wireguard-tools ifupdown-ng-wireguard&lt;/code&gt; &lt;/p&gt;
&lt;p&gt;Edit the &lt;code&gt;/etc/xrdp/xrdp.ini&lt;/code&gt; file to ensure xrdp listens only on the VPN’s private IP, avoiding exposure to the LAN (or worse, the WAN):&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;port=tcp://172.16.16.1:3389
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Enable xrdp:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;rc-update add xrdp
rc-update add xrdp-sesman
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Configuring Wireguard&lt;/h2&gt;
&lt;p&gt;To set up Wireguard, navigate to &lt;code&gt;/etc/wireguard&lt;/code&gt; and create the keys:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;wg genkey | tee server.privatekey | wg pubkey &amp;gt; server.publickey&lt;/code&gt; &lt;/p&gt;
&lt;p&gt;Create a configuration file &lt;code&gt;wg0.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;[Interface]
Address = 172.16.16.1/24
ListenPort = 4242
PrivateKey = &amp;lt;server private key value&amp;gt; # the key from the previously generated privatekey file

[Peer]
PublicKey = &amp;lt;client public key value&amp;gt; # client’s public key
AllowedIPs = 172.16.16.2/32
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On the client, the configuration should look like this:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;[Interface]
PrivateKey = &amp;lt;client private key value&amp;gt;
Address = 172.16.16.2/24

[Peer]
PublicKey = &amp;lt;server public key value&amp;gt;
AllowedIPs = 172.16.16.0/24
Endpoint = &amp;lt;server public ip&amp;gt;:4242
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, open the &lt;code&gt;/etc/network/interfaces&lt;/code&gt; file and add:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;auto wg0
iface wg0 inet static
pre-up wg-quick up /etc/wireguard/wg0.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Reboot the VM, and everything should be ready. Just be sure to set your router/firewall to forward the 4242 UDP port to the VPS LAN ip for Wireguard access. If the VM has been exposed via public IP, this won't be necessary, but remember that ssh will be exposed, too so take care.&lt;/p&gt;
&lt;h2&gt;Connecting via Remote Desktop&lt;/h2&gt;
&lt;p&gt;Use your favorite RDP remote desktop client and point it to &lt;code&gt;172.16.16.1&lt;/code&gt;. You should see a login screen.&lt;/p&gt;
&lt;h2&gt;Installing Brave Browser&lt;/h2&gt;
&lt;p&gt;To install Brave Browser on Alpine Linux, the easiest way is to use Flatpak. Open a terminal and, as root, install Flatpak and Brave Browser:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;su -
apk add flatpak
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak install flathub com.brave.Browser
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After logging out and back into the remote desktop, Brave should appear in the list of applications. Launch it, and you can synchronize it with the Brave installation on your work PC. This setup ensures that everything works seamlessly on the virtual remote desktop.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This approach offers multiple benefits. By exposing the remote desktop via Wireguard, you significantly enhance security without compromising access to internal services. This method ensures that your internal resources remain protected while being easily accessible when needed.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefano Marinelli</dc:creator><pubDate>Tue, 14 May 2024 08:05:51 +0000</pubDate><guid isPermaLink="true">https://it-notes.dragas.net/2024/05/14/How-to-Set-Up-an-Alpine-Linux-VM-Hosting-XRDP-and-XFCE-for-Secure-Remote-Desktop-Access/</guid><category>alpine</category><category>linux</category><category>server</category><category>networking</category><category>hosting</category><category>tutorial</category><category>desktop</category><category>ownyourdata</category></item><item><title>How to Create a FreeBSD Jail Hosting XRDP and XFCE for Remote Desktop Access</title><link>https://it-notes.dragas.net/2023/12/13/how-to-create-a-freebsd-jail-hosting-xrdp-and-xfce-remote-access-desktop/</link><description>&lt;p&gt;&lt;img src="https://it-notes.dragas.net/featured/server_rack.webp" alt="How to Create a FreeBSD Jail Hosting XRDP and XFCE for Remote Desktop Access"&gt;&lt;/p&gt;&lt;h2&gt;How to Create a FreeBSD Jail Hosting XRDP and XFCE for Remote Desktop Access&lt;/h2&gt;
&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;This tutorial guides you through the process of setting up a FreeBSD jail that hosts XRDP and XFCE. This setup enables secure remote desktop access.&lt;/p&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;FreeBSD system&lt;/li&gt;
&lt;li&gt;Basic knowledge of FreeBSD jails using &lt;a href="https://bastillebsd.org/"&gt;BastilleBSD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;SSH access to the FreeBSD server&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Step 1: Create a New Jail with Bastille&lt;/h3&gt;
&lt;p&gt;First, we create a new jail using BastilleBSD. The following command initializes a jail named &lt;code&gt;xfce&lt;/code&gt; with FreeBSD 14.1-RELEASE on IP 10.0.0.200:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;bastille create xfce 14.1-RELEASE 10.0.0.200 bastille0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After creating the jail, modify its configuration (in a default environment, it would be &lt;em&gt;/usr/local/bastille/jails/xfce/jail.conf&lt;/em&gt;) to enable certain features. Default configuration of xrdp needs an IPv6 address:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;sysvshm = new;
allow.mount.procfs = 1;
ip6.addr = &amp;quot;fd12:3456:789a:1::1&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Step 2: Restart the Jail&lt;/h3&gt;
&lt;p&gt;Restart the jail to apply the new settings:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;bastille restart xfce
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Step 3: Install XRDP and XFCE&lt;/h3&gt;
&lt;p&gt;Access the jail's console, and install XRDP and XFCE:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;bastille console xfce
pkg install xorg xrdp xfce
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Step 4: Configure XRDP&lt;/h3&gt;
&lt;p&gt;Enable XRDP services by adding the following lines to your jail's &lt;em&gt;/etc/rc.conf&lt;/em&gt;:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;xrdp_enable=&amp;quot;YES&amp;quot;
xrdp_sesman_enable=&amp;quot;YES&amp;quot; # Enable if running xrdp-sesman on the same machine
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Step 5: Modify the startwm script&lt;/h3&gt;
&lt;p&gt;Edit the &lt;em&gt;/usr/local/etc/xrdp/startwm.sh&lt;/em&gt; file:&lt;/p&gt;
&lt;p&gt;Uncomment &lt;code&gt;exec startxfce4&lt;/code&gt; to ensure XFCE is started with XRDP.&lt;/p&gt;
&lt;h3&gt;Step 6: Add a User&lt;/h3&gt;
&lt;p&gt;Create a user in the jail for remote access: &lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-bash"&gt;adduser
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Follow the prompts to set up the user.&lt;/p&gt;
&lt;h3&gt;Step 7: Secure the Connection&lt;/h3&gt;
&lt;p&gt;Never expose the RDP port directly. Instead, use an SSH tunnel:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Restart the jail. Establish an SSH tunnel from your local machine to the host machine of the jail, forwarding the traffic to the jail's IP address (10.0.0.200) on port 3389, which is the default port for xrdp.&lt;/li&gt;
&lt;li&gt;Connect to the jail using an RDP client through the tunnel.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You now have a secure, remote desktop environment using XFCE within a FreeBSD jail, accessible through an SSH tunnel. This setup is ideal for managing isolated environments or for secure, remote workspace solutions.&lt;/p&gt;
&lt;p&gt;&lt;mastodon-comments host="mastodon.bsd.cafe" user="stefano" tootId="111572574813376951"&gt;&lt;/mastodon-comments&gt;&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefano Marinelli</dc:creator><pubDate>Wed, 13 Dec 2023 09:05:51 +0000</pubDate><guid isPermaLink="true">https://it-notes.dragas.net/2023/12/13/how-to-create-a-freebsd-jail-hosting-xrdp-and-xfce-remote-access-desktop/</guid><category>freebsd</category><category>server</category><category>networking</category><category>hosting</category><category>tutorial</category><category>jail</category><category>container</category><category>desktop</category></item></channel></rss>