Skip to content

jonscafe/whaley

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🐳 Whaley

Dedicated Docker Instancer for CTF Competitions

Features β€’ Quick Start β€’ Documentation β€’ Screenshots β€’ Contributing


πŸ“‹ Overview

Whaley is a production-ready Docker instance manager designed specifically for Capture The Flag (CTF) competitions. Deploy it on a dedicated server to provide each participant with their own isolated challenge environmentβ€”complete with automatic port allocation, resource limits, and seamless CTFd integration.

Why Whaley?

Problem Whaley's Solution
Shared challenge instances cause interference πŸ”’ Isolated containers per user/team
Manual port management is error-prone 🎯 Automatic port allocation with collision prevention
No visibility into player resource usage πŸ“Š Real-time monitoring dashboard
Difficult to detect flag sharing πŸ” Suspicious submission detection
Complex setup for dynamic flags πŸ’‰ Simple CTFd integration with auto flag injection

✨ Features

πŸš€ Core Functionality

  • Dynamic Instance Spawning β€” Isolated Docker containers per user/team
  • Automatic Port Allocation β€” Smart port management (10000-60000 range)
  • Multi-Port Challenges β€” Support for complex multi-service challenges
  • Auto-Cleanup β€” Instances automatically terminated after timeout
  • Docker Compose Support β€” Standard .yaml and .yml formats
  • Enforced Resource Limits β€” Global memory, CPU & PID caps enforced on all containers
  • Per-Challenge Resource Overrides β€” Fine-tune limits per challenge from admin panel

πŸ” Authentication & Security

  • CTFd Integration β€” Validate users via CTFd access tokens
  • No-Auth Mode β€” IP-based identification for open events
  • Network Isolation β€” Each instance in its own Docker network
  • Distributed Locking β€” Redis-based locks for multi-worker safety
  • Fork Bomb Protection β€” PID limits per container

🚩 Dynamic Flags

  • Unique Flags β€” Each user/team gets unique flag per challenge
  • Auto Flag Injection β€” Inject flags into challenge files at build time
  • CTFd Registration β€” Automatically register flags with CTFd
  • Submission Monitoring β€” Detect and log flag sharing attempts
  • Team Mode Support β€” Shared flags per team when enabled

πŸ“Š Monitoring & Admin

  • Real-Time Metrics β€” Live CPU/RAM usage per container
  • Instance Forensics β€” Capture logs on termination or on-demand
  • Admin Dashboard β€” Web UI for monitoring and management
  • Challenge Manager β€” Upload & edit challenges without SSH
  • Challenge Toggle β€” Activate/deactivate challenges from admin panel
  • Admin Settings UI β€” Configure all Whaley settings via the web UI (no env/compose edits needed)
  • Event Logging β€” Comprehensive audit trail with Docker errors

πŸš€ Quick Start

Prerequisites

  • Docker Engine 24.0+ with Docker Compose v2
  • 4+ CPU cores, 8GB+ RAM (see capacity planning)
  • Linux server (Ubuntu 22.04+ or Debian 12+ recommended)

Installation

# Clone the repository
git clone https://github.com/jonscafe/whaley.git
cd whaley

# Configure environment
cp .env.example .env
nano .env  # Edit with your settings

# Start Whaley
docker compose up -d

Access Points

Interface URL Description
User Dashboard http://your-server:8000/ Challenge spawning interface
Admin Panel http://your-server:8000/admin Monitoring & management
API Docs http://your-server:8000/docs Swagger API documentation

βš™οΈ Configuration

Essential Settings

# Authentication
AUTH_MODE=ctfd                    # "ctfd" or "none"
CTFD_URL=https://your-ctfd.com    # Your CTFd instance URL
CTFD_API_KEY=ctfd_xxx...          # CTFd admin API key

# Network
PUBLIC_HOST=auto                  # VPS IP ("auto" for detection)
PORT_RANGE_START=20000
PORT_RANGE_END=50000

# Admin
ADMIN_KEY=your-secure-key         # Admin dashboard access key

# Dynamic Flags
DYNAMIC_FLAGS_ENABLED=true
FLAG_PREFIX=FLAG                  # e.g., FLAG{...}

# Team Mode
TEAM_MODE=auto                    # "auto", "enabled", or "disabled"

Production Settings (Optional)

# PostgreSQL for high availability
DATABASE_URL=postgresql+asyncpg://user:pass@db:5432/whaley

# Redis for distributed locking (required for multiple workers)
REDIS_URL=redis://redis:6379/0

# Network Isolation (recommended)
NETWORK_ISOLATION_ENABLED=true
NETWORK_ICC_DISABLED=true

# Resource Limits (enforced on all containers)
CONTAINER_MAX_MEMORY=512m         # Max memory per container
CONTAINER_MAX_CPU=1.0             # Max CPU cores per container
CONTAINER_PIDS_LIMIT=256          # Max PIDs per container (fork bomb protection)

πŸ’‘ Tip: Most settings (including Authentication & CTFd integration) can be configured instantly via the Admin Panel β†’ βš™οΈ Settings tab.

πŸ“– Full configuration guide: See DOCUMENTATION.md


πŸ“ Challenge Structure

Create challenges in the challenges/ directory:

challenges/
└── my-web-challenge/
    β”œβ”€β”€ challenge.yaml        # Challenge metadata
    β”œβ”€β”€ docker-compose.yaml   # Container definition
    β”œβ”€β”€ Dockerfile
    β”œβ”€β”€ flag.txt              # Flag file (auto-injected)
    └── src/
        └── app.py

challenge.yaml

id: my-web-challenge
name: "SQL Injection Lab"
category: web
description: "Can you bypass the login?"
ports:
  - 80
timeout: 3600  # 1 hour

docker-compose.yaml

services:
  web:
    build: .
    ports:
      - "${PORT_80}:80"
    environment:
      - FLAG=${FLAG}
    mem_limit: 256m
    cpus: 0.5

⚠️ Resource enforcement: Even if a challenge sets mem_limit: 2g, Whaley will cap it to the global CONTAINER_MAX_MEMORY (default 512m). You can set per-challenge overrides via the admin panel.

πŸ“– More examples: See DOCUMENTATION.md


πŸ‘₯ Team Mode

Whaley supports CTFd Team Mode where instances and flags are shared per-team:

Feature User Mode Team Mode
Instance Ownership Per user Per team
Dynamic Flags Unique per user Shared per team
Instance Control Only spawner Any team member
Suspicious Detection User vs User Team vs Team

Enable with TEAM_MODE=auto to automatically detect from CTFd settings.


πŸ“Š Capacity Planning

Estimation Formula

Concurrent Instances = Teams Γ— Active Challenges Γ— 0.5
RAM Required = Concurrent Instances Γ— 256MB (average)
Ports Required = Concurrent Instances Γ— Ports per Challenge

Server Recommendations

Event Size CPU RAM Storage Example
Small (≀50 teams) 4 cores 8 GB 40 GB SSD Local CTFs
Medium (50-150 teams) 8 cores 32 GB 100 GB SSD University CTFs
Large (150-300 teams) 16 cores 64 GB 200 GB SSD National CTFs

Example Calculation

Scenario: 150 teams, 5 active challenges, 2 ports each

  • Peak instances: 150 Γ— 5 Γ— 0.5 = 375 instances
  • RAM needed: 375 Γ— 256MB = ~96 GB (recommend 64 GB with swap)
  • Ports needed: 375 Γ— 2 = 750 ports

πŸ“Έ Screenshots

User Dashboard
User Dashboard
Admin Dashboard
Admin Dashboard
Event Logs
Event Logs
Challenge Manager
Challenge Manager
Dynamic Flags
Dynamic Flags
CTFd Sync
CTFd Challenge Sync

βš™οΈ Admin Settings & Challenge Management

Live Settings (No Restart Required)

All key Whaley settings can be changed at runtime via the Admin Panel β†’ βš™οΈ Settings tab:

Category Settings
Instance Timeout, max instances per user/team
Resources Container max memory, CPU cores, PID limit
Network Port range, isolation, public host
Features Dynamic flags, flag prefix
Authentication Auth mode (CTFd/None), CTFd URL, Admin Key
Forensics Auto capture, retention period

Changes persist to the database and survive container restartsβ€”no need to edit docker-compose.yaml or .env files.

Challenge Active/Inactive Toggle

Control which challenges are visible and spawnable from the Challenge Manager tab:

  • 🟒 Active β€” Visible on the user dashboard, can be spawned
  • πŸ”΄ Inactive β€” Hidden from users, spawn requests rejected (HTTP 403)

Use this during competitions to stage challenges for later rounds, or to quickly disable a broken challenge without deleting it.

Enforced Resource Limits

Whaley enforces maximum resource limits on every container, regardless of what the challenge's docker-compose.yaml specifies:

CONTAINER_MAX_MEMORY=512m    # Caps mem_limit in compose files
CONTAINER_MAX_CPU=1.0        # Caps cpus in compose files
CONTAINER_PIDS_LIMIT=256     # Injects pids_limit (fork bomb protection)

Per-challenge overrides can be set via the admin API if certain challenges need more resources.


πŸ“– Documentation

For comprehensive documentation, see DOCUMENTATION.md:


🀝 Contributing

Contributions are welcome! Here's how you can help:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Ideas for Contribution

  • πŸ› Bug fixes and improvements
  • πŸ“ Documentation enhancements
  • 🎨 UI/UX improvements
  • πŸ§ͺ Test coverage
  • 🌐 Internationalization

πŸ“„ License

This project is licensed under the MIT License β€” see the LICENSE file for details.


πŸ‘¨β€πŸ’» Author

keii
keii

Creator & Maintainer

Built with ❀️ for the CTF community

If you find Whaley useful, please consider giving it a ⭐

GitHub stars

About

🐳 Whaley - a dedicated docker instancer for ctf competitions

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors