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)
sudoaccess- 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.