Last edited on 2026-04-12 • Tagged under #netbsd #bsd #encrypt
The first time I installed NetBSD I used sysinst(8), a menu-based program launched at boot that runs in the console. It has a clear and concise layout and I was quickly up-and-running on my new BSD system.
For my next install I wanted to include disk encryption to protect personal data in case the device is lost or stolen. Its not really enough to simply encrypt home directories. Passphrases and sensitive data can linger and be extracted from locations such as system logs and swap memory. There is a trade-off to be made between how much to encrypt, the convenience of operating the system, and the ability for the system to boot.
- 1. Start Here
- 2. Configure the Live Environment
- 3. Prepare the DISK
- 4. Disk Encryption
- 5. Installation
- 6. Configure the System
- 7. Finish Up
- 8. Resources
1. Start Here
Throughout this HOWTO, if you see square brackets [] in code blocks, that means the word of code (square brackets included) should be replaced with something else. This is detailed in the instructions before or after the code block.
NetBSD will be installed as the sole operating system on a single disk using a four-partition layout:
- Partition
ESPis the EFI system partition. - Partition
roothosts a minimal root filesystem that boots to an encryption passphrase prompt, which upon entry unlocks… - … the encrypted device on partition
syscgdcontaining the contents ofvar,usr, andhome. - Partition
swapis swap memory auto-encrypted at boot using a random key.
A few assumptions:
- Target device is
amd64architecture using UEFI to boot. - Secure boot is disabled on target device.
- Network access during install uses a wired interface.
Sysinst does not provide the option for encrypting the system in this manner, so early in the install process I switch to the console and proceed to manually install NetBSD.
Acquire an installation image
The latest official installation images (as of April 2026) are available here: Images and torrents
Download the NetBSD-11.0_RC3-amd64-install.img.gz image and the SHA512 file for verification:
wget https://cdn.netbsd.org/pub/NetBSD/images/11.0_RC3/NetBSD-11.0_RC3-amd64-install.img.gz
wget https://cdn.netbsd.org/pub/NetBSD/images/11.0_RC3/SHA512
Verify the image using sha512sum:
sha512sum -c --ignore-missing SHA512
Decompress the image:
gunzip NetBSD-11.0_RC3-amd64-install.img.gz
Prepare the USB installation medium
Write the installer to an unmounted USB storage device running the dd(1) command as root.
WARNING
Be very careful to note the proper device (which can be identified with lsblk). All contents on the device will be lost!
Example: On a Linux system, if a USB stick appears as sdx1, then write the installer to sdx (omit partition number):
dd bs=4M conv=fsync oflag=direct status=progress if=NetBSD-11.0_RC3-amd64-install.img of=/dev/sdx
2. Configure the Live Environment
Boot the target device from the NetBSD installation medium. Select Option 1 (default) to Install NetBSD.
After the installer has successfully booted into the NetBSD kernel, a prompt appears to select which language will be used for installation messages, followed by a prompt to select a different keyboard type if desired or leave unchanged.
Next up the menu-based sysinst program is launched:
NetBSD-11.0_RC3 Install System
>a: Install NetBSD to hard disk
b: Upgrade NetBSD on a hard disk
c: Re-install sets or install additional sets
d: Reboot the computer
e: Utility menu
f: Config menu
x: Exit Install System
Connect to the internet
At the Install System main menu, select >e: Utility menu then >c: Configure network.
Available interfaces lists the network interfaces detected by the NetBSD installer.
Example: With my target device Available interfaces lists two: wm0 (wired) and iwn0 (wireless). I choose to configure the wired ethernet interface:
Network media (empty to autoconfigure) [autoselect]: <enter>
Perform autoconfiguration?
>a: Yes
Your host name: foobox
Your DNS domain: home.arpa
The following are the values you entered.
[...]
Are they OK?
>a: Yes
Remote login to the installer
Make this manual installation process easier (i.e. cut-n-paste commands) by remotely logging into the installer via ssh from another computer.
Open a shell by selecting >a: Run /bin/sh from the Utilities menu.
Set a password for root:
passwd
Open the sshd_config file for editing using the vi editor:
vi /etc/ssh/sshd_config
Set permission to allow root to login:
PermitRootLogin yes
Save changes and exit.
Start the sshd daemon:
/etc/rc.d/sshd onestart
Retrieve the IP address for the active interface configured earlier (example: wm0):
ifconfig wm0
Switch to the other computer and ssh into the target device:
ssh root@[ip_address]
… where [ip_address] is the target device’s address obtained with the ifconfig command above.
3. Prepare the DISK
NOTE
For the purposes of this HOWTO, the example target device has a single NVMe disk with an existing install of Linux that will be erased and replaced by NetBSD. Device IDs and storage sizes will vary between devices.
Identify disks and partitions
Discover what disk devices and partitions have been recognized by the kernel:
# sysctl hw.disknames
hw.disknames = ld0 dk0 dk1 dk2 dk3 sd0 dk4 dk5
NVMe devices show up as ld and hard disks are identified by wd. USB devices usually show up as sd.
The dk devices are partitions (know as wedges in NetBSD parlance) on the storage devices, and this early after boot are usually displayed in order, that is: dk0 through dk3 are wedges on the NVMe target device ld0, and dk4 and dk5 on the USB installer sd0.
Verify by asking for a list of wedges on sd0:
# dkctl sd0 listwedges
/dev/rsd0: 2 wedges:
dk4: EFI system, 262144 blocks at 2048, type: msdos
dk5: 30c4cc4e-5369-449c-8994-a4b1ea665b4b, 4853760 blocks at 264192, type: ffs
Verify which device the installer booted from:
# dmesg | fgrep "root on"
[ 4.158650] root on dk5
There is also the nvmectl command (use atactl for SATA drives):
# nvmectl identify nvme0 | egrep 'Model|Device type|Capacity'
Model Number: Samsung SSD 980 1TB
Define DISK variable
The NVMe storage device detected above as ld0 is where NetBSD will be installed. Adjust accordingly for your own storage device:
DISK="ld0"
Wipe DISK
Wipe existing file systems and partition table on DISK:
gpt destroy $DISK && gpt show $DISK
Partition DISK
NOTE
I typically set the swap partition size equal to the amount of physical RAM to a maximum 16g.
Create a GPT partition table on DISK with the following layout:
| Number | Size | Type | Use as |
|---|---|---|---|
| 1 | 550m | efi | ESP partition |
| 2 | 6g | ffs | Root partition |
| 3 | 16g | swap | Encrypted swap partition |
| 4 | ->END | cgd | Encrypted system partition |
Create a new GPT partition table:
gpt create -f $DISK
Create the wedges:
gpt add -l "ESP" -t efi -s 550m $DISK
gpt add -l "root" -t ffs -s 6g $DISK
gpt add -l "swap" -t swap -s 16g $DISK
gpt add -l "syscgd" -t cgd $DISK
gpt show $DISK
Define wedge variables
List wedges:
# dkctl $DISK listwedges
/dev/rld0: 4 wedges:
dk2: ESP, 524288 blocks at 34, type: msdos
dk3: root, 16777216 blocks at 524322, type: ffs
dk4: swap, 33554432 blocks at 17301538, type: swap
dk5: syscgd, 1902669165 blocks at 50855970, type: cgd
NOTE
Your dk[number] numbering may differ from above. Adjust accordingly:
Define variables:
DK_ESP="dk2"
DK_ROOT="dk3"
Format and mount the ESP wedge
newfs_msdos /dev/r${DK_ESP} && mount /dev/${DK_ESP} /mnt
Add EFI boot entries to ESP
mkdir -p /mnt/EFI/boot && cp -v /usr/mdec/*.efi /mnt/EFI/boot
Unmount wedge:
umount /mnt
Format and mount the root wedge
Format and mount the root wedge with the FFSv2 file system with support for extended attributes and access control lists:
newfs -O 2ea /dev/r${DK_ROOT} && mount /dev/${DK_ROOT} /targetroot
4. Disk Encryption
NetBSD uses the cryptographic device driver (CGD) to create and manage encrypted devices.
Create encrypted device
Using cgdconfig, a parameters file is generated that stores the encryption type, key length, and a random password salt for the new encrypted device.
There are a few different encryption ciphers supported. I choose aes-xts with a 512-bit key:
mkdir -p /targetroot/etc/cgd && chmod 700 /targetroot/etc/cgd
cgdconfig -g -V disklabel -o /targetroot/etc/cgd/syscgd aes-xts 512
NOTE
NAME=syscgd is the label for the CGD wedge created earlier.
Create the encrypted device and assign it a passphrase. This passphrase will be used to open the CGD device at boot:
cgdconfig -V re-enter cgd0 NAME=syscgd /targetroot/etc/cgd/syscgd
Create disklabels
NOTE
Disklabels c and d have special meaning in NetBSD and should not be used.
Within the encrypted device, three disklabels are created:
| Disklabel | Mountpoint | Size |
|---|---|---|
| cgd0a | /var | 8GB |
| cgd0b | /usr | 48GB |
| cgd0e | /home | ->END |
Create the labels using disklabel in interactive mode:
# disklabel -Ii cgd0
Enter '?' for help
...
Create cgd0a:
partition>a
Filesystem type [4.2BSD]: <enter>
Start offset ('x' to start after partition 'x') [0c, 0s, 0M]: <enter>
Partition size ('$' for all remaining) [947594c, 1940672512s, 947594M]: 8G
a: ...
Create cgd0b:
partition>b
Filesystem type [unused]: 4.2BSD
Start offset ('x' to start after partition 'x') [0c, 0s, 0M]: a
Partition size ('$' for all remaining) [0c, 0s, 0M]: 48G
b: ...
Create cgd0e:
partition>e
Filesystem type [unused]: 4.2BSD
Start offset ('x' to start after partition 'x') [0c, 0s, 0M]: b
Partition size ('$' for all remaining) [0c, 0s, 0M]: $
e: ...
Write the label and quit:
partition>W
Label disk [n]?y
Label written
partition>Q
Verify encrypted device
Set configuration in target device:
echo 'cgd0 NAME=syscgd /etc/cgd/syscgd' > /targetroot/etc/cgd/cgd.conf
Close the CGD device:
cgdconfig -u cgd0
Unlock the CGD device again with the passphrase set earlier:
cgdconfig cgd0 NAME=syscgd /targetroot/etc/cgd/syscgd
The cgd0 drive should now be open and the disklabel visible:
disklabel cgd0
Format and mount disklabels
Format:
newfs -O 2ea cgd0a
newfs -O 2ea cgd0b
newfs -O 2ea cgd0e
Mount:
mkdir /targetroot/var /targetroot/usr /targetroot/home
mount /dev/cgd0a /targetroot/var
mount /dev/cgd0b /targetroot/usr
mount /dev/cgd0e /targetroot/home
5. Installation
The new system is composed of sets (collections of packages) installed to the target device. These sets are located in /amd64/binary/sets. Move into that directory:
cd /amd64/binary/sets && ls
NOTE
Adding flag p to the tar command is important. It ensures that all files preserve their owners and mode.
At a minimum, you must select a kernel and the base and etc sets. Below are the sets I choose to install for a desktop setup:
# for set in base comp etc games gpufw kern-GENERIC man misc modules rescue tests text xbase xcomp xetc xfont xserver; do
> tar -xvzpf $set.tar.xz -C /targetroot
> done
6. Configure the System
Chroot into the freshly installed NetBSD and configure the new OS.
Chroot
chroot /targetroot
Directories
Create the kern and proc directories:
mkdir kern proc
Devices
cd dev
sh MAKEDEV all
On a previous install, after rebooting the boot process halted with the error message:
/etc/defaults/rc.conf: cannot create /dev/null: read-only file system
/etc/rc: cannot create /dev/null: read-only file system
MAKEDEV had created null but it was incorrectly configured:
# ls -l /dev/null
-rw-r--r-- 1 root wheel 0 Apr 5 13:06 null
To avoid this error, remove the existing null:
rm /dev/null
Re-create null with mknod:
# mknod -m 0666 -u root -g wheel /dev/null c 2 2 && ls -l /dev/null
crw-rw-rw- 1 root wheel 2, 2 Apr 11 13:10 /dev/null
Root password
passwd
Superuser
Create a user account assigned to the wheel and operator groups:
useradd -G [groups] -m [username]
Example: Create an account for user foo and assign a password:
useradd -G wheel,operator -m foo
passwd foo
userinfo foo
Fstab
# cat > /etc/fstab << EOF
NAME=root / ffs rw,log,noatime 1 1
NAME=swap none swap sw,dp 0 0
tmpfs /tmp tmpfs rw,-m1777,-sram%25
kernfs /kern kernfs rw
ptyfs /dev/pts ptyfs rw
procfs /proc procfs rw
tmpfs /var/shm tmpfs rw,-m1777,-sram%25
/dev/cgd0a /var ffs rw,log,noatime 1 2
/dev/cgd0b /usr ffs rw,log,noatime 1 2
/dev/cgd0e /home ffs rw,log,noatime 1 2
EOF
Startup
Open rc.conf for editing:
vi /etc/rc.conf
NOTE
In this HOWTO, my hostname was earlier set to foobox.home.arpa during network setup, and my wired interface is wm0. Adjust accordingly:
# If this is not set to YES, the system will drop into single-user mode.
#
rc_configured=YES
# Add local overrides below.
#
# Wait for CGD to be unlocked before mounting.
critical_filesystems_local="OPTIONAL:/var OPTIONAL:/usr"
dhcpcd=YES
dhcpcd_flags="-qM wm0"
hostname=foobox.home.arpa
sshd=YES
ntpd=YES
ntpdate=YES
wscons=YES
cgd=YES
Save changes and exit.
NOTE
Any Error: /dev/ttyp0: No such file or directory messages can be safely ignored.
Keyboard
A full list of keyboard mappings and variants can be found in wskbd(4).
Set encoding [type_of_keyboard] in wscons.conf.
Open file for editing:
vi /etc/wscons.conf
Example: I use the non-default colemak keymap:
encoding us.colemak
Save changes and exit.
Timezone
Create a symlink to the appropriate timezone for your localtime:
ln -sf /usr/share/zoneinfo/[region/<city_or_sub-region] /etc/localtime
Example: Set localtime to Canada/Eastern:
ln -sf /usr/share/zoneinfo/Canada/Eastern /etc/localtime && date
Network interface
ifconfig.if(5) contains the configuration details for each network interface.
Example: Create an interface file for the wm0 interface that is assigned an IP address via DHCP:
# cat > /etc/ifconfig.wm0 << EOF
up
media autoselect
EOF
Terminals
Set the status of terminals ttyE1-ttyE3 in ttys from off to on.
Open file for editing:
vi /etc/ttys
This is how it should look:
# name getty type status comments
#
console "/usr/libexec/getty Pc" wsvt25 off secure
constty "/usr/libexec/getty Pc" wsvt25 on secure
ttyE0 "/usr/libexec/getty Pc" wsvt25 off secure
ttyE1 "/usr/libexec/getty Pc" wsvt25 on secure
ttyE2 "/usr/libexec/getty Pc" wsvt25 on secure
ttyE3 "/usr/libexec/getty Pc" wsvt25 on secure
Save changes and exit.
7. Finish Up
Exit chroot:
exit
cd /
Unmount:
umount /targetroot/home
umount /targetroot/usr
umount /targetroot/var
umount /targetroot
Close encrypted device:
cgdconfig -u cgd0
Reboot system:
shutdown -r now
NOTE
When prompted for the passphrase to unlock the encrypted device, keymap is us qwerty regardless of keymap that might have been set in wscons.conf.
User is prompted for the passphrase to unlock the encrypted syscgd device. Upon success, boot resumes:
NetBSD/amd64 (foobox.home.arpa) (constty)
login: root
Password:
Welcome to NetBSD!
To shutdown/poweroff the system:
shutdown -p now
8. Resources
- This HOWTO posted by vsis was crucial in getting my own system configured with encryption: NetBSD - UEFI installation with Full Disk Encryption
- Alternative approach for disk encryption using a ramdisk on BIOS boot systems: NetBSD Full-Disk Encryption with CGD (BIOS/GPT)
- NetBSD INSTALL: Installation procedure for NetBSD/amd64
- NetBSD Wiki: Installing NetBSD on a x86 system with UEFI
- NetBSD Guide: Chapter 14. The cryptographic device driver (CGD)
- Suggested tools for inspecting disks: Disk management from Installation ISO
- Skipping sysinst install for a more “hands-on” approach: Manual NetBSD install on GPT/UEFI
- Swap encryption is now automatic using the
vm.swap_encrypt=1sysctl(8) variable: Announcing NetBSD 10.0
Next: NetBSD: After the First Boot (TODO)
You can like, share, or comment on this post on the Fediverse 💬