Building from Source
The Release workflow publishes dev pushes to nightly (the dev update channel),
and main pushes to staging (the beta update channel). Stable version releases
come from main and update both release and beta; they never overwrite dev.
Versioned releases are built on
v* tags matching the workspace version. The instructions below cover source
builds; .github/workflows/release.yml drives automated packaging.
Before pushing dev, run bash scripts/push-dev.sh to rebase on the latest main.
Enable the local push guard with git config core.hooksPath .githooks.
Public attachments contain packages, manifest.json, and SHA256SUMS;
individual checksum files and build provenance remain internal CI inputs.
Release packages
Section titled “Release packages”CLI (gproxy-*) and Application (gproxy-tauri-*) are separate programs;
each has its own portable archives and installers. Applications embed the Console.
| Platform | CLI | Application |
|---|---|---|
| Linux GNU (x86_64, aarch64, riscv64) | ZIP, DEB | ZIP, DEB |
| Linux musl (x86_64, aarch64, riscv64) | ZIP, Alpine APK | ZIP, Alpine APK |
| Windows (x86_64, aarch64) | ZIP, MSIX | ZIP, MSIX |
| macOS (x86_64, aarch64) | ZIP, DMG | ZIP, DMG |
| Android (x86_64, aarch64) | ZIP, Termux DEB | APK only |
| OpenHarmony / HarmonyOS NEXT | ARM64 / x86_64 ZIP | ARM64 unsigned HAP |
The Linux CLI DEB installs gproxy under /usr/bin; the Termux DEB installs
under /data/data/com.termux/files/usr. Android CLI builds use the source
recipe in distribution/termux/ and a pinned official Termux builder.
Both DEB and ZIP use Termux’s libc++, OpenSSL and CA certificates; ZIPs include
the launcher, executable and TERMUX.txt with installation/update instructions.
Self-update is disabled in these builds: install a newer DEB with APT, or use
pkg upgrade gproxy once an enabled repository provides it. Windows CLI
MSIX uses a distinct .CLI identity and a console execution alias. macOS CLI
DMGs include the executable and Terminal installation instructions.
Application ZIPs retain desktop resources and, on macOS, the complete .app.
OHOS builds use a cached toolchain image and a pinned experimental Tauri branch; other platforms retain stable Tauri. HAP files require signing before installation. The HAP has been verified on an emulator. Continuous background execution is implemented, but availability depends on the device, OS version and granted permissions; the proxy stops when the application process exits.
Nightly filenames stay fixed; the manifest records the commit SHA. GNU Linux Applications require the distribution’s GTK 3 and WebKitGTK 4.1 packages. musl builds target Alpine and ship as APKs, not DEBs. macOS uses ad-hoc signing; Developer ID signing and notarization are not configured.
Windows uses the Microsoft Store package identity. Configure four variables in
the release environment: MS_STORE_IDENTITY_NAME, MS_STORE_DISPLAY_NAME,
MS_STORE_IDENTITY_PUBLISHER, and MS_STORE_PUBLISHER_DISPLAY_NAME. Stable
releases retain both architecture packages for Store submission. With
MS_STORE_PUBLISH_ENABLED enabled, successful GitHub publication triggers the
Store submission workflow. The MSIX files on GitHub are unsigned, just like the
Store submission packages; the Store signs them for distribution. They are not
trusted packages that can be installed by double-clicking. The app requires the
system WebView2 Runtime.
Android APKs are signed and verified using the existing ANDROID_SIGNING_*
secrets. Each app’s <target-triple>-tauri-apk entry joins the Ed25519-signed
update manifest, separately from CLI ZIP updates. The legacy server-wrapper APK is no longer built. Missing required keys or Store identity variables fail packaging.
For a local build, prepare the Console and invoke the packaging script:
pnpm --dir console buildnode console/scripts/sync-to-embed.mjspnpm --dir crates/gproxy-host-tauri install --frozen-lockfileTARGET_OS=linux TARGET_TRIPLE=x86_64-unknown-linux-gnu \ ARTIFACT_NAME=gproxy-tauri-linux-x86_64 \ GPROXY_BUILD_VERSION=$(scripts/release-metadata.sh version) \ scripts/package-tauri-release.shOutputs go to dist/release/. The workflow also publishes native server ZIPs,
Termux packages, Edge bundles, and GNU/musl container images. Application
packages receive build provenance attestations hosted on GitHub.
Build environment
Section titled “Build environment”Install stable Rust (edition 2024), Go, Clang, Node.js 22.12+ (24 LTS recommended), and pnpm. Linux desktop builds also need the webkit2gtk-4.1, gtk+-3.0, and libsoup-3.0 development packages. The release workflow configures the other platform toolchains.
Build the CLI and console
Section titled “Build the CLI and console”From the repository root:
pnpm --dir console install --frozen-lockfilepnpm --dir console buildcargo build -p gproxy --release./target/release/gproxy serve --data-dir ./dataThe console build copies resources into the HTTP and Tauri embed directories. A subsequent Rust build includes them. A fresh checkout built with Rust alone has no console assets, so /console returns 404. You can also pass --console-path console/dist to serve a separate build.
CLI defaults include all channels, memory cache, local file storage, and bundled vocabulary. Select fewer channels or add backends as needed:
cargo build -p gproxy --release --no-default-features \ --features embedded-console,memory,fs,codex,claudecode,openai,customPostgreSQL, MySQL, Redis, and S3 require postgres, mysql, redis, and s3 respectively. SQLite is always available.
Headless CLI for CI
Section titled “Headless CLI for CI”The Release workflow builds headless packages independently of the frontend:
| Platform | Architectures | Package |
|---|---|---|
| Linux GNU | x86_64, aarch64, riscv64 | gproxy-headless-linux-<arch>.zip |
| Linux musl | x86_64, aarch64, riscv64 | gproxy-headless-linux-<arch>-musl.zip, gproxy-headless-linux-<arch>-musl.apk |
| Windows | x86_64, aarch64 | gproxy-headless-windows-<arch>.zip |
| macOS | x86_64, aarch64 | gproxy-headless-macos-<arch>.zip |
| Android (Termux) | x86_64, aarch64 | gproxy-headless-android-<arch>.zip, gproxy-headless-android-<arch>.deb |
Download from Releases: nightly
for dev, staging for beta, or a stable version. Self-update selects the matching
headless package. On Android, install the Termux package with
pkg install ./gproxy-headless-android-<arch>.deb and run gproxy serve --console=false.
It replaces the full gproxy package, as both provide the gproxy command. To use
the ZIP instead, run pkg install libc++ openssl ca-certificates, extract it under
Termux’s home directory, then run ./gproxy serve --console=false.
On Windows, use gproxy.exe in place of gproxy.
This variant excludes the bundled Web console and retains proxy routes, management APIs, all channels, SQLite, memory cache, local file storage and bundled vocabulary. Configure it through the CLI or management API. It needs no Node.js, pnpm or desktop libraries to build:
cargo build --locked --release -p gproxy --bin gproxy \ --no-default-features --features channels,memory,fs,bundled-vocabulary,postgres,mysql./target/release/gproxy serve --console=falseOmitting embedded-console excludes frontend assets even when the checkout
already contains a built console. --console=false also disables serving an
external console directory. To build a console-enabled variant with a custom
feature set, add embedded-console.
Build Application
Section titled “Build Application”After building the console:
cargo run -p gproxy-host-tauri --bin gproxy-desktopA new instance opens the setup wizard. The window manages it over IPC, while the HTTP listener serves gateway clients. Use the release workflow’s platform toolchains and packaging scripts for mobile builds.
The default workspace members exclude Tauri so backend builds do not require desktop dependencies. --workspace includes it.
Build Workers
Section titled “Build Workers”From the repository root:
rustup target add wasm32-unknown-unknowncargo install worker-buildpnpm --dir console install --frozen-lockfilepnpm --dir deploy/cloudflare installpnpm --dir deploy/cloudflare buildpnpm --dir deploy/cloudflare checkworker-build compiles and optimizes WASM. check runs a Wrangler deployment dry run without publishing. See Edge deployment for configuration and runtime restrictions.
Validate changes
Section titled “Validate changes”Backend default members:
cargo fmt --all --checkcargo clippy --all-targets -- -D warningscargo testCheck the desktop host separately:
cargo clippy -p gproxy-host-tauri --all-targets -- -D warningscargo test -p gproxy-host-tauriWASM checks include supported libraries and hosts, not the CLI or Tauri. Do not use the entire workspace for this target:
cargo check --target wasm32-unknown-unknown \ -p gproxy-protocol -p gproxy-store -p gproxy-seaorm -p gproxy-client \ -p gproxy-cache -p gproxy-channel -p gproxy-core -p gproxy-file \ -p gproxy-tokenizer -p gproxy-sdk -p gproxy-app -p gproxy-host-axum \ -p gproxy-host-edgeConsole and docs:
pnpm --dir console lintpnpm --dir console testpnpm --dir console buildpnpm --dir docs install --frozen-lockfilepnpm --dir docs checkpnpm --dir docs buildbash scripts/check-docs.shAfter changing Rust DTOs, run pnpm --dir console types to regenerate the TypeScript types.
Publish
Section titled “Publish”Run bash scripts/release.sh from a clean checkout included in main. Before
pushing a stable tag, it updates Console and docs npm dependencies with
pnpm update --latest, upgrades Rust registry requirements with cargo upgrade
(including major and pinned versions), and refreshes Cargo.lock with cargo update.
Compatibility bridges for RSA/getrandom, JNI/Tauri, Codex reqwest and WebSocket
configs retain their upstream-required version lines; compatible updates still
refresh through cargo update.
Install the Rust helper with cargo install cargo-edit --locked first.
If these commands change tracked files, the script stops before creating or
pushing the tag. Resolve compatibility changes, run the checks above, commit and
push to main, then rerun the script. Prerelease tags skip this dependency refresh.
A version tag must match the workspace version and have a docs/release-notes/v<version>.md file. The workflow builds packages, creates a signed update manifest, and uploads assets. A build or signing failure means publication is incomplete.
Version tags also invoke scripts/publish-crates.sh for selected MIT libraries. Other crates use git or path dependencies; see Embedding the core.