# ECS

{% columns %}
{% column %}
Deploy Alma on Amazon ECS to **monitor runtime network traffic** with zero app code changes.

Alma runs the **Packet Sensor** as a **sidecar container** in your ECS tasks.

It captures traffic and forwards it to an **Alma Receiver** in your VPC.

You get visibility into **95%+ of common application protocols** out of the box.

If you’re new to Alma, start with [Alma Overview](/about-alma/quickstart.md).
{% endcolumn %}

{% column %}
![Alma Packet Sensor on ECS overview](/files/sX8IbuzQGPmBsEyV3YkI)
{% endcolumn %}
{% endcolumns %}

### How it works

When installed, this setup adds:

* **Alma Packet Sensor (sidecar)** attached to your existing ECS task definitions.
* **Alma Receiver (EC2 instance)** deployed to receive and process captured packets.

For best performance, deploy the receiver in the **same VPC** as your tasks.

Use the **same subnet** when possible.

### Prerequisites

* Access to your ECS cluster and task definitions.
* Basic familiarity with ECS task definition structure.
* AWS CLI configured for the target account.
* Terraform **v1.3+**.

### Install (Terraform)

{% stepper %}
{% step %}

### 1) Identify your VPC and subnet IDs

The Alma Receiver EC2 instance must be deployed in the **same VPC** as your ECS tasks.

#### Option A: AWS Console

1. Open the Amazon ECS console.
2. Select your cluster.
3. Select your service.
4. Open the **Networking** tab.
5. Under **Network configuration**, note the **VPC** value.
6. If VPC is not shown, open a **Subnet** link.
7. The Subnet details page shows the **VPC ID** at the top.

#### Option B: AWS CLI

Get a subnet ID from the service:

```bash
# List services in a cluster
aws ecs list-services --cluster YOUR_CLUSTER_NAME

# Get one subnet ID from the service
aws ecs describe-services \
  --cluster YOUR_CLUSTER_NAME \
  --services YOUR_SERVICE_NAME \
  --query 'services[0].networkConfiguration.awsvpcConfiguration.subnets[0]' \
  --output text
```

Get the corresponding VPC ID:

```bash
SUBNET_ID=$(
  aws ecs describe-services \
    --cluster YOUR_CLUSTER_NAME \
    --services YOUR_SERVICE_NAME \
    --query 'services[0].networkConfiguration.awsvpcConfiguration.subnets[0]' \
    --output text
)

aws ec2 describe-subnets \
  --subnet-ids "$SUBNET_ID" \
  --query 'Subnets[0].VpcId' \
  --output text
```

{% hint style="info" %}
If you provide only a VPC ID, Terraform will auto-select the **first available subnet** in that VPC.
{% endhint %}
{% endstep %}

{% step %}

### 2) Configure Terraform variables

Create or update `terraform.tfvars`:

```hcl
# Required: VPC ID (subnet is optional)
alma_receiver_vpc_id    = "vpc-0a1b2c3d4e5f6g7h8" # replace with your VPC ID

# Optional: if empty, a subnet is auto-selected
alma_receiver_subnet_id = ""

# Deploy an Alma Receiver EC2 instance (set false if you already run one)
deploy_alma_receiver = true
```

After `terraform apply`, fetch the receiver private IP:

```bash
terraform output alma_receiver_private_ip
```

{% endstep %}

{% step %}

### 3) Attach the Packet Sensor sidecar to your ECS task definition

You have two options.

#### Option A: Use the automation script

Use this when your Terraform builds containers via `jsonencode`.

The script appends the Alma sidecar container to your existing task definition.

It also creates a backup of `main.tf`.

#### Option B: Add the sidecar manually

Append the sidecar to `container_definitions`.

Example:

```hcl
resource "aws_ecs_task_definition" "your_task" {
  family = "your-app"
  # ... other configuration

  container_definitions = jsonencode([
    {
      name  = "your-app"
      image = "your-image:latest"
      # ... your app container config
    },
    {
      name      = "alma-packet-sensor"
      image     = "public.ecr.aws/r1b5k6e6/alma-packet-sensor:0.0.1"
      essential = false
      environment = [
        {
          name  = "CAPTURE_BPF_FILTER"
          value = "tcp"
        },
        {
          name  = "SERVER_ADDRESS"
          value = var.deploy_alma_receiver && var.alma_receiver_vpc_id != "" ?
            aws_instance.alma_receiver[0].private_ip :
            var.alma_server_address
        }
      ]
    }
  ])
}
```

{% endstep %}
{% endstepper %}

### Alternative: use an existing receiver

Use this when you already have a receiver running.

{% hint style="warning" %}
Prefer a stable address (private DNS or a static private IP). Avoid hardcoding an ephemeral IP.
{% endhint %}

```hcl
{
  name      = "alma-packet-sensor"
  image     = "public.ecr.aws/r1b5k6e6/alma-packet-sensor:0.0.1"
  essential = false
  environment = [
    { name = "CAPTURE_BPF_FILTER", value = "tcp" },
    { name = "SERVER_ADDRESS", value = "10.10.2.124" }
  ]
}
```

### Validate

1. Deploy a new task revision with the sidecar attached.
2. Confirm the service stabilises and tasks are running.
3. Confirm the receiver instance is reachable from the task subnet.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.alma-security.com/integrations/ecs.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
