Un sistema completo que administro, con pruebas verificables en vivo
El sitio que estás leyendo funciona en un servidor que yo mismo configuro, protejo, actualizo y superviso, desde la máquina vacía hasta esta página.
La necesidad
Un portfolio debería demostrar competencias, no solo enumerarlas. Alojarlo en una plataforma gestionada ocultaría precisamente lo que quiero mostrar: mantener un servicio fiable y seguro a lo largo del tiempo.
La idea
Convertir el propio alojamiento en la demostración: todo lo que se cuenta aquí se puede comprobar en directo, en la misma máquina que sirve esta página.
Lo que construí
- Un servidor en la nube en la región de París, conseguido tras seis intentos a lo largo de varios días: la capacidad gratuita allí escasea.
- Toda la pila web, con cada servicio en su propio espacio restringido para que un problema no pueda propagarse a los demás.
- Refuerzo de la seguridad desde la primera noche —7 medidas aplicadas en una sola noche sin ninguna interrupción— y continuado paso a paso.
- Actualizaciones automáticas: un cambio aprobado se publica solo, se comprueba su estado y se revierte automáticamente si la nueva versión no responde.
- Copias de seguridad continuas de la base de datos, además de instantáneas nocturnas conservadas a diario, semanal y mensualmente.
- Una sonda independiente que comprueba la seguridad del sitio cada hora y publica el resultado: puedes verlo más abajo.
El resultado
- 5comprobaciones de seguridad repetidas cada hora por una sonda independiente
- 7aplicadas en una noche, sin interrupción
- 6intentos para conseguir el servidor
- 1 hentre dos comprobaciones de seguridad independientes
Sirve este portfolio desde agosto de 2026, junto con EventMap. Los controles en directo que aparecen más abajo los mide una sonda independiente; no están escritos a mano.
Compruébalo tú mismo
Controles en directo
- TLS verificado
- origen verificado
- cabeceras verificado
- DNSSEC verificado
- disponibilidad verificado
En imágenes
Lo que aprendí
No probar nunca solo desde la propia máquina: con dos cortafuegos superpuestos, un servicio puede responder perfectamente en local mientras nadie en Internet puede alcanzarlo. Y decidir no instalar algo —aquí, un servidor de bases de datos— también es una competencia de operaciones.
Detalles técnicos Tecnologías, arquitectura y decisiones, para lectores técnicos
Tecnologías
- Ubuntu 22.04
- Oracle Cloud ARM (Always Free)
- nginx
- Node.js + Express
- SQLite (node:sqlite)
- systemd
- fail2ban
- iptables
- Cloudflare
- GitHub Actions
- Litestream + restic
La arquitectura de un vistazo
- El navegador del visitante
- Cloudflare — TLS y caché
- nginx — cabeceras de seguridad, limitación de peticiones
- Node.js + Express — páginas generadas en el servidor, en 7 idiomas; un servicio systemd aislado
- SQLite (node:sqlite) — proyectos y registro de visitas propio, sin terceros
- Alrededor: GitHub Actions prueba cada cambio; la VM descarga la versión validada, comprueba /health y vuelve atrás si algo falla; el Observatorio de seguridad repite sus comprobaciones cada 30 minutos.
Cómo funciona
- Máquina virtual de 4 OCPU / 24 GB (Ubuntu 22.04). Proxy inverso nginx delante de servicios aislados, cada uno con un usuario de sistema dedicado sin shell, con ProtectSystem=strict y NoNewPrivileges.
- Primera noche (23 de agosto de 2026): contraseña de administración regenerada, fail2ban en SSH, cabeceras de seguridad estrictas (CSP, HSTS, X-Frame-Options), último octeto de la IP a cero en los registros de acceso, retención de journald acotada, rotación de registros de nginx y copia cifrada de los secretos guardada fuera de la máquina.
- Después: limitación de peticiones en nginx, rpcbind desactivado, swap, escritorio remoto limitado a 127.0.0.1 (solo por túnel SSH), autenticación SSH por contraseña desactivada y certificado Cloudflare Origin CA en modo Full (strict).
- Despliegue continuo en modo pull: un push a master se valida en GitHub Actions, que mueve una etiqueta prod; la máquina la descarga mediante un temporizador systemd, comprueba su estado y vuelve atrás automáticamente. Ningún puerto de entrada abierto y ninguna credencial de la máquina almacenada en GitHub.
- Dos cortafuegos superpuestos (iptables en la máquina + la Security List de la nube): por eso nunca pruebo solo desde la propia máquina.
- Compromiso deliberado: las actualizaciones de seguridad se instalan solas, pero la máquina nunca se reinicia ni cambia de versión mayor por su cuenta.
- Solo seguimiento de visitas propio: ninguna cookie de terceros, direcciones IP cifradas con hash antes de guardarse y registros eliminados a los 12 meses.
Decisiones y compromisos
- Páginas generadas en el servidor en lugar de cargadas en el navegador: siguen siendo indexables en siete idiomas y legibles sin JavaScript.
- Servicios systemd en lugar de Docker: la producción funciona como unidades systemd aisladas, con cuotas de CPU y memoria; un contenedor que nunca se despliega no demostraría nada.
- Un único flujo JSON público (/api/contenus.json), reutilizado por Mindmap, en lugar de una segunda API: una sola fuente de verdad y nada que sincronizar.
Incidentes y soluciones
- Tras el rediseño, el informe automático de las pull requests superó el límite de 65.536 caracteres de los comentarios de GitHub (por las capturas incrustadas): las pruebas pasaban, pero la publicación fallaba. Se resolvió con miniaturas más ligeras y un presupuesto de 60.000 caracteres.
- Cloudflare seguía sirviendo scripts antiguos hasta 4 horas después de un despliegue: ahora cada URL de CSS y JavaScript lleva una huella de su contenido (?v=), así que una versión nueva nunca se mezcla con archivos antiguos.
- En árabe, un valor como «43 → 9.9 MB» se mostraba al revés por culpa del algoritmo de texto bidireccional: ahora los valores latinos se aíslan con marcas Unicode.
Lo que aún falta
- Sin reinicio automático: una decisión deliberada