Want complete certainty that your scheduling data and appointments never leave your own infrastructure? LockMyCal is built on open-source foundations and deploys effortlessly on your own server — VPS, homelab, or corporate intranet. In this guide, we walk through deployment via Docker Compose.

Why Self-Host

  • Total Data Sovereignty — appointments, client records, and access tokens remain strictly on your machines.
  • No Tier Limitations — all premium features including webhooks, analytics, and Stripe payments are unlocked.
  • Local Network Integration — connect internal Exchange or Nextcloud instances, and private Jitsi video servers.

Keep in mind that backups, updates, and server security remain under your management.

Prerequisites

  • A Linux server with Docker and Docker Compose (a modest VPS with 1 vCPU and 1 GB RAM is sufficient).
  • A Domain or Subdomain with DNS pointing to your server.
  • An SMTP server or transactional email service (Postmark, SendGrid, Mailgun) for dispatching confirmations.

1. Docker Compose Configuration

You can build the image directly from source via Docker Compose without manually cloning the repository:

services:
  app:
    build:
      context: https://github.com/lockmycal/lockmycal.git#main
      dockerfile: Dockerfile.docker
    image: lockmycal:main
    restart: unless-stopped
    env_file:
      - .env
    environment:
      DATABASE_HOST: db
      DATABASE_PORT: 5432
    ports:
      - "127.0.0.1:4000:4000"
    depends_on:
      db:
        condition: service_healthy
    volumes:
      - app_data:/app/data

  db:
    image: postgres:17-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: lockmycal
      POSTGRES_USER: lockmycal
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U lockmycal -d lockmycal"]
      interval: 5s
      timeout: 5s
      retries: 12

volumes:
  app_data:
  pgdata:

You can target a specific git tag after #. The public repository is hosted at github.com/lockmycal/lockmycal.

2. Environment Variables (.env)

Create a .env file alongside docker-compose.yml:

SECRET_KEY_BASE=...        # openssl rand -base64 64
DATA_ENCRYPTION_KEY=...    # openssl rand -base64 48
PHX_HOST=schedule.yourdomain.com
POSTGRES_USER=lockmycal
POSTGRES_DB=lockmycal
POSTGRES_PASSWORD=strong_database_password

EMAIL_ADAPTER=smtp
EMAIL_FROM_ADDRESS=notifications@yourdomain.com
SMTP_HOST=smtp.yourdomain.com
SMTP_PORT=587
SMTP_USERNAME=notifications@yourdomain.com
SMTP_PASSWORD=...

DATA_ENCRYPTION_KEY encrypts integration credentials in the database — never lose or modify it after initial setup. Values in .env are read literally without variable expansion.

3. Starting the Service

docker compose up -d --build
docker compose logs -f app

Initial image build takes a couple of minutes. Database migrations execute automatically during startup. The first user who registers through the web interface becomes the system administrator.

4. Reverse Proxy & HTTPS

Place LockMyCal behind a reverse proxy (Caddy, Nginx, Traefik) terminating TLS. Ensure WebSocket forwarding is enabled — LockMyCal relies on real-time Phoenix LiveView connections. Ready-to-use proxy configs are available in our documentation.

5. Updates & Maintenance

  • Updates: Update the git ref in build.context and run docker compose build --pull app && docker compose up -d. Review breaking changes documentation prior to updates.
  • Backups: Schedule regular database dumps (pg_dump), backup the /app/data volume, and archive your .env encryption key.

Next Steps

Connect calendars, video services, and payment gateways following our documentation — full environment configuration is detailed in the Environment Variables Reference.