# Runners self-hosted

> Usa Egress CI en runners self-hosted de Linux, con sudo o Docker, en hosts de un solo job y compartidos.

En un runner self-hosted la acción necesita lo mismo que en uno de GitHub: root, para instalar el bloqueo nftables. Lo consigue de una de estas dos formas, en este orden:

| Cómo | Qué necesita | Cómo se ejecuta el sidecar |
|---|---|---|
| `sudo` | El usuario del job puede usar `sudo` sin contraseña (`sudo -n true` funciona) | Como un proceso root en el host |
| Docker | El usuario del job llega al daemon de Docker (pertenece al grupo `docker`) | En un contenedor privilegiado con la red del host, a partir de una imagen local vacía (no se descarga nada), con el `/` del host montado en solo lectura |

Sin ninguna de las dos, la acción arranca igualmente el proxy, pero sin el bloqueo: solo se informa de lo que pasa por `HTTPS_PROXY` y, en enforce, solo eso se rechaza; las herramientas que ignoran las variables de proxy y los contenedores no quedan cubiertos. Pon `lock: "on"` para que el paso falle en ese caso. Cuando hay root pero el bloqueo no se puede instalar (falta `nft`, por ejemplo), enforce hace fallar el paso.

## Requisitos

- Linux en x64 o arm64, con nftables (`nft` en `/usr/sbin`, `/sbin` o `/usr/bin`) y un kernel que lo soporte, e iproute2 (`ip`).
- `bash`, `curl`, `gzip`, `sha256sum` y `sudo` o `docker` en el `PATH` del job.
- Para el seguimiento de Docker: el socket del daemon y el bridge `docker0`.
- El usuario del job en el runner no es root (el bloqueo afecta a los sockets de ese usuario; la acción se niega a bloquear el uid 0).

## Ejemplo

```yaml
jobs:
  test:
    runs-on: [self-hosted, linux, x64]
    steps:
      - uses: actions/checkout@v5
      - uses: openwaf-dev/egress-action@v0.3.2
        with:
          lock: "on"
          containers: track
      - run: make test
```

## Hosts compartidos

Varios runners pueden compartir host si cada uno usa su propio usuario:

- El bloqueo es una tabla nftables por usuario (`egress_ci_<uid>`) que solo afecta a los sockets de ese usuario y a las subredes de las redes Docker de ese job. Los jobs de otro usuario del runner no se ven afectados.
- Los puertos del sidecar son fijos por usuario, por debajo del rango efímero; si están ocupados, pasa a los siguientes libres.
- Usa `containers: track`, nunca `lock-all`: `lock-all` rechaza el tráfico fuera de la política del job actual de cualquier contenedor, también el de los demás jobs.
- Un runner que da a cada slot de jobs su propio socket de Docker en `DOCKER_HOST` sigue funcionando: el socket del job reenvía a él.

Ejecuta cada runner de un host con su propio usuario: dos runners del mismo usuario en un host compartirían la tabla del bloqueo.

## Qué significa root aquí

La acción necesita root para bloquear el job, y el job tiene ese mismo root: un paso que ejecute `sudo nft delete table …` o que use el grupo docker para arrancar un contenedor privilegiado puede quitar el bloqueo. En un runner self-hosted, el grupo docker equivale a root. Egress CI hace visible y más difícil la exfiltración por parte de una dependencia o una herramienta; no contiene a un paso que se propone escaparse. Ver [límites](https://developers.openwaf.dev/es/egress/ci/limits/).

## Runners efímeros

En los runners que empiezan limpios en cada job (efímeros o just-in-time, VMs con autoescalado), `lock-all` es seguro y no hay nada que limpiar entre jobs. En los runners persistentes, el paso posterior (que se ejecuta aunque falle un paso) quita el bloqueo, el sidecar y el builder del job; conserva la caché de BuildKit del builder, hasta 4 GB, para el siguiente job del mismo usuario.
