<!--order=3-->


<h1>Headless Setup and Remote Management on Raspberry Pi 5</h1>
<p>Running Pi's headless — no monitor, no keyboard — is the right approach when they're deployed in the field or tucked away in an enclosure. This covers the full setup: pre-imaging configuration, SSH hardening, keeping the system updated remotely, and the tools that make managing several Pi's at once manageable.</p>

<h2>Pre-imaging with Raspberry Pi Imager</h2>
<p>Raspberry Pi Imager's advanced options (the gear icon, or Ctrl+Shift+X) are the cleanest way to configure a headless Pi before the first boot. Set these before writing:</p>

<table>
  <thead><tr><th>Setting</th><th>What to set</th><th>Why</th></tr></thead>
  <tbody>
    <tr><td>Hostname</td><td>Something specific (e.g., <code>pizero-north</code>)</td><td>Avoids hostname collisions on the network; easier to find with mDNS</td></tr>
    <tr><td>SSH</td><td>Enable with public key</td><td>Paste your <code>~/.ssh/id_ed25519.pub</code> — no password needed</td></tr>
    <tr><td>Username/password</td><td>Set a non-default user</td><td>Default "pi" is a known target</td></tr>
    <tr><td>WiFi</td><td>SSID + password (if using wifi)</td><td>Written to <code>/etc/wpa_supplicant/wpa_supplicant.conf</code> on boot</td></tr>
    <tr><td>Locale/timezone</td><td>Set correctly</td><td>Correct timestamps in logs; RTC accuracy</td></tr>
  </tbody>
</table>

<h2>Finding the Pi on the Network</h2>
<pre>
# mDNS — works if your router/network supports it (most do)
$ ssh pi@hostname.local

# Scan the local subnet for new hosts
$ nmap -sn 192.168.1.0/24

# Check your router's DHCP lease table (fastest if you have router access)

# Set a static IP — edit /etc/dhcpcd.conf or use NetworkManager:
$ sudo nmcli con mod "Wired connection 1" \
    ipv4.addresses 192.168.1.50/24 \
    ipv4.gateway 192.168.1.1 \
    ipv4.dns "192.168.1.1" \
    ipv4.method manual
$ sudo nmcli con up "Wired connection 1"
</pre>

<h2>SSH Key Setup</h2>
<pre>
# On your local machine — generate a key if you don't have one
$ ssh-keygen -t ed25519 -C "jason@mymachine"

# Copy it to the Pi (if not done at imaging time)
$ ssh-copy-id -i ~/.ssh/id_ed25519.pub pi@raspberrypi.local

# Test key auth works, then disable password auth on the Pi:
# Edit /etc/ssh/sshd_config:
PasswordAuthentication no
PermitRootLogin no
MaxAuthTries 3

$ sudo systemctl reload sshd
</pre>

<h2>SSH Client Config (~/.ssh/config)</h2>
<p>With multiple Pi's, a client config saves a lot of typing:</p>
<pre>
Host pi5-home
    HostName 192.168.1.50
    User pi
    IdentityFile ~/.ssh/id_ed25519

Host pico-gateway
    HostName 192.168.1.51
    User pi
    IdentityFile ~/.ssh/id_ed25519

Host vim3
    HostName 192.168.1.52
    User jason
    IdentityFile ~/.ssh/id_ed25519

# Now: ssh pi5-home  (instead of ssh pi@192.168.1.50)
</pre>

<h2>Keeping the System Updated</h2>
<pre>
# Manual update
$ sudo apt update && sudo apt full-upgrade -y

# Automated unattended upgrades (security patches only — safe for headless)
$ sudo apt install unattended-upgrades
$ sudo dpkg-reconfigure unattended-upgrades   # select "Yes"

# Check what would be upgraded
$ sudo unattended-upgrade --dry-run --debug
</pre>

<h2>Monitoring System Health Remotely</h2>
<pre>
# Temperature and throttling
$ vcgencmd measure_temp
$ vcgencmd get_throttled    # 0x0 = healthy

# CPU frequency (throttled = lower)
$ vcgencmd measure_clock arm

# Memory
$ free -h

# Disk
$ df -h

# One-liner health check — useful in a quick alias
$ echo "Temp: $(vcgencmd measure_temp) | Throttle: $(vcgencmd get_throttled) | Mem: $(free -h | awk 'NR==2{print $3"/"$2}')"
</pre>

<h2>tmux for Persistent Sessions</h2>
<p>When running something long over SSH, tmux keeps the session alive if your connection drops:</p>
<pre>
# Install
$ sudo apt install tmux

# Basic usage
$ tmux new -s mysession      # start a named session
$ tmux attach -t mysession   # reattach after reconnect

# Inside tmux:
Ctrl+B D    # detach (session keeps running)
Ctrl+B C    # new window
Ctrl+B N    # next window
Ctrl+B ?    # help / key bindings

# List sessions
$ tmux ls
</pre>

<h2>Managing Multiple Pi's: GNU Parallel / pssh</h2>
<pre>
# Run a command on several Pi's at once
# Using a simple loop:
for host in pi5-home pico-gateway vim3; do
    ssh $host "sudo apt update && sudo apt -y upgrade" &
done
wait

# Or with pssh (parallel-ssh):
$ sudo apt install pssh
$ pssh -H "pi5-home pico-gateway vim3" -l pi "vcgencmd measure_temp"
</pre>

<h2>Sending Files</h2>
<pre>
# Copy a file to a Pi
$ scp ./myscript.py pi5-home:~/scripts/

# Copy a directory
$ scp -r ./project/ pi5-home:~/

# rsync — faster for subsequent syncs (only transfers changes)
$ rsync -avz ./project/ pi5-home:~/project/

# Pull logs back from the Pi
$ rsync -avz pi5-home:/var/log/myapp/ ./logs/
</pre>

<h2>References</h2>
<ul>
  <li><a href="https://www.raspberrypi.com/documentation/computers/remote-access.html" target="_blank" rel="noopener">Raspberry Pi Remote Access Documentation ↗</a></li>
  <li><a href="https://tmux.github.io" target="_blank" rel="noopener">tmux project ↗</a></li>
  <li><a href="https://man.openbsd.org/ssh_config.5" target="_blank" rel="noopener">ssh_config(5) man page ↗</a></li>
</ul>
