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.contextand rundocker 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/datavolume, and archive your.envencryption key.
Next Steps
Connect calendars, video services, and payment gateways following our documentation — full environment configuration is detailed in the Environment Variables Reference.