Produkty

Sandboxes

Izolowane środowiska (microVM) do uruchamiania kodu przez agentów AI: exec, pliki, kernel Pythona, podgląd portów, SDK, MCP i AI Gateway.

Sandboxes (Panel → projekt → Sandboxes) to izolowane środowiska uruchamiane na żądanie, w których agent AI lub Twoja aplikacja może bezpiecznie wykonać dowolny kod. Każdy sandbox to osobna maszyna: domyślnie microVM (Kata Containers + Cloud Hypervisor, własne jądro i izolacja KVM), opcjonalnie gVisor (tańszy, szybszy start, jądro w przestrzeni użytkownika). Sandboxy działają wyłącznie na dedykowanym serwerze workerów, bez dostępu do baz danych.

Szybki start

curl -X POST https://host.ulewicz.space/api/v1/projects/<ref>/sandboxes \
  -H "Authorization: Bearer $HOSTBASE_TOKEN" -H "Content-Type: application/json" \
  -d '{"template":"python-3.12"}'
# -> { "id": "sbx...", "state": "running", "timings": { "total_ms": 40, "from_pool": true }, ... }

curl -X POST .../sandboxes/<id>/exec -H "Authorization: Bearer $HOSTBASE_TOKEN" \
  -d '{"cmd":"python3 -c \"print(1+1)\""}'
# -> { "exit_code": 0, "stdout": "2\n", "stderr": "" }

curl -X DELETE .../sandboxes/<id> -H "Authorization: Bearer $HOSTBASE_TOKEN"

Szablony

IdNazwaZawartość
python-3.12Python 3.12 (data science)numpy, pandas, matplotlib, scipy, scikit-learn, seaborn; Jupyter-like kernel with PNG charts and HTML tables
node-22Node.js 22Node.js 22 LTS, npm, git, build tools
bunBun 1Bun runtime, package manager, test runner
ubuntuUbuntu 24.04 (base)Ubuntu 24.04 + Python 3, pip, git, curl, jq, build-essential
playwright-chromiumPlaywright + ChromiumPlaywright with Chromium/Firefox/WebKit (headless browser automation)

Limity i plany

Domyślnie: 1 vCPU, 1024 MB RAM, 5 GB dysku (/workspace), wyłączenie po 5 min bezczynności (idle_timeout_s, 30 s – 24 h; wywołania API, ruch na adresie podglądu i obciążenie CPU ≥ 10% jednego vCPU odnawiają licznik) i po maks. 1 h życia (lifetime_s, do 24 h). Dysk /workspace to osobny obraz ext4 o stałym rozmiarze — zapis ponad limit kończy się błędem „No space left”.

Planmaks. vCPUmaks. RAMmaks. dyskmaks. życierównoleglew cenie (godz. vCPU / godz. GB)
free11024 MB2 GB1 h25 / 10
pro24096 MB20 GB24 h10100 / 200
team48192 MB50 GB24 h40500 / 1000

Exec i strumieniowanie

POST …/exec przyjmuje cmd (tekst uruchamiany w bash -c albo tablica argumentów), cwd, env, timeout_s (domyślnie 60) i stdin. Z "stream": true odpowiedź to strumień SSE zdarzeń {"type":"stdout"|"stderr"|"exit",…}. Z "background": true proces startuje w tle (wyjście w pliku logu), np. serwer HTTP. Zmienne środowiskowe ustawione przy tworzeniu są dostępne w każdym wywołaniu. Interaktywny terminal (xterm.js) jest w panelu; w API: terminal + strumień SSE + input.

Pliki

Ścieżki względne liczą się od /workspace. files/list, files/content (surowe bajty, GET/PUT/DELETE), files/mkdir oraz files/archive (tar — hurtowe wgrywanie i pobieranie katalogu). Limit pojedynczego pliku: 256 MB.

Uruchamianie kodu (kernel)

POST …/run-code z {"code": "…", "language": "python"} działa jak komórka notebooka: kernel Pythona (szablony python-3.12 i ubuntu) zachowuje stan między wywołaniami o tym samym context_id. Odpowiedź zawiera listę results: stdout, stderr, wartość ostatniego wyrażenia (text/plain), tabele text/html (pandas), wykresy matplotlib jako image/png (base64) oraz obiekt error z tracebackiem. Dla javascript (Node/Bun) i bash każdy przebieg jest bezstanowy.

Adresy podglądu portów

Dowolny port sandboxa jest dostępny pod https://<id>-<port>.sbx.workers-waw1.host.ulewicz.space (certyfikat TLS, WebSockety obsługiwane). Domyślnie podgląd jest publiczny (adres zawiera losowy identyfikator); z "preview": "private" wymagany jest token (nagłówek x-hostbase-sandbox-token lub ?hb_token=, zwrócony przy tworzeniu). Odpowiedzi mają X-Robots-Tag: noindex. Dostęp do adresu liczy się jako aktywność (odnawia timeout bezczynności).

Pauza i wznowienie

pause w trybie freeze zamraża maszynę w pamięci (wznowienie w dziesiątkach ms, procesy przeżywają; rozliczana jest tylko połowa stawki za RAM, bez CPU). Tryb stop zatrzymuje maszynę i zwalnia RAM, a zachowuje dysk /workspace (wznowienie to zimny start ok. 2 s, procesy nie przeżywają). Wstrzymany sandbox wygasa po 24 h.

Polityka ruchu wychodzącego

  • open — internet dostępny (domyślnie);
  • allowlist — tylko wskazane nazwy hostów lub adresy IP/CIDR (nazwy są rozwiązywane i odświeżane co 5 min; DNS do 1.1.1.1 / 8.8.8.8 jest dozwolony);
  • none — brak ruchu wychodzącego.

Niezależnie od trybu zablokowane są zawsze: sieci prywatne (RFC1918, w tym serwery baz danych), usługa metadanych chmury, sieci innych sandboxów, port 25 oraz porty typowe dla koparek kryptowalut (stratum).

Metryki, logi, zużycie

metrics zwraca próbki co 10 s (CPU, RAM, sieć, procesy) i zajętość dysku; logs — zdarzenia cyklu życia i log kernela; usage — zużycie miesięczne projektu i organizacji względem limitu planu.

Rozliczenie

Płacisz za zarezerwowane zasoby w czasie, gdy sandbox działa: vCPU-sekundy i GB-sekundy RAM. W planie: Free 5 godz. vCPU i 10 godz. GB (twardy limit), Pro 100 / 200, Team 500 / 1000. Powyżej limitu: 0,25 zł netto za godzinę vCPU i 0,04 zł za godzinę GB. Pozycje widać w Koszty i na fakturze.

Model bezpieczeństwa

  • Izolacja: microVM Kata + Cloud Hypervisor — oddzielne jądro gościa i granica sprzętowa (KVM); gVisor jako opcja. Kod nie widzi hosta ani innych sandboxów.
  • Sieć: osobny mostek i podsieć na sandbox; bez dostępu do sieci prywatnych, metadanych chmury, baz danych i innych sandboxów.
  • Zasoby: sztywne limity CPU, RAM, PID-ów i dysku, wymuszone wyłączenie po bezczynności i po maks. czasie życia.
  • Nadużycia: wykrywamy stale wysycone CPU, procesy koparek i próby połączeń stratum. Sandbox z koparką jest wyłączany, a właściciel dostaje powiadomienie.
  • Sekrety: sandbox nie dostaje kluczy projektu — przekazujesz tylko zmienne env, które sam wskażesz.

Zakresy tokenów

sandboxes:read (lista, metryki, logi, zużycie) i sandboxes:write (tworzenie, exec, pliki, terminal, zamykanie); sandboxes:* daje oba. W rolach projektu zapis mają owner, admin i developer; readonly tylko odczyt.

Management API

GET|POST   /api/v1/projects/{ref}/sandboxes                       (?all=1 includes recently ended)
GET        /api/v1/projects/{ref}/sandboxes/templates
GET        /api/v1/projects/{ref}/sandboxes/usage
GET|DELETE /api/v1/projects/{ref}/sandboxes/{id}
POST       /api/v1/projects/{ref}/sandboxes/{id}/pause          { mode: "freeze" | "stop" }
POST       /api/v1/projects/{ref}/sandboxes/{id}/resume
POST       /api/v1/projects/{ref}/sandboxes/{id}/timeout        { idle_timeout_s, lifetime_s }
POST       /api/v1/projects/{ref}/sandboxes/{id}/egress         { mode: "open"|"allowlist"|"none", hosts }
POST       /api/v1/projects/{ref}/sandboxes/{id}/ports          { port }
POST       /api/v1/projects/{ref}/sandboxes/{id}/exec           { cmd, cwd, env, timeout_s, stdin, stream, background }
POST       /api/v1/projects/{ref}/sandboxes/{id}/run-code       { code, language, context_id, timeout_s }
GET        /api/v1/projects/{ref}/sandboxes/{id}/files/list?path=
GET|PUT|DELETE /api/v1/projects/{ref}/sandboxes/{id}/files/content?path=
POST       /api/v1/projects/{ref}/sandboxes/{id}/files/mkdir?path=
GET|PUT    /api/v1/projects/{ref}/sandboxes/{id}/files/archive?path=   (tar)
GET        /api/v1/projects/{ref}/sandboxes/{id}/metrics
GET        /api/v1/projects/{ref}/sandboxes/{id}/logs
POST       /api/v1/projects/{ref}/sandboxes/{id}/terminal       { cols, rows } -> { session_id }
GET        /api/v1/projects/{ref}/sandboxes/{id}/terminal/{sid}/stream   (SSE, base64 chunks)
POST       /api/v1/projects/{ref}/sandboxes/{id}/terminal/{sid}/input    { data, base64 }
POST       /api/v1/projects/{ref}/sandboxes/{id}/terminal/{sid}/resize   { cols, rows }
DELETE     /api/v1/projects/{ref}/sandboxes/{id}/terminal/{sid}

SDK TypeScript

import { Sandbox } from "@hostbase/sandbox";

const sbx = await Sandbox.create({ apiKey: process.env.HOSTBASE_TOKEN!, project: "<ref>", template: "python-3.12", timeoutS: 600 });
const r = await sbx.exec("ls -la /workspace");               // { exitCode, stdout, stderr }
await sbx.files.write("/workspace/hello.py", "print('hi')");
const text = await sbx.files.read("/workspace/hello.py");
const run = await sbx.runCode("import numpy as np; np.arange(5).sum()");
await sbx.close();

Szkielet SDK dla Pythona znajdziesz w repozytorium (sdk/sandbox-python).

MCP

Narzędzia dla Claude Code, Cursora i innych agentów: create_sandbox, sandbox_exec, sandbox_run_code, sandbox_write_file, sandbox_read_file, list_sandboxes i close_sandbox. Wymagają zakresu sandboxes:write (lista: sandboxes:read).

AI Gateway: code_interpreter

W żądaniu do /api/ai/v1/chat/completions dodaj "hostbase_tools": ["code_interpreter"]. Bramka udostępnia modelowi narzędzie wykonujące Pythona w sandboxie projektu (kernel ze stanem, wykresy zwracane jako obrazy) i prowadzi pętlę narzędzi do 4 rund; sandbox jest zamykany po zakończeniu odpowiedzi.

Wydajność startu

Dla każdego szablonu trzymamy małą pulę rozgrzanych microVM o domyślnym rozmiarze (1 vCPU / 1 GB / 5 GB). Utworzenie sandboxa o domyślnych parametrach przejmuje gotową maszynę (rzędu dziesiątek ms); niestandardowe parametry lub pusta pula oznaczają zimny start (ok. 2 s). Pole timings w odpowiedzi pokazuje, co się stało.

Pomiary na host-workers-waw1 (D4as_v5, 4 vCPU / 16 GB)

KrokMediana / zakres
Utworzenie z puli (domyślny rozmiar, microVM)12-29 ms
Pierwsze polecenie po utworzeniu130-200 ms
Utworzenie, zimny start microVM1.9-2.1 s / 1.8-1.9 s / 1.6 s / 1.6 s / 1.6 s
Utworzenie, zimny start gVisor0.65 s / 0.60 s
Management API POST /sandboxes end-to-end (z puli)~260 ms
Pauza (freeze) / wznowienie41-46 ms / 37-48 ms
Pauza (stop) / wznowienie (start VM)0.54 s / 1.4 s
run-code Python, pierwsze wywołanie (import pandas + matplotlib) / kolejne2.5 s / 0.12 s
Zamknięcie (usunięcie VM, dysku, sieci)0.63-0.68 s

Pula rozgrzanych maszyn: 3 x python-3.12, 2 x ubuntu, 2 x node-22 (uzupełniana w tle, ok. 2 s na sztukę). Zimny start obejmuje utworzenie mostu sieciowego, obrazu dysku ext4, start maszyny Kata + Cloud Hypervisor i oczekiwanie na agenta gościa.