Self-Host Your Scheduling: Cal.com on Ubuntu with a Pangolin VPS Proxy

Self-Host Your Scheduling: Cal.com on Ubuntu with a Pangolin VPS Proxy (Revised)

Want to take control of your scheduling with a private, open-source alternative to Calendly? This guide will walk you through installing Cal.com on an Ubuntu Virtual Machine (VM). To make it securely accessible from anywhere, we’ll use Pangolin on a Virtual Private Server (VPS) and the Newt tunnel client to create a secure link, all managed cleanly within a single file.

This revised guide includes a crucial fix to prevent common performance issues when accessing your instance over the internet.

Let’s get started!


Part 1: Initial Setup on Your Ubuntu VM

First, we need to prepare your Ubuntu environment by installing Docker and Docker Compose.

Step 1.1: Install Docker & Docker Compose

  1. Install Docker. The official script is the simplest method:

    curl -fsSL https://get.docker.com -o get-docker.sh
    sudo sh get-docker.sh
    
  2. Add your user to the Docker group. This avoids having to type sudo for every Docker command.

    sudo usermod -aG docker ${USER}
    

    Crucially, you must log out and log back in for this change to take effect.

  3. Install the Docker Compose Plugin. This tool lets you manage multi-service applications like Cal.com with ease.

    sudo apt-get update
    sudo apt-get install docker-compose-plugin -y
    

Part 2: Configuring Cal.com and Newt

Now we’ll create the configuration files that tell Docker how to run Cal.com, its database, and the Newt tunnel client.

Step 2.1: Create Your Project Directory and Files

  1. Create a dedicated folder for your Cal.com setup.

    mkdir ~/calcom-setup
    cd ~/calcom-setup
    
  2. Inside this directory, create two files: docker-compose.yml for the service definitions and .env for your secrets and configuration variables.

    touch docker-compose.yml
    touch .env
    

Step 2.2: Configure the Environment Variables (.env file)

  1. Open the .env file with a text editor.

    nano .env
    
  2. Copy and paste the following configuration. This file holds all your secrets and settings.

    # --- Cal.com Configuration ---
    # !! IMPORTANT: Set your public Cal.com URL here. This must be the final address you will use.
    NEXT_PUBLIC_WEBAPP_URL=https://meet.myurl.co.uk
    
    # !! PREVENT PERFORMANCE ISSUES: This line is crucial.
    # It tells the Cal.com backend to use its local address for internal API calls,
    # preventing the "CLIENT_FETCH_ERROR" that causes slowness over a tunnel.
    NEXTAUTH_URL=http://localhost:3000/api/auth
    
    # !! IMPORTANT: Generate unique, random secrets for these keys.
    # Use `openssl rand -base64 32` in your terminal to generate each one.
    NEXTAUTH_SECRET=YOUR_UNIQUE_NEXTAUTH_SECRET
    CALENDSO_ENCRYPTION_KEY=YOUR_UNIQUE_ENCRYPTION_KEY
    
    # Agree to the license terms
    NEXT_PUBLIC_LICENSE_CONSENT=agree
    
    # Database Credentials (can leave as default)
    POSTGRES_USER=unicorn_user
    POSTGRES_PASSWORD=magical_password
    POSTGRES_DB=calendso
    DATABASE_HOST=database:5432
    DATABASE_URL=postgresql://unicorn_user:magical_password@database:5432/calendso
    DATABASE_DIRECT_URL=postgresql://unicorn_user:magical_password@database:5432/calendso
    
    # --- Newt Tunnel Client Configuration ---
    # !! IMPORTANT: These values will come from your Pangolin dashboard in the next part.
    # Leave them blank for now.
    PANGOLIN_ENDPOINT=https://your-pangolin-domain.com
    NEWT_ID=
    NEWT_SECRET=
    
  3. Update the placeholder values:

    • https://meet.myurl.co.uk: Change this to the final, public URL you will use.
    • YOUR_UNIQUE_NEXTAUTH_SECRET: Replace with a long, random string.
    • YOUR_UNIQUE_ENCRYPTION_KEY: Replace with another long, random string.
    • https://your-pangolin-domain.com: Change this to the domain of your Pangolin VPS instance.
  4. Save the file and exit (Ctrl+X, then Y, then Enter).

Step 2.3: Define the Services (docker-compose.yml file)

  1. Now, open the docker-compose.yml file.

    nano docker-compose.yml
    
  2. Copy and paste the following service definitions. This sets up the Cal.com app, the PostgreSQL database it needs, and the Newt client.

    version: '3.8'
    
    services:
      database:
        image: postgres:15
        container_name: calcom-db
        restart: always
        volumes:
          - database-data:/var/lib/postgresql/data
        env_file: .env
        networks:
          - calcom-stack
    
      calcom:
        image: calcom/cal.com:latest
        container_name: calcom-app
        restart: always
        ports:
          # We only expose the port to the local machine, not the public internet.
          - "127.0.0.1:3000:3000"
        env_file: .env
        depends_on:
          - database
        networks:
          - calcom-stack
    
      newt:
        image: fosrl/newt:latest
        container_name: calcom-newt
        restart: unless-stopped
        env_file: .env
        depends_on:
          - calcom
        # This allows Newt to talk to the other containers on the same network.
        networks:
          - calcom-stack
    
    volumes:
      database-data:
    
    networks:
      calcom-stack:
        driver: bridge
    
  3. Save and exit the editor.


Part 3: Connecting to Pangolin

Now, let’s get the credentials from your Pangolin VPS to allow the newt container to connect.

  1. In your Pangolin dashboard, navigate to Sites and click Add Site.
  2. Give it a name (e.g., Ubuntu VM Calcom) and click Create Site.
  3. Pangolin will immediately display the credentials for this site. You will see a Newt ID and a Newt Secret.
  4. Back on your Ubuntu VM, edit your .env file one last time.
    nano .env
    
  5. Carefully copy the Newt ID and Newt Secret from the Pangolin dashboard and paste them into the NEWT_ID and NEWT_SECRET variables.
  6. Save and close the file.

Part 4: Launching and Exposing Cal.com

With the configuration complete, it’s time to bring everything online.

Step 4.1: Launch the Services

  1. Make sure you are in your project directory (~/calcom-setup).
  2. Run the following command to download the images and start all three containers.
    docker compose up -d
    
    This may take several minutes the first time as Docker downloads the Cal.com and PostgreSQL images. The -d flag runs it in the background.

Step 4.2: Expose the Cal.com App in Pangolin

  1. In your Pangolin dashboard, go to Resources and click Add Resource.
  2. Fill out the form:
    • Name: Cal.com App
    • Site: Select the site you just created (e.g., Ubuntu VM Calcom).
    • Resource Type: HTTP Resource.
    • HTTP Settings > Sub-domain: meet (or whatever matches the NEXT_PUBLIC_WEBAPP_URL you set).
  3. Click Create Resource.
  4. On the next page, under Target Configuration:
    • Method: http
    • Host: Use the container name of your Cal.com app: calcom-app. Because newt is on the same Docker network, it can find the app by its name.
    • Port: 3000
  5. Click Add Target and then Save Targets.

Part 5: Final Setup

You’re done! Open a web browser and navigate to the public URL you configured (e.g., https://meet.myurl.co.uk). Cal.com’s initial setup wizard should greet you, allowing you to create your first user account. With the added configuration, your instance should now be fast and stable.

Enjoy your new, private, self-hosted scheduling platform!