ghost-on-kubernetes

Ghost on Kubernetes by SREDevOps.org - Deploy Ghost v6 on Kubernetes (k8s, k3s, etc) with our hardened distroless non root custom image.

View on GitHub

Ghost on Kubernetes (v6.x) by SREDevOps.Org

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).

Build Multiarch Image Size OpenSSF Scorecard Fork this repository Star this repository OpenSSF Best Practices Artifact Hub

Key Highlights: Security & Efficiency

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.

Enhanced Security

Example Security Reports:

Ghost Official Image Ghost on Kubernetes Image
Example scan for the Ghost Official Image: Docker Scout Report - Ghost Official Image Example of our Ghost on Kubernetes Image on Docker Hub: Docker Scout Report - Ghost on Kubernetes Image

Performance & Architecture

Deployment Architecture Overview

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.

Installation Instructions (Production)

Follow these steps to deploy Ghost on your Kubernetes cluster.

Prerequisites

  1. A functioning Kubernetes cluster (kubectl configured).
  2. A provisioned StorageClass (required for PVCs).

0. Clone (or fork) the Repository

## 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

1. Review and Configure

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).

2. Deployment Sequence

It is crucial to apply the manifests in the correct order to ensure dependency resolution (especially the database components).

  1. Create the Namespace:

     kubectl apply -f deploy/00-namespace.yaml
    
  2. 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
    
  3. Create Persistent Storage and Services:

    kubectl apply -f deploy/02-pvc.yaml  
    kubectl apply -f deploy/03-service.yaml
    
  4. Deploy MySQL Database (StatefulSet):

    # Wait for the MySQL PVC to be bound  
    kubectl apply -f deploy/05-mysql.yaml
    
  5. Deploy the Ghost Application (Deployment):

     # Wait for MySQL to be ready before starting
    kubectl apply -f deploy/06-ghost-deployment.yaml
    
  6. Expose Ghost with Ingress (Optional/Recommended):

     # Routes external traffic to the Ghost Service
     kubectl apply -f deploy/07-ingress.yaml
    

Your Ghost Blog is Deployed!

Congratulations! You have deployed a highly secure and scalable Ghost v6 instance on Kubernetes.

Accessing Without a Domain Name (Testing)

To preview the website without configuring Ingress or a TLD, you can use port forwarding:

  1. Temporarily configure both url and admin URLs in your config.production.json Secret to use http://localhost:2368/.
  2. Restart the Ghost pod(s) after updating the Secret.
  3. Run the port-forwarding command:
  kubectl port-forward -n ghost-on-kubernetes services ghost-on-kubernetes-service 2368:2368

Contributing

We welcome contributions from the community! Please check the CONTRIBUTING.md file for more information on how to contribute to this project.

License and Credits

Star History

Star History Chart