Operator guide — This document is for infrastructure operators setting up the Kubernetes cluster manually. For most users, run
./setup.shinstead — it auto-detects host capabilities and handles kCTF setup on Linux hosts. See setup.md for the full quickstart.Requirements: Linux host. KVM is not required for kCTF itself. (KVM is required only for
kata-firecracker.)
kCTF is Google's CTF infrastructure framework. It uses Kubernetes with nsjail (namespace-based sandboxing) inside each pod for challenge isolation.
IsolateX uses kCTF-style pods: standard Kubernetes pods with hardened security contexts. You do not need to install the full kCTF toolchain — IsolateX manages pod lifecycle directly via the Kubernetes API.
# Install kind
curl -Lo /usr/local/bin/kind \
https://kind.sigs.k8s.io/dl/v0.22.0/kind-linux-amd64
chmod +x /usr/local/bin/kind
# Run the IsolateX kCTF setup script
./infra/kctf/setup-cluster.sh --kindk3s is a lightweight, production-ready Kubernetes distribution.
# Install k3s (disabling built-in Traefik — IsolateX brings its own gateway)
curl -sfL https://get.k3s.io | sh -s - --disable traefik --disable servicelb
# Run the IsolateX kCTF setup script
sudo ./infra/kctf/setup-cluster.sh- Creates the
kctfnamespace - Applies Pod Security Standards (restricted profile) on the namespace
- Applies default-deny NetworkPolicy (no east-west pod traffic)
- Applies LimitRange (CPU/memory caps per pod)
- Creates the
isolatex-workerServiceAccount + RBAC Role
Challenge Docker images for kCTF must:
- Run as a non-root user (UID != 0)
- Not require write access to the root filesystem (use
tmpfsfor/tmp) - Not require any Linux capabilities
- Listen on the port specified in the challenge config
Example Dockerfile:
FROM ubuntu:22.04
RUN useradd -r -u 65534 challenge
WORKDIR /challenge
COPY challenge .
RUN chown challenge:challenge /challenge/challenge
USER challenge
EXPOSE 8888
CMD ["/challenge/challenge"]The default-deny NetworkPolicy means:
- Challenge pods cannot reach each other
- Challenge pods can only receive traffic from the IsolateX gateway
- Challenge pods can resolve DNS (UDP/TCP port 53 is allowed out)
IsolateX exposes challenge backends as internal ClusterIP services (not NodePort).
Players reach challenges only through the reverse proxy + CTFd auth checks.
If a challenge needs outbound internet access, add a specific NetworkPolicy
in the challenge's deployment config. See infra/kctf/manifests/network-policy.yaml.
For the strongest isolation, you can run nsjail inside your kCTF pods.
nsjail provides another layer of Linux namespace isolation on top of Kubernetes.
Example: run your challenge binary inside nsjail within the pod:
nsjail \
--mode o \
--port 8888 \
--chroot /chroot \
--user 65534 \
--group 65534 \
--iface_no_lo \
-- /challenge/challengeSee the nsjail documentation for full options. This is recommended for pwn challenges running in kCTF (since container isolation is weaker than KVM).
# Check namespace
kubectl get namespace kctf
# Check NetworkPolicy
kubectl get networkpolicy -n kctf
# Check LimitRange
kubectl get limitrange -n kctf
# Check RBAC
kubectl get serviceaccount isolatex-worker -n kctf
kubectl get role isolatex-worker -n kctf
kubectl get rolebinding isolatex-worker -n kctf