Files
homelab-manifests/booking-system/booking.yaml
Renovate Bot 03b8af9b78
renovate/stability-days Updates have met minimum release age requirement
Update busybox Docker tag to v1.38
2026-06-06 00:04:43 +00:00

503 lines
14 KiB
YAML

---
# Cal.com - Open-source scheduling infrastructure
# https://cal.com/
#
# Features:
# - Stripe payment integration (native)
# - Configurable time slots
# - Cancellation policies with fees
# - Google Calendar sync
# - Email notifications
# - Multiple event types
# - Booking notes
# - White-label capable
#
# Prerequisites:
# 1. Create databases in shared PostgreSQL:
# kubectl exec -it postgresql-1 -n database-system -- psql -U postgres
#
# -- Main database
# CREATE DATABASE calcom;
# CREATE USER calcom WITH PASSWORD 'your-secure-password';
# GRANT ALL PRIVILEGES ON DATABASE calcom TO calcom;
# \c calcom
# GRANT ALL ON SCHEMA public TO calcom;
#
# 2. Set up Stripe account at https://stripe.com (Hungary supported)
# Get API keys from Dashboard -> Developers -> API keys
#
# 3. (Optional) Set up Google OAuth for calendar sync:
# https://console.cloud.google.com/apis/credentials
---
apiVersion: v1
kind: Namespace
metadata:
name: booking-system
labels:
app.kubernetes.io/name: calcom
---
# Redis for Cal.com (required for sessions, rate limiting, etc.)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: calcom-redis
namespace: booking-system
labels:
app.kubernetes.io/instance: calcom
app.kubernetes.io/name: redis
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: calcom-redis
namespace: booking-system
labels:
app.kubernetes.io/instance: calcom
app.kubernetes.io/name: redis
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/instance: calcom
app.kubernetes.io/name: redis
template:
metadata:
labels:
app.kubernetes.io/instance: calcom
app.kubernetes.io/name: redis
spec:
containers:
- name: redis
image: redis:7-alpine
imagePullPolicy: IfNotPresent
args:
- redis-server
- --appendonly
- "yes"
- --maxmemory
- "256mb"
- --maxmemory-policy
- "allkeys-lru"
ports:
- containerPort: 6379
name: redis
protocol: TCP
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 256Mi
volumeMounts:
- name: data
mountPath: /data
livenessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: data
persistentVolumeClaim:
claimName: calcom-redis
---
apiVersion: v1
kind: Service
metadata:
name: calcom-redis
namespace: booking-system
labels:
app.kubernetes.io/instance: calcom
app.kubernetes.io/name: redis
spec:
type: ClusterIP
ports:
- port: 6379
targetPort: redis
protocol: TCP
name: redis
selector:
app.kubernetes.io/instance: calcom
app.kubernetes.io/name: redis
---
# Cal.com Web Application
apiVersion: apps/v1
kind: Deployment
metadata:
name: calcom
namespace: booking-system
labels:
app.kubernetes.io/instance: calcom
app.kubernetes.io/name: calcom
app.kubernetes.io/version: "v6.1.12"
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/instance: calcom
app.kubernetes.io/name: calcom
template:
metadata:
labels:
app.kubernetes.io/instance: calcom
app.kubernetes.io/name: calcom
annotations:
match-regex.version-checker.io/calcom: '^v?\d+\.\d+\.\d+$'
spec:
initContainers:
# Wait for PostgreSQL
- name: wait-for-db
image: busybox:1.38
command:
- sh
- -c
- |
echo "Waiting for PostgreSQL..."
until nc -z postgresql-rw.database-system.svc.cluster.local 5432; do
echo "PostgreSQL not ready, waiting..."
sleep 2
done
echo "PostgreSQL is ready!"
# Wait for Redis
- name: wait-for-redis
image: busybox:1.38
command:
- sh
- -c
- |
echo "Waiting for Redis..."
until nc -z calcom-redis 6379; do
echo "Redis not ready, waiting..."
sleep 2
done
echo "Redis is ready!"
containers:
- name: calcom
image: docker.io/calcom/cal.com:v6.2.0
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- |
echo "Copying missing icons..."
# Copy to public/app-store for web serving
mkdir -p /calcom/apps/web/public/app-store/googlevideo
cp /calcom/packages/app-store/googlevideo/static/logo.webp /calcom/apps/web/public/app-store/googlevideo/logo.webp
echo "Copied googlevideo logo.webp to public folder"
echo "Starting Cal.com..."
cd /calcom
exec ./scripts/start.sh
env:
# License (empty for AGPL, set key for enterprise features)
- name: CALCOM_LICENSE_KEY
value: ""
# Telemetry
- name: NEXT_PUBLIC_IS_E2E
value: "false"
- name: CALCOM_TELEMETRY_DISABLED
value: "1"
# URLs
- name: NEXT_PUBLIC_WEBAPP_URL
value: "https://booking.dooplex.hu"
- name: NEXTAUTH_URL
value: "https://booking.dooplex.hu/api/auth"
- name: NEXT_PUBLIC_API_V2_URL
value: "https://booking.dooplex.hu/api/v2"
- name: NEXTAUTH_COOKIE_DOMAIN
value: ".dooplex.hu"
- name: NEXT_PUBLIC_EMBED_LIB_URL
value: "https://booking.dooplex.hu/embed/embed.js"
# Database - using shared PostgreSQL
- name: DB_USER
valueFrom:
secretKeyRef:
name: calcom-db
key: username
- name: DB_PASS
valueFrom:
secretKeyRef:
name: calcom-db
key: password
- name: DATABASE_URL
value: "postgresql://$(DB_USER):$(DB_PASS)@postgresql-rw.database-system.svc.cluster.local:5432/calcom"
- name: DATABASE_DIRECT_URL
value: "postgresql://$(DB_USER):$(DB_PASS)@postgresql-rw.database-system.svc.cluster.local:5432/calcom"
# Redis
- name: REDIS_URL
value: "redis://calcom-redis:6379"
# Auth secrets
- name: NEXTAUTH_SECRET
valueFrom:
secretKeyRef:
name: calcom-app
key: nextauth-secret
- name: CALENDSO_ENCRYPTION_KEY
valueFrom:
secretKeyRef:
name: calcom-app
key: calendso-encryption-key
# Email/SMTP
- name: EMAIL_FROM
valueFrom:
secretKeyRef:
name: smtp-credentials
key: from-address
- name: EMAIL_SERVER_HOST
valueFrom:
secretKeyRef:
name: smtp-credentials
key: host
- name: EMAIL_SERVER_PORT
valueFrom:
secretKeyRef:
name: smtp-credentials
key: port
- name: EMAIL_SERVER_USER
valueFrom:
secretKeyRef:
name: smtp-credentials
key: username
- name: EMAIL_SERVER_PASSWORD
valueFrom:
secretKeyRef:
name: smtp-credentials
key: password
# Stripe (optional - for payments)
- name: STRIPE_API_KEY
valueFrom:
secretKeyRef:
name: calcom-app
key: stripe-api-key
- name: STRIPE_WEBHOOK_SECRET
valueFrom:
secretKeyRef:
name: calcom-app
key: stripe-webhook-secret
- name: NEXT_PUBLIC_STRIPE_PUBLIC_KEY
valueFrom:
secretKeyRef:
name: calcom-app
key: next-public-stripe-key
- name: PAYMENT_FEE_PERCENTAGE
value: "0"
- name: PAYMENT_FEE_FIXED
value: "0"
# Google Calendar (optional)
- name: GOOGLE_API_CREDENTIALS
valueFrom:
secretKeyRef:
name: calcom-app
key: google-api-credentials
- name: GOOGLE_LOGIN_ENABLED
value: "false"
# Timezone
- name: TZ
value: "Europe/Budapest"
# Misc
- name: NODE_ENV
value: "production"
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: "0"
# Allow signup (set to "false" after creating your account if you want to restrict)
- name: NEXT_PUBLIC_DISABLE_SIGNUP
value: "false"
# CSP - needed for embedded iframes if you want to embed booking widget
- name: CSP_POLICY
value: ""
ports:
- containerPort: 3000
name: http
protocol: TCP
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: "2"
memory: 2Gi
livenessProbe:
tcpSocket:
port: 3000
initialDelaySeconds: 120
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 5
readinessProbe:
tcpSocket:
port: 3000
initialDelaySeconds: 60
periodSeconds: 15
timeoutSeconds: 10
failureThreshold: 3
startupProbe:
tcpSocket:
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 10
failureThreshold: 30
---
apiVersion: v1
kind: Service
metadata:
name: calcom
namespace: booking-system
labels:
app.kubernetes.io/instance: calcom
app.kubernetes.io/name: calcom
spec:
type: ClusterIP
ports:
- port: 3000
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/instance: calcom
app.kubernetes.io/name: calcom
---
# Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: calcom
namespace: booking-system
labels:
app.kubernetes.io/instance: calcom
app.kubernetes.io/name: calcom
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
external-dns.alpha.kubernetes.io/hostname: booking.dooplex.hu,booking.home
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "64m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
# Required for WebSocket connections (if using Cal.com video)
nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
nginx.ingress.kubernetes.io/proxy-set-headers: "booking-system/calcom-proxy-headers"
nginx.ingress.kubernetes.io/configuration-snippet: |
set $geo_allowed 0;
if ($remote_addr ~ "^192\.168\.") { set $geo_allowed 1; }
if ($remote_addr ~ "^10\.") { set $geo_allowed 1; }
if ($geoip2_country_code = "HU") { set $geo_allowed 1; }
if ($geo_allowed = 0) {
return 403 "Access restricted to Hungary";
}
spec:
ingressClassName: nginx-internal
rules:
- host: booking.dooplex.hu
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: calcom
port:
number: 3000
- host: booking.home
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: calcom
port:
number: 3000
tls:
- hosts:
- booking.dooplex.hu
secretName: calcom-tls
---
# ConfigMap for nginx proxy headers (WebSocket support)
apiVersion: v1
kind: ConfigMap
metadata:
name: calcom-proxy-headers
namespace: booking-system
data:
Upgrade: "$http_upgrade"
Connection: "upgrade"
---
# Optional: Prisma Studio for database management/first user creation
# Uncomment if you need direct database access
# Access via port-forward: kubectl port-forward svc/calcom-prisma-studio 5555:5555 -n booking-system
# ---
# apiVersion: apps/v1
# kind: Deployment
# metadata:
# name: calcom-prisma-studio
# namespace: booking-system
# labels:
# app.kubernetes.io/instance: calcom
# app.kubernetes.io/name: prisma-studio
# spec:
# replicas: 1
# selector:
# matchLabels:
# app.kubernetes.io/instance: calcom
# app.kubernetes.io/name: prisma-studio
# template:
# metadata:
# labels:
# app.kubernetes.io/instance: calcom
# app.kubernetes.io/name: prisma-studio
# spec:
# containers:
# - name: prisma-studio
# image: calcom/cal.com:v5.9.15
# command: ["npx", "prisma", "studio"]
# env:
# - name: DATABASE_URL
# value: "postgresql://calcom:YOUR_PASSWORD@postgresql-rw.database-system.svc.cluster.local:5432/calcom"
# ports:
# - containerPort: 5555
# name: http
# ---
# apiVersion: v1
# kind: Service
# metadata:
# name: calcom-prisma-studio
# namespace: booking-system
# spec:
# type: ClusterIP
# ports:
# - port: 5555
# targetPort: 5555
# selector:
# app.kubernetes.io/instance: calcom
# app.kubernetes.io/name: prisma-studio