Guía de despliegue

Alojar Cal.com en VPS: guía completa con Docker

Desplegar en un VPS Cloud →

Tutorial

Alojar Cal.com en VPS: guía completa con Docker

Autoalojamiento9 min de lectura11 pasos

Calendly es práctico, pero propietario, limitado en su plan gratuito y ávido de sus datos de reuniones. Cal.com es su equivalente open source: reserva de citas, integraciones de calendario y videollamada, y todo alojable en su propio VPS. Esta guía cubre el despliegue inicial, la configuración del reverse proxy, el CLIENT_FETCH_ERROR que bloquea las nuevas instalaciones Docker desde principios de 2026 y los errores más frecuentes.

Contenido· Por qué autoalojar Cal.com en un VPS1/9
  1. 01Por qué autoalojar Cal.com en un VPS
  2. 02Beneficios concretos de Cal.com autoalojado
  3. 03Requisitos técnicos
  4. 04Desplegar Cal.com paso a paso
  5. 05Reverse proxy: nginx y Caddy
  6. 06Invariantes críticos del primer arranque
  7. 07Actualizar Cal.com de forma segura
  8. 08Depuración: CLIENT_FETCH_ERROR y otros errores Docker
  9. 09Para ir más lejos

Por qué autoalojar Cal.com en un VPS

Cal.com es una aplicación Next.js respaldada por PostgreSQL que gestiona la planificación de citas, los tipos de evento, las disponibilidades y la sincronización con los calendarios (Google, CalDAV, Office 365). El autoalojamiento responde a una necesidad concreta: controlar los datos de disponibilidad y de reserva de sus clientes, que normalmente pasan por un servicio externo estadounidense. En un VPS elimina los límites del plan gratuito (un solo tipo de evento, marca impuesta), conecta sus propias claves de API de Google y de videollamada, e integra el widget de reserva directamente en su sitio bajo su dominio. Como Cal.com es una aplicación Node persistente con base de datos y build de producción, exige un VPS: un alojamiento compartido no puede ni ejecutar el proceso ni alojar PostgreSQL.

Beneficios concretos de Cal.com autoalojado

  • Tipos de evento ilimitados: entrevistas de 15 min, demos de 30 min, talleres de grupo, sin muro de pago.
  • Datos de reserva en su servidor: ninguna fuga de los contactos ni de los horarios de sus clientes hacia un SaaS externo.
  • White-label total: el enlace de reserva lleva su dominio, no el de un proveedor.
  • Webhooks y API: active automatizaciones (CRM, facturación) con cada cita reservada.
  • Integraciones con Google Calendar, CalDAV y videollamada (Jitsi, Google Meet) configuradas con sus propias claves.
  • Reservas de equipo y round-robin para repartir las citas entre varios colaboradores.

Requisitos técnicos

Cal.com es más exigente que la media del self-hosting por su base Next.js y por la etapa de build. Prevea 2 vCPU, 4 GB de RAM y 20 GB de disco para una instancia de equipo cómoda; 2 GB de RAM pueden bastar para un uso individual, pero el build inicial queda más ajustado. Necesita Docker y Docker Compose, una base de datos PostgreSQL (incluida en el compose oficial), un dominio rdv.yourdomain.com apuntando al VPS y varias variables de entorno obligatorias: NEXTAUTH_SECRET, CALENDSO_ENCRYPTION_KEY (claves generadas aleatoriamente) y NEXT_PUBLIC_WEBAPP_URL ajustada a su URL HTTPS final. Para la sincronización del calendario y la videollamada, prepare las credenciales OAuth de Google.

Desplegar Cal.com paso a paso

  1. Clonar el repositorio de despliegue Docker

    En el VPS: git clone https://github.com/calcom/docker.git cal-docker && cd cal-docker. Este repositorio proporciona un docker-compose.yml y un archivo .env.example que hay que adaptar.

  2. Generar los secretos y configurar el entorno

    Copie .env.example como .env y genere después las claves: openssl rand -base64 32 para NEXTAUTH_SECRET y para CALENDSO_ENCRYPTION_KEY. Indique NEXT_PUBLIC_WEBAPP_URL=https://rdv.yourdomain.com y las credenciales de PostgreSQL. Guarde estos tres valores en un gestor de secretos de inmediato — no podrá cambiarlos tras el primer arranque sin perder todas sus integraciones.

  3. Añadir NEXTAUTH_URL_INTERNAL para evitar el CLIENT_FETCH_ERROR

    Añada NEXTAUTH_URL_INTERNAL=http://calcom:3000 a su .env. Sin esta variable, el contenedor Next.js intenta resolver su propio dominio público (rdv.yourdomain.com) desde dentro de la red Docker, donde el DNS externo no responde — cada petición de autenticación del lado del servidor falla con CLIENT_FETCH_ERROR. NEXTAUTH_URL_INTERNAL cortocircuita esa resolución apuntando directamente al nombre del servicio Docker (calcom es el nombre del servicio en docker-compose.yml). Esta variable es independiente de NEXTAUTH_URL: ambas deben estar presentes.

  4. Compilar y arrancar la stack

    Arranque con docker compose up -d. El primer arranque construye la imagen Next.js y aplica las migraciones Prisma sobre PostgreSQL: es la etapa más larga, sígala con docker compose logs -f.

  5. Conectarse por primera vez

    Abra la URL: Cal.com le redirige a su asistente de primera configuración (/auth/setup), donde crea SU cuenta de administrador. Hágalo nada más terminar la instalación: ese asistente no está protegido por nada mientras no exista la primera cuenta.

  6. Crear la cuenta y configurar las disponibilidades

    Defina sus franjas horarias y un primer tipo de evento. Pruebe una reserva de principio a fin para validar toda la cadena antes de conectar las integraciones.

  7. Conectar calendario y videollamada

    En las integraciones, añada sus credenciales OAuth de Google para la sincronización bidireccional del calendario y active Jitsi o Google Meet para generar automáticamente un enlace de videollamada en cada reserva.

Reverse proxy: nginx y Caddy

Cal.com escucha en el puerto 3000 dentro del contenedor. Un reverse proxy HTTPS es necesario por dos motivos: exponer el puerto 443 y reenviar la cabecera Host correcta — de lo contrario NEXT_PUBLIC_WEBAPP_URL ya no coincide con el origen real y las redirecciones de autenticación fallan.

Con Caddy (recomendado, certificado automático):

rdv.yourdomain.com {
    reverse_proxy calcom:3000
}

Caddy obtiene y renueva el certificado Let's Encrypt sin configuración adicional.

Con nginx, añada este bloque a su configuración:

server {
    listen 443 ssl;
    server_name rdv.yourdomain.com;
    ssl_certificate     /etc/letsencrypt/live/rdv.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/rdv.yourdomain.com/privkey.pem;
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

En ambos casos, la URL debe coincidir exactamente con NEXT_PUBLIC_WEBAPP_URL: sin barra oblicua final, en HTTPS, con el subdominio correcto. Una diferencia de un solo carácter produce redirecciones infinitas o pantalla en blanco.

Invariantes críticos del primer arranque

Tres variables de entorno quedan permanentemente bloqueadas en el primer arranque de Cal.com. Modificarlas después corrompe silenciosamente todas las integraciones almacenadas: la aplicación reinicia con normalidad, no muestra ningún error, pero Google Calendar, Zoom y todas las conexiones OAuth dejan de funcionar — sus tokens fueron cifrados con la clave original, ahora incompatible. Este comportamiento está documentado en calcom/docker issue #333 y calcom/cal.diy issue #13290: usuarios han perdido todas sus integraciones tras una actualización que regeneró el archivo .env.

CALENDSO_ENCRYPTION_KEY — cifra los tokens OAuth almacenados en la base de datos. Cualquier cambio invalida silenciosamente todas las integraciones existentes.

NEXTAUTH_URL — ancla las cookies de sesión. Un cambio rompe la autenticación para todos los usuarios activos.

NEXT_PUBLIC_WEBAPP_URL — integrada en el build de Next.js en el momento de la compilación. Cambiar este valor exige un rebuild completo y volver a conectar todas las integraciones.

Buena práctica: copie estos tres valores en un gestor de secretos (Bitwarden, HashiCorp Vault, Ansible Vault) en cuanto los genere. Si gestiona su VPS como infraestructura-como-código, guárdelos en un vault cifrado — nunca deje que el archivo .env sea su único almacén.

Actualizar Cal.com de forma segura

  1. Hacer copia de seguridad de la base PostgreSQL

    Antes de cualquier actualización: docker exec cal-docker-db-1 pg_dump -U calcom calcom | gzip > /opt/backup/calcom-$(date +%Y%m%d).sql.gz. Las migraciones Prisma no son reversibles — esta copia de seguridad es su única red de seguridad.

  2. Verificar que CALENDSO_ENCRYPTION_KEY no ha cambiado

    Compare el valor de su .env con el almacenado en su gestor de secretos. Si difieren, no continúe: restaure el valor original antes de seguir. Una clave diferente destruirá silenciosamente todas sus integraciones OAuth al reiniciar.

  3. Descargar la nueva imagen y reiniciar

    Actualice con docker compose pull && docker compose up -d. Siga el arranque con docker compose logs -f calcom — espere el mensaje que indica que el servidor está listo antes de hacer pruebas.

  4. Verificar las integraciones tras la actualización

    Abra Configuración → Integraciones y confirme que cada conexión existente (Google Calendar, Zoom, etc.) sigue activa. Un estado «no conectado» indica que la clave cambió entre reinicios — restaure la copia de seguridad y el .env original.

Depuración: CLIENT_FETCH_ERROR y otros errores Docker

CLIENT_FETCH_ERROR al cargar la página — Desde principios de 2026, todas las nuevas instalaciones Docker encuentran este error en la primera carga. Causa: el contenedor Next.js intenta resolver NEXTAUTH_URL (su dominio público) desde dentro de la red Docker, donde el DNS externo no es accesible. Solución: añada NEXTAUTH_URL_INTERNAL=http://calcom:3000 a su .env y reinicie con docker compose up -d. Esta variable fuerza a NextAuth a llamar a su propia API internamente, sin pasar por el dominio público. Documentado en calcom/cal.diy (febrero 2026, issue #27668) (febrero de 2026, 8 comentarios que confirman el error en todas las distribuciones Docker recientes).

Integraciones perdidas tras una actualización — La causa es casi siempre una CALENDSO_ENCRYPTION_KEY diferente entre dos arranques. Compruebe que su .env no haya sido sobreescrito por un .env.example durante el pull. Compare el valor actual con el guardado en su gestor de secretos. Si difieren: restaure la base PostgreSQL, vuelva a poner la clave original en .env y reinicie con docker compose up -d.

Build «JavaScript heap out of memory» — El compilador Next.js se queda sin RAM. Solución: fallocate -l 2G /swapfile && mkswap /swapfile && swapon /swapfile, y vuelva a ejecutar docker compose build. En un VPS de 2 GB, el swap suele ser imprescindible para el primer build y las actualizaciones mayores. Retire el archivo swap una vez terminado el build.

Bucle de redirección o «Unable to find valid origin»NEXT_PUBLIC_WEBAPP_URL no coincide con la URL real. Compruebe que esta variable sea exactamente https://rdv.yourdomain.com (sin barra oblicua final, dominio correcto, protocolo HTTPS), que el reverse proxy reenvíe correctamente la cabecera Host, y reinicie con docker compose up -d --build para forzar un rebuild con la URL correcta.

Migraciones Prisma bloqueadas al arrancar — Si el contenedor reinicia en bucle con errores de migración, es posible que la base de datos todavía no esté lista. Espere unos segundos y ejecute docker compose restart calcom. Si el problema persiste, revise los logs de PostgreSQL con docker compose logs db.

Automatice la copia de seguridad de su base PostgreSQL con un cron diario. Ejemplo de comando a programar: docker exec cal-docker-db-1 pg_dump -U calcom calcom | gzip > /opt/backup/calcom-$(date +%Y%m%d-%H%M).sql.gz. Conserve al menos 7 días de copias rotativas y envíelas a un almacenamiento de objetos externo (compatible con S3, Backblaze B2): en caso de pérdida del VPS, la base de datos PostgreSQL es la única parte no reproducible de su instancia de Cal.com.

Para ir más lejos

Una vez que Cal.com funciona, varios pasos para reforzar la instalación: activar alertas sobre los certificados SSL para anticipar sus vencimientos, configurar monitorización HTTP (Uptime Kuma, Better Uptime) sobre https://rdv.yourdomain.com/api/health, y restringir el puerto 3000 del contenedor a 127.0.0.1 para que no sea accesible directamente. Para instalaciones de equipo, el reverse proxy puede servir varias instancias de Cal.com detrás de subdominios distintos desde un único VPS — consulte el despliegue con Coolify para una gestión multi-servicio simplificada. La documentación oficial de Cal.com también cubre la configuración SMTP para los correos de confirmación y la integración con Stripe para reservas de pago.

Aloje su sistema de citas

El VPS Cloud de ServOrbit aporta la RAM y el Docker necesarios para compilar Cal.com, con una plantilla PostgreSQL y reverse proxy lista para configurar. Ofrezca a sus clientes un enlace de reserva bajo su propio dominio.

¿Necesita ayuda?

Consulte nuestro centro de ayuda y nuestra FAQ, o contacte con nuestro equipo: llamada, WhatsApp o correo electrónico. Soporte en francés, inglés y árabe.

Escribir por WhatsAppse abre en una pestaña nueva