129 lines
5.4 KiB
Markdown
129 lines
5.4 KiB
Markdown
# Self-hosted HTTP Toolkit
|
|
|
|
A private distribution repo that builds [HTTP Toolkit](https://httptoolkit.com) into a
|
|
**single self-contained binary** that runs the backend and serves the web UI locally:
|
|
|
|
```bash
|
|
./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**.
|
|
|
|
```bash
|
|
git submodule update --init --recursive
|
|
bash scripts/build.sh # → dist/httptoolkit
|
|
bash scripts/smoke.sh # optional: verify it runs
|
|
```
|
|
|
|
Run it:
|
|
|
|
```bash
|
|
./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
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
git tag v1.27.1 && git push origin v1.27.1
|
|
```
|