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.

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:
- DNS resuelve al proxy correcto (CNAME o A según docs).
- HTTPS 200 en
https://agente.tudominio.com/health(o/webhook). - El certificado cubre exactamente ese hostname (no solo el apex).
- 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

| Plataforma | Hostname de regalo | Custom domain | TLS |
|---|---|---|---|
| Vercel | *.vercel.app por deploy | Settings → Domains + CNAME | Automático |
| Railway | *.railway.app | Custom domain en el env de prod | Automático |
| Workers | *.workers.dev | Custom Domains (no Routes) | Cloudflare |
| Fly | *.fly.dev | fly certs add + DNS | ACME |
Errores comunes

| Síntoma | Causa | Fix |
|---|---|---|
| Telegram 502 intermitente | apuntaste a un Preview que se recicla | setWebhook al dominio de prod |
| Cert pending 24 h | CNAME mal o DNS aún en el registrar viejo | dig CNAME agente.tudominio.com |
| Apex sin HTTPS | A record mal, o WWW vs apex | un hostname, no tres |
Worker dev recibe el bot | Custom Domain en el env equivocado | dominio solo en el Worker de prod |
| Slack firma ok, Telegram no | puerto raro / HTTP | 443 HTTPS |
Relación con el resto
Checklist
- Un solo hostname de producción documentado
- CNAME/A verificados con
dig - HTTPS 200 en
/healtho/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.
Lecturas relacionadas
Sigue explorando Deploy y otras piezas para builders.



