Skip to main content

HexRift

Python Build Coverage License uv Ruff

Config generator for the Conglomerate distributed proxy network. Takes a topology definition and produces Xray JSON configs and HAProxy configs for every node. Hub nodes additionally support WireGuard and XDNS inbounds.

Installation

uv sync

Usage

All commands require a topology YAML file:

hexrift --yaml conglomerate.yaml <command>

Commands

Command Description
validate Validate the topology YAML against the schema
show Visualize the network topology (regions, nodes, users, guests, portals)
derive [users|groups|portals|nodes|all] Show derived identifiers (UUIDs, shortIds, emails)
nodes list [--names|--domains|--json] [--type exit|hub] List nodes with hostnames; machine-friendly output for automation
nodes add NODE_ID [--type exit|hub] [--region ID] [--hostname HOST] [--no-ipv6] [--hysteria] [--reality-dest HOST:PORT] [--reality-server-names LIST] [--xhttp-path PATH] Add a node to its region in the topology YAML, creating the region when missing
nodes remove NODE_ID Remove a node from the topology YAML, keeping its region
gen-keys [NODE_ID|--all] [--force] [--keys-dir PATH] Generate x25519 + ML-KEM 768 keypairs for nodes
build [NODE_ID|--all] --xray|--haproxy [--keys-dir PATH] [--out-dir PATH] Build Xray config.json and/or HAProxy .cfg
gen-portal [PORTAL_ID|--all] [--group ID] [--fp FINGERPRINT] [--out-dir PATH] [--keys-dir PATH] Build Xray bridge config.json for portal(s) from the top-level portals: section
diff NODE_ID [--current-dir PATH] [--keys-dir PATH] Diff generated config against deployed config
share USERNAME [--hub NODE_ID] [--fp FINGERPRINT] [--cdn] [--wg] [--server] [--guest LABEL] [--all-guests] [--bare] [--keys-dir PATH] Generate VLESS share URLs or WireGuard client configs (--wg)

Examples

# Validate topology
hexrift validate

# Visualize topology
hexrift show

# Show all derived identifiers
hexrift derive all

# List all exit node IDs (for scripts)
hexrift nodes list --names --type exit

# Structured node list (id, hostname, region, type) for other tools
hexrift nodes list --json

# Add a node to the topology file (creates the region if needed)
hexrift nodes add nlA20 --reality-dest www.samsung.com:443 --xhttp-path /login/

# Generate keys for all nodes
hexrift gen-keys --all

# Build Xray config for a specific node
hexrift build nlA00 --xray --out-dir ./out

# Build all configs (Xray + HAProxy)
hexrift build --all --xray --haproxy --out-dir ./out

# Diff against deployed config
hexrift diff nlA00 --current-dir /etc/xray

# Generate a share link (CDN URL)
hexrift share alice --cdn

# Generate share links for all guests of a user
hexrift share alice --all-guests --bare | clip

# Generate a WireGuard client config
hexrift share alice --wg

Topology options

Beyond the basic hub/exit split:

  • HAProxy-less nodes - by default every node runs HAProxy on :443 in front of Xray. Set haproxy: false to drop HAProxy and have Xray's Reality inbound bind 0.0.0.0:443 (or [::]:443 when ipv6 is supported) directly. build --haproxy then emits a no-op stub haproxy.cfg so managed HAProxy service stays up without touching :443. CDN (cdn_xhttp_path) needs HAProxy TLS termination and cannot be combined with haproxy: false.
  • All-in-one node - set routing.hub_default: direct to make a hub egress everything itself (direct outbound) instead of routing to exit region. This allows topology with hub node(s) and no exit regions - single node clients connect to that proxies straight to the internet. hub_routes still apply for per-domain/user exceptions.
  • Hysteria 2 - defaults.hub.hysteria: (or a node-level hysteria:) adds a QUIC/UDP inbound for users with access: [hysteria]; hexrift share USER --hy2 prints the hysteria2:// URL. An exit region with protocol: hysteria is dialed by hubs over Hysteria instead of VLESS+Reality (tuning via defaults.exit.hysteria → regions[].hysteria → nodes[].hysteria); an exit that defines hysteria on the region/node serves the listener regardless of protocol, so switching a region's protocol only redeploys hub configs. Hysteria needs a real TLS cert: by default HexRift derives a self-signed leaf from the node's Reality key (key_type: ed25519, or ecdsa-p256) and pins it (hub outbounds via pinnedPeerCertSha256, share URLs via pinSHA256); set certificate: {cert_file, key_file} + sni to serve an operator-issued cert instead. Xray's Hysteria dialer parrots Chrome's QUIC ClientHello, which cannot negotiate Ed25519 certs, so hubs dialing an ed25519 exit set disableChromeParrot; a hysteria2:// URL has no such switch, so hub listeners that Xray-based client apps dial should use ecdsa-p256. UDP ports must not collide with wireguard/xdns on the same hub. See Topology Schema.
  • Site-to-site portals - portals: declares a machine (e.g. a home server) that dials the hubs and opens a reverse tunnel; hub traffic from the portal's member users that matches routes egresses there. publish: forwards a hub-bound port into the tunnel for the ingress direction - that port is unauthenticated internet ingress and ignores portals[].users, so set allow. strict: true (the default) confines portal-side egress to the declared routes/publish matchers and blackholes the rest. See Topology Schema.

Architecture

hexrift/
  components/
    schema/     # Pydantic models for yaml
    derive/     # Identity derivation (UUIDs, shortIds, emails), defaults resolution,
                # topology->Xray-fragment construction, WireGuard and Hysteria derivation
    keys/       # x25519 + ML-KEM 768 keypair generation and storage
    render/     # Xray config builder + HAProxy Jinja2 templates
  core/         # BaseApplication / Component / Controller framework
  inbounds/     # Pluggable inbound specs (xhttp, cdn, proxy, xdns, wireguard, hysteria) + node contexts
  links/        # Pluggable hub→exit link protocols (vless+reality, hysteria): dial context + outbound
  shared/       # Cross-component helpers (crypto encoding, Xray/xhttp/hysteria fragments)
  templates/    # Jinja2 stubs
    haproxy/
    wireguard/

Derivation

All identifiers are deterministically derived from the topology:

  • NAMESPACE UUID = UUID5(UUID(0), namespace)
  • User UUID = UUID5(NAMESPACE_UUID, username)
  • Server UUID = UUID5(USER_UUID, {username}-server)
  • Portal UUID = UUID5(NAMESPACE_UUID, portal/{id})
  • Guest UUID = UUID5(USER_UUID, {label})
  • Hub-exit UUID = UUID5(NAMESPACE_UUID, {hubId}-{exitId})
  • Warp UUID = Hub-exit UUID with 3rd segment replaced by ffff
  • Group shortId = SHA256{groupId}.{namespace}
  • Hub shortId = SHA256{nodeId}.hub.{namespace}
  • Exit shortId = SHA256{nodeId}.exit.{namespace}
  • WireGuard keypair = x25519(HMAC-SHA256(reality_private_key, {identity_uuid}.wireguard.{namespace}))
  • Hysteria certificate = self-signed leaf for the SNI; key seed = HMAC-SHA256(reality_private_key, hysteria-tls.{namespace}) for ed25519, hysteria-tls-ecdsa-p256.{namespace} for ecdsa-p256; the pin is SHA-256 of its DER
  • Hysteria obfs password = base64url(HMAC-SHA256(reality_private_key, hysteria-obfs.{namespace}))

Keys

Keypairs are stored in keys/{nodeId}.yaml. Hub nodes in the same region share the same keypair. Key strings follow the format:

  • Decryption (server inbound): {method}.{mode}.{session_time}[.{padding}].{PRIVATE_KEY_b64}
  • Encryption (client outbound): {method}.{mode}.0rtt.{PUBLIC_KEY_b64}

Release files for hexrift 0.13.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hexrift 0.13.1
File Size Uploaded
hexrift-0.13.1.tar.gz 251.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hexrift 0.13.1
File Interpreter ABI Platform
hexrift-0.13.1-py3-none-any.whl Python 3 none any Details

Total release size: 360.1 kB

Release files / hexrift-0.13.1.tar.gz

Download URL hexrift-0.13.1.tar.gz
Size 251.3 kB
Tags Source
SHA-256 checksum
How to use checksums
9d1b89067d4b1b64e7c14a8aa4c8d8afc92fc9c66877c640fce01698262a56dd
BLAKE2b-256 checksum
How to use checksums
2dcc1e2c3860082e0d15e9c11cb280b0107ea4d3e97fd01e15ff668f0e15c215
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / hexrift-0.13.1-py3-none-any.whl

Download URL hexrift-0.13.1-py3-none-any.whl
Size 108.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5d7e3032ea886af5a671bd9e19b7b04c86c84875531bc89b01fce9ae4d4528c1
BLAKE2b-256 checksum
How to use checksums
267f0fdc1dc7e3d3d21defe473e8e37e76afdb3558dd105489e86abe07932036
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.13.1 This release

2 release files

0.13.0

2 release files

0.12.3

2 release files

0.12.1

2 release files

0.12.0

2 release files

0.10.2

2 release files

0.10.1

2 release files

0.10.0

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page