Archinstall Web Server Setup: Hardening a 10-Year NUC
Can an old 17-watt box from 2013 with a 1.1 GHz Celeron still run a hardened, encrypted web server in 2026? Yes - if you do not fight the hardware.
I had an Intel NUC Kit DCCP847DYE gathering dust under my desk. It has two slow cores, 8 GB of DDR3 memory, and an mSATA SSD. I wanted to turn it into an encrypted, self-hosted web server without exposing my home network to the entire internet.
Installing Arch Linux used to mean typing thirty manual disk partitioning and cryptsetup commands from memory. With the redesigned Archinstall 4.x, the installer has a completely overhauled Textual interface with built-in toggles for Unified Kernel Images, Btrfs snapshots, and firewalls.
Here is how to set up the installer for Polish localization, full disk encryption, and production-grade security on modest hardware.
Step 1: Navigating Archinstall 4.x
Boot into the latest Arch Linux live ISO and run the guided installer:
1
archinstall
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Archinstall (Textual TUI)
1. Archinstall language [en]
2. Locales [pl, pl_PL.UTF-8]
3. Mirrors and repositories [Poland, multilib: off]
4. Disk configuration [Btrfs, LUKS2, Snapper]
5. Swap [zram: enabled]
6. Bootloader [systemd-boot, UKI: on]
7. Kernels [linux-hardened]
8. Additional firmware [intel-ucode]
9. Hostname [nucbox]
10. Authentication [root disabled, user: sudo]
11. Profile [Minimal]
12. Applications [Firewall: UFW]
13. Network configuration [NetworkManager]
14. Pacman [Parallel: 5]
15. Additional packages [caddy, cloudflared, apparmor]
16. Timezone [Europe/Warsaw]
17. Automatic time sync (NTP) [True]
Earlier guides talk about the old menu, but version 4.x organizes settings into cleaner groups.
Locales and console fonts
Enter the Locales submenu:
-
Keyboard layout: Pick
pl. -
Locale language: Pick
pl_PL.UTF-8for full Polish system messages, oren_US.UTF-8if you prefer terminal logs in English. -
Console font: Select
Lat2-Terminus16oreurlatgr.
Without a Latin-2 font, Polish letters like ą, ć, and ł display as unreadable hollow blocks in the virtual console before your display manager loads.
Partitioning, LUKS, and Snapper
Enter the Disk configuration submenu:
- Select your mSATA drive (
/dev/sda). - Choose Use a best-effort default partition layout with
btrfs. - In Btrfs snapshots, select
Snapper. Archinstall configures automatic subvolume rollbacks for you. - In Disk encryption, choose
LUKS, enter your passphrase, and leave the default iteration time at 2000 ms.
Bootloader and hardened kernel
- Under Bootloader, select
systemd-bootand set Unified kernel images (UKI) toEnabled. UKIs combine the kernel, initramfs, and boot parameters into one cohesive EFI binary. - Under Kernels, select
linux-hardenedfor memory exploit mitigations and user-namespace restrictions. - In Applications, toggle Firewall to
UFW.
Hit Install and let the script download and configure your base system.
Step 2: The hardware reality of an older Celeron
Once the system reboots into your fresh installation, you must address two hardware limitations of the Celeron 847 processor:
- No AES-NI: This CPU has no hardware AES acceleration.
- No TPM 2.0 or modern Secure Boot: The 2013 BIOS does not support automated TPM key sealing.
Testing the cipher overhead
Check the difference software AES makes on your CPU:
1
cryptsetup benchmark
1
2
3
4
# Tests are approximate using memory only.
# Algorithm | Key | Encryption | Decryption
aes-xts 256b 84.2 MiB/s 86.1 MiB/s
chacha20-poly1305 256b 212.4 MiB/s 214.0 MiB/s
Without AES-NI, software AES caps disk throughput at roughly 85 MiB/s while running both cores hot. For secondary drives or backups on older CPUs, the modern Adiantum cipher (xchacha12,aes-adiantum-plain64) gives near native speeds at low CPU overhead.
Firmware protection
Because there is no TPM chip to bind the boot sequence, guard physical access through your firmware:
- Press
F2at startup to open the Intel Visual BIOS. - Set a strong Supervisor/Admin password.
- Disable boot from external USB devices and network PXE.
Step 3: Unlocking LUKS with a YubiKey (FIDO2)
Typing a 30-character encryption passphrase on every reboot gets old fast. Because the NUC lacks a TPM 2.0 chip, the cleanest modern alternative is binding LUKS2 to a YubiKey via FIDO2.
First, install the user-space library:
1
sudo pacman -S libfido2
1
2
3
4
resolving dependencies...
looking for conflicting packages...
Packages (1) libfido2-1.15.0-1
Total Installed Size: 0.41 MiB
Plug in your YubiKey and bind it to the encrypted partition:
1
sudo systemd-cryptenroll --fido2-device=auto /dev/sda2
1
Enrolled FIDO2 token on keyslot 1.
Your original password stays safe in keyslot 0 as a recovery fallback.
Configuring early boot hooks
To let systemd unlock the device before mounting root, switch your initramfs hooks to systemd and sd-encrypt in /etc/mkinitcpio.conf:
1
HOOKS=(base systemd autodetect keyboard sd-vconsole modconf block sd-encrypt filesystems fsck)
Point the initramfs to your FIDO2 device in /etc/crypttab.initramfs:
1
root UUID=4a91b6e4-802c-47ea-a06f-12903487abcd - fido2-device=auto
Regenerate your boot images:
1
sudo mkinitcpio -P
1
2
==> Building image from preset: /etc/mkinitcpio.d/linux-hardened.preset
-> Successfully generated image: '/boot/initramfs-linux-hardened.img'
When you power on the machine, the YubiKey LED flashes. Touch the gold button, and the drive decrypts instantly. If the key is not plugged in, boot waits briefly and drops back to the standard password prompt.
Step 4: Enabling AppArmor and the firewall
Turn on Mandatory Access Control to isolate system daemons:
1
sudo systemctl enable --now apparmor.service
1
Created symlink /etc/systemd/system/multi-user.target.wants/apparmor.service -> /usr/lib/systemd/system/apparmor.service.
Activate the UFW firewall installed by Archinstall:
1
2
3
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable
1
Firewall is active and enabled on system startup
Step 5: Hosting safely with Cloudflare Tunnel
Opening ports 80 and 443 on your home router exposes your residential IP address to automated botnets and port scanners.
Instead, route traffic through an outbound encrypted tunnel:
1
cloudflared tunnel login
1
2
3
A browser window should have opened. If not, open this URL:
https://dash.cloudflare.com/argotunnel?callback=...
Successfully fetched origin cert.
Create a tunnel named nuc-web:
1
cloudflared tunnel create nuc-web
1
Created tunnel nuc-web with id 4a91b6e4-802c-47ea-a06f-12903487abcd
Map your domain to the local web server in ~/.cloudflared/config.yml:
1
2
3
4
5
6
7
tunnel: 4a91b6e4-802c-47ea-a06f-12903487abcd
credentials-file: /etc/cloudflared/4a91b6e4-802c-47ea-a06f-12903487abcd.json
ingress:
- hostname: yourdomain.com
service: http://localhost:80
- service: http_status:404
Route the DNS record and start the tunnel as a background service:
1
2
cloudflared tunnel route dns nuc-web yourdomain.com
sudo systemctl enable --now cloudflared
1
Created symlink /etc/systemd/system/multi-user.target.wants/cloudflared.service -> /usr/lib/systemd/system/cloudflared.service.
Your website is live over HTTPS with zero open router ports.
Step 6: Sandboxing the Caddy web server
Caddy serves static files with negligible memory overhead. Configure /etc/caddy/Caddyfile:
:80 {
root * /var/www/yoursite
file_server
encode zstd gzip
}
Lock down the process using systemd isolation flags by editing the service overrides:
1
sudo systemctl edit caddy
Add these security boundaries:
1
2
3
4
5
6
7
[Service]
ProtectSystem=strict
ProtectHome=yes
PrivateDevices=yes
PrivateTmp=yes
NoNewPrivileges=yes
ReadOnlyPaths=/var/www/yoursite
Start Caddy:
1
sudo systemctl enable --now caddy
1
Created symlink /etc/systemd/system/multi-user.target.wants/caddy.service -> /usr/lib/systemd/system/caddy.service.
Even if an attacker finds an exploit in your web server, systemd blocks access to user directories, block devices, and root binaries.
Step 7: Keeping a rolling-release server up to date
Running a rolling-release distribution on an unattended home server requires a balance between staying patched and avoiding surprise breakages.
Because we chose Btrfs and Snapper in Archinstall, we can add a foolproof safety net.
Automatic snapshots before every update
Install snap-pac to take pre- and post-transaction snapshots whenever pacman modifies the system:
1
sudo pacman -S snap-pac
1
2
Packages (1) snap-pac-3.0.1-2
Total Installed Size: 0.03 MiB
If a new kernel or glibc update ever breaks boot or networking, you can roll back to the exact snapshot taken seconds before the upgrade.
Checking updates safely
Avoid unattended automated upgrades on Arch. Instead, use checkupdates to safely check for pending patches without touching your live package databases:
1
2
sudo pacman -S pacman-contrib
checkupdates
1
2
3
linux-hardened 6.11.2.hardened1-1 -> 6.11.3.hardened1-1
caddy 2.8.4-1 -> 2.8.5-1
cloudflared 2024.9.1-1 -> 2024.10.0-1
When you are ready to apply updates, run standard upgrades manually:
1
sudo pacman -Syu
Cleaning the package cache
Pacman keeps every downloaded .pkg.tar.zst file in /var/cache/pacman/pkg/. On a small mSATA SSD, this cache will eventually fill your drive.
Enable the systemd timer to trim old package versions automatically every week:
1
sudo systemctl enable --now paccache.timer
1
Created symlink /etc/systemd/system/timers.target.wants/paccache.timer -> /usr/lib/systemd/system/paccache.timer.
Knowing when to reboot
After applying updates, check whether the running kernel or critical daemons need a restart:
1
2
sudo pacman -S needrestart
sudo needrestart
1
2
3
Scanning processes...
Scanning candidates...
NEEDRESTART: Kernel update detected. Reboot required.
Reboot when required, tap your YubiKey to unlock the drive, and your sandboxed web services will resume immediately.
Summary
- Archinstall 4.x makes hardened setups practical: UKIs, Snapper subvolumes, and UFW firewalls are now simple menu toggles.
-
Console fonts matter: Pick
Lat2-Terminus16during setup so Polish diacritics render cleanly in the TTY. - YubiKey replaces typing passphrases: Enrolling FIDO2 via systemd-cryptenroll and the sd-encrypt hook gives instant hardware-touch unlocking with password fallback.
- Respect old hardware: A 1.1 GHz Celeron without AES-NI struggles with heavy encryption algorithms, but runs lightweight tools like Caddy and Cloudflare Tunnel smoothly.
- Never open inbound router ports: Use an outbound tunnel to protect your home network while keeping the site fast and responsive.
- Update with a safety net: Pair snap-pac with Snapper for automatic pre-upgrade snapshots, and use paccache.timer to prevent your mSATA SSD from running out of space.
Keep your old hardware out of the landfill - a silent 15-watt box makes an ideal private server when configured with care.
Resources
- Archinstall GitHub Repository - Source code and documentation for the Archinstall Textual TUI release.
- ArchWiki: dm-crypt and Full Disk Encryption - Comprehensive guide to configuring LUKS block devices on Arch Linux.
- ArchWiki: systemd-cryptenroll - Official Arch Linux guide for enrolling FIDO2 tokens into LUKS2 volumes.
- ArchWiki: System Maintenance - Official guide on pacman cache maintenance, news review, and package upgrades.
- Caddy Server Repository - Official repository for the Caddy web server.
-
Cloudflare Tunnel Documentation - Source code and configuration guides for
cloudflared.
