A Raspberry Pi 400 in the Browser: SSH via Cloudflare Tunnel
A Raspberry Pi 400 arrived at my desk a few weeks ago. It sat unused until Cloudflare launched Auditable Terminal, which turned out to be the perfect excuse to put the Pi to work. Auditable Terminal provides a full SSH client inside a browser tab: you authenticate through Cloudflare Access and get a terminal session from anywhere. Combined with Cloudflare Tunnel, the Pi 400 can be reached securely without opening any ports on the home firewall.
The result is a surprisingly smooth experience. From a browser URL, I can SSH into the Pi 400, authenticate via Cloudflare for Teams, and get a real terminal — complete with 256 colours, Unicode support, and consistent fonts across devices. The SSH session is even bookmarkable.
What follows is a practical walkthrough of how I connected a brand-new Pi 400 to Cloudflare and accessed it from anywhere.
Preparing the Pi
The Pi 400 plugs into a TV via HDMI and connects to the network over Ethernet. The OS ships pre-installed on the SD card, so boot time to the welcome screen is quick. A brand-new machine meant a batch of updates had to install before first login.
SSH is not enabled by default, so I ran sudo raspi-config from the command line. Under “3 Interface Options”, the “P2 SSH” option turns on the SSH server. This defaults to password authentication, so changing the well-known pi/raspberry credentials is essential. For this setup I stuck with password auth, but Cloudflare offers a short-lived certificate mechanism to replace it entirely.
Setting Up Cloudflare Tunnel
With SSH running on the Pi 400, the next step was making it reachable from outside the home network. Rather than punching a hole in the firewall, I used Cloudflare Tunnel — a free daemon called cloudflared that maintains outgoing connections from the Pi 400 to multiple Cloudflare data centers. Once authenticated to a Cloudflare account, the tunnel can be managed through Cloudflare for Teams.
I had a domain already configured on Cloudflare, which simplified things. The first unknown was the Pi’s architecture: running lscpu showed armv7l, which is 32-bit. Rather than building cloudflared from source, I downloaded it directly with wget.
Authentication followed the standard flow. Running cloudflared tunnel login on a headless machine prints a URL; I pasted it into a browser, logged into my Cloudflare account, and selected the domain for the tunnel. The daemon then generated a cert.pem file, and the dashboard confirmed the tunnel was registered.
I named the tunnel ‘terminal’ and set it up, but left it not running for the moment. The next piece was Cloudflare for Teams.
Configuring Cloudflare for Teams
I visited dash.teams.cloudflare.com and followed the setup guide, choosing the team name jgctesting. The documentation presents three choices at this point, and it wasn't immediately obvious that adding an application — not a location — was the correct path. For an SSH server on a self-hosted Raspberry Pi, the right option is a Self-Hosted Application.
I gave the application the name “Raspberry Pi 400” and set the URL to pi400.jgc.org. For identity, I chose the simplest option: a one-time PIN sent via email. The access rule allows anyone with an @jgc.org address to request a PIN; more complex zero-trust policies are possible but not needed for this demo. Finally, I enabled browser rendering, which activates the SSH access and Auditable Terminal.
Connecting the Pieces
At this stage I had cloudflared authorized on the Pi 400, Cloudflare for Teams configured for pi400.jgc.org, but nothing wired together yet. That meant editing a config file on the Pi and telling Cloudflare to route traffic to the tunnel.
The config file lives at /home/pi/.cloudflared/config.yml. I first obtained the tunnel ID from cloudflared tunnel list, then made three edits:
- tunnel: the tunnel ID
- credentials-file: a JSON file in the same directory, named after the tunnel ID
- hostname:
pi400.jgc.org
With the tunnel configured, I ran it and confirmed the connection. It established four connections to Cloudflare — two to Lisbon and two to Amsterdam — which Cloudflare Tunnel manages to keep the Pi 400 reachable across the network. The final step was routing pi400.jgc.org to the tunnel using the tunnel ID.
Testing the Setup
Pointing the browser at pi400.jgc.org brought up a login screen. After entering an @jgc.org email, I received a one-time PIN. Since SSH was still on password authentication, I entered the username and password next — and landed directly at a command prompt on the Pi 400.
The same flow worked from a phone. To make the setup permanent, I installed cloudflared as a service with sudo cloudflared --config .cloudflared/config.yml service install, so the tunnel starts automatically.
Two security improvements remain worth considering: short-lived certificates can replace SSH password auth, and SSO would be a stronger identity option than one-time PINs for a production deployment. But for a quick, browser-based terminal session to a Raspberry Pi hidden behind the sofa, this setup is both fast and effective.



