--- title: "Cómo instalar y configurar Envoy Proxy en Ubuntu 24.04" description: "Instala Envoy Proxy en Ubuntu 24.04 como servicio systemd y configúralo como balanceador HTTP con round robin, health checks, reintentos y panel de admin." category: "Proxy y Equilibrio de Carga" language: es source: https://cubepath.com/es/docs/proxy-y-equilibrio-de-carga/instalacion-y-configuracion-del-proxy-envoy updated: 2026-09-25 --- # Cómo instalar y configurar Envoy Proxy en Ubuntu 24.04 Envoy es un proxy de capa 7 de alto rendimiento, proyecto graduado de la CNCF, que se usa como proxy de borde, balanceador de carga y sidecar en mallas de servicios como Istio. Se configura con un archivo YAML basado en cuatro piezas: listeners (dónde escucha), filtros (qué hace con el tráfico), rutas (a dónde lo envía) y clusters (los backends). En este tutorial instalarás Envoy en Ubuntu 24.04 a partir del binario oficial, lo ejecutarás como servicio systemd con un usuario sin privilegios y lo configurarás como balanceador HTTP delante de dos backends, con health checks activos, reintentos y la interfaz de administración para comprobar su estado. ## Requisitos previos Para seguir este tutorial necesitas: - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 1 GB de RAM. - Un usuario no root con privilegios `sudo`. - El puerto 80 libre (si tienes Nginx o Apache escuchando en él, detenlo o usa otro puerto en el listener). ## Paso 1: Descargar e instalar el binario de Envoy El repositorio APT oficial de Envoy no publica paquetes para Ubuntu 24.04 y va varias versiones por detrás, así que la forma más fiable de instalarlo es el binario estático que se adjunta a cada release en GitHub. Consulta la última versión en la [página de releases de Envoy](https://github.com/envoyproxy/envoy/releases) y guárdala en una variable (este tutorial usa la 1.39.1): ```bash ENVOY_VERSION=1.39.1 ``` Descarga el binario y el archivo de checksums: ```bash cd /tmp curl -fLO "https://github.com/envoyproxy/envoy/releases/download/v${ENVOY_VERSION}/envoy-${ENVOY_VERSION}-linux-x86_64" curl -fLO "https://github.com/envoyproxy/envoy/releases/download/v${ENVOY_VERSION}/checksums.txt.asc" ``` En un servidor ARM64, sustituye `x86_64` por `aarch_64` en el nombre del archivo. Comprueba que el SHA-256 del binario coincide con el publicado: ```bash echo "$(grep "/envoy-${ENVOY_VERSION}-linux-x86_64$" checksums.txt.asc | cut -d' ' -f1) envoy-${ENVOY_VERSION}-linux-x86_64" | sha256sum -c ``` ```output envoy-1.39.1-linux-x86_64: OK ``` Instálalo en `/usr/local/bin` con los permisos correctos: ```bash sudo install -m 0755 "envoy-${ENVOY_VERSION}-linux-x86_64" /usr/local/bin/envoy envoy --version ``` ```output envoy version: .../1.39.1/Clean/RELEASE/BoringSSL ``` > Nota: Si prefieres contenedores, la imagen oficial es `envoyproxy/envoy:v1.39-latest`. El archivo de configuración de este tutorial funciona igual montándolo en `/etc/envoy/envoy.yaml` dentro del contenedor. ## Paso 2: Crear el usuario y el directorio de configuración Envoy no necesita privilegios de root. Crea un usuario de sistema sin shell y el directorio donde vivirá la configuración: ```bash sudo useradd --system --no-create-home --shell /usr/sbin/nologin envoy sudo mkdir -p /etc/envoy ``` Comprueba que el usuario existe: ```bash id envoy ``` ```output uid=998(envoy) gid=998(envoy) groups=998(envoy) ``` ## Paso 3: Levantar dos backends de prueba Para ver el balanceo necesitas algo detrás de Envoy. Si ya tienes una aplicación escuchando en local, puedes saltarte este paso y usar sus puertos en el Paso 4. Si no, crea dos servidores HTTP mínimos con Python, cada uno con una página que indica quién responde: ```bash sudo mkdir -p /srv/backend1 /srv/backend2 echo "respuesta desde backend1" | sudo tee /srv/backend1/index.html echo "respuesta desde backend2" | sudo tee /srv/backend2/index.html ``` Arráncalos como servicios transitorios de systemd, escuchando solo en `127.0.0.1` en los puertos 8081 y 8082: ```bash sudo systemd-run --unit=backend1 python3 -m http.server 8081 --bind 127.0.0.1 --directory /srv/backend1 sudo systemd-run --unit=backend2 python3 -m http.server 8082 --bind 127.0.0.1 --directory /srv/backend2 ``` Comprueba que responden: ```bash curl http://127.0.0.1:8081/ curl http://127.0.0.1:8082/ ``` ```output respuesta desde backend1 respuesta desde backend2 ``` ## Paso 4: Escribir la configuración de Envoy La configuración estática de Envoy tiene dos bloques principales. En `static_resources.listeners` defines el puerto en el que escucha y la cadena de filtros; para HTTP, el filtro clave es el `http_connection_manager`, que contiene las rutas y termina en el filtro `router`. En `static_resources.clusters` defines los backends, la política de balanceo y los health checks. El bloque `admin` expone la interfaz de administración. Crea el archivo de configuración: ```bash sudo nano /etc/envoy/envoy.yaml ``` Pega el siguiente contenido: ```yaml admin: address: socket_address: { address: 127.0.0.1, port_value: 9901 } static_resources: listeners: - name: http_listener address: socket_address: { address: 0.0.0.0, port_value: 80 } 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 route_config: name: local_route virtual_hosts: - name: app domains: ["*"] routes: - match: { prefix: "/" } route: cluster: app_backend timeout: 15s retry_policy: retry_on: "connect-failure,refused-stream,5xx" num_retries: 2 http_filters: - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: app_backend connect_timeout: 2s type: STATIC lb_policy: ROUND_ROBIN load_assignment: cluster_name: app_backend endpoints: - lb_endpoints: - endpoint: address: socket_address: { address: 127.0.0.1, port_value: 8081 } - endpoint: address: socket_address: { address: 127.0.0.1, port_value: 8082 } health_checks: - timeout: 1s interval: 5s unhealthy_threshold: 2 healthy_threshold: 2 http_health_check: path: "/" ``` Qué hace cada parte: - **`admin`**: la interfaz de administración escucha solo en `127.0.0.1:9901`. Nunca la expongas a Internet: permite, entre otras cosas, apagar Envoy. - **Listener `http_listener`**: acepta HTTP en el puerto 80 de todas las interfaces y escribe un log de acceso por petición en la salida estándar, que acabará en journald. - **`route_config`**: todas las peticiones (`domains: ["*"]`, prefijo `/`) van al cluster `app_backend`, con un timeout de 15 segundos y hasta 2 reintentos si el backend rechaza la conexión o devuelve un 5xx. - **Cluster `app_backend`**: dos endpoints con IP fija (`type: STATIC`) balanceados en round robin. El health check pide `/` cada 5 segundos y saca un endpoint del balanceo tras 2 fallos seguidos. Si tus backends se identifican por nombre DNS en lugar de IP, usa `type: STRICT_DNS` y pon el nombre en `address`. Valida la sintaxis antes de arrancar nada: ```bash envoy --mode validate -c /etc/envoy/envoy.yaml ``` ```output configuration '/etc/envoy/envoy.yaml' OK ``` Si hay un error, Envoy indica el campo exacto que no reconoce. Los fallos más habituales son la indentación y un `@type` mal escrito. ## Paso 5: Ejecutar Envoy como servicio systemd Crea una unidad de systemd que ejecute Envoy con el usuario `envoy`. La capacidad `CAP_NET_BIND_SERVICE` le permite escuchar en el puerto 80 sin ser root, y `ExecStartPre` valida la configuración antes de cada arranque para que un error de sintaxis no tumbe el servicio en marcha: ```bash sudo nano /etc/systemd/system/envoy.service ``` ```ini [Unit] Description=Envoy Proxy After=network-online.target Wants=network-online.target [Service] User=envoy Group=envoy ExecStartPre=/usr/local/bin/envoy --mode validate -c /etc/envoy/envoy.yaml ExecStart=/usr/local/bin/envoy -c /etc/envoy/envoy.yaml --log-level info AmbientCapabilities=CAP_NET_BIND_SERVICE CapabilityBoundingSet=CAP_NET_BIND_SERVICE NoNewPrivileges=true LimitNOFILE=65536 Restart=on-failure [Install] WantedBy=multi-user.target ``` Recarga systemd, habilita el servicio y arráncalo: ```bash sudo systemctl daemon-reload sudo systemctl enable --now envoy sudo systemctl status envoy ``` ```output ● envoy.service - Envoy Proxy Loaded: loaded (/etc/systemd/system/envoy.service; enabled; preset: enabled) Active: active (running) since Thu 2026-09-25 10:12:41 UTC; 3s ago ``` Si usas UFW, abre el puerto 80: ```bash sudo ufw allow 80/tcp ``` ## Paso 6: Comprobar el balanceo Lanza varias peticiones seguidas. Envoy las reparte en round robin entre los dos backends: ```bash for i in 1 2 3 4; do curl -s http://localhost/; done ``` ```output respuesta desde backend1 respuesta desde backend2 respuesta desde backend1 respuesta desde backend2 ``` Cada petición deja una línea en el log de acceso, que puedes seguir con journald: ```bash sudo journalctl -u envoy -f ``` ```output [2026-09-25T10:13:02.114Z] "GET / HTTP/1.1" 200 - 0 25 1 1 "-" "curl/8.5.0" "..." "localhost" "127.0.0.1:8081" ``` El último campo indica qué backend atendió la petición. Pulsa `CTRL+C` para salir. ## Paso 7: Usar la interfaz de administración y probar los health checks La interfaz de administración es la herramienta principal para saber qué está haciendo Envoy. Comprueba que el proceso está listo para recibir tráfico: ```bash curl -s http://127.0.0.1:9901/ready ``` ```output LIVE ``` Consulta el estado de salud de cada endpoint del cluster: ```bash curl -s http://127.0.0.1:9901/clusters | grep health_flags ``` ```output app_backend::127.0.0.1:8081::health_flags::healthy app_backend::127.0.0.1:8082::health_flags::healthy ``` Ahora simula la caída de un backend: ```bash sudo systemctl stop backend2 ``` Espera unos 10 segundos (dos health checks fallidos) y vuelve a consultar: ```bash curl -s http://127.0.0.1:9901/clusters | grep health_flags ``` ```output app_backend::127.0.0.1:8081::health_flags::healthy app_backend::127.0.0.1:8082::health_flags::/failed_active_hc ``` Todas las peticiones van ya a `backend1`, sin errores para el cliente: ```bash for i in 1 2 3; do curl -s http://localhost/; done ``` ```output respuesta desde backend1 respuesta desde backend1 respuesta desde backend1 ``` Las estadísticas del cluster muestran cuántas peticiones se han servido y cuántos health checks han fallado: ```bash curl -s http://127.0.0.1:9901/stats | grep -E 'cluster.app_backend.(upstream_rq_2xx|health_check.failure)' ``` ```output cluster.app_backend.health_check.failure: 4 cluster.app_backend.upstream_rq_2xx: 7 ``` Otros endpoints útiles son `/config_dump` (la configuración efectiva en JSON), `/listeners` y `/stats/prometheus` (las mismas métricas en formato Prometheus, listas para que las recoja tu sistema de monitorización a través de un túnel o un proxy autenticado). Cuando termines las pruebas, detén y elimina los backends de ejemplo: ```bash sudo systemctl stop backend1 sudo rm -rf /srv/backend1 /srv/backend2 ``` ## Aplicar cambios de configuración Envoy no relee `envoy.yaml` al recibir una señal. Para aplicar cambios en una configuración estática, valida y reinicia: ```bash envoy --mode validate -c /etc/envoy/envoy.yaml && sudo systemctl restart envoy ``` El reinicio corta las conexiones abiertas durante un instante. Si necesitas cambios sin cortes, el camino es la configuración dinámica (xDS) con un plano de control, que es lo que hacen Istio o Envoy Gateway. ## Solución de problemas **El servicio no arranca y `journalctl -u envoy` muestra un error de validación**: el `ExecStartPre` ha detectado un error en el YAML. Ejecuta `envoy --mode validate -c /etc/envoy/envoy.yaml` para ver el campo exacto. **`cannot bind '0.0.0.0:80': Address already in use`**: otro proceso usa el puerto 80. Identifícalo con `sudo ss -ltnp 'sport = :80'` y detenlo o cambia `port_value` en el listener. **`cannot bind '0.0.0.0:80': Permission denied`**: falta la capacidad `CAP_NET_BIND_SERVICE` en la unidad. Revisa las líneas `AmbientCapabilities` y `CapabilityBoundingSet` y ejecuta `sudo systemctl daemon-reload`. **Envoy responde `503` con `no healthy upstream`**: todos los endpoints han fallado el health check. Comprueba con `/clusters` qué endpoints están marcados como `/failed_active_hc` y que la ruta del `http_health_check` devuelve un 200 en tus backends. **Envoy responde `503` con `upstream connect error`**: el backend no acepta conexiones en la IP y puerto configurados. Pruébalo directamente con `curl` desde el servidor. ## Conclusión Tienes Envoy instalado en Ubuntu 24.04 como servicio systemd sin privilegios de root, balanceando tráfico HTTP entre dos backends con health checks activos y reintentos, y sabes usar la interfaz de administración para ver el estado de cada endpoint y las métricas. Como siguientes pasos puedes añadir un listener en el puerto 443 con terminación TLS mediante un `transport_socket` y tus certificados, crear rutas por prefijo o por dominio que apunten a clusters distintos, o recoger `/stats/prometheus` con Prometheus para vigilar latencias y errores.