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 nginx

Rutas que van a Astro SSR

  • / (home) — si la query no tiene wc-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/:

VhostServicio
dash.yaxa.co.confOMS
dashdemo.yaxa.co.confOMS demo
api.yaxa.co.confAPI interna
automata.yaxa.co.confn8n
analytics.yaxa.co.confPlausible (inactivo)
sherlock.yaxa.co.confPostHog
passwords.yaxa.co.confVaultwarden
marketing.yaxa.co.confMautic
docs.yaxa.co.confeste vault
cc.yaxa.co.confClaude 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 nginx

Runbook relacionado: nginx-reload.