Tu cliente escribe app.theircustomer.com en su navegador y espera. Detrás de esa carga de tres segundos, tu infraestructura está orquestando una búsqueda DNS, validando un certificado comodín, enrutando a través de tu proxy inverso, y sirviendo su panel personalizado — todo sin que sepan tu IP de servidor real. He implementado este patrón de dominio personalizado cuatro veces en diferentes stacks, y cada implementación sacó a la luz trampas que nunca aparecieron en la especificación del producto: límites de velocidad de Let's Encrypt que bloquean la incorporación de tu décimo cliente, comportamiento de aplanamiento de CNAME que se rompe en proveedores DNS específicos, retrasos de propagación que hacen que los tickets de soporte se acumulen durante la semana de lanzamiento. Arquitecturarás esto una vez pensando que es un proyecto de dos sprints — antes de descubrir los casos extremos que convierten la automatización de SSL en un fin de semana de depuración de API de Cloudflare y validación de cadena de certificados.

Este artículo es el manual que desearía haber tenido. Vamos a cubrir subdominios comodín para aplicaciones multi-tenant, aprovisionamiento automático de SSL con Let's Encrypt y alternativas, dominios de vanidad personalizados donde los clientes traen los suyos propios, y las preocupaciones operativas que te morderán a las 2 AM si no planificas para ellas.

Tabla de Contenidos

Dominios Personalizados para SaaS: Subdominios Comodín y SSL Automatizado

Por qué los Dominios Personalizados Importan para SaaS

Los dominios personalizados no son solo una característica de vanidad. Son una señal de confianza. Cuando el cliente de tu cliente visita portal.acmecorp.com en lugar de acmecorp.tu-saas.io, refuerza la marca del cliente. Elimina fricción. Y para muchos acuerdos empresariales, es un requisito difícil — el equipo de adquisiciones no aprobará software que obligue a los empleados a un dominio de terceros.

También hay un ángulo SEO. Si estás construyendo un SaaS que implica páginas públicamente accesibles (piensa en tiendas Shopify, constructores de páginas de destino, bases de conocimiento o portales de cliente), los clientes necesitan sus propios dominios para construir autoridad de dominio. No puedes hacer eso en un subdominio de la plataforma de otra persona. Bueno, puedes, pero es subóptimo.

Los tres patrones más comunes que veo:

  1. Subdominios de plataformacustomer.tu-app.com (más fácil)
  2. Subdominios personalizadosapp.customer.com (complejidad media)
  3. Dominios personalizados apexcustomer.com (más difícil, porque los registros CNAME no funcionan en el apex)

La mayoría de productos SaaS maduros terminan soportando los tres.

Descripción General de la Arquitectura: Tres Enfoques

Antes de entrar en los detalles de implementación, veamos los tres enfoques arquitectónicos principales y cuándo tiene sentido cada uno.

Enfoque Complejidad Mejor Para Método SSL Requisito DNS
Subdominio comodín Baja Subdominios controlados por la plataforma Certificado comodín único Registro comodín DNS A/AAAA
Proxy inverso con SNI Media Dominios personalizados a escala moderada Certificado por dominio vía ACME CNAME o registro A del cliente
CDN/Edge con dominios personalizados Baja-Media Alta escala, distribución global Administrado por proveedor CDN CNAME o registro A del cliente
Balanceador de carga dedicado por tenant Alta Requisitos de aislamiento empresarial Certificado por tenant Delegación DNS de cliente

Para la mayoría de aplicaciones SaaS, comenzarás con subdominios comodín y eventualmente agregarás soporte de dominio personalizado basado en proxy inverso. Vamos a profundizar en cada uno.

Subdominios Comodín para Multi-Tenencia

Este es tu punto de partida. Cada tenant obtiene {slug}.tuapp.com. Aquí está cómo configurarlo correctamente.

Configuración DNS

Necesitas un registro DNS comodín:

*.tuapp.com.  300  IN  A      203.0.113.10
*.tuapp.com.  300  IN  AAAA   2001:db8::1

Esto significa que cualquier subdominio de tuapp.com se resuelve a tu servidor. Tu aplicación entonces lee el encabezado Host para determinar qué tenant servir.

Enrutamiento a Nivel de Aplicación

En una aplicación Next.js (que construimos mucho en Social Animal), manejarías esto en middleware:

// middleware.ts
import { NextRequest, NextResponse } from 'next/server';

export function middleware(request: NextRequest) {
  const hostname = request.headers.get('host') || '';
  const subdomain = hostname.split('.')[0];
  
  // Saltar para dominio principal y subdominios conocidos
  if (['www', 'app', 'api'].includes(subdomain)) {
    return NextResponse.next();
  }
  
  // Reescribir a ruta específica de tenant
  const url = request.nextUrl.clone();
  url.pathname = `/tenant/${subdomain}${url.pathname}`;
  return NextResponse.rewrite(url);
}

export const config = {
  matcher: ['/((?!_next|api|static).*)'],
};

Para sitios basados en Astro (otro framework que usamos mucho), manejarías esto en tu middleware de servidor o en el edge.

Certificado SSL Comodín

Un certificado comodín único cubre todos los subdominios:

certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  -d 'tuapp.com' \
  -d '*.tuapp.com'

Nota: los certificados comodín de Let's Encrypt requieren validación de desafío DNS-01. No puedes usar HTTP-01 para comodines. Esto significa que necesitas acceso API a tu proveedor DNS. Certbot tiene complementos para Cloudflare, Route53, Google Cloud DNS, y la mayoría de proveedores principales.

Los certificados comodín de Let's Encrypt son válidos por 90 días, así que automatiza esa renovación. En serio. Establece una alerta de monitoreo si la renovación falla — no seas la persona que derriba 500 sitios de clientes porque un certificado expiró.

Dominios Personalizados para SaaS: Subdominios Comodín y SSL Automatizado - arquitectura

SSL Automatizado con Let's Encrypt

Cuando los clientes traen sus propios dominios, necesitas certificados por dominio. Aquí es donde las cosas se ponen interesantes.

El Protocolo ACME

Let's Encrypt usa el protocolo ACME (Automatic Certificate Management Environment). Los dos desafíos en los que te enfocarás:

  • HTTP-01: Demuestras la propiedad del dominio sirviendo un archivo específico en http://tudominio.com/.well-known/acme-challenge/{token}. Más fácil de automatizar, funciona para dominios individuales.
  • DNS-01: Demuestras la propiedad creando un registro TXT específico. Requerido para comodines, más difícil de automatizar para dominios de clientes (no controlas su DNS).

Para dominios personalizados, casi siempre usarás HTTP-01. El flujo se ve así:

  1. El cliente agrega un CNAME apuntando su dominio a tu plataforma
  2. Tu sistema detecta que el DNS se está resolviendo correctamente
  3. Inicias una solicitud de certificado ACME
  4. Let's Encrypt envía un desafío HTTP-01
  5. Tu servidor responde con el token de desafío correcto
  6. El certificado se emite y se almacena
  7. Tu proxy inverso comienza a servir HTTPS para ese dominio

Caddy: La Opción Perezosa (Inteligente)

Honestamente, si no estás ya comprometido con nginx, solo usa Caddy. Maneja HTTPS automático listo para usar, incluyendo TLS bajo demanda para dominios desconocidos:

{
  on_demand_tls {
    ask http://localhost:5555/check-domain
    interval 2m
    burst 5
  }
}

https:// {
  tls {
    on_demand
  }
  reverse_proxy localhost:3000
}

El punto final ask es crítico — es donde Caddy verifica con tu aplicación si un dominio es realmente un dominio de cliente válido antes de solicitar un certificado. Sin esto, cualquiera podría apuntar su dominio a tu IP y activar solicitudes de certificados, potencialmente quemando los límites de velocidad de Let's Encrypt.

// Punto final /check-domain
app.get('/check-domain', async (req, res) => {
  const domain = req.query.domain;
  const isValid = await db.customDomains.findOne({ 
    domain, 
    verified: true,
    active: true 
  });
  
  if (isValid) {
    res.status(200).send('OK');
  } else {
    res.status(404).send('Not found');
  }
});

Enfoque Nginx + Certbot

Si ya estás ejecutando nginx, puedes usar certbot con el complemento webroot:

certbot certonly --webroot -w /var/www/certbot \
  -d customer-domain.com \
  --non-interactive --agree-tos \
  --email ssl@tuapp.com

Necesitarás actualizar dinámicamente las configuraciones de nginx y recargar:

server {
    listen 443 ssl;
    server_name customer-domain.com;
    
    ssl_certificate /etc/letsencrypt/live/customer-domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/customer-domain.com/privkey.pem;
    
    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Esto funciona pero es doloroso de administrar a escala. Cada nuevo dominio significa generar una configuración, solicitar un certificado y recargar nginx. Querrás construir automatización alrededor de esto, e honestamente el TLS bajo demanda de Caddy es solo más fácil.

Límites de Velocidad de Let's Encrypt (2025)

Estos importan y necesitas planificar alrededor de ellos:

Límite Valor Notas
Certificados por Dominio Registrado 50/semana Por tu dominio raíz
Certificado Duplicado 5/semana Mismo conjunto exacto de nombres de host
Validaciones Fallidas 5/hora por cuenta por nombre de host Puede bloquearte rápido
Nuevos Pedidos 300/3 horas Cuenta general
Autorizaciones Pendientes 300/cuenta Limpia las antiguas

En 50 certs por semana, si estás incorporando más de ~7 dominios personalizados por día, necesitas pensar en esto. Opciones:

  • Usa una CA ACME diferente (ZeroSSL, BuyPass) como respaldo
  • Solicita un aumento de límite de velocidad de Let's Encrypt (lo otorgan para casos legítimos de uso de SaaS)
  • Pre-valida DNS antes de intentar la emisión de certificados
  • Implementa lógica de reintento con retroceso exponencial

Dominios de Vanidad Personalizados: El Flujo Completo

Aquí está el viaje completo del usuario que recomiendo, habiendo construido este flujo múltiples veces.

Paso 1: El Cliente Ingresa Dominio en Tu Panel

Proporciona instrucciones claras. Muéstrale exactamente qué registro DNS crear:

Tipo: CNAME
Host: portal (o cualquier subdominio que quieran)
Valor: custom.tuapp.com
TTL: 300

Para dominios apex (bare customer.com), necesitan un registro A apuntando a tu IP, o necesitan un proveedor DNS que apoye aplanamiento de CNAME (Cloudflare, registros ALIAS de Route53, etc.).

Paso 2: Verificación DNS

No verifiques solo una vez. La propagación DNS puede tomar minutos a horas. Implementa un mecanismo de sondeo:

async function verifyDomain(domain: string, expectedTarget: string): Promise<boolean> {
  try {
    const records = await dns.promises.resolveCname(domain);
    return records.some(r => r === expectedTarget);
  } catch (err) {
    // Para registros A (dominios apex)
    try {
      const aRecords = await dns.promises.resolve4(domain);
      return aRecords.some(r => EXPECTED_IPS.includes(r));
    } catch {
      return false;
    }
  }
}

// Sondea cada 30 segundos por hasta 24 horas
async function waitForDNS(domain: string) {
  const maxAttempts = 2880; // 24 horas en intervalos de 30s
  for (let i = 0; i < maxAttempts; i++) {
    if (await verifyDomain(domain, 'custom.tuapp.com')) {
      return true;
    }
    await sleep(30000);
  }
  return false;
}

Paso 3: Aprovisionamiento de Certificados

Una vez que se verifica DNS, solicita el certificado. Con Caddy, esto sucede automáticamente en la primera solicitud. Con nginx/certbot, actívalo programáticamente.

Paso 4: Monitoreo Continuo

Los dominios pueden romperse. Los clientes cambian registros DNS accidentalmente. Los certificados expiran si la renovación falla. Necesitas monitorear:

  • La resolución DNS aún apunta a ti (verifica diariamente)
  • Fechas de vencimiento de certificados (alerta a los 14 días, crítica a los 7)
  • Éxito del apretón SSL (monitoreo sintético)
  • Códigos de respuesta HTTP en dominios de cliente

Patrones de Infraestructura por Plataforma

El enfoque varía significativamente dependiendo de dónde estés alojando.

Vercel

Vercel tiene soporte de dominio personalizado incorporado. Para una aplicación Next.js multi-tenant, usarías su API de Dominios:

curl -X POST "https://api.vercel.com/v10/projects/{projectId}/domains" \
  -H "Authorization: Bearer $VERCEL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "portal.customer.com"}'

Vercel maneja SSL automáticamente. La limitación principal: estás sujeto a su precios. En el plan Pro ($20/miembro del equipo/mes), obtén 50 dominios por proyecto. Enterprise te da más. Si tienes miles de clientes con dominios personalizados, el costo se suma.

Cloudflare para SaaS (SSL para SaaS)

Esta es probablemente la mejor opción para escala en 2025. El producto SSL for SaaS de Cloudflare (anteriormente llamado Custom Hostnames) maneja todo:

  • Emisión automática de certificados y renovación
  • CDN global y protección DDoS
  • Verificación de dominio integrada
  • API para administración programática
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/custom_hostnames" \
  -H "Authorization: Bearer $CF_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "hostname": "portal.customer.com",
    "ssl": {
      "method": "http",
      "type": "dv"
    }
  }'

Precios: $0.10/nombre de host personalizado/mes después de los primeros 100 (que son gratis en el plan Enterprise). Para un SaaS con 1,000 dominios personalizados, eso es aproximadamente $90/mes. Muy razonable.

AWS (ALB + ACM + Route53)

Si estás en AWS, puedes usar:

  • ALB para enrutamiento con selección de certificados basada en SNI
  • ACM (AWS Certificate Manager) para certificados gratuitos
  • Route53 para verificación DNS

La trampa: Los certificados ACM solo se pueden usar con servicios de AWS (ALB, CloudFront, API Gateway). Y ALB tiene un límite de 25 certificados por balanceador de carga por defecto (puede aumentarse a 100). Para escala seria, pondrías CloudFront al frente con su límite de 100 certificados por distribución.

Esto se vuelve costoso y complejo. Honestamente recomendaría Cloudflare for SaaS sobre este enfoque a menos que tengas requisitos específicos de AWS.

Fly.io

Fly.io tiene un buen comando fly certs add e API para agregar dominios personalizados:

fly certs add portal.customer.com

Maneja Let's Encrypt automáticamente. Funciona bien para pequeña a mediana escala.

Configuración DNS y Verificación

La parte DNS hace tropezar a más equipos que cualquier otra parte de esta característica. Aquí está lo que necesitas saber.

El Problema de CNAME-en-Apex

Los clientes inevitablemente querrán usar su dominio desnudo (customer.com, sin subdominio). La especificación DNS no permite registros CNAME en el apex de una zona porque los registros CNAME deben ser exclusivos — no pueden coexistir con otros tipos de registros, y el apex siempre tiene registros SOA y NS.

Soluciones:

  1. Aplanamiento CNAME (Cloudflare) — resuelve el CNAME a nivel DNS, devuelve un registro A
  2. Registros ALIAS (Route53, DNSimple) — tipo de registro propietario que funciona como un CNAME en el apex
  3. Registros ANAME (algunos proveedores) — similar a ALIAS
  4. Registro A — solo proporciona a los clientes tu dirección IP

La opción 4 (registros A) es la más universal pero la menos flexible. Si alguna vez cambias la IP de tu servidor, cada cliente que use un registro A necesita actualizar su DNS. Con un CNAME, solo actualizas a qué se resuelve tu destino CNAME.

Mi recomendación: soporta ambos. Dile a los clientes que usen un CNAME para subdominios y un registro A (o ALIAS/ANAME si su proveedor lo soporta) para dominios apex.

Verificación de Propiedad

Más allá de confirmar que el dominio se resuelve a tu infraestructura, podrías querer verificar que la persona configurando el dominio en tu SaaS realmente lo controla. Un enfoque común es requerir un registro TXT:

_verification.customer.com  TXT  "tuapp-verify=abc123unique"

Esto previene que alguien apunte un dominio que no controla a tu plataforma y afirme que pertenece a su cuenta.

Endurecimiento de Producción y Monitoreo

Esta sección es la diferencia entre una demostración y un sistema de producción.

Almacenamiento de Certificados

No almacenes certificados en disco si estás ejecutando múltiples instancias. Usa una tienda distribuida:

  • Caddy: soporta backends de almacenamiento para Redis, Consul, S3, PostgreSQL
  • Personalizado: almacena certs en una base de datos encriptada o administrador de secretos (AWS Secrets Manager, HashiCorp Vault)

Alternativa Elegante

¿Qué sucede cuando el dominio de un cliente está mal configurado? No muestres un error SSL. En su lugar:

  1. Detecta el apretón SSL fallido
  2. Redirige a una página de estado explicando el problema
  3. Envía una notificación al cliente
  4. Reintenta automáticamente el aprovisionamiento de certificados

Verificaciones de Salud

Construye un trabajo en segundo plano que verifica regularmente cada dominio personalizado:

async function healthCheckDomains() {
  const domains = await db.customDomains.find({ active: true });
  
  for (const domain of domains) {
    const checks = {
      dnsResolves: await checkDNS(domain.hostname),
      sslValid: await checkSSL(domain.hostname),
      httpOk: await checkHTTP(domain.hostname),
    };
    
    if (!checks.dnsResolves) {
      await alertCustomer(domain, 'DNS no longer points to our platform');
      await markDomain(domain, 'dns_error');
    } else if (!checks.sslValid) {
      await triggerCertRenewal(domain);
    }
    
    await db.domainHealthChecks.insert({
      domainId: domain.id,
      ...checks,
      checkedAt: new Date(),
    });
  }
}

Ejecútalo cada hora. En 10,000 dominios, los verificadores se completan en unos pocos minutos si paralelizas adecuadamente.

Análisis de Costos a Escala

Vamos a hablar números reales para precios 2025.

Solución 100 Dominios 1,000 Dominios 10,000 Dominios Notas
Caddy + Let's Encrypt (auto-administrado) ~$50/mes servidor ~$200/mes servidores ~$1,000/mes servidores Tu carga de ops
Cloudflare para SaaS Gratis (Enterprise) ~$90/mes ~$990/mes Mejor valor a escala
Vercel (Pro) Incluido $0 extra Necesita Enterprise Limitado a 50/proyecto en Pro
AWS CloudFront + ACM ~$100/mes ~$300/mes ~$2,000/mes Incluye costos de transferencia CDN
Fastly ~$150/mes ~$500/mes Precios personalizados Bueno si ya usas Fastly

Para la mayoría de productos SaaS, Cloudflare para SaaS golpea el punto dulce. Obtienes CDN global, protección DDoS, y certificados automatizados por aproximadamente una moneda por dominio por mes. Difícil de superar eso.

Si estás construyendo en una arquitectura CMS sin cabeza — algo que hacemos mucho — Cloudflare para SaaS se empareja particularmente bien ya que ya estás tratando con frontends desacoplados que se benefician del caché en edge.

Preguntas Frecuentes

¿Cuánto tiempo tarda un dominio personalizado en activarse después de la configuración DNS? La propagación DNS típicamente toma 5-30 minutos, aunque en casos raros puede tomar hasta 48 horas. El aprovisionamiento de certificados con Let's Encrypt agrega otros 30-60 segundos una vez que DNS se está resolviendo correctamente. En la práctica, la mayoría de dominios personalizados están completamente activos dentro de 15 minutos. Recomiendo sondear DNS cada 30 segundos y activar el aprovisionamiento de certificados inmediatamente cuando la resolución tiene éxito.

¿Puedo usar Let's Encrypt para miles de dominios personalizados en mi SaaS? Sí, pero necesitas planificar alrededor de los límites de velocidad. La restricción principal es 50 certificados por dominio registrado por semana (para tus propios subdominios de plataforma) y 300 nuevos pedidos por 3 horas. Para dominios personalizados de clientes, cada dominio es un dominio registrado separado, así que el límite por dominio no se aplica de la misma manera. También puedes solicitar a Let's Encrypt un aumento de límite de velocidad si puedes demostrar necesidad legítima. ZeroSSL es un proveedor ACME de respaldo sólido.

¿Cuál es la diferencia entre subdominios comodín y dominios personalizados? Los subdominios comodín (*.tuapp.com) son controlados completamente por ti — un registro DNS, un certificado SSL, enrutamiento simple. Los dominios personalizados (portal.customer.com) son dominios controlados por tus clientes, requiriendo que configuren DNS y tú aprovisiones certificados individuales. La mayoría de productos SaaS comienzan con subdominios comodín y agregan soporte de dominio personalizado más adelante como característica premium.

¿Cómo manejo dominios apex (desnudos) personalizados? Los dominios apex (customer.com sin www) no pueden usar registros CNAME según la especificación DNS. Tus opciones son: haz que los clientes creen registros A apuntando a tu IP, usa proveedores DNS que soporten registros ALIAS/ANAME, o recomienda proveedores con aplanamiento de CNAME como Cloudflare. Siempre soporta configuraciones tanto de apex como de subdominio — los clientes querrán ambas.

¿Debo usar Caddy o nginx para SSL automatizado? Si estás comenzando de nuevo, usa Caddy. Su característica de TLS bajo demanda fue literalmente construida para el caso de uso de dominios personalizados multi-tenant. Nginx está bien si ya lo tienes en tu stack, pero necesitarás construir más automatización alrededor de certbot para administración del ciclo de vida del certificado. Caddy maneja issuance, renovación, almacenamiento, y OCSP stapling automáticamente.

¿Cómo prevengo abuso de mi característica de dominio personalizado? Tres capas: Primero, verifica la propiedad del dominio con un registro TXT antes de aceptar un dominio personalizado. Segundo, implementa un punto final "ask" (como el de Caddy on_demand_tls ask) que valida dominios antes de solicitar certificados. Tercero, limita la velocidad de adiciones de dominio por cuenta. Sin esto, alguien podría apuntar miles de dominios a tu IP y quemar tus límites de velocidad de certificados o usar tu infraestructura para domain fronting.

¿Qué sucede si un cliente elimina su registro DNS? Tu plataforma debe detectar esto dentro de horas a través de verificaciones de salud regulares. Cuando DNS deja de resolvarse a tu infraestructura, marca el dominio como insalubre, notifica al cliente, y detén intentos de renovación de certificados. No elimines la configuración del dominio inmediatamente — los clientes a veces rompen DNS temporalmente durante migraciones. Recomiendo un período de gracia de 30 días antes de desactivar completamente un dominio personalizado.

¿Vale la pena Cloudflare para SaaS en comparación con auto-administrar certificados? Para la mayoría de productos SaaS, sí. En $0.10/nombre de host/mes, el costo es trivial en comparación con el tiempo de ingeniería que gastarías construyendo y manteniendo automatización de certificados, manejando casos extremos, monitoreando renovaciones, y tratando con límites de velocidad. También obtienes un CDN global y protección DDoS incluidos. La razón principal para auto-administrar es si necesitas control total sobre tu infraestructura o tienes requisitos de cumplimiento específicos que previenen usar un proxy de terceros. Si quieres discutir el enfoque correcto para tu producto específico, contáctanos — hemos implementado ambos patrones.

Los dominios personalizados son una de esas características de SaaS donde el diablo realmente está en los detalles. El camino feliz es directo, pero la preparación para producción significa manejar retrasos de propagación DNS, fallas de certificados, configuración errónea de clientes, y monitoreo a escala. Comienza con subdominios comodín, agrega soporte de dominio personalizado cuando los clientes lo pidan (y lo harán), y no intentes construir todo desde cero cuando herramientas como Caddy y Cloudflare para SaaS existen. Tu yo futuro de guardia nocturna te lo agradecerá.