Self-hosted control panel for Discord bots. Drag & drop a bot folder into the browser, fill in the env vars, hit Start — the panel handles runtime detection, dependency installation, process supervision and real-time log streaming. Everything runs inside a single Docker container, with SQLite on disk for state.
No login screen. No external services. Intended for a homelab network.
- Drag & Drop & Start — drop a whole folder (or a
.zip) into the UI. The panel auto-detects the runtime (Node.js / Python), the main file (index.js,bot.py, etc.) and the.envtemplate. - Dynamic environment form — parsed from
.env/.env.exampleand rendered as a form. Saving writes back to the on-disk.env. - Start / Stop / Restart per instance with live Online/Offline status.
- Live console & file browser per instance, powered by WebSockets.
- Auto-restart on crash (with exponential backoff) and auto-start on panel boot.
- Resource limits (CPU soft-limit, RAM hard-kill via the monitor loop).
- Backup / restore — download any instance as a
.zip. - System health dashboard — CPU, RAM, disk and uptime for the host.
- Dark / light HUD aesthetic — Space Grotesk + IBM Plex Mono + Instrument Serif, corner-bracket cards, HUD status bar.
# 1. Clone or copy this directory
cd h0melab-bot-hosting
# 2. Build & run
docker compose up -d --build
# 3. Open the panel
# http://localhost:8080That's it. The container creates ./data on first boot — keep that
directory if you want your bots to survive docker compose down.
- Click + New Instance on the dashboard, give it a name.
- Open the instance, drag your bot folder into the dropzone.
- The panel proposes a runtime and a main file — confirm or pick another from the dropdown.
- Click Install dependencies (runs
npm installorpip install -r requirements.txtinside the instance folder). - Fill in the
.envform under the Environment tab. - Hit ▶ Start. Logs stream live in the Console tab.
┌────────────────────────── Docker container ──────────────────────────┐
│ │
│ ┌────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │
│ │ Frontend │ │ FastAPI │ │ Bot Manager (asyncio) │ │
│ │ (React, │◄──┤ backend │◄──┤ spawns / supervises / │ │
│ │ Vite bld) │ │ /api + /ws │ │ monitors child procs │ │
│ └────────────┘ └──────┬───────┘ └────────────┬─────────────┘ │
│ │ │ │
│ ┌──────▼──────┐ ┌───────▼────────┐ │
│ │ SQLite DB │ │ /data/instances │ │
│ │ (metadata) │ │ /data/logs │ │
│ └─────────────┘ │ /data/backups │ │
│ └─────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘
- Backend: Python 3.12 + FastAPI.
asyncio.create_subprocess_execgives us one task per bot without needingsupervisord. - Frontend: React 18 + Vite, built into static assets and served by
FastAPI's
StaticFiles. - Runtime in the container: Python 3.12 and Node.js 20 so the panel can run both Python and JavaScript Discord bots directly.
- State: SQLite file at
/data/h0melab.db. No separate DB container. - Ports: only
8000(HTTP + WebSocket) is exposed.
.
├── backend/
│ └── app/
│ ├── main.py FastAPI app + lifespan hooks
│ ├── config.py Paths & env-driven config
│ ├── database.py SQLAlchemy 2 engine/session
│ ├── models.py BotInstance ORM model
│ ├── schemas.py Pydantic request/response types
│ ├── bot_manager.py Process supervisor & log bus
│ ├── detector.py Runtime / entrypoint / .env detection
│ ├── file_handler.py Uploads, zip, file browser, backups
│ ├── system_info.py Host CPU/RAM/disk sampling
│ └── routers/ FastAPI routers (instances, files, ws, system)
├── frontend/
│ └── src/ React app (components, pages, features)
├── Dockerfile Multi-stage single-container build
├── docker-compose.yml
└── README.md
# terminal 1 — backend
cd backend
python -m venv .venv && source .venv/bin/activate # or .venv\Scripts\activate on Windows
pip install -r requirements.txt
H0MELAB_DATA_DIR=./_data \
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# terminal 2 — frontend
cd frontend
npm install
npm run dev # Vite dev server on :5173, proxies /api + /ws to :8000Open http://localhost:5173.
All tunables are environment variables — set them in docker-compose.yml
or your shell:
| Variable | Default | Purpose |
|---|---|---|
H0MELAB_DATA_DIR |
/data |
Where DB, instance folders, logs, backups live. |
H0MELAB_LOG_RING_SIZE |
2000 |
Max log lines per instance kept in memory. |
H0MELAB_MAX_UPLOAD_SIZE |
524288000 (500 MB) |
Maximum upload size per request. |
H0MELAB_FRONTEND_DIR |
/app/frontend |
Location of the built SPA. |
- The panel has no authentication by design — expose it on trusted networks only (homelab VLAN, Tailscale, Wireguard, a reverse proxy with auth, etc.). There is no user account system.
- Uploaded code runs with the same privileges as the container process. Treat every bot you install as if you had written it yourself.
- Resource limits in the UI are soft — a rogue bot that forks
aggressively can still impact the host. The
deploy.resources.limitsblock indocker-compose.ymlcaps the whole panel. - The file browser enforces strict path-traversal checks so API clients cannot read or write outside an instance directory.
- "No entrypoint configured" — open the Settings tab, pick the correct file from the dropdown, click Save settings.
- Bot crashes immediately after start — open the Console tab; the last few stderr lines are usually enough to diagnose missing env vars or uninstalled dependencies. Hit Install dependencies from Settings if you haven't yet.
- Uploads fail with 413 — raise
H0MELAB_MAX_UPLOAD_SIZE. - Panel does not start:
docker logs h0melab-bot-hosting— the most common cause is a volume with wrong permissions.chown -R 1000 ./datausually fixes that on Linux hosts.
MIT.