Skip to content

Latest commit

 

History

4,233 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GitHub commit activity GitHub language count CodeQLDependabot Updates

README

The CoLab system provides instructor support for collaborative learning groups. In its current state, it deploys successfully to Heroku with Amazon SES & S3 (using ActiveStorage), Scheduler and JAWS Maria DB add-ons with a libVips buildpack. It should run in a paid dyno with SSL enabled or a configuration change would be required.

What is this repository for?

The CoLab system which is based upon and supports the continued research of Micah Gideon Modell, Ph.D.

How do I get set up?

CoLab uses Podman containers for all development and testing. The entire toolchain runs inside containers managed by devContainers and VS Code, so your host machine needs only a small set of tools installed. Development is supported on macOS, Linux, and Windows (via WSL2).


Prerequisites

All platforms

Tool Notes
Podman Desktop Includes podman, podman compose, and the Podman Machine (VM) backend. Required on macOS and Windows; on Linux you can install podman and podman-compose via your package manager instead.
VS Code With the Dev Containers extension (ms-vscode-remote.remote-containers) installed.
Git To clone the repository.

Memory: Podman Machine needs at least 8 GB of RAM. Configure it with:

podman machine set -m 8192

Windows-only additional requirements

  1. WSL2 — required by Podman Desktop. Enable it in PowerShell (as Administrator) and then reboot:
    wsl --install
  2. Configure VS Code to use Podman — add the following to your VS Code user settings (File → Preferences → Settings, search for dockerPath):
    "dev.containers.dockerPath": "podman"
    Alternatively, set the DOCKER_HOST environment variable to the Podman socket before launching VS Code.

macOS-only note

Podman Desktop installs a Podman Machine automatically. No extra steps are needed beyond installing Podman Desktop and VS Code. See the macOS rootless Podman — extra step section below for instructions on making the bind-mounted source tree writable.


Step 1 — Clone the repository

(Recommended) First, set up SSH keys on GitHub.

Open a terminal (on Windows, use PowerShell or Windows Terminal) and run:

# Using SSH (recommended)
git clone git@github.com:mgmodell/CoLab.git

# Or using HTTPS
git clone https://github.com/mgmodell/CoLab.git

Navigate into the project directory:

cd CoLab

Step 2 — Build the container images

The container images must be built before opening the devcontainer in VS Code.

macOS / Linux (bash)

./buildContainers.sh -b

Windows note: If you're on Windows, run the PowerShell script (.\buildContainers.ps1) from PowerShell/Windows Terminal. Running the bash script from Git Bash/WSL is not the recommended path, because the PowerShell path keeps Podman/Dev Containers integration aligned with Windows host settings.

To build only the dev containers (faster, skips the test container):

./buildContainers.sh -d

Run ./buildContainers.sh -h for a full list of options.

Automatic devcontainer compose selection: buildContainers.sh runs ./configureDevcontainer.sh before building images. It detects podman info --format '{{.Host.Security.Rootless}}' and host OS, then updates .devcontainer/devcontainer.json to include:

  • docker-compose.rootless.yml on Linux rootless Podman
  • docker-compose.macos.yml on macOS rootless Podman
  • base docker-compose.yml otherwise

Windows (PowerShell)

.\buildContainers.ps1 -Both

To build only the dev containers:

.\buildContainers.ps1 -DevOnly

Run .\buildContainers.ps1 -Help for a full list of options.

Automatic devcontainer compose selection: buildContainers.ps1 runs .\configureDevcontainer.ps1 before building images, applying the same rootless/OS detection and .devcontainer/devcontainer.json update.

Note: The build uses the project root as the build context (required for COPY instructions inside the Dockerfiles). Run the script from the project root directory.


Step 3 — (Optional) Configure environment variables

Copy .env.example to .env and fill in any values you need:

cp .env.example .env

The .env file is gitignored. Add any environment variables you need here; see .env.example for the available options.


Step 4 — Open the devcontainer in VS Code

  1. Open VS Code in the project directory:
    code .
  2. VS Code will detect the devcontainer configuration and show a notification: "Reopen in Container". Click it.
    • If the notification doesn't appear, open the Command Palette (Ctrl+Shift+P / Cmd+Shift+P) and run "Dev Containers: Reopen in Container".
  3. VS Code will start all services (db, redis, browser, moodle, selenium) and attach to the app container.
  4. On first open, postCreateCommand runs automatically to install the Ruby/Node toolchain via mise and install all gems. This takes a few minutes.

Linux rootless Podman — manual fallback

Use this manual fallback only if automatic compose selection did not choose the Linux rootless override correctly, or if you want to force the Linux rootless configuration explicitly.

On Linux with rootless Podman, the bind-mounted source tree needs userns_mode: keep-id so that container file writes are owned by your host user. Enable it by referencing the provided override in .devcontainer/devcontainer.json:

"dockerComposeFile": [
  "../containers/dev_env/docker-compose.yml",
  "../containers/dev_env/docker-compose.rootless.yml"
]

Windows (native): do not add the rootless override. It causes an "unsupported UNC path" error when Podman tries to forward the WSLg Wayland socket into the container. Use docker-compose.windows.yml instead — see Windows (Podman Desktop) — extra step below.

macOS rootless Podman — manual fallback

Use this manual fallback only if automatic compose selection did not choose the macOS rootless override correctly, or if you want to force the macOS rootless configuration explicitly.

On macOS, Podman shares the host filesystem into its Linux VM via virtiofs. Without the macOS override, the bind-mounted files appear as uid:0 / nogroup inside the container (not writable) because rootless Podman's user namespace remaps the macOS user UID 501 to container UID 0 without the userns_mode: keep-id setting.

The macOS compose override applies two settings together to fix this:

  • userns_mode: keep-id — maps the Podman Machine user UID (501) into the container unchanged so bind-mounted source files owned by UID 501 are writable.
  • USER_UID: "501" build arg — rebuilds the dev-server image so that the colab container user has UID 501, matching the macOS user UID so file ownership is shown as colab.

Note: bind-mounted files may still display the group as nogroup or dialout in ls -l because the macOS staff GID (20) has no corresponding group in the Ubuntu container. This is cosmetic — write access works correctly because the colab user is the file owner (UID 501 matches).

Enable it by referencing it in .devcontainer/devcontainer.json:

"dockerComposeFile": [
  "../containers/dev_env/docker-compose.yml",
  "../containers/dev_env/docker-compose.macos.yml"
]

After adding the override, run "Dev Containers: Rebuild and Reopen in Container" (Command Palette: Cmd+Shift+P) so the image is rebuilt with the correct UID.

If you had already created the named volumes without this override, delete and recreate them so they are re-seeded with the correct ownership:

podman volume rm dev_env_devmise

Windows (native): do not add the macOS override. userns_mode: keep-id on Windows triggers an "unsupported UNC path" error (WSLg Wayland socket). Use docker-compose.windows.yml instead — see Windows (Podman Desktop) — extra step below. Linux: use docker-compose.rootless.yml instead.

Windows (Podman Desktop) — extra step

On Windows with Podman Desktop, the container host filesystem is shared into the Linux VM via virtio-9p (v9fs). This means platform-specific native Node.js modules (such as @rspack/binding) may be installed with Windows binaries into the bind-mounted node_modules, which the Linux container cannot use. A named Docker volume (devnodemodules) in the base compose file already addresses this by shadowing node_modules so the container always builds its own Linux-native copy — no extra volume configuration is needed.

Enable the Windows override by updating .devcontainer/devcontainer.json:

"dockerComposeFile": [
  "../containers/dev_env/docker-compose.yml",
  "../containers/dev_env/docker-compose.windows.yml"
]

Order matters: always list the base docker-compose.yml first. Docker Compose merges override files on top of the base in the order they appear, so reversing the order would break the base configuration.

After adding the override, run "Dev Containers: Rebuild and Reopen in Container" (Command Palette: Ctrl+Shift+P) so the container is recreated, the devnodemodules volume is initialised, and yarn install runs inside the container with the correct Linux binaries.

If you encounter Cannot find native binding errors after a rebuild, wipe and repopulate the volume manually:

podman volume rm dev_env_devnodemodules

Then rebuild the container.

WSL2 users: if you have set up your development environment inside WSL2 (rather than running VS Code natively on Windows), treat your setup as Linux and use docker-compose.rootless.yml instead. WSL2 presents a normal Linux filesystem, so the Windows override is not needed.

The following ports are forwarded automatically to your host machine: |------|---------| | 3000 | Rails development server | | 3035 | Shakapacker (JavaScript) dev server | | 4444 | Selenium WebDriver | | 6080 | VNC browser (noVNC web UI) | | 8080 | Moodle LMS |


Step 5 — Set up the development database

Inside the VS Code terminal (which runs inside the devcontainer), prepare the database:

./dev_serv.sh -p

To load a pre-existing database snapshot (if you have one in db/dev_db.sql), run this from a terminal on your host machine (not inside VS Code):

./mng_db.sh -j

Step 6 — Create a test user and start the server

These commands run inside the devcontainer (use the VS Code integrated terminal):

# Create a test user with your email address and password 'password'
./dev_serv.sh -e "haccess[yourEmail@something.com]"

# Start the Rails development server
./dev_serv.sh -s

Open http://localhost:3000 in your browser.

You can also view the integrated VNC browser at http://localhost:6080, or connect a native VNC client to vnc://localhost:5909 (password: password).

Note: dev_serv.sh is designed to run inside the devcontainer. It checks for the container environment and will print a warning if run on the host directly.

Run ./dev_serv.sh -h inside the devcontainer to see all available options.


Running the full test suite

run_tests.sh orchestrates the Cucumber test container and must be run from a terminal outside VS Code (on your host machine, or in WSL2):

# First-time: initialise the test database
./run_tests.sh -c

# Run all tests (rerun only failures from the previous run if any exist)
./run_tests.sh -r

# Show failures from the previous run without re-running
./run_tests.sh -s

Run ./run_tests.sh -h for a full list of options.

Database management

mng_db.sh manages database snapshots. Run it from your host machine (not inside the devcontainer). No host MySQL client is required — it uses podman compose exec internally, so the DB container must be running:

./mng_db.sh -j   # Load the dev DB snapshot (db/dev_db.sql)
./mng_db.sh -d   # Dump the current dev DB to db/dev_db.sql
./mng_db.sh -h   # Show all options

The script resolves all file and compose paths from its own location, so it works correctly regardless of which directory you invoke it from.


Contribution instructions

  1. Review the issues
  2. Find one that interests you
  3. Assign it to yourself
  4. Start working in your own branch
    • git branch <enter_new_branch_name>
    • git checkout <enter_new_branch_name>
  5. Create what you need (inside the devcontainer terminal)
    • Run ./dev_serv.sh -e "haccess[yourEmail@something.com]"
    • Run ./dev_serv.sh -e "examples[yourEmail@something.com]"
  6. Open the test server
  7. Play with it to understand the problem
  8. Start writing tests
  9. Check in your code
    • git add <file name>
    • git commit -m `<meaningful message>`
    • git push

LTI 1.3 Integration

CoLab supports LTI 1.3 for single sign-on, roster provisioning, and grade sync with Moodle, Canvas, Blackboard, Brightspace, and other compliant LMS platforms.

See doc/LTI_INTEGRATION.md for step-by-step connection instructions.

Security (penetration-testing) environment

An isolated container stack for authorized security testing pairs a faithful production build of CoLab (heroku-26 stack + Ruby + jemalloc + Node) with a Kali pentesting toolbox (nmap, sqlmap, nuclei, ZAP/Burp, ffuf, testssl.sh, jwt_tool, and more). It is driven by sec_serv.sh and is kept on its own network, isolated from the dev stack.

./sec_serv.sh -b      # build the images
./sec_serv.sh -u      # bring the stack up  (target -> http://localhost:13000)
./sec_serv.sh -i      # (re-)initialise the target DB from db/dev_db.sql
./sec_serv.sh -p      # open a shell in the pentest toolbox
./sec_serv.sh -h      # full help

See doc/PENTEST_ENV.md for the full environment setup, the per-tool catalog (purpose, usage, engagement-relevant flags), and the licensing / external-feed activation steps (Nessus, OpenVAS/GVM, nuclei templates, …).

Engagement boot mode (mode selector)

./sec_serv.sh -u first runs an interactive engagement-mode selector (boot_mode.sh) before the containers spin up — a real engagement kickoff. Pick a scenario and the lab tailors itself to it:

Mode Scenario What's in scope to reference AI-assist posture
[1] Black Box External attacker, no prior knowledge Only what recon reveals — no stack, schema, source, or creds Recon-only guidance; the stack stays hidden until you earn it
[2] White Box Full internal access Full stack (heroku-26 / Ruby / jemalloc / Node.js / MariaDB), DB schema, mounted source, sandbox creds Source-assisted: schema-targeted SQLi, FERPA endpoint mapping
[3] Gray Box Role-authenticated (a student account) Authenticated student surface only — no source/admin/schema Auth/authz focused: IDOR/BOLA, privesc, session/JWT

On each boot the selector:

  • Exports PENTEST_MODE (blackbox | whitebox | graybox) into the toolbox container via containers/sec_env/.env. Confirm it inside the toolbox (./sec_serv.sh -p) with echo $PENTEST_MODE.
  • Logs a timestamped record to sessions/SESSION_CONTEXT_<timestamp>.md — selected mode, start time, tester name, the ROE scope reminder, a mode-specific recon checklist + tool order, and a ready-to-paste Claude AI-assist prompt header. Paste that header as the first message in a new Claude session to lock the AI pair-operator into the right mode (e.g. recon-only for Black Box). Commit these to branch Sec for the audit trail.
  • Refreshes the plain-text CoLab Pentest Lab - Quick Start.txt in the repo root (full setup guide + mode-selector reference) so it stays in sync.

Re-running -u re-prompts (it's idempotent). To regenerate just the Quick Start without booting: ./boot_mode.sh --quickstart.

Who do I talk to?

  • @micah_gideon
  • Ask on Slack

Contributors

My two children and their mother, Misun, have been instrumental in making this possible by putting up with me throughout.

About

A collaboration-focused learning management system grounded in research.

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages