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 thon2. Run Setup Script
bash ./scripts/setup.shThis 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.shAdditionally 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
Option A: Interactive Setup (Recommended)
# Interactive wizard — creates thon.yaml
python -m thon init
# Review and edit the generated config
cat thon.yamlThe 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-interactiveGenerates a thon.yaml with sensible defaults:
- One group
alphawith usersaliceandbob - 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: false5. Install Prerequisites and Configure
# Install all prerequisites and configure components from thon.yaml
python -m thon setupThis runs a 6-step process:
- System prerequisites (
setup.sh) - SSL directory
- Lemonade Server (if
lemonade.enabled) - AI Gateway (if
gateway.enabled) .envfile generation- Summary
6. Run VS Code Instances
# Start instances from thon.yaml
python -m thon run
# Start only one group
python -m thon run --group alphaOr use main.py directly for more control:
python ./scripts/main.py --groups groups.yaml --external-ip YOUR_EXTERNAL_IP7. 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 8501Dashboard 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 8501For 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.mainSee Dashboard → Authentication for full details.
The FastAPI REST API also provides Swagger UI at http://localhost:8100/docs
for programmatic access:
python -m app.mainSee 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:
- eveRun from YAML
python ./scripts/main.py --groups groups.yaml --external-ip YOUR_EXTERNAL_IPRun 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_IPWhen using --from-db, PVC workspace volumes from the database are
reattached automatically, preserving user data across instance recreations.
Configure SSL Certificates
Option A: mkcert (Recommended for Development)
# 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 localhostOption 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.keyOptional: 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_IPThis will:
- Install Lemonade Server from PPA
- Configure for your GPU backend
- Generate API keys
- Download the default chat model (gemma-4-31b-it)
- Download the default embedding model (harrier-oss-v1-0.6b)
- Create
kilo.jsonfor 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-embeddingCustom 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_IPSee 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-embeddingRunning 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.1See 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.jsonThis 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 validateAccess VS Code
- Open browser to the URL shown in terminal output
- 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 Key | Description |
|---|---|
config_groups_yaml | Groups and users definition |
config_kilo_json | Kilo Code provider config |
config_vscode_settings | VS 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 stopRemove 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.dRemove 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