Envoy Setup on Fedora

This guide walks through installing Envoy on Fedora, running a minimal static configuration, and verifying that the proxy is working correctly. The same steps apply to RHEL and CentOS Stream with minor repository differences.

Prerequisites

  • Fedora 38 or later (x86-64 or aarch64)
  • sudo access
  • Internet access to reach the Tetrate package repository

Step 1: Add the Tetrate RPM repository

The Envoy project does not publish official RPM packages. The recommended source for Fedora/RHEL is the Tetrate Envoy Builds repository, which mirrors the upstream release schedule.

1
2
3
4
5
6
7
8
sudo tee /etc/yum.repos.d/tetrate-envoy.repo << 'EOF'
[tetrate-envoy]
name=Tetrate Envoy Builds
baseurl=https://packages.tetrate.io/rpm/envoy/stable/$basearch/
enabled=1
gpgcheck=1
gpgkey=https://packages.tetrate.io/rpm/tetrate-rpm-key.asc
EOF

Import the GPG key and verify the fingerprint before proceeding:

1
2
sudo rpm --import https://packages.tetrate.io/rpm/tetrate-rpm-key.asc
rpm -q gpg-pubkey --qf '%{name}-%{version}-%{release} --> %{summary}\n' | grep -i tetrate

Step 2: Install Envoy

1
2
sudo dnf install -y envoy
envoy --version

A successful install prints a line similar to:

envoy  version: 1.30.x/Clean/RELEASE/BoringSSL

Step 3: Create a minimal static configuration

Create a directory for configuration and write a basic configuration that listens on port 10000 and proxies all traffic to httpbin.org:80.

1
sudo mkdir -p /etc/envoy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        address: 0.0.0.0
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          access_log:
          - name: envoy.access_loggers.stdout
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
          http_filters:
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.filters.http.router.v3.Router
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  host_rewrite_literal: www.httpbin.org
                  cluster: service_httpbin

  clusters:
  - name: service_httpbin
    connect_timeout: 5s
    type: LOGICAL_DNS
    dns_lookup_family: V4_ONLY
    load_assignment:
      cluster_name: service_httpbin
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: www.httpbin.org
                port_value: 80

admin:
  address:
    socket_address:
      address: 127.0.0.1
      port_value: 9901

Save this file to /etc/envoy/envoy.yaml.

Step 4: Open the firewall port

If firewalld is active, allow port 10000:

1
2
sudo firewall-cmd --add-port=10000/tcp --permanent
sudo firewall-cmd --reload

Step 5: Start Envoy

Run in the foreground (for testing)

1
envoy -c /etc/envoy/envoy.yaml

Envoy logs to stdout. You should see listener binding messages:

[info] all dependencies initialized. starting workers

Run as a systemd service

Create a dedicated system user and a unit file:

1
sudo useradd --system --no-create-home --shell /sbin/nologin envoy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=Envoy Proxy
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=envoy
ExecStart=/usr/bin/envoy -c /etc/envoy/envoy.yaml
Restart=on-failure
RestartSec=5s
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
1
2
3
sudo systemctl daemon-reload
sudo systemctl enable --now envoy
sudo systemctl status envoy

Step 6: Verify the proxy

Send a request through Envoy on port 10000:

1
curl -s http://localhost:10000/get | python3 -m json.tool

You should receive a JSON response from httpbin.org. Check the admin interface for runtime stats:

1
2
3
4
5
6
7
8
# Listener stats
curl -s http://localhost:9901/stats | grep listener

# Cluster health
curl -s http://localhost:9901/clusters | grep service_httpbin

# Current config dump
curl -s http://localhost:9901/config_dump | python3 -m json.tool | head -50

Step 7: Enable access logging (optional)

The configuration above already writes access logs to stdout, which systemd captures in the journal:

1
sudo journalctl -u envoy -f

To write access logs to a file instead, replace the StdoutAccessLog section with:

1
2
3
4
5
access_log:
- name: envoy.access_loggers.file
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
    path: /var/log/envoy/access.log

Create the log directory and adjust permissions:

1
2
sudo mkdir -p /var/log/envoy
sudo chown envoy:envoy /var/log/envoy

Upgrading Envoy

Tetrate publishes new RPMs as Envoy releases land. To upgrade:

1
2
sudo dnf update envoy
sudo systemctl restart envoy

Envoy supports hot restarts (--restart-epoch) for zero-downtime upgrades on the same host, but for most single-host setups a brief restart is acceptable.

What to avoid

Do not run Envoy as root. The systemd unit above uses a dedicated envoy system user. Envoy needs no special privileges once it has bound its listener ports.

Do not expose the admin interface publicly. Port 9901 allows draining listeners, changing log levels, and dumping the full running config. Bind it to 127.0.0.1 as shown above and access it via SSH tunnelling if needed remotely.

Do not pin to a specific patch version in the repo config. The stable channel tracks the latest stable release line. Pinning to a specific version prevents security patches from being applied automatically.

Do not use the static config for production service mesh deployments. Static configuration requires a process restart for every change. For dynamic environments multiple services, certificate rotation, traffic shifting integrate Envoy with a control plane such as Istio or Envoy Gateway that manages configuration via the xDS API. See the Introduction to Envoy for xDS details.