Skip to content

Release Build

The native release combines the Rust workspace build with the console assets. The release workflow builds console/, uploads the synced assets/console/ directory, and then builds --bin gproxy for each native target.

Run this when console source, translations, routing, or styling changed:

Terminal window
cd console
pnpm install --frozen-lockfile
pnpm build
cd ..

pnpm build performs:

  1. tsc -b
  2. vite build
  3. node ./scripts/sync-to-embed.mjs

The final step copies console/dist/ into assets/console/. The native server embeds that directory through rust-embed and serves it at /console.

From the repository root:

Terminal window
cargo build --release --bin gproxy

The output is:

target/release/gproxy

For a target-specific build:

Terminal window
cargo build --release --bin gproxy --target x86_64-unknown-linux-gnu

The release workflow builds Linux glibc, Linux musl, macOS, Windows, and Android targets. Linux GNU and musl builds cover x86_64, AArch64, and RISC-V 64; the RISC-V targets are cross-compiled with cross. Android archives include the NDK libc++_shared.so runtime beside a small gproxy launcher script; the actual ELF binary is packaged as gproxy.bin. The launcher prepends the archive directory to LD_LIBRARY_PATH so ./gproxy can find the bundled C++ runtime after extraction. The Android targets also publish per-ABI APKs (arm64-v8a and x86_64) that carry the same native payload. The workflow also smoke-checks selected binaries with --help before packaging.

Each native matrix job keeps the portable ZIP and also emits the platform installer where applicable: Linux .deb, macOS .dmg, Windows .msi, and Android .apk. The installer templates live under scripts/installers/; the packaging entry points are package-linux-deb.sh, package-macos-dmg.sh, package-windows-release.ps1, and package-native-release.sh for APK/ZIP.

The Docker release combines amd64, arm64, and riscv64 images into both the default GNU manifest and the -musl manifest.

The binary is configured by CLI flags and environment variables. There is no v2 TOML runtime config file.

Common settings:

CLI Env Default
--host GPROXY_HOST 127.0.0.1
--port GPROXY_PORT 8787
--persistence GPROXY_PERSISTENCE db
--data-dir GPROXY_DATA_DIR ./data
--dsn GPROXY_DSN SQLite under <data-dir>/gproxy.db
--redis-url GPROXY_REDIS_URL in-process memory cache
--admin-user GPROXY_ADMIN_USER admin
--admin-password GPROXY_ADMIN_PASSWORD random first-boot password if needed

GPROXY_MASTER_KEY is env-only. It must be standard base64 for exactly 32 bytes when you want v2 to seal credentials and user API keys at rest.

For a simple archive:

Terminal window
mkdir -p dist
cp target/release/gproxy dist/gproxy
cp README.md dist/
(cd dist && zip -9 ../gproxy-local.zip gproxy README.md)
shasum -a 256 gproxy-local.zip > gproxy-local.zip.sha256

The release workflow may UPX-compress selected Linux, Android, and Windows artifacts before packaging. It signs macOS artifacts ad hoc with codesign --sign -. Android APKs are signed with the configured release keystore. Tagged release builds require the configured signing secrets; local or non-release packaging may fall back to an ephemeral debug key.

On startup the native server:

  1. creates GPROXY_DATA_DIR;
  2. builds the secret cipher from GPROXY_MASTER_KEY;
  3. auto-migrates a v1 SQLite database when the default v1-to-v2 conditions match;
  4. opens the configured persistence backend;
  5. imports GPROXY_IMPORT_FILE only if providers and users are empty;
  6. ensures or recovers the admin user;
  7. registers per-user desktop login startup on the first eligible run;
  8. starts the cache, upstream transport, snapshot, router, console, and gateway.

Android uses its foreground service and boot receiver instead of the Rust desktop startup manager. Containers, headless sessions, and configurations that depend on secrets or external connection URLs are not auto-registered.

Use ./gproxy --help to inspect every current flag on the built binary.