503 lines
14 KiB
YAML
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.36
|
|
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.36
|
|
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.1.12
|
|
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
|