---
title: "Deploy Cal.com — Open Source Calendly Alternative"
description: "Self-hosted scheduling with Postgres — no per-seat booking fees"
category: "Other"
url: https://railway.com/deploy/calcom-scheduling-postgres
---

# Deploy Cal.com — Open Source Calendly Alternative

Self-hosted scheduling with Postgres — no per-seat booking fees

**[Deploy Cal.com — Open Source Calendly Alternative on Railway](https://railway.com/template/calcom-scheduling-postgres)**

- **Creator:** SilverBanana
- **Category:** Other

## Template content

### Cal.com https://raw.githubusercontent.com/calcom/cal.com/main/apps/web/public/cal-com-icon.svg

- **Image:** calcom/cal.com:latest
- **Public domain:** Yes

### Postgres https://devicons.railway.app/i/postgresql.svg

- **Image:** ghcr.io/railwayapp-templates/postgres-ssl:18

## Documentation

# Deploy and Host Cal.com on Railway

Cal.com is the leading open-source scheduling platform — a self-hosted alternative to Calendly and Acuity. Share a booking link, let people pick a slot, and sync it to Google, Outlook, or CalDAV automatically. Unlimited event types, unlimited bookings, no per-seat fees, and your customers' calendar data stays on infrastructure you own. This template deploys Cal.com with a managed PostgreSQL database, pre-wired and persistent.

---

## What This Template Deploys

| Service | Purpose |
| --- | --- |
| **Cal.com** | The Next.js scheduling app, booking pages, and admin on port `3000` |
| **PostgreSQL** | Users, event types, bookings, and encrypted calendar credentials |

Both services run on Railway's private network with credentials injected automatically. Railway handles SSL and domain provisioning, and Prisma runs the database migrations on first boot.

---

## About Hosting Cal.com

Cal.com is a Next.js application, and that creates one specific pitfall on any container platform that catches most self-hosters: **`NEXT_PUBLIC_WEBAPP_URL` is compiled into the app at build time**, not read at runtime. Any variable prefixed `NEXT_PUBLIC_` is baked into the client bundle when the image is built, so setting it afterward as an environment variable does nothing — booking links, OAuth redirect URIs, and confirmation-email links all point at `localhost` and break. This template supplies that URL at build time so your links resolve to your real domain from the first boot.

Two secrets must be generated once and then never changed:

- **`NEXTAUTH_SECRET`** signs user sessions — `openssl rand -base64 32`
- **`CALENDSO_ENCRYPTION_KEY`** encrypts every stored calendar credential (Google and Microsoft OAuth tokens). It is **24 bytes**, not 32 — `openssl rand -base64 24`. Change it and every connected calendar is permanently corrupted and must be reconnected by hand.

Cal.com also needs `DATABASE_DIRECT_URL` alongside `DATABASE_URL`; Prisma uses the direct connection to run migrations. Both are wired to the Railway Postgres service here.

The database is not just app data — it holds OAuth tokens granting read/write access to your users' real calendars. Treat it as sensitive and back it up regularly.

Typical cost: **~$5–15/month** on Railway for a small instance with Postgres. Cal.com's own cloud starts at $12/user/month for team features, so self-hosting removes per-seat billing entirely.

---

## How It Compares

| | Cal.com (self-hosted) | Calendly | Acuity | Cal.com Cloud |
| --- | --- | --- | --- | --- |
| Cost model | Flat ~$5–15/mo infra | Per user/month | Per user/month | From $12/user/mo |
| Event types | Unlimited | Limited on free | Per plan | Unlimited |
| Data ownership | Full | Vendor | Vendor | Cal-hosted |
| Calendar sync | Google, Outlook, CalDAV | Google, Outlook | Google, Outlook | Same |
| Custom branding | Full | Higher tiers | Higher tiers | Team plans |
| Self-hostable | Yes | No | No | No |

Calendly and Acuity are more polished out of the box. Cal.com wins on unlimited event types at a flat cost, full branding control, and keeping your customers' calendar credentials on your own infrastructure.

---

## Deploy in Under 5 Minutes

1. Click **Deploy on Railway** — Cal.com and PostgreSQL build automatically (the Next.js build takes a few minutes)
2. Confirm `NEXT_PUBLIC_WEBAPP_URL` is set to your Railway domain **as a build argument**, and `NEXTAUTH_URL` matches it
3. Confirm `NEXTAUTH_SECRET` and the 24-byte `CALENDSO_ENCRYPTION_KEY` are set — and save both externally
4. Open your Railway domain; Cal.com redirects to the `/auth/setup` wizard
5. Create your admin account, set your availability, and share your first booking link

Configure the `EMAIL_SERVER_*` variables so booking confirmations and reminders send.

---

## Common Use Cases

- **Calendly replacement** — share booking links with unlimited event types and no per-seat fees
- **Team scheduling** — round-robin and collective event types route bookings across a team
- **Client-facing booking pages** — branded scheduling for consultants, coaches, and agencies on your own domain
- **Support and office hours** — recurring availability windows with buffer times and booking limits
- **Embedded scheduling** — drop Cal.com booking widgets into your own site or app

---

## Configuration

| Variable | Required | Description |
| --- | --- | --- |
| `NEXT_PUBLIC_WEBAPP_URL` | Required (build arg) | Your Railway domain — compiled into the app at build time, not runtime |
| `NEXTAUTH_URL` | Required | Same as your public URL — used for authentication callbacks |
| `NEXTAUTH_SECRET` | Required | Session signing key — `openssl rand -base64 32`, keep stable |
| `CALENDSO_ENCRYPTION_KEY` | Required | Credential encryption — **`openssl rand -base64 24`** (24 bytes). Never change it |
| `DATABASE_URL` | Auto-injected | PostgreSQL connection string via Railway reference variable |
| `DATABASE_DIRECT_URL` | Auto-injected | Direct connection for Prisma migrations — same as `DATABASE_URL` |
| `NEXT_PUBLIC_LICENSE_CONSENT` | Pre-set | `agree` — acknowledges the AGPLv3 self-host terms |
| `CALCOM_TELEMETRY_DISABLED` | Optional | Set `1` to disable telemetry |
| `EMAIL_FROM` | Required | Sender address for booking emails |
| `EMAIL_SERVER_HOST` | Required | SMTP hostname |
| `EMAIL_SERVER_PORT` | Required | SMTP port, e.g. `587` |
| `EMAIL_SERVER_USER` | Required | SMTP username |
| `EMAIL_SERVER_PASSWORD` | Required | SMTP password |

> **`NEXT_PUBLIC_WEBAPP_URL` must be a build argument.** It is compiled into the client bundle, so setting it only at runtime leaves booking and OAuth links pointing at `localhost`. This is the single most common broken self-hosted Cal.com deployment.

> **`CALENDSO_ENCRYPTION_KEY` is 24 bytes and permanent.** It encrypts stored calendar credentials. Changing it corrupts every connected calendar. Generate it once, back it up externally, and never rotate it.

---

## Dependencies for Cal.com Hosting

- Railway account — Hobby plan (~$5–15/month) covers both services
- An SMTP provider for booking confirmations and reminders
- Optional: Google Cloud OAuth credentials for Google Calendar sync
- Optional: Microsoft Azure app credentials for Outlook sync

### Deployment Dependencies

- [Cal.com GitHub Repository](https://github.com/calcom/cal.com)
- [Cal.com Docker Repository](https://github.com/calcom/docker)
- [Cal.com Self-Hosting Documentation](https://cal.com/docs/self-hosting)
- [Railway Variables Documentation](https://docs.railway.com/guides/variables)

### Implementation Details

The template runs the official `calcom/cal.com` image on port `3000` against a managed Railway PostgreSQL service. Because `NEXT_PUBLIC_WEBAPP_URL` is a Next.js public variable, it is provided as a build argument so the correct domain is compiled into the client bundle rather than defaulting to `localhost` — the failure that breaks booking links, OAuth redirects, and email URLs on naive deployments.

Both `DATABASE_URL` and `DATABASE_DIRECT_URL` point at the Postgres service; Prisma uses the direct URL to apply migrations, which run automatically on startup when schema changes are present. `NEXTAUTH_SECRET` and the 24-byte `CALENDSO_ENCRYPTION_KEY` are generated at deploy time and must persist unchanged, since the encryption key protects stored OAuth tokens for connected calendars.

All application data lives in PostgreSQL, including the encrypted calendar credentials. That database is both your bookings and a set of tokens with read/write access to real calendars, so it should be backed up on a schedule and treated as sensitive.

---

## Frequently Asked Questions

**My booking links point at localhost — why?** `NEXT_PUBLIC_WEBAPP_URL` was set at runtime instead of build time. It's compiled into the app, so it must be a build argument set to your real domain. This template handles that; if you fork it, preserve the build-arg setup.

**Why is `CALENDSO_ENCRYPTION_KEY` only 24 bytes?** Cal.com's credential encryption expects a 24-byte key — generate it with `openssl rand -base64 24`, not 32. Using the wrong length or changing it later permanently corrupts every stored calendar credential.

**Do my calendar connections survive a redeploy?** Yes, provided `CALENDSO_ENCRYPTION_KEY` stays constant. The OAuth tokens are encrypted with it and stored in Postgres; the key must not change or they become unreadable.

**Why does it need `DATABASE_DIRECT_URL`?** Prisma uses a direct database connection to run migrations, separate from the pooled connection the app uses. Both are wired to the same Railway Postgres here.

**Is the self-hosted version free?** Yes. Cal.com's community edition is AGPLv3 with no per-seat fees. Some enterprise features require a license, but core scheduling and calendar sync are fully open.

**How do I enable Google Calendar sync?** Create a Google Cloud project, enable the Calendar and People APIs, configure the OAuth consent screen, and add credentials with your Railway domain as the redirect URI. Then set the Google client ID and secret in Cal.com.

**Do I need SMTP?** Yes, for booking confirmations, reminders, and password resets. Configure the `EMAIL_SERVER_*` variables with your provider before going live.

---

## Why Deploy Cal.com on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying Cal.com on Railway you get open-source scheduling with the build-time pitfall already solved — Cal.com and PostgreSQL pre-wired over a private network, the webapp URL compiled correctly, encryption keys generated, automatic HTTPS, and Prisma migrations run for you. Unlimited event types, no per-seat billing, and your customers' calendar credentials on infrastructure you own.

## Similar templates

- [Rocky Linux](https://railway.com/deploy/rocky-linux) — [Jul'26] Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀
- [Foundry Virtual Tabletop](https://railway.com/deploy/X5tR6G) — A Self-Hosted & Modern Roleplaying Platform
- [Letta Code Remote](https://railway.com/deploy/letta-code-remote) — Run a Letta Code agent 24/7. No inbound ports, just deploy.

Open this page in a browser: https://railway.com/deploy/calcom-scheduling-postgres
