Skip to main content

Open-source alternatives guide

Self-Host Cal.com: Calendly Alternative Scheduling 2026

Self-host Cal.com as a Calendly alternative in 2026. AGPL 3.0, ~32K stars, TypeScript/Next.js — scheduling, team booking, round-robin, Google/Outlook sync.

·OSSAlt Team
Share:

TL;DR

Cal.com (AGPL 3.0, ~32K GitHub stars, TypeScript/Next.js) is the open source Calendly — a scheduling platform where people book meetings on your calendar without email back-and-forth. Calendly charges $10–16/month for professional features. Self-hosted Cal.com gives you unlimited event types, team scheduling, round-robin assignment, and payment collection for free.

Key Takeaways

  • Cal.com: AGPL 3.0, ~32K stars, TypeScript/Next.js — full scheduling platform
  • Multiple event types: 1:1, group, round-robin, collective (all team members present)
  • Calendar sync: Google Calendar, Outlook, CalDAV — no double-bookings
  • Customizable: Embed booking widget on your website
  • Payments: Stripe integration for paid bookings
  • Requirements: Node.js + PostgreSQL; ~500MB RAM

Cal.com vs Calendly

FeatureCal.com (self-hosted)Calendly EssentialsCalendly Teams
CostFree (hosting)$10/user/mo$16/user/mo
Event typesUnlimited1 type (free)Unlimited
Team schedulingYesNo (free)Yes
Round-robinYesNoYes
Payments (Stripe)YesNoYes
Custom domainYesYes (paid)Yes
Zapier/webhooksYesYes (paid)Yes
Self-hostedYesNoNo

Part 1: Docker Setup

Cal.com requires several environment variables. The official repo has a .env.example:

git clone https://github.com/calcom/cal.com calcom
cd calcom
cp .env.example .env

Edit .env:

DATABASE_URL=postgresql://calcom:password@db:5432/calcom
NEXTAUTH_SECRET=$(openssl rand -hex 32)
CALENDSO_ENCRYPTION_KEY=$(openssl rand -hex 32)
NEXTAUTH_URL=https://cal.yourdomain.com
NEXT_PUBLIC_WEBAPP_URL=https://cal.yourdomain.com

# Email (required):
EMAIL_FROM=noreply@yourdomain.com
EMAIL_SERVER_HOST=smtp.yourdomain.com
EMAIL_SERVER_PORT=587
EMAIL_SERVER_USER=noreply@yourdomain.com
EMAIL_SERVER_PASSWORD=your-smtp-password
# docker-compose.yml
services:
  db:
    image: postgres:16-alpine
    restart: unless-stopped
    volumes:
      - db_data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: calcom
      POSTGRES_USER: calcom
      POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U calcom"]
      interval: 10s

  calcom:
    image: calcom/cal.com:latest
    container_name: calcom
    restart: unless-stopped
    ports:
      - "3000:3000"
    depends_on:
      db:
        condition: service_healthy
    env_file:
      - .env
    environment:
      DATABASE_URL: "postgresql://calcom:${POSTGRES_PASSWORD}@db:5432/calcom"

volumes:
  db_data:
docker compose up -d

Part 2: HTTPS with Caddy

cal.yourdomain.com {
    reverse_proxy localhost:3000
}

Visit https://cal.yourdomain.com → create admin account.


Part 3: Create Your First Event Type

  1. Event Types → New Event Type
  2. Title: "30-minute Meeting"
  3. URL: cal.yourdomain.com/yourname/30min
  4. Duration: 30 minutes
  5. Location: Zoom / Google Meet / Custom (add as an app first)
  6. Availability: Select your schedule (or create a custom one)
  7. Save

Share the link: https://cal.yourdomain.com/yourname/30min


Part 4: Calendar Integration (No Double-Bookings)

Connect your calendar so Cal.com checks availability:

  1. Settings → Connected Calendars → Connect Calendar
  2. Google Calendar: OAuth2 flow (add Google credentials in Settings → Apps → Google)
  3. Outlook: Microsoft OAuth2
  4. CalDAV: Enter CalDAV URL + credentials

Cal.com reads busy/free blocks from connected calendars, so scheduled meetings never overlap with existing events.

Create events on booking: Select which calendar new bookings are added to.


Part 5: Team Scheduling

Add team members to collective or round-robin events:

Round-Robin (One team member, rotated)

  1. Event Types → New Event Type → Type: Round-Robin
  2. Add team members
  3. Algorithm: Round Robin (equal distribution) or Maximize Availability (first available)
  4. Booking URL: cal.yourdomain.com/team/yourteam/support

Customers book → Cal.com assigns to the next available team member.

Collective (All must attend)

  1. Event Type → Type: Collective
  2. Add attendees (all must be available for the booking to show)
  3. Used for: interviews, demos with multiple presenters

Part 6: Availability Schedules

  1. Settings → Availability → New Schedule
  2. Name: "Business Hours"
  3. Days: Monday–Friday
  4. Hours: 9:00 AM – 5:00 PM
  5. Timezone: Your timezone

Set buffer times:

  • Before event: 15 minutes (prep time)
  • After event: 15 minutes (recovery time)

Part 7: Booking Page Customization

Event Type → Advanced:

  • Custom confirmation redirect URL
  • Custom email templates
  • Questions to ask bookers (custom form fields)
  • Require payment (Stripe) before confirming

Embed on your website:

<!-- Inline embed: -->
<div style="width:100%;height:100%;overflow:scroll">
  <iframe src="https://cal.yourdomain.com/yourname/30min?embed=true"
    frameborder="0" allowfullscreen></iframe>
</div>

<!-- Or use the Cal.com embed snippet: -->
<script src="https://cal.yourdomain.com/embed/embed.js"></script>
<script>Cal("init"); Cal("inline", {calLink: "yourname/30min"})</script>

Part 8: Stripe Payments

Accept payment when someone books:

  1. Settings → Apps → Stripe → Install
  2. Connect Stripe account (OAuth)
  3. In Event Type → Payments → Enable, set price
  4. Bookers must pay before the booking is confirmed

Part 9: Webhooks

Trigger webhooks on booking events for automation:

  1. Settings → Developer → Webhooks → New Webhook
  2. Endpoint URL: https://n8n.yourdomain.com/webhook/calcom
  3. Events: Booking Created, Booking Cancelled, Booking Rescheduled

Use with n8n or Zapier to:

  • Add bookings to a CRM
  • Send custom confirmation SMS
  • Create a Notion/Airtable record
  • Notify a Slack channel

Maintenance

# Update Cal.com:
docker compose pull
docker compose up -d

# Backup:
docker exec calcom-db-1 pg_dump -U calcom calcom | gzip \
  > calcom-backup-$(date +%Y%m%d).sql.gz

# Logs:
docker compose logs -f calcom

# Run migrations after update:
docker exec calcom npx prisma migrate deploy

See all open source productivity and scheduling tools at OSSAlt.com/alternatives/calendly.

See open source alternatives to Cal.com on OSSAlt.

Monitoring and Operational Health

Deploying a self-hosted service without monitoring is running blind. At minimum, set up three layers: uptime monitoring, resource monitoring, and log retention.

Uptime monitoring with Uptime Kuma gives you HTTP endpoint checks every 30-60 seconds with alerts to Telegram, Slack, email, or webhook. Create a monitor for your primary application URL and any API health endpoints. The status page feature lets you communicate incidents to users without custom tooling.

Resource monitoring tells you when a container is leaking memory or when disk is filling up. Prometheus + Grafana is the standard self-hosted monitoring stack — Prometheus scrapes container metrics via cAdvisor, Grafana visualizes them with pre-built Docker dashboards. Set alerts for memory above 80% and disk above 75%; both give you time to act before they become incidents.

Log retention: Docker container logs are ephemeral by default. Add logging: driver: json-file; options: max-size: 100m; max-file: 3 to your docker-compose.yml to limit log growth and retain recent logs for debugging. For centralized log search across multiple containers, Loki integrates with the same Grafana instance.

Backup discipline: Schedule automated backups of your Docker volumes using Duplicati or Restic. Back up to remote storage (Backblaze B2 or Cloudflare R2 cost $0.006/GB/month). Run a restore drill monthly — a backup that has never been tested is not a reliable backup. Your restore procedure documentation should live somewhere accessible from outside the failed server.

Update strategy: Pin Docker image versions in your compose file rather than using latest. Create a monthly maintenance window to review changelogs and update images. Major version updates often require running migration scripts before the new container starts — check the release notes before pulling.

Cal.com fits naturally into a broader self-hosted productivity stack. n8n can automate Cal.com webhook events — sending custom notifications, creating CRM records, or triggering workflows when bookings are confirmed or cancelled. Plausible Analytics can track your Cal.com booking page's traffic and conversion rate without sending visitor data to third-party analytics services.

Network Security and Hardening

Self-hosted services exposed to the internet require baseline hardening. The default Docker networking model exposes container ports directly — without additional configuration, any open port is accessible from anywhere.

Firewall configuration: Use ufw (Uncomplicated Firewall) on Ubuntu/Debian or firewalld on RHEL-based systems. Allow only ports 22 (SSH), 80 (HTTP redirect), and 443 (HTTPS). Block all other inbound ports. Docker bypasses ufw's OUTPUT rules by default — install the ufw-docker package or configure Docker's iptables integration to prevent containers from opening ports that bypass your firewall rules.

SSH hardening: Disable password authentication and root login in /etc/ssh/sshd_config. Use key-based authentication only. Consider changing the default SSH port (22) to a non-standard port to reduce brute-force noise in your logs.

Fail2ban: Install fail2ban to automatically ban IPs that make repeated failed authentication attempts. Configure jails for SSH, Nginx, and any application-level authentication endpoints.

TLS/SSL: Use Let's Encrypt certificates via Certbot or Traefik's automatic ACME integration. Never expose services over HTTP in production. Configure HSTS headers to prevent protocol downgrade attacks. Check your SSL configuration with SSL Labs' server test — aim for an A or A+ rating.

Container isolation: Avoid running containers as root. Add user: "1000:1000" to your docker-compose.yml service definitions where the application supports non-root execution. Use read-only volumes (volumes: - /host/path:/container/path:ro) for configuration files the container only needs to read.

Secrets management: Never put passwords and API keys directly in docker-compose.yml files committed to version control. Use Docker secrets, environment files (.env), or a secrets manager like Vault for sensitive configuration. Add .env to your .gitignore before your first commit.

Production Deployment Checklist

Before treating any self-hosted service as production-ready, work through this checklist. Each item represents a class of failure that will eventually affect your service if left unaddressed.

Infrastructure

  • Server OS is running latest security patches (apt upgrade / dnf upgrade)
  • Firewall configured: only ports 22, 80, 443 open
  • SSH key-only authentication (password auth disabled)
  • Docker and Docker Compose are current stable versions
  • Swap space configured (at minimum equal to RAM for <4GB servers)

Application

  • Docker image version pinned (not latest) in docker-compose.yml
  • Data directories backed by named volumes (not bind mounts to ephemeral paths)
  • Environment variables stored in .env file (not hardcoded in compose)
  • Container restart policy set to unless-stopped or always
  • Health check configured in Compose or Dockerfile

Networking

  • SSL certificate issued and auto-renewal configured
  • HTTP requests redirect to HTTPS
  • Domain points to server IP (verify with dig +short your.domain)
  • Reverse proxy (Nginx/Traefik) handles SSL termination

Monitoring and Backup

  • Uptime monitoring configured with alerting
  • Automated daily backup of Docker volumes to remote storage
  • Backup tested with a successful restore drill
  • Log retention configured (no unbounded log accumulation)

Access Control

  • Default admin credentials changed
  • Email confirmation configured if the app supports it
  • User registration disabled if the service is private
  • Authentication middleware added if the service lacks native login

Conclusion

The decision to self-host is ultimately a question of constraints and priorities. Data ownership, cost control, and customization are legitimate reasons to run your own infrastructure. Operational complexity, reliability guarantees, and time cost are legitimate reasons not to.

The practical path forward is incremental. Start with the service where self-hosting provides the most clear value — usually the one with the highest SaaS cost or the most sensitive data. Build your operational foundation (monitoring, backup, SSL) correctly for that first service, then evaluate whether to expand.

Self-hosting done well is not significantly more complex than using SaaS. The tools available in 2026 — containerization, automated certificate management, hosted monitoring services, and S3-compatible backup storage — have reduced the operational overhead to something manageable for any developer comfortable with the command line. What it requires is discipline: consistent updates, tested backups, and monitoring that alerts before users do.

Cal.com self-hosting is a compelling option for businesses with compliance requirements around booking data, high booking volumes where Calendly's per-seat pricing is expensive, or teams that need customization beyond what the hosted tier allows. The Docker Compose deployment is stable and well-documented. The main operational consideration is email delivery — configure a transactional email provider (Postmark, Resend, or SMTP relay) before your first booking, since meeting confirmations and reminders are central to the product's value. Budget 2-3 hours for the initial deployment and configuration, and 15-30 minutes per month for updates.

Cal.com's event type configuration allows per-event buffer times, confirmation workflows, and custom questions — the same features that drive Calendly's paid tier pricing. Configure your integration calendar (Google Calendar, Outlook, or CalDAV) before inviting external users to book. Booking conflicts and availability sync depend on this integration being correctly configured. The self-hosted instance supports multiple users and teams with role-based access, making it suitable for team scheduling coordination without per-seat licensing costs.

The SaaS-to-Self-Hosted Migration Guide (Free PDF)

Step-by-step: infrastructure setup, data migration, backups, and security for 15+ common SaaS replacements. Used by 300+ developers.

Join 300+ self-hosters. Unsubscribe in one click.