$ cat /blog/four-raspberry-pis-baseline.mdx

·10 min read

Four Raspberry Pis from an abandoned project: how I finally put them to work

Three years ago I bought Raspberry Pis 'to learn Kubernetes' and never opened the boxes. This is what I did with them once I finally admitted that wasn't happening — and the repeatable baseline that means I never have to think about Pi setup again.

There are three Raspberry Pi 4B 2GB models and one Pi 4B 8GB in my homelab, and every one of them was originally bought to “learn Kubernetes on Pi.” That plan lasted a weekend. The Pis then spent two and a half years in a drawer, developing a small pile of guilt around them.

This post is how I stopped ignoring the drawer and built something useful with what was inside — plus the setup process I finally got repeatable so I never dread setting up a Pi again. (If you want the wider context — the two mini PCs, the six goals, why Ansible and Proxmox — start with the origin story.)

If you’re new to Raspberry Pis: they’re credit-card-sized ARM64 computers that run Linux, boot from an SD card, sip a few watts of power, and cost less than a video game. They’re a homelab staple because you can leave a bunch of them plugged in 24/7 without noticing on your electricity bill.

The four Pis

  • 3× Raspberry Pi 4B 2GB — the three “workhorse” Pis. Bought in 2022 for the abandoned Kubernetes project.
  • 1× Raspberry Pi 4B 8GB — added later once I had a real plan. Reserved for the one workload I knew would need more RAM.

If you have a similar pile of unused Pi in a drawer, this post is aimed at you.

Why use Pis at all when I already had two mini PCs?

Reasonable question. If the mini PCs can run VMs, why bother with Pis? Three reasons:

1. Power draw. A Pi 4B idles at around 3–4 watts. My mini PCs idle at ~15 W each. For workloads that need to be always-on but don’t need much compute — DNS, home automation — the electricity math over three years is not trivial. Two Pis running DNS 24/7 costs a lot less on the power bill than the same workload as a VM.

2. Physical separation. If I unplug a mini PC to move it, I lose the VMs on it. If DNS is a Pi on a separate power outlet and separate ethernet port, then “I need to move a PC around” doesn’t take down the whole house’s internet.

3. Blast radius. The mini PCs are where I experiment. Experiments break. I don’t want DNS or Home Assistant on the box where I’m currently trying to make a Docker network do something it wasn’t designed to do.

The Pis and the mini PCs solve different problems. The Pis get the “always-on, low-blast-radius” workloads. The mini PCs get everything else.

The mistake I made three times before I stopped making it

Every time I set up a Pi in 2023 and 2024, I did it slightly differently:

  • First time: Raspberry Pi OS Lite, raspi-config, hand-configured Wi-Fi, hand-installed everything, no notes.
  • Second time: same, but I remembered halfway through that I wanted a specific username.
  • Third time: I’d forgotten what I did the first time. Started over with a slightly different setup.

Six months later, when the SD card in Pi #2 died and I had to rebuild it, I had no idea how I’d originally set it up. I remembered what it was running but not how it got there. That was the day I promised future-me: write it down. Make it repeatable. Never set up a Pi manually again.

This is the writing-it-down. The steps below are the six-step baseline that gets any Pi from “unboxed” to “Ansible can take over.” One SSH session. Then never SSH by hand again.

The plan

Any Pi in my homelab gets the same six-step baseline before it does anything specific. The specific service on top (Pi-hole, Home Assistant, whatever) is a separate post per service. This post is only the baseline — the thing every Pi post assumes is already done.

The end state we’re aiming for:

  • SSH works as a non-root user
  • sudo works without a password prompt (Ansible needs this)
  • The Pi has a static IP on the LAN
  • Password-based login is disabled — SSH keys only

Once those four things are true, any Ansible playbook can run against the Pi unattended. From there, “make this Pi a DNS server” is a playbook away, not an SSH session.

Step 1: Flash the SD card with Pi Imager

(Or an SSD, if the workload is going to write a lot. There’s a whole section further down on why — skip ahead if that’s you.)

Download Raspberry Pi Imager on your regular computer. It’s the official flasher, and it does most of the first-boot work for you.

In Pi Imager:

  • OS: Raspberry Pi OS Lite (64-bit). “Lite” means no desktop — you don’t want a desktop on a headless Pi.
  • Storage: pick your SD card.
  • Click the settings gear (advanced options). This is where the magic happens.

In advanced options, fill in:

  • Hostname: pick what this Pi is going to be called. Final name. Renaming later means edits in several places.
  • Enable SSH: yes. Choose allow public-key authentication only. Paste your regular computer’s SSH public key (cat ~/.ssh/id_ed25519.pub or id_rsa.pub). If you don’t have an SSH key, generate one first (ssh-keygen -t ed25519).
  • Set username and password: use a username your Ansible tree expects — I use homelab because it’s clear what the account is for. Set a password too; you’ll type it exactly once.
  • Configure wireless LAN: skip if wired (recommended for anything that matters).
  • Set locale settings: yes, do this. Skipping it means your Pi will have a UK keyboard layout and you’ll type | and get #.

Write. Wait a couple of minutes. Eject when it’s done.

Step 2: First boot — find the Pi on the network

Plug the SD card into the Pi. Plug ethernet in. Plug power in last (Pi 4s don’t have a power button; power = booted).

Wait about 30–45 seconds for first boot. Then find it:

Easy path: if you set the hostname in Pi Imager, <hostname>.local should just work:

ssh [email protected]

Fallback: look at your router’s DHCP client list. Fresh Pi will show up with a fresh MAC address. Pi 4B MACs typically start with dc:a6:32 or e4:5f:01; older Pis (1/2/3) use b8:27:eb.

Type the password from Pi Imager when prompted. This is the only time you’ll type that password.

Step 3: Static IP (the tricky one)

You want the Pi’s IP to stay the same forever. Options:

  • Router-side DHCP reservation (recommended): tell your router “always give this MAC address this IP.” Set-and-forget. All configuration in one place.
  • Pi-side static IP: configure it on the Pi itself.

I do both — belt and suspenders — but if you’re just starting, do the router-side one. It’s easier.

If you’re doing the Pi-side version (on Debian Bookworm/Trixie, which is what modern Raspberry Pi OS is based on), the tool is nmcli. One command sets everything:

sudo nmcli con mod 'Wired connection 1' \
  ipv4.method manual \
  ipv4.addresses <target-ip>/24 \
  ipv4.gateway <router-ip> \
  ipv4.dns '<dns1> <dns2>' \
  connection.autoconnect yes \
  && sudo systemd-run --on-active=3sec --unit=nm-relink \
     bash -c 'nmcli con down "Wired connection 1" && nmcli con up "Wired connection 1"'

Why the systemd-run --on-active=3sec at the end?

If you just run sudo nmcli con up after changing the IP, your SSH session dies mid-command because the interface is being reconfigured. The command hangs, you don’t know what state the Pi is in, and you might as well pull the plug.

systemd-run --on-active=3sec schedules the interface bounce to happen three seconds from now. That gives your command time to return, gives your SSH session time to close cleanly, and then the interface flips. Reconnect on the new IP.

Fun trick. Wish someone had told me about it before I unplugged three Pis mid-config in a row.

Step 4: Passwordless sudo (Ansible needs it)

Ansible drives things via sudo and cannot type a password. You need to allow your user to sudo without one:

echo 'homelab ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/homelab-nopasswd
sudo chmod 0440 /etc/sudoers.d/homelab-nopasswd

Two things to get right here:

  • Don’t edit /etc/sudoers directly. Drop a file under /etc/sudoers.d/ instead. If you make a syntax error editing /etc/sudoers, you might lock yourself out of sudo entirely. Sub-files are safer — bad syntax means sudo skips that file instead of refusing everything.
  • Mode 0440 matters. World-readable sudoers files sometimes get ignored silently by strict sudo configs. The chmod avoids that.

Type your password one last time when sudo prompts. From here on, this Pi never asks you for a password again.

Step 5: Confirm SSH key access

You already pasted a key in Pi Imager’s user-data, so key auth should already work from that machine. Double-check:

ssh homelab@<pi-ip> 'whoami'

If it prints homelab with no password prompt, you’re good.

If you have a second control machine you want to also SSH from:

ssh-copy-id homelab@<pi-ip>

This is idempotent — if the key is already there, it says “already installed.”

Step 6: Verify Ansible can take over

The whole point of this baseline is that Ansible can now drive the Pi unattended. Prove it before you commit:

ssh -o BatchMode=yes homelab@<pi-ip> 'sudo -n whoami'

Two things this checks:

  • BatchMode=yes disables all password prompts. If key-based SSH isn’t working, this fails immediately instead of silently prompting.
  • sudo -n runs sudo non-interactively. If NOPASSWD isn’t set up, this fails immediately instead of silently prompting.

The remote command should print root. If it does, you’re done. Any Ansible playbook can now run against this Pi.

If you see anything else — password prompt, permission denied, blank output — don’t proceed. The baseline is broken and Ansible will fail in confusing ways later. Fix it now.

The seventh step: don’t die on an SD card

This isn’t in the six steps above, and it’s tempting to skip. Don’t. It’s the difference between a Pi you set up once and a Pi you set up every six months.

SD cards die. Especially the cheap ones. Especially in workloads that write a lot — Home Assistant is famous for burning through SD cards in 6–12 months because it constantly writes state, logs, and database updates. If you’re running anything that touches disk 24/7 (a database, a container that logs verbosely, Home Assistant, an ELK stack) on an SD card, you’re on a countdown you can’t see.

Two Pi 4B’s in this homelab boot from USB-SSD instead of SD card:

  • hass (the 8 GB Pi) — Home Assistant absolutely chews through SD cards. Booting from a cheap USB3-to-SATA SSD has been rock solid for 18 months.
  • Anything with database writes.

The Pi 4B needs a bootloader update to boot from USB — one sudo rpi-eeprom-config --edit and a BOOT_ORDER=0xf14 line — but the setup is otherwise identical to the SD flow. Pi Imager just writes to the SSD instead of the SD card.

If your Pi is running anything write-heavy 24/7, spend the small extra on a cheap SSD. Way cheaper than another Pi-worth of recovery time when the SD card dies at 2am on a Saturday.

Done. What now?

You now have a Pi that:

  • Answers to SSH on a static IP with just an SSH key
  • Runs sudo without a password
  • Is password-login-off (Pi Imager did that)

That is the baseline. Every Pi-specific post from here on assumes this is done — it’s the “shows up in the office and can take instructions” step.

The next post picks a service and builds it on top. First up in the service series will probably be the DNS pair — two of these baseline Pis becoming redundant Pi-hole + Unbound resolvers. That’s where the homelab starts feeling less like a pile of parts and more like something that actually saves you money every month.

Stay tuned. Or don’t — the RSS feed is still there.


$ cd /blog  // all posts