Envoy Proxy is a high-performance, cloud-native Layer 7 proxy originally built at Lyft and now a CNCF graduated project. Unlike Nginx or HAProxy, Envoy is designed with dynamic configuration via xDS APIs and deep observability baked in, making it the proxy of choice for service meshes such as Istio. On RHEL 8 you can run Envoy as a standalone edge proxy, a sidecar for a specific application, or as the data plane for a full service mesh. This guide installs Envoy using the GetEnvoy repository, writes a minimal static YAML configuration, and demonstrates HTTP proxying, upstream cluster definitions, and health checking.
Prerequisites
- RHEL 8 server with root or
sudoaccess and internet connectivity - Basic familiarity with YAML syntax
- An upstream application to proxy (the examples use a local
httpdon port 8080 as the backend) - Podman or Docker available if you prefer the container-based installation path
- Ports 10000 (listener) and 9901 (admin UI) available
Step 1 — Install Envoy via the GetEnvoy Repository
The GetEnvoy project (now maintained by Tetrate) provides pre-built Envoy binaries packaged as an RPM for RHEL/CentOS.
# Add the GetEnvoy (Tetrate) repository
curl -sL https://rpm.tetratelabs.io/getenvoy/release/rpm/el8/getenvoy.repo
-o /etc/yum.repos.d/getenvoy.repo
dnf install -y getenvoy-envoy
# Verify the installation
envoy --version
If you prefer not to add a third-party repository, you can run Envoy as a container instead. Pull the official image and use podman run with a volume mount for the configuration file — see the alternative below.
# Alternative: container-based Envoy (no RPM needed)
dnf install -y podman
podman pull docker.io/envoyproxy/envoy:v1.29-latest
# Run: podman run --rm -p 10000:10000 -p 9901:9901
# -v /etc/envoy/envoy.yaml:/etc/envoy/envoy.yaml:ro
# envoyproxy/envoy:v1.29-latest
Step 2 — Write a Minimal Envoy Configuration File
Create /etc/envoy/envoy.yaml. This configuration defines an admin interface, a single listener on port 10000 with an HTTP connection manager filter, and a static cluster pointing to the upstream backend on port 8080.
mkdir -p /etc/envoy
cat > /etc/envoy/envoy.yaml << 'EOF'
admin:
address:
socket_address:
address: 0.0.0.0
port_value: 9901
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.extensions.filters.http.router.v3.Router
route_config:
name: local_route
virtual_hosts:
- name: backend
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: backend_service
clusters:
- name: backend_service
connect_timeout: 5s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: backend_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 8080
health_checks:
- timeout: 3s
interval: 10s
unhealthy_threshold: 2
healthy_threshold: 1
http_health_check:
path: /health
EOF
Step 3 — Validate the Configuration and Start Envoy
Use the --mode validate flag to catch YAML and schema errors before launching the process.
envoy --config-path /etc/envoy/envoy.yaml --mode validate
echo "Config OK: $?"
# Start Envoy in the foreground (Ctrl-C to stop)
envoy --config-path /etc/envoy/envoy.yaml --log-level info
To run Envoy as a persistent background service, create a systemd unit file at /etc/systemd/system/envoy.service:
cat > /etc/systemd/system/envoy.service << 'EOF'
[Unit]
Description=Envoy Proxy
After=network.target
[Service]
User=root
ExecStart=/usr/bin/envoy --config-path /etc/envoy/envoy.yaml --log-level info
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now envoy
systemctl status envoy
Step 4 — Open the Firewall and Test Proxying
firewall-cmd --add-port=10000/tcp --permanent
firewall-cmd --add-port=9901/tcp --permanent
firewall-cmd --reload
# Send a request through Envoy to the backend
curl -v http://localhost:10000/
# Check the Envoy admin UI for live stats
curl http://localhost:9901/stats | grep backend_service
# View active clusters and health check status
curl http://localhost:9901/clusters
The /stats endpoint exposes hundreds of counters including upstream_cx_total (total connections to the backend) and upstream_rq_2xx (successful responses). These metrics can be scraped directly by Prometheus using the /stats/prometheus endpoint.
Step 5 — Add a Second Upstream Endpoint for Load Balancing
Envoy’s static cluster definition accepts multiple endpoints. Add a second backend host to demonstrate round-robin load balancing without restarting Envoy (use xDS in production for zero-downtime updates).
# Edit /etc/envoy/envoy.yaml — extend lb_endpoints under backend_service:
# - endpoint:
# address:
# socket_address:
# address: 127.0.0.1
# port_value: 8081
systemctl restart envoy
# Watch the round-robin in action
for i in $(seq 1 6); do curl -s http://localhost:10000/ | grep -o "server:[^<]*"; done
Step 6 — Envoy as a Sidecar Proxy (Service Mesh Overview)
In a service mesh pattern, an Envoy sidecar runs alongside every application instance in the same network namespace, intercepting all inbound and outbound traffic via iptables rules injected by a control plane (e.g., Istio’s istio-init container). The sidecar enforces mutual TLS, applies traffic policies, and emits telemetry to a central collector — all transparently to the application code. The same envoy.yaml structure used in this tutorial is generated dynamically by the control plane via the xDS (Discovery Service) API, allowing configuration updates without any restart.
# Inspect Envoy's xDS config dump from the admin API
curl http://localhost:9901/config_dump | python3 -m json.tool | head -80
Conclusion
You have installed Envoy Proxy on RHEL 8, written a static YAML configuration with an HTTP connection manager, defined an upstream cluster with health checking, and tested round-robin load balancing across two backend endpoints. The admin API at port 9901 provides rich runtime observability and integrates with Prometheus out of the box, making Envoy a powerful building block for both standalone proxy use cases and full service-mesh deployments.
Next steps: How to Deploy Istio Service Mesh on Kubernetes from RHEL 8, How to Collect Envoy Metrics with Prometheus on RHEL 8, and How to Set Up a Complete DevSecOps Pipeline on RHEL 8.