I have tried different setups for CTFs and penetration testing labs. I wanted the tools I regularly use in one place, without installing all their dependencies on my host. At the same time, I wanted to keep using my normal browser, notes, and clipboard manager.

Exegol fits that workflow well. I previously used it through WSL on Windows, and today I run it on Arch Linux with Hyprland. In this post, I want to share my setup and the features I find most useful during my CPTS preparation.

๐Ÿ“ฆ Why I use Exegol#

Exegol is a Docker-based environment for offensive security. It provides prepared images with tools and resources, together with a wrapper for managing the containers. The image is the template; the container is the environment I actually work in.

During the eJPT training, the browser-based attacker machines were convenient because the tools were already installed. After completing the certification, I returned to the HTB Penetration Tester Job Role Path and needed my own environment for longer labs.

This became especially noticeable in Active Directory modules. I may use NetExec, Impacket, BloodHound, Certipy, BloodyAD, and pyWhisker during the same lab. Keeping everything installed directly on my host would mean maintaining those tools and their dependencies myself.

A virtual machine would also work. For my everyday labs, however, I prefer running the security tools in a container while keeping the rest of my workflow on the host.

๐Ÿ–ฅ๏ธ My host and desktop setup#

My browser, notes, screenshots, and clipboard history stay on the host. I regularly copy commands, IP addresses, usernames, and paths during a box, so keeping my usual clipboard manager is useful. It can also retain passwords, which is something to keep in mind before copying sensitive data.

For graphical applications inside Exegol, I use VNC and open the container desktop in TigerVNC. A desktop entry lets me connect with a single click.

X11 forwarding was a little fiddly in my old Windows and WSL setup. On Arch Linux with Hyprland, both X11 and VNC have worked without problems for me. I still use VNC across my containers because it keeps the routine consistent.

I also keep two containers for the HTB environments I use:

Container VPN connection
htba HTB Academy VPN
htbl HTB Labs VPN

When working through Academy modules, I use htba. For HTB Labs machines, I switch to htbl. Each container already has the corresponding VPN configuration, so I do not have to change files whenever I switch environments.

The network mode still matters. If containers use host networking, they share the host’s network stack. Separate container names alone do not isolate their VPN routes.

๐Ÿ“ Working with shared files#

Exegol mounts a persistent workspace at /workspace inside the container. By default, the host directories are stored below ~/.exegol/workspaces/, although this location can be changed in the wrapper configuration.

This lets my tools write scan results and collected files inside the container while my host applications open the same files. I do not have to copy everything between two systems before adding it to my notes.

When creating a container, I can use a specific host directory as its workspace:

exegol start <CONTAINER> <IMAGE> --workspace <WORKSPACE_PATH>

<CONTAINER> is the container name, <IMAGE> selects the image, and <WORKSPACE_PATH> is the host directory to mount at /workspace.

Alternatively, I can mount the current directory:

exegol start <CONTAINER> <IMAGE> --cwd-mount

These options apply when creating the container. Starting an existing one does not replace its mounts. The shared workspace is convenient, but it also gives the container access to those host files. I would not treat this setup as a hard security boundary.

๐Ÿ” Exegol-history and prepared commands#

The feature I initially underestimated most was Exegol’s pre-filled shell history. Many pentesting commands have enough options that I regularly need to look up the syntax. The prepared history gives me a starting point without searching for the same command again.

It becomes more useful when combined with Exegol-history, or exh. This tool stores credentials and hosts in a database and lets me select them for the current shell.

For example, a credential can be added with:

exh add creds -u '<USER>' -p '<PASSWORD>' -H '<NT_HASH>' -d '<DOMAIN>'

The options specify the username, password, NT hash, and domain. I only supply the values I have; a local Linux account does not need all of them.

To select a stored credential, I run:

exh set creds

This opens an interactive interface. After selecting an entry, its values are exported as environment variables such as USER, PASSWORD, NT_HASH, and DOMAIN. My prompt also shows the active credential set, which helps when switching between accounts.

Hosts work in a similar way. The following example adds a fictional Domain Controller:

exh add hosts --ip '10.10.10.10' -n 'dc01.lab.local' -r 'DC'
exh set hosts

--ip specifies the IP address, -n the hostname, and -r the role. Selecting a host loads the relevant variables, such as TARGET, IP, DC_IP, and DC_HOST.

I can check the currently selected values with:

exh show

My usual workflow is to select a credential, select a host, and then find the command I need in the shell history. Exegol’s prepared commands already use matching variables. For example:

nxc smb "$TARGET" -u "$USER" -p "$PASSWORD"

After selecting another credential or host, the same command uses the new values. The double quotes keep each variable expansion as a single argument, including passwords containing spaces.

This saves repeated typing during longer AD labs, where several accounts and systems may be relevant at once. I still check the active context with exh show and review the command before running it. A prepared command is only useful if I understand what it does and which system it will target.

๐ŸŽฅ Shell logging with Asciinema#

Exegol’s built-in shell logging is useful when I want to review an earlier attempt or write a walkthrough. It records the terminal session, so I can return to the commands and output instead of relying only on my notes.

To enable it when starting a container:

exegol start <CONTAINER> <IMAGE> --log

Asciinema is the default logging method. It can also be selected explicitly with --log-method asciinema. When logging is enabled during container creation, future shells opened in that container are logged automatically.

The recordings are stored in /workspace/logs/ and compressed with gzip by default. Since the workspace is shared, I can access them from my host.

To replay a recording:

gunzip -c <SESSION>.asciinema.gz | asciinema play -

gunzip -c decompresses the file to standard output, and asciinema play - reads it from the pipe. Asciinema preserves the terminal output and its timing, which also helps when reviewing interactive tools such as exh.

If I only need the text, I use:

gunzip -c <SESSION>.asciinema.gz | asciinema cat -

I view the logs from the host. Replaying them inside a shell that is being recorded could put the replay into another log.

Recordings can contain passwords, hashes, tokens, and other sensitive output. I review the complete session before sharing it and use separate sessions with fictional data for public demonstrations. The logs and the Exegol-history database need the same care as my other assessment files.

โœ… My conclusion#

For my current setup, Exegol works well because the tools are ready while my everyday applications stay on the host. The shared workspace and TigerVNC connection make switching between both easy.

Exegol-history has become particularly useful during my CPTS preparation. Selecting credentials and hosts once, then reusing them in prepared commands, saves me from repeatedly typing the same information. The shell logs help when I need to retrace my steps or write a post like this one.

I still need to maintain the containers and understand the tools I use. A dedicated VM remains useful when stronger separation is required. For HTB machines and Academy labs, though, this is the setup I prefer.

๐Ÿ“š References#