BookStack on Kubernetes (in-cluster MySQL + external HAProxy)
Image used: lscr.io/linuxserver/bookstack:latest (community-maintained, actively updated, includes /status health endpoint that BookStack's own HA docs recommend probing).
1. Create the database in your existing MySQL
BookStack manages its own schema, so it just needs an empty database + a user with full rights on it. Run on your existing MySQL:
CREATE DATABASE bookstack CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'bookstack'@'%' IDENTIFIED BY 'CHANGE_ME_strong_password';
GRANT ALL PRIVILEGES ON bookstack.* TO 'bookstack'@'%';
FLUSH PRIVILEGES;
Use the same password in 01-secret.yaml (DB_PASSWORD).
2. Edit before applying
| File | What to change |
|---|---|
01-secret.yaml |
DB_PASSWORD to match what you set in MySQL |
02-configmap.yaml |
APP_URL (must match the host users/HAProxy hit), DB_HOST (your MySQL Service DNS name) |
03-pvc.yaml |
storageClassName — run kubectl get storageclass to see what's available |
06-ingress.yaml |
host, and ingressClassName if you're not on ingress-nginx |
DB_HOST resolution inside the cluster:
- Same namespace as MySQL's Service → just the Service name, e.g.
mysql - Different namespace →
mysql.<that-namespace>.svc.cluster.local
3. Apply
kubectl apply -f 01-namespace.yaml
kubectl apply -f 04-secret.yaml
kubectl apply -f 03-configmaps.yaml
kubectl apply -f 04-storage-class.yaml
kubectl apply -f 05-deployment.yaml
kubectl apply -f 06-service.yaml
Check it's healthy:
kubectl -n bookstack get pods
kubectl -n bookstack logs -f deploy/bookstack
kubectl -n bookstack port-forward svc/bookstack 8080:80
curl -i http://localhost:8080/status # should return 200
Default login is admin@admin.com / password — change it immediately after first login.
4. Point HAProxy
This setup gives you Proxy Service and Ingress Should point the DNS to the Proxy service. Because Bookstakc is running in diffrent Namespace, so HAProxy cannot cross-connect to diffrent namespace.
Create Proxy for Bookstack:
apiVersion: v1
kind: Service
metadata:
name: bookstack-proxy
namespace: default
spec:
type: ExternalName
externalName: bookstack.bookstack.svc.cluster.local
ports:
- port: 80
Example HAProxy backend:
I Hosts:
- bookstack.yourdomain.com
Add the below in rules:
- host: bookstack.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: bookstack-proxy
port:
number: 80