Deploy the leading open-source publishing platform, Ghost, on Kubernetes with maximum security and efficiency using a hardened, multi-arch container image.
Maintained by SREDevOps.org: SRE, DevOps, Linux, Ethical Hacking, AI, ML, Open Source, Cloud Native, Platform Engineering in English, Español, and Portugués (Brasil).
This repository implements Ghost CMS v6.xx.x from @TryGhost (Official) on Kubernetes with a custom built image, which delivers significant improvements for production use and security features in Kubernetes.
Example Security Reports:
| Ghost Official Image | Ghost on Kubernetes Image |
|---|---|
Example scan for the Ghost Official Image: ![]() |
Example of our Ghost on Kubernetes Image on Docker Hub: ![]() |
This project provides complete Kubernetes manifest files (deploy/) to run a production-ready Ghost instance backed by a MySQL database.
| Resource | Components | Details |
|---|---|---|
| Namespace | ghost-on-kubernetes | Provides logical isolation for all components. (File: 00-namespace.yaml) |
| StatefulSet | ghost-on-kubernetes-mysql | Manages the MySQL 8 database, ensuring stable networking and persistent storage. (File: 05-mysql.yaml) |
| Deployment | ghost-on-kubernetes | Manages the Ghost v6 application pods. (File: 06-ghost-deployment.yaml) |
| Services | ghost-on-kubernetes-service, ghost-on-kubernetes-mysql-service | Exposes Ghost (2368) and MySQL (3306) internally within the cluster. (File: 03-service.yaml) |
| PersistentVolumeClaims (PVC) | k8s-ghost-content, ghost-on-kubernetes-mysql-pvc | Requests persistent storage for Ghost content (themes, images) and MySQL data. (File: 02-pvc.yaml) |
| Secrets | ghost-config-prod, ghost-on-kubernetes-mysql-env, tls-secret | Securely stores Ghost configuration, database credentials, and TLS certificates (optional). (Files: 01-mysql-config.yaml, 04-ghost-config.yaml, 01-tls.yaml) |
| Ingress | ghost-on-kubernetes-ingress | Exposes the Ghost application to the outside world via HTTP/HTTPS (requires a TLD). (File: 07-ingress.yaml) |
Note: You can host multiple Ghost instances by replacing the Namespace specification in each manifest file.
Follow these steps to deploy Ghost on your Kubernetes cluster.
## Clone the repository
git clone https://github.com/sredevopsorg/ghost-on-kubernetes.git --depth 1 --branch main --single-branch --no-tags
## Change directory
cd ghost-on-kubernetes
Review the example configuration files and modify the manifests in the deploy/ folder to suit your environment (e.g., storage class, domain name, secret values).
It is crucial to apply the manifests in the correct order to ensure dependency resolution (especially the database components).
Create the Namespace:
kubectl apply -f deploy/00-namespace.yaml
Create Secrets (Credentials and Config):
# IMPORTANT: Customize these secrets before applying
kubectl apply -f deploy/01-mysql-config.yaml
kubectl apply -f deploy/04-ghost-config.yaml
kubectl apply -f deploy/01-tls.yaml
Create Persistent Storage and Services:
kubectl apply -f deploy/02-pvc.yaml
kubectl apply -f deploy/03-service.yaml
Deploy MySQL Database (StatefulSet):
# Wait for the MySQL PVC to be bound
kubectl apply -f deploy/05-mysql.yaml
Deploy the Ghost Application (Deployment):
# Wait for MySQL to be ready before starting
kubectl apply -f deploy/06-ghost-deployment.yaml
Expose Ghost with Ingress (Optional/Recommended):
# Routes external traffic to the Ghost Service
kubectl apply -f deploy/07-ingress.yaml
Congratulations! You have deployed a highly secure and scalable Ghost v6 instance on Kubernetes.
To preview the website without configuring Ingress or a TLD, you can use port forwarding:
http://localhost:2368/. kubectl port-forward -n ghost-on-kubernetes services ghost-on-kubernetes-service 2368:2368
We welcome contributions from the community! Please check the CONTRIBUTING.md file for more information on how to contribute to this project.