Files
httptoolkit/README.md
T
2026-08-15 02:14:26 +05:00

5.4 KiB

Self-hosted HTTP Toolkit

A private distribution repo that builds HTTP Toolkit into a single self-contained binary that runs the backend and serves the web UI locally:

./httptoolkit --port 7070
# → starts the proxy server and opens the web UI at http://localhost:7070

No Electron, no hosted UI, no account/login. Upstream is tracked as git submodules and all local modifications live in this repo as patches + an overlay, so updating to a new upstream release is a controlled, reviewable step.

Layout

.
├── httptoolkit-ui/         # submodule → github.com/httptoolkit/httptoolkit-ui (pinned)
├── httptoolkit-server/     # submodule → github.com/httptoolkit/httptoolkit-server (pinned)
├── patches/
│   ├── ui/                 # diffs against upstream UI files
│   └── server/             # diffs against upstream server files
├── overlay/server/         # NEW files copied into the server submodule (never conflict)
│   ├── htk-entry.ts        #   single-file binary entry (Bun)
│   └── src/
│       ├── htk-app.ts      #   shared: run backend + serve UI + open browser
│       └── commands/app.ts #   oclif fallback command
├── scripts/
│   ├── apply.sh            # reset submodules → apply patches → copy overlay
│   ├── build.sh            # build UI → embed → bun compile → dist/
│   └── smoke.sh            # launch binary & verify it serves + backend is up
├── .build/prod/           # Docker builder (Gitea `docker-compose` runner)
│   ├── Dockerfile         #   Node + Bun + native toolchain
│   ├── compose.yml        #   mounts repo, runs build.sh
│   ├── build.sh           #   build + smoke → out/
│   └── release.sh         #   Gitea-API release + upload
└── .gitea/workflows/build.yml

What the patches change

Kind File Change
UI patch src/model/account/account-store.ts injects a synthetic active Pro subscription
UI patch src/components/settings/settings-page.tsx removes the account/subscription card
UI patch src/components/app.tsx removes the "Give feedback" sidebar button
Server patch src/constants.ts allow localhost/127.0.0.1 origins in prod builds
Overlay htk-entry.ts, src/htk-app.ts, src/commands/app.ts serve the UI locally + --port

Security note: upstream restricts a packaged build's API to https://app.httptoolkit.tech so no other local page can drive your proxy. Because we self-host the UI on localhost we must allow localhost origins (this matches upstream's own dev-mode allowlist). Trade-off: any local HTTP page could talk to the server while it's running. Acceptable for a personal tool.

Build locally

Requires node ≥22, npm, bun, and tar.

git submodule update --init --recursive
bash scripts/build.sh          # → dist/httptoolkit
bash scripts/smoke.sh          # optional: verify it runs

Run it:

./dist/httptoolkit --port 7070          # UI on :7070
./dist/httptoolkit --no-open            # don't auto-open a browser
./dist/httptoolkit --help

Updating to a new upstream release

# bump a submodule to a new tag
cd httptoolkit-ui && git fetch && git checkout v<new> && cd ..
git add httptoolkit-ui

# re-apply and see if patches still fit
bash scripts/apply.sh

If a patch no longer applies, apply.sh fails and names the patch. Fix it:

cd httptoolkit-ui
git checkout -- .                       # reset
# hand-apply the change, then regenerate the patch:
git diff -- <file> > ../patches/ui/000X-....patch

Overlay files never conflict (they're new files), so only the small patches/ diffs ever need attention on upgrade.

Packaging notes / risks

  • Single file via Bun --compile. The server pulls in native .node addons (node-datachannel, registry-js, adbkit, …). These cannot be cross-compiled, so the binary is built per host platform. scripts/smoke.sh is the guard: if a native addon won't load from the embedded FS, it fails there.
  • Linux only, for now. CI builds inside a Linux Docker container, which produces a trustworthy Linux x64 binary. Windows/macOS binaries are not reliably buildable from Linux Docker (foreign-platform native addons can't be produced or smoke-tested there, and macOS needs signing) — they'd need real Windows/macOS runners.
  • The UI is embedded as ui.tar.gz and extracted to $TMPDIR/httptoolkit-ui-<version> on first run.
  • No HTK_SERVER_TOKEN is set, so the local UI talks to the backend without a token.

CI (Gitea Actions, Docker)

Matches the docker-compose runner convention:

  • .gitea/workflows/build.yml — on a v* tag (or manual dispatch): checks out with submodules, runs docker compose run --rm prod in .build/prod/, then creates a Gitea release and uploads the artifacts via the Gitea API (secrets.PAT_GITEA).
  • .build/prod/ — the Docker builder:
    • Dockerfile — Node 22 + Bun + native-build toolchain
    • compose.yml — mounts the repo at /source, caches npm/bun
    • build.sh — runs scripts/build.sh + scripts/smoke.sh, drops the binary in out/
    • release.sh — Gitea-API release + asset upload

Tag a release:

git tag v1.27.1 && git push origin v1.27.1