To reliably remote login to a Raspberry Pi 5 for headless embedded projects, bypass local network NAT issues by using Tailscale over standard SSH, and wire a GPIO heartbeat LED to confirm network and daemon state without needing a monitor. This guide targets the Raspberry Pi 5 (8GB variant) running Raspberry Pi OS (Bookworm or newer), providing the exact hardware, decision frameworks, and debugging steps to keep your remote nodes online.

The Remote Access Decision Matrix

When deploying a Pi 5 in a closet, attic, or remote job site, local mDNS (raspberrypi.local) quickly fails if you cross VLANs or leave your home network. Port forwarding is a security liability. Here is the decision path for choosing your remote login protocol:

Method Pros Cons Best For
Local SSH (mDNS) Zero config, no internet required Fails across subnets/VLANs, breaks on mobile hotspots Bench testing only
Router Port Forwarding Direct IP access from anywhere Exposes port 22 to the internet, fails behind CGNAT Legacy systems (not recommended)
Cloudflare Tunnel Hides IP, great for web dashboards Complex SSH routing via cloudflared client Web-hosted sensor dashboards
Tailscale (SSH) WireGuard NAT traversal, auto DNS, free for hobbyists Requires internet connection to establish initial handshake Default Pick: Headless embedded nodes
Decision Verdict: Use Tailscale. It creates a virtual mesh network, assigning your Pi a static 100.x.y.z IP that you can SSH into from your phone or laptop anywhere in the world, completely bypassing router firewall rules. Install it via curl -fsSL https://tailscale.com/install.sh | sh.

Parts List & Hardware Spec Sheet

Headless Pi 5 deployments demand strict power and thermal management. The Pi 5 spikes to 12W+ under load; undervoltage will cause silent SD card corruption and drop your SSH session.

Component Exact Variant / Model Why This Specific Part
Compute Board Raspberry Pi 5 (8GB RAM) 8GB prevents OOM kills when running Docker + Tailscale + Python sensors.
Power Supply Official 27W USB-C PD (5V/5A) Third-party 5V/3A supplies trigger USB current limiting on the Pi 5.
Storage Samsung PRO Plus 128GB (A2 Rating) A2 rating ensures high random I/O for OS logging; prevents boot hangs.
Thermal Official Active Cooler Piezo fan keeps SoC under 60°C; passive cases throttle the Pi 5 at 80°C.
Indicator LED 5mm Green LED + 330Ω Resistor Visual heartbeat for SSH/Network status when headless.

Headless Wiring & GPIO Status Code

When a headless Pi loses network, you cannot SSH in to check systemctl status ssh. We wire a physical status LED to GPIO 17 to blink based on local SSH daemon health.

Pin Mapping Table

Function Pi 5 GPIO (BCM) Physical Pin Wiring Notes
Status LED Anode GPIO 17 Pin 11 Wire through 330Ω resistor to LED.
Status LED Cathode GND Pin 9 Common ground.

Note: On Raspberry Pi OS Bookworm, the RPi.GPIO library is deprecated. You must use gpiozero with the lgpio backend. Install via terminal: sudo apt install python3-gpiozero python3-lgpio.

SSH Heartbeat Python Script

This script checks if port 22 (SSH) is actively listening on the local loopback interface. Save as ssh_monitor.py and run it as a systemd service.

import time
import socket
from gpiozero import LED
from signal import pause

# Pin definitions (BCM numbering)
STATUS_LED_PIN = 17
SSH_PORT = 22

led = LED(STATUS_LED_PIN)

def is_ssh_listening():
    """Checks if the SSH daemon is accepting connections locally."""
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(1.0)
    try:
        result = sock.connect_ex(('127.0.0.1', SSH_PORT))
        return result == 0
    except socket.error:
        return False
    finally:
        sock.close()

try:
    print(f"Monitoring SSH daemon on GPIO {STATUS_LED_PIN}...")
    while True:
        if is_ssh_listening():
            # Slow blink: SSH is up and ready for remote login
            led.blink(on_time=1.5, off_time=1.5, background=False)
        else:
            # Fast blink: SSH daemon is down or crashed
            led.blink(on_time=0.1, off_time=0.1, background=False)
        time.sleep(2)

except KeyboardInterrupt:
    led.off()
    print("\nMonitor stopped by user.")
except Exception as e:
    led.off()
    print(f"Hardware or socket error: {e}")
Pro Tip: If the LED is solid ON or completely OFF instead of blinking, your gpiozero backend is failing to claim the pin. Verify lgpio is installed and that no other process (like Home Assistant) has locked GPIO 17.

Debugging Network & SSH Failures

When you attempt to remote login and the terminal hangs or rejects you, do not immediately reboot the Pi. Match your exact terminal output to the ranked causes below.

Error 1: ssh: connect to host 100.x.y.z port 22: Connection refused

What it means: The network path is valid (Tailscale/local IP is reachable), but the Pi is actively rejecting the TCP handshake on port 22.
Ranked Causes:

  1. SSH is disabled in the OS. Raspberry Pi OS ships with SSH disabled by default for security. Fix: Create an empty file named ssh (no extension) in the boot partition of the SD card, or run sudo raspi-config via a connected monitor to enable it.
  2. sshd.service crashed. Often caused by a malformed /etc/ssh/sshd_config file after an edit. Fix: Plug in a keyboard/monitor and run sudo sshd -t to test the config syntax.
  3. Firewall rules (UFW/iptables) blocking port 22. Fix: Run sudo ufw allow 22/tcp.

Error 2: ssh: connect to host 192.168.1.50 port 22: Connection timed out

What it means: Your computer sent the SYN packet, but never received a SYN-ACK. The Pi is either offline, on a different subnet, or the network dropped.
Ranked Causes:

  1. Stale DHCP lease / Wrong IP. The router assigned a new IP after a reboot. Fix: Log into your router's admin panel and check the DHCP lease table for the Pi's MAC address, or use its Tailscale IP instead.
  2. Wi-Fi power management dropping the link. The Pi's Wi-Fi chip goes to sleep. Fix: Disable Wi-Fi power save: sudo iwconfig wlan0 power off.
  3. Kernel panic or brownout. The Pi 5 crashed due to a voltage drop. Fix: Check your physical LED. If it's dead, check the power supply. Ensure you are using the 27W 5A supply, not a standard phone charger.

Error 3: WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

What it means: The cryptographic fingerprint of the Pi doesn't match what your laptop has saved in ~/.ssh/known_hosts.
Ranked Causes:

  1. You re-flashed the SD card. The OS generated new SSH keys. Fix: Run ssh-keygen -R 100.x.y.z on your host machine to clear the old key.
  2. IP address collision. Another device on your network claimed the Pi's old IP. Fix: Verify the MAC address in your router's ARP table.

The First 3 Things to Check When It Fails

Before pulling the power cable, execute this exact diagnostic sequence:

  1. Ping the Tailscale IP, not the local IP. Run ping 100.x.y.z. If it replies, your network is fine; the issue is isolated to the SSH daemon (see Error 1).
  2. Check the physical Ethernet link lights. The Pi 5 has amber/green LEDs on the RJ45 jack. If they are dark, the switch port is dead or the cable is unseated. Wi-Fi debugging is impossible if the RF environment is saturated.
  3. Read the router's ARP table. If the Pi's IP doesn't appear in the router's active client list, the Pi has completely dropped off the network layer (crash, brownout, or Wi-Fi sleep).

Extending or Simplifying the Build

Depending on your deployment environment, you may need to scale this architecture up or strip it down.

How to Simplify (The Local-Only Build)

If this Pi is strictly for a local home lab and you don't want to manage Tailscale accounts:

  • Skip the Tailscale installation.
  • Assign a Static DHCP Reservation in your router (e.g., 192.168.1.50) tied to the Pi's MAC address.
  • Rely entirely on ssh pi@raspberrypi.local using mDNS.
  • Trade-off: You lose remote access when you leave your house, and mDNS will fail if you isolate IoT devices on a separate VLAN without an mDNS reflector (like Avahi).

How to Extend (The Fleet Management Build)

If you are deploying five or more Pi 5 nodes across different physical locations (e.g., remote weather stations or edge computing nodes):

  • Add MQTT Telemetry: Instead of just blinking an LED, have the Python script publish the SSH daemon state to an MQTT broker (e.g., Mosquitto) on a home/nodes/pi5_01/status topic.
  • Use Tailscale SSH: Instead of managing local Linux passwords or SSH keys, enable Tailscale's built-in SSH daemon (tailscale set --ssh). This allows you to enforce access policies via the Tailscale web dashboard and automatically rotates keys.
  • Automate OS Patching: Install unattended-upgrades to handle security patches automatically, ensuring your remote nodes don't become vulnerable while sitting headless in a closet.

By combining Tailscale for network traversal, a physical GPIO heartbeat for immediate visual diagnostics, and strict power/thermal hardware selection, your Raspberry Pi 5 remote login setup will survive the realities of embedded deployment without requiring a truck roll to reboot it.