Automatic Challenge Deployment Service
Hosted CTFd offers a service that allows you to manage and automatically deploy Capture The Flag challenges in the form of challenge containers. Challenge containers are typical applications packaged using Docker into Docker images and are deployed in our challenge container servers.
Applications that are deployed through this service can be accessed by any user with knowledge of the URL/hostname.
If you are looking for a per-account instance of an application, where it can be deployed by each user, please see Application Target Challenges.
Hosted CTFd currently only supports images built for the
linux/amd64 platform. Details on how to build an appropriate image while using an ARM based system (Apple Silicon, ARM, ARM64) can be found on Docker's documentation on Buildx.
Challenge containers/services must meet the following requirements:
- Challenge containers must EXPOSE a port (e.g. EXPOSE 8000) in their Dockerfile/image
- Challenge containers should have a network service running that listens on your EXPOSE'ed port that then relays the network connection to your main service (see this page for an example)
- Challenge containers should be as small as possible
- Challenge containers should not be comprised of multiple applications
- Challenge containers are not made with Docker Compose
It's worth noting as well that Hosted CTFd instances are not required to use our challenge deployment infrastructure. If you have very specific requirements, you're free to run your application on seperate servers. For example those provided by DigitalOcean, Amazon Web Services, Google Cloud Platform, or Microsoft Azure.
To create a service-based challenge:
Login as an administrator and navigate to the Admin Panel.
Click on the Services link on the top right.
Click the "plus" icon to go to the create service page.
Give your service a title (alphanumeric and dashes only) and click the Create button.
Build your docker image.
After building the docker image, open your terminal and run the commands listed on the service page.
Login with your CTFd username as
<username>@<subdomain.ctfd.io>and account password.
$ docker login -u '[email protected]' registry.ctfd.io
Tag the target image
registry.ctfd.io/[subdomain]/[challenge-name]with the source image
[your image name].
$ docker tag your-image-name registry.ctfd.io/[subdomain]/[challenge-name]
Push the tagged image to CTFd's service registry.
$ docker push registry.ctfd.io/[subdomain]/[challenge-name]
The service page will then update with the deployed domain name of the challenge (You may need to manually refresh the page). You should receive an email every time the challenge is deployed.
Below is a hypothetical example using the demo.ctfd.io hosted CTFd instance.
$ docker login registry.ctfd.io
Username: [email protected]
$ docker tag <image> registry.ctfd.io/demo/<challenge-name>
$ docker push registry.ctfd.io/demo/<challenge-name>
The push refers to repository [registry.ctfd.io/demo/<challenge-name>]
latest: digest: sha256:... size: 12345
As a reminder, your Docker image must have a port exposed. Most images do, but if you happen to be writing something custom, here's the reference in the Docker documentation.
Common examples are
EXPOSE 80 or
Once the docker image succeeds, the services page should show:
Current Status: deployed
Deployed On: demo-challenge.chals.io
Internal Port: 8000
This is persistent link that participants can use to access your challenge.
Connecting to Services
Hosted CTFd instances uses an improved customized infrastructure based on SNI multiplexing to host challenge services. Our infrastructure automatically encrypts all communication to a challenge service and all communication happens over a single well known port (443). You can read more about the this design on our blog at https://blog.ctfd.io/hosted-challenge-deployment-improvements/.
If the underlying application you've deployed is a web server, you can simply open the URL in a browser and it will work seamlessly (e.g.
However, if your underlying application communicates directly over TCP you have a few options:
You may use an SSL/TLS aware client software such as our snicat (sc) tool.
Or you can "Request a TCP port" from our infrastructure and use a tool such as netcat. Keep in mind that this will forego any security or vanity benefits provided by using our encrypted connections.
snicat is designed to be very similar to netcat whilst providing vanity urls and encrypted connections. snicat can also be downloaded for Mac, Linux, and Windows.
❯ sc demo-challenge.chals.io
(connected to demo-challenge.chals.io:443 and reading from stdin)
For Linux and Mac the following commands should download snicat for you:
wget "https://github.com/CTFd/snicat/releases/latest/download/sc_`uname`_`uname -m`" -O sc
chmod +x sc
For Mac, you may need to remove the quarantine attribute by running:
xattr -d com.apple.quarantine sc
For Windows, you can download the x64 exe here and then run it from the command prompt.
Please refer to https://github.com/CTFd/snicat for full details and documentation
netcat / Requesting a TCP port
If you'd like users to use netcat, you can, however keep in mind that connections will be unencrypted.
- Browse to your deployed service and select the TCP connection tab
- Click on "Request TCP Port". Confirm that you'd like to request a port.
Refresh the page if it does not automatically refresh
You should receive a hostname and port as shown below:
Once you've been allocated a hostname and port, share it with your users for them to be able to connect to the service via tools like netcat.
Alternatively you can also leverage our fallback proxy service that allows netcat to connect to challenge services without requesting a port.
❯ nc cloud.chals.io 23
If none of the above options work for you, you can take a look at some of the other options here.
If you have any questions or any feedback, please feel free to contact us.