A few weeks ago I received a Raspberry Pi 400 as a gift. I didn’t have time to do anything beyond plug it in and verify that it works. It’s great that the Pi 400 comes with everything you need except for a screen: there’s the computer itself, mouse, HDMI cable and power adapter.
The Pi 400 has been sitting gathering dust when Cloudflare launched Auditable Terminal giving me the perfect excuse to get out the Pi 400 and hook it up.
Auditable Terminal gives you a fully featured SSH client in your browser. You authenticate using Cloudflare Access and can log into a computer from anywhere just using the browser and get a terminal. And using Cloudflare Tunnel you can securely connect a computer to Cloudflare without punching holes in a firewall. And you end up with a consistent terminal experience across devices: 256 colours, Unicode support and the same fonts everywhere.
This is ideal for my use case: set up the Pi 400 on my home network, use Cloudflare Tunnel to connect it to the Cloudflare network, use Auditable Terminal to connect to the Pi 400 via Cloudflare and the tunnel using nothing more than a browser.
Here’s what it looks like:
Before getting into the details of how I set that up, it’s worth stopping and appreciating how cool this is. I am logging into the Pi 400 via SSH but inside the browser window just by visiting a URL in a browser and authenticating using Cloudflare for Teams. And since it’s a URL that SSH session can just be a browser bookmark!
There’s another reason I wanted to do this: I like to use Cloudflare’s own products. I have a number of Cloudflare accounts that I pay for so that I see the true customer experience. I see the emails we send out and what it’s like to navigate our UI for real use. The Pi 400 gave me a chance to experience with Cloudflare Tunnel and Auditable Terminal.
Also this is really cool.
So… if you want to do this yourself, follow along as I take you through the steps I went through to hook a brand new Pi 400 up to Cloudflare and access it from anywhere.
Stage 1: Prepare the Pi
I plugged the Pi 400 into my TV via HDMI, to the Internet via Ethernet and booted it. It comes with the OS pre-installed on an SD card so it only took seconds to be at a welcome screen:
Inevitably with a brand new machine there were a lot of updates to install so I let the machine run through that before logging in for the first time.
The Pi 400 doesn’t come with the SSH server enabled, so it’s necessary to run the raspi-config program from the command line (sudo raspi-config
). The SSH server is under option “3 Interface Options”:
It’s option “P2 SSH” and when turned on will allow SSH access to the machine. By default this will be using SSH with password authentication and so it’s pretty important to change the default pi/raspberry combination (and to go much further and switch to using certificates).
But for the rest of this run through I am going to stick with password authentication in SSH. We’ll see later that Cloudflare has a clever solution to setting up SSH security with certificates.
With SSH access setup and the Pi 400 fully updated, the second step is to set up Cloudflare Tunnel.
Stage 2: Cloudflare Tunnel
Even with SSH setup on the Pi 400 it’s only accessible from inside my home network and I want to get access to it from anywhere. I could open a port in my home firewall, but I hate that idea.
The answer is Cloudflare Tunnel. It’s a (free!) small daemon (called cloudflared
) that will connect from the Pi 400 to multiple Cloudflare data centers and maintain connections to them. It’ll be authenticated to my Cloudflare account and once setup I’ll be able to use Cloudflare for Teams to connect to it via the web.
Setting it up is a doddle. I already had a domain name setup on Cloudflare, if I hadn’t I could have set one up quickly. The Cloudflare Tunnel documentation takes you through installing it.
The only thing I didn’t know was the architecture of the Pi 400 (32 bit? 64 bit?); so I ran lscpu
which tells me that it’s armv7l
(which is 32-bit). How did I know that armv7l was 32-bit? I didn’t. I googled it.
You can build cloudflared
from source if you wish as it’s an open source project. But I chose to go the speedy route and wget
it.
With cloudflared
installed on the Pi 400 it was time to authenticate it to my account. Authentication is clearly documented and I started by typing cloudflared tunnel login
. On a machine with a UI and browser this would have opened the browser ready for me to log into my Cloudflare account and set up cloudflared
.
Since I was doing all this while SSH’d into the Pi I had to copy and paste the URL to my browser and then choose which of my domains I would use. (I did this before we changed the name from Argo Tunnel to Cloudflare Tunnel… it’s the same thing).
Once authorized, the cloudflared
command running on the Pi 400 automatically sets up the tunnel. In the dashboard I received confirmation of this:
And back on the Pi 400 there was confirmation that cloudflared
had been authorized and that a cert.pem
file was created.
Now that cloudflared
was authorized it was time to go ahead and set up an actual tunnel that can be used for the Auditable Terminal. I chose the incredibly original name ‘terminal’ for this.
At this point the tunnel is set up but not running yet. So the Pi 400 is not yet connected to Cloudflare. I’ll come back to that. But the next step is setting up Cloudflare for Teams so that users can authenticate to the other end of the tunnel and get access.
Stage 3: Cloudflare for Teams
I didn’t have Cloudflare for Teams setup so the first step was to visit https://dash.teams.cloudflare.com/ and following the setup guide. I chose the unoriginal team name jgctesting
and entered it:
And it’s here that things got complicated. I ended up writing this blog post to give anyone a step-by-step guide to getting Auditable Terminal working, but also so that we can learn from my confusion. (The team has put up a complete tutorial on this here.)
If you follow the Cloudflare for Teams documentation you have three choices.
It wasn’t 100% obvious to me that what I needed to do was add an application (as opposed to a location). The answer is… add an application. The process for doing so is documented here.
In particular, I’m going to add a Self-Hosted Application (rather than SaaS) since I’m self-hosting it; it’s an SSH server on a Raspberry Pi 400 hidden behind the sofa after all.
The next step is to give the application a name and specify the URL it will be accessible via. For me that’s “Raspberry Pi 400” (yeah, I’m great with original names) and I’m making it available via pi400.jgc.org.
Cloudflare for Teams provides a lot of different authentication and identity options, but for this demo I am going to use the simplest. When I want to connect to this application (which will be Auditable Terminal ultimately) I’m going to have Cloudflare email me a one-time PIN.
Next up is adding a rule which will let Cloudflare for Teams know who should be allowed access to this application. I am allowing anyone with an @jgc.org email address to get a one-time PIN. Rules can be much more complex than that!
And finally I need to enable browser rendering (which will enable the SSH access and Auditable Terminal).
Stage 4: Connecting it all together
At this stage I had cloudflared
setup and authorized on the Pi 400, Cloudflare for Teams setup so that anyone with an @jgc.org email could get a PIN to access Auditable Terminal on pi400.jgc.org (I’ve since reconfigured everything so going to that URL doesn’t do anything today).
But all these things need connecting together. That means: editing a config file on the Pi 400 and telling Cloudflare to route to the tunnel for pi400.jgc.org.
I started with the config file which was /home/pi/.cloudflared/config.yml
. The first step was to get the tunnel ID.
And then edit the config file. Three things needed changing from the defaults: the tunnel (which is just the ID from cloudflared tunnel list
), the credentials-file (which is a JSON file in the same location as the config file and with the same name as the tunnel ID) and the hostname (in my case pi400.jgc.org)
With the tunnel installed, authorized and configured I was able to finally run it and make sure that it can connect to Cloudflare. It worked! And created four connections to Cloudflare. Two to Lisbon and two to Amsterdam. Cloudflare Tunnel manages these connections to ensure that my Pi 400 is reachable across the Cloudflare network.
And finally… I just needed to tell cloudflared
to route pi400.jgc.org to the tunnel (once again using that tunnel ID).
Stage 5: Try it!
And then it was time to try it. I went back to my browser and browsed to pi400.jgc.org and was greeted with a login screen. Since I’d authorized any @jgc.org address I entered an @jgc.org email.
The next step was to enter the one-time PIN that was emailed to me.
And, since I am using user/password for SSH I was asked for the user name followed by password.
And, wow, there I was looking at a command prompt on the Pi 400.
Of course, just doing on my laptop wasn’t enough, so I went ahead and logged in the same way on my phone.
The absolute last step was to make sure that cloudflared
runs automatically which was as simple as typing sudo cloudflared --config .cloudflared/config.yml service install
.
Conclusion
This was pretty fast (especially factoring in my ignorance about all the details of configuring Cloudflare for Teams and Cloudflare Tunnel). Now I can log into that Pi 400 from anywhere in just a browser. So powerful.
But it’s still using username/password for SSH and that can be fixed with short-lived certificates. And my authentication to access is using one-time PINs; for a real application it would be better to use SSO.