How to Update Hysteria Core to the Latest Version: 3 Methods Explained

You can update Hysteria core using the built-in check-update command, rely on automatic 24-hour background checks, or execute the official install script from scripts/install_server.sh.

Hysteria provides multiple mechanisms to keep its core binary current, ranging from manual CLI commands to fully automatic background updates. Whether you are running a server or client instance, the repository at apernet/hysteria ensures you can quickly verify and install the latest release without manual binary management. This guide covers all update pathways using the actual source implementation.

Method 1: Using the Built-In Update Command

The fastest way to manually verify your version is through the check-update subcommand defined in app/cmd/update.go. This command constructs an UpdateChecker instance and queries the Hysteria update API to compare your current build against the latest release.

When you invoke hysteria check-update, the application executes the check immediately and prints the results. For server deployments, the code uses utils.NewServerUpdateChecker, while client deployments use utils.NewClientUpdateChecker to route the request through the active Hysteria connection, preventing SNI fingerprinting by censors.


# Display current installed version

hysteria version

# Check for available updates

hysteria check-update

Method 2: Automatic Background Updates

Hysteria can automatically check for updates every 24 hours without user intervention. This mechanism is implemented in app/cmd/update.go through the functions runCheckUpdateServer and runCheckUpdateClient, which spawn a background goroutine executing checkUpdateRoutine.

The routine creates a time.NewTicker(updateCheckInterval) set to 24 hours and repeatedly queries the update API. When an update is available, the process logs the new version, download URL, and urgency flag.

To disable this behavior, pass the --disable-update-check flag defined in app/cmd/root.go:


# Start server with automatic update checks disabled

hysteria --disable-update-check server -c config.yaml

Method 3: Updating via the Install Script

For server administrators, the scripts/install_server.sh bash script provides a complete update workflow. The script detects your environment, compares the installed version against the latest release using the vercmp function, and handles binary replacement automatically.

The script supports three operational modes:

  • Check mode (-c or --check): Verifies if an update is available without installing
  • Install mode (default): Downloads and installs the latest binary via download_hysteria only if newer than the current version
  • Force mode (-f or --force): Re-installs the binary even when get_installed_version matches get_latest_version

# Check only without installing

curl -sSL https://get.hy2.sh | bash -s -- --check

# Standard update (or fresh install)

curl -sSL https://get.hy2.sh | bash -s --

# Force reinstallation regardless of current version

curl -sSL https://get.hy2.sh | bash -s -- -f

The script places the binary at /usr/local/bin/hysteria by default.

Understanding the Update Mechanism

The core update logic resides in app/internal/utils/update.go within the UpdateChecker struct. Understanding this implementation helps diagnose connectivity or version-check failures.

API Endpoint and Request Structure

The checker sends a GET request to https://api.hy2.io/v1/update with query parameters encoding the current version, platform, architecture, channel, and side (server or client):

const updateCheckEndpoint = "https://api.hy2.io/v1/update"
url := fmt.Sprintf("%s?cver=%s&plat=%s&arch=%s&chan=%s&side=%s",
    updateCheckEndpoint, uc.CurrentVersion, uc.Platform,
    uc.Architecture, uc.Channel, uc.Side)
resp, err := uc.Client.Get(url)

Response Handling

The API returns a JSON UpdateResponse containing:

  • update: Boolean indicating if a newer version exists
  • lver: Latest version string (e.g., "v2.6.0")
  • url: Direct download URL for the new binary
  • urgent: Boolean flag marking critical security updates

Transport Differences

  • Server checks use a standard http.Client instantiated via NewServerUpdateChecker
  • Client checks route HTTP requests through the active Hysteria connection using NewClientUpdateChecker, ensuring the update check traffic is indistinguishable from regular data and cannot be blocked by simple SNI filters

Programmatic Update Checks

You can integrate update checking into custom Go applications using the UpdateChecker utilities. This is useful for building management dashboards or monitoring tools that track version drift across deployments.

import (
    "fmt"
    "github.com/apernet/hysteria/app/internal/utils"
    "github.com/apernet/hysteria/core/v2/client"
)

func checkForUpdate(hyClient client.Client) {
    // Create checker for client side (tunnelled through hyClient)
    checker := utils.NewClientUpdateChecker(
        "v2.5.1", "linux", "amd64", "release", hyClient,
    )
    
    resp, err := checker.Check()
    if err != nil {
        panic(err)
    }
    
    if resp.HasUpdate {
        fmt.Printf("New version %s available: %s\n", 
            resp.LatestVersion, resp.URL)
    } else {
        fmt.Println("You are on the latest version.")
    }
}

Summary

  • Use hysteria check-update for immediate manual checks via the Cobra command in app/cmd/update.go
  • Automatic background checks run every 24 hours via checkUpdateRoutine unless disabled with the --disable-update-check flag
  • The install script at scripts/install_server.sh handles complete server upgrades using get_latest_version and vercmp logic
  • Server and client instances use different transport methods: plain HTTP for servers, tunneled connections for clients to avoid censorship
  • All mechanisms query https://api.hy2.io/v1/update and return structured UpdateResponse data containing version, URL, and urgency indicators

Frequently Asked Questions

How often does Hysteria check for updates automatically?

Hysteria checks for updates once every 24 hours when the automatic background ticker is enabled. This interval is hardcoded as updateCheckInterval in app/cmd/update.go. The check runs in a separate goroutine started by either runCheckUpdateServer or runCheckUpdateClient after the main process initializes, ensuring the binary stays current without user interaction.

What is the difference between server and client update checking?

Server update checks use a standard HTTP client that connects directly to the update API via NewServerUpdateChecker, while client checks route the request through the active Hysteria connection using NewClientUpdateChecker. This tunneling approach prevents censors from detecting update checks through SNI fingerprinting or blocking the update API endpoint separately from the proxy traffic.

Can I update Hysteria without stopping the service?

The install script (scripts/install_server.sh) downloads the new binary to a temporary location and replaces the executable at /usr/local/bin/hysteria, but you must restart the service to load the new binary into memory. For zero-downtime updates, deploy the new binary alongside the running instance, swap the files, and trigger a graceful restart via your process manager or init system.

Why does the install script report the latest version is already installed when I want to force an update?

The install script compares versions using the vercmp function and skips the download_hysteria step if the installed version matches the latest release. To force a reinstallation regardless of the current version, use the -f or --force flag when running the script, which bypasses the version comparison and executes the download and installation routine immediately.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →