Case study
Infraestructura propia — VPS, Coolify y un casi-lockout My own infrastructure — VPS, Coolify, and a near-lockout
Monté mi propio servidor para dejar de depender de plataformas ajenas. La lección más cara no fue instalar nada: fue cerrar tres puertos y quedarme afuera. I set up my own server to stop depending on someone else platform. The most expensive lesson was not installing anything: it was closing three ports and locking myself out.
Contexto Context
Venía deployando todo en plataformas administradas sin entender qué pasaba abajo. Alquilé un VPS propio y monté Coolify encima como PaaS, para tener un solo lugar donde deployar mis proyectos y, sobre todo, para aprender administración de servidores de verdad: con un server que si lo rompo, lo arreglo yo. I had been deploying everything on managed platforms without understanding what happened underneath. I rented my own VPS and set up Coolify on top as a PaaS, to have a single place to deploy my projects and, above all, to actually learn server administration: with a server that, if I break it, I fix it.
El incidente The incident
Coolify publica algunos puertos internos que Docker abre salteándose el firewall del sistema. Para cerrarlos usé el firewall del panel del proveedor y escribí una política con tres reglas de bloqueo, confiando en que las reglas implícitas de aceptar todo que la interfaz mostraba al final seguirían valiendo. No valían: al aplicar una política propia, esas implícitas dejan de existir y todo lo que no esté permitido explícitamente queda bloqueado. Cerré también el 22, el 80 y el 443. Sin SSH y sin dashboard. Coolify publishes some internal ports that Docker opens bypassing the system firewall. To close them I used the provider panel firewall and wrote a policy with three block rules, trusting that the implicit accept-all rules the UI listed at the end would still apply. They did not: once you apply your own policy, those implicit rules stop existing and anything not explicitly allowed is blocked. I also closed 22, 80, and 443. No SSH, no dashboard.
Cómo salí y cómo lo arreglé bien How I got out, and how I fixed it properly
- El servidor nunca dejó de funcionar: respondía al ping, era filtrado puro. Salí quitando la política desde el panel del proveedor, que es externo al server — el paracaídas que hay que tener identificado ANTES de tocar un firewall.
- La herramienta correcta no era un firewall externo más contundente, sino la cadena DOCKER-USER de iptables: es la que Docker respeta y nunca pisa.
- Esa cadena vive en FORWARD, o sea el tráfico hacia contenedores, así que por diseño no puede cortar el SSH del host, que va por INPUT. No hay lockout posible.
- El detalle que costó entender: hay que filtrar por el puerto que pidió el cliente ANTES del NAT de Docker. Filtrar por el puerto de destino común no funciona, porque a esa altura ya fue traducido al puerto interno del contenedor.
- Reglas persistidas para que sobrevivan al reboot, y verificación desde afuera del servidor, no desde adentro.
Mi rol My role
Todo, y a propósito a mano: evaluación y compra del proveedor, instalación, hardening, dominio y certificados para el dashboard, y el runbook de deploy por proyecto. Es el proyecto donde decidí no automatizar nada hasta entenderlo, porque el objetivo era aprender, no terminar rápido. Everything, and deliberately by hand: evaluating and buying the provider, installation, hardening, domain and certificates for the dashboard, and the per-project deploy runbook. This is the project where I decided not to automate anything until I understood it, because the goal was learning, not finishing fast.
Aprendizajes Learnings
- La política por defecto de un firewall se verifica contra la documentación o con una prueba reversible. No se deduce de lo que muestra una interfaz.
- Antes de aplicar un cambio de red, tener el camino de vuelta identificado y probado. Y verificar 22, 80 y 443 desde afuera inmediatamente después, no solo los puertos que querías cerrar.
- Elegir la herramienta hecha para el problema antes que la más contundente. La opción más agresiva fue justamente la que casi me deja afuera.
- Los incidentes valen si se escriben. Este quedó documentado con causa raíz y regla, y por eso no volvió a pasar.