Add complete Bookstack deployment manifests

Added comprehensive Kubernetes deployment for Bookstack including:
- MySQL StatefulSet with PersistentVolumeClaim (10Gi encrypted storage)
- MySQL Service (ClusterIP)
- Bookstack Deployment with OIDC/Pocket-ID integration
- Bookstack Service (ClusterIP)
- Ingress with TLS certificate (bookstack.basicstack.de)

The deployment uses existing sealed secrets for MySQL credentials and
Bookstack OIDC client secret. Bookstack is configured with proper
health checks and resource limits.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
CTO Agent 2026-07-12 11:14:33 +00:00
parent 4149802477
commit 62c4398787

View file

@ -0,0 +1,281 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: bookstack
---
# MySQL PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data
namespace: bookstack
spec:
accessModes:
- ReadWriteOnce
storageClassName: hcloud-volumes-encrypted
resources:
requests:
storage: 10Gi
---
# MySQL StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: bookstack
spec:
serviceName: mysql
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql
key: mysql-root-password
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: mysql
key: mysql-database
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: mysql
key: mysql-user
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql
key: mysql-password
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "2Gi"
cpu: "1000m"
livenessProbe:
exec:
command:
- mysqladmin
- ping
- -h
- localhost
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
readinessProbe:
exec:
command:
- mysqladmin
- ping
- -h
- localhost
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-data
---
# MySQL Service
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: bookstack
spec:
type: ClusterIP
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
protocol: TCP
---
# Bookstack Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: bookstack
namespace: bookstack
spec:
replicas: 1
selector:
matchLabels:
app: bookstack
template:
metadata:
labels:
app: bookstack
spec:
initContainers:
- name: wait-for-mysql
image: busybox:latest
command:
- sh
- -c
- |
until nc -z mysql 3306; do
echo "Waiting for MySQL to be ready..."
sleep 2
done
echo "MySQL is ready!"
containers:
- name: bookstack
image: lscr.io/linuxserver/bookstack:latest
ports:
- containerPort: 80
name: http
env:
- name: PUID
value: "1000"
- name: PGID
value: "1000"
- name: TZ
value: "Europe/Berlin"
- name: APP_URL
value: "https://bookstack.basicstack.de"
- name: DB_HOST
value: "mysql"
- name: DB_PORT
value: "3306"
- name: DB_DATABASE
valueFrom:
secretKeyRef:
name: mysql
key: mysql-database
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: mysql
key: mysql-user
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql
key: mysql-password
# OIDC Configuration
- name: AUTH_METHOD
value: "oidc"
- name: AUTH_AUTO_INITIATE
value: "false"
- name: OIDC_NAME
value: "Pocket-ID"
- name: OIDC_DISPLAY_NAME_CLAIMS
value: "name"
- name: OIDC_CLIENT_ID
value: "bookstack"
- name: OIDC_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: bookstack-oidc
key: client-secret
- name: OIDC_ISSUER
value: "https://pocket-id.basicstack.de"
- name: OIDC_ISSUER_DISCOVER
value: "true"
- name: OIDC_PUBLIC_KEY
value: ""
- name: OIDC_AUTH_ENDPOINT
value: ""
- name: OIDC_TOKEN_ENDPOINT
value: ""
- name: OIDC_DUMP_USER_DETAILS
value: "false"
- name: OIDC_USER_TO_GROUPS
value: "true"
- name: OIDC_GROUPS_CLAIM
value: "groups"
- name: OIDC_REMOVE_FROM_GROUPS
value: "false"
volumeMounts:
- name: bookstack-config
mountPath: /config
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 60
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 30
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
volumes:
- name: bookstack-config
emptyDir: {}
---
# Bookstack Service
apiVersion: v1
kind: Service
metadata:
name: bookstack
namespace: bookstack
spec:
type: ClusterIP
selector:
app: bookstack
ports:
- port: 80
targetPort: 80
protocol: TCP
---
# Bookstack Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: bookstack
namespace: bookstack
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
ingressClassName: traefik
tls:
- hosts:
- bookstack.basicstack.de
secretName: bookstack-tls
rules:
- host: bookstack.basicstack.de
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: bookstack
port:
number: 80