Calendly's free tier caps you at one event type and locks routing forms, round-robin assignment, and workflow automation behind a paid plan that scales with every teammate you add. Cal.com is the open-source scheduling platform the same booking-link idea was built on, with over 40,000 GitHub stars, no per-seat fee, and full control over your own booking data. The one thing that trips up most self-hosted setups is a single encryption key that permanently breaks every calendar connection if you get it wrong. This guide covers installing Cal.com with Docker, avoiding that mistake, and putting it on a real domain with Localtonet.
Why Pay Monthly for a Booking Link
A booking page is not a complicated piece of software: check your calendar, offer open slots, confirm the meeting. Calendly turned that into a subscription business by gating round-robin assignment, routing forms, and workflow reminders behind paid tiers that get more expensive per teammate you add.
Cal.com, launched in 2021 as Calendso and rebranded in 2022, is the open-source implementation of that same idea, with those exact features included, because there is no seat count to monetize when you run it yourself.
The booking link works the same for the person scheduling with you, only the monthly bill disappears.
What Is Cal.com?
Cal.com is an open-source scheduling platform under the AGPLv3 license, built with Next.js and PostgreSQL. It handles the entire booking flow: connecting your calendar, publishing available time slots, and confirming meetings, without a third party sitting in the middle of your calendar data.
Cal.com is a Next.js application backed by PostgreSQL. Plan for around 4GB of RAM for a comfortable single-instance deployment, Docker and Docker Compose installed, and a domain you intend to keep, calendar OAuth connections are tied to it.
Install Cal.com With Docker Compose
Generate your secrets
openssl rand -base64 32 # NEXTAUTH_SECRET
openssl rand -base64 24 # CALENDSO_ENCRYPTION_KEY
Clone the official Docker repository and configure .env
git clone https://github.com/calcom/docker calcom-docker
cd calcom-docker
cp .env.example .env
Fill in the required variables
NEXTAUTH_SECRET=your_generated_secret
CALENDSO_ENCRYPTION_KEY=your_generated_key
DATABASE_URL=postgresql://unicorn_user:magical_password@database:5432/calendso
NEXT_PUBLIC_WEBAPP_URL=https://cal.example.com
NEXTAUTH_URL=https://cal.example.com
Start the stack
docker compose up -d
Cal.com runs its database migrations automatically on first startup. The setup wizard walks you through creating your first user.
Every stored credential in Cal.com, Google OAuth tokens, calendar connections, integration secrets, is encrypted with this key. Change or lose it after your first run and none of that data re-encrypts, it becomes permanently unreadable, and every calendar connection breaks for good. Save it somewhere safe the moment you generate it, right alongside your database backups.
Remote Access With Localtonet
Cal.com's own production guides typically call for a local reverse proxy like Caddy just to get HTTPS in front of port 3000. Localtonet already terminates HTTPS on your custom domain, so that extra layer is not needed here.
Create an HTTP tunnel
Point it at 127.0.0.1:3000 and map a custom domain, such as cal.example.com.
Match NEXT_PUBLIC_WEBAPP_URL and NEXTAUTH_URL exactly
Both need to be the real public HTTPS address, not localhost, or booking confirmation links and login sessions will point to the wrong place.
Update your Google or Outlook OAuth redirect URI
Calendar integrations validate the redirect URL against what you registered in the provider's developer console, it needs to match your custom domain, not localhost.
Keep It Running Permanently
Add restart: unless-stopped to every service in your Compose file so the stack survives a Docker restart on its own. To survive a full machine reboot, install the Localtonet client as a background service once with your AuthToken from Dashboard โ My Tokens:
sudo localtonet --install-service --authtoken YOUR_TOKEN
sudo localtonet --start-service --authtoken YOUR_TOKEN
Only tunnels that were in Start state in the dashboard come back automatically, your booking domain included.
Cal.com vs. Calendly
| Feature | Calendly | Self-hosted Cal.com |
|---|---|---|
| Pricing | Per-seat, scales with team size | Free, your own hosting cost only |
| Routing forms and round-robin | Paid tiers only | Included |
| Where booking data lives | Calendly's servers | Your own database |
| Custom branding and domain | Limited to higher tiers | Fully white-label by default |
| Setup effort | None, sign up and connect a calendar | An evening of Docker and configuration |
The honest trade-off: Calendly is genuinely the faster path if you need something running in the next five minutes and do not mind the subscription. Cal.com's advantage shows up the moment you would otherwise be paying for a team plan, at that point the one-time setup cost pays for itself within a couple of months.
๐ Tips for Getting the Most Out of Cal.com
Troubleshooting Common Issues
| Symptom | Likely cause | Fix |
|---|---|---|
| Booking links or emails still show localhost | NEXT_PUBLIC_WEBAPP_URL or NEXTAUTH_URL was not updated | Set both to the exact https:// custom domain and restart the stack |
| Google or Outlook calendar connection fails | OAuth redirect URI does not match your custom domain | Update the redirect URI in the provider's developer console to match your Localtonet domain |
| Every calendar connection breaks after a restart | CALENDSO_ENCRYPTION_KEY changed or was regenerated | Restore the original key from backup, there is no way to recover encrypted data with a new one |
| No confirmation emails arrive | SMTP variables are missing or incorrect | Verify SMTP_HOST, SMTP_USER, and SMTP_PASS, then send a test booking |
Frequently Asked Questions
Is self-hosted Cal.com really free?
Yes, the self-hosted version is open source under AGPLv3 with no per-seat pricing. Your only cost is the hosting it runs on. A small number of enterprise-only features are reserved for Cal.com's paid cloud product, but the core scheduling platform is not gated.
What happens if I lose CALENDSO_ENCRYPTION_KEY?
Every encrypted credential in the database becomes unreadable, including calendar OAuth tokens. You would need to reconnect every calendar integration from scratch. Back the key up the moment you generate it.
Can I use my own domain for booking pages?
Yes, that is the default when self-hosting. Map a Localtonet custom domain to your HTTP tunnel and set NEXT_PUBLIC_WEBAPP_URL to match, booking pages are fully white-label from the start.
Does Cal.com sync with Google Calendar and Outlook?
Yes, Google Calendar, Outlook, and CalDAV connections keep your availability accurate in both directions, so bookings do not collide with events you already have scheduled.
Can I charge for consultations directly through Cal.com?
Yes, Stripe integration lets you collect payment at the moment someone books a paid slot, common for consultants and educators offering office hours.
Does my computer need to stay on for booking pages to work?
Yes, both the Cal.com containers and the Localtonet client need to be running. Setting both up as background services means bookings keep working without manual intervention after a reboot.
Can I set up round-robin scheduling across a small team?
Yes, round-robin and collective event types are included in the self-hosted version, no upgrade required to assign bookings across multiple team members automatically.
Ready to Cancel That Scheduling Subscription?
Deploy Cal.com with Docker, connect your calendar, then put it on a real domain with a Localtonet tunnel. Free to start, no credit card required.
Get Started Free โ