Alternativas autoalojadas a Calendly comparadas
Compara Cal.com, Easy!Appointments, Rallly y DayOtter en un VPS: sincronizacion bidireccional de calendarios y envio de correo saliente.
La respuesta breve
Una alternativa autoalojada a Calendly tiene que hacer algo que las herramientas internas de su VPS nunca hacen: responder al público. La página de reservas es el producto. Necesita un nombre de dominio real y TLS (seguridad de la capa de transporte) desde el primer día. También tiene que entregar correo a personas que nunca han oído hablar de su servidor.
Cuatro proyectos cubren las opciones realistas. Cal.com es la alternativa más parecida a Calendly y la opción predeterminada para un consultor independiente. Easy!Appointments es la opción ligera, basada en PHP y MySQL, y funciona bien en un VPS de 1 GB. Rallly es una herramienta para realizar encuestas de grupo y no tiene ninguna página de reservas. DayOtter es el proyecto más reciente: una plataforma de programación con licencia AGPLv3 y un asistente que solicita confirmación antes de actuar.
Dos preguntas determinan cuál puede ejecutar realmente. ¿Se sincroniza en ambos sentidos con el calendario que ya utiliza? ¿Puede enviar correo? La segunda pregunta es donde suelen fallar silenciosamente la mayoría de las configuraciones de reservas autoalojadas, por eso se aborda primero.
El correo saliente es la parte que falla
Una confirmación de reserva llega al buzón de un desconocido. Es correo transaccional que llega a Gmail o Microsoft 365, y esos receptores evalúan la IP de envío y los registros DNS.
Enviar directamente desde el VPS casi nunca funciona. La mayoría de los proveedores bloquean el puerto TCP saliente 25 en las cuentas nuevas, por lo que la conexión se queda esperando y después agota el tiempo de espera. Aunque el puerto 25 esté abierto, una dirección nueva del VPS no tiene historial de envío, y los grandes receptores consideran sospechosas las direcciones desconocidas de rangos de hosting. La reserva se escribe en la base de datos, la página indica que está confirmada y nadie recibe un correo. Desde el servidor no parece haber ningún problema, por lo que normalmente esto se descubre semanas después, cuando un cliente que nunca se presentó lo comunica.
Use un relay. Cualquier proveedor de correo transaccional sirve, y la aplicación sólo necesita un nombre de host, un puerto, un usuario y una contraseña. Compruebe que el puerto sea accesible antes de modificar la configuración de la aplicación:
nc -vz -w 5 "$SMTP_HOST" 587Una línea succeeded indica que la ruta está abierta. Una espera prolongada o Connection refused indica que el puerto está bloqueado en la capa de red, y modificar .env no solucionará el problema. Los relays escuchan en 587 o 465 precisamente porque el puerto 25 está bloqueado con mucha frecuencia.
Cada proyecto configura el relay de una forma distinta. Cal.com lee EMAIL_FROM, EMAIL_SERVER_HOST, EMAIL_SERVER_PORT, EMAIL_SERVER_USER y EMAIL_SERVER_PASSWORD, y también acepta un RESEND_API_KEY. Preste atención a este último: el .env.example incluido apunta EMAIL_SERVER_HOST a localhost en el puerto 1025, que corresponde a un buzón de desarrollo local. Si deja el valor predeterminado, la aplicación envía los mensajes a ninguna parte sin mostrar ningún error. Rallly utiliza SMTP_HOST, SMTP_PORT, SMTP_USER y SMTP_PWD. DayOtter utiliza la configuración SMTP o una clave de Resend. Easy!Appointments envía sus notificaciones desde la aplicación, por lo que debe configurarla para usar el mismo relay desde su página de ajustes antes de aceptar una reserva real.
Después, publique los registros DNS que le proporcione el relay. Un registro SPF (sender policy framework) indica qué servidores pueden enviar correo para su dominio, y una clave DKIM (domainkeys identified mail) firma cada mensaje para que el receptor pueda demostrar que no se modificó. Añada una política DMARC (domain-based message authentication, reporting and conformance) cuando ambas comprobaciones se superen. Envíe una reserva de prueba a una dirección real de un proveedor importante, abra las cabeceras del mensaje y confirme que las líneas de autenticación muestran pass. Una página de reservas que no puede enviar correo es peor que no tener página de reservas, porque falla de forma silenciosa.
Qué backends de calendario sincronizan realmente en ambos sentidos
La sincronización tiene dos direcciones y pueden fallar por separado. La dirección de lectura proporciona la disponibilidad: la aplicación debe ver los bloques que ya figuran como ocupados o asignará una franja en la que ya tiene otro compromiso. La dirección de escritura corresponde a la reserva: el evento confirmado debe aparecer en el calendario que realmente consulta, no sólo dentro de la herramienta de reservas.
Google Calendar y Microsoft 365 funcionan en ambas direcciones, con una condición en una instalación autoalojada. Debe crear usted mismo el cliente OAuth (autorización abierta), porque el ID de cliente del producto alojado no está incluido en el código fuente. En Cal.com, ese cliente es GOOGLE_API_CREDENTIALS en .env, donde se almacena el JSON que descarga desde la consola de Google Cloud. DayOtter utiliza las credenciales OAuth de Google y Microsoft de la misma forma.
Aquí pueden producirse dos fallos, y conviene conocerlos antes de empezar. Primero, la URI de redirección registrada debe coincidir exactamente con la URL pública, incluido el esquema y cualquier ruta final; de lo contrario, Google interrumpe la conexión con redirect_uri_mismatch en la pantalla de consentimiento. Segundo, un proyecto de Google cuyo estado de publicación esté en Testing emite tokens de actualización que caducan después de siete días. La sincronización funciona durante toda la semana y después se detiene; en la siguiente actualización, los registros de la aplicación muestran invalid_grant. Cambie la pantalla de consentimiento a In production o acepte volver a conectar manualmente cada lunes.
CalDAV (extensiones de calendario para WebDAV) es la opción abierta, pero su compatibilidad es más limitada. Cal.com incluye una aplicación CalDAV que todavía está marcada como beta y que se ha verificado con servidores como Baikal, Radicale, Nextcloud y Kerio Connect. Apple iCloud funciona mediante la misma aplicación, pero necesita una contraseña específica de aplicación en lugar de la contraseña del Apple ID. DayOtter incluye Apple mediante CalDAV junto a Google y Microsoft 365.
Un feed ICS no es una sincronización. Una URL .ics suscrita es de sólo lectura por diseño. Puede bloquear tiempo en la página de reservas, pero nunca puede recibir la reserva. Si una herramienta sólo ofrece ICS para su calendario, tendrá la mitad de la integración y seguirá copiando los eventos manualmente.
Easy!Appointments sincroniza Google Calendar y ningún otro servicio. Rallly no consulta la disponibilidad: recopila votos sobre un conjunto de fechas candidatas. Es la herramienta adecuada para «cuándo podemos reunirnos los seis» y la incorrecta para «reserva 30 minutos conmigo».
La página de reservas es pública, por lo que TLS es lo primero
La mayor parte de los servicios que se alojan por cuenta propia son privados. Una wiki, un tablero o un panel pueden estar detrás de una VPN o de un inicio de sesión SSO y no exponerse nunca a Internet pública. Un enlace de reservas no puede hacerlo. Todas las personas a las que lo envíe deben poder cargarlo, lo que cambia la configuración en tres aspectos concretos.
Necesita un nombre de dominio con un registro A que apunte al VPS antes de instalar nada. Necesita un certificado desde el primer día, porque los navegadores marcan un formulario HTTP sin cifrar como no seguro y el cliente introduce en él su nombre y dirección de correo electrónico. También debe establecer correctamente la URL pública de la aplicación en su configuración, porque ese valor se incluye en los enlaces de los correos salientes y en los URI de redirección de OAuth. Establezca NEXT_PUBLIC_WEBAPP_URL en Cal.com, DOMAIN en Rallly, BASE_URL en Easy!Appointments o DAYOTTER_DOMAIN durante la instalación, y asígnelo a la dirección https:// que realmente utilizará.
Rallly y DayOtter gestionan TLS automáticamente. La pila incluida con Rallly contiene Traefik y emite certificados de Let's Encrypt utilizando la dirección de ACME_EMAIL. El instalador de DayOtter inicia Caddy con HTTPS automático. Cal.com y Easy!Appointments no lo hacen, por lo que debe colocar nginx delante y emitir el certificado usted mismo, igual que en un certificado de Let's Encrypt en nginx con Certbot. Vincule el contenedor de la aplicación a 127.0.0.1 para que la única forma de acceder sea mediante el proxy que controla. Si el mismo equipo ya ejecuta una alternativa autoalojada a Trello para sus tableros internos, manténgala detrás de la autenticación existente y exponga públicamente sólo el bloque de servidor del host de reservas.
Cal.com en tu VPS
La configuración de Docker está en su propio repositorio y las imágenes ya están compiladas en Docker Hub, por lo que debes descargarlas en lugar de compilarlas.
git clone --recursive https://github.com/calcom/cal.diy.git
cd cal.diy
cp .env.example .env
openssl rand -base64 32
openssl rand -base64 24
docker compose pull
docker compose up -dEl primer valor aleatorio va en NEXTAUTH_SECRET y el segundo, en CALENDSO_ENCRYPTION_KEY. Ambos son obligatorios. Define DATABASE_URL y apunta NEXT_PUBLIC_WEBAPP_URL a tu dirección pública. La pila incluida contiene la aplicación web, PostgreSQL y Prisma Studio. La documentación indica docker compose up -d calcom para ejecutar sólo la aplicación contra una base de datos alojada en otro lugar. Eso es lo que necesitas cuando la instalación ya esté estable.
Descarga la imagen. No la compiles en el VPS. Las instrucciones del proyecto indican que debes exportar NODE_OPTIONS="--max-old-space-size=16384" al compilar desde el código fuente. Esto asigna un heap de 16 GB sólo para Node. En hardware ARM, añade el sufijo -arm a la etiqueta de la imagen. El proyecto no publica un mínimo de recursos para ejecutar la imagen precompilada. Por tanto, considera 2 GB para la aplicación y PostgreSQL como una estimación práctica, no como un requisito documentado. Monitoriza la memoria durante la primera semana.
Comprueba que se haya iniciado:
docker compose ps
docker compose logs -f calcom
curl -sI https://cal.example.com | head -n 1curl debe mostrar HTTP/2 200. Un 502 Bad Gateway de nginx mientras el contenedor aparece como activo suele indicar que el primer arranque todavía está aplicando las migraciones de la base de datos. Espera unos minutos y revisa los registros antes de concluir que hay un fallo. Los webhooks de Cal.com se ejecutan con cada reserva confirmada. Por tanto, una reserva puede activar cualquier automatización que ya uses, por ejemplo una instancia de n8n accesible mediante HTTPS en tu VPS.
El núcleo usa AGPLv3. Algunas funciones están en un directorio enterprise con una licencia comercial independiente. Lee esa licencia antes de crear un proceso empresarial de pago basado en las funciones de equipo.
Easy!Appointments en un servidor de 1 GB
Los requisitos son Apache o Nginx, PHP 8.2 o posterior y MySQL. Hay una imagen oficial en alextselegidis/easyappointments.
Primero, una advertencia. El docker-compose.yml del repositorio es un entorno de desarrollo. Espera que abra un shell en el contenedor y ejecute npm install && composer install && npm start. No es un despliegue. Use la imagen publicada:
services:
easyappointments:
image: alextselegidis/easyappointments # pin the current tag from Docker Hub
environment:
- BASE_URL=https://book.example.com
- DB_HOST=mysql
- DB_NAME=easyappointments
- DB_USERNAME=easyapp
- DB_PASSWORD=change-me
ports:
- '127.0.0.1:8080:80'
depends_on:
- mysql
mysql:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=change-me-too
- MYSQL_DATABASE=easyappointments
- MYSQL_USER=easyapp
- MYSQL_PASSWORD=change-me
volumes:
- ./mysql:/var/lib/mysqlBASE_URL debe ser la dirección HTTPS pública. Si la configura mal, los enlaces de reserva de los correos de confirmación apuntarán a un host al que el cliente no puede acceder. La imagen sirve HTTP sin cifrar en el puerto 80 y no tiene un certificado propio. Por eso el puerto está vinculado a 127.0.0.1 y nginx termina TLS delante. Si la sintaxis de Compose es nueva para usted, empiece por Conceptos básicos de Docker Compose en un VPS y vuelva después.
Esta es, con diferencia, la opción más ligera. Dos contenedores, una aplicación PHP y MySQL, funcionan sin problemas en un VPS de 1 GB. La contrapartida es la compatibilidad: Google Calendar es el único backend de calendario y la interfaz es un panel de administración tradicional, no un flujo de reservas moderno. Si su calendario es Microsoft 365, Fastmail o Nextcloud, descarte esta opción desde el principio.
Rallly para encuestas de grupo
Rallly responde a otra necesidad. No publica tu disponibilidad. Presenta un conjunto de horarios candidatos a un grupo y recopila votos. Eso es lo que necesitas para una reunión de la junta y no sirve para un enlace de reservas de clientes.
curl -fsSL https://get.rallly.co | bashLee cualquier script antes de pasarlo a un shell. Sustituye bash por less, revisa qué hace y ejecútalo después. El procedimiento manual realiza el mismo trabajo en pasos visibles:
git clone https://github.com/lukevella/rallly-selfhosted.git
cd rallly-selfhosted
./rallly.sh setup
./rallly.sh startLos requisitos documentados son al menos 2 GB de RAM, Docker 19.03 o posterior con Compose v2, los puertos 80 y 443 libres y un dominio que apunte al servidor. La pila incluida consta de Traefik para HTTPS, la aplicación web, PostgreSQL y Garage para el almacenamiento de objetos compatible con S3. Configura DOMAIN, un SECRET_PASSWORD de al menos 32 caracteres, SUPPORT_EMAIL y INITIAL_ADMIN_EMAIL. Si ya ejecutas un reverse proxy, configura PROXY_MODE=external y WEB_PORT para que Traefik no interfiera. Si ya ejecutas un almacenamiento de objetos compatible con S3 autoalojado con MinIO, apunta las variables S3_* a ese servicio y elimina el contenedor de Garage.
SMTP no es opcional en este caso, porque el inicio de sesión usa un enlace mágico. Sin un relay operativo, nadie puede iniciar sesión, incluida la cuenta de administrador que acabas de crear. Este es el resultado favorable del fallo del correo: te detiene en el acceso en lugar de hacerte perder la reserva de un cliente tres semanas después.
DayOtter, el participante más reciente
DayOtter es una plataforma de programación AGPLv3 con un asistente integrado. La instalación de producción se realiza con un solo comando:
curl -fsSL https://raw.githubusercontent.com/Dayotter/dayotter/main/deploy/install.sh \
| sudo DAYOTTER_DOMAIN=cal.example.com bashLéalo antes de ejecutarlo, como se indicó anteriormente. El instalador configura Docker, genera secretos y pone en marcha toda la pila: la aplicación web Next.js, un worker en segundo plano que gestiona recordatorios, sincronización de calendarios y webhooks, PostgreSQL, Redis y Caddy con HTTPS automático.
Es la opción con la compatibilidad de calendarios más amplia de las cuatro. Incluye Google, Microsoft 365, Apple mediante CalDAV y fuentes ICS, con la salvedad de ICS indicada anteriormente. Las demás integraciones se habilitan de forma opcional mediante variables de entorno. Incluyen SMTP o Resend para el correo, ANTHROPIC_API_KEY para el asistente, Twilio para SMS y Stripe para los pagos. El asistente requiere confirmación previa: propone una acción, usted la aprueba y nada llega al calendario sin un sí explícito. Si deja vacía la clave de API, esa parte del producto no se ejecuta.
La licencia es clara para quienes alojan el servicio por su cuenta. El núcleo usa AGPLv3 y un directorio ee/ contiene una licencia comercial exclusiva para la nube, que permanece inactiva mientras no se establezca DAYOTTER_CLOUD=1. Por tanto, las funciones de equipo del plan alojado, cuyo precio es de $9 por usuario al mes en agosto de 2026, están disponibles en su propio servidor.
Esta es también la pila más pesada de las cuatro y el proyecto más reciente. Ejecútelo junto con su enlace de reservas actual durante dos semanas, acepte reservas reales mediante ambos sistemas y revise los registros del worker antes de migrar a sus clientes.
Qué coste real tiene cada stack
El número de contenedores es el indicador más fiable de lo que un stack exigirá a un VPS pequeño, porque cada servicio tiene su propio consumo mínimo de memoria. Estos son los recuentos de los stacks Docker publicados por cada proyecto, consultados en agosto de 2026.
The data behind this chart
[
{
"tool": "Easy!Appointments",
"containers": 2,
"database": "MySQL"
},
{
"tool": "Cal.com",
"containers": 3,
"database": "PostgreSQL"
},
{
"tool": "Rallly",
"containers": 4,
"database": "PostgreSQL"
},
{
"tool": "DayOtter",
"containers": 5,
"database": "PostgreSQL and Redis"
}
]Easy!Appointments necesita 2 contenedores y funciona con 1 GB. El stack incluido de Rallly tiene 4, y su documentación solicita 2 GB. El instalador de DayOtter inicia 5, por lo que necesita el servidor más grande de los 4 que se muestran aquí. Cal.com y DayOtter no publican ninguna cifra mínima de memoria, así que tomo 2 GB como punto de partida para ambos, no como una cantidad admitida oficialmente.
Dos de estos recuentos disminuyen si ya ejecuta parte de la infraestructura. Los contenedores Traefik y Garage de Rallly dejan de ser necesarios si se configura para usar su propio proxy y almacenamiento de objetos. Prisma Studio de Cal.com es una herramienta de desarrollo que no debería dejar ejecutándose en un servidor público.
Qué alternativa de Calendly autoalojada debería elegir
Un consultor independiente debería usar Cal.com. Es el único proyecto de esta lista que combina una página de reservas reconocible, imágenes precompiladas que evitan compilar Node en el VPS y una integración con CalDAV para quienes no usan un calendario de Google o Microsoft. Una base de datos PostgreSQL y un contenedor de aplicación representan una carga de mantenimiento que puede gestionar durante años. Reserve una tarde para configurar el cliente OAuth y el relay de correo. Tenga en cuenta que la aplicación CalDAV todavía está en fase beta. Pruebe una reserva real de principio a fin antes de publicar el enlace.
Un equipo pequeño debería considerar DayOtter. La asignación round robin ponderada y las reservas colectivas forman parte del núcleo con licencia AGPLv3. Por tanto, el autoalojamiento ofrece funciones que un servicio alojado cobra por cada usuario. El proceso worker está diseñado para los recordatorios y los webhooks que un equipo utiliza de forma habitual. La contrapartida es la madurez: es el proyecto más nuevo de esta lista. Ejecútelo primero en paralelo y mantenga activo el enlace anterior hasta observar un mes completo de reservas.
Hay dos casos más específicos. Si sólo necesita una encuesta para encontrar una hora en la que el grupo pueda reunirse, instale Rallly y deténgase ahí. Si tiene un VPS de 1 GB, usa Google Calendar y quiere la aplicación más pequeña que acepte reservas, Easy!Appointments durará más que cualquier opción más compleja que pueda instalar en ese servidor. Para conocer otras aplicaciones que merecen espacio en el mismo servidor, consulte qué merece la pena autoalojar en 2026.
FAQ
¿Puedo ejecutar una página de reservas autoalojada sin un nombre de dominio?
No. Todas estas aplicaciones escriben su URL pública en los enlaces de los correos de confirmación, y Google y Microsoft comparan el URI de redirección de OAuth con ese mismo valor. Por eso, una dirección IP sin dominio muestra redirect_uri_mismatch en la pantalla de consentimiento. Let's Encrypt tampoco emite certificados para direcciones IP, así que la página se carga mediante HTTP sin cifrar y el navegador marca el formulario como no seguro. Compre primero el dominio, apunte un registro A a la VPS y, después, instale la aplicación.
¿Por qué nunca llegan mis correos de confirmación de reservas?
Casi siempre se debe a que el servidor intenta entregar el correo directamente. La mayoría de los proveedores de VPS bloquean el puerto saliente 25 en las cuentas nuevas, por lo que la conexión queda bloqueada. Además, aunque el puerto esté abierto, una dirección nueva no tiene reputación de envío y los grandes receptores la rechazan. Configure la aplicación para usar un relay de correo transaccional en el puerto 587, confirme que el puerto sea accesible con nc -vz -w 5 "$SMTP_HOST" 587 y publique los registros SPF y DKIM que le proporcione el relay. Si ejecuta Cal.com, compruebe que haya reemplazado los valores predeterminados EMAIL_SERVER_HOST=localhost y EMAIL_SERVER_PORT=1025 incluidos con la aplicación, que apuntan a un buzón de desarrollo local.
¿Cal.com autoalojado se sincroniza con CalDAV o sólo con Google?
Con ambos, aunque con distinto nivel de madurez. La aplicación CalDAV está marcada como beta y se verifica con servidores como Baikal, Radicale, Nextcloud y Kerio Connect. Apple iCloud también funciona mediante ella con una contraseña específica de la aplicación. Google Calendar y Microsoft 365 se sincronizan en ambas direcciones, pero en una instalación autoalojada debe crear su propio cliente OAuth y proporcionarlo mediante GOOGLE_API_CREDENTIALS, porque las credenciales del servicio alojado no están incluidas en el código fuente.
¿Por qué la sincronización con Google Calendar deja de funcionar después de una semana?
Porque el proyecto de Google Cloud todavía tiene el estado de publicación Testing. Google proporciona tokens de actualización a las aplicaciones con ese estado, pero caducan después de siete días. Por eso, la conexión funciona inicialmente, falla durante la siguiente renovación del token y el registro de la aplicación muestra invalid_grant. Cambie la pantalla de consentimiento de OAuth a In production y vuelva a conectar el calendario una vez. Volver a conectarlo sin cambiar el estado sólo le proporciona otros siete días.
¿Cuál de estas aplicaciones se ejecutará en una VPS de 1 GB?
Easy!Appointments funcionará, porque es una aplicación PHP con MySQL. Rallly documenta un mínimo de 2 GB y su conjunto incluido ejecuta cuatro servicios. Cal.com y DayOtter no publican un mínimo, pero una aplicación Next.js con PostgreSQL, y en el caso de DayOtter también Redis y un proceso de trabajo, implica que debe planificar 2 GB o más. Nunca compile Cal.com desde el código fuente en un servidor pequeño: las instrucciones de compilación del proyecto requieren un heap de Node de 16 GB. Use en su lugar la imagen precompilada.