Self-Host Cal.com: Calendly Alternative Scheduling 2026
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
| Feature | Cal.com (self-hosted) | Calendly Essentials | Calendly Teams |
|---|---|---|---|
| Cost | Free (hosting) | $10/user/mo | $16/user/mo |
| Event types | Unlimited | 1 type (free) | Unlimited |
| Team scheduling | Yes | No (free) | Yes |
| Round-robin | Yes | No | Yes |
| Payments (Stripe) | Yes | No | Yes |
| Custom domain | Yes | Yes (paid) | Yes |
| Zapier/webhooks | Yes | Yes (paid) | Yes |
| Self-hosted | Yes | No | No |
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
- Event Types → New Event Type
- Title: "30-minute Meeting"
- URL:
cal.yourdomain.com/yourname/30min - Duration: 30 minutes
- Location: Zoom / Google Meet / Custom (add as an app first)
- Availability: Select your schedule (or create a custom one)
- 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:
- Settings → Connected Calendars → Connect Calendar
- Google Calendar: OAuth2 flow (add Google credentials in Settings → Apps → Google)
- Outlook: Microsoft OAuth2
- 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)
- Event Types → New Event Type → Type: Round-Robin
- Add team members
- Algorithm: Round Robin (equal distribution) or Maximize Availability (first available)
- Booking URL:
cal.yourdomain.com/team/yourteam/support
Customers book → Cal.com assigns to the next available team member.
Collective (All must attend)
- Event Type → Type: Collective
- Add attendees (all must be available for the booking to show)
- Used for: interviews, demos with multiple presenters
Part 6: Availability Schedules
- Settings → Availability → New Schedule
- Name: "Business Hours"
- Days: Monday–Friday
- Hours: 9:00 AM – 5:00 PM
- 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:
- Settings → Apps → Stripe → Install
- Connect Stripe account (OAuth)
- In Event Type → Payments → Enable, set price
- Bookers must pay before the booking is confirmed
Part 9: Webhooks
Trigger webhooks on booking events for automation:
- Settings → Developer → Webhooks → New Webhook
- Endpoint URL:
https://n8n.yourdomain.com/webhook/calcom - 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.