ghost-on-kubernetes
ghost-on-kubernetes copied to clipboard
Ghost 5 Self hosted on Kubernetes (@TryGhost) k3s, GKE, AKS, etc, production-ready, with our hardened distroless non root container, amd64 and arm64 support
Ghost on Kubernetes by SREDevOps
This repo deploys a clean Ghost CMS v5.xx.x from @TryGhost (upstream) in Kubernetes, as a Deployment using our custom image, based on the "official" Ghost 5 debian image, but with some modifications:
Recent Changes
We've made some significant updates to improve the security and efficiency of our Ghost deployment on Kubernetes:
-
Distroless Base Image: The Ghost container image is now based on a Distroless base image. This reduces the attack surface by eliminating unnecessary components like shell, package managers, and utilities that aren't needed for our application to run. The image is also built using a multi-stage build process, which makes the final image smaller and more secure.
-
MySQL StatefulSet: We've changed the MySQL deployment back to a StatefulSet. This provides stable network identifiers and persistent storage, which are important for databases like MySQL that need to maintain state.
-
Non-Root User: By default, the Ghost container now runs as a non-root user. This is a best practice for security, as it reduces the potential damage if the container is compromised. The Ghost application is started with an init container, which performs necessary setup tasks before the main Ghost container starts.
Please refer to the updated deploy/06-ghost-deployment.yaml file for the implementation details of these changes.
Features
- ARM64 support!
- We use the official Node 18 Hydrogen bookworm image as build environment.
- Introduced a multi-stage build to compile the image.
- distroless node 18 debian 12 as the final image.
- Removed gosu, we use the default user node.
- ~~Modified the entrypoint to run as node user, so we can run the pod as non-root.~~ DELETED ENTRYPOINT
- Update every possible dependencies in the base image to minimize vulnerabilities.
- We use the latest version of Ghost 5 (at the time of build the image)
*Note for ARM users 📌: ARM64 supported! ~~At this time, we dropped support for arm64 and armv7l (link to discussion), but we will add it back soon. Pull requests are welcome._~~ *
Star History
Installation
1. Clone 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
# Create a new branch for your changes in deattach mode (optional but recommended).
git checkout -b my-branch --no-track --detach
2. Review the default values and make changes as per your requirements, if any into the following files
-
deploy/00-namespace.yaml
-
deploy/01-secrets.yaml
apiVersion: v1 kind: Secret metadata: name: mysql-ghost-k8s namespace: ghost-k8s type: Opaque stringData: MYSQL_DATABASE: mysql-db-name # Same as in deploy/04-config.production.yaml MYSQL_USER: mysql-db-user # Same as in deploy/04-config.production.yaml MYSQL_PASSWORD: mysql-db-password # Same as in deploy/04-config.production.yaml MYSQL_ROOT_PASSWORD: mysql-db-root-password # Same as in deploy/04-config.production.yaml
-
deploy/02-pvc.yaml # Change the storageClassName as per your requirements
-
deploy/03-services.yaml # Change the hosts as per your requirements
-
deploy/04-config.production.yaml # Change values according to secrets and services
-
deploy/05-mysql.yaml # Change values according to secrets and services
-
deploy/06-ghost-deployment.yaml # Change values according to secrets and services
-
deploy/07-ingress.yaml # Optional
3. Apply your manifests
# Create the namespace
kubectl apply -f deploy/00-namespace.yaml
# Create the secrets
kubectl apply -f deploy/01-secrets.yaml
# Create the persistent volume
kubectl apply -f deploy/02-pvc.yaml
# Create services
kubectl apply -f deploy/03-service.yaml
# Create Ghost config
kubectl apply -f deploy/04-config.production.yaml
# Create the MySQL database
kubectl apply -f deploy/05-mysql.yaml
# Create the Ghost deployment
kubectl apply -f deploy/06-ghost-deployment.yaml
# Create the Ghost Ingrees
kubectl apply -f deploy/07-ghost-ingress.yaml
4. Access your Ghost CMS
# Get the ingress IP address
kubectl get ing -n ghost-k8s -o wide
# Or create a port-forward to access the Ghost CMS
kubectl port-forward -n ghost-k8s svc/ghost-k8s 2368:2368