// docs
What is Oxid
Oxid is a self-hosted control plane for branch-based preview environments with real scale-to-zero. Push a branch, get a URL; stop pushing, get your RAM back. This section of the docs covers the moving parts at a working-strength level — enough to operate it day to day, without restating every line of the source.
| Component | What it is | Docs |
|---|---|---|
oxidd |
The daemon: HTTP control plane, SQLite state, secret encryption, Docker orchestration, GC/scheduler, embedded dashboard. A single static binary. | Daemon |
oxid |
The CLI: a thin HTTP client over the daemon's API. Full lifecycle, secrets, backups, multi-daemon contexts, --json everywhere. |
CLI |
| Web dashboard | Embedded in the daemon binary — no build step, no bundler. Same API, different surface. | Dashboard |
| Traefik optional | When OXID_DOCKER_NETWORK is set, containers get Host() subdomains instead of published ports — and wake-on-request scale-to-zero activates. |
Daemon |
Everything talks to one HTTP surface — the CLI and the dashboard are thin clients over
the same API you can drive with curl.
CLI reference
Every command, option and exit code: lifecycle, observation, secrets, contexts, backups and day-2 operations.
Daemon
Running oxidd: every environment variable, defaults, and what lives inside the data directory.
HTTP API
The /api/v1 surface: authentication rules and every endpoint the CLI and dashboard use.
Web dashboard
The embedded UI served at the daemon root — sections, auth and what it can (and can't) do.
Quickstart — 60 seconds to first preview
Zero-config Docker, a five-click wizard, then every push deploys itself. The whole
install is one command plus a browser tab — no .env to hand-wire.
1 — Run the stack
Recommended: one line from nothing — verifies checksums, generates secrets (0600, never rotated on re-run), pulls ghcr.io/sazardev/oxid, starts daemon + Traefik, waits for health and verifies wiring.
curl -fsSL https://raw.githubusercontent.com/sazardev/oxid/main/install.sh | sh -s -- --docker # → Dashboard: http://localhost:8080 (wizard auto-opens) # or manually, no .env needed thanks to OXID_AUTO_TOKEN=1: docker compose up -d docker compose logs oxid-daemon | grep -A2 Generated # your token, printed once
Docker is required on the daemon host only. The CLI runs anywhere with network access to the daemon — point it via --api or a context.
2 — Walk the wizard (5 clicks)
Open http://localhost:8080 — first visit auto-redirects to /ui/onboarding:
- Token — paste
OXID_API_TOKEN(or grab it fromdocker compose logswhenOXID_AUTO_TOKEN=1). - Infrastructure — one-click bootstrap of Docker network + Traefik (idempotent; direct-publish mode shows "nothing to bootstrap" instead).
- First project — register by Git URL (
https://github.com/you/app.git, scp-stylegit@host:org/repo.gitworks too; private repos take an encrypted PAT) or a path under the mounted./repos. First deploy ofmainkicks off for you with live polling. - Webhooks — pick provider, copy URL + auto-generated secret into your Git host.
- CLI — copy-paste
oxid context add prod --api … --token …snippet. Done → environments page.
Everything here is also available as CLI/API: oxid infra setup, POST /api/v1/projects {"repo_url": …}, POST /api/v1/infra/bootstrap.
3 — Push and breathe
$ git push origin feature-carrito [>] Building image (cache hit: 85%) ... [+] https://feature-carrito.local.dev (or :port in direct-publish mode) $ oxid up main --repo https://github.com/you/app.git # same flow from the CLI $ oxid status # live URLs + ports $ oxid logs -f feature-carrito
Every push deploys its branch; deleting the branch destroys its environment. No traffic for a while? Oxid pauses it and gives the RAM back — next request wakes it in milliseconds.
Other ways to run
$ curl -fsSL .../install.sh | sh -s -- --server # systemd + auto secrets + Traefik
$ curl -fsSL .../install.sh | sh # CLI + daemon binaries only
$ OXID_DATA_DIR=~/.oxid oxidd # bare binary
$ docker run -d -v /var/run/docker.sock:/var/run/docker.sock \
-v oxid-data:/data -p 8080:8080 \
-e OXID_API_TOKEN=$(openssl rand -hex 32) \
-e OXID_WEBHOOK_SECRET=$(openssl rand -hex 32) \
ghcr.io/sazardev/oxid:latest
See Daemon → Environment variables for every knob, and Home → Install for the marketing one-pager.