Guía9 min

Dominio custom y TLS para un agente IA: webhooks que no se caen

Resumen

Cómo poner un hostname estable (no *.vercel.app ni *.railway.app) delante del agente: DNS, certificados automáticos en Vercel, Railway, Workers y Fly, puertos que Telegram acepta, Custom Domains vs Routes, y por qué el preview no debe heredar el dominio de producción.

VercelRailwayCloudflare
Hostname estable y candado TLS delante de un agente con webhook

Qué resuelve

Esta pieza se queda en la decisión práctica: qué instalar, qué riesgo agrega y cómo aplicarlo sin romper operación.

El webhook del bot no apunta a un commit. Apunta a un hostname. Si usas algo-git-abc.vercel.app o el *.railway.app de un redeploy, Telegram, Slack o WhatsApp se quedan pegados a una URL que muere. Dominio custom + TLS no es branding: es el contrato del webhook. Fuentes oficiales consultadas el 3 de septiembre de 2026.

El deploy comparativo elige plataforma. Preview vs production aísla secretos. Esta guía cubre el nombre público que esas plataformas sirven.

La regla

Production = un hostname que no cambia (agente.tudominio.com) con certificado válido. Preview = URL efímera, sin el CNAME de producción.

Si el preview hereda el dominio, el PR “gana” el webhook de tus usuarios.

Qué exige el webhook

Telegram setWebhook solo acepta HTTPS en puertos 443, 80, 88 o 8443. Certificado autofirmado casero es pelea innecesaria: deja que el proveedor emita Let’s Encrypt / ACME.

Checklist mínimo antes de setWebhook:

  1. DNS resuelve al proxy correcto (CNAME o A según docs).
  2. HTTPS 200 en https://agente.tudominio.com/health (o /webhook).
  3. El certificado cubre exactamente ese hostname (no solo el apex).
  4. El token de Telegram de producción apunta a esa URL, no a un *.vercel.app.

Vercel

Cada deploy recibe un hostname *.vercel.app asignado por orden de llegada: no se reserva. Settings → Domains → añade agente.tudominio.com. Si el dominio está en un registrar externo, Vercel te pide CNAME a cname.vercel-dns.com (o A al apex). Si lo compraste en Vercel, los nameservers ya apuntan y el certificado se renueva solo. Production alias = ese dominio. Los Preview siguen en *.vercel.app.

No pegues el dominio de prod a un Preview. Si el webhook vive en un Route Handler, la URL de Telegram debe ser el dominio de Production; el de Preview usa otro bot.

Railway

Public networking expone el servicio a internet con SSL automático. El hostname servicio.railway.app cambia de semántica si recreas el servicio. En Settings → Networking → Public Networking puedes generar el dominio de Railway o añadir un custom domain. Railway pide CNAME y TXT: los dos. Sin el TXT el hostname no valida. TLS lo termina Railway.

Un PR environment no debe robar ese custom domain. El env de production conserva el hostname; el PR usa el *.railway.app temporal o ninguno.

Workers

Un Custom Domain en Cloudflare ata el hostname al Worker sin ruta extra: todos los paths van al Worker. Distinto de Workers Routes (ejemplo.com/api/*). No puedes crear un Custom Domain sobre un hostname que ya tiene CNAME, ni en una zona que no es tuya. Cloudflare crea el DNS y el certificado. En Wrangler: custom_domain = true en el pattern. Para un webhook quieres el Custom Domain en el Worker de prod (mi-agente), no en mi-agente-dev.

No mezcles el cron de prod y el hostname de dev.

Fly.io

Al crear la app, Fly asigna un *.fly.dev. Para producción: fly certs add agente.tudominio.com (comillas si es wildcard). Fly emite el certificado cuando verifica el dominio por al menos uno de: AAAA hacia la app, CNAME _acme-challenge, o TXT _fly-ownership. Lo recomendado para conexión directa es A + AAAA al anycast. Autostop no invalida el cert; sí puede alargar el primer hit del webhook — ver cold starts, no esta guía. fly certs check te dice si el DNS ya alcanza.

Tabla

DNS y certificado delante de Vercel, Railway, Workers y Fly

PlataformaHostname de regaloCustom domainTLS
Vercel*.vercel.app por deploySettings → Domains + CNAMEAutomático
Railway*.railway.appCustom domain en el env de prodAutomático
Workers*.workers.devCustom Domains (no Routes)Cloudflare
Fly*.fly.devfly certs add + DNSACME

Errores comunes

Fallo típico: webhook apuntando a una URL de preview

SíntomaCausaFix
Telegram 502 intermitenteapuntaste a un Preview que se reciclasetWebhook al dominio de prod
Cert pending 24 hCNAME mal o DNS aún en el registrar viejodig CNAME agente.tudominio.com
Apex sin HTTPSA record mal, o WWW vs apexun hostname, no tres
Worker dev recibe el botCustom Domain en el env equivocadodominio solo en el Worker de prod
Slack firma ok, Telegram nopuerto raro / HTTP443 HTTPS

Relación con el resto

Checklist

  • Un solo hostname de producción documentado
  • CNAME/A verificados con dig
  • HTTPS 200 en /health o /webhook
  • setWebhook (o equivalente) apunta a ese hostname
  • Preview sin ese dominio
  • Certificado cubre el hostname exacto

FAQ

¿Puedo usar el *.vercel.app de Production? Sí, hasta el primer alias que cambia o un proyecto duplicado. El custom domain evita esa lotería.

¿WWW y apex a la vez? Uno solo. Telegram guarda una URL. Redirige el otro; no duplices setWebhook.

¿Cloudflare proxy naranja delante de Vercel? Doble proxy rompe el cert a veces. O Custom Domain en Workers, o CNAME a Vercel, no ambos en el mismo hostname.

El ensayo: cambia un string del prompt, mergea a main, pega un mensaje al bot de prod. Si el bot no responde, el webhook murió con el deploy — casi siempre es hostname, no el modelo.

Siguiente paso: si el dominio ya es estable y prod igual se rompe, mira rollback y logs. Si aún no hay runtime, el curso deja el agente en local antes de pelear con DNS.