Build a 100% Free Self-Hosted Booking System — No Calendly, No Subscription

Share

Build a 100% Free Self-Hosted Booking System — No Calendly, No Subscription

If you sell a system that runs on free software, your calendar shouldn't be the thing that costs you money. Calendly Business is ~$15/user/month. Cal.com self-hosted looks free — until you realize recipients get a 404 because it's only reachable on your laptop.

Here's the stack that actually works, for $0 in software: Rallly (open-source scheduling) behind a Cloudflare Tunnel on your own domain. This is exactly what ViewsAI runs on, and it's the DIY playbook our customers get.

Why self-hosted beats the SaaS calendar

  • Free forever — no seats, no tiers, no upgrade nagging
  • Your domain — bookings live at booking.yourdomain.com, which builds trust (nobody wants to book on someone's subdomain of a SaaS)
  • Private — your data, your database
  • Ownership — it's a component you can sell, teach, and hand over

Part 1 — Run Rallly (the booking app)

Rallly is a free, self-hosted scheduling/poll app: create a poll with time options, share the link, participants pick a slot. Two Docker services: the app and its PostgreSQL database.

# ~/docker/rallly/docker-compose.yml
version: '3.8'
services:
  rallly:
    image: lukevella/rallly:latest
    ports: ["3009:3000"]
    environment:
      DATABASE_URL: "postgresql://rallly_user:rallly_pass@rallly-db:5432/rallly"
      NEXTAUTH_SECRET: "openssl rand -hex 32"
      NEXTAUTH_URL: "http://localhost:3009"
      SECRET_PASSWORD: "openssl rand -hex 24"     # required in new Rallly
      NEXT_PUBLIC_BASE_URL: "https://booking.YOURDOMAIN.com"  # required
      SUPPORT_EMAIL: "[email protected]"         # required
      NEXT_PUBLIC_SELF_HOSTED: "true"
      NODE_ENV: "production"
      DATABASE_SSL: "false"
    depends_on: [rallly-db]
  rallly-db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: rallly_user
      POSTGRES_PASSWORD: rallly_pass
      POSTGRES_DB: rallly
    volumes: [rallly-db-data:/var/lib/postgresql/data]
volumes:
  rallly-db-data:

Gotchas we hit: newer Rallly crashes at boot with "Invalid environment variables" if you're missing SECRET_PASSWORD, NEXT_PUBLIC_BASE_URL, or SUPPORT_EMAIL. And the healthcheck path /api/health 404s — point it at / instead.

Part 2 — Expose it with a Cloudflare Tunnel

A Cloudflare Tunnel gives your localhost a public URL with zero inbound ports open. Fully scriptable via API with a token that has Tunnel:Edit.

# 1) create the tunnel
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT/cfd_tunnel" \
  -H "Authorization: Bearer $CF_TOKEN" -H "Content-Type: application/json" \
  -d '{"name":"viewsai-booking","config_src":"local"}'

# 2) route hostname → local app (ingress)
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT/cfd_tunnel/$TUNNEL_ID/configurations" \
  -H "Authorization: Bearer $CF_TOKEN" -H "Content-Type: application/json" \
  -d '{"config":{"ingress":[{"hostname":"booking.YOURDOMAIN.com","service":"http://localhost:3009"},{"service":"http_status:404"}]}}'

# 3) grab the tunnel token and run cloudflared with it
curl -H "Authorization: Bearer $CF_TOKEN" \
  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT/cfd_tunnel/$TUNNEL_ID/token"
# → save it, run: cloudflared tunnel run --token <token>  (as a launchd service on macOS)

Part 3 — The one manual step: DNS

Your tunnel token can't edit DNS, so add one CNAME in the Cloudflare dashboard:

Type: CNAME   Name: booking   Target: <TUNNEL_ID>.cfargotunnel.com   Proxy: Proxied (orange cloud)

Part 4 — Verify and go

dig booking.YOURDOMAIN.com
curl https://booking.YOURDOMAIN.com   # 200 → Rallly loads

Then drop the link into your outbound emails. In the ViewsAI pipeline, the CTA lives in the email template — instead of "book a call" with no destination, every email can carry a real, clickable booking link.

The money math

Calendly Business$15/user/mo
Cal.com cloudstarts at $20/mo
This stack$0 software + your domain

The only real costs in the whole ViewsAI system are the email domain and sending mailboxes. Everything else — scheduling, CRM, automation, lead pipeline — runs on free, self-hosted, open-source software you own.

Want this whole system? It's part of the ViewsAI stack — recruiting AI, outbound automation, and the free infrastructure that runs it all.