# How to Build Hysteria Core from Source: A Complete Developer Guide

> Learn to build Hysteria core from source using hyperbole.py for cross-platform compilation or go build for single-platform binaries. Get detailed developer instructions now.

- Repository: [Aperture Internet Laboratory/hysteria](https://github.com/apernet/hysteria)
- Tags: how-to-guide
- Published: 2026-05-13

---

**You can build Hysteria core from source using the repository's [`hyperbole.py`](https://github.com/apernet/hysteria/blob/main/hyperbole.py) script, which automates cross-platform compilation and injects version metadata, or by running `go build` directly on the `app/` directory for quick single-platform binaries.**

Hysteria is a high-performance QUIC-based proxy written in Go. While pre-built binaries are available, compiling the core from the **apernet/hysteria** repository gives you full control over build flags, platform targets, and bleeding-edge features. The build process centers on the [`app/main.go`](https://github.com/apernet/hysteria/blob/main/app/main.go) entry point and relies on the [`hyperbole.py`](https://github.com/apernet/hysteria/blob/main/hyperbole.py) helper to manage complex cross-compilation logic.

## Prerequisites

Before building, ensure your environment meets these requirements:

- **Git** (for cloning and version detection)
- **Go 1.22 or later** (the `go.mod` declares module requirements)
- **Python 3** (only required if using the Hyperbole build script)

Clone the repository to your local machine:

```bash
git clone https://github.com/apernet/hysteria.git
cd hysteria

```

## Method 1: Build with Hyperbole (Recommended)

The **Hyperbole** build script ([`hyperbole.py`](https://github.com/apernet/hysteria/blob/main/hyperbole.py)) is the official method for producing release-grade binaries. It handles platform detection, environment variable injection, and linker flag configuration automatically.

### Environment Variables

Control the build by exporting these variables before running the script:

- `HY_APP_VERSION` – Custom version tag (e.g., `v2.4.5`)
- `HY_APP_COMMIT` – Git commit hash (defaults to `git rev-parse HEAD` output)
- `HY_APP_PLATFORMS` – Comma-separated list of `os/arch` targets (e.g., `linux/amd64,windows/amd64,darwin/arm64`)

### Build Command

Execute the script to compile for your specified platforms:

```bash
export HY_APP_VERSION=v2.4.5
export HY_APP_COMMIT=$(git rev-parse HEAD)
export HY_APP_PLATFORMS="linux/amd64,windows/amd64"

python3 hyperbole.py build

```

The script generates binaries in `./build/` with platform-specific naming (e.g., `hysteria-linux-amd64`, `hysteria-windows-amd64.exe`).

For optimized release builds that strip debug symbols, append the `--release` (or `-r`) flag:

```bash
python3 hyperbole.py build --release

```

## Method 2: Build with Go Directly

For rapid development or single-platform testing, invoke the Go toolchain directly without the Python wrapper:

```bash
go build -o hysteria ./app

```

This produces a binary for your current operating system and architecture. However, the binary will lack embedded version information unless you manually pass the linker flags that the Hyperbole script automatically injects.

To replicate the official build metadata, include the `-ldflags` argument:

```bash
go build -o hysteria \
  -ldflags "-X github.com/apernet/hysteria/app/v2/cmd.appVersion=v2.4.5 \
            -X github.com/apernet/hysteria/app/v2/cmd.appCommit=$(git rev-parse HEAD) \
            -X github.com/apernet/hysteria/app/v2/cmd.appDate=$(date -u +%Y-%m-%dT%H:%M:%SZ) \
            -X github.com/apernet/hysteria/app/v2/cmd.appType=release \
            -X github.com/apernet/hysteria/app/v2/cmd.libVersion=v0.9.0" \
  ./app

```

## Understanding the Build Architecture

The **core** library resides in the `core/` directory, containing the QUIC transport implementation, congestion control algorithms, and proxy logic. The **executable** entry point is [`app/main.go`](https://github.com/apernet/hysteria/blob/main/app/main.go), which imports the command package from `app/v2/cmd/`.

When building, the `-ldflags` inject values into variables defined in the `cmd` package:

```go
// Located in app/v2/cmd/
var (
    appVersion   string
    appCommit    string
    appDate      string
    appType      string
    libVersion   string
    appPlatform  string
    appArch      string
)

```

These values appear when running `hysteria -version`, enabling accurate debugging and support requests.

### Android-Specific Considerations

For Android targets, the Hyperbole script automatically sets **CGO_ENABLED=1** and configures the appropriate `CC` compiler wrapper. It also appends `-checklinkname=0` to the linker flags to satisfy Go 1.23+ restrictions on internal symbol references.

```bash

# Hyperbole handles these automatically for android/arm64

export CGO_ENABLED=1
go build -ldflags "-checklinkname=0 -X ..." ./app

```

## Summary

- **Use [`hyperbole.py`](https://github.com/apernet/hysteria/blob/main/hyperbole.py)** for production builds, cross-compilation, and automatic metadata injection via `HY_APP_VERSION`, `HY_APP_COMMIT`, and `HY_APP_PLATFORMS`.
- **Use `go build ./app`** for quick local development cycles on your host machine.
- **Reference [`app/main.go`](https://github.com/apernet/hysteria/blob/main/app/main.go)** as the binary entry point and `core/` for the underlying library implementation.
- **Include `-ldflags`** with the nine `-X` variables defined in `app/v2/cmd/` to prevent "unknown" version strings in your binaries.

## Frequently Asked Questions

### What is the minimum Go version required to build Hysteria?

Hysteria requires **Go 1.22 or later**, as specified in the `go.mod` file. Using older versions will result in compilation errors due to language features and dependency requirements in the `core/` package.

### Why does my binary show "unknown" version when I build manually?

This occurs when the linker flags are omitted during compilation. The version strings are set at build time via `-X` flags that map to variables in `app/v2/cmd/`. Without these flags, the variables retain their zero values ("unknown"). Either use [`hyperbole.py`](https://github.com/apernet/hysteria/blob/main/hyperbole.py) or manually specify the `-ldflags` as shown in the direct build method.

### Can I build Hysteria for Android from source?

Yes. The [`hyperbole.py`](https://github.com/apernet/hysteria/blob/main/hyperbole.py) script supports Android cross-compilation by setting `CGO_ENABLED=1` and adding `-checklinkname=0` to work around Go 1.23+ linker restrictions. Ensure you have the Android NDK toolchain installed and configured in your `PATH` before building.

### Where is the core library located versus the application entry point?

The **core library** implementing the QUIC proxy logic lives in the `core/` directory. The **application entry point** is [`app/main.go`](https://github.com/apernet/hysteria/blob/main/app/main.go), which imports packages from `app/v2/cmd/` to handle CLI arguments and start the server. When compiling, you target `./app` (the folder containing [`main.go`](https://github.com/apernet/hysteria/blob/main/main.go)), not the `core/` directory directly.