Best of Product Hunt

How to Set Up Self-Hosted Employee Scheduling Software with Cal.com (Docker + Reverse Proxy + SSO)

A practical, security-minded guide to running Cal.com as self-hosted employee scheduling software using Docker, a reverse proxy with HTTPS, and SSO (SAML/OIDC). Covers prerequisites, deployment steps, environment variables, SSO configuration tips, and common pitfalls.

Share:

Deploy Cal.com with Docker Compose using a Cal.com app container plus a PostgreSQL database (or managed Postgres). Configure key environment variables like DATABASE_URL, NEXTAUTH_URL (your public domain), and a strong NEXTAUTH_SECRET, ideally stored in a .env file or Docker secrets.

You’ll need a Linux server/VM, a domain such as schedule.company.com, Docker + Docker Compose, and a reverse proxy like Traefik or Nginx. For SSO, you also need access to an identity provider (Okta, Azure AD, Google Workspace, Keycloak, etc.).

Use a reverse proxy (Traefik or Nginx) to terminate TLS and route traffic to the Cal.com container over an internal Docker network. Make sure HTTP redirects to HTTPS and that forwarded headers like X-Forwarded-Proto and X-Forwarded-Host are correctly passed.

NEXTAUTH_URL must be set to your public HTTPS URL (for example, https://schedule.company.com) so Cal.com generates correct links and authentication redirects. If it’s wrong, you can see issues like http:// links behind HTTPS or broken SSO callbacks.

Configure SSO using OIDC (common) or SAML via your IdP by providing the correct redirect/callback URL, plus client ID/secret and issuer/discovery URL for OIDC or metadata/certificate for SAML. The callback URL must match exactly what you configure in the identity provider.

Use defense-in-depth by requiring authentication (SSO), restricting by email domain where appropriate, and disabling public sign-ups if you don’t want external accounts. You can also IP-allowlist at the reverse proxy (for example, VPN ranges) for additional protection.

A frequent issue is “Redirect URI mismatch,” which is fixed by making the IdP callback URL match exactly (including https and the correct subdomain). Clock drift can also break token validation, so enable NTP time sync on the server.

Confirm OAuth app credentials are configured and the redirect URIs match your production domain. Test with multiple users, and verify time zones and working hours behavior to ensure bookings reliably write to calendars.

Treat it like a production service: set up nightly PostgreSQL backups, test restores, and store backups securely offsite. Pin versions where possible, update via staging first with a rollback plan, and monitor uptime, health checks, disk usage, and TLS certificate renewals.

How to Set Up Self-Hosted Employee Scheduling Software with Cal.com (Docker + Reverse Proxy + SSO)

Self-hosting employee scheduling software is often about control: keeping availability data inside your network, enforcing company authentication policies, and integrating with your existing identity provider (Okta, Azure AD, Google Workspace, Keycloak, etc.). The good news: you can get a production-grade setup running with Docker, put it behind a reverse proxy for HTTPS, and enable SSO so employees log in with their corporate accounts.

This article walks through a practical setup for **self-hosted scheduling with** [PRODUCT_LINK]Cal.com[/PRODUCT_LINK] using:

- **Docker** (repeatable deployments)

- **Reverse proxy** (TLS termination + clean public URL)

- **SSO** (OIDC or SAML via your IdP)

The goal is a stable foundation you can adapt to your infrastructure.

---

What you’ll build (and why it matters)

A common employee scheduling workflow is:

1. Teams publish internal booking pages (or share links) for 1:1s, interviews, office hours, shift handoffs, etc.

2. Bookings write into staff calendars (Google/Microsoft).

3. Authentication is enforced centrally (SSO), so only employees can access internal scheduling pages.

4. Admins can self-host to meet compliance requirements and keep control over data residency.

Self-hosting adds responsibilities—TLS, backups, secrets management—but gives you predictable governance.

---

Prerequisites

Before you start, make sure you have:

- A Linux VM or server (Ubuntu is common)

- A domain/subdomain (e.g., `schedule.company.com`)

- Docker + Docker Compose installed

- A reverse proxy (examples below use **Traefik** or **Nginx**)

- Access to an IdP for SSO (Okta / Azure AD / Google / Keycloak)

Also decide where persistent data should live:

- Database (typically PostgreSQL)

- Uploaded assets (if applicable)

- Environment secrets (do **not** commit to Git)

---

Step 1: Plan your deployment architecture

A solid “small production” layout looks like this:

- `calcom` app container

- `postgres` container (or managed Postgres)

- reverse proxy container (Traefik/Nginx/Caddy)

- optional: Redis, monitoring, log shipping

**Recommendation:** Put the reverse proxy and the app on the same Docker network. Terminate TLS at the proxy and forward traffic internally over HTTP.

---

Step 2: Create Docker Compose for Cal.com + Postgres

Instead of pasting a huge file with every possible option, use the official docs as your source of truth and keep your Compose minimal.

Start by reviewing the self-hosting and Docker guidance in the official documentation for [PRODUCT_LINK]the Cal.com self-hosted deployment docs[/PRODUCT_LINK]. You’ll typically configure:

- `DATABASE_URL`

- `NEXTAUTH_URL` (your public URL)

- `NEXTAUTH_SECRET` (random, strong)

- SMTP (optional but recommended for invites/notifications)

Example: Compose structure (conceptual)

Your `docker-compose.yml` will generally include services similar to:

- **postgres**

- persistent volume

- strong credentials

- **calcom**

- environment variables

- depends on postgres

- connected to a shared network with the reverse proxy

> Tip: Prefer a **managed Postgres** when possible—fewer moving parts, better backups, less operational risk.

Environment variables and secrets

Use a `.env` file (or Docker secrets) for:

- database credentials

- NextAuth secrets

- OAuth/SSO client secrets

Keep `.env` out of version control.

---

Step 3: Put it behind a reverse proxy (HTTPS + clean routing)

A reverse proxy gives you:

- HTTPS certificates (Let’s Encrypt)

- a stable external hostname

- headers/security controls

- optional IP allowlisting for internal-only scheduling

Option A: Traefik (popular with Docker)

Traefik can auto-discover containers via labels and issue certificates automatically.

Key things to configure:

- entrypoints (`:80`, `:443`)

- Let’s Encrypt resolver

- routing rule for `schedule.company.com`

- forwarded headers (so the app knows the original protocol/host)

Option B: Nginx (explicit config)

Nginx works well if you prefer explicit files and predictable behavior.

At minimum you’ll configure:

- `server_name schedule.company.com;`

- TLS certs

- `proxy_pass http://calcom:3000;`

- websocket support (if required)

- security headers (HSTS, X-Frame-Options, etc.)

Don’t skip these proxy essentials

- **Set the correct public URL** in the app (e.g., `NEXTAUTH_URL=https://schedule.company.com`).

- Ensure the proxy passes `X-Forwarded-Proto` and `X-Forwarded-Host`.

- Redirect HTTP → HTTPS.

---

Step 4: Configure SSO (OIDC or SAML) for employee login

SSO is where self-hosted employee scheduling becomes “enterprise-ready.” With SSO, you can enforce:

- MFA

- conditional access

- account lifecycle policies

- group-based access

The simplest modern approach is **OIDC** (OpenID Connect), though **SAML** is still common in many enterprises.

What you’ll need from your IdP

Regardless of OIDC vs SAML, you’ll typically set:

- a redirect/callback URL (must match exactly)

- a client ID

- a client secret (for OIDC)

- issuer / discovery URL (for OIDC)

- metadata URL / certificate (for SAML)

Follow the official steps in [PRODUCT_LINK]Cal.com’s SSO configuration documentation[/PRODUCT_LINK] for the provider-specific fields and supported flows.

Implementation tips that prevent 80% of SSO issues

- **Make URLs consistent:** If your public URL is `https://schedule.company.com`, don’t configure callbacks for `http://` or a different subdomain.

- **Time sync matters:** Ensure your server has NTP enabled—clock drift can break token validation.

- **Decide on JIT vs pre-provisioning:**

- *Just-in-time provisioning* creates users at first login (faster rollout).

- *Pre-provisioning* can be cleaner if you want strict control.

- **Use groups/claims if available:** Map IdP groups (e.g., `HR`, `IT`, `Managers`) to access policies or onboarding flows.

---

Step 5: Lock down “employee-only” scheduling

If the goal is internal scheduling, consider defense-in-depth:

- **Require authentication** for scheduling pages

- **Restrict by email domain** (e.g., `@company.com`) where appropriate

- **IP allowlisting** at the reverse proxy (e.g., only VPN ranges)

- **Disable public sign-ups** if you don’t want external accounts

Even with SSO enabled, IP allowlisting is useful for sensitive environments.

---

Step 6: Validate calendar integrations (Google / Microsoft)

Employee scheduling only works if bookings reliably write to calendars.

Checklist:

- Confirm OAuth app credentials are configured for Google/Microsoft

- Ensure redirect URIs match your production domain

- Test with at least two users in different departments

- Verify time zones and working hours behavior

If you’re migrating from cloud scheduling to self-hosted, plan a pilot group first.

---

Step 7: Operational basics (backups, updates, monitoring)

Self-hosted scheduling is now a production service—treat it like one.

Backups

At minimum:

- nightly Postgres backups

- tested restore procedure

- secure offsite storage

Updates

- Pin versions where possible

- Roll out updates in a staging environment

- Keep a rollback path (previous image tag)

Monitoring

- uptime checks against `/` and login endpoints

- container health checks

- database disk usage

- reverse proxy certificate renewal alerts

For broader guidance on running it in your environment, the [PRODUCT_LINK]open-source scheduling platform Cal.com[/PRODUCT_LINK] resources on installation and self-hosting are worth bookmarking.

---

Common pitfalls (and quick fixes)

1) “Redirect URI mismatch” during SSO login

- Fix: Ensure the callback/redirect URL in the IdP matches *exactly* what the app expects.

2) App generates `http://` links behind HTTPS

- Fix: Confirm `NEXTAUTH_URL` is `https://...` and proxy forwards `X-Forwarded-Proto: https`.

3) Login works, but calendar sync fails

- Fix: Re-check Google/Microsoft OAuth redirect URIs and scopes. Verify tokens are stored and refreshed.

4) Random logouts or token errors

- Fix: Check server time sync (NTP). Verify cookie and domain settings.

---

Conclusion

Setting up self-hosted employee scheduling software is mostly about getting the fundamentals right: reliable Docker deployment, a reverse proxy with correct headers and TLS, and SSO that matches your organization’s identity policies.

Once those pieces are in place, you can iterate—tighten access rules, add monitoring, and standardize onboarding so teams can create scheduling links without IT intervention. If you want to go deeper on configuration details, start with the official self-host and SSO docs and adapt them to your proxy and identity provider.

More from Cal.com