Some links in this post may be affiliate links. We may get paid if you buy something or take an action after clicking one of these, but without addictional costs for you compared to direct buying.

cloudflare-tunnel-raspberry-pi-featured-image

Cloudflare Tunnel + Raspberry PI + Docker: Publish a Local Service to the Internet in Minutes

0
(0)
cloudflare-tunnel-raspberry-pi-tested-badge

This tutorial will show you how to install and setup a Cloudflare tunnel with a Raspberry PI so that you can publish a local service running in your Raspberry PI computer board.

About Cloudflare Tunnels

A Cloudflare Tunnel is a secure way to publish a service running on your computer (like a website on a Raspberry Pi) to the internet without opening ports on your router.

Instead of accepting inbound connections, a small program called cloudflared makes an outbound, encrypted connection to Cloudflare.

When someone visits your domain, Cloudflare receives the request and forwards it through the tunnel to your local service. This reduces exposure of your home IP address and avoids port forwarding.

You can use it to expose web apps, SSH, and other services, often with HTTPS handled at Cloudflare.

IMPORTANT NOTE: If you want to use a Cloudflare tunnel, you must have your own public domain. You can buy your domain from any domain registrar or from Cloudflare. This tutorial will also show you a way to test a tunnel with the Cloudflare Quick Connect, which allows you to try it before going for a more stable setup.

What We Need

As usual, I suggest adding from now to your favourite e-commerce shopping cart all the needed hardware, so that at the end you will be able to evaluate overall costs and decide if to continue with the project or remove them from the shopping cart. So, hardware will be only:

raspberry-pi-5-model-b-board

Step-by-Step Procedure

Prepare the Operating System

The first step is to install the Raspberry PI OS Lite to get a fast and lightweight operating system (headless). If you need a desktop environment, you can also use the Raspberry PI OS Desktop, in which case you will work from its terminal app. Please find the differences between the 2 OS versions in my Raspberry PI OS Lite vs Desktop article. For low RAM Raspberry PI computer models, the Lite OS is strongly suggested.

Please make sure that your OS is up to date. From your terminal, use the following command:

sudo apt update -y && sudo apt full-upgrade -y

We also need to install Docker. You can use my tutorial for this: Beginner’s Guide to Install and Use Docker with Raspberry PI.

We’ll make all of our tests from a folder where we’ll save all the (few) required files. Create and enter it. You can give the name you prefer to this folder:

mkdir cloudfl
cd cloudfl

As we’ll use a simple httpd service to expose a simple page in our tests, please create an “httpd_folder” with a simple index.html file. This file will include just a hello message:

mkdir httpd_folder
echo "Hello from peppe8o!" > httpd_folder/index.html

Test Cloudflare Quick Connect

The first test will allow us to quickly test if we have all the resources required to expose a service via Cloudflare tunnels. Please create a docker compose file:

nano docker-compose.yaml

And fill it with the following content:

services:
  web_service:
    image: httpd:2.4
    container_name: httpd-test
    volumes:
      - ./httpd_folder:/usr/local/apache2/htdocs/:ro

  cloudflared:
    image: cloudflare/cloudflared:latest
    container_name: cloudflared-test
    command: tunnel --url http://web_service:80
    depends_on:
      - web_service

Save and close.

You can now create this infrastructure with the following command:

docker compose up -d

This command will download the required container images and run the infrastructure.

Please check the cloudflared logs with the following command:

docker logs cloudflared-test

In the resulting log, you will find a banner where you can find the link you can use in a browser to reach your web service:

+--------------------------------------------------------------------------------------------+
|  Your quick Tunnel has been created! Visit it at (it may take some time to be reachable):  |
|  https://******-*****-***-**********.trycloudflare.com                                     |
+--------------------------------------------------------------------------------------------+

Use the URL in a browser, and you should get something like the following page:

cloudflare-tunnel-raspberry-pi-quick-connect-test

This means that your tunnel is working correctly.

You can’t use this tunnel for production as the link may change from time to time. For a persistent result, we’ll need to use a true domain.

We’ll see it in the following chapter. For the moment, please remove the infrastructure:

docker compose down

Create a Cloudflare Tunnel with Raspberry PI with Public Domain

In this example, we’ll create a Cloudflare tunnel able to run for production environments. For this task, you need to ensure that your public domain is already managed by Cloudflare. Please note that if you recently changed the nameservers, you may need a few hours to complete the move.

We need a new folder inside the one previously created. We also need to make this folder owned by the cloudflared user as follows:

mkdir cloudflared
sudo chown -R 65532:65532 cloudflared

Create the cert.pem Authentication File

The first step is creating an authentication certificate (cert.pem file). This file will allow our cloudflared system to directly authenticate with Cloudflare for any task.

Please use the following terminal command:

docker run --rm -it -v "$PWD/cloudflared:/home/nonroot/.cloudflared" cloudflare/cloudflared:latest tunnel login

In this command, it is important to note that the Docker container is just running the final tunnel login command. We’ll use this strategy as it allows us to execute cloudflared commands without the need to install it in our Raspberry PI environment (as it runs only inside the container).

This command will return you a URL to use to confirm the login authentication, similar to the following:

Please open the following URL and log in with your Cloudflare account:

https://dash.cloudflare.com/argotunnel?aud=&callback=https%3A%2F%2Flogin.cloudflareaccess.org%******_*****************_***********************

Leave cloudflared running to download the cert automatically.

Copy the URL to your browser and complete the login process by selecting the connection and then authorising it:

cloudflare-tunnel-raspberry-pi-login_2

Back to the Raspberry PI terminal, after you complete the login process, you will find a new cert.pem file inside the cloudflared folder:

pi@raspberrypi:~/cloudfl $ ls -la cloudflared
total 12
drwxrwxr-x 2 65532 65532 4096 Jan  4 15:07 .
drwxrwxr-x 4 pi    pi    4096 Jan  4 14:50 ..
-rw------- 1 65532 65532  266 Jan  4 15:07 cert.pem

Create the Cloudflare Tunnel

We must now create the new tunnel. Similarly to the previous file, you can get it easily with the following command:

Please use the following command to create a new tunnel named my_tunnel (or whatever name you prefer for it):

docker run --rm -it -v "$PWD/cloudflared:/home/nonroot/.cloudflared" cloudflare/cloudflared:latest tunnel create my_tunnel

This will save the tunnel credentials in a file inside the cloudflared folder in your Raspberry PI (which is mapped to the /home/nonroot/.cloudflared/ folder in the container) and will give you the tunnel ID (here hidden for security reasons):

Tunnel credentials written to /home/nonroot/.cloudflared/********-****-****-****-************.json. cloudflared chose this file based on where your origin certificate was found. Keep this file secret. To revoke these credentials, delete the tunnel.

Created tunnel my_tunnel with id ********-****-****-****-************

Please take note of the tunnel ID, as we’ll need it in the following parts.

You can also check that the tunnel is configured, as well as any other tunnels if previously created, with the tunnel list command:

pi@raspberrypi:~/cloudfl $ docker run --rm -it -v "$PWD/cloudflared:/home/nonroot/.cloudflared" cloudflare/cloudflared:latest tunnel list

You can obtain more detailed information for each tunnel with `cloudflared tunnel info <name/uuid>`
ID                                   NAME           CREATED              CONNECTIONS
********-****-****-****-************ my_tunnel      2026-01-07T11:33:56Z

In any case, the tunnel create command generated a JSON file in our cloudflared folder where the cert.pem file was saved:

pi@raspberrypi:~/cloudfl $ ls -la cloudflared/
total 8
4 -r-------- 1 65532 65532 175 Jan  4 15:10 ********-****-****-****-************.json
4 -rw------- 1 65532 65532 266 Jan  4 15:07 cert.pem

Create a Route for the Cloudflare Tunnel

A route is a way to tell Cloudflare that all the incoming connections to our domain (or its subdomains) must be routed through the tunnel to our Raspberry PI. In this case, I’ll create a route for the root domain, but you can modify this command to route also subdomains.

For the following command, it is important to have your domain integrated with Cloudflare. I’ll use the domain “example.com” for the scope of this tutorial, but you will need to use your domain instead.

To create a simple route, please use the following command:

docker run --rm -it -v "$PWD/cloudflared:/home/nonroot/.cloudflared" cloudflare/cloudflared:latest tunnel route dns my_tunnel example.com

This command will be executed immediately, but it may take a few seconds to become effectively active as this will write a new DNS record for your domain.

Create the Docker Compose Files

In this last part, we’ll create a configuration file and a docker compose file to get all wrapped together. Let’s begin with the configuration file. Create it with the following command:

sudo nano cloudflared/config.yml

Please fill this file with the following content, caring to change the bolded parts (tunnel name, tunnel ID/JSON and domain) with your ones:

tunnel: my_tunnel
credentials-file: /etc/cloudflared/********-****-****-****-************.json

ingress:
  - hostname: example.com
    service: http://web_service:80
  - service: http_status:404

Now, let’s change the docker compose file:

nano docker-compose.yaml

And fill it as in the following:

services:
  web_service:
    image: httpd:2.4
    container_name: httpd-test
    volumes:
      - ./httpd_folder:/usr/local/apache2/htdocs/:ro
    restart: unless-stopped

  cloudflared:
    image: cloudflare/cloudflared:latest
    container_name: cloudflared-test
    command: tunnel --config /etc/cloudflared/config.yml run
    volumes:
      - ./cloudflared:/etc/cloudflared:ro
    depends_on:
      - web_service
    restart: unless-stopped

Run Cloudflared Tunnel with Raspberry PI

We can now run the tunnel. As a final check, you should now have the following folders/files:

└── cloudfl
   ├── cloudflared
   │   ├── ********-****-****-****-************.json
   │   ├── cert.pem
   │   └── config.yml
   ├── docker-compose.yaml
   └── httpd_folder
       └── index.html

You can now run the tunnel with the following terminal command:

docker compose up -d

At any time, you can check the cloudflared logs with the following:

docker logs cloudflared-test

Please use your browser to reach your domain, which should give you something like the following:

cloudflare-tunnel-raspberry-pi-result

Common Issues

If the browser gives you errors about insecure connections or TLS handshake, it may be useful to set the encryption mode to “Flexible” in the SSL/TLS encryption menu of your Cloudflare account. Sometimes, for domains with nameservers just been moved, it may be enough just to wait a few hours for Cloudflare to automatically issue a certificate for your domain.

Next Steps

Interested in more projects with your Raspberry PI? Take a look at peppe8o Raspberry PI computer tutorials pages.

Enjoy!

Resources

peppe8o author image
peppe8o (Giuseppe Cassibba)

Open source and Raspberry PI lover, writes tutorials for beginners since 2019. He's an ICT expert, with a strong experience in supporting medium to big companies and public administrations to manage their ICT infrastructures. He's supporting the Italian public administration in digital transformation projects.

websitexfacebookinstagramlinkedinyoutubepinterest

How useful was this post?

Click on a star to rate it anonymously!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Leave a Comment

Your email address will not be published. Required fields are marked *

×