Instancer

Configure per-team challenge instances with Docker or Kubernetes.

Edit this page View Markdown

The instancer gives each team an isolated copy of a challenge service running on Docker or Kubernetes. Participants can start, inspect, extend, and stop their instance through rCTF.

Instanced challenges work well when teams need private mutable state, a dedicated service process, or a target that should disappear after a timeout.

Warning (Hostile workloads)

Treat challenge images as hostile. Set resource limits, keep containers or pods unprivileged, and avoid mounting host paths unless the challenge explicitly needs them.

Pick a backend

Both providers give participants the same controls and use the same shared challenge fields, but each backend has its own deployment guide.

How it works

Each challenge uses instancerConfig to select a named instancer and set its ID, timeout, public endpoints, and provider-specific settings. If the challenge does not select one, rCTF uses defaultInstancer or the only configured instancer.

When a participant starts an instance, rCTF validates the challenge configuration and sends the request to Docker or Kubernetes. The challenge page shows the instance status and the endpoints in the order listed under expose, along with controls to extend or stop it.

Provider configuration

Define instancers under the instancers map in rctf.d/. Each key is a name you choose, and challenges use that name to select an instancer. defaultInstancer chooses the fallback for challenges that don’t specify one. It is required when you configure more than one instancer. With only one, rCTF selects it automatically.

rctf.d/instancer.yaml
instancers:
docker:
name: instancers/docker
options:
apiUrl: http://tiny-instancer:1337
authToken: <shared-secret>
k8s:
name: instancers/k8s
options:
apiUrl: https://k8s.example.com
authToken: <service-account-token>
caCertificate: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
defaultInstancer: docker

A single-instancer deployment only needs one entry, and defaultInstancer can be omitted:

rctf.d/instancer.yaml
instancers:
docker:
name: instancers/docker
options:
apiUrl: http://tiny-instancer:1337
authToken: <shared-secret>

instancers/docker calls into the bundled Docker instancer or any compatible tiny-instancer API.

Field or variable Purpose
options.apiUrl Base URL of the Docker instancer API from the rCTF API process.
options.authToken Shared token sent as rctfAuthToken when rCTF creates, reads, extends, or deletes an instance.
DOCKER_INSTANCER_API_URL Environment override for apiUrl.
DOCKER_INSTANCER_AUTH_TOKEN Environment override for authToken.

See Docker instancer for the deployment walkthrough and Docker-specific challenge schema.

Note (Environment overrides and multiple instancers)

The DOCKER_INSTANCER_* and K8S_INSTANCER_* environment variables apply globally per provider type, so they’re best suited to single-instancer deployments. When you run two instancers of the same type, set their options inline instead.

Challenge configuration

Each instanced challenge needs instancerConfig. Its ID, timeout, extension setting, and exposed endpoints work the same with either provider. The contents of config depend on whether the challenge uses Docker or Kubernetes.

challenge.yaml
instancerConfig:
challengeIntegrationId: web-demo
instancer: docker
timeoutMilliseconds: 600000
extendable: true
config:
# Provider-specific config.
expose:
- kind: https
hostPrefix: web-demo
containerName: app
containerPort: 8080
shouldDisplay: true
title: Challenge
Field Purpose
challengeIntegrationId Stable ID used in Docker labels, Kubernetes resource names, and instance requests. Don’t change it after launch.
instancer Name of the instancer (a key in the instancers map) this challenge runs on. Omit to use defaultInstancer. The admin challenge editor exposes this as a dropdown of configured instancers.
timeoutMilliseconds Instance lifetime for create and extend operations.
extendable Lets participants extend their instance when set to true.
config Provider-specific service or pod configuration. See Docker or Kubernetes for the schema.
expose Public endpoints rCTF should display or keep hidden for internal routing.

The expose entries map public endpoints to a service container or pod:

Field Purpose
kind Endpoint kind. The values are http, https, tcp, and tcp-ssl.
hostPrefix Prefix used when generating the per-instance hostname.
containerName Docker service name or Kubernetes pod name receiving traffic.
containerPort Port inside the service container or Kubernetes service.
shouldDisplay Controls whether the endpoint is shown to participants. Hidden endpoints still exist.
title Optional display label.

Endpoint kinds

Endpoint support is provider-specific:

Kind Docker behavior Kubernetes behavior
http Traefik HTTP router on the configured HTTP port. The default is 80. Traefik IngressRoute on the web entrypoint. The public port is 80.
https Traefik HTTPS router on the configured HTTPS port. The default is 443. Traefik IngressRoute on the websecure entrypoint plus an HTTP redirect route. The public port is 443.
tcp Rewritten to tcp-ssl because Traefik needs SNI routing. Returned as unsupported-by-instancer with port 0. Kubernetes configs should use tcp-ssl.
tcp-ssl Traefik TCP router with TLS and HostSNI on the configured TCP port. The default is 1337. Traefik IngressRouteTCP with TLS and HostSNI on port 1337.

Participant actions and API routes

The instance routes are under /api/v2/integrations/challs/:id/instance:

Method Action
GET Returns current status, time left, and endpoints.
PUT Creates an instance.
PATCH Extends an instance when the challenge is extendable.
DELETE Stops an instance.

The returned status is stopped, starting, running, stopping, or errored.

Captcha can protect create and extend actions:

rctf.d/captcha.yaml
captcha:
protectedEndpoints:
- instancerStart
- instancerExtend

Provider schemas and the admin UI

The fields shared by both providers remain the same. Only config differs. Docker accepts a Compose-like service definition, while Kubernetes accepts pods[]. Each provider publishes a JSON Schema that describes and validates its version of config.

The schema endpoint returns the schema for each configured instancer and identifies the default. Deployment tools can use the same endpoint to validate a challenge before sending it to rCTF.

Dynamic admin UI

The challenge editor builds its form from these schemas. If several instancers are configured, selecting one updates the available fields and validation rules. Use the advanced YAML editor when a setting cannot be represented by the generated form.

Type to search.