Scaffolding to run a GZCTF instance.
make wizard # interactive prompts → writes .env + appsettings.json
make setup # creates the external `traefik` docker network
make platform-up # starts gzctf + db + cache + traefikThe wizard prints the auto-generated admin password at the end — copy
it before closing the terminal. Then log in at https://PUBLIC_ENTRY
as user Admin.
make help lists every target. SMTP / captcha / private-registry
credentials can also be configured later under /admin/settings.
For an Attack & Defense challenge you can let each team run the vulnerable service on their own machine instead of the platform hosting one copy per team. The platform launches only a lightweight tunnel relay; the team connects their service to it with a single outbound command — no public IP, inbound firewall rule, or VPN on the team's side. The SLA checker, attack proxy, flag rotation and scoreboard all behave exactly as for a hosted service.
Enable it on any A&D challenge by setting selfHosted: true in its
ad: block (see challenges/attack-defense/challenge.yml):
type: AttackDefense
container:
exposePort: 80 # the port your service listens on
ad:
selfHosted: true # ← teams run the service themselvesWhat a team does (all from the in-game challenge panel):
- Open the challenge → Download
setup.sh. - Run
sh setup.sh. It pulls the challenge's service image from the platform and a tiny agent, writes adocker-compose.yml, anddocker compose ups them — the agent dials the platform and the service goes live. Their status goes green within a tick.
Requirements (this template already satisfies them):
- Docker provider only. The relay launch is skipped on Kubernetes, so BYOC
needs the docker-compose deployment (the
compose/stack), notk8s/. - Reachable at
PUBLIC_ENTRY. The team's agent connects towss://PUBLIC_ENTRY/...; the bundled traefik already routes that host to gzctf and proxies the WebSocket — nothing extra to configure. - Relay/agent image is public (
dimasmaualana/gzctf-byoc-relay) and pulled automatically through the mounted docker socket — no registry setup. Override it viaAd:Byoc:RelayImage/Ad:Byoc:AgentImageinappsettings.jsonif you self-host the image. - Make sure the platform image is current:
make pull-gzctf && make update-gzctf(BYOC needs a recentdimasmaualana/gzctf:develop).
Teams that prefer to run a modified service (rather than the image you ship) can grab a plain compose instead via the panel's "bring your own service" link.
cd k8s/
$EDITOR 30-gzctf-config.yaml # set passwords + PublicEntry
$EDITOR 50-ingress.yaml # set hostname
kubectl apply -f .
kubectl -n gzctf rollout status deploy/gzctfSee k8s/README.md for details (storage classes, RBAC, cert-manager swap).