# Envoy RPM Package Envoy proxy packaged from the upstream release binaries (`envoy--linux-x86_64` / `-linux-aarch_64`, standard build, not contrib). Intended to sit behind angie/nginx (TLS termination) and route to containers on the same host. ``` client → angie :443 (TLS) → envoy 127.0.0.1:10000 → containers 127.0.0.1: ``` ## Package structure | Package | Contents | |-------------------|--------------------------------------------------------------------------| | `envoy` | `envoy` user (128:128), `/etc/envoy/{envoy,lds,cds}.yaml`, LICENSE/NOTICE | | `envoy-service` | `/usr/libexec/envoy` binary, `envoy.service`, `/usr/bin/envoy` symlink | | `envoy-container` | `envoy.container` quadlet (`Network=host`), `/usr/bin/envoy` shim (noarch) | `envoy-service` and `envoy-container` conflict; install one of them. Both restart `envoy.service` on upgrade. ## Configuration | File | Content | Applied | |------------------------|-----------------------------|----------------------------| | `/etc/envoy/envoy.yaml`| bootstrap: admin, xDS paths | `systemctl restart envoy` | | `/etc/envoy/lds.yaml` | listeners and routes | live, polled every 5s | | `/etc/envoy/cds.yaml` | clusters (upstreams) | live, polled every 5s | Defaults: listener `http` on `127.0.0.1:10000` (404 for everything), admin on `127.0.0.1:9901`, WebSocket upgrades enabled, access log to stdout (journal). One trusted proxy hop (`use_remote_address: true`, `xff_num_trusted_hops: 1`): the client address is the last `X-Forwarded-For` entry set by angie, passed upstream as `x-envoy-external-address`. `X-Forwarded-Proto` from angie is kept. Client-sent `x-envoy-*` headers are stripped from external requests. Since angie connects over loopback, Envoy appends the host's own address (not `127.0.0.1`) to `X-Forwarded-For`. LDS/CDS use `path_config_source.poll_interval`, so files can be edited in place (no atomic `mv` needed). Only changed content is applied. - An invalid `lds.yaml`/`cds.yaml` is rejected; the last good configuration stays active. Check `journalctl -u envoy`. - `envoy --mode validate -c /etc/envoy/envoy.yaml` checks only the bootstrap, not `lds.yaml`/`cds.yaml`. - A route referencing a cluster not yet in `cds.yaml` is rejected (`unknown cluster`). When adding both, save `cds.yaml` first; otherwise one warning is logged and the listener is applied on the next poll. - Admin state: `curl -s localhost:9901/ready`, `/clusters`, `/listeners`, `/config_dump`. ### Adding a container backend `cds.yaml`: ```yaml resources: - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster name: app type: STATIC connect_timeout: 5s load_assignment: cluster_name: app endpoints: - lb_endpoints: - endpoint: address: socket_address: { address: 127.0.0.1, port_value: 8080 } ``` `lds.yaml`, add a virtual host before `default`: ```yaml - name: app domains: ["app.example.com"] routes: - match: { prefix: "/" } route: { cluster: app } ``` ### angie/nginx in front ```nginx location / { proxy_pass http://127.0.0.1:10000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } ``` ## Service (`envoy-service`) - `Type=simple`; Envoy has no sd_notify support. - `ExecStartPre` validates the bootstrap; runs as `envoy` with `CAP_NET_BIND_SERVICE` (ports < 1024 allowed). - `--disable-hot-restart`: single instance, restarts are plain restarts. ```bash dnf install envoy-service systemctl enable --now envoy ``` ## Container (`envoy-container`) - Image `docker.io/envoyproxy/envoy:v` (Ubuntu based), `Network=host`. - `/etc/envoy` mounted read-only. The image entrypoint remaps its `envoy` user to `ENVOY_UID/ENVOY_GID=128`, matching the host user, and drops root. Ports < 1024 are therefore not bindable in the container variant. - Health: bash `/dev/tcp` request to admin `/ready` (image has no curl), `Notify=healthy`, `HealthOnFailure=kill`. - Enabled at boot via `/etc/containers/systemd/envoy.container.d/enable.conf`. - `/usr/bin/envoy` shim runs `podman run --rm` of the same image, so `envoy --mode validate -c /etc/envoy/envoy.yaml` works while the container is stopped. Run as root. ```bash dnf install envoy-container systemctl daemon-reload systemctl start envoy ``` ## Updating 1. Bump `Version:` in `envoy.spec`. The image tag in `envoy.container` and the shim follows automatically (`@VERSION@` substituted in `%install`). 2. Download and verify the release binaries: ```bash v=1.40.2 base=https://github.com/envoyproxy/envoy/releases/download/v$v for f in envoy-$v-linux-x86_64 envoy-$v-linux-aarch_64 checksums.txt.asc; do curl -sSfLO "$base/$f" done grep -E "envoy-$v-linux-(x86_64|aarch_64)$" checksums.txt.asc | sha256sum -c gpg --verify checksums.txt.asc # key: thirdparty/envoy/envoy-maintainers-public.key ``` 3. Refresh `LICENSE`/`NOTICE` from `thirdparty/envoy` if changed, add a `%changelog` entry.