Installing Debian on a NAS in fully automated mode
- Published on
- ·5 min read
Why automate the installation?
Picture this: your NAS works great. Everything's smooth. Then one day, bam - the system drive dies. You're staring at a manual Debian installation again. Download the ISO, click through the installer (did I forget anything?), mess with networking, and spend half a day thinking "oh man, I should've picked that option."
A fully automated installation solves this pain. Boot the ISO, get a coffee, and 10 minutes later you're done. No clicking. No second-guessing. Just repeatability.
That's what I set up on my TerraMaster F4-424, replacing TOS (TerraMaster's proprietary mess) with Debian 13 Trixie using a custom preseed ISO.
The hardware
The F4-424 is solid for this kind of thing:
- CPU: Intel N95 (Alder Lake-N, 4 cores, up to 3.4 GHz)
- RAM: 8 GB DDR5
- Network: 2x 2.5GbE Realtek RTL8125
- Storage: ASMedia ASM1166 controller with 6 SATA ports
- Boot: 4 GB internal USB drive
The setup: Debian boots from USB in UEFI mode, the 4 SATA bays hold all the actual data. Clean separation.
Building the custom ISO
Here's where preseed comes in. You write a config file that answers every question the Debian installer would ask, inject it into an ISO, and you're golden. The build.sh script uses xorriso to do the heavy lifting. Network parameters (IP, gateway, DNS) go in a .env file so you can tweak them without editing scripts:
# .env - ISO configuration
PRESEED_IP=192.168.1.50
PRESEED_GATEWAY=192.168.1.1
PRESEED_DNS=192.168.1.1
PRESEED_HOSTNAME=nas
PRESEED_DOMAIN=home.lan
Here's the build script:
#!/bin/bash
set -euo pipefail
source .env
# Extract the Debian 13 netinst ISO
mkdir -p ./iso-extract
xorriso -osirrox on -indev debian-13-amd64-netinst.iso -extract / ./iso-extract
# Inject the preseed file
cp preseed.cfg ./iso-extract/
# Configure GRUB for automatic boot
cat > ./iso-extract/boot/grub/grub.cfg << 'GRUB'
set timeout=3
menuentry "Debian Auto Install" {
linux /install.amd/vmlinuz auto=true priority=critical \
preseed/file=/cdrom/preseed.cfg
initrd /install.amd/initrd.gz
}
GRUB
# Rebuild the UEFI-bootable ISO
xorriso -as mkisofs \
-o debian-nas-auto.iso \
-isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin \
-c isolinux/boot.cat \
-b isolinux/isolinux.bin -no-emul-boot \
-boot-load-size 4 -boot-info-table \
-eltorito-alt-boot \
-e boot/grub/efi.img -no-emul-boot \
-isohybrid-gpt-basdat \
./iso-extract
First time dealing with xorriso? Yeah, that's a lot of flags. Welcome to the club.
The preseed file
This is the magic. Preseed is basically text that tells the installer: "use this IP, set this hostname, create this user, done." Zero interaction. Here are the key sections:
# preseed.cfg - key sections
# Locale and keyboard
d-i debian-installer/locale string fr_FR.UTF-8
d-i keyboard-configuration/xkb-keymap select fr(latin9)
d-i time/zone string Europe/Paris
# Static network
d-i netcfg/choose_interface select auto
d-i netcfg/disable_autoconfig boolean true
d-i netcfg/get_ipaddress string 192.168.1.50
d-i netcfg/get_netmask string 255.255.255.0
d-i netcfg/get_gateway string 192.168.1.1
d-i netcfg/get_nameservers string 192.168.1.1
d-i netcfg/get_hostname string nas
d-i netcfg/get_domain string home.lan
d-i netcfg/confirm_static boolean true
# Partitioning - targets the internal USB drive (2-8 GB)
d-i partman-auto/disk string /dev/sda
d-i partman-auto/method string regular
d-i partman-auto/choose_recipe select atomic
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
# User accounts
d-i passwd/root-login boolean true
d-i passwd/user-fullname string NAS Admin
d-i passwd/username string nasadmin
# Minimal packages
tasksel tasksel/first multiselect standard
d-i pkgsel/include string sudo openssh-server python3 python3-apt \
ca-certificates bash-completion
d-i pkgsel/upgrade select full-upgrade
One thing: the partitioning targets /dev/sda in the 2-8 GB range. This makes sure you won't accidentally wipe a data drive. (Spoiler: I learned this the hard way. Not personally, but I know someone who did.)
Post-installation bootstrap
Once Debian finishes installing, a late_command in the preseed sets up the essentials:
- SSH key for
nasadmin(password-free login) - Shadow file fix (so the account actually works)
- SSH in key-only mode
- A custom systemd service that triggers Ansible on first boot
# late_command in the preseed
d-i preseed/late_command string \
in-target mkdir -p /home/nasadmin/.ssh; \
in-target sh -c 'echo "ssh-ed25519 AAAA... admin@workstation" \
> /home/nasadmin/.ssh/authorized_keys'; \
in-target chown -R nasadmin:nasadmin /home/nasadmin/.ssh; \
in-target chmod 700 /home/nasadmin/.ssh; \
in-target chmod 600 /home/nasadmin/.ssh/authorized_keys; \
in-target cp /target/tmp/provision.service \
/target/etc/systemd/system/provision.service; \
in-target systemctl enable provision.service
The provision.service wakes up on first boot, waits for the network, then runs Ansible. The NAS configures itself. Pretty neat.
Testing before flashing
Before you start flashing USB drives left and right (which gets annoying if the ISO is broken), test it in a VM first. QEMU/KVM works great:
# Create a 4 GB virtual disk
qemu-img create -f qcow2 test-nas.qcow2 4G
# Launch the VM
qemu-system-x86_64 \
-m 2048 \
-enable-kvm \
-bios /usr/share/ovmf/OVMF.fd \
-cdrom debian-nas-auto.iso \
-drive file=test-nas.qcow2,format=qcow2 \
-nic user,hostfwd=tcp::2222-:22
Verify the installation runs clean. Test SSH from your host:
ssh -p 2222 nasadmin@localhost
Works? Good. Now flash the ISO onto a real USB drive with dd and boot your NAS from it.
Done.
Automation isn't a luxury - it's reliability. If my system drive fails tomorrow, I'm back up in 15 minutes flat. And since it's all automated, I can run it a hundred times without breaking anything. Then Ansible takes over and configures the rest - storage, services, security.
Debian NAS from scratch series — This article is part of a complete series on building a Debian NAS.
Previous: Migrating Synology data to a Debian NAS without losing anything | Next: Docker on NAS: network architecture and best practices