Overview
Labtainer is the Naval Postgraduate School's Docker-based cybersecurity lab framework, giving students isolated, repeatable hands-on labs. By default it's built to run on a single local machine. This project turns it into a multi-user system that runs on CRADLE Lab's OpenStack/Jetstream2 cloud environment, so many students can run the same labs independently on one shared server — with no local install and no per-student virtual machine.
The work has two phases: first, building a fully OpenStack-compatible Labtainer image; second, making that image support many independent, non-conflicting users at the same time. Phase 1 is complete. Phase 2 is in progress.
Phase 1 — OpenStack-Compatible Image Completed
Labtainer ships with its own Docker install, and its lab containers are pre-wired to run on it. Exosphere — the browser-friendly OpenStack client used on Jetstream2 — also automatically installs its own Docker on every new instance, to run its own browser-access tools (Guacamole) for one-click shell and desktop access. Put both on the same image, and they collide: Exosphere's Docker install fails outright, and even forcing it through leaves Labtainer's labs unable to run correctly on the Docker setup Exosphere creates.
Rather than letting the two systems fight over Docker, the fix integrates them: Exosphere's own Docker installation step is disabled, and its Guacamole containers are pointed at the Docker daemon Labtainer already provides. Concretely, this meant forking Exosphere's provisioning tasks, pointing the image at that customized fork, removing the redundant Docker install step, and reconfiguring Guacamole's container deployment to target Labtainer's existing Docker daemon. The result: one Docker daemon runs both the native Labtainer labs and Exosphere's Guacamole stack side by side, with no conflicts.
Beyond that core conflict, getting the image to behave like a proper, reusable OpenStack image took a series of smaller fixes — none of them documented anywhere, all found by repeatedly deploying the image through Exosphere, reading the logs, and isolating whatever failed next:
- Base OpenStack packages: installing
cloud-init,qemu-guest-agent, and SSH so the image can talk to OpenStack's metadata service, accept SSH keys, and resize its disk on first boot. - Removing background auto-updates: Ubuntu's
unattended-upgradeswas silently holding the package manager lock during provisioning, causing install steps to hang. - Remote-desktop software: installing TurboVNC and VirtualGL for the labs' graphical sessions, then removing their extra package repositories afterward so they don't conflict with Exosphere's own provisioning steps later on.
- Serial console output: enabling it in the boot configuration, since Exosphere reads it to know when an instance has finished booting — without it, instances launched through Exosphere would simply time out.
- Cleanup & generalization (always last): right before saving the image, clearing cached boot state, machine IDs, and SSH host keys, so every new instance created from the image gets its own clean identity instead of quietly cloning the original.
This work was built and validated directly on Jetstream2, an NSF-funded research cloud whose operational software is genuine, production OpenStack — so an image that works cleanly there is, by definition, OpenStack-compatible more broadly. The result gives students one-click, browser-based access to Labtainer labs, with no local VirtualBox or VMware installation required.
Phase 2 — Independent Multi-User Sessions In Progress
A single working image isn't enough on its own — the next step is letting many students run the same labs on the same server at the same time, each in their own independent session that never interferes with anyone else's. Sharing one server this way surfaced three distinct problems:
- When two users started the same lab at the same time, they collided with a "lab already running" error, caused by both labs trying to use identically named containers.
- Different users' remote desktop sessions occasionally ran into display mismatches (for example, a lab's GUI window failing to appear).
- A temporary folder shared by all users' lab sessions ran into permission conflicts once more than one person was using the server.
Here's how each is being addressed:
- A small, targeted change to Labtainer's own startup logic now tags every container name with the real operating-system username running it. Because both starting and stopping a lab go through the same code path, this one change keeps the two in sync automatically, and two users' labs can no longer collide.
- The display issue turned out not to be a Labtainer problem at all — it traced back to different users connecting through different display numbers, and was confirmed resolved by testing under the original single-user setup.
- The shared temporary folder was only writable by whichever user happened to create it first. Opening up its permissions — the same way the system's own temp directory already behaves — lets every user's first run create its own subfolder without a permissions error.
Next step: confirm the permission fix holds up under continued use, then roll the container-naming fix out to the rest of the lab's users one by one.
Related Project
Back to Research & ProjectsQuick Facts
- Type: Project
- Status: Ongoing
- Lead: Ali Arslan
- Platform: Jetstream2 / OpenStack