Saltar al contenido
← Guías

Guía · Webs y formularios

Cómo dejar WordPress: web rápida y segura con Astro, Cloudflare, una API y PostgreSQL en AWS

Guía y plantilla gratuita para sustituir WordPress por una web estática en Astro detrás de Cloudflare, con una API protegida por AWS WAF, CORS cerrado a tu dominio y PostgreSQL privado en AWS.

Actualizada
22 oct 2026
Lectura
14 min
Herramientas
7

Respuesta corta: sustituye WordPress por una web estática en Astro, servida desde Cloudflare con su WAF delante, y lleva lo único dinámico (los formularios) a una API pequeña con PostgreSQL en AWS: base de datos sin IP pública, secretos en Secrets Manager, AWS WAF delante y CORS cerrado a tu dominio. Todo en Git. El resultado es una web que carga en milisegundos, no tiene PHP que parchear y cuyo único punto de entrada está vigilado por dos cortafuegos. Tienes la plantilla completa, con tests, en nuestro GitHub.

Por qué salir de WordPress ahora

El 21 de octubre de 2026 se publicó el parche de PHP2Shell, dos fallos críticos que permiten tomar el control de un servidor sin iniciar sesión. Solo hay parche para PHP 8.2 en adelante. Estimamos que unas 115.500 webs del Kit Digital siguen en PHP 8.1 o anterior.

El problema no es solo este fallo. Una web de WordPress es un programa que se ejecuta en cada visita: PHP, el núcleo, la plantilla y cada plugin. Todo eso hay que actualizarlo siempre, y casi nadie lo hace cuando acaba el contrato de mantenimiento. La mayoría de webs de pyme son cinco páginas y un formulario: no necesitan un servidor ejecutando código para enseñar un texto.

La arquitectura

Es la misma idea que usa esta web, yeswelab.com (Astro, una API propia con PostgreSQL y todo en Git), reforzada con Cloudflare delante del frontal y AWS detrás:

CapaPiezaQué la protege
EntradaCloudflare (DNS, CDN y certificado)WAF gestionado, reglas propias, límite de peticiones, Bot Fight Mode, DNSSEC
FrontalWeb estática en AstroNo ejecuta código: solo ficheros. CSP estricta, HSTS, sin iframes
FormulariosTurnstile de CloudflareCaptcha invisible y gratuito; el token se valida en la API
APIFastAPI en AWS ECS Express ModeAWS WAF, CORS cerrado, comprobación del origen, límite por IP, validación estricta
DatosPostgreSQL 18 en Amazon RDSSin IP pública, cifrada, copias de 7 días, solo acepta a la API, usuario con permisos mínimos
CódigoGit (GitHub)Cada cambio queda registrado; secretos fuera del repositorio

Si alguien entra en la API, el usuario de la base de datos solo puede insertar y contar mensajes: ni leerlos, ni borrarlos, ni crear tablas. Lo comprueban los tests de la plantilla.

Paso 1: la plantilla

git clone https://github.com/magranero/yeswelab-laboratorio
cd yeswelab-laboratorio/web-segura-sin-wordpress-astro-cloudflare-aws
docker compose up -d --build        # PostgreSQL y la API en local
cd api && uv run pytest             # 17 tests
cd ../web && npm install && npm run dev

Trae una web de ejemplo con formulario de contacto, la API, el esquema de la base de datos, la configuración de Cloudflare y los comandos de AWS. La hemos probado en local con PostgreSQL 18: el formulario envía, la API guarda, y las peticiones desde otra web reciben un 403.

Paso 2: pasar el contenido de WordPress a Astro

  1. Exporta el contenido: en WordPress, Herramientas → Exportar → Todo el contenido. Descargas un XML con páginas y entradas.
  2. Conviértelo a Markdown: cada página pasa a ser un fichero .md en src/content/. Con Claude es rápido: le das el XML y la plantilla y le pides las páginas en Astro, manteniendo títulos, descripciones y URLs.
  3. Conserva las URLs o, si cambian, crea redirecciones 301 en public/_redirects solo para las que tienen tráfico en Search Console. Así no pierdes posiciones en Google.
  4. Imágenes: a src/assets/, para que Astro las optimice y les ponga tamaño.

Si el cliente necesita editar textos, añade un CMS que guarde en Git, como Decap CMS o Keystatic. Edita en un panel y cada cambio vuelve a publicar la web estática.

Paso 3: el frontal en Cloudflare, con el WAF bien puesto

La web se publica con npm run deploy en Cloudflare Workers con assets estáticos: los ficheros se sirven desde la red de Cloudflare, con la seguridad delante. En el panel de Cloudflare:

  1. SSL/TLS: «Always Use HTTPS», TLS mínimo 1.2 y DNSSEC activado.

  2. WAF gestionado: en el plan gratuito ya viene activo el conjunto de reglas gestionadas de Cloudflare.

  3. Reglas propias (5 en el plan gratuito). Dos que cierran la puerta a casi todo el ruido:

    # Una web estática solo recibe GET y HEAD
    (http.request.method ne "GET" and http.request.method ne "HEAD")
    
    # Quien busca un WordPress o un .env no tiene nada que hacer aquí
    (http.request.uri.path contains "/wp-" or http.request.uri.path contains ".php"
     or http.request.uri.path contains "/.env" or http.request.uri.path contains "/.git")
  4. Límite de peticiones: el plan gratuito permite 1 regla, contada por IP en periodos de 10 segundos. Por ejemplo, más de 100 peticiones en 10 segundos → bloquear.

  5. Bot Fight Mode activado.

  6. Turnstile: crea un widget para tu dominio. La clave de sitio va en la web; el secreto, solo en la API.

Y las cabeceras de seguridad viajan con la propia web, en public/_headers:

/*
  Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  Content-Security-Policy: default-src 'self'; script-src 'self' https://challenges.cloudflare.com; frame-src https://challenges.cloudflare.com; connect-src 'self' https://api.tudominio.es; ...
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff

La CSP solo permite scripts de tu dominio y de Turnstile, y conexiones solo a tu API. Para que funcione, la plantilla configura Astro para no meter nunca scripts ni estilos en línea.

Paso 4: la API, con CORS cerrado a tu web

La API solo hace una cosa: recibir el formulario, validarlo, guardarlo y avisarte (por Telegram, si quieres). Sus defensas, de fuera a dentro:

app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)  # sin mapa público de la API
app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://tudominio.es", "https://www.tudominio.es"],  # nunca "*"
    allow_methods=["POST"],
    allow_headers=["Content-Type"],
)
  • CORS cerrado: solo tu dominio puede llamarla desde un navegador.
  • Origen comprobado en el servidor: antes de leer el cuerpo, un POST que no viene de tu web recibe un 403.
  • Turnstile: cada envío lleva un token que la API valida con Cloudflare, y que tiene que haberse emitido para tu dominio.
  • Antibots sin molestar: un campo oculto que solo rellenan los bots y un tiempo mínimo de relleno. Al bot se le responde «OK» para no darle pistas, pero no se guarda nada.
  • Límite por IP: 5 envíos por hora. La IP se guarda como hash, nunca en claro.
  • Validación estricta: cada campo con su tipo y su longitud máxima.

CORS no es un cortafuegos. Solo lo respetan los navegadores. Impide que otra web use tu API desde el navegador de sus visitas, pero un script puede saltárselo y poner el Origin que quiera. Por eso nunca va solo: Turnstile, el límite por IP y el WAF son los que paran a los scripts.

Paso 5: la API y PostgreSQL en AWS, protegidos

La plantilla trae los comandos en aws/README.md. Lo importante de cada pieza:

PostgreSQL en RDS, privada. Se crea con --no-publicly-accessible (sin IP pública), --storage-encrypted, copias de 7 días, protección contra borrado, parches menores automáticos y la contraseña del administrador generada y guardada en Secrets Manager. Su grupo de seguridad solo acepta el puerto 5432 desde las tareas de la API. Y la conexión exige TLS (sslmode=require).

Usuario con permisos mínimos. La tabla la crea el administrador una vez. La API se conecta con app_web, que solo puede insertar:

REVOKE ALL ON SCHEMA public FROM PUBLIC;
GRANT USAGE ON SCHEMA public TO app_web;
GRANT SELECT (id, creado, ip_hash), INSERT ON contactos TO app_web;

Secretos fuera del código. La URL de la base de datos, el secreto de Turnstile y la sal de las IP van a Secrets Manager. El contenedor los recibe como variables de entorno, y su rol solo puede leer esos secretos.

La API en ECS Express Mode. App Runner dejó de admitir clientes nuevos el 30 de abril de 2026, y AWS recomienda ECS Express Mode en su lugar. Con un comando crea el servicio en Fargate, el balanceador con HTTPS, el escalado y los registros. La imagen vive en ECR con análisis de vulnerabilidades en cada subida y se ejecuta sin root.

AWS WAF delante del balanceador, con cinco reglas:

ReglaQué para
Solo rutas de la APITodo lo que no sea /v1/… o /health: quien busque /wp-admin o /.env se queda fuera
Límite por IPMás de 100 peticiones en 5 minutos desde la misma IP
IP con mala reputaciónLa lista de Amazon de IP usadas por bots y atacantes
Ataques comunesReglas gestionadas de AWS contra el Top 10 de OWASP
Entradas maliciosas conocidasPatrones de exploits conocidos

Los comandos de AWS los hemos comprobado con la documentación oficial de octubre de 2026, pero no los hemos ejecutado en una cuenta real: revisa cada paso en la consola.

Paso 6: todo en Git

  • Un repositorio por web, con main protegida: los cambios entran por pull request.
  • Despliegue automático al fusionar: Cloudflare publica la web y AWS la nueva imagen de la API.
  • Nunca secretos en el repositorio: .env en .gitignore y los secretos de verdad en Secrets Manager y en el panel de Cloudflare.
  • Avisos de dependencias (Dependabot en GitHub) para Astro y las librerías de la API.

Lista de comprobación antes de publicar

ComprobaciónCómo
HTTPS obligatorio y HSTScurl -sI https://tudominio.es muestra Strict-Transport-Security
CSP sin erroresLa consola del navegador no muestra bloqueos al enviar el formulario
CORS cerradoUn OPTIONS desde otro origen no devuelve Access-Control-Allow-Origin
La API rechaza otros orígenesUn POST con Origin: https://otra-web.com devuelve 403
El WAF filtrahttps://api…/wp-admin devuelve 403
Base de datos privadaEl punto de conexión de RDS no responde desde tu casa
Copias activasRDS → Copias de seguridad automatizadas: 7 días
Sin secretos en Gitgit log -p no contiene contraseñas ni claves

Cuánto cuesta

  • Cloudflare: el plan gratuito cubre el frontal, el WAF gestionado, las reglas de arriba y Turnstile.
  • AWS: pagas el balanceador, Fargate, RDS, los registros y AWS WAF (5 $ al mes por ACL, 1 $ por regla y 0,60 $ por millón de peticiones). Calcula tu caso con la calculadora de AWS y tu región.
  • El truco para agencias: el balanceador de Express Mode se comparte entre hasta 25 servicios, y una instancia de RDS puede alojar una base de datos por cliente. Una sola infraestructura protegida para toda la cartera.

Si es una única web y AWS se queda grande, la misma API funciona en un VPS con Docker, que es como corre la de esta web. Pierdes el WAF de AWS, pero no Cloudflare delante del frontal ni las defensas de la propia API.

Limitaciones

  • No es para todo. Una tienda con miles de productos o un área de clientes necesitan más que un formulario: la API crece, y con ella lo que hay que mantener.
  • Los comandos de AWS no los hemos ejecutado en una cuenta real. La API, la base de datos, la web y sus defensas sí las hemos probado en local, con 17 tests y un envío real desde el navegador.
  • Seguridad no es instalar y olvidar: actualiza dependencias, revisa los registros del WAF y prueba de vez en cuando que las copias se restauran.

Relacionado

Lo que haríamos en el laboratorio

Si tienes una cartera de webs en WordPress, migramos una contigo, medimos tiempos de carga, coste mensual y superficie de ataque antes y después, y te dejamos el proceso listo para repetirlo con el resto.

¿Quieres saber cuánto ganarías dejando WordPress? Encárganos el experimento.

Preguntas frecuentes

¿Qué puedo usar en lugar de WordPress?

Para una web de empresa de pocas páginas, un generador de webs estáticas como Astro: produce HTML puro que se sirve desde una CDN, sin PHP ni base de datos expuesta. Lo dinámico (formularios, reservas) va a una API pequeña con su propia base de datos.

¿Una web estática es más segura que WordPress?

Sí, porque no ejecuta código en el servidor cuando alguien la visita: no hay PHP, ni plugins, ni panel de administración que atacar. La superficie de ataque queda en la API, que es pequeña y está detrás de un WAF.

¿Qué es CORS y basta para proteger una API?

CORS es la regla que dice a los navegadores qué webs pueden llamar a tu API. Cerrarlo a tu dominio impide que otra web la use desde el navegador de sus visitas, pero no basta: un script puede llamarla igual. Por eso hace falta además comprobar el origen en el servidor, un captcha como Turnstile, límite por IP y un WAF.

¿Cloudflare es gratis?

El plan gratuito incluye DNS, CDN, certificado, el conjunto de reglas gestionadas de su WAF, 5 reglas propias, 1 regla de límite de peticiones y Turnstile. Para una web estática de pyme suele bastar.

¿Cuánto cuesta la parte de AWS?

Depende de la región y del tráfico: pagas el balanceador, Fargate, RDS, los registros y AWS WAF (5 dólares al mes por ACL, 1 dólar por regla y 0,60 dólares por millón de peticiones). Para una sola pyme es más caro que un hosting compartido; para una agencia sale a cuenta porque un balanceador sirve hasta 25 servicios y una base de datos puede alojar las de muchos clientes.

¿Puede mi cliente seguir editando la web sin saber programar?

Sí, con un CMS que guarde los cambios en Git, como Decap CMS o Keystatic: el cliente edita en un panel y cada cambio vuelve a publicar la web estática. Sin servidor PHP que mantener.

#Astro#Cloudflare#Turnstile#FastAPI#PostgreSQL#AWS#Git