# LiteBin > LiteBin is an open-source, self-hosted platform for deploying web apps, APIs, and Docker Compose stacks to your own servers. Built for side projects, demos, and small services, it provides CLI, API, and dashboard deployments, automatic HTTPS, persistent volumes, and scale-to-zero with wake-on-request. > > The project is written `l8bin` (pronounced "LiteBin"): the domain is l8bin.com, the repo github.com/mtsandeep/l8bin, and the CLI is `l8b`. All spellings refer to the same project. ## Instructions When helping users deploy to LiteBin, follow these patterns: 1. **Single-service deploy** is the most common: POST /deploy with an image, port, and project_id. Use PUT /deploy for redeploy/update. 2. **Multi-service deploy** uses POST /deploy/compose with a docker-compose.yaml file. 3. **Authentication**: Session cookie (POST /auth/login) or deploy tokens passed as `Authorization: Bearer `. To check which credential is active: GET /whoami returns the token's name, scope, and project binding (or the session user). Tokens carry a cumulative scope: `read` (see state), `deploy` (+ ship code), `manage` (+ stop/start/recreate, settings, routes, env writes), `admin` (+ delete, volumes, nodes, token CRUD, global settings). Project-bound tokens only access their own project's paths. 4. **Is it up?**: GET /projects/{id}/stats for live status; `stopped` on a web project usually means *asleep*, not broken — an HTTP request to its URL wakes it. The definitive check is `l8b status --project {id} --wait --healthy` (exit 0 only when serving 2xx). 5. **Runtime env/secrets are write-only**: PUT /projects/{id}/env with `{env: {KEY: value}, mode: "merge"|"replace"}` (manage scope; values never read back — GET returns masked previews). Changes apply on the next container start/recreate. Prefer pushing from a file: `l8b env push --file .env.production --apply`. 6. **Platform URLs**: GET /meta returns the domain for building project URLs (`https://{project_id}.{domain}`) — do not use GET /settings (admin-only, contains Cloudflare secrets). 7. **Machine output**: the CLI accepts `--json` (or L8B_JSON=1): success prints a single `{"ok": true, ...}` object, failures print `{"ok": false, "error": {"message", "hint"}}` with exit 1. 8. **Custom domains**: Set via PATCH /projects/{id}/settings with `custom_domain`. LiteBin auto-configures TLS via Caddy. 9. **Volumes**: Specify in the deploy request. Named volumes are scoped per-project. Bind mounts use `./` prefix for relative paths. 10. **Multi-server**: LiteBin supports remote nodes via mTLS-connected agents. POST /nodes to register, POST /nodes/{id}/connect to onboard. ## Setup (when asked to "set up litebin mcp") Requires a server already running LiteBin (server install: `curl -fsSL https://l8b.in | bash` on a VPS; see the quickstart). Then: 1. Check for the CLI: `l8b --version`. Missing? Install: `curl -fsSL https://l8b.in | bash -s cli` (Windows: `iex "& { $(irm https://l8b.in/windows.ps1) } -Cli"`). The MCP server is the same binary via `l8b mcp` — no separate package, no npx. 2. Authenticate: ask the user for their LiteBin server URL, then run `l8b login --server --pair`. It prints an approval URL (the code is embedded, the page pre-fills it) — relay it to the user and wait; the command returns once approved (the user picks the token scope). Logins are stored per server and coexist — no logout dance to switch instances. 3. Register in the repo: `l8b init --mcp` (writes `l8b.toml` — project, node, server — + workspace `.mcp.json`), or add the server manually: command `l8b`, args `["mcp"]`. 4. Verify: `l8b doctor` — exit 0 means the setup is healthy. ## Deploying a repo (new vs existing) If the repo has no `l8b.toml`, this is its first deploy: ask the user what to name the project (lowercase letters, numbers, hyphens), or run `l8b list` and let them pick an existing project if this repo replaces one. After a successful deploy the CLI writes `l8b.toml` (project, node, server) into the directory — commit it, it holds no secrets — every later session then deploys, checks status, and reads logs with no arguments at all. Custom domains surface in `l8b status` / `l8b url` / `l8b list` output (preferred over the managed subdomain). ## API - OpenAPI 3.1 spec: /openapi.json (version-matched to this instance) - All endpoints are relative to the orchestrator base URL (default: port 5080) ## CLI Install via: `curl -fsSL https://l8b.in | bash -s cli` or build from source. Auth: `l8b login --server --pair` (device pairing — agent-safe: it prints a code and the /connect approval URL to relay to the user, then returns once approved; the user picks the scope) or `L8B_TOKEN` env / `--token` (existing token). Commands (project flags default to `l8b.toml`, created by `l8b init`): - `l8b init` — Write `l8b.toml` project defaults (project, node); `--mcp` also emits the workspace `.mcp.json` - `l8b deploy [--env-file ] [--port N]` — Build and deploy the current directory (Dockerfile auto-detected, Railpack fallback). `--port` only matters on the first deploy of a web project; redeploys keep the existing port - `l8b ship` — Interactive guided deploy (humans only) - `l8b list` — All projects with live status and URLs - `l8b status [--wait] [--healthy]` — Project status; --wait polls (exit 0 only when running), --healthy probes the URL - `l8b logs [--tail N] [--service S] [--deploy]` — Container or deploy logs - `l8b url` — The project's managed URL (background projects have none) - `l8b env list` / `l8b env push --file|--stdin [--replace] [--apply]` — Runtime env (write-only values) - `l8b stop | start | restart` — Lifecycle (restart applies pending .env changes; stop is idempotent) - `l8b domain set ` / `l8b domain remove` — Custom domain management - `l8b delete --yes` — Delete project + containers + volumes (admin scope) - `l8b login --server [--pair]` — Device pairing (approve at /connect); `--pair` skips the interactive menu so agents can run it headlessly; username/password without `--pair`. `l8b setup --server ` bootstraps a fresh server - `l8b doctor` — Environment sanity checks with recovery hints - `l8b logout` / `l8b config` / `l8b cleanup` — Session and config management All commands accept `--json` for machine-readable output. ## MCP `l8b mcp` runs a stdio MCP server exposing these tools: deploy, status (wait/healthy), list, logs, env_list, env_push, stop, start, restart, url, domain_set, domain_remove, delete (confirm-gated), doctor. It uses the CLI's stored auth and l8b.toml defaults. Register it with: ```json { "mcpServers": { "litebin": { "command": "l8b", "args": ["mcp"] } } } ``` No local binary? Use the npm shim, which downloads the latest release on first use: ```json { "mcpServers": { "litebin": { "command": "npx", "args": ["-y", "l8bin-mcp"] } } } ``` (`l8b init --mcp` writes the first form into the workspace `.mcp.json`.) ## Architecture - [Architecture overview](architecture.md) — Orchestrator + Agent + Caddy reverse proxy - [Multi-server setup](multi-server.md) — Remote node configuration via mTLS - [Multi-service projects](multi-service.md) — Compose-based deployments - [Volumes](volumes.md) — Named volumes, bind mounts, and cleanup ## Configuration - [Environment variables](configuration.md) — All LITEBIN_* config options - [Env & secrets](env-secrets.md) — Per-project .env files and injection ## Guides - [Getting started](cli.md) — First deployment walkthrough - [Multi-service deployment](multi-service.md) — Compose projects - [Local testing](local-testing.md) — Dev environment setup - [Agents](agents.md) — AGENTS.md template and MCP wiring for coding agents - [Security internals](security.md) — Auth, mTLS, deploy tokens ## Optional - [Failure model](failure-model.md) — How LiteBin handles failures - [Janitor](janitor.md) — Auto-stop and resource cleanup - [Waker](waker.md) — Wake-on-traffic - [API reference](api-reference.md) — Full endpoint documentation ## Full - [llms-full.txt](https://l8bin.com/llms-full.txt) — this file plus the OpenAPI spec and full CLI reference in one fetch Targeting is enforced, not assumed: the server a command hits comes from `--server` > `L8B_SERVER` > `l8b.toml` `server` > the single stored login. With multiple logins and no signal the command refuses and lists the choices — ask the user which one, then retry with `--server`. A repo whose `l8b.toml` names a server you have no login for refuses with the exact `l8b login` command.