Skip to main content

Run the edge agent

This guide is for whoever runs the Axiad edge agent on a machine inside your network — usually someone on the IT or infrastructure team. Your Mesh administrator sends you two things: a one-time enrollment token and a command to run. This page walks you through running that command and confirming the agent connected.

Who this is for

If you manage connectors from the Mesh dashboard instead, see Set up an on-prem connector.

What the edge agent is

The edge agent is a small program that runs as a container on a machine inside your network. It lets Mesh reach internal systems that aren't exposed to the internet.

The agent only ever connects out to Mesh over HTTPS, and keeps that secure connection open. It never accepts incoming connections — so you don't need to open any firewall ports for it.

Before you begin

Here's what you need to have ready:

  • A Linux machine inside your network with Docker installed and running (Step 1 shows how to check). Another container runtime such as Podman works too.
  • Outbound HTTPS (port 443) from that machine to Mesh. No inbound ports.
  • A network path from that machine to the internal systems you want Mesh to collect from.
  • From your Mesh administrator: your one-time enrollment token and the command to run.
Your token is short-lived — use it right away

The enrollment token is valid for 15 minutes and works only once.

The 15 minutes starts when your administrator creates the token, not when it reaches you. So if it came to you after a delay — an email that sat for a while, or a handoff between people — you may have less time left, or none. Run the command as soon as you get the token, and if you're not sure how long ago it was created, just ask for a fresh one.

If the token expires first, enrollment fails with enroll: ENROLL_TOKEN expired. Ask your administrator to register the agent again and send a new token — there's nothing to clean up first, and it doesn't matter that an earlier try failed.

Step 1 — Check that Docker is installed and running

The agent runs as a Docker container, so first make sure Docker is installed and running. Open a terminal on the machine and follow along.

Check that Docker is installed:

docker --version

You should see a version string, for example Docker version 27.3.1, build ce12230. If you get command not found, install Docker first — see Install Docker Engine — then come back here.

Start Docker and confirm it's running:

sudo systemctl start docker
docker info

docker info prints the server details when Docker is running. If you instead see Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?, Docker isn't started yet — run the systemctl start line above and try again.

The agent should come back on its own after a reboot, so set Docker to start automatically:

sudo systemctl enable docker
On a Mac or Windows host, or a Linux host without systemd

systemctl only exists on systemd Linux hosts. With Docker Desktop (macOS or Windows), start it from your terminal instead:

docker desktop start

Or open the Docker Desktop app and wait until it says the engine is running. Either way, docker info is the check — if it succeeds, you're ready for Step 2.

Using Podman, containerd, or Kubernetes instead of Docker

The agent image needs nothing Docker-specific — any standard container runtime that can pull an image and run a container with a mounted volume works.

  • Podman — mostly a drop-in replacement (podman run takes the same flags as docker run here). One thing to watch: in Podman's default rootless mode, you may need one extra one-time step to give the agent write access to its storage before the first start.
  • containerd (via its nerdctl tool) — behaves like Docker directly, without Podman's rootless difference.
  • Kubernetes — if you already run Kubernetes, you can deploy the agent as a normal workload there instead of a standalone container. The storage-permission step still applies, just handled the usual Kubernetes way on the volume.

Step 2 — Run the agent

Your administrator copies the command from the Add on-prem agent dialog in Mesh and sends it to you along with the token. Here's what they see:

The Mesh Add on-prem agent dialog showing the one-time enrollment token above a highlighted Run on the customer host command block containing the docker pull and docker run commands

The command has three parts — one takes your token, one downloads the agent, one runs it:

# 1) Paste your enrollment token. (read -rs keeps it out of your command history.)
read -rs ENROLL_TOKEN && export ENROLL_TOKEN
echo "${#ENROLL_TOKEN}" # Prints the token's length — make sure it's NOT zero. Nothing
# shows on screen as you paste, so this is your only check.

# 2) Download the agent image. 1.0.0 is an example — use the version the dialog shows you.
docker pull axiadpublicregistry.azurecr.io/mesh-edge-agent:1.0.0

# 3) Run the agent.
docker run -d --name axiad-edge-agent --restart unless-stopped --user 0:0 \
-e ENROLL_TOKEN="$ENROLL_TOKEN" \
-e MESH_SSRF_ALLOW_PRIVATE=1 \
-e STRICT_CONFIG_SIGNING=true \
-v mesh-edge-data:/var/lib/mesh-edge \
axiadpublicregistry.azurecr.io/mesh-edge-agent:1.0.0

Run the first line on its own. The terminal waits quietly — paste your token and press Enter. Nothing appears on screen (that's on purpose, so your token doesn't end up in your command history). The echo line then prints the token's length; check that it isn't zero, which is your one sign the paste actually worked.

Use the same terminal window the whole time

Your token is held in a variable that only exists in the terminal window where you pasted it. If you open a new window, switch users (for example sudo -i), or reconnect over SSH before you run the agent, that variable is empty again — and Docker won't warn you. The agent starts and then fails with a confusing config: gateway address unknown.

So paste the token and run the agent in the same window. If some time has passed, run echo "${#ENROLL_TOKEN}" again and check it's still not zero before you continue.

Double-check the paste

If you accidentally copied an extra line break or a trailing space with the token, enrollment fails with a confusing error — and nothing on screen tells you the paste was messy. To check for a stray line break:

printf '%s' "$ENROLL_TOKEN" | wc -l

This should print 0. If it prints 1 or more, copy the token again and re-paste it.

What the parts mean:

PartWhat it does
ENROLL_TOKENYour one-time token, from the first command. The agent uses it once to join Mesh, then remembers its own identity — so you won't need it again. The token also tells the agent where your Mesh environment is, so there's nothing else to point it at (no need to set MESH_GATEWAY).
MESH_SSRF_ALLOW_PRIVATE=1Lets the agent reach systems on your private network. Keep it if any of your targets are internal (the usual case); drop it only if every target is on the public internet.
-v mesh-edge-data:/var/lib/mesh-edgeWhere the agent stores its identity and state. Docker creates this on first run — nothing to set up — and it survives restarts and upgrades.
--user 0:0Runs the agent as root so it can create its storage on first start.
--restart unless-stoppedStarts the agent again automatically after a reboot.
STRICT_CONFIG_SIGNING=trueTells the agent to accept only connector settings that Mesh has signed. On by default — leave it on.
Storing the agent's data: two options

The command above keeps the agent's data in a Docker volume called mesh-edge-data. That's the recommended default — Docker creates it for you, and with --user 0:0 there's nothing to prepare.

If you'd rather store the data in a folder on the host machine, swap the -v for a host path, for example -v /var/lib/axiad-edge:/var/lib/mesh-edge. Only the left side changes; the right side stays /var/lib/mesh-edge. One catch: the folder has to exist and be writable by the agent before you start it, or the agent stops right away with mkdir .../store: permission denied.

Which user needs access depends on how you run the agent:

# If you keep --user 0:0, the agent runs as root — just create the folder:
sudo mkdir -p /var/lib/axiad-edge

# If you remove --user 0:0, the agent runs as its own user (ID 65532). Create the
# folder AND give that user access:
sudo mkdir -p /var/lib/axiad-edge
sudo chown 65532:65532 /var/lib/axiad-edge
Keep your token out of your command history

When you pass the token with -e, it appears on the command line — which means it's saved in your command history and visible in the machine's process list. To avoid that, put the settings in a file and use --env-file instead:

cat > ~/mesh-edge.env <<'EOF'
ENROLL_TOKEN=paste-your-token-here
MESH_SSRF_ALLOW_PRIVATE=1
STRICT_CONFIG_SIGNING=true
EOF

docker run -d --name axiad-edge-agent --restart unless-stopped --user 0:0 \
--env-file ~/mesh-edge.env \
-v mesh-edge-data:/var/lib/mesh-edge \
axiadpublicregistry.azurecr.io/mesh-edge-agent:1.0.0

Don't put quotes around the values — ENROLL_TOKEN="abc" treats the quotes as part of the token. Delete the file once the agent has joined.

Step 3 — Verify it enrolled and connected

Watch the agent's logs to confirm it joined Mesh and connected:

docker logs -f axiad-edge-agent

The agent prints its logs as JSON. Look for these messages, in order:

  • enroll: success — the agent registered with Mesh.
  • agent.connect ok — the secure connection to Mesh is up. This line also shows which gateway it reached, for example gateway=edge.example.axiad.io:443.
  • heartbeat: initial tick sent — the agent has checked in and is healthy.

Terminal output from docker logs showing the agent enrolling successfully and connecting to the Mesh gateway

A warning on first start is normal

If this machine ran an agent before, you might see enroll: ENROLL_TOKEN identity differs from the cached cert. That's fine — the agent simply re-joins with your new token and drops the old identity. Nothing for you to do.

You can also ask the agent for its status directly:

docker exec axiad-edge-agent agent status
  • Joined: agent kid=... issued_at=... not_after=.... The not_after value is when its certificate expires — it renews on its own.
  • Not joined yet: agent: not enrolled.
If the container keeps restarting or is stopped

docker exec only works while the container is actually running — which is exactly when a struggling agent won't be, since it spends its time restarting. When that happens, you can read the same status from a quick throwaway container that looks at the same stored data. It needs no token and nothing else running — just reuse the same -v from your run command:

# Use the tag you actually ran (1.0.0 is an example).
docker run --rm --user 0:0 -v mesh-edge-data:/var/lib/mesh-edge \
axiadpublicregistry.azurecr.io/mesh-edge-agent:1.0.0 status

This is the quickest way to check the agent's identity, certificate expiry, and last crash reason (the last_crash= line) when the container won't stay up. You can also run docker logs axiad-edge-agent on a stopped (but not removed) container to read its recent logs — no running process required.

Once the agent is connected, let your administrator know. On their side it shows as Enrolled, and its Overview tab shows the version and platform you're running:

The agent detail panel in Mesh, Overview tab, showing enrollment status enrolled alongside agent version, platform, agent ID and certificate expiry

Keeping it running

  • Restart it: docker restart axiad-edge-agent. The agent reuses its stored identity and reconnects — no new token needed. Heads up: a restart keeps the same settings the container started with. It won't pick up a new token or any changed -e / --env-file value, because a container's settings are fixed when you first run it. To change a setting — for example to fix a bad token — you have to recreate the container, not restart it: run docker rm -f axiad-edge-agent, then docker run again. (This is why a corrected token sometimes seems to "not take effect" — a plain restart ignored it.)

  • Stop it: docker stop axiad-edge-agent. It shuts down cleanly (boot: shutdown complete) and stays down until you start it again.

  • After a reboot: thanks to --restart unless-stopped, the agent starts on its own — as long as Docker starts with the machine (Step 1).

  • Certificate renewal: the agent's certificate lasts 90 days, and the agent renews it automatically about 7 days before it expires — over its existing connection, with no new token and no restart. The only way this breaks is if the agent stays completely offline for the full 90 days; then the certificate lapses and your administrator issues a new enrollment token.

  • Upgrade to a new version: there's no automatic update. To move to a newer version, download the new tag and recreate the container (1.1.0 here is an example — use the version you're upgrading to):

    docker pull axiadpublicregistry.azurecr.io/mesh-edge-agent:1.1.0
    docker rm -f axiad-edge-agent
    docker run -d --name axiad-edge-agent --restart unless-stopped --user 0:0 \
    -e ENROLL_TOKEN="" \
    -e MESH_SSRF_ALLOW_PRIVATE=1 \
    -e STRICT_CONFIG_SIGNING=true \
    -v mesh-edge-data:/var/lib/mesh-edge \
    axiadpublicregistry.azurecr.io/mesh-edge-agent:1.1.0

    Your mesh-edge-data storage keeps the agent's identity through the upgrade, so you don't need a new token — you can leave ENROLL_TOKEN empty. Your administrator can see the running version on the agent's Overview tab in Mesh.

  • Remove it: if your administrator decommissions the agent in Mesh, it shuts down and won't reconnect. To retire the machine yourself, remove the container and its stored data:

    docker rm -f axiad-edge-agent
    docker volume rm mesh-edge-data

Behind a proxy

If this machine reaches the internet through an HTTP proxy, tell the container about it the usual Docker way — add -e HTTPS_PROXY=http://proxy.example.com:8080 to your docker run command.

Troubleshooting

SymptomWhat to do
Cannot connect to the Docker daemon at unix:///var/run/docker.sockDocker isn't running. Start it with sudo systemctl start docker (or start Docker Desktop), then redo Step 1.
Logs show enroll: ENROLL_TOKEN expiredThe token ran out before the agent joined, and can't be reused. Ask your administrator to register the agent again, then run the command with the new token.
Logs show enroll: ENROLL_TOKEN required...The token never reached the container. Check that -e ENROLL_TOKEN="$ENROLL_TOKEN" is in your command.
Logs show config: ENROLL_TOKEN is set but emptyThe token variable is there but empty — usually a paste that didn't land, or a new terminal window where it was lost. Redo the read -rs ENROLL_TOKEN && export ENROLL_TOKEN step from Step 2, use the "Double-check the paste" check, and run the agent again.
Logs show config: gateway address unknownThe token was missing or empty, so the agent couldn't find your Mesh address inside it. Check the token landed with echo "${#ENROLL_TOKEN}" (should not be zero) and re-paste it in the same terminal window. You don't need to set MESH_GATEWAY — the address comes from the token.
The token looks set, but the agent still says it's missing or emptyEither it was lost when you switched terminal windows (re-paste it in the same one), or you changed the token and only restarted the container. A restart keeps the old settings — recreate it instead: docker rm -f axiad-edge-agent, then docker run again with the correct token.
Logs show MESH_GATEWAY="..." overrides the enrollment token's gateway "..." and the agent won't startSomething set MESH_GATEWAY to a different address than the one in your token. The agent refuses to join one Mesh environment and connect to another. Remove the MESH_GATEWAY setting and let the token decide, or ask your administrator for a token for the environment you meant to use.
Logs show certificate signed by unknown authorityThe agent connected to the wrong Mesh environment — easy to do by pointing at the wrong address. Double-check any MESH_GATEWAY setting, and make sure you copied the command from the right environment.
docker exec axiad-edge-agent agent status says Container ... is restarting or ... is not runningdocker exec only works while the container is up. Use the throwaway-container trick under Step 3 to read status, and check docker logs axiad-edge-agent for the last error.
You never see agent.connect okThe machine can't reach Mesh on port 443. Check your outbound firewall and DNS.
Your administrator sees the agent as Enrolled but Stale in MeshJoining Mesh and staying connected are two separate steps — the agent can join successfully but then fail to keep its connection open. Check the logs for agent.connect ok; if it's not there, it's the same port-443 problem as the row above.
A connector test can't reach an internal systemMake sure the machine can reach that system, and that MESH_SSRF_ALLOW_PRIVATE=1 is set.
tip

Need more detail while troubleshooting? Add -e MESH_LOG_LEVEL=debug to your docker run command for more verbose logs.

Verify

You're done when:

  • docker info succeeds — Docker is installed and running.
  • docker logs shows enroll: success and agent.connect ok.
  • docker exec axiad-edge-agent agent status shows agent kid=....
  • Your administrator sees the agent as Enrolled in Mesh.