Nginx routing
Nginx decide si cada request va a Astro SSR (storefront, performance-first) o a WordPress + WooCommerce (admin, REST API, PHP legacy). La lógica vive 100% en /etc/nginx/sites-available/store.yaxa.co.conf.
Archivo principal
/etc/nginx/sites-available/store.yaxa.co.conf — cubre TODOS los tenants LATAM + España + subdominios especiales (yabuy, express, etc.). Un solo server_name con muchos hostnames.
⚠️ sites-enabled es copia, no symlink — siempre copiar después de editar:
sudo cp /etc/nginx/sites-available/store.yaxa.co.conf /etc/nginx/sites-enabled/store.yaxa.co.conf
sudo nginx -t && sudo systemctl restart nginxRutas que van a Astro SSR
/(home) — si la query no tienewc-api,add-to-cart, etc./products,/product,/product-category,/explorar,/comprar…/checkout,/carrito,/api,/gracias,/transferencia-bancaria(sin cache)/nosotros,/contacto,/politicas,/tienda,/seguimiento… (con cache)/data/(con cache)/_img/→ imgproxy (cache propio)
Backend: PM2 cluster en 127.0.0.1:4321. Ver astro-ssr.
Rutas que van a WordPress (PHP FastCGI 8001)
/wp-admin/,/wp-json/(nunca cacheadas)*.php(con FastCGI cache)- Fallback (
try_files ... index.php) - Si Astro responde 418 en home (query
wc-api,add-to-cart…) →@wordpress
Cloudflare → origen
Los hostnames proxied por CF llegan al origen con:
- Cliente real en
X-Forwarded-For/CF-Connecting-IP - HTTPS siempre (CF→origen via 443)
CF tiene Page Rules globales para *.yaxa.co que cachean agresivamente (TTL de meses). Para subdominios donde no queremos cache (como docs.yaxa.co), hay que enviar Cache-Control: no-store y CDN-Cache-Control: no-store desde el origen.
Catch-all y ACME challenges
/etc/nginx/sites-enabled/default es catch-all para Host’s no-matcheados:
- Atrapa requests a dominios cuyo hostname no está aún en ningún
server_name - Sirve ACME challenges desde
/home/store/public_html/.well-known/acme-challenge/(con fallback a/home/meet/public_html) - Devuelve
444(drop) para todo lo demás
⚠️ Gotcha crítico: el return 444 debe ir DENTRO de location /, NO a nivel server. A nivel server se ejecuta en la fase rewrite (antes del location matching) y bloquea el location ^~ /.well-known/acme-challenge/ — el resultado es “Empty reply from server” en certbot.
Subdominios en vhosts dedicados
Cada uno tiene su propio archivo en sites-available/:
| Vhost | Servicio |
|---|---|
dash.yaxa.co.conf | OMS |
dashdemo.yaxa.co.conf | OMS demo |
api.yaxa.co.conf | API interna |
automata.yaxa.co.conf | n8n |
analytics.yaxa.co.conf | Plausible (inactivo) |
sherlock.yaxa.co.conf | PostHog |
passwords.yaxa.co.conf | Vaultwarden |
marketing.yaxa.co.conf | Mautic |
docs.yaxa.co.conf | este vault |
cc.yaxa.co.conf | Claude Code |
Herramientas útiles
# Ver qué vhost atrapa un request:
curl -sv -H "Host: dominio" http://148.113.161.108/ 2>&1 | head -40
# Validar config antes de reload:
sudo nginx -t
# Reload sin downtime:
sudo systemctl reload nginx
# Reinicio completo (solo si reload no basta):
sudo systemctl restart nginxRunbook relacionado: nginx-reload.