---
title: Configuration file · Cloudflare Zero Trust docs
description: Locally-managed tunnels run as an instance of cloudflared on your machine.  You can configure cloudflared properties by modifying command line parameters or by editing the tunnel configuration file.
lastUpdated: 2025-02-27T03:56:47.000Z
source_url:
  html: https://zt-dark-mode-changelog.preview.developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/index.md
  md: https://zt-dark-mode-changelog.preview.developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/
---

Note

[Quick tunnels](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms/#quick-tunnels) do not need a configuration file.

Locally-managed tunnels run as an instance of `cloudflared` on your machine. You can configure `cloudflared` properties by modifying [command line parameters](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/) or by editing the tunnel [configuration file](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/#4-create-a-configuration-file).

The CLI provides a quick way to handle configurations if you are connecting a single service through `cloudflared`. The tunnel configuration file is useful if you are connecting multiple services and need to configure properties or exceptions for specific origins. In the configuration file, you can define top-level properties for your `cloudflared` instance as well as [origin-specific properties](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/). For a full list of configuration options, type `cloudflared tunnel help` in your terminal.

In the absence of a configuration file, `cloudflared` will proxy outbound traffic through port `8080`.

## File structure for private networks

If you are [exposing a private network](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/private-net/) to end users running WARP, you need to add the `warp-routing` key and set it to `true`:

```yml
tunnel: <Tunnel-UUID>
credentials-file: /path/<Tunnel-UUID>.json
warp-routing:
  enabled: true
```

## File structure for public hostnames

If you are exposing local services to the Internet, you can assign a public hostname to each service:

```yml
tunnel: 6ff42ae2-765d-4adf-8112-31c55c1551ef
credentials-file: /root/.cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json


ingress:
  - hostname: gitlab.widgetcorp.tech
    service: http://localhost:80
  - hostname: gitlab-ssh.widgetcorp.tech
    service: ssh://localhost:22
  - service: http_status:404
```

Configuration files that contain ingress rules must always include a catch-all rule that concludes the file. In this example, `cloudflared` will respond with a `404` status code when the request does not match any of the previous hostnames.

### How traffic is matched

When `cloudflared` receives an incoming request, it evaluates each ingress rule from top to bottom to find which rule matches the request. Rules can match either the hostname or path of an incoming request, or both.

Wildcards

You can use wildcards to match traffic to multiple subdomains or paths. For example, if you set the `hostname` key to `*.example.com`, both `test.example.com` and `try.example.com` will route traffic to your origin.

If a rule does not specify a hostname, all hostnames will be matched. If a rule does not specify a path, all paths will be matched.

The last ingress rule must be a catch-all rule that matches all traffic.

Here is an example configuration file that specifies several rules:

```yml
tunnel: 6ff42ae2-765d-4adf-8112-31c55c1551ef
credentials-file: /root/.cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json


ingress:
  # Rules map traffic from a hostname to a local service:
  - hostname: example.com
    service: https://localhost:8000
  # Rules can match the request's path to a regular expression:
  - hostname: static.example.com
    path: \.(jpg|png|css|js)$
    service: https://localhost:8001
  # Rules can match the request's hostname to a wildcard character:
  - hostname: "*.example.com"
    service: https://localhost:8002
  # An example of a catch-all rule:
  - service: https://localhost:8003
```

### Supported protocols

In addition to HTTP, `cloudflared` supports protocols like SSH, RDP, arbitrary TCP services, and Unix sockets. You can also route traffic to the built-in `Hello World` test server or respond to traffic with an HTTP status.

```yml
tunnel: 6ff42ae2-765d-4adf-8112-31c55c1551ef
credentials-file: /root/.cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json


ingress:
  # Example of a request over TCP:
  - hostname: example.com
    service: tcp://localhost:8000
  # Example of an HTTP request over a Unix socket:
  - hostname: staging.example.com
    service: unix:/home/production/echo.sock
  # Example of a request mapping to the Hello World test server:
  - hostname: test.example.com
    service: hello_world
  # Example of a rule responding to traffic with an HTTP status:
  - service: http_status:404
```

| Service | Description | Example `service` value |
| - | - | - |
| HTTP/S | Incoming HTTP requests are proxied directly to your local service. | `https://localhost:8000` |
| HTTP over Unix socket | Just like HTTP, but using a Unix socket instead. | `unix:/home/production/echo.sock` |
| HTTPS over Unix socket | Just like HTTPS, but using a Unix socket instead. | `unix+tls:/home/production/echo.sock` |
| TCP | TCP connections are proxied to your local service. | `tcp://localhost:2222` |
| SSH | SSH connections are proxied to your local service. [Learn more](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/use-cases/ssh/). | `ssh://localhost:22` |
| RDP | RDP connections are proxied to your local service. [Learn more](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/use-cases/rdp/). | `rdp://localhost:3389` |
| kubectl bastion mode | `cloudflared` will act like a jumphost, allowing access to any local address. | `bastion` |
| Hello World | Test server for validating your Cloudflare Tunnel setup. | `hello_world` |
| HTTP status | Responds to all requests with the given HTTP status. | `http_status:404` |

### Origin configuration

If you need to proxy traffic to multiple origins within one instance of `cloudflared`, you can define the way `cloudflared` sends requests to each service by specifying [configuration options](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/) as part of your ingress rules.

In the following example, the top-level configuration `connectTimeout: 30s` sets a 30-second connection timeout for all services within that instance of `cloudflared`. The ingress rule for `service: localhost:8002` then configures an exception to the top-level configuration by setting `connectTimeout` for that service at `10s`. The 30-second connection timeout still applies to all other services.

```yml
tunnel: 6ff42ae2-765d-4adf-8112-31c55c1551ef
credentials-file: /root/.cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json
originRequest: # Top-level configuration
  connectTimeout: 30s


ingress:
  # The localhost:8000 service inherits all root-level configuration.
  # In other words, it will use a connectTimeout of 30 seconds.
  - hostname: example.com
    service: localhost:8000
  - hostname: example2.com
    service: localhost:8001
  # The localhost:8002 service overrides some root-level config.
  - service: localhost:8002
    originRequest:
      connectTimeout: 10s
      disableChunkedEncoding: true
  # Some built-in services such as `http_status` do not use any configuration.
  # The service below will simply respond with HTTP 404.
  - service: http_status:404
```

### Validate ingress rules

To validate the ingress rules in your configuration file, run:

```sh
cloudflared tunnel ingress validate
```

This will ensure that the set of ingress rules specified in your config file is valid.

### Test ingress rules

To verify that `cloudflared` will proxy the right traffic to the right local service, use `cloudflared tunnel ingress rule`. This checks a URL against every rule, from first to last, and shows the first rule that matches. For example:

```sh
cloudflared tunnel ingress rule https://foo.example.com
```

```sh
Using rules from /usr/local/etc/cloudflared/config.yml
Matched rule #3
  hostname: *.example.com
  service: https://localhost:8000
```

## Update a configuration file

When making changes to the configuration file for a given tunnel, we suggest relying on [`cloudflared` replicas](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/) to propagate the new configuration with minimal downtime.

1. Have a `cloudflared` instance running with the original version of the configuration file.
2. Start a `cloudflared` replica running with the updated version of the configuration file.
3. Wait for the replica to be fully running and usable.
4. Stop the first instance of `cloudflared`.

Your `cloudflared` will now be running with the updated version of your configuration file.

Traffic handling

When the first instance of `cloudflared` is stopped, long-lived HTTP requests (for example, Websocket) and TCP connections (for example, SSH) will be dropped. UDP flows will also be dropped, as they are modeled based on timeouts. When the new replica connects, it will handle all new traffic, including new HTTP requests, TCP connections, and UDP flows.
