---
layout: docs
page_title: External <> Internal Services -  Ingress Gateways
description: >-
  An ingress gateway enables ingress traffic from services outside the Consul
  service mesh to services inside the Consul service mesh. This section details
  how to use Envoy and describes how you can plug in a gateway of your choice.
---

# Ingress Gateways

-> **1.8.0+:** This feature is available in Consul versions 1.8.0 and newer.

Ingress gateways enable ingress traffic from services outside the Consul
service mesh to services inside the Consul service mesh. An ingress gateway is
a type of proxy and must be registered as a service in Consul, with the
[kind](/api/agent/service#kind) set to "ingress-gateway". They are an
entrypoint for outside traffic and allow you to define what services should be
exposed and on what port. You configure an ingress gateway by defining a set of
[listeners](/docs/connect/config-entries/ingress-gateway#listeners) that each map
to a set of backing
[services](/docs/connect/config-entries/ingress-gateway#services).

To enable easier service discovery, a new Consul [DNS
subdomain](/docs/discovery/dns#ingress-service-lookups) is provided, on
`<service>.ingress.<domain>`.

For listeners with a
[protocol](/docs/connect/config-entries/ingress-gateway#protocol) other than
`tcp`, multiple services can be specified for a single listener. In this
case, the ingress gateway relies on host/authority headers to decide the
service that should receive the traffic. The host used to match traffic
defaults to the [Consul DNS ingress
subdomain](/docs/discovery/dns#ingress-service-lookups), but can be changed using
the [hosts](/docs/connect/config-entries/ingress-gateway#hosts) field.

![Ingress Gateway Architecture](/img/ingress-gateways.png)

## Prerequisites

Ingress gateways also require that your Consul datacenters are configured correctly:

- You'll need to use Consul version 1.8.0 or newer.
- Consul [Connect](/docs/agent/options#connect) must be enabled on the datacenter's Consul servers.
- [gRPC](/docs/agent/options#grpc_port) must be enabled on all client agents.

Currently, [Envoy](https://www.envoyproxy.io/) is the only proxy with ingress gateway capabilities in Consul.

## Running and Using an Ingress Gateway

For a complete example of how to allow external traffic inside your Consul service mesh,
review the [ingress gateway tutorial](https://learn.hashicorp.com/tutorials/consul/service-mesh-ingress-gateways).

## Ingress Gateway Configuration

Ingress gateways are configured in service definitions and registered with Consul like other services, with two exceptions.
The first is that the [kind](/api/agent/service#kind) must be "ingress-gateway". Second,
the ingress gateway service definition may contain a `Proxy.Config` entry just like a
Connect proxy service, to define opaque configuration parameters useful for the actual proxy software.
For Envoy there are some supported [gateway options](/docs/connect/proxies/envoy#gateway-options) as well as
[escape-hatch overrides](/docs/connect/proxies/envoy#escape-hatch-overrides).

-> **Note:** If ACLs are enabled, ingress gateways must be registered with a token granting `service:write` for the ingress gateway's service name,
`service:read` for all services in the ingress gateway's configuration entry, and `node:read` for all nodes of the services
in the ingress gateway's configuration entry. These privileges authorize the token to route communications to other Connect services.
If the Consul client agent on the gateway's node is not configured to use the default gRPC port, 8502, then the gateway's token
must also provide `agent:read` for its node's name in order to discover the agent's gRPC port. gRPC is used to expose Envoy's xDS API to Envoy proxies.

~> [Configuration entries](/docs/agent/config-entries) are global in scope. A configuration entry for a gateway name applies
across all federated Consul datacenters. If ingress gateways in different Consul datacenters need to route to different
sets of services within their datacenter then the ingress gateways **must** be registered with different names.

<!-- Add a "permalink" anchor here since this title is long and may be edited
     but we need to deep-link to it elsewhere -->
<a name="sds"></a>

## Custom TLS Certificates via Secret Discovery Service (SDS)

~> **Advanced Topic!** This is a low-level feature designed for developers
building integrations with custom TLS management solutions.

Consul 1.11 added support for Ingress Gateways to serve TLS certificates to
inbound traffic that are sourced from an external service. The external service
must implement Envoy's [gRPC Secret Discovery
Service](https://www.envoyproxy.io/docs/envoy/latest/configuration/security/secret)
(or SDS) API.

The steps below are necessary to fully configure an Ingress Gateway with TLS
certificates from an SDS source. They assume the operator is familiar with Envoy
 configuration and the SDS protocol.

### 1. Configure Static SDS Cluster(s).

Each Ingress Gateway Envoy instance must have one or more additional [static
clusters](/docs/connect/proxies/envoy#envoy_extra_static_clusters_json) defined
when registering the ingress gateway to specify how to connect to the external
service. This requires a manual registration of the Ingress Gateway proxy rather
than relying on `-register` flag to `consul connect envoy -gateway=ingress`.

The cluster(s) must provide connection information and any necessary
authentication information such as mTLS credentials.

In this example we will show:
 - A DNS name to discover the SDS service addresses
 - Local certificate files for TLS client authentication with the SDS server
   (the certificates are assumed to be created and managed by some other
   process)

#### 1.1 Registering the Proxy Service

The following Proxy Service Definition defines the bootstrap overrides needed to
add this configuration to Envoy when it starts. With this TLS configuration,
Envoy will detect changes to the certificate and key files on disk so an
external process may maintain and rotate them without needing an Envoy restart.

```hcl
// public-ingress.hcl
Services {
  Name = "public-ingress"
  Kind = "ingress-gateway"

  Proxy {
    Config {
      envoy_extra_static_clusters_json = <<EOF
{
  "name": "sds-cluster",
  "connect_timeout": "5s",
  "http2_protocol_options": {},
  "type": "LOGICAL_DNS",
  "transport_socket": {
    "name":"tls",
    "typed_config": {
      "@type":"type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
      "common_tls_context":{
        "tls_certificate_sds_secret_configs": [
          {
            "name":"tls_sds",
            "sds_config":{
              "path":"/certs/sds-auth-cert.json"
            }
          }
        ],
        "validation_context_sds_secret_config": {
          "name":"validation_context_sds",
          "sds_config":{
              "path":"/certs/sds-validation.json"
          }
        }
      }
    }
  },
  "load_assignment": {
    "cluster_name": "sds-cluster",
    "endpoints": [
      {
        "lb_endpoints": [
          {
            "endpoint": {
              "address": {
                "socket_address": {
                  "address": "sds-server.svc.cluster.local",
                  "port_value": 8080,
                }
              }
            }
          }
        ]
      }
    ]
  }
}
EOF
    }
  }
}
```

**Run `consul services register public-ingress.hcl`** to create the
registration. This must be run on the node where the Envoy proxy is going to run
to register the proxy with the local Consul agent.

#### 1.2 Setup TLS Client Authentication for SDS

This configuration relies on files like the following being present on disk
where the Envoy proxy will run, along with the actual certificates and keys
referenced.

 * `sds-client-auth.{crt,key}` are the PEM-encoded certificate and key
files to be used for TLS Client Authentication with the SDS service.
 * `sds-ca.crt` is the Certificate Authority certificate used to validate the the
SDS server's TLS credentials.

Please refer to [Envoy's
documentation](https://www.envoyproxy.io/docs/envoy/latest/api-v3/bootstrap/bootstrap)
for more details on this configuration and other possible authentication
options.

```json
// /certs/sds-auth-cert.json
{
  "resources": [
    {
      "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret",
      "name": "tls_sds",
      "tls_certificate": {
        "certificate_chain": {
          "filename": "/certs/sds-client-auth.crt"
        },
        "private_key": {
          "filename": "/certs/sds-client-auth.key"
        }
      }
    }
  ]
}
```
```json
// /certs/sds-validation.json
{
  "resources": [
    {
      "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret",
      "name": "validation_context_sds",
      "validation_context": {
        "trusted_ca": {
          "filename": "/certs/sds-ca.crt"
        }
      }
    }
  ]
}
```

#### 1.3 Start Envoy

**Start Envoy** with:

```bash
$ consul connect envoy -gateway=ingress -service public-ingress
```

### 2. Configure the Ingress Gateway to use certificates from SDS

SDS certificates may now be configured in the `ingress-gateway` Config Entry.

The following example shows a single default certificate and key being used for
all listeners.

```hcl
// public-ingress-cfg.hcl
Kind = "ingress-gateway"
Name = "public-ingress"

TLS {
  SDS {
    # This must match the name of the static cluster from step #1
    ClusterName = "sds-cluster"
    # This is the name of the certificate resource to load.
    CertResource = "example.com-public-cert"
  }
}

Listeners = [
  {
    Port = 8443
    Protocol = "http"
    Services = ["*"]
  }
]

```

Run `consul config write public-ingress-cfg.hcl` to write this configuration.

The Envoy instance will now start a listener on port 8443 and attempt to fetch
the TLS certificate named from the SDS server.

Separate certificates may be loaded per listener or per-service with hostname
(SNI) switching. See the [Config Entry
reference](/docs/connect/config-entries/ingress-gateway) for more details.