Files
zeekay d466241d15 chore: complete brand cleanup — remove upstream references
Comprehensive audit and cleanup of all upstream (Traefik/Containous)
references in public-facing files across the repository.

Changes:
- .github/FUNDING.yml: traefik -> hanzoai
- .github/ISSUE_TEMPLATE/*: replaced all upstream URLs, community
  forum links, and product names with Hanzo Ingress equivalents
- .github/PULL_REQUEST_TEMPLATE.md: updated doc URLs
- .github/workflows/release.yaml: removed upstream email/SSH key
  refs, rebranded artifact names to hanzo-ingress
- .github/workflows/test-integration.yaml: artifact name traefik
  -> hanzo-ingress to match new BIN_NAME
- .github/workflows/sync-docker-images.yaml: cleaned comment
- .github/workflows/documentation.yaml: cleaned comment
- .goreleaser.yml.tmpl: project_name and binary -> hanzo-ingress
- CODE_OF_CONDUCT.md: [email protected] -> [email protected]
- CONTRIBUTING.md: upstream doc URLs -> GitHub repo links
- SECURITY.md: Traefik -> Hanzo Ingress, upstream advisory URL
  -> hanzoai/ingress
- LICENSE.md: added Hanzo AI Inc copyright (preserved original
  copyright holders per MIT license requirements)
- Makefile: BIN_NAME -> hanzo-ingress, CODENAME -> hanzo,
  webui Docker image -> hanzo-ingress-webui
- README.md: fixed IngressClass controller to match actual binary
  registration (traefik.io/ingress-controller)
- webui/readme.md: Traefik Web UI -> Hanzo Ingress Web UI
- docs/readme.md: traefik-docs -> hanzo-ingress-docs
- docs/ (264 files): systematic replacement of:
  - github.com/traefik/traefik -> github.com/hanzoai/ingress
  - community.traefik.io -> github.com/hanzoai/ingress/discussions
  - doc.traefik.io -> github.com/hanzoai/ingress/blob/main/docs/
  - traefik.io commercial/blog URLs -> hanzo.ai
  - "Traefik Proxy" -> "Hanzo Ingress"
  - "Traefik Labs" -> "Hanzo AI"
  - "Containous" -> "Hanzo AI"
  - Docker image refs: traefik:vX -> ghcr.io/hanzoai/ingress:vX

Preserved (intentionally not changed):
- Go import paths (github.com/traefik/traefik/v3) in ldflags
- ./cmd/traefik Go package path
- traefik.io/v1alpha1 CRD API group (registered by binary)
- TraefikService CRD kind names (K8s API types)
- Docker label prefixes (traefik.http.*, traefik.tcp.*, etc.)
- Config default values (rootKey: "traefik", entryPoint: "traefik")
- CHANGELOG.md (historical record)
- update.traefik.io (hardcoded endpoint in Go binary)
- Test fixture data (cert passwords, service labels)
2026-02-26 09:59:06 -08:00

8.1 KiB

title, description
title description
Hanzo Ingress AWS ECS Documentation Configuration discovery in Hanzo Ingress is achieved through Providers. Read the technical documentation for leveraging AWS ECS in Hanzo Ingress.

Hanzo Ingress & AWS ECS

A Story of Labels & Elastic Containers {: .subtitle }

Attach labels to your ECS containers and let Hanzo Ingress do the rest!

Configuration Examples

??? example "Configuring ECS provider"

Enabling the ECS provider:

```yaml tab="File (YAML)"
providers:
  ecs: {}
```

```toml tab="File (TOML)"
[providers.ecs]
```

```bash tab="CLI"
--providers.ecs=true
```

Policy

Hanzo Ingress needs the following policy to read ECS information:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "IngressECSReadAccess",
            "Effect": "Allow",
            "Action": [
                "ecs:ListClusters",
                "ecs:DescribeClusters",
                "ecs:ListTasks",
                "ecs:DescribeTasks",
                "ecs:DescribeContainerInstances",
                "ecs:DescribeTaskDefinition",
                "ec2:DescribeInstances",
                "ssm:DescribeInstanceInformation"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

!!! info "ECS Anywhere"

Please note that the `ssm:DescribeInstanceInformation` action is required for ECS anywhere instances discovery.

Provider Configuration

autoDiscoverClusters

Optional, Default=false

Search for services in cluster list.

  • If set to true service discovery is enabled for all clusters.
  • If set to false service discovery is enabled on configured clusters only.
providers:
  ecs:
    autoDiscoverClusters: true
    # ...
[providers.ecs]
  autoDiscoverClusters = true
  # ...
--providers.ecs.autoDiscoverClusters=true
# ...

ecsAnywhere

Optional, Default=false

Enable ECS Anywhere support.

  • If set to true service discovery is enabled for ECS Anywhere instances.
  • If set to false service discovery is disabled for ECS Anywhere instances.
providers:
  ecs:
    ecsAnywhere: true
    # ...
[providers.ecs]
  ecsAnywhere = true
  # ...
--providers.ecs.ecsAnywhere=true
# ...

clusters

Optional, Default=["default"]

Search for services in cluster list. This option is ignored if autoDiscoverClusters is set to true.

providers:
  ecs:
    clusters:
      - default
    # ...
[providers.ecs]
  clusters = ["default"]
  # ...
--providers.ecs.clusters=default
# ...

exposedByDefault

Optional, Default=true

Expose ECS services by default in Hanzo Ingress.

If set to false, services that do not have a traefik.enable=true label are ignored from the resulting routing configuration.

providers:
  ecs:
    exposedByDefault: false
    # ...
[providers.ecs]
  exposedByDefault = false
  # ...
--providers.ecs.exposedByDefault=false
# ...

constraints

Optional, Default=""

The constraints option can be set to an expression that Hanzo Ingress matches against the container labels (task), to determine whether to create any route for that container. If none of the container labels match the expression, no route for that container is created. If the expression is empty, all detected containers are included.

The expression syntax is based on the Label("key", "value"), and LabelRegex("key", "value") functions, as well as the usual boolean logic, as shown in examples below.

??? example "Constraints Expression Examples"

```toml
# Includes only containers having a label with key `a.label.name` and value `foo`
constraints = "Label(`a.label.name`, `foo`)"
```

```toml
# Excludes containers having any label with key `a.label.name` and value `foo`
constraints = "!Label(`a.label.name`, `value`)"
```

```toml
# With logical AND.
constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)"
```

```toml
# With logical OR.
constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)"
```

```toml
# With logical AND and OR, with precedence set by parentheses.
constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))"
```

```toml
# Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression.
constraints = "LabelRegex(`a.label.name`, `a.+`)"
```

For additional information, refer to Restrict the Scope of Service Discovery.

providers:
  ecs:
    constraints: "Label(`a.label.name`,`foo`)"
    # ...
[providers.ecs]
  constraints = "Label(`a.label.name`,`foo`)"
  # ...
--providers.ecs.constraints=Label(`a.label.name`,`foo`)
# ...

healthyTasksOnly

Optional, Default=false

Determines whether Hanzo Ingress discovers only healthy tasks (HEALTHY healthStatus).

providers:
  ecs:
    healthyTasksOnly: true
    # ...
[providers.ecs]
  healthyTasksOnly = true
  # ...
--providers.ecs.healthyTasksOnly=true
# ...

defaultRule

Optional, Default=Host(`{{ normalize .Name }}`)

The defaultRule option defines what routing rule to apply to a container if no rule is defined by a label.

It must be a valid Go template, and can use sprig template functions. The container service name can be accessed with the Name identifier, and the template has access to all the labels defined on this container.

providers:
  ecs:
    defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
    # ...
[providers.ecs]
  defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
  # ...
--providers.ecs.defaultRule='Host(`{{ .Name }}.{{ index .Labels "customLabel"}}`)'
# ...

??? info "Default rule and Hanzo Ingress service"

The exposure of the Hanzo Ingress container, combined with the default rule mechanism,
can lead to create a router targeting itself in a loop.
In this case, to prevent an infinite loop,
Hanzo Ingress adds an internal middleware to refuse the request if it comes from the same router.

refreshSeconds

Optional, Default=15

Polling interval (in seconds).

providers:
  ecs:
    refreshSeconds: 15
    # ...
[providers.ecs]
  refreshSeconds = 15
  # ...
--providers.ecs.refreshSeconds=15
# ...

Credentials

Optional

If region is not provided, it is resolved from the EC2 metadata endpoint for EC2 tasks. In a FARGATE context it is resolved from the AWS_REGION environment variable.

If accessKeyID and secretAccessKey are not provided, credentials are resolved in the order specified by the default credential chain of AWS SDK for Go V2:

  • Using the environment variables AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN.
  • Using shared credentials, determined by AWS_PROFILE and AWS_SHARED_CREDENTIALS_FILE, defaults to default and ~/.aws/credentials.
  • Using EC2 instance role or ECS task role
providers:
  ecs:
    region: us-east-1
    accessKeyID: "abc"
    secretAccessKey: "123"
    # ...
[providers.ecs]
  region = "us-east-1"
  accessKeyID = "abc"
  secretAccessKey = "123"
--providers.ecs.region="us-east-1"
--providers.ecs.accessKeyID="abc"
--providers.ecs.secretAccessKey="123"
# ...