Skip to content
👨🏻‍💻 Erdal

Setting up Cloudflare Argo & Access on a Raspberry Pi

RaspberryPi, Cloudflare, NAS, HomeServer, Guide3 min read

Banner

A few nights ago I was casually browsing on /r/SelfHosted when I came across a post mentioning how insecure some of the home servers are regarding to their WAN access.

The obvious answer is Cloudflare Argo & Cloudflare Access. Before explaining everything, let's clarify what this guide is about: If you are looking to access your homeserver from outside, for example, your Raspberry Pi, in a secure way without exposing ports on your own, this guide is for you.

Before you begin you will need a few things:

  • A Cloudflare account
  • A registered domain name with access to the DNS panel (ideally through Cloudflare but at the very least point the nameservers to them)
  • A Raspberry Pi or a server with your favorite Linux distribution
  • Some basic knowledge of Docker, shell commands and networking

What's Cloudflare Argo & Access ?

Cloudflare Argo tunnels allows you to create an encrypted tunnel between your homeserver and the Cloudflare servers. This is done seamlessly, in a few lines of shell commands.

As you can see from the image below (from the Cloudflare Blog), you should consider the tunnel like a third party making sure you get the fastest access with the least risks of exposing your services.

Argo Tunnel

On the technical side you get a few features as a bonus like TLS certificates, DDOS protection and smart routing.

Another Cloudflare service is Access, which is part of Cloudflare Teams and it allows you to use their zero-trust infrastructure to access your services securely. What we are most interested in are the access policies and the application dashboard.

Cloudflare Access

If you are interested in more technical information you should consider reading their developer documentation.

Practical deployment

To illustrate how easy and magical it is, I will deploy from start to finish three docker containers (portainer, gluetun & librespeed) on a Raspberry Pi.

Get your Raspberry Pi OS Lite image and use balenaEtcher to write it down on your SD card. You can add an "ssh" file without any extensions to make your Raspberry Pi headless and accessible from your computer or just plug-it in.

Let's get some updates

1sudo apt update
2sudo apt upgrade

We can now install Docker

1curl -sSL https://get.docker.com | sh

Add permissions to the current user

1sudo usermod -aG docker ${USER}

Let's also install docker-compose

1sudo apt-get install libffi-dev libssl-dev
2sudo apt install python3-dev
3sudo apt-get install -y python3 python3-pip
4sudo pip3 install docker-compose

You can enable the docker service

1sudo systemctl enable docker

Let's deploy our docker containers, but before that a bit of explanation about the containers we are going to use:

  • Portainer is a GUI for docker.
  • Gluetun is a super awesome, vpn docker container, that allows you to route any other service through that container for additional privacy.
  • Librespeed is just a lightweight speedtest implementation and will serve as an exemple of network routing.

All these containers are just here to illustrate this practical example and are not necessary for the Cloudflare side of things.

Let's start with Portainer

1docker run -d -p 8000:8000 -p 9443:9443 --name portainer \
2 --restart=always \
3 -v /var/run/docker.sock:/var/run/docker.sock \
4 -v portainer_data:/data \
5 portainer/portainer-ce:latest

You can go to http://[your-machine-ip]:9443 and finish the Portainer setup on your own (and follow the official guide if needed)

If you did everything right, your Portainer dashboard should look like this (without the two other containers at this moment): Portainer

Now we can docker compose gluetun and librespeed in one file, please note that I'm using PIA vpn but you can use something else and even skip if needed. This is just an example of how to route a container through another.

1mkdir gluetunAndLibrespeed
2cd gluetunAndLibrespeed
3touch docker-compose.yml
4nano docker-compose.yml

And paste the following lines:

The documentation of gluetun is here if you need help for your vpn.

1---
2version: "2.1"
3services:
4 gluetun:
5 image: qmcgaw/gluetun
6 container_name: gluetun
7 cap_add:
8 - NET_ADMIN
9 volumes:
10 - /home/pi/gluetunAndLibrespeed:/gluetun
11 environment:
12 - VPNSP=private internet access
13 - OPENVPN_USER=[YOUR_USERNAME]
14 - OPENVPN_PASSWORD=[YOUR_PASSWORD]
15 - REGION=[YOUR_REGION]
16 ports:
17 - 7777:80
18 restart: unless-stopped
19
20 librespeed:
21 image: ghcr.io/linuxserver/librespeed
22 container_name: librespeed
23 environment:
24 - PUID=1000
25 - PGID=1000
26 - TZ=Europe/Paris
27 - PASSWORD=PASSWORD
28 volumes:
29 - /home/pi/gluetunAndLibrespeed:/config
30 network_mode: "service:gluetun"
31 depends_on:
32 - gluetun
33 restart: unless-stopped

To get this started, make sure to still be in the folder

1docker-compose up -d

Finally the Cloudflare part!

Let's setup Cloudflare teams to configure our access rules and our dashboard

Go to the Teams area, you should have a configuration page with a teams name selection. I suggest you spend some time on the Teams dashboard to configure a default policy for your apps (I only use the one-time pin), once your understand the basics (policies, dashboard, etc..) let's add our first self-hosted application.

Cloudflare Self-Hosted Selection

Cloudflare Self-Hosted Application setup

Once you are ready to add your first application, just give it a name, then a subdomain (like librespeed.[YOUR_DOMAIN].tld), choose your domain in the list, then click next to add the policy configuration that you feel comfortable with and you're pretty much done for the web configuration.

We can use the tunnel as a service, docker container or standalone like we are doing right now. I'm following (and you should too) the great documentation provided by Cloudflare.

1cd
2wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-arm.tgz
3tar -xvzf cloudflared-stable-linux-arm.tgz
4sudo cp ./cloudflared /usr/local/bin
5sudo chmod +x /usr/local/bin/cloudflared
6cloudflared -v

Let's authenticate

1cloudflared tunnel login

Once this is done, you should have choosen a hostname (like "pi") and we will use that for the creation of our tunnels. If I want to expose my librespeed container, I will create the tunnel

1cloudflared tunnel create pi librespeed.[YOUR_DOMAIN].tld

Finally you modify the configuration file the .cloudflared directory and it should look like this:

1# url: http://localhost:9000
2tunnel: XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX
3credentials-file: /home/pi/.cloudflared/XXXXXXXXXXXXXXXXXXX.json
4
5ingress:
6- hostname: librespeed.[YOUR_DOMAIN].tld
7 service: http://localhost:7777
8- service: http_status:404

Congratulations, go to [YOUR_NAME].cloudflareaccess.com and that's it, I will include a few screenshots of how it looks like in the browser.

Teams url access

Teams pin code

Teams dashboard

Teams librespeed app

If you enjoyed this guide you can also check the previous one about iCloud custom domains.

© 2021. All rights reserved.