Skip to content
Steven KangAugust 18, 20234 min read

Secure IoT Device Connectivity with Cloudflare and Portainer


This blog post will walk through how to set up Cloudflare tunnels with WAF rules to host Portainer and Edge Agents protected by mTLS as per below:


Disclaimer: This is a technical blog to demonstrate the implementation described above.
It does not cover end-to-end mTLS setup; instead, it is for only Edge Devices to Cloudflare, and the rest is handled by the Cloudflare tunnels with no mTLS.


Ensure the following elements are prepared before proceeding:

  • 3 x Linux environments to deploy the Portainer server and Edge Agent containers.
  • Cloudflare:
    • Generate a Client Certificate for Portainer Edge Agents, and enable mTLS for the primary Portainer API endpoint published by Cloudflare:

    • Enable Zero Trust to create Tunnels.
    • Create a DNS zone to enable proxy.


1. Spin up a Portainer Server core instance per this document in a container runtime environment. This uses a Docker standalone on Linux as an example:

docker run -detach \
  --port 9443:9443 \
  --volume /var/run/docker.sock:/var/run/docker.sock:z \
  --volume portainer_data:/data \
  --network internal-net \
  --name portainer \
  portainer/portainer-ee:2.18.4 --log-level DEBUG

It is crucial to ensure the Portainer server container runs on the same Docker network as the Cloudflare tunneld containers. This is to allow tunneld containers to communicate with Portainer with the name portainer on port 9000 and 8000 over the private Docker network. Exposing port 9443 (HTTPS) is mandatory to access Portainer UI.

Note: if you want tunneld containers to communicate with Portainer over HTTPS, which is what we recommend, the use of a public CA-signed certificate at the Portainer level will be mandatory. Specify the --hostname switch to match the DNS your certificate expects.

2. Once deployed, navigate to Settings -> Edge Compute to finish off configuring the Edge Compute Settings:

Screenshot 2023-08-18 at 10.55.23

3. Next, navigate to Environments -> Auto onboarding, and record the Edge Key:

Screenshot 2023-08-17 at 16.30.02

4. Now, two tunneld will be deployed to publish two Portainer endpoints; API and Tunnel. Navigate to Zero Trust -> Access -> Tunnels -> Create a tunnel:

5. select Docker to install and run a connector once you go next. Record the token:

Screenshot 2023-08-18 at 08.51.59

6. Back to Portainer, navigate to the Local environment where Portainer runs -> Containers -> Add container to deploy a tunneld container:

Screenshot 2023-08-18 at 11.25.46

Screenshot 2023-08-18 at 11.26.08

Screenshot 2023-08-18 at 11.26.38

After a second, you will now see the connector details from your Cloudflare page:

Screenshot 2023-08-18 at 09.11.26

7. Next, set the public hostname. Below is an example:

Screenshot 2023-08-18 at 09.12.26-1


Since we only published the /api endpoint, executing a simple curl the command below would be sufficient to confirm that the endpoint is alive:

404 page not found

If you are planning to run Standard Edge Agents, then repeat above steps 4-7 to deploy an additional tunneld container to publish below:

Screenshot 2023-08-18 at 09.17.48

8. Time to protect the Portainer API endpoint with WAF. Navigate to Security -> WAF, and create a rule:

Screenshot 2023-08-18 at 09.41.50

Rule: ( in {""} and not cf.tls_client_auth.cert_verified)

- in {""} - this is to trigger this WAF rule if the DNS is hit
- not cf.tls_client_auth.cert_verified - this is to enforce that client certificates are presented to interact with the DNS above

Running the same curl operation again, you will now see a block message since Cloudflare signed client certificates were not presented:

<h2 data-translate="blocked_why_headline">Why have I been blocked?</h2>

For further testing, direct to the folder where the client certificates are, and execute below to provide the client certificates:

curl --cert client.cert --key client.key
404 page not found

9. Time to deploy Edge Agents. SSH to the second Linux environment, and make sure the client certificates; client.cert and client.key are located under the directory /certs, and execute below with the EDGE_KEY recorded in step 3:

Async Mode
docker run --detach \
--env EDGE=1 \
--env EDGE_ID=$(uuidgen) \
--env EDGE_KEY=${EDGE_KEY} \
--env EDGE_ASYNC=1 \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume /var/lib/docker/volumes:/var/lib/docker/volumes \
--volume /:/host \
--volume portainer_agent_data:/data \
--volume /certs:/certs \
--restart always \
portainer/agent:2.18.4 --log-level DEBUG --mtlscert /certs/client.cert --mtlskey /certs/client.key
Standard Mode
docker run --detach \
--env EDGE=1 \
--env EDGE_ID=$(uuidgen) \
--env EDGE_KEY=${EDGE_KEY} \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume /var/lib/docker/volumes:/var/lib/docker/volumes \
--volume /:/host \
--volume portainer_agent_data:/data \
--volume /certs:/certs \
--restart always \
portainer/agent:2.18.4 --log-level DEBUG --mtlscert /certs/client.cert --mtlskey /certs/client.key

10. Navigate to Portainer -> Waiting Room, and you will see the device in the queue to be trusted. Associate the device to onboard it:

Screenshot 2023-08-18 at 10.39.08

11. The device will now show up on the homepage of Portainer. Giving it a minute or two will take a snapshot as per below:

Screenshot 2023-08-18 at 10.41.23

12. Clicking on the async device will lead you to take a snapshot of it:

Screenshot 2023-08-18 at 10.41.41

13. Below is an example of a Standard Edge Agent with an interactive session established to browse images:

Screenshot 2023-08-18 at 11.31.35

Screenshot 2023-08-18 at 11.32.06


This is it! Now the Edge Agent communicates with Cloudflare with client certificates, and you can start configuring Edge Groups, Edge Stacks, and so on!

Feel free to leave a reply or reach out to me directly if you have any questions or need clarification.

Try Portainer with 3 Nodes Free

If you're ready to get started with Portainer Business, 3 nodes free is a great place to begin. If you'd prefer to get in touch with us, we'd love to hear from you!


Steven Kang

Steven is a technologist and consultant interested in cloud, container and open-source technology, who loves solving complex problems.


Related articles