Skip to main content
The Odigos VM Agent is available as part of Odigos Pro. For access and licensing details, contact us.
This deployment runs the agent daemon on every container instance plus one odigos-ecs-proxy task per cluster. The agents dial the proxy instead of Central, so the proxy is the cluster’s single upstream connection and the whole cluster appears in Odigos Central as one platform — with an aggregated workload list, cluster-wide configuration, a config journal for nodes that join later, and an optional coverage check. This guide is a superset of Install: Agent Only: same agent, same task definition, plus one component. If you don’t need cluster-wide aggregation, that guide is simpler.
Complete the System Requirements first. You need both images here: odigos-ecs-agent and odigos-ecs-proxy.

Deployment order

Deploy the proxy first, then the agents. That way the agents connect on their very first boot, with the correct proxy address baked into their first task definition revision — no retry-loop noise and no redeploy.
1

Choose the proxy's stable address

Internal NLB (preferred), or a pinned instance for test/dev.
2

Deploy the proxy

One task per cluster, listening on TCP 4321.
3

Deploy the agent daemon

Enable the proxy, with ODIGOS_ECS_BEHIND_PROXY=true.

Step 1: Set your session variables

Run every command in this guide in the same shell.

Step 2: License token and IAM roles

Identical to the Agent-only guide — the agent needs the license token; the proxy never touches it. Both task definitions reuse the same two roles.
The proxy’s coverage check reports ACTIVE container instances that have no agent connected — the check that catches a daemon that failed to place, a crash-looping agent, or a license failure. It calls the ECS/EC2 inventory APIs:
Without these permissions, leave ODIGOS_COVERAGE_CHECK unset — everything else works.

Step 3: Give the proxy a stable address

The agents need one fixed host:4321 reachable from the container instances. That is the proxy’s only networking requirement — no Cloud Map, no service discovery. Pick one of two options.
Option B (pinned instance) is for test and development only. If that instance is replaced, the proxy’s address changes and you must re-point both the placement constraint and the agents. See the pinned-IP caveat. Use Option A (internal NLB) in production.
An internal Network Load Balancer is the production method: it survives instance and task replacement. The proxy runs with awsvpc networking and registers its ENI IP in the target group.
The NLB DNS name is the agents’ endpoint:
Keep "networkMode": "awsvpc" and the portMappings block in the proxy task definition below.
The container instances’ security group must allow TCP 4321 — from the NLB (Option A) or from the other instances (Option B).

Step 4: Register the proxy task definition

Save this as odigos-ecs-proxy.json.
Option A (NLB) keeps the file as-is. Option B (pinned instance) requires two edits: change "networkMode": "awsvpc" to "host", and remove the portMappings block.
ODIGOS_CLUSTER_NAME becomes the platform name in Central. Drop ODIGOS_COVERAGE_CHECK if you did not grant the coverage permissions in Step 2. See the proxy environment variables for the full list. To keep the config journal across task replacement, add the EFS volume shown in persist the config journal on EFS.

Step 5: Create the proxy service

The proxy is a singleton — one task per cluster. Use the tab for the address option you chose in Step 3.
Wait for the proxy to come up and connect to Central before continuing:

Step 6: Register the agent task definition

Use the same task definition as the Agent-only guide, with two differences: the endpoint is the proxy’s, and ODIGOS_ECS_BEHIND_PROXY is true.
ODIGOS_ECS_BEHIND_PROXY=true matters. The agent cannot tell a proxy address from a Central address — both are just host:port — and the two modes report different platform names. Behind the proxy, each agent identifies itself by node hostname (the proxy is what reports the cluster name upstream, and its coverage check matches agent names against the instances’ private DNS). If you leave it false here and every agent registers under the cluster name instead, which makes the coverage check report all instances as uncovered.

Step 7: Create the agent daemon service

Because the proxy was already live, agents connect on their first boot. For later changes, use update-servicecreate-service is one-time.

Step 8: Verify

1

Every instance runs an agent, on a supported kernel

2

Agents are connected to the proxy

Expect a connection to <PROXY_ENDPOINT> and no runtime-detector stopped errors.
3

The proxy sees every agent

The proxy’s /healthz returns the full membership view: connected agents (id, node, version, connected-at), tombstones for departed nodes, and the last coverage result.
The proxy image is slim and ships no curl — use bash’s /dev/tcp inside the session:
The number of connected agents should match your container-instance count.
4

Central shows one platform for the cluster

Open the Central UI: one platform named after the ECS cluster (not one per node), with workloads aggregated across all nodes.

Caveat: the pinned proxy address

With Option B, if the pinned instance is replaced (instance failure, ASG replacement, manual termination) the proxy’s address changes. You must:
  1. Re-run Step 3 against a live instance to get a new EC2_ID and PROXY_ENDPOINT.
  2. Re-create the proxy service with the new placement constraint.
  3. Re-point every agent’s ODIGOS_DEFAULT_CONFIG at the new endpoint, register a new revision, and update-service --force-new-deployment.
If that fragility is unacceptable, use Option A (internal NLB) — it survives instance and task replacement at the cost of one extra AWS resource.

Persist the config journal on EFS

By default the journal is a file on the proxy task’s local storage (/var/lib/odigos-ecs-proxy/journal.jsonl). Task replacement loses it. Agents already persist their own config, so a healthy cluster is unaffected — the journal only closes the gap for a node that was absent when a change was made. If that gap matters, put the journal on EFS. ODIGOS_PROXY_JOURNAL is a file path, not a directory. Mount EFS at a directory and point the variable at a file inside it. Per-agent replay cursors are written next to that file (journal.jsonl.cursors.json), so the whole directory must be on the volume. Add a volume and mount to the proxy task definition, and set the environment variable:
Merge those fields into odigos-ecs-proxy.json — do not replace the rest of the task definition. Then:
  • Create the file system in the same VPC as the proxy, with a mount target in each subnet the task can land in.
  • Allow NFS (TCP 2049) from the proxy’s security group to the EFS mount targets (Option A: the task’s awsvpc security group; Option B: the container instances’ security group).
  • Grant the task role elasticfilesystem:ClientMount and elasticfilesystem:ClientWrite on that file system. If you enable IAM authorization on the volume (authorizationConfig.iam: ENABLED), also set elasticfilesystem:ClientRootAccess or use an access point whose POSIX user the proxy can write as.
An existing EFS file system is fine. This is optional: skip it if replaying missed mutations from Central after a proxy replacement is acceptable.

Current limits

  • Journal durability — without EFS, the config journal is lost when the proxy task is replaced. See persist the config journal on EFS.
  • Per-node workload entries — workload lists are concatenated across nodes, so a service with tasks on several nodes currently appears once per node.
  • Single-node targeting — profiling jobs and diagnose bundles are served by one agent; targeting a specific node is not yet supported.
  • Coverage matching — instances are correlated to agents by hostname; an instance whose private DNS cannot be resolved is conservatively reported as uncovered.

Next steps

Add Sources

Choose which ECS tasks to instrument — cluster-wide.

Add Destinations

Send the telemetry to your observability backend.

Configuration Reference

Agent and proxy environment variables.

Troubleshooting

Logs, odictl, /healthz, and common failures.