Cal Com

Scheduling infrastructure: booking pages and calendar availability

Cal.com on Cubeship

Cal.com is open-source scheduling: share a link, and people book time on your calendar without the back-and-forth.

This template installs it on a Cubeship instance with the managed Postgres it keeps users, event types and bookings in.

What it creates

  • cal-com — the Cal.com web app, from calcom/cal.com:v6.2.0, answering on the domain you choose.
  • cal-com-db — a managed Postgres 18 database, attached to the app.

What you are asked

InputWhat to give
Where Cal.com answersA domain you control, pointed at your instance.
The secret sessions are signed withNothing — the instance generates it and shows it once.
The key Cal.com encrypts stored credentials withNothing — the instance generates it and shows it once. Keep a copy: a new key cannot read the calendar and app credentials saved under the old one.
Your SMTP serverThe host your mail provider gives you, like smtp.mailgun.org.
Its port587 unless your provider says otherwise.
The SMTP usernameFrom your mail provider.
The SMTP passwordFrom your mail provider.
The address Cal.com sends fromAn address your provider lets you send as.

Mail is not optional. A booking's confirmation, its cancellation, the organizer's notice that somebody booked, and password resets are all emails. Without them Cal.com still takes bookings, and nobody is told.

Port 465 gets TLS from the first byte; any other port starts plain and upgrades with STARTTLS.

After installing

  1. The first start takes a few minutes. Cal.com migrates its database and fills its app store before it listens, and the domain answers only once it does.
  2. Open https://<your domain>/auth/setup straight away. Cal.com has no default account: the first person to open it creates the admin. Until you do, that is anyone who finds the domain.
  3. Book a test event with an address you read, to see that mail arrives.

The SMTP settings are variables on the cal-com app. Change them and redeploy.

The URLs assume the instance serves HTTPS. On an instance with TLS off, change NEXT_PUBLIC_WEBAPP_URL and NEXTAUTH_URL to start with http://.

Calendars and video

Google Calendar, Outlook, Zoom and the other integrations each need an OAuth app you register with that provider, pointed back at your domain. None is set up here; follow Cal.com's self-hosting docs for the one you want, add what it asks for to the cal-com app, and redeploy.

What is not included

  • API v2. Cal.com's newer API is a separate service with its own image, and this template does not run it. The web app works without it.
  • Enterprise features. Cal.com is AGPLv3, except the code under its ee directories, which is under a commercial license and needs a license key from Cal.com.

Resources

The app is limited to 1 CPU and 2 GiB of memory. Raise limits in template.yaml for a busy instance.

What this creates

cal-com

calcom/cal.com:v6.2.0

cal-com-db

Postgres 18

template.yaml
# yaml-language-server: $schema=https://cubeship.dev/schema/template/v1.json
version: 1
minCubeship: "0.6.0"
project: cal-com

inputs:
  - key: domain
    type: domain
    label: Where Cal.com answers
  - key: authSecret
    type: secret
    label: The secret sessions are signed with
    generate: 32
  - key: encryptionKey
    type: secret
    label: The key Cal.com encrypts stored credentials with
    help: Keep a copy. Without it, connected calendars and apps cannot be read again.
    # AES-256 takes the string's bytes as the key, so it must be exactly 32.
    generate: 32
  - key: smtpHost
    type: text
    label: Your SMTP server
    help: Every booking, cancellation and password reset is an email, so without working mail nobody hears about a booking.
  - key: smtpPort
    type: number
    label: Its port
    help: 465 connects with TLS from the first byte; any other port upgrades with STARTTLS.
    default: 587
    min: 1
    max: 65535
  - key: smtpUser
    type: text
    label: The SMTP username
  - key: smtpPassword
    type: secret
    label: The SMTP password
  - key: mailFrom
    type: text
    label: The address Cal.com sends from
    help: One your SMTP provider lets you send as, like bookings@example.com.
    pattern: ^[^@\s]+@[^@\s]+\.[^@\s]+$

databases:
  - key: db
    name: cal-com-db
    engine: postgres
    version: "18"
    database: calcom

apps:
  - key: web
    name: cal-com
    image: calcom/cal.com
    tag: v6.2.0
    port: 3000
    # Answers 200 without signing in and without touching the database.
    health: /api/version
    domains:
      - host: ${input.domain}
    attach:
      - database: db
    limits: { cpu: 1, memory: 2Gi }
    env:
      # The image is built for http://localhost:3000; its start script
      # rewrites that into the built pages when this differs.
      NEXT_PUBLIC_WEBAPP_URL: https://${input.domain}
      NEXTAUTH_URL: https://${input.domain}
      NEXTAUTH_SECRET: ${input.authSecret}
      CALENDSO_ENCRYPTION_KEY: ${input.encryptionKey}
      # Prisma's schema names a direct URL too, and refuses to start without it.
      DATABASE_DIRECT_URL: postgresql://${db.db.user}:${db.db.password}@${db.db.host}:${db.db.port}/${db.db.name}?sslmode=disable
      # The start script waits for this before migrating, and needs host:port.
      DATABASE_HOST: ${db.db.host}:${db.db.port}
      CALCOM_TELEMETRY_DISABLED: "1"
      EMAIL_SERVER_HOST: ${input.smtpHost}
      EMAIL_SERVER_PORT: ${input.smtpPort}
      EMAIL_SERVER_USER: ${input.smtpUser}
      EMAIL_SERVER_PASSWORD: ${input.smtpPassword}
      EMAIL_FROM: ${input.mailFrom}