Technology Encyclopedia Home >Deploy Cal.com on a VPS — Your Own Open-Source Scheduling Tool Without Monthly Fees

Deploy Cal.com on a VPS — Your Own Open-Source Scheduling Tool Without Monthly Fees

I use scheduling links for consulting calls and demo bookings. The workflow is useful: send someone a link, they pick a slot, it goes into my calendar. The per-user cost for the hosted tools adds up, and for something this workflow-critical I'd rather control the infrastructure.

Cal.com is the open-source alternative to managed scheduling services. Same workflow — share a link, people book slots based on your availability — but running on your own server. Calendar integrations, Zoom link generation, booking forms, email reminders — all there.

Fair warning upfront: Cal.com is a large Next.js application. The build process is memory-hungry, and there's a specific Node.js memory flag you need to set or the build will fail. I'll cover that explicitly so you don't spend time debugging it.

I switched my consulting bookings to a self-hosted Cal.com instance after realizing I was paying for Calendly features I wasn't using while missing Cal.com features that would be useful. The setup is more involved than simpler apps, but once it's running, it's solid.

I run Cal.com on Tencent Cloud Lighthouse. Cal.com needs at least 2 GB RAM (PostgreSQL + Next.js); the 2 vCPU / 2 GB RAM plan is the starting point. For scheduling software specifically, uptime and reliable availability matter — your booking page needs to be accessible when someone follows a scheduling link. Lighthouse's stable infrastructure and the ability to upgrade specs from the control panel mean you can start lean and scale as your booking volume grows, without migrating to a new server. The snapshot feature is useful before Cal.com version upgrades, which can have database migration steps.


Table of Contents

  1. What Cal.com Can Do
  2. What You Need
  3. Part 1: Install Dependencies
  4. Part 2: Clone and Configure Cal.com
  5. Part 3: Set Up the Database
  6. Part 4: Build and Run
  7. Part 5: Configure Nginx with HTTPS
  8. Part 6: Connect Your Calendars
  9. The Thing That Tripped Me Up
  10. Troubleshooting
  11. Summary

  • Key Takeaways
  • Use the appropriate Lighthouse application image to skip manual installation steps where available
  • Lighthouse snapshots provide one-click full-server backup before major changes
  • OrcaTerm browser terminal lets you manage the server from any device
  • CBS cloud disk expansion handles growing storage needs without server migration
  • Console-level firewall + UFW = two independent protection layers

What Cal.com Can Do {#what-calcom-does}

  • Scheduling links — share a link; people pick available slots
  • Multiple event types — 30-min call, 1-hour consultation, team meetings
  • Calendar integration — syncs with Google Calendar, Outlook, Apple Calendar, CalDAV
  • Availability rules — set working hours, buffer time, minimum notice
  • Booking forms — collect custom fields when people book
  • Team scheduling — round-robin or collective availability for multiple people
  • Video integration — Zoom, Google Meet, Whereby links generated automatically
  • Webhooks — trigger automations when bookings are created/changed
  • Email notifications — reminders for both host and guest

What You Need {#prerequisites}

Requirement Details
Server Ubuntu 22.04, 2 GB+ RAM
Node.js v18+
PostgreSQL 13+
Domain Required — Cal.com needs a domain for OAuth and email
Email SMTP credentials for booking confirmations

Part 1: Install Dependencies {#part-1}

1.1 — Install Node.js 18

curl -fsSL https://deb.nodesource.com/setup_18.x | sudo bash -
sudo apt install -y nodejs
node --version  # Should be v18.x

1.2 — Install PostgreSQL

sudo apt install -y postgresql postgresql-contrib
sudo systemctl enable postgresql
sudo systemctl start postgresql

1.3 — Install Yarn (Cal.com uses Yarn)

npm install -g yarn

Part 2: Clone and Configure Cal.com {#part-2}

2.1 — Clone the Repository

cd /opt
sudo git clone https://github.com/calcom/cal.com.git
sudo chown -R ubuntu:ubuntu cal.com
cd cal.com

2.2 — Checkout a Stable Release

git fetch --tags
git checkout $(git describe --tags $(git rev-list --tags --max-count=1))

2.3 — Install Dependencies

yarn install

This takes 3–5 minutes.

2.4 — Create Environment File

cp .env.example .env
nano .env

Key settings to configure:

# Database
DATABASE_URL=postgresql://calcom:your-db-password@localhost:5432/calcom

# NextAuth
NEXTAUTH_SECRET=generate-with-openssl-rand-base64-32
NEXTAUTH_URL=https://cal.yourdomain.com

# Calendso URL
NEXT_PUBLIC_WEBAPP_URL=https://cal.yourdomain.com

# Email configuration (required for booking confirmations)
EMAIL_FROM=noreply@yourdomain.com
EMAIL_SERVER_HOST=smtp.sendgrid.net
EMAIL_SERVER_PORT=587
EMAIL_SERVER_USER=apikey
EMAIL_SERVER_PASSWORD=your-sendgrid-api-key

# Optional: Google Calendar OAuth
GOOGLE_API_CREDENTIALS={"installed":{"client_id":"...","client_secret":"..."}}

Generate NEXTAUTH_SECRET:

openssl rand -base64 32

Part 3: Set Up the Database {#part-3}

3.1 — Create PostgreSQL User and Database

sudo -u postgres psql
CREATE USER calcom WITH ENCRYPTED PASSWORD 'your-db-password';
CREATE DATABASE calcom OWNER calcom;
GRANT ALL PRIVILEGES ON DATABASE calcom TO calcom;
\q

3.2 — Run Database Migrations

cd /opt/cal.com
yarn db:migrate

This creates all Cal.com tables. Takes about 1–2 minutes.

3.3 — Seed Initial Data

yarn db:seed

Part 4: Build and Run {#part-4}

4.1 — Build the Application

cd /opt/cal.com
yarn build

The build takes 5–10 minutes — Cal.com is a large Next.js application.

4.2 — Test Run

yarn start

Access via SSH tunnel: ssh -L 3000:localhost:3000 ubuntu@YOUR_SERVER_IP

Open http://localhost:3000 and create the first admin account.

Press Ctrl+C to stop.

4.3 — Create systemd Service

sudo nano /etc/systemd/system/calcom.service
[Unit]
Description=Cal.com
After=network.target postgresql.service

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/opt/cal.com
EnvironmentFile=/opt/cal.com/.env
ExecStart=/usr/bin/yarn start
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable calcom
sudo systemctl start calcom
sudo systemctl status calcom

Part 5: Configure Nginx with HTTPS {#part-5}

sudo apt install -y nginx certbot python3-certbot-nginx
sudo nano /etc/nginx/sites-available/calcom
server {
    listen 80;
    server_name cal.yourdomain.com;

    location / {
        proxy_pass http://localhost: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;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        
        # Cal.com needs longer timeouts for some operations
        proxy_read_timeout 120s;
    }
}
sudo ln -s /etc/nginx/sites-available/calcom /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d cal.yourdomain.com

Access Cal.com at https://cal.yourdomain.com and complete the admin setup.


Part 6: Connect Your Calendars {#part-6}

Google Calendar

  1. Create a Google Cloud project and enable Calendar API
  2. Create OAuth 2.0 credentials
  3. Add https://cal.yourdomain.com/api/integrations/googlecalendar/callback as a redirect URI
  4. Add client ID and secret to your .env:
GOOGLE_API_CREDENTIALS={"installed":{"client_id":"YOUR_CLIENT_ID","project_id":"project","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","client_secret":"YOUR_CLIENT_SECRET","redirect_uris":["https://cal.yourdomain.com/api/integrations/googlecalendar/callback"]}}
  1. In Cal.com settings → Integrations → Google Calendar → Connect

Zoom Integration

  1. Create a Zoom app at marketplace.zoom.us
  2. Add OAuth credentials to .env:
ZOOM_CLIENT_ID=your-zoom-client-id
ZOOM_CLIENT_SECRET=your-zoom-client-secret

The Thing That Tripped Me Up {#gotcha}

During the build step, I kept getting JavaScript heap out of memory errors:

FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

Cal.com is a large monorepo and the build process is memory-intensive. On a 2 GB RAM server, the default Node.js heap limit (1.5 GB) wasn't enough.

The fix: Increase Node.js memory during the build:

export NODE_OPTIONS="--max-old-space-size=1536"
yarn build

Or add it to the build command in package.json temporarily:

NODE_OPTIONS='--max-old-space-size=1536' yarn build

After this, the build completed successfully. The startup memory footprint is smaller than the build memory requirement, so the service runs fine on 2 GB once built.


Troubleshooting {#troubleshooting}

Issue Likely Cause Fix
Build fails with OOM Insufficient memory Set NODE_OPTIONS="--max-old-space-size=1536"
Database connection error Wrong DATABASE_URL Check postgres user/password/database name
Email not sending SMTP config error Test SMTP credentials separately
OAuth redirect mismatch Wrong callback URL Add exact URL to Google/Zoom OAuth settings
"Invalid environment variable" Missing required env vars Check all required vars in .env.example
Slow load times First request compiles pages Normal for Next.js; subsequent requests are faster
Calendar not syncing OAuth token expired Re-connect calendar in Cal.com settings

Summary {#verdict}

What you built:

  • Full Cal.com scheduling platform on your own server
  • PostgreSQL database for booking storage
  • HTTPS access via Nginx with Let's Encrypt
  • Google Calendar and Zoom integrations (optional)
  • Systemd service for 24/7 operation
  • Custom booking pages at cal.yourdomain.com/yourname

Self-hosted Cal.com removes per-user fees while giving you full control over your scheduling data and branding.

Frequently Asked Questions {#faq}

What data does self-hosted Cal.com protect compared to cloud services?
Your content — notes, documents, calendar events, tasks — is stored on your server and never sent to a third party's infrastructure. This matters for sensitive personal or professional information.

Can I collaborate with others on a self-hosted Cal.com instance?
Most productivity tools support multiple users. The number of users depends on the tool and your server resources. Check the guide's prerequisites for per-user resource estimates.

How do I access self-hosted Cal.com from mobile devices?
Install the official mobile app and configure it to connect to your server URL instead of the default cloud service. The setup is typically done in the app's server settings.

What happens to my data if the server goes down?
Data on the server is preserved. You won't have access until the server is restored, but data isn't lost. Lighthouse snapshots provide backup and quick recovery.

How do I keep the application updated?
Update procedures vary by application. Container-based apps (docker compose pull) are typically straightforward. The guide includes update instructions specific to the application.

👉 Get started with Tencent Cloud Lighthouse
👉 View current pricing and launch promotions
👉 Explore all active deals and offers