oxid/ docs

// 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.

ComponentWhat it isDocs
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.

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:

  1. Token — paste OXID_API_TOKEN (or grab it from docker compose logs when OXID_AUTO_TOKEN=1).
  2. Infrastructure — one-click bootstrap of Docker network + Traefik (idempotent; direct-publish mode shows "nothing to bootstrap" instead).
  3. First project — register by Git URL (https://github.com/you/app.git, scp-style git@host:org/repo.git works too; private repos take an encrypted PAT) or a path under the mounted ./repos. First deploy of main kicks off for you with live polling.
  4. Webhooks — pick provider, copy URL + auto-generated secret into your Git host.
  5. 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

native / manual
$ 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.