Self-Hosting on Red Hat OpenShift
This guide covers running KoAkademy on Red Hat OpenShift Container Platform (OCP), Azure Red Hat OpenShift (ARO), or Red Hat OpenShift on AWS (ROSA).
OpenShift Architectural Considerations
Section titled “OpenShift Architectural Considerations”- Security Context Constraints (SCC):
- KoAkademy’s base container sets POSIX capabilities (
CAP_NET_BIND_SERVICE) on FrankenPHP and defaults to non-root UID1000:1000. - On OpenShift clusters with restricted SCCs, the pod will run with an arbitrary assigned UID from the project’s UID range. The container filesystem and
/tmp/opcache-file-cachepermissions support standard OpenShift non-root user execution.
- KoAkademy’s base container sets POSIX capabilities (
- OpenShift Routes:
- OpenShift uses
Routeobjects backed by HAProxy routers for ingress traffic and automatic TLS edge termination.
- OpenShift uses
- Storage:
- For multi-replica setups without S3/R2 object storage, ensure your StorageClass supports
ReadWriteMany(RWX) for/app/storage.
- For multi-replica setups without S3/R2 object storage, ensure your StorageClass supports
Step 1: Create Project & Secrets
Section titled “Step 1: Create Project & Secrets”Create a dedicated OpenShift project:
oc new-project koakademy --display-name="KoAkademy School System"Create OpenShift secrets:
oc create secret generic koakademy-secrets \ --from-literal=APP_KEY="base64:YOUR_32_BYTE_APP_KEY" \ --from-literal=DB_PASSWORD="YourSecurePostgresPassword" \ --from-literal=REDIS_PASSWORD="YourSecureRedisPassword"Step 2: Create ConfigMap
Section titled “Step 2: Create ConfigMap”apiVersion: v1kind: ConfigMapmetadata: name: koakademy-config namespace: koakademydata: APP_NAME: "KoAkademy" APP_ENV: "production" APP_DEBUG: "false" APP_URL: "https://koakademy.apps.cluster.example.com" OCTANE_SERVER: "frankenphp" AUTO_MIGRATE: "true" RUN_OPTIMIZE: "foreground"
# DB & Redis DB_CONNECTION: "pgsql" DB_HOST: "postgresql" DB_PORT: "5432" DB_DATABASE: "koakademy" DB_USERNAME: "koakademy" REDIS_HOST: "redis" REDIS_PORT: "6379"
# PDF Service GOTENBERG_URL: "http://gotenberg:3000" FILESYSTEM_DISK: "public"Apply the ConfigMap:
oc apply -f koakademy-configmap.yamlStep 3: Deploy Gotenberg, PostgreSQL & Redis
Section titled “Step 3: Deploy Gotenberg, PostgreSQL & Redis”You can use OpenShift Template or standard manifests:
apiVersion: apps/v1kind: Deploymentmetadata: name: gotenberg namespace: koakademyspec: replicas: 1 selector: matchLabels: app: gotenberg template: metadata: labels: app: gotenberg spec: containers: - name: gotenberg image: gotenberg/gotenberg:8 ports: - containerPort: 3000 resources: requests: cpu: 200m memory: 512Mi limits: cpu: 1000m memory: 1Gi---apiVersion: v1kind: Servicemetadata: name: gotenberg namespace: koakademyspec: selector: app: gotenberg ports: - port: 3000 targetPort: 3000Apply dependencies:
oc apply -f dependencies.yamlStep 4: Deploy KoAkademy Application
Section titled “Step 4: Deploy KoAkademy Application”apiVersion: apps/v1kind: Deploymentmetadata: name: koakademy namespace: koakademyspec: replicas: 2 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 selector: matchLabels: app: koakademy template: metadata: labels: app: koakademy spec: containers: - name: app image: ghcr.io/yukazakiri/koakademy:latest imagePullPolicy: IfNotPresent ports: - containerPort: 8000 name: http - containerPort: 2019 name: admin envFrom: - configMapRef: name: koakademy-config - secretRef: name: koakademy-secrets resources: requests: cpu: 500m memory: 1Gi limits: cpu: 2000m memory: 2Gi livenessProbe: httpGet: path: /up port: 8000 initialDelaySeconds: 30 periodSeconds: 15 readinessProbe: httpGet: path: /up port: 8000 initialDelaySeconds: 10 periodSeconds: 10---apiVersion: v1kind: Servicemetadata: name: koakademy namespace: koakademyspec: selector: app: koakademy ports: - name: http port: 8000 targetPort: 8000Apply application deployment:
oc apply -f koakademy-deployment.yamlStep 5: Expose OpenShift Route with TLS
Section titled “Step 5: Expose OpenShift Route with TLS”Create an edge-terminated OpenShift Route:
apiVersion: route.openshift.io/v1kind: Routemetadata: name: koakademy namespace: koakademy annotations: haproxy.router.openshift.io/timeout: "300s" haproxy.router.openshift.io/proxy-body-size: "100m"spec: host: koakademy.apps.cluster.example.com to: kind: Service name: koakademy weight: 100 port: targetPort: http tls: termination: edge insecureEdgeTerminationPolicy: RedirectApply Route:
oc apply -f koakademy-route.yamlStep 6: Verify Deployment
Section titled “Step 6: Verify Deployment”Check deployment status:
oc get pods -n koakademyoc logs -f deployment/koakademy -n koakademyOpen the OpenShift Route URL (https://koakademy.apps.cluster.example.com/setup) in your browser to complete installation.