This is a Helm chart for deploying GZCTF on Kubernetes. It deploys the official GZCTF Docker image. Optional HA/Autoscaling (experimental) + postgresql or postgresql-ha + Garnet or redis-ha + RustFS S3. Also supports using external Postgresql/Redis/S3.
helm repo add gzctf https://gzctf.github.io/helmThis installs a single-node gzctf with ReadWriteOnce PVC and a single replica of postgresql (statefulset). appsettings has the default configurations
helm install gzctf gzctf/gzctf \
--set env[0].name=GZCTF_ADMIN_PASSWORD \
--set env[0].value=xxxIf you need to install garnet or redis-ha and/or postgresql-ha and/or RustFS. Also if you need to set passwords/xorkey
helm install gzctf gzctf/gzctf -f values.yamlBuild helm dependencies before installing the chart.
helm dependency updateSet the values in values.yaml to your desired configuration. Then install
helm install release-name . -f values.yaml --create-namespace --namespace gzctfhelm uninstall release-name --namespace gzctf- multi-node deployment is still experimental (needs extensive testing)
- gzctf support for s3 bucket is experimental (single-node deployment doesnt need s3 bucket)
- garnet/redis is not needed for single-node deployment
minio stopped releasing community edition binaries and docker images minio/minio/issues/21647We replaced it with RustFS instead.- postgresql-ha bitnami image is legacy/deprecated
gzctf:
image:
tag: "latest"appsettings: | { "AllowedHosts": "*", "ConnectionStrings": { "Database": "Host=gzctf-db:5432;Database=gzctf;Username=postgres;Password=gzctf", "RedisCache": "gzctf-garnet:6379,password=gzctf", "Storage": "minio.s3://accessKey=...;secretKey=...;bucket=...;endpoint=...;forcePathStyle=true" }, ... } # content of appsettings.jsonenv:
- name: LC_ALLvalue: "en_US.UTF-8"
- name: GZCTF_ADMIN_PASSWORDvalue: "astrongpassword"autoscaling:
enabled: false # (set to true for multi-node. still experimental)minReplicas: 2maxReplicas: 5targetCPUUtilizationPercentage: 80targetMemoryUtilizationPercentage: 80garnet:
enabled: trueconfig:
garnetConf: | { "AuthenticationMode": "Password", "Password": "gzctf" # needs to be consistent with the RedisCache password in appsettings.json }redis-ha:
enabled: false # (Can be enabled instead of garnet. Configure your appsettings to connect to release-name-redis-ha-haproxy )postgresql:
enabled: trueenv:
- name: POSTGRES_PASSWORDvalue: gzctf # needs to be consistent with the database password in appsettings.jsonpersistence:
enabled: truesize: 2Girustfs:
enabled: truesecret:
rustfs:
access_key: "gzctf"secret_key: "gzctf"# needs to be consistent with the storage configurations in appsettings.jsonstorageclass:
dataStorageSize: 10GiGZCTF:
image:
tag: "latest"appsettings: | { "AllowedHosts": "*", "ConnectionStrings": { "Database": "Host=...;Database=...;Username=...;Password=...", "RedisCache": "...,password=...", "Storage": "minio.s3://accessKey=...;secretKey=...;bucket=...;endpoint=...;forcePathStyle=true" }, ... } # content of appsettings.jsonpostgresql:
enabled: falsegarnet:
enabled: falserustfs:
enabled: false| Repository | Name | Version |
|---|---|---|
| https://charts.bitnami.com/bitnami | postgresql-ha | 16.3.2 |
| https://dandydeveloper.github.io/charts | redis-ha | 4.33.7 |
| https://rustfs.github.io/helm | rustfs | 0.2.0 |
| oci://ghcr.io/microsoft/helm-charts | garnet | 0.2.2 |
| Key | Type | Default | Description |
|---|---|---|---|
| extraObjects | list | [] | Additional Kubernetes manifests to deploy with this Helm chart |
| garnet.config.existingSecret | string | "" | Garnet secret (if you want to use an existing secret). This secret must contains a key called 'garnet.conf'. |
| garnet.config.garnetConf | string | "{\n \"AuthenticationMode\": \"Password\",\n \"Password\": \"gzctf\"\n}\n" | The garnet.conf data content. |
| garnet.enabled | bool | false | Enable Microsoft Garnet cache-store deployment |
| garnet.image | object | {"registry":"ghcr.io","repostiory":"microsoft/garnet","tag":""} | Garnet container image configuration |
| garnet.image.registry | string | "ghcr.io" | Garnet image registry |
| garnet.image.repostiory | string | "microsoft/garnet" | Garnet image repository |
| garnet.image.tag | string | "" | Garnet image tag (empty string uses chart appVersion) |
| garnet.persistence | object | Disabled (persistence not needed for cache) | Persistent storage configuration for Garnet |
| garnet.persistence.enabled | bool | false | Enable persistent storage for Garnet (not recommended for cache workloads) |
| gzctf.affinity | object | {} | Affinity rules for GZCTF pod scheduling |
| gzctf.appsettings | string | See values.yaml for full configuration | GZCTF application settings (appsettings.json content) |
| gzctf.autoscaling.enabled | bool | false | Enable autoscaling |
| gzctf.autoscaling.maxReplicas | int | 100 | Maximum number of replicas |
| gzctf.autoscaling.minReplicas | int | 1 | Minimum number of replicas |
| gzctf.autoscaling.targetCPUUtilizationPercentage | int | 80 | Target CPU utilization percentage |
| gzctf.autoscaling.targetMemoryUtilizationPercentage | int | 80 | Target memory utilization percentage |
| gzctf.clusterRole.create | bool | true | Create ClusterRole for GZCTF (required for Kubernetes challenge container management) |
| gzctf.clusterRole.rules | list | [{"apiGroups":["*"],"resources":["*"],"verbs":["*"]},{"nonResourceURLs":["*"],"verbs":["*"]}] | ClusterRole rules (full cluster access for managing challenge containers) |
| gzctf.env | list | [{"name":"GZCTF_ADMIN_PASSWORD","value":"xxx"},{"name":"LC_ALL","value":"en_US.UTF-8"}] | Environment variables for GZCTF container |
| gzctf.env[0] | object | {"name":"GZCTF_ADMIN_PASSWORD","value":"xxx"} | Initial admin password for GZCTF |
| gzctf.env[1] | object | {"name":"LC_ALL","value":"en_US.UTF-8"} | Locale configuration |
| gzctf.fullnameOverride | string | "" | Override the full name of the chart |
| gzctf.image | object | {"pullPolicy":"Always","repository":"ghcr.io/gztimewalker/gzctf/gzctf","tag":"v1.8.5"} | GZCTF container image configuration |
| gzctf.image.pullPolicy | string | "Always" | Image pull policy |
| gzctf.image.repository | string | "ghcr.io/gztimewalker/gzctf/gzctf" | GZCTF image repository |
| gzctf.image.tag | string | "v1.8.5" | GZCTF image tag |
| gzctf.imagePullSecrets | list | [] | Image pull secrets for private container registries |
| gzctf.ingress.annotations | object | {"traefik.ingress.kubernetes.io/service.sticky.cookie":"true","traefik.ingress.kubernetes.io/service.sticky.cookie.httponly":"true","traefik.ingress.kubernetes.io/service.sticky.cookie.name":"LB_Session"} | Annotations for ingress resource |
| gzctf.ingress.className | string | "" | Ingress class name |
| gzctf.ingress.enabled | bool | true | Enable ingress for GZCTF |
| gzctf.ingress.hosts | list | [{"host":"gctf.example.com","paths":[{"path":"/","pathType":"Prefix"}]}] | Ingress hosts configuration |
| gzctf.ingress.tls | list | [] | TLS configuration for ingress |
| gzctf.livenessProbe | object | {"httpGet":{"path":"/healthz","port":"metrics"}} | Liveness probe configuration |
| gzctf.metrics.enabled | bool | true | Enable metrics port |
| gzctf.metrics.port | int | 3000 | Metrics port number |
| gzctf.nameOverride | string | "" | Override the name of the chart |
| gzctf.nodeSelector | object | {} | Node labels for GZCTF pod assignment |
| gzctf.podAnnotations | object | {} | Annotations to add to GZCTF pods |
| gzctf.podLabels | object | {} | Labels to add to GZCTF pods |
| gzctf.podSecurityContext | object | {} | Security context for GZCTF pod |
| gzctf.pvc.accessMode | string | "ReadWriteOnce" | Access mode for the PVC (use ReadWriteMany when deploying multiple instances) |
| gzctf.pvc.create | bool | true | Create a PVC for GZCTF |
| gzctf.pvc.size | string | "2Gi" | Size of the PVC |
| gzctf.pvc.storageClassName | string | "standard" | Storage class name for the PVC (empty string uses cluster default) |
| gzctf.readinessProbe | object | {"httpGet":{"path":"/healthz","port":"metrics"}} | Readiness probe configuration |
| gzctf.replicaCount | int | 1 | Number of GZCTF replicas (Set to >1 for multi-node. Needs requirements) |
| gzctf.resources | object | {"requests":{"cpu":"1000m","memory":"384Mi"}} | Resource requests and limits for GZCTF container |
| gzctf.resources.requests | object | {"cpu":"1000m","memory":"384Mi"} | Resource requests |
| gzctf.resources.requests.cpu | string | "1000m" | CPU request |
| gzctf.resources.requests.memory | string | "384Mi" | Memory request |
| gzctf.securityContext | object | {} | Security context for GZCTF container |
| gzctf.service | object | {"annotations":{},"port":8080,"type":"ClusterIP"} | GZCTF service configuration |
| gzctf.service.annotations | object | {} | Annotations to add to the service |
| gzctf.service.port | int | 8080 | Service port |
| gzctf.service.type | string | "ClusterIP" | Service type |
| gzctf.serviceAccount | object | {"annotations":{},"automount":true,"create":true,"name":""} | ServiceAccount configuration for GZCTF |
| gzctf.serviceAccount.annotations | object | {} | Annotations to add to the ServiceAccount |
| gzctf.serviceAccount.automount | bool | true | Automatically mount ServiceAccount token |
| gzctf.serviceAccount.create | bool | true | Create a ServiceAccount for GZCTF |
| gzctf.serviceAccount.name | string | "" | ServiceAccount name (generated from chart fullname if not set) |
| gzctf.strategyType | string | "RollingUpdate" | Deployment strategy type |
| gzctf.tolerations | list | [] | Tolerations for GZCTF pod scheduling |
| gzctf.volumeMounts | list | [] | Additional volume mounts for GZCTF container |
| gzctf.volumes | list | [] | Additional volumes for GZCTF pod |
| postgresql-ha.enabled | bool | false | Enable or disable PostgreSQL HA deployment (THIS USES BITNAMI LEGACY IMAGES BY DEFAULT WHICH NO LONGER RECIEVE RPOPER SECURITY UPDATES) |
| postgresql-ha.metrics.enabled | bool | false | postgresql exporter enable |
| postgresql-ha.metrics.image.registry | string | "docker.io" | postgres-exporter image registry |
| postgresql-ha.metrics.image.repository | string | "bitnamilegacy/postgres-exporter" | postgres-exporter image repository |
| postgresql-ha.metrics.image.tag | string | "0.17.1-debian-12-r16" | postgres-exporter image tag |
| postgresql-ha.persistence.accessMode | string | "ReadWriteOnce" | Volume access mode |
| postgresql-ha.persistence.enabled | bool | true | Enable persistent volume for database storage |
| postgresql-ha.persistence.size | string | "2Gi" | Persistent volume size |
| postgresql-ha.persistence.storageClass | string | "" | Storage class name (empty string uses cluster default) |
| postgresql-ha.pgpool.image.registry | string | "docker.io" | pgpool image registry |
| postgresql-ha.pgpool.image.repository | string | "bitnamilegacy/pgpool" | pgpool image repository |
| postgresql-ha.pgpool.image.tag | string | "4.6.3-debian-12-r0" | pgpool image tag |
| postgresql-ha.postgresql.database | string | "gzctf" | Default database name to create |
| postgresql-ha.postgresql.image.registry | string | "docker.io" | Docker registry for PostgreSQL image |
| postgresql-ha.postgresql.image.repository | string | "bitnamilegacy/postgresql-repmgr" | PostgreSQL repository (bitnamilegacy repmgr version) |
| postgresql-ha.postgresql.image.tag | string | "17.6.0-debian-12-r2" | PostgreSQL image tag (version 17.6.0) |
| postgresql-ha.postgresql.password | string | "gzctf" | PostgreSQL superuser password (should be overridden or use secrets) |
| postgresql-ha.postgresql.username | string | "postgres" | PostgreSQL superuser username |
| postgresql-ha.volumePermissions.enabled | bool | true | Enable init container to set proper volume permissions |
| postgresql-ha.volumePermissions.image.registry | string | "docker.io" | volume-permissions image registry |
| postgresql-ha.volumePermissions.image.repository | string | "bitnamilegacy/os-shell" | volume-permissions image repository |
| postgresql-ha.volumePermissions.image.tag | string | "12-debian-12-r51" | volume-permissions image tag |
| postgresql.affinity | object | {} | Affinity rules for PostgreSQL pod scheduling |
| postgresql.enabled | bool | true | Enable PostgreSQL deployment |
| postgresql.env | list | [{"name":"POSTGRES_PASSWORD","value":"gzctf"}] | Environment variables for PostgreSQL container |
| postgresql.env[0] | object | Must match the database password in appsettings.json | PostgreSQL password environment variable |
| postgresql.image | object | {"imagePullSecrets":[],"pullPolicy":"IfNotPresent","registry":"docker.io","repository":"postgres","tag":"16-alpine"} | PostgreSQL image configuration |
| postgresql.image.imagePullSecrets | list | [] | Image pull secrets for private registries |
| postgresql.image.pullPolicy | string | "IfNotPresent" | Image pull policy |
| postgresql.image.registry | string | "docker.io" | Docker registry for PostgreSQL image |
| postgresql.image.repository | string | "postgres" | PostgreSQL image repository |
| postgresql.image.tag | string | "16-alpine" | PostgreSQL image tag |
| postgresql.livenessProbe | object | {} | Liveness probe configuration for PostgreSQL container |
| postgresql.nodeSelector | object | {} | Node labels for PostgreSQL pod assignment |
| postgresql.persistence.accessMode | string | "ReadWriteOnce" | Access mode for the persistent volume |
| postgresql.persistence.enabled | bool | true | Enable persistent storage for PostgreSQL |
| postgresql.persistence.size | string | "2Gi" | Size of the persistent volume |
| postgresql.persistence.storageClassName | string | "" | Storage class name for persistent volume (empty string uses cluster default) |
| postgresql.podAnnotations | object | {} | Annotations to add to PostgreSQL pods |
| postgresql.podLabels | object | {} | |
| postgresql.podSecurityContext | object | {} | Security context for PostgreSQL pod |
| postgresql.readinessProbe | object | {} | Readiness probe configuration for PostgreSQL container |
| postgresql.resources | object | {"requests":{"cpu":"500m","memory":"512Mi"}} | Resource requests and limits for PostgreSQL container |
| postgresql.resources.requests | object | {"cpu":"500m","memory":"512Mi"} | Resource requests |
| postgresql.resources.requests.cpu | string | "500m" | CPU request |
| postgresql.resources.requests.memory | string | "512Mi" | Memory request |
| postgresql.securityContext | object | {} | Security context for PostgreSQL container |
| postgresql.service | object | {"port":5432} | PostgreSQL service configuration |
| postgresql.service.port | int | 5432 | PostgreSQL service port |
| postgresql.tolerations | list | [] | Tolerations for PostgreSQL pod scheduling |
| postgresql.volumeMounts | list | [] | Additional volume mounts for PostgreSQL container |
| postgresql.volumes | list | [] | Additional volumes for PostgreSQL pod |
| redis-ha.additionalAffinities | object | {} | Additional affinities to add to the Redis server pods. |
| redis-ha.affinity | string | "" | Assign custom [affinity] rules to the Redis pods. |
| redis-ha.auth | bool | true | Configures redis-ha with AUTH |
| redis-ha.containerSecurityContext | object | See [values.yaml] | Redis HA statefulset container-level security context |
| redis-ha.enabled | bool | false | Deploys a High-Availability Redis cluster |
| redis-ha.exporter.enabled | bool | false | Enable Prometheus redis-exporter sidecar |
| redis-ha.exporter.image | string | "ghcr.io/oliver006/redis_exporter" | Repository to use for the redis-exporter |
| redis-ha.exporter.tag | string | "v1.78.0" | Tag to use for the redis-exporter |
| redis-ha.haproxy.additionalAffinities | object | {} | Additional affinities to add to the haproxy pods. |
| redis-ha.haproxy.affinity | string | "" | Assign custom [affinity] rules to the haproxy pods. |
| redis-ha.haproxy.containerSecurityContext | object | See [values.yaml] | HAProxy container-level security context |
| redis-ha.haproxy.enabled | bool | true | Enabled HAProxy LoadBalancing/Proxy |
| redis-ha.haproxy.hardAntiAffinity | bool | true | Whether the haproxy pods should be forced to run on separate nodes. |
| redis-ha.haproxy.labels | object | {"app.kubernetes.io/name":"gzctf-redis-ha-haproxy"} | Custom labels for the haproxy pod. |
| redis-ha.haproxy.metrics.enabled | bool | true | HAProxy enable prometheus metric scraping |
| redis-ha.haproxy.tolerations | list | [] | [Tolerations] for use with node taints for haproxy pods. |
| redis-ha.hardAntiAffinity | bool | true | Whether the Redis server pods should be forced to run on separate nodes. |
| redis-ha.image.repository | string | "public.ecr.aws/docker/library/redis" | Redis repository |
| redis-ha.image.tag | string | "7.2.11-alpine" | Redis tag |
| redis-ha.persistentVolume.enabled | bool | false | Configures persistence on Redis nodes |
| redis-ha.redis.config | object | See [values.yaml] | Any valid redis config options in this section will be applied to each server (see redis-ha chart) |
| redis-ha.redis.config.save | string | '""' | Will save the DB if both the given number of seconds and the given number of write operations against the DB occurred. "" is disabled |
| redis-ha.redis.masterGroupName | string | "gzctf" | Redis convention for naming the cluster group: must match ^[\\w-\\.]+$ and can be templated |
| redis-ha.redisPassword | string | "gzctf" | A password that configures a requirepass and masterauth in the conf parameters (Requires auth: enabled) |
| redis-ha.tolerations | list | [] | [Tolerations] for use with node taints for Redis pods. |
| redis-ha.topologySpreadConstraints | object | {"enabled":false,"maxSkew":"","topologyKey":"","whenUnsatisfiable":""} | Assign custom [TopologySpreadConstraints] rules to the Redis pods. # https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ |
| redis-ha.topologySpreadConstraints.enabled | bool | false | Enable Redis HA topology spread constraints |
| redis-ha.topologySpreadConstraints.maxSkew | string | "" (defaults to 1) | Max skew of pods tolerated |
| redis-ha.topologySpreadConstraints.topologyKey | string | "" (defaults to topology.kubernetes.io/zone) | Topology key for spread |
| redis-ha.topologySpreadConstraints.whenUnsatisfiable | string | "" (defaults to ScheduleAnyway) | Enforcement policy, hard or soft |
| rustfs.enabled | bool | false | Enable RustFS deployment (set to false if you want to use an external S3 bucket) |
| rustfs.mode | object | {"distributed":{"enabled":false},"standalone":{"enabled":true}} | RustFS mode configuration |
| rustfs.mode.distributed | object | {"enabled":false} | Distributed mode configuration |
| rustfs.mode.standalone | object | {"enabled":true} | Standalone mode configuration |
| rustfs.secret | object | {"rustfs":{"access_key":"","secret_key":""}} | RustFS secret configuration |
| rustfs.secret.rustfs | object | {"access_key":"","secret_key":""} | RustFS secret name |
| rustfs.secret.rustfs.access_key | string | "" | RustFS access key |
| rustfs.secret.rustfs.secret_key | string | "" | RustFS secret key |
| rustfs.storageclass | object | {"dataStorageSize":"10Gi"} | RustFS storage class configuration |
| rustfs.storageclass.dataStorageSize | string | "10Gi" | Data storage size |
Autogenerated from chart metadata using helm-docs