Chapter 9 of The Privacy Diet recommends a used mini PC and tells you to install Docker on it. This is the part in between: turning a bare machine into a server you can reach from your desk and forget about.
We’re using Ubuntu Server LTS. Not the desktop edition — a home server has no business running a display stack. LTS releases get five years of security updates, which matters when the whole point is a box that runs unattended.
What you need
- A machine to install onto. A used HP EliteDesk/ProDesk Mini, Lenovo ThinkCentre Tiny or Dell OptiPlex Micro is ideal — quiet, 15–35 W, and £80–£200 on eBay.
- A USB stick, 4 GB or larger. It will be erased.
- A keyboard and monitor for the install only. After that the machine runs headless.
- A wired ethernet connection. Don’t put a server on Wi-Fi if you can avoid it.
Write the installer to USB
Download the current Ubuntu Server LTS ISO from ubuntu.com/download/server, then verify it before you write it. Skipping verification means trusting your network and a mirror you’ve never heard of with the root of everything you’re about to build.
# Fetch the checksums and Canonical's signature over them
curl -LO https://releases.ubuntu.com/24.04/SHA256SUMS
curl -LO https://releases.ubuntu.com/24.04/SHA256SUMS.gpg
# Confirm the checksum file is genuinely Canonical's
gpg --keyid-format long --keyserver hkp://keyserver.ubuntu.com \
--recv-keys 0x46181433FBB75451 0xD94AA3F0EFE21092
gpg --verify SHA256SUMS.gpg SHA256SUMS
# Now check the ISO against it
sha256sum -c SHA256SUMS --ignore-missing
You want ubuntu-24.04.x-live-server-amd64.iso: OK. Anything else — stop and download again.
Write it to the stick. On Linux, identify the device carefully with lsblk first; dd will happily erase the wrong disk without a word of warning.
lsblk -o NAME,SIZE,MODEL,TRAN # find your USB stick — check the SIZE and MODEL
sudo dd if=ubuntu-24.04.2-live-server-amd64.iso of=/dev/sdX bs=4M status=progress oflag=sync
On Windows or macOS, use Balena Etcher instead.
Work through the installer
Boot from the USB (usually F12, F10 or Del at power-on to reach the boot menu). Most of the installer is self-explanatory. Four screens matter:
Network
The installer defaults to DHCP. A server needs a fixed address so your other machines, and your router’s DNS settings, can rely on it.
You have two ways to do this, and the better one is usually a DHCP reservation on your router — pin the address to the server’s MAC, and the server keeps asking for DHCP as normal. It keeps all your addressing in one place, which matters more than it sounds once you have a handful of services.
If you’d rather set it on the machine, edit the interface in the installer:
- Subnet:
192.168.1.0/24(match your own network) - Address:
192.168.1.50— pick something outside your router’s DHCP pool - Gateway:
192.168.1.1 - Name servers: your router, or a resolver from the DNS resolver comparison
Storage
Accept the guided full-disk layout, and untick “Set up this disk as an LVM group” unless you have a specific reason to want LVM. It adds a layer of indirection you’ll have to reason about later during every disk operation.
Leave encryption off for a machine that must boot unattended — full-disk encryption means typing a passphrase on a keyboard that isn’t plugged in every time the power blips. Encrypt the backups instead; that’s covered in the Restic walkthrough.
Profile
Pick a real username — not admin, not ubuntu. This becomes your SSH login.
SSH
Tick “Install OpenSSH server.” If you already have an SSH public key, this screen will import it from GitHub or Launchpad; otherwise we’ll copy one across in a moment.
Skip every “Featured Server Snap” on the next screen. Install what you need later, deliberately.
First boot
Reboot, pull the USB out, and from your normal machine:
ssh [email protected]
If you don’t have an SSH key yet, make one and copy it over — it’s the foundation for turning password logins off entirely:
ssh-keygen -t ed25519 -C "laptop -> homelab"
ssh-copy-id [email protected]
Update everything, then reboot into the new kernel:
sudo apt update && sudo apt full-upgrade -y
sudo reboot
Make it patch itself
An unattended server that never gets patched is worse than no server. Ubuntu ships the machinery; it just needs turning on.
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
Then tell it to also apply regular updates, not just security ones, and to reboot itself in the small hours when a kernel update needs it:
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
"${distro_id}ESMApps:${distro_codename}-apps-security";
"${distro_id}ESM:${distro_codename}-infra-security";
"${distro_id}:${distro_codename}-updates";
};
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";
Check it’s actually working:
sudo unattended-upgrades --dry-run --debug
Turn on the firewall
Ubuntu ships ufw, disabled. Default-deny inbound, allow SSH, and open ports only as you deploy things that need them.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from 192.168.1.0/24 to any port 22 proto tcp comment 'SSH from LAN only'
sudo ufw enable
sudo ufw status verbose
Restricting SSH to your LAN range is the single highest-value line there. Combined with the router hardening in Chapter 7 — no remote management, no UPnP — there is no path to this port from the internet at all.
Where this leaves you
A headless machine on a known address, patching itself, firewalled to the LAN, reachable over SSH. That’s the substrate.
Next: hardening SSH to key-only, then installing Docker and Compose — at which point you’re at the line where Chapter 9 picks up, and Vaultwarden is about twenty minutes away.