The Hackathon Organizer Node

Installation and Setup

Complete installation guide for THON - The Hackathon Organizer Node

Installation and Setup

Prerequisites

System Requirements

  • OS: Linux (Ubuntu 20.04+ recommended)
  • Docker: 20.10+ with Docker daemon running
  • Python: 3.10+
  • Memory: 4GB+ RAM (8GB+ recommended for multiple instances)
  • GPU: AMD ROCm or NVIDIA CUDA (optional, for Lemonade inference)

Network Requirements

  • Ports 443 (nginx HTTPS) and 80 (nginx HTTP) available
  • Port 13305 available for Lemonade Server (optional)
  • Port 9080 available for APISIX AI Gateway (optional)
  • Unique port per VS Code instance (starting from 8443 by default)

Step-by-Step Installation

1. Clone Repository

git clone https://github.com/WaterPistolAI/thon.git
cd thon

2. Run Setup Script

bash ./scripts/setup.sh

This installs:

  • python3 and pip
  • nginx web server
  • docker.io container runtime
  • mkcert for local CA certificates
  • openssl as SSL fallback

With AI Gateway (Optional)

INSTALL_GATEWAY=true bash ./scripts/setup.sh

Additionally installs:

  • apisix API gateway
  • etcd-server configuration store for APISIX
  • redis-server for shared rate limiting

3. Build Docker Image

docker build -t waterpistol/thon:latest ./

The image includes:

  • code-server: VS Code in the browser
  • Python 3.12: Development environment
  • Non-root user: Security best practice

4. Configure THON

# Interactive wizard — creates thon.yaml
python -m thon init

# Review and edit the generated config
cat thon.yaml

The wizard walks you through:

  • External IP (auto-detected)
  • Groups and users
  • Sandbox settings (domain, image, port)
  • VS Code security (password auth)
  • Nginx and SSL
  • Workspace persistence
  • Lemonade Server (local LLM)
  • Kilo Code integration
  • AI Gateway (rate limiting)
  • Dashboard settings
  • OIDC authentication

Option B: Non-Interactive Setup (CI/CD)

python -m thon init --non-interactive

Generates a thon.yaml with sensible defaults:

  • One group alpha with users alice and bob
  • All optional features disabled
  • Can be edited manually afterward

Option C: Manual YAML

Create thon.yaml manually (see Configuration for full reference):

external_ip: "1.2.3.4"
groups:
  alpha:
    - alice
    - bob
  beta:
    - charlie
    - dave
lemonade:
  enabled: false
gateway:
  enabled: false

5. Install Prerequisites and Configure

# Install all prerequisites and configure components from thon.yaml
python -m thon setup

This runs a 6-step process:

  1. System prerequisites (setup.sh)
  2. SSL directory
  3. Lemonade Server (if lemonade.enabled)
  4. AI Gateway (if gateway.enabled)
  5. .env file generation
  6. Summary

6. Run VS Code Instances

# Start instances from thon.yaml
python -m thon run

# Start only one group
python -m thon run --group alpha

Or use main.py directly for more control:

python ./scripts/main.py --groups groups.yaml --external-ip YOUR_EXTERNAL_IP

7. Run the Dashboard (Optional)

The Streamlit dashboard provides a web UI for managing instances, groups, and monitoring the Lemonade server:

pip install streamlit pandas
streamlit run dashboard/streamlit_app.py --server.port 8501

Dashboard available at http://localhost:8501.

Securing the Dashboard

For internal deployments, set a simple password:

AUTH_LOCAL_PASSWORD=mysecret streamlit run dashboard/streamlit_app.py --server.port 8501

For production, enable OIDC authentication on the REST API:

AUTH_ENABLED=true \
AUTH_SESSION_SECRET=$(openssl rand -hex 32) \
AUTH_GITHUB_CLIENT_ID=xxx \
AUTH_GITHUB_CLIENT_SECRET=xxx \
python -m app.main

See Dashboard → Authentication for full details.

The FastAPI REST API also provides Swagger UI at http://localhost:8100/docs for programmatic access:

python -m app.main

See Dashboard for full documentation.

Alternative: Using main.py Directly

If you prefer the traditional CLI approach without thon.yaml:

Create Groups Configuration

Create groups.yaml in your project directory:

groups:
  alpha:
    users:
      - alice
      - bob
  beta:
    users:
      - charlie
      - dave
  gamma:
    users:
      - eve

Run from YAML

python ./scripts/main.py --groups groups.yaml --external-ip YOUR_EXTERNAL_IP

Run from Database

After importing groups via the dashboard, you can start instances from the database:

# Start all groups from database
python ./scripts/main.py --from-db --external-ip YOUR_EXTERNAL_IP

# Start a specific group from database
python ./scripts/main.py --from-db --group beta --external-ip YOUR_EXTERNAL_IP

When using --from-db, PVC workspace volumes from the database are reattached automatically, preserving user data across instance recreations.

Configure SSL Certificates

# Install local CA
mkcert -install

# Generate certificate for your IP
mkcert -cert-file /etc/nginx/ssl/server.crt \
       -key-file /etc/nginx/ssl/server.key \
       165.245.138.159 localhost

Option B: Let's Encrypt (Production)

sudo certbot certonly --standalone -d your-domain.com
sudo cp /etc/letsencrypt/live/your-domain.com/fullchain.pem /etc/nginx/ssl/server.crt
sudo cp /etc/letsencrypt/live/your-domain.com/privkey.pem /etc/nginx/ssl/server.key

Optional: Lemonade Server Setup

For local LLM inference with Kilo Code, Continue, or Cline extensions.

Quick Setup

bash ./scripts/setup-lemonade.sh \
    --groups groups.yaml \
    --generate-keys \
    --external-ip YOUR_EXTERNAL_IP

This will:

  1. Install Lemonade Server from PPA
  2. Configure for your GPU backend
  3. Generate API keys
  4. Download the default chat model (gemma-4-31b-it)
  5. Download the default embedding model (harrier-oss-v1-0.6b)
  6. Create kilo.json for Kilo Code (with semantic indexing config)

Without Embedding Model

bash ./scripts/setup-lemonade.sh \
    --groups groups.yaml \
    --generate-keys \
    --external-ip YOUR_EXTERNAL_IP \
    --no-embedding

Custom llama.cpp Build (AMD MI300X)

For optimal performance on AMD MI300X GPUs:

# Build llama.cpp with ROCm support
bash ./build-amd-mi300x-llama-server.sh

# Then run setup with system binary preference
bash ./scripts/setup-lemonade.sh \
    --groups groups.yaml \
    --generate-keys \
    --external-ip YOUR_EXTERNAL_IP

See Lemonade Server for detailed configuration options.

Optional: AI Gateway Setup

For rate limiting LLM API access with per-user or per-group API keys:

Quick Setup

# Install APISIX (or use INSTALL_GATEWAY=true during initial setup)
INSTALL_GATEWAY=true bash ./scripts/setup.sh

# Setup gateway with per-user rate limiting (includes embedding route)
python scripts/apisix_gateway.py setup --groups groups.yaml \
    --lemonade-url http://127.0.0.1:13305

# Per-group (shared API key per group)
python scripts/apisix_gateway.py setup --groups groups.yaml \
    --lemonade-url http://127.0.0.1:13305 --per-group

# Without embedding route
python scripts/apisix_gateway.py setup --groups groups.yaml \
    --lemonade-url http://127.0.0.1:13305 --no-embedding

Running with Gateway

# Per-user: each user gets their own API key and rate limit
python ./scripts/main.py --groups groups.yaml --external-ip 1.2.3.4 --gateway

# Per-group: all users in a group share an API key with combined rate limit
python ./scripts/main.py --groups groups.yaml --external-ip 1.2.3.4 \
    --gateway --gateway-per-group

# With Redis-backed rate limiting (recommended for multi-gateway)
python ./scripts/main.py --groups groups.yaml --external-ip 1.2.3.4 \
    --gateway --gateway-redis-host 127.0.0.1

See AI Gateway for detailed configuration options.

Running with Lemonade

After setting up Lemonade Server:

python ./scripts/main.py \
    --groups groups.yaml \
    --external-ip YOUR_EXTERNAL_IP \
    --lemonade kilo.json

This injects kilo.json into each sandbox at /home/vscode/.config/kilo/config.json, enabling Kilo Code to connect to your local LLM with both chat and semantic indexing.

Verification

Check Services

# Docker is running
docker ps

# Nginx is configured
ls /etc/nginx/sites-enabled/

# Lemonade server is running (if configured)
sudo systemctl status lemonade-server

# Config is valid
python -m thon config validate

Access VS Code

  1. Open browser to the URL shown in terminal output
  2. For mkcert certificates, install the CA:
    # Download CA certificate
    curl -o ca.crt https://YOUR_IP/ca.crt
    
    # Install in browser (varies by browser)
    # Chrome: Settings > Privacy > Certificates > Authorities > Import
    # Firefox: Settings > Privacy > Certificates > View Certificates > Authorities > Import

Config File Management

The dashboard's Settings page and the /api/config-files REST API allow you to store configuration files in the database:

Config KeyDescription
config_groups_yamlGroups and users definition
config_kilo_jsonKilo Code provider config
config_vscode_settingsVS Code settings for each sandbox

When main.py runs without CLI flags (e.g., python ./scripts/main.py without --groups or --lemonade), it reads these from the database. CLI flags always take precedence over database-stored configs.

Uninstallation

Remove VS Code Instances

# Clean up nginx configs
python ./scripts/main.py --cleanup

# Or use thon CLI
python -m thon cleanup

# Stop all sandboxes (via Docker)
docker ps -q | xargs -r docker stop

Remove Lemonade Server

sudo systemctl stop lemonade-server
sudo apt-get remove --purge lemonade-server
sudo rm -rf /var/lib/lemonade
sudo rm -rf /etc/systemd/system/lemonade-server.service.d

Remove All

# Remove packages
sudo apt-get remove --purge nginx docker.io mkcert

# Remove certificates
sudo rm -rf /etc/nginx/ssl

# Remove Docker image
docker rmi waterpistol/thon:latest

# Remove database
rm -rf ~/.thon/thon.db

On this page