Skip to main content
Version: Next

Run Agent Manager on a VM with Docker

Not recommended for production use

Both installation paths on this page Simple and Advanced are intended for evaluation, demos, and proof-of-concept use only. Do not use them to run production workloads or to handle sensitive or regulated data.

For production, run Agent Manager on a properly operated Kubernetes platform with high availability, a managed and backed-up database, secret management, monitoring, and a hardened, redundant ingress following your organization's production practices. Use these installers to try Agent Manager out, not to run it for real.

Stronger agent isolation tiers

Agents run sandboxed under the standard runc runtime by default. Agent Manager also supports stronger per-environment isolation tiers, gVisor (userspace kernel) and Kata Containers (per-agent VM), but they have hardware/OS requirements and need a dedicated node. For more information, see the gVisor and Kata Containers setup guides.

Install Agent Manager on a Linux VM where Docker is the only host dependency. Pick the path that fits you:

  • Simple: give the installer the VM's public IP and it does everything else: hostnames are derived from the IP via sslip.io and TLS certificates are issued automatically by Let's Encrypt. No domain, no DNS setup, no certificate handling. Best for demos and quick evaluations.
  • Advanced: a config-file-driven installer for a custom domain, on a VM that is either publicly reachable or private-network-only. Choose how TLS is handled: automatic Let's Encrypt, the DNS-01 challenge for a private VM, your own certificate, a generated local CA, or a load balancer in front. Adds pre-flight validation of your config, certificates, and DNS.

The simple installer exposes the platform over HTTPS using sslip.io hostnames derived from the VM's public IP, so there's no domain registration.

Prerequisites​

You need an SSH client to log into the VM. On the VM itself, install the tools below before running the installer. It verifies they are present and exits with install hints if any are missing; it does not install host tooling for you. The whole stack runs on Docker: k3d runs the Kubernetes cluster as Docker containers, and Caddy runs as a container.

ToolVersionPurpose
Dockerv26+ (8 GB RAM, 4 CPU)Container runtime
k3dv5.8+Local Kubernetes cluster
kubectlv1.33+Kubernetes CLI
Helmv3.12+Package manager

curl and lsof are also required. They are usually preinstalled, but on a minimal image install them with your OS package manager (for example sudo apt-get install -y curl lsof).

Verify everything is installed:

docker --version
k3d --version
kubectl version --client
helm version --short

Verify the Docker daemon is running:

docker info > /dev/null

The VM also needs:

  • A static (reserved) public IP and SSH access (sudo). The install derives every hostname, TLS certificate, and OAuth issuer from the IP (*.amp.<IP>.sslip.io), so a changing IP breaks the install, and stopping the VM (for example to resize its disk) releases an ephemeral IP. Reserve the address before installing. If the IP ever changes, reinstall against the new IP.
  • At least 50 GB of disk. Building and running agents pushes the in-cluster image store past 13 GB; on a smaller disk the node hits DiskPressure, which evicts pods and can take cluster DNS down mid-build.
  • Inbound 443/tcp open in the cloud security group / firewall, and only 443. Certificates issue via the TLS-ALPN-01 ACME challenge, which runs inside the :443 TLS handshake, so no inbound port 80 is ever needed. The :443 exposure must be TCP passthrough (not a TLS-terminating load balancer in front), since the challenge happens inside the handshake.

Install​

SSH into the VM and run the one-command installer with sudo. It downloads a single versioned install bundle (no repository clone) and runs from it:

# on the VM (Docker, k3d, kubectl, helm already installed)
curl -fsSL https://github.com/wso2/agent-manager/releases/download/amp/v0.0.0-dev/bootstrap.sh \
| sudo bash -s -- simple \
--host <VM_PUBLIC_IP> \
--version 0.0.0-dev \
--email you@example.com

Pass --host the VM's public IPv4 address. A cloud VM usually can't read its own public IP (it's NAT'd behind the address you used to SSH in), so the installer needs it to build the *.amp.<IP>.sslip.io hostnames.

The installer runs in two phases: preflight (verify the required tools + open the firewall) and the platform install + Caddy startup. Allow 8-15 minutes. It needs sudo because it opens the firewall and creates the cluster. Downloading one bundle instead of cloning the repo and fetching each file separately avoids the GitHub rate-limiting that can throttle a per-file install.

Options​

FlagDefaultPurpose
--host(required)The VM's public IPv4 address
--version(required)Agent Manager release to install; an existing amp/v* release (the bootstrap.sh URL embeds the same version)
--email(none)ACME contact for expiry notices
--no-external-gatewaysoffDrop the gateway control-plane endpoint if you won't connect external gateways

What gets exposed​

The installer fronts the stack with Caddy, an open-source web server that terminates TLS, obtains and renews Let's Encrypt certificates automatically, and reverse-proxies each public hostname to the right service. It runs as a single amp-caddy Docker container and is the only process listening on the internet-facing ports.

Only :443 faces the internet; all other service ports are bound to the VM's loopback and reached only by Caddy.

Every public hostname resolves to the VM's IP (via sslip.io) and arrives at Caddy on :443; Caddy terminates TLS and reverse-proxies to the matching loopback port. The Agent Manager services are ClusterIP inside the cluster: Caddy forwards the console, API, Thunder, gateway-control-plane, and per-environment Thunder hosts to the OpenChoreo control-plane kgateway (loopback :8080), the observer host to the observability-plane kgateway (loopback :11080), and the OTel-ingest host plus the deployed-agent wildcard to the data-plane kgateway (loopback :19080). Each gateway routes by the preserved Host header. Certificates are obtained over that same :443 using the TLS-ALPN-01 challenge, so no inbound port 80 is needed.

Two of these tiers are dynamic: a new host appears the first time you deploy into a new org/project, and each time you create an environment. A wildcard certificate cannot be issued for them via TLS-ALPN-01 up front, so Caddy issues one concrete certificate per hostname on demand, at the first request to it.

URLPurpose
https://console.amp.<IP>.sslip.ioConsole UI
https://api.amp.<IP>.sslip.ioAgent Manager API (used by amctl)
https://thunder.amp.<IP>.sslip.ioThunder OAuth (login)
https://<org>-<env>.thunder.<IP>.sslip.ioPer-environment Thunder (one host per environment, created on demand)
https://observer.amp.<IP>.sslip.ioAgent Manager Observer
https://gateway.amp.<IP>.sslip.io/otelOTel trace ingest for externally-hosted agents (see below)
https://<org>-<project>.agents.<IP>.sslip.io/...Deployed-agent invocation endpoints (one wildcard host per org/project)
https://cp.amp.<IP>.sslip.ioGateway control plane; connect external gateways here (on by default)
Agents deployed on this VM do not use the public OTel host

gateway.amp.<IP>.sslip.io/otel exists for agents running outside the platform, which set AMP_OTEL_ENDPOINT themselves. Agents deployed by Agent Manager run inside the cluster and export their traces straight to the in-cluster gateway runtime instead, so their traffic never leaves the VM or passes through Caddy.

Log in​

Open https://console.amp.<IP>.sslip.io and sign in with the seeded admin user admin (password admin). This user holds the Agent Manager Admin role, which grants full administrative permissions for both console and API access.

The admin account is provisioned with the Agent Manager Admin role during bootstrap, so API calls are authenticated and authorized. Use the same credentials for both console login and API access via Bearer token authentication.

Deployed-agent invocation​

When you deploy an agent, its endpoint is published on a per-project host <org>-<project>.agents.<IP>.sslip.io and routed by Caddy to the OpenChoreo data-plane gateway. Because these hostnames are dynamic (a new one per org/project), Caddy issues their TLS certificates on demand at the first request (via the same ACME challenge as the fixed hosts), rather than up front. Invocations are authenticated with a user token that the gateway validates against the public Thunder issuer.

Because issuance is on demand and uses TLS-ALPN-01 (the challenge runs inside the :443 handshake), the very first request to a newly-deployed agent host can fail with a one-time certificate error. That first connection is consumed by Caddy answering the ACME challenge, so the client briefly sees the challenge certificate instead of the real one. Every client hits this; only the wording differs. Chromium-based browsers (Chrome, Edge, Brave) report ERR_CERTIFICATE_TRANSPARENCY_REQUIRED, while other browsers and command-line clients report their own untrusted-certificate error. Issuance completes within a second or two; reload the page (or open it in a fresh tab) and it serves the trusted Let's Encrypt certificate. This only affects the first hit per new agent host; the certificate is then cached in the amp-caddy-data volume.

The same applies to the per-environment Thunder hosts (<org>-<env>.thunder.<IP>.sslip.io): they are created when you add an environment and get their certificates on demand the same way, so the first request to a brand-new environment's Thunder can show the same one-time error.

amp-api advertises each agent endpoint with the https:// scheme (the installer sets tlsEnabled on the service), so the console (and any other caller) invokes it over TLS directly through the wildcard site.

TLS​

Caddy obtains and auto-renews trusted Let's Encrypt certificates on first start, with no manual certificate steps. Issuance uses the TLS-ALPN-01 challenge, which runs inside the :443 TLS handshake, so only inbound 443 is ever required and there is no port-80 dependency. Certificates and the ACME account persist in the amp-caddy-data Docker volume, so restarts do not re-request them.

Because the challenge happens inside the TLS handshake, the public :443 must reach Caddy as raw TCP; do not put a TLS-terminating load balancer in front of the VM. There is no :80 listener, so plain http:// URLs are not served (no automatic http→https redirect); always use the https:// URLs the installer prints.

Persistence and teardown​

Application data (PostgreSQL), issued certificates, and the k3d cluster persist across Docker/host restarts via named volumes. Everything the installer created lives either inside the k3d cluster or in the Caddy container and its two volumes, so tearing down is the three commands below, plus one optional cleanup:

sudo k3d cluster delete amp-local # delete the cluster (workloads + app data)
sudo docker rm -f amp-caddy # remove the Caddy front door
sudo docker volume rm amp-caddy-data amp-caddy-config # drop the cached certs + ACME account

sudo rm -f /opt/amp/Caddyfile # optional: the generated Caddy config

Use sudo; the installer runs Docker and k3d as root. Note that the installer leaves no repository checkout on the VM, because bootstrap.sh unpacks the versioned bundle into a temporary directory and deletes it on exit. Teardown is therefore done with the commands above rather than an uninstall script. Deleting the cluster removes the platform's data; deleting the Caddy volumes discards the issued certificates and the ACME account, so a reinstall re-requests them from Let's Encrypt (which counts against its rate limits).

Connect an external gateway​

Agent Manager can drive external WSO2 AI gateways. The control-plane endpoint https://cp.amp.<IP>.sslip.io is exposed by default for this. In the console, open Infrastructure → Gateways, generate a registration token, and follow the generated commands, which point the gateway at cp.amp.<IP>.sslip.io:443, where it opens a control WebSocket and pulls its configuration. If you do not need external gateways, install with --no-external-gateways to drop this endpoint.

Security: the registration token grants a gateway your LLM-provider API keys and proxy credentials. Treat it as a secret, revoke/regenerate it from the Gateways page when a gateway is decommissioned, and optionally restrict cp.amp... to known gateway source IPs at the firewall.

Troubleshooting​

  • Certificates never issue / hosts unreachable from outside. Open inbound :443 in your cloud security group / NACL, and make sure the public :443 reaches the VM as raw TCP: a TLS-terminating load balancer in front breaks the TLS-ALPN-01 challenge. The installer can't verify external reachability from inside the VM, so this surfaces as Caddy failing to obtain certificates (docker logs amp-caddy).
  • Certificate not issued. Check docker logs amp-caddy. Let's Encrypt rate limits on sslip.io are high but not infinite; if hit, retry shortly.
  • Login redirect mismatch. Confirm you reached the console via its console.amp.<IP>.sslip.io URL, not the raw IP.
  • Certificate error on first agent invocation (ERR_CERTIFICATE_TRANSPARENCY_REQUIRED in Chromium-based browsers, an untrusted-certificate warning elsewhere): the per-agent certificate is issued on demand, and the first request races with that issuance. Reload the page after a second or two; it only happens once per new agent host (see Deployed-agent invocation).