Creating an Edge Agent in Portainer CE is way more complex that it should be. I will explain how to get Portainer Edge Agent to work vir Cloudflare Tunnel.


Portainer Server Docker Compose

Make sure you expose port 9000 and port 8000 on your container server. Your compose file should look something like this:

version: "3"
services:
  portainer:
    image: portainer/portainer-ce:latest
    ports:
      - 9443:9443  # Main UI/API (HTTPS)
      - 9000:9000  # Required for Edge Agent communication for /api (non HTTPS)
      - 8000:8000  # Required for Edge Agent tunnel connection and remote management
    volumes:
      - data:/data
      - /var/run/docker.sock:/var/run/docker.sock
    restart: unless-stopped
volumes:
  data:

Port 9000: Used by the Edge Agent to communicate with the /api endpoint

Port 8000: Used for the tunnel connection between the agent and the server and for the server to remotely manage the edge agent.


Portainer Edge Agent via Cloudflare Tunnel Setup

For this post, I assume you already have a Cloudflare Tunnel up and running. You need to add 2 new public hostnames to your tunnel:

Tunnel 1 will be for the Portainer Edge Agent to communicate with the /api endpoint:

Cloudflare Portainer Agent Tunnel 1

Tunnel 2 will be for the Portainer Edge Agent to establish a tunnel with the server for remote management:

Cloudflare Portainer Agent Tunnel 2

Cloudflare WAF Firewall Rule

To make things more secure, add a WAF rule to only allow your remote server’s IP address to communicate with these endpoints. I am hosting in Oracle Cloud (free VMs) and they both have static IP addresses:

Cloudflare Portainer Edge Agent WAF Rule

If you want to see what your VMs public IP address is, run this command:

curl 'https://api.ipify.org?format=json'

Portainer Server Setup

In Portainer, enable Edge compute. A entirely new menu will appear on the left hand side.

Enable Portainer Server Edge Compute

Next, add a new environment.

Portainer Server Add new Environment

Select “Docker Standalone” and click on the “Start Wzard” button:

Docker Standalone Environment

Select “Edge Agent Standard” and enter your API tunnel URL, for example “https://port-rem-api.mydomain.com“. We will add the tunnel URL shortly.

Portainer Edge Agent Config

Don’t worry too much about the rest of the settings now, but change polling to something a bit more suitable as the default could be a bit too much. I chose 30 seconds but you can change it later on.

Click on the “Create” button.

Where things get tricky

Decode the Base64 string

Once you’ve clicked on “Create” the docker command will be displayed that you must run on your remote server. We are interested in the “EDGE_KEY” value.

EDGE_KEY is a base64 encoded string that contains the API URL you just entered as well as a second URL for the tunnel that Portainer derives from the API URL. But we need to change this second URL. (It also contains keys and such so keep this base64 string and its contents secure).

This is what my docker command looks like:

Docker Command

Go to https://www.base64decode.org/ and paste that EDGE_KEY value and click on “Decode“.

You will see the first hostname (the API endpoint hostame that you entered) and then a pipe character, and then the second URL and then a pipe character again. We need to modify this second URL between the 2 pipe characters.

This is what my decoded base64 string looked like:

Decoded base64

Modify and Encode the Bae64 string

Now go to https://www.base64encode.org/ Here we will modify our string and encode it back to base64. That second URL between the 2 pipe characters must be your “Portainer Tunnel” endpoint. In my case, my tunnel endpoint is “https://port-rem-tun.mydomain.com

Modified Base64 string

Make sure you ticked the “URL-safe encoding” tickbox, and click on “Encode“.

Modify the Portainer Edge Agent docker command

Now copy that docker command that the Portainer Server gave you and paste it into a text file, and overwrite the “EDGE_KEY” value with your newly encoded string. Make sure to keep the “<space>\” at the end of the string, similar to all the other lines.

New encoded string


Running the command on the remote Portainer client

Head over to your client and paste that entire docker command. It will probably download the image and then start up.

You can check the logs of that container with this command:

docker logs -f portainer_edge_agent

The URL circled in red is the second URL we added to our EDGE_KEY. If we didn’t change that URL to the correct URL, the tunnel connection would’ve failed. If the client experiences any connection errors, you will see it in these logs.

Portainer Edge Agent client logs


Portainer Server Dashboard

Back in your Portainer server go to your home dahsboard. You will see your newly added Portainer Edge Agent and its heartbeat. Clicking on it will open the usual management interface.

Portainer Server Dashboard

By using Edge Agents you don’t have to expose your portainer agents port 9001 to the internet anymore.


necrolingus

Tech enthusiast and home labber