managing twingate

AWS ECS with Twingate (Headless & Userspace)

Secure private access for ECS workloads using Service Accounts

Summary

Twingate can be used to provide secure network access for workloads running on AWS ECS using service accounts. This could be a service (frontend app, AI agent, etc.) that needs private and secure access to a backend.

Depending on the ECS launch type, workloads can run either:

  • Userspace (HTTP/HTTPS proxy mode) — supported on ECS Fargate
  • Full headless client (TUN mode) — supported on ECS on EC2 (Managed Instances)

This guide explains the differences, limitations, and recommended deployment models for each.


AWS ECS Fargate

Supported Mode: Userspace (HTTP/s Proxy Only)

ECS Fargate does not currently support the Linux kernel capabilities required for full network tunneling.

Specifically, the Twingate Client requires:

  • Access to /dev/net/tun for device access
  • CAP_NET_ADMIN to create interfaces, routes, and IP rules for that device

AWS Fargate does not allow adding kernel capabilities beyond SYS_PTRACE.

As a result:

  • Full TUN mode is not supported on Fargate
  • Userspace (HTTP/HTTPS proxy mode) is supported

This aligns with Twingate’s userspace networking model, where traffic is explicitly sent through an HTTP proxy instead of being intercepted at the kernel level.


Fargate Architecture

In a typical Fargate task:

  • The Twingate Client runs in userspace mode (--tun off)
  • Application containers explicitly send HTTP/HTTPS traffic through the proxy
  • Access is enforced via Zero Trust (what the Client has access to)

Because the Twingate Client container does not expose a shell, it is started using the twingated entrypoint with arguments passed at runtime.


Service Account Injection (Why an Init Container Is Still Required)

AWS Secrets Manager injects secrets into ECS containers as environment variables, not as files.

The Twingate Client expects the service key at:

/etc/twingate/service_key.json

Because:

  • The client image does not provide a writable entrypoint
  • The secret must exist as a file before twingated starts
  • Secrets cannot be securely mounted as files directly in Fargate

An init container is used to:

  • Read the service key from Secrets Manager (via env var)
  • Write it to /etc/twingate/service_key.json
  • Share the file with the Twingate Client via a volume

This pattern is functionally equivalent to mounting a secret volume and is the recommended approach on ECS Fargate.

Example Fargate Task Definition

Twingate Userspace Client
{
"containerDefinitions": [
{
"command": [
"sh",
"-lc",
"set -e; mkdir -p /etc/twingate; printf '%s' \"$SERVICE_KEY_JSON\" > /etc/twingate/service_key.json; chmod 0444 /etc/twingate/service_key.json"
],
"cpu": 0,
"environment": [],
"essential": false,
"image": "alpine:latest",
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/tg-userspace-client",
"awslogs-create-group": "true",
"awslogs-region": "<region>",
"awslogs-stream-prefix": "init"
}
},
"mountPoints": [
{
"containerPath": "/etc/twingate",
"readOnly": false,
"sourceVolume": "twingate-etc"
}
],
"name": "init-write-key",
"portMappings": [],
"secrets": [
{
"name": "SERVICE_KEY_JSON",
"valueFrom": "arn:aws:secretsmanager:<region>:<account-id>:secret:twingate/service-key"
}
],
"systemControls": [],
"volumesFrom": []
},
{
"command": [
"--http-proxy",
"0.0.0.0:9999",
"--tun",
"off"
],
"cpu": 0,
"dependsOn": [
{
"condition": "SUCCESS",
"containerName": "init-write-key"
}
],
"entryPoint": [
"twingated"
],
"environment": [],
"essential": true,
"image": "twingate/client:latest",
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/tg-userspace-client",
"awslogs-create-group": "true",
"awslogs-region": "<region>",
"awslogs-stream-prefix": "twingate"
}
},
"mountPoints": [
{
"containerPath": "/etc/twingate",
"readOnly": false,
"sourceVolume": "twingate-etc"
}
],
"name": "tg-userspace-client",
"portMappings": [
{
"containerPort": 9999,
"hostPort": 9999,
"protocol": "tcp"
}
],
"systemControls": [],
"volumesFrom": []
},
{
"command": [
"sh",
"-lc",
"apk add --no-cache curl >/dev/null; TARGETS='http://my-private-backend.int https://ipinfo.io/what-is-my-ip'; i=0; while true; do i=$((i+1)); echo \"[$(date -Iseconds)] attempt=$i\"; for url in $TARGETS; do echo \"→ $url\"; curl -vk --max-time 20 --proxy http://127.0.0.1:9999 \"$url\" || true; done; echo 'sleeping 300s'; sleep 300; done"
],
"cpu": 0,
"dependsOn": [
{
"condition": "START",
"containerName": "tg-userspace-client"
}
],
"environment": [],
"essential": false,
"image": "alpine:latest",
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/tg-userspace-client",
"awslogs-create-group": "true",
"awslogs-region": "<region>",
"awslogs-stream-prefix": "tester"
}
},
"mountPoints": [],
"name": "tg-userspace-tester",
"portMappings": [],
"systemControls": [],
"volumesFrom": []
}
],
"cpu": "1024",
"executionRoleArn": "arn:aws:iam::<account-id>:role/ecsTaskExecutionAndSecretsRead",
"family": "tg-userspace-client",
"memory": "2048",
"networkMode": "awsvpc",
"requiresCompatibilities": [
"FARGATE"
],
"volumes": [
{
"host": {},
"name": "twingate-etc"
}
]
}

AWS ECS on EC2 (and Managed Instances)

ECS on EC2 runs containers on a fleet of customer-managed Linux hosts.

This environment does support:

  • Kernel capabilities
  • Privileged containers
  • System services (systemd)

As a result, both networking modes are supported.


For larger deployments, Twingate recommends running one client per EC2 host, not one per application task.

This is done by:

  • Installing the Twingate Client directly on the EC2 host
  • Running it as a systemd service
  • Authenticating using a service account

Benefits:

  • One client per host (not per task)
  • Full network tunneling
  • Lower operational overhead
  • Better performance for non-HTTP traffic

This deployment model is fully supported and commonly used.


Option 2: Userspace Mode on EC2

If workloads only require HTTP/HTTPS access, userspace mode can also be used on ECS EC2.

This may be appropriate for:

  • Least-privilege environments
  • Sidecar-style deployments
  • Incremental adoption

However, for most EC2-based deployments, full headless mode is preferred.

Choosing the Right Model

EnvironmentSupported ModeRecommendation
ECS FargateUserspace onlyHTTP/HTTPS workloads
ECS on EC2Full headlessDefault / recommended
ECS on EC2UserspaceHTTP-only or least-privilege

Troubleshooting

If access fails in ECS deployments:

  • Confirm the Twingate Client is running and authenticated
  • Verify the service key file exists at /etc/twingate/service_key.json
  • Confirm applications are explicitly using the proxy (userspace mode)
  • Check ECS task logs for startup or auth errors
  • Review Recent Activity for the Resource in the Admin Console

For Fargate specifically:

  • Verify traffic is HTTP/HTTPS only
  • Ensure no application attempts raw TCP or UDP connections
  • Confirm Secrets Manager permissions on the execution role

For additional help, see the Twingate Troubleshooting Guide.


Last updated 14 minutes ago