> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/harness-platform/use-harness-platform/delegates/delegate-3x-closed-beta/install-a-delegate/install-delegate-ecs-fargate.md).

# Install a Delegate on Amazon ECS or AWS Fargate

{% hint style="warning" %}
**CLOSED BETA**

Delegate 3.x is currently in closed beta and available only to select users. Access is determined by the product team. See [Feature Parity](/harness-platform/use-harness-platform/delegates/delegate-3x-closed-beta/feature-parity.md) for current supported use cases.
{% endhint %}

This guide walks you through installing Delegate 3.x on Amazon Elastic Container Service (ECS) or AWS Fargate. The delegate runs as a container in your ECS cluster and connects to Harness to execute CI builds and other tasks. For supported connectors, CI steps, secret managers, and module support by deployment type, see the [Feature Parity](/harness-platform/use-harness-platform/delegates/delegate-3x-closed-beta/feature-parity.md) page.

{% hint style="info" %}
To learn more about Delegate 3.x, including architecture and how it compares to the legacy delegate, see the [Delegate 3.x Overview](/harness-platform/use-harness-platform/delegates/delegate-3x-closed-beta/delegate-overview.md).
{% endhint %}

### Important considerations <a href="#important-considerations" id="important-considerations"></a>

Before deploying the delegate on ECS or Fargate, review the following information:

* **Feature parity with Kubernetes:** Delegate 3.x on ECS targets the same capabilities as Kubernetes delegates, including CI builds, CD deployments, and Database DevOps tasks. Go to the [Feature Parity](/harness-platform/use-harness-platform/delegates/delegate-3x-closed-beta/feature-parity.md) page to verify support for your specific connectors and pipeline steps.
* **Manual updates required:** Delegates deployed on ECS do not auto-update. You must manually update the delegate by deploying a new task definition with the latest image. Harness recommends updating every 3 to 6 months to balance security and feature updates.
* **Infrastructure limits on Fargate:** When using AWS Fargate, tasks that exceed the specified CPU or memory limits will be terminated by AWS. This is a limitation of Fargate infrastructure. If you need more flexibility with resource limits, consider using ECS on EC2 instances or a Kubernetes-based deployment.
* **Docker image compatibility:** Delegate 3.x uses a different Docker image than legacy delegates. Ensure you use the correct image format for Delegate 3.x deployments.
* **Network requirements:** The delegate requires outbound HTTPS (443), HTTP (80 for package managers), SSH (22 for Git), and Git protocol (9418) connectivity. The security group must allow these outbound connections.

### Get Harness credentials <a href="#get-harness-credentials" id="get-harness-credentials"></a>

Before installation, obtain your Account ID, Delegate Token, and Harness URL from the Harness platform.

{% tabs %}
{% tab title="Interactive Guide" %}
{% embed url="<https://app.tango.us/app/embed/Get-Delegate-2-0-Credentials-41d069778e3e421d8791dd4dcc8ab793>" %}
Get credentials for Delegate 3.x
{% endembed %}
{% endtab %}

{% tab title="Step-by-Step" %}

1. **Open Delegate settings:** In the left nav, go to **Project Settings**, then under **Project-level Resources**, click **Delegates**.
2. **Create a new delegate:** Click **+ New Delegate** and choose **Docker** as your delegate type.
3. **Copy the credentials** from the `docker run` command:

   * `ACCOUNT_ID` → Your Account ID
   * `DELEGATE_TOKEN` → Your Delegate Token
   * `MANAGER_HOST_AND_PORT` → Your Harness URL (e.g., `https://app.harness.io`)

   ![](/files/KwcthBMMTFwCSXdvpMWa)

{% hint style="info" %}
Keep these values ready — you'll use them in the task definition.
{% endhint %}
{% endtab %}
{% endtabs %}

***

### Choose your deployment type <a href="#choose-your-deployment-type" id="choose-your-deployment-type"></a>

Delegate 3.x supports two ECS deployment types: **Fargate (serverless)** and **EC2 (container instances)**. Choose based on your requirements:

| Feature                       | Fargate                                             | ECS on EC2                                          |
| ----------------------------- | --------------------------------------------------- | --------------------------------------------------- |
| **Infrastructure management** | Fully managed (serverless)                          | Requires managing EC2 instances                     |
| **Docker-in-Docker**          | ❌ Not supported                                     | ✅ Supported via Docker socket                       |
| **Privileged containers**     | ❌ Not supported                                     | ✅ Supported                                         |
| **Ephemeral storage**         | Up to 200 GiB                                       | Unlimited (depends on instance)                     |
| **Task startup time**         | 30-60 seconds                                       | Faster (10-20 seconds)                              |
| **Use cases**                 | CD deployments, DB DevOps, CI builds without Docker | CI builds with Docker, advanced container workflows |
| **Cost**                      | Pay per task (vCPU + memory)                        | Pay for EC2 instances (even when idle)              |

**Recommendation:**

* Use **Fargate** for most deployments (simpler, no instance management)
* Use **EC2** if you need Docker-in-Docker for building container images in CI pipelines

***

### Deploy a delegate to Amazon ECS <a href="#deploy-a-delegate-to-amazon-ecs" id="deploy-a-delegate-to-amazon-ecs"></a>

Use these steps to deploy a delegate to an ECS cluster running on EC2 instances. The delegate runs as an ECS service and connects to your AWS resources.

#### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* An active AWS account with permissions to create ECS resources
* AWS CLI installed and configured
* An existing ECS cluster or permissions to create one

#### Step 1: Create an ECS cluster <a href="#step-1-create-an-ecs-cluster" id="step-1-create-an-ecs-cluster"></a>

If you don't already have an ECS cluster, create one using the AWS Console or CLI.

**Using AWS Console:**

1. Go to the [Amazon ECS Console](https://console.aws.amazon.com/ecs/).
2. Click **Clusters** in the left navigation, then click **Create Cluster**.
3. Choose **EC2 Linux + Networking** as the cluster template.
4. Configure your cluster:
   * **Cluster name:** Enter a name (e.g., `harness-delegate-cluster`)
   * **EC2 instance type:** Select an instance type with at least 2 GB RAM (e.g., `t3.small` or larger)
   * **Number of instances:** Start with 1 instance
   * **Networking:** Use your default VPC and subnets, or create new ones
5. Click **Create** and wait for the cluster to be ready.

**Using AWS CLI:**

```bash
aws ecs create-cluster --cluster-name harness-delegate-cluster
```

#### Step 2: Create the task definition <a href="#step-2-create-the-task-definition" id="step-2-create-the-task-definition"></a>

The task definition specifies how the delegate container should run, including environment variables, resource limits, and the Docker image.

1. Copy the following JSON into a file named `task-definition.json`:

   ```json
   {
     "family": "harness-delegate-task",
     "containerDefinitions": [
       {
         "name": "harness-delegate",
         "image": "us-docker.pkg.dev/gar-prod-setup/harness-public/harness/delegate:3.0.0",
         "cpu": 1024,
         "memory": 2048,
         "essential": true,
         "environment": [
           {
             "name": "HARNESS_ACCOUNT_ID",
             "value": "PUT_YOUR_ACCOUNT_ID"
           },
           {
             "name": "HARNESS_TOKEN",
             "value": "PUT_YOUR_DELEGATE_TOKEN"
           },
           {
             "name": "HARNESS_URL",
             "value": "PUT_YOUR_HARNESS_URL"
           },
           {
             "name": "HARNESS_NAME",
             "value": "ecs-delegate"
           }
         ],
         "logConfiguration": {
           "logDriver": "awslogs",
           "options": {
             "awslogs-group": "/ecs/harness-delegate",
             "awslogs-region": "us-east-1",
             "awslogs-stream-prefix": "delegate"
           }
         }
       }
     ],
     "requiresCompatibilities": ["EC2"],
     "networkMode": "bridge",
     "cpu": "1024",
     "memory": "2048"
   }
   ```
2. Replace the placeholder values:

   | **Field**                 | **Description**                                                                           |
   | ------------------------- | ----------------------------------------------------------------------------------------- |
   | `PUT_YOUR_ACCOUNT_ID`     | Your Harness account ID from the [Get Harness credentials](#get-harness-credentials) step |
   | `PUT_YOUR_DELEGATE_TOKEN` | Your delegate token from Harness                                                          |
   | `PUT_YOUR_HARNESS_URL`    | Your Harness URL (e.g., `https://app.harness.io`)                                         |
   | `awslogs-region`          | The AWS region where your ECS cluster is located                                          |

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p><strong>SECURITY BEST PRACTICE</strong></p><p>For production deployments, store the <code>HARNESS_TOKEN</code> in AWS Secrets Manager instead of plaintext in the task definition. Replace the environment variable with a <code>secrets</code> array:</p><pre class="language-json"><code class="lang-json">"secrets": [
     {
       "name": "HARNESS_TOKEN",
       "valueFrom": "arn:aws:secretsmanager:REGION:ACCOUNT_ID:secret:harness/delegate-token"
     }
   ]
   </code></pre><p>For more information, go to <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html">Specifying sensitive data</a> in the AWS documentation.</p></div>
3. **Create CloudWatch Logs group** (required for logging):

   ```bash
   aws logs create-log-group --log-group-name /ecs/harness-delegate --region YOUR_AWS_REGION
   ```

   Replace `YOUR_AWS_REGION` with your AWS region (e.g., `us-east-1`, `us-west-2`).
4. **Register the task definition:**

   ```bash
   aws ecs register-task-definition --cli-input-json file://task-definition.json
   ```

#### Step 3: Create the ECS service <a href="#step-3-create-the-ecs-service" id="step-3-create-the-ecs-service"></a>

Create a service to run and maintain the delegate task.

**Using AWS CLI:**

```bash
aws ecs create-service \
  --cluster harness-delegate-cluster \
  --service-name harness-delegate-service \
  --task-definition harness-delegate-task \
  --desired-count 1 \
  --launch-type EC2
```

**Using AWS Console:**

1. Go to your ECS cluster in the AWS Console.
2. Click **Create** under the **Services** tab.
3. Configure the service:
   * **Launch type:** EC2
   * **Task Definition:** Select `harness-delegate-task`
   * **Service name:** `harness-delegate-service`
   * **Number of tasks:** 1
4. Click **Create Service**.

#### Step 4: Verify the delegate <a href="#step-4-verify-the-delegate" id="step-4-verify-the-delegate"></a>

1. Go to your Harness account.
2. Navigate to **Project Settings** > **Delegates**.
3. Verify that your delegate (named `ecs-delegate`) appears in the list with a **Connected** status.

   ![Delegate connected in Harness](/files/m1jTbh7FqUCeRJbl8mNY)

***

### Deploy a delegate to AWS Fargate <a href="#deploy-a-delegate-to-aws-fargate" id="deploy-a-delegate-to-aws-fargate"></a>

Use these steps to deploy a delegate to AWS Fargate. Fargate is a serverless compute engine for containers that removes the need to manage EC2 instances.

#### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* An active AWS account with permissions to create ECS and IAM resources
* AWS CLI installed and configured
* **VPC with subnets**: Minimum of 2 subnets in different Availability Zones, each with outbound internet access (public subnets via Internet Gateway, or private subnets via NAT Gateway)
* **Security group**: Must allow outbound traffic on ports 443, 80, 22, and 9418

#### Step 1: Create an ECS cluster <a href="#step-1-create-an-ecs-cluster" id="step-1-create-an-ecs-cluster"></a>

If you don't have an ECS cluster, create one for Fargate.

**Using AWS Console:**

1. Go to the [Amazon ECS Console](https://console.aws.amazon.com/ecs/).
2. Click **Clusters** in the left navigation, then click **Create Cluster**.
3. Choose **Networking only** (Fargate) as the cluster template.
4. Configure your cluster:
   * **Cluster name:** `harness-delegate-fargate-cluster`
5. Click **Create**.

**Using AWS CLI:**

```bash
aws ecs create-cluster --cluster-name harness-delegate-fargate-cluster
```

#### Step 2: Create an IAM execution role <a href="#step-2-create-an-iam-execution-role" id="step-2-create-an-iam-execution-role"></a>

Fargate requires an IAM execution role that grants ECS permission to pull container images and write logs.

1. Create a file named `trust-policy.json` with the following content:

   ```json
   {
     "Version": "2012-10-17",
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Service": "ecs-tasks.amazonaws.com"
         },
         "Action": "sts:AssumeRole"
       }
     ]
   }
   ```
2. Create the IAM role:

   ```bash
   aws iam create-role \
     --role-name ecsTaskExecutionRole \
     --assume-role-policy-document file://trust-policy.json
   ```
3. Attach the required policy:

   ```bash
   aws iam attach-role-policy \
     --role-name ecsTaskExecutionRole \
     --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
   ```

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>IAM PERMISSIONS REQUIRED</strong></p><p>The <code>ecsTaskExecutionRole</code> needs the following permissions:</p><ul><li><strong>ECR</strong>: Pull container images (<code>ecr:GetAuthorizationToken</code>, <code>ecr:BatchGetImage</code>, <code>ecr:GetDownloadUrlForLayer</code>)</li><li><strong>CloudWatch Logs</strong>: Create log groups and streams (<code>logs:CreateLogGroup</code>, <code>logs:CreateLogStream</code>, <code>logs:PutLogEvents</code>)</li><li><strong>Secrets Manager</strong> (if using secrets): Retrieve secrets (<code>secretsmanager:GetSecretValue</code>)</li></ul></div>

#### Step 3: Create the task definition <a href="#step-3-create-the-task-definition" id="step-3-create-the-task-definition"></a>

1. Copy the following JSON into a file named `fargate-task-definition.json`:

   ```json
   {
     "family": "harness-delegate-fargate-task",
     "networkMode": "awsvpc",
     "requiresCompatibilities": ["FARGATE"],
     "cpu": "1024",
     "memory": "2048",
     "executionRoleArn": "arn:aws:iam::PUT_YOUR_AWS_ACCOUNT_ID:role/ecsTaskExecutionRole",
     "containerDefinitions": [
       {
         "name": "harness-delegate",
         "image": "us-docker.pkg.dev/gar-prod-setup/harness-public/harness/delegate:3.0.0",
         "essential": true,
         "environment": [
           {
             "name": "HARNESS_ACCOUNT_ID",
             "value": "PUT_YOUR_ACCOUNT_ID"
           },
           {
             "name": "HARNESS_TOKEN",
             "value": "PUT_YOUR_DELEGATE_TOKEN"
           },
           {
             "name": "HARNESS_URL",
             "value": "PUT_YOUR_HARNESS_URL"
           },
           {
             "name": "HARNESS_NAME",
             "value": "fargate-delegate"
           }
         ],
         "logConfiguration": {
           "logDriver": "awslogs",
           "options": {
             "awslogs-group": "/ecs/harness-delegate-fargate",
             "awslogs-region": "us-east-1",
             "awslogs-stream-prefix": "delegate"
           }
         }
       }
     ]
   }
   ```
2. Replace the placeholder values:

   | **Field**                 | **Description**                                   |
   | ------------------------- | ------------------------------------------------- |
   | `PUT_YOUR_AWS_ACCOUNT_ID` | Your 12-digit AWS account ID                      |
   | `PUT_YOUR_ACCOUNT_ID`     | Your Harness account ID                           |
   | `PUT_YOUR_DELEGATE_TOKEN` | Your delegate token from Harness                  |
   | `PUT_YOUR_HARNESS_URL`    | Your Harness URL (e.g., `https://app.harness.io`) |
   | `awslogs-region`          | The AWS region where your cluster is located      |

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p><strong>SECURITY BEST PRACTICE</strong></p><p>For production deployments, store the <code>HARNESS_TOKEN</code> in AWS Secrets Manager instead of plaintext. Replace the environment variable with a <code>secrets</code> array as shown in the ECS section above.</p></div>
3. **Create CloudWatch Logs group** (required for logging):

   ```bash
   aws logs create-log-group --log-group-name /ecs/harness-delegate-fargate --region YOUR_AWS_REGION
   ```

   Replace `YOUR_AWS_REGION` with your AWS region (e.g., `us-east-1`, `us-west-2`).

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>The <code>ecsTaskExecutionRole</code> must have permissions to write logs to CloudWatch. If you encounter a <code>ResourceInitializationError</code> related to log creation, ensure the log group is created manually as shown above.</p></div>
4. **Register the task definition:**

   ```bash
   aws ecs register-task-definition --cli-input-json file://fargate-task-definition.json
   ```

#### Step 4: Create the service <a href="#step-4-create-the-service" id="step-4-create-the-service"></a>

Create a service configuration file to define networking and launch settings for Fargate.

1. Copy the following JSON into a file named `fargate-service.json`:

   ```json
   {
     "cluster": "harness-delegate-fargate-cluster",
     "serviceName": "harness-delegate-fargate-service",
     "taskDefinition": "harness-delegate-fargate-task",
     "launchType": "FARGATE",
     "desiredCount": 1,
     "networkConfiguration": {
       "awsvpcConfiguration": {
         "subnets": [
           "PUT_YOUR_SUBNET_ID"
         ],
         "securityGroups": [
           "PUT_YOUR_SECURITY_GROUP_ID"
         ],
         "assignPublicIp": "ENABLED"
       }
     },
     "platformVersion": "LATEST",
     "schedulingStrategy": "REPLICA"
   }
   ```
2. Replace the placeholder values:

   | **Field**                    | **Description**                                                                                                                                   |
   | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
   | `PUT_YOUR_SUBNET_ID`         | The subnet ID where the task should run. Use a public subnet if `assignPublicIp` is `ENABLED`, or a private subnet with NAT Gateway if `DISABLED` |
   | `PUT_YOUR_SECURITY_GROUP_ID` | A security group ID that allows outbound traffic to the internet (required for the delegate to communicate with Harness)                          |

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p><strong>SECURITY BEST PRACTICE</strong></p><p>For production deployments, use <code>"assignPublicIp": "DISABLED"</code> and place the task in a private subnet with a NAT Gateway. This ensures the delegate only has outbound connectivity to Harness and is not exposed to the public internet. The example above uses <code>ENABLED</code> for simplicity in getting started.</p></div>
3. **Find your subnet and security group IDs:**

   List available subnets:

   ```bash
   aws ec2 describe-subnets --query "Subnets[*].[SubnetId,VpcId,AvailabilityZone,CidrBlock]" --output table
   ```

   List security groups:

   ```bash
   aws ec2 describe-security-groups --query "SecurityGroups[*].[GroupId,GroupName,VpcId]" --output table
   ```
4. **Create the service:**

   ```bash
   aws ecs create-service --cli-input-json file://fargate-service.json
   ```

#### Step 5: Verify the delegate <a href="#step-5-verify-the-delegate" id="step-5-verify-the-delegate"></a>

1. Check the service status:

   ```bash
   aws ecs describe-services \
     --cluster harness-delegate-fargate-cluster \
     --services harness-delegate-fargate-service
   ```
2. Go to your Harness account.
3. Navigate to **Project Settings** > **Delegates**.
4. Verify that your delegate (named `fargate-delegate`) appears in the list with a **Connected** status.

   ![Delegate connected in Harness](/files/m1jTbh7FqUCeRJbl8mNY)

***

### Configure the delegate <a href="#configure-the-delegate" id="configure-the-delegate"></a>

After the delegate is installed, you can configure additional settings using environment variables in the task definition.

#### Common environment variables <a href="#common-environment-variables" id="common-environment-variables"></a>

| **Variable**         | **Description**                                                            | **Required**                        |
| -------------------- | -------------------------------------------------------------------------- | ----------------------------------- |
| `HARNESS_ACCOUNT_ID` | Your Harness account ID                                                    | Yes                                 |
| `HARNESS_TOKEN`      | Delegate token for authentication                                          | Yes                                 |
| `HARNESS_URL`        | Harness platform URL                                                       | Yes                                 |
| `HARNESS_NAME`       | Name for the delegate                                                      | No (defaults to `harness-delegate`) |
| `HARNESS_TAGS`       | Comma-separated list of tags for the delegate (e.g., `aws,ecs,production`) | No                                  |

For more configuration options, go to [Configure a Delegate](/harness-platform/use-harness-platform/delegates/delegate-3x-closed-beta/install-a-delegate/configure-delegate.md).

***

### Configure advanced settings <a href="#configure-advanced-settings" id="configure-advanced-settings"></a>

#### Security contexts <a href="#security-contexts" id="security-contexts"></a>

When the delegate executes CI/CD tasks, you can configure security contexts for task containers. These settings control container privileges and security options.

{% hint style="info" %}
Security contexts are configured through the Harness platform when defining pipeline steps, not in the delegate's task definition itself.
{% endhint %}

| **Field**                   | **Description**                                            | **Fargate**     | **EC2**     |
| --------------------------- | ---------------------------------------------------------- | --------------- | ----------- |
| `privileged`                | Run container in privileged mode with extended permissions | ❌ Not supported | ✅ Supported |
| `read_only_root_filesystem` | Mount the container's root filesystem as read-only         | ✅ Supported     | ✅ Supported |
| `run_as_user`               | UID to run the container process as                        | ✅ Supported     | ✅ Supported |
| `run_as_group`              | GID to run the container process as                        | ✅ Supported     | ✅ Supported |
| `add_capability`            | Linux capabilities to add (e.g., `NET_ADMIN`, `SYS_ADMIN`) | ✅ Supported     | ✅ Supported |
| `drop_capability`           | Linux capabilities to drop (e.g., `ALL`)                   | ✅ Supported     | ✅ Supported |

**Example security context configuration:**

When configuring a pipeline step in Harness, you can specify security settings that will be applied to the task containers:

* **Privileged containers**: Required for Docker-in-Docker workflows (EC2 only)
* **Read-only root filesystem**: Enhances security by preventing writes to the root filesystem
* **User/Group IDs**: Run processes as non-root users for better security
* **Capabilities**: Fine-grained control over Linux capabilities (e.g., add `NET_ADMIN` for network configuration)

#### Volume types <a href="#volume-types" id="volume-types"></a>

Delegate tasks can use different volume types for storing data and sharing files between containers.

**EmptyDir volumes**

Ephemeral storage that exists for the lifetime of the task. Useful for sharing data between containers in the same task.

| **Field**   | **Description**          | **Fargate**                              | **EC2**                         |
| ----------- | ------------------------ | ---------------------------------------- | ------------------------------- |
| `empty_dir` | Ephemeral storage volume | Up to 200 GiB                            | Unlimited (depends on instance) |
| `size_mib`  | Optional size in MiB     | Minimum 21 GiB (21,504 MiB) if specified | N/A                             |

**Example use case:** Sharing workspace files between build steps.

**HostPath volumes**

Bind mount from the host filesystem (EC2 only). Useful for accessing Docker socket or host directories.

| **Field**   | **Description**           | **Fargate**     | **EC2**     |
| ----------- | ------------------------- | --------------- | ----------- |
| `host_path` | Path on the host to mount | ❌ Not supported | ✅ Supported |
| `read_only` | Mount as read-only        | ❌ Not supported | ✅ Supported |

**Example use case:** Mounting Docker socket (`/var/run/docker.sock`) for Docker-in-Docker builds.

**EFS volumes**

Amazon Elastic File System volumes for persistent, shared storage across multiple tasks.

| **Field**            | **Description**                                  |
| -------------------- | ------------------------------------------------ |
| `filesystem_id`      | EFS filesystem ID (e.g., `fs-12345678`)          |
| `root_directory`     | Root directory within EFS (e.g., `/cache`)       |
| `transit_encryption` | Enable TLS encryption for data in transit        |
| `access_point_id`    | EFS access point ID for IAM-based access control |
| `iam`                | Use IAM authorization for EFS access             |

**Example use cases:**

* Persistent build caches shared across pipeline executions
* Shared artifacts between different stages
* Long-term storage for test results and reports

**EFS volume configuration:**

To use EFS volumes, ensure:

1. The EFS filesystem is in the same VPC as your ECS tasks
2. The security group allows NFS traffic (port 2049) from ECS tasks to EFS
3. The task role has permissions: `elasticfilesystem:ClientMount`, `elasticfilesystem:ClientWrite` (if IAM authorization is enabled)

***

### Update the delegate <a href="#update-the-delegate" id="update-the-delegate"></a>

To update the delegate to a new version:

1. Update the `image` field in your task definition JSON file to the latest delegate version:

   ```json
   "image": "us-docker.pkg.dev/gar-prod-setup/harness-public/harness/delegate:3.0.0"
   ```

   Check the [Harness release notes](/release-notes/delegate.md) for the latest version number.
2. Register the new task definition:

   **For ECS (EC2):**

   ```bash
   aws ecs register-task-definition --cli-input-json file://task-definition.json
   ```

   **For Fargate:**

   ```bash
   aws ecs register-task-definition --cli-input-json file://fargate-task-definition.json
   ```
3. Update the service to use the new task definition:

   **For ECS (EC2):**

   ```bash
   aws ecs update-service \
     --cluster harness-delegate-cluster \
     --service harness-delegate-service \
     --task-definition harness-delegate-task \
     --force-new-deployment
   ```

   **For Fargate:**

   ```bash
   aws ecs update-service \
     --cluster harness-delegate-fargate-cluster \
     --service harness-delegate-fargate-service \
     --task-definition harness-delegate-fargate-task \
     --force-new-deployment
   ```

***

### Troubleshooting <a href="#troubleshooting" id="troubleshooting"></a>

#### Delegate does not appear in Harness <a href="#delegate-does-not-appear-in-harness" id="delegate-does-not-appear-in-harness"></a>

* Verify that the `HARNESS_ACCOUNT_ID`, `HARNESS_TOKEN`, and `HARNESS_URL` values are correct.
* Check CloudWatch Logs for error messages:

  ```bash
  aws logs tail /ecs/harness-delegate --follow
  ```
* Ensure the security group allows outbound HTTPS traffic (port 443).

#### Task fails to start on Fargate <a href="#task-fails-to-start-on-fargate" id="task-fails-to-start-on-fargate"></a>

**Common causes:**

* **Execution role ARN is incorrect:** Verify that the execution role ARN in your task definition matches the actual role in your AWS account.
* **Subnets lack internet access:** Check that your subnets have a route to the internet (either via an Internet Gateway for public subnets or NAT Gateway for private subnets).
* **CloudWatch Logs permissions error:** If you see `ResourceInitializationError: failed to validate logger args` or `AccessDeniedException: User is not authorized to perform: logs:CreateLogGroup`, the execution role lacks permissions to create log groups.

**Solution for CloudWatch Logs error:**

Create the log group manually before starting the service:

```bash
aws logs create-log-group --log-group-name /ecs/harness-delegate-fargate --region us-east-1
```

Then force a new deployment:

```bash
aws ecs update-service \
  --cluster YOUR_CLUSTER_NAME \
  --service YOUR_SERVICE_NAME \
  --force-new-deployment \
  --region us-east-1
```

**To diagnose task failures:**

View stopped task details to see the exact error:

```bash
aws ecs describe-tasks \
  --cluster YOUR_CLUSTER_NAME \
  --tasks $(aws ecs list-tasks --cluster YOUR_CLUSTER_NAME --service-name YOUR_SERVICE_NAME --desired-status STOPPED --region us-east-1 --query 'taskArns[0]' --output text) \
  --region us-east-1 \
  --query 'tasks[0].stoppedReason'
```

#### Delegate disconnects frequently <a href="#delegate-disconnects-frequently" id="delegate-disconnects-frequently"></a>

* Ensure the task has sufficient CPU and memory resources.
* Check for network connectivity issues between the ECS task and Harness.

#### CloudWatch Logs rate limit errors <a href="#cloudwatch-logs-rate-limit-errors" id="cloudwatch-logs-rate-limit-errors"></a>

If you're running many concurrent tasks and see `ThrottlingException` or `ResourceAlreadyExistsException` errors related to log groups:

**Problem:** AWS CloudWatch Logs has API rate limits:

* `CreateLogGroup`: 5 requests per second
* `CreateLogStream`: 50 requests per second
* `PutLogEvents`: 800 requests per second per log group

**Solution:** Use a shared log group instead of creating individual log groups per task. Update your task definition:

```json
{
  "logConfiguration": {
    "logDriver": "awslogs",
    "options": {
      "awslogs-group": "/ecs/harness-delegates",
      "awslogs-region": "YOUR_AWS_REGION",
      "awslogs-stream-prefix": "delegate"
    }
  }
}
```

Then create the shared log group once:

```bash
aws logs create-log-group --log-group-name /ecs/harness-delegates --region YOUR_AWS_REGION
```

This allows multiple delegate tasks to write to the same log group, avoiding rate limit issues.

***

For additional help, contact [Harness Support](https://support.harness.io).
