GudCalGudCal
Docs
Self-Hosting

Self-Hosting

Deploy GudCal on your own infrastructure.

GudCal is designed to be self-hosted. Run it on your own server, VPS, or container platform with full control over your data.

Prerequisites

  • Node.js 18.17 or later
  • PostgreSQL 14 or later (Neon, Supabase, or self-hosted)
  • pnpm package manager

Quick Start

  1. Clone the repository:
git clone https://github.com/cavewebs/gudcal.git
cd gudcal
  1. Install dependencies:
pnpm install
  1. Copy the environment file and configure it:
cp .env.example .env.local
  1. Set up the database:
pnpm prisma generate
pnpm prisma db push
  1. Start the application:
pnpm build
pnpm start

Environment Variables

These are the required environment variables for self-hosting:

VariableDescription
DATABASE_URLPostgreSQL connection string
NEXTAUTH_SECRETRandom secret for session encryption
NEXTAUTH_URLYour deployment URL (e.g. https://cal.example.com)
NEXT_PUBLIC_APP_URLSame as NEXTAUTH_URL
GOOGLE_CLIENT_IDGoogle OAuth client ID
GOOGLE_CLIENT_SECRETGoogle OAuth client secret
ENCRYPTION_KEY32-byte hex key for encrypting calendar tokens

Optional Variables

VariableDescription
RESEND_API_KEYFor sending email notifications
STRIPE_*For billing (not needed for self-hosted free usage)
GOOGLE_CALENDAR_CLIENT_IDFor Google Calendar integration
GOOGLE_CALENDAR_CLIENT_SECRETFor Google Calendar integration
CRON_SECRETSecret for the reminder cron endpoint
NEXT_PUBLIC_IS_SELF_HOSTEDSet to true to disable cloud-only features

Self-Hosted vs Cloud

When NEXT_PUBLIC_IS_SELF_HOSTED=true, the following features are disabled:

  • Analytics dashboard
  • MCP server (Team plan feature)
  • AI features
  • Custom domains

All core scheduling features work identically in both modes.

Generating an Encryption Key

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Reverse Proxy

If you run GudCal behind a reverse proxy (nginx, Caddy, etc.), make sure to:

  • Forward the Host header
  • Set X-Forwarded-Proto to https
  • Set X-Forwarded-For to the client IP
  • Configure WebSocket passthrough if needed