Skip to content

Commit 0aba3c8

Browse files
authored
Add first blog post and disable taxonomies due to rendering error on webite (#73)
* chore: remove useless comment * fix: remove taxonomies due to layaout error * docs: add blog section with first blog post * chore: add link to GitHub repo * chore: update publication date * chore: review feedback
1 parent f381d50 commit 0aba3c8

File tree

9 files changed

+169
-7
lines changed

9 files changed

+169
-7
lines changed

config/_default/menus.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ main:
33
url: "/#hero"
44
weight: 10
55

6-
# - name: "Blog"
7-
# url: "/blog"
8-
# weight: 20
6+
- name: "Blog"
7+
url: "/blog"
8+
weight: 20
99

1010
- name: "About"
1111
url: "/about"
@@ -26,9 +26,9 @@ footer:
2626
url: "/#hero"
2727
weight: 10
2828

29-
# - name: "Blog"
30-
# url: "/blog"
31-
# weight: 20
29+
- name: "Blog"
30+
url: "/blog"
31+
weight: 20
3232

3333
- name: "About"
3434
url: "/about"

content/blog/_index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
title: Blog
3+
description: Central hub for blogs spanning numerous topics, all empowered by CTFer.io software.
4+
---
47.5 KB
Loading
33.9 KB
Loading
45.7 KB
Loading
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
---
2+
author: NicoFgrx
3+
title: "Everything on Docker"
4+
date: "2025-10-15"
5+
# description: Step by step instructions to use Docker with Chall-Manager, for begginers.
6+
resources:
7+
- src: "**.png"
8+
- src: "**gif"
9+
---
10+
11+
Since the early days at CTFer.io, we have always assumed a Kubernetes cluster as the foundation for deployments. This made orchestration simpler and shaped our solutions to run inside containers.
12+
13+
Moreover, we observed that most of the time, a challenge with infrastructure consisted of a single Docker image, exposed on a single port.
14+
Having a load of Docker container, continuously spinning up and down given on-demand usage, was coherent with the orchestrating capabilities of Kubernetes.
15+
We even eased deployment by creating a simplistic recipe `kubernetes.ExposedMonopod` that was the cornerstone solution to these problems... but the community still was not satisfied by all the requirements for a local lab: setting up a Kubernetes cluster can be quite overkill, or simply too complex.
16+
17+
Indeed, while we are comfortable with Kubernetes, that's not always the case for our users - mostly student teams or nonprofit volunteers organizing their first CTF, often from scratch.
18+
19+
The goal of this article is to present an alternative to our original Kubernetes-based setup using only virtual machines and Docker. All code referenced in this blog post is [available on GitHub](https://github.com/nicofgrx/ctferio-everything-on-docker), under an open-source license, and can be reused freely.
20+
21+
## What’s the Architecture?
22+
23+
We'll set up two virtual machines:
24+
25+
- A `ctf` VM hosting the CTF platform, including [CTFd](https://github.com/ctfd/ctfd), Chall-Manager, Chall-Manager-Janitor, and the ctfd-chall-manager plugin;
26+
- A `challenges` VM hosting the individual challenge instances that will be deployed.
27+
28+
{{< imgproc achi.excalidraw Resize "900x" >}}
29+
{{< /imgproc >}}
30+
31+
32+
## How to Deploy the Platform?
33+
34+
You only need **Vagrant** and **VirtualBox** installed on your system.
35+
36+
### Create the Platform
37+
38+
```bash
39+
# Clone the repository
40+
git clone https://github.com/nicofgrx/ctferio-everything-on-docker
41+
cd ctferio-everything-on-docker
42+
43+
# Launch the virtual machines
44+
vagrant up
45+
```
46+
47+
### Create a Challenge in CTFd
48+
49+
1. Go to [CTFd](http://192.168.56.10:8000)
50+
51+
2. Log in with the credentials:
52+
- Username: `ctfer`
53+
- Password: `ctfer`
54+
55+
3. Create a challenge:
56+
- Navigate to [Challenge Creation](http://192.168.56.10:8000/admin/challenges/new);
57+
- Select the `dynamic_iac` type;
58+
- Fill in the fields as you like;
59+
- In the **Scenario** tab, enter:
60+
```
61+
registry:5000/examples/docker:latest
62+
```
63+
- In **Advanced > Challenge configuration**, fill the form as below:
64+
- `hostname`: `192.168.56.11`
65+
- `docker_host`: `tcp://192.168.56.11:2375`
66+
67+
{{< imgproc challenge_advanced Resize "900x" >}}
68+
Extract of challenge advanced configuration.
69+
{{< /imgproc >}}
70+
71+
4. Go to the [Challenges page](http://192.168.56.10:8000/challenges);
72+
5. Deploy a challenge instance:
73+
74+
{{< imgproc instance_creation Resize "900x" >}}
75+
{{< /imgproc >}}
76+
77+
## How Does It Work?
78+
79+
By following the steps above, we've deployed an instance of `pandatix/license-lvl1:latest` on the `challenges` VM.
80+
81+
Now, let’s break down how it works.
82+
83+
### Platform Setup
84+
85+
- `Vagrantfile`: creates the two virtual machines and runs the setup scripts located in the `scripts/` directory;
86+
- `scripts/ctf.sh`: installs Docker Compose v2, starts containers defined in `scripts/compose.yml`, and pushes the scenario from `scenario/` to the local registry;
87+
- `scripts/compose.yml`: defines all containers needed for the platform;
88+
- `scripts/challenge.sh`: installs Docker and exposes the Docker socket on `TCP/2375`.
89+
90+
### What’s in the Compose File?
91+
92+
- `ctfd`: the CTFd platform with the ctfd-chall-manager plugin;
93+
- `chall-manager`: API that handles challenge deployment;
94+
- `chall-manager-janitor`: cleans up challenges;
95+
- `ctfd-setup`: automates basic setup of CTFd;
96+
- `registry`: a local OCI registry for storing scenarios and challenge images.
97+
98+
### What’s in the Scenario?
99+
100+
The scenario is defined in `scenario/main.go`, which uses Pulumi and the [Docker Provider](https://www.pulumi.com/registry/packages/docker/) to deploy Docker images.
101+
102+
You can customize the scenario using **additional values** in the challenge configuration.
103+
104+
| Variable | Default | Description |
105+
|-----------------|--------------------------------|--------------------------------------------------------------|
106+
| `image` | `pandatix/license-lvl1:latest` | The Docker image to deploy. |
107+
| `port` | `8080` | The port to expose the container on. |
108+
| `hostname` | `localhost` | The public address or domain for the connection information. |
109+
| `protocol_port` | `tcp` | The protocol to forward incoming traffic to. |
110+
| `protocol_url` | `http` | The protocol used in the connection information. |
111+
| `docker_host` | `unix:///var/run/docker.sock` | The Docker socket URI (e.g., `tcp://192.168.56.11:2375`). |
112+
113+
The scenario is compiled and pushed to the local OCI registry by the `scripts/ctf.sh` script. When creating the challenge in CTFd, reference it with `registry:5000/examples/docker:latest`.
114+
115+
**Note:** The final `connectionInfo` will look like: `{protocol_url}://{hostname}:{computed_exposed_port}`
116+
117+
### How to Deploy a Custom Image?
118+
119+
You can modify the additional configuration to deploy any Docker image.
120+
121+
Let’s say you want to deploy the image `anssi/fcsc2023-pwn-robot:latest` from [Hackropole](https://hackropole.fr/fr/) which exposes port `4000/tcp`. You can configure the challenge as follows:
122+
- In **Advanced > Challenge configuration**, fill the form as below:
123+
- `hostname`: `192.168.56.11`
124+
- `docker_host`: `tcp://192.168.56.11:2375`
125+
- `image`: `anssi/fcsc2023-pwn-robot:latest`
126+
- `port`: `4000`
127+
- `protocol_url`: `tcp`
128+
129+
{{< imgproc challenge_advanced_2 Resize "900x" >}}
130+
Extract of challenge advanced configuration.
131+
{{< /imgproc >}}
132+
133+
Once deployed, you may receive a URL like: `tcp://192.168.56.11:32769`
134+
135+
You can connect using netcat: `nc 192.168.56.11 32769`
136+
137+
It will output something like:
138+
```bash
139+
Que faites-vous ?
140+
1: Construire un robot 4: Rédiger le mode d'emploi
141+
2: Le faire parler 5: Afficher le mode d'emploi
142+
3: Jouer avec le robot 6: Admin
143+
0: Quitter
144+
>
145+
```
146+
147+
## Conclusion
148+
149+
Deploying CTFer.io ecosystem on Docker offers a simpler and more accessible alternative for teams who may not be familiar with container orchestration platforms. By relying on lightweight tools like Vagrant, VirtualBox, and Docker, this setup drastically lowers the entry barrier for organizing CTF events, especially in academic or volunteer-led environments.
150+
151+
While it doesn't provide the full scalability or automation capabilities of a Kubernetes-based infrastructure, it is fully functional, reproducible, and sufficient for many real-world use cases. More importantly, it serves as a solid starting point for teams to understand and experiment with CTFer.io’s ecosystem.
152+
153+
As a future work we'll work toward adding a specialised SDK in Chall-Manager to cover common Docker deployments, as the one documented per this blog post.
698 KB
Loading

data/home/carousel.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
enable: true # disabled for the moment (logo usage permission)
1+
enable: true
22

33
title: "Our solutions already be deployed in several events"
44
items:

hugo.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,8 @@ module:
1919
mounts:
2020
- source: webdocs
2121
target: content/docs/ctfd-chall-manager
22+
23+
disableKinds:
24+
- taxonomy
25+
- term
26+
- rss

0 commit comments

Comments
 (0)