Uso de OpenBSD para hospedaje de página web

By B.E. Alejandro4 minutes read


Contexto y motivación

Decidí migrar el hospedaje de mi página web a OpenBSD como un ejercicio deliberado de control, simplicidad y seguridad.
No fue una decisión basada en rendimiento, escalabilidad comercial ni automatización extrema, sino en comprensión total del sistema.

OpenBSD obliga a entender cada archivo de configuración, cada servicio activo y cada permiso. No oculta complejidad: la expone. Ese fue el motivo central de esta migración.

El objetivo era claro: un servidor auditable, predecible y mínimo.

Infraestructura y VM

El servidor corre en una máquina virtual alquilada (VPS) de bajo costo, suficiente para contenido estático y servicios mínimos.

Características generales de la VM:

El proveedor no es relevante: OpenBSD no depende de features del host. El sistema se mantiene portable y reproducible.

Elección del stack

El stack fue elegido conscientemente para reducir superficie de ataque:

No hay nginx, no hay docker, no hay paneles web, no hay Node en producción. Solo binarios del sistema base y archivos de texto.

Migración a OpenBSD

La migración incluyó:

Separación clara entre: sistema (/etc), contenido (/var/www), claves (/etc/ssl, /etc/acme). Nada se dejó “por default” sin entenderlo.

Servidor web con httpd

El servidor web se configuró usando httpd nativo, sin módulos externos.

Configuración base simplificada:

server "nezzontli.xyz" {
    listen on * port 80
    root "/htdocs"

    location "/.well-known/acme-challenge/*" {
        root "/acme"
        request strip 2
    }
}

server "nezzontli.xyz" {
    listen on * tls port 443
    root "/htdocs"

    tls {
        certificate "/etc/ssl/nezzontli.xyz.fullchain.pem"
        key "/etc/ssl/private/nezzontli.xyz.key"
    }
}

HTTPS con acme-client

OpenBSD incluye acme-client en base, lo que elimina dependencias externas.

Flujo real:

  1. Configurar httpd solo en HTTP
  2. Resolver DNS correctamente (A records apuntando a la VM)
  3. Ejecutar: doas acme-client -v nezzontli.xyz
  4. Verificar creación de certificados en /etc/ssl
  5. Habilitar TLS en httpd
  6. Reiniciar servicio

No se usan scripts externos. La renovación se maneja vía cron del sistema.

Problemas encontrados (y soluciones)

1. Error 404 en ACME challenge

Causa: httpd no estaba sirviendo correctamente /var/www/acme.

Solución:

doas mkdir -p /var/www/acme
doas chown -R web:web /var/www

2. DNS no propagado

Durante el primer intento, el dominio resolvía a múltiples IPs antiguas: dig nezzontli.xyz +short

Solución: Esperar propagación completa y eliminar registros conflictivos.

3. Confusión con DNSSEC

DNSSEC no es requisito para Let’s Encrypt HTTP-01. DNSSEC es independiente de TLS. No se activó en esta etapa.

Generación del sitio con Zola

El sitio es 100% estático.

Flujo básico:

zola build
doas rsync -a --delete public/ /var/www/htdocs/

No hay generación en runtime. No hay escritura desde el servidor web.

Mirror Tor (.onion)

Se configuró un Hidden Service de Tor como mirror del sitio.

/etc/tor/torrc:

HiddenServiceDir /var/tor/hidden_service/
HiddenServicePort 80 127.0.0.1:80

httpd escucha solo en localhost para Tor:

server "*" {
    listen on 127.0.0.1 port 80
    root "/tor"
}

Build específico para Tor:

zola build --base-url http://<onion>.onion
doas rsync -a --delete public/ /var/www/tor/

Integración Tor Browser (Onion-Location):

<meta http-equiv="onion-location" content="http://<onion>.onion">

Automatización del despliegue

Script único para clearnet + Tor:

#!/bin/sh
set -e

ONION_URL="http://<onion>.onion"

git pull

zola build
doas rsync -a --delete public/ /var/www/htdocs/

zola build --base-url "$ONION_URL"
doas rsync -a --delete public/ /var/www/tor/

Instalado en: /usr/local/bin/update-site

Control de acceso: SSH + YubiKey

Acceso remoto sin contraseñas persistentes:

La clave privada nunca toca el disco.

Control de versiones y firmas

Repositorio alojado en Codeberg:

El servidor no compila desde hooks remotos: el despliegue es consciente y manual.

Estructura del proyecto

site/
├── config.toml
├── content/
├── templates/
├── static/
├── public/
└── scripts/

En servidor:

/var/www/
├── htdocs/
├── tor/
└── acme/

Qué falta por hacer

Pendientes reales:

Idea central

Este proyecto no busca conveniencia ni velocidad de desarrollo.

Busca:

OpenBSD no acelera el trabajo. Elimina errores silenciosos. Ese es el valor.