Multi-tenant VM hosting platform. Users get full Alpine Linux VMs via Telegram and Solana payments.
make build
export TELEGRAM_BOT_TOKEN="your-token"
export SOLANA_RPC="mainnet"
sudo ./hive
Access admin dashboard at `http://localhost:49160` (deployed at `https://krons.cx/hive`)
Alpine Linux 3.21 with:
| Variable | Default | Description |
|----------|---------|-------------|
| `ADDRESS` | `0.0.0.0:49160` | API listen address |
| `DATA_DIR` | `/srv/data/hive` | VM storage path |
| `SPOOL_DIR` | `/srv/spool/hive` | Download cache |
| `TELEGRAM_BOT_TOKEN` | Required | Platform bot token |
| `SOLANA_RPC` | `mainnet` | Solana RPC endpoint |
| `PAYMENT_AMOUNT` | `0.1` | SOL per VM |
See [internal/util/config.go](internal/util/config.go) for all options.
Production deployment at `krons.cx/hive` uses nginx reverse proxy:
Local development runs on `localhost:49160` without prefix.
| Method | Path | Description |
|--------|------|-------------|
| `POST` | `/api/vm` | Create VM (auto-starts) |
| `GET` | `/api/vm` | List VMs (?archived=true/false) |
| `GET` | `/api/vm/{id}` | VM details |
| `DELETE` | `/api/vm/{id}` | Soft delete VM |
| `POST` | `/api/vm/{id}/start` | Start VM |
| `POST` | `/api/vm/{id}/stop` | Stop VM |
| `POST` | `/api/vm/{id}/archive` | Archive VM |
| `POST` | `/api/vm/{id}/unarchive` | Unarchive VM |
| `POST` | `/api/vm/{id}/config` | Update credentials (pushed to agent) |
| `GET` | `/api/vm/{id}/log` | Serial console log |
| `*` | `/api/vm/{id}/proxy/*` | HTTP/WS proxy to agent |
| `*` | `/api/vm/{id}/files/*` | Caddy file browser (entire filesystem) |
| `*` | `/api/vm/{id}/files/webdav/root/*` | WebDAV write access to /root |
| `GET` | `/api/events` | SSE stream of VM events |
| `GET` | `/api/generate-name` | Generate artist-themed name |
| `GET` | `/health` | Health check |
WebSocket terminal: `ws://localhost:49160/api/vm/{id}/proxy/v1/shell` (login shell for PATH)
WebSocket Claude: `ws://localhost:49160/api/vm/{id}/proxy/v1/claude-stream`
Agent endpoints at `:11435` in each VM:
**Reverse Proxy Support**: Centralized API URL handling via `apiUrl()` helper respects `X-Forwarded-Prefix` header for deployment at `krons.cx/hive`. All fetch calls and WebSocket connections work transparently whether running locally or behind nginx.
**Agent Health Checking**: Platform queries agent `/status` endpoint to distinguish between booting (QEMU running but agent not ready) and running (fully operational) states.
**Login Shell**: WebSocket terminal spawns `bash -l` to automatically source `/etc/profile` and `/etc/profile.d/*`, ensuring tools like `uv`, `bun`, `g`, and npm globals are in PATH.
**File Access**: Caddy serves entire filesystem from `/` with browse enabled. WebDAV provides read-only access to all files, write access to `/root` only. Protected by HTTP Basic Auth when credentials configured.
**Event Notifications**: SSE events trigger UI notification banners in header (max 5, FIFO eviction). Auto-dismiss after timeout or manual close.
**Retry Logic**: Claude CLI installation retries once after 5s delay on network errors during VM provisioning.
make build # Build api and agent
make test # Fast unit tests (<5s)
make smoke # Full e2e suite (~80s)
make lint # go vet, staticcheck
make fmt # go fmt
cd tests/web
npx playwright test # Run all tests
npx playwright test archive # Specific test file
npx playwright test --headed # With browser UI
npx playwright test --grep @slow # Only slow tests
Test suite covers:
See [tests/web/TEST_SUITE_SUMMARY.md](tests/web/TEST_SUITE_SUMMARY.md) for details.
cmd/hive/ API server entry point
internal/
├── util/ Configuration, name generation
├── vm/ VM lifecycle, networking, QEMU
├── platform/ User management, Telegram, payments, events
└── server/ HTTP handlers and routing
agent/ Guest agent (:11435 in each VM)
web/ Admin dashboard (htmx + xterm.js)
tests/ Integration and E2E tests
cloud-init.tmpl VM provisioning template
See [ARCHITECTURE.md](ARCHITECTURE.md) for system design, [CLAUDE.md](CLAUDE.md) for developer reference.