A modular Helm chart for deploying CTFd (Capture The Flag framework) with MySQL and Redis dependencies on Kubernetes with OpenShift compatibility. This chart uses a library chart pattern for modular, reusable components.
- Kubernetes 1.16+
- Helm 3.2.0+
- OpenShift 4.x (optional, but the chart is designed with OpenShift security constraints in mind)
- Modular Architecture: Uses Helm library charts for MySQL and Redis components for better maintainability and reusability
- OpenShift Compatible: Runs with non-root security contexts and proper SELinux contexts
- Flexible Database Options: Choose between library chart MySQL, Bitnami MySQL subchart, or external database
- Flexible Cache Options: Choose between library chart Redis, Bitnami Redis subchart, or external cache
- Persistent Storage: Configurable persistent volumes for uploads, logs, and database/cache data
- Security Hardened: Follows security best practices with non-root containers and minimal privileges
- Single Replica Default: MySQL and Redis run as single replicas by default for resource efficiency
- Composable Components: Library charts can be reused in other Helm applications
- Clone or download this chart
- Build dependencies:
cd ctfd-helm
helm dependency build- Install the chart:
helm install my-ctfd ./ctfd-helm- Get the application URL:
kubectl get ingress
# OR if using port-forward
kubectl port-forward svc/my-ctfd 8080:80- Access CTFd at
http://localhost:8080and complete the setup wizard
The following table lists the configurable parameters and their default values:
| Parameter | Description | Default |
|---|---|---|
ctfd.replicaCount |
Number of CTFd replicas | 1 |
ctfd.image.repository |
CTFd image repository | ctfd/ctfd |
ctfd.image.tag |
CTFd image tag | "" (uses Chart.AppVersion) |
ctfd.secretKey |
CTFd secret key | "change-me-in-production" |
ctfd.service.type |
Kubernetes service type | ClusterIP |
ctfd.service.port |
Service port | 80 |
The chart provides three database options:
internalMySQL:
enabled: true
mysql-library:
mysql:
enabled: true
database: "ctfd"
username: "ctfd"
password: "ctfd-password"mysql:
enabled: true
internalMySQL:
enabled: falsemysql:
enabled: false
internalMySQL:
enabled: false
externalDatabase:
connectionString: "mysql+pymysql://user:pass@host:3306/db"The chart provides three cache options:
internalRedis:
enabled: true
redis-library:
redis:
enabled: trueredis:
enabled: true
internalRedis:
enabled: falseredis:
enabled: false
internalRedis:
enabled: false
externalRedis:
connectionString: "redis://host:6379/0"The chart is pre-configured for OpenShift with non-root security contexts and includes an OpenShift Route for external access:
security:
fsGroup: 1000860000
runAsGroup: 1000860000
runAsUser: 1000860000
# OpenShift Route (enabled by default)
route:
enabled: true
tls:
enabled: true
termination: edge
insecureEdgeTerminationPolicy: Redirectroute:
enabled: true
host: "ctfd.apps.cluster.example.com" # Optional custom hostname
tls:
enabled: true
termination: edge # edge, passthrough, or reencryptroute:
enabled: false
ingress:
enabled: true
hosts:
- host: ctfd.example.com
paths:
- path: /
pathType: PrefixConfigure persistent storage for CTFd uploads and logs:
ctfd:
persistence:
uploads:
enabled: true
size: 10Gi
storageClass: ""
logs:
enabled: false
size: 5Gi
storageClass: ""helm install ctfd ./ctfd-helmhelm install ctfd ./ctfd-helm \
--set ctfd.secretKey="my-super-secret-key" \
--set ctfd.persistence.uploads.size=20Gihelm install ctfd ./ctfd-helm \
--set mysql.enabled=false \
--set internalMySQL.enabled=false \
--set externalDatabase.connectionString="mysql+pymysql://user:pass@host:3306/db"helm install ctfd ./ctfd-helm \
--namespace ctfd \
--set route.host="ctfd.apps.mycluster.example.com" \
--set ctfd.secretKey="my-production-secret-key"helm install ctfd ./ctfd-helm \
--set route.enabled=false \
--set ingress.enabled=true \
--set ingress.hosts[0].host="ctfd.example.com"To upgrade the CTFd deployment:
helm upgrade ctfd ./ctfd-helmTo uninstall/delete the CTFd deployment:
helm uninstall ctfd- Change Default Passwords: Always change the default database passwords and secret key in production
- Use External Secrets: Consider using Kubernetes secrets or external secret management for sensitive data
- Network Policies: Implement network policies to restrict traffic between pods
- HTTPS: Configure ingress with TLS certificates for production deployments
If you encounter pod security issues, ensure your project has the appropriate Security Context Constraints (SCC):
oc adm policy add-scc-to-user anyuid -z defaultCheck the database connectivity:
kubectl logs deployment/ctfd-mysql
kubectl logs deployment/ctfdVerify persistent volume claims:
kubectl get pvc
kubectl describe pvc ctfd-uploads- Fork the repository
- Create a feature branch
- Commit your changes
- Push to the branch
- Create a Pull Request
This chart uses Helm library charts for modularity and reusability:
ctfd-helm/
├── Chart.yaml # Main chart metadata
├── values.yaml # Main chart values
├── templates/ # CTFd application templates
│ ├── ctfd-deployment.yaml
│ ├── ctfd-service.yaml
│ └── ...
└── charts/ # Library charts
├── mysql-library/ # MySQL library chart
│ ├── Chart.yaml # type: library
│ ├── values.yaml
│ └── templates/
│ ├── _helpers.tpl # MySQL template functions
│ ├── deployment.yaml
│ ├── service.yaml
│ └── ...
└── redis-library/ # Redis library chart
├── Chart.yaml # type: library
├── values.yaml
└── templates/
├── _helpers.tpl # Redis template functions
├── deployment.yaml
├── service.yaml
└── ...
- Modularity: MySQL and Redis components are self-contained and reusable
- Maintainability: Each library chart can be developed and tested independently
- Flexibility: Easy to switch between internal library charts and external subcharts
- Reusability: Library charts can be used in other Helm applications
- Version Control: Each component can have its own versioning strategy
Library charts are referenced in the main Chart.yaml as local dependencies:
dependencies:
- name: mysql-library
version: "0.1.0"
repository: "file://./charts/mysql-library"
condition: internalMySQL.enabled
- name: redis-library
version: "0.1.0"
repository: "file://./charts/redis-library"
condition: internalRedis.enabledThe main chart's helpers reference library chart templates:
{{- define "ctfd.mysql.connectionString" -}}
{{- if .Values.internalMySQL.enabled }}
{{- include "mysql-library.connectionString" . }}
{{- end }}
{{- end }}This chart is licensed under the MIT License.