Rilgate is a reverse proxy gateway that uses proof-of-work challenges. It places a browser challenge in front of your web application, then forwards requests after the browser completes the required work.
Website · Quick start · Documentation · Issues · Contributing
- Two PoW algorithms: lightweight SHA-256 (
fast) and memory-intensive RandomX. - Request policies: choose allow, deny, challenge or score adjustments using paths, user agents and headers.
- Two RandomX modes: local verification or access granted after P2Pool accepts a submitted share. RandomX starts only after explicit browser consent.
- Shared Rust implementation: native verification and browser WebAssembly use the same RandomX core.
- Customizable web UI: templates, branding, translations, cookie names and internal paths come from configuration or filesystem overrides.
- Bounded resources: proof rate limits, verifier queues, pool sessions, request bodies and timeouts. Web resources support atomic reloads.
You need stable Rust through rustup. The repository toolchain includes the WebAssembly target. Node.js 24 is needed to run the browser tests; Python 3 is used only for the demo upstream below.
Clone the repository and build the gateway:
git clone https://github.com/ViGrise/rilgate.git
cd rilgate
scripts/build.shIn one terminal, start a small upstream site:
demo_dir="$(mktemp -d)"
mkdir -p "$demo_dir/protected"
printf '%s\n' '<h1>Hello from the upstream</h1>' > "$demo_dir/protected/index.html"
python3 -m http.server 3000 --bind 127.0.0.1 --directory "$demo_dir"In another terminal, copy the example to your configuration file and start Rilgate:
cp config/rilgate.example.yml config/rilgate.yml
export RILGATE_SECURITY_SECRET="$(openssl rand -hex 32)"
./target/debug/rilgate --config config/rilgate.ymlOpen http://localhost:8080/protected/. The browser solves a Fast challenge, receives an access cookie and reloads the same URL to reach the upstream page. The balanced preset challenges application traffic regardless of User-Agent and requires no external pool. Policies that select RandomX need explicit P2Pool configuration. See configuration for environment references.
Check gateway health:
curl http://localhost:8080/.well-known/rilgate/api/healthflowchart TD
Browser[Browser] --> Gateway[Rilgate]
Gateway --> Policy{Request policy}
Policy -->|Allow| Upstream[Upstream application]
Policy -->|Deny| Denied[Denied page]
Policy -->|Challenge| Auth{Valid access cookie?}
Auth -->|Yes| Upstream
Auth -->|No| Challenge[Browser challenge]
Challenge --> Verify[Verify proof]
Verify --> Cookie[Issue access cookie]
Cookie -->|Reload original URL| Browser
Without a valid access cookie, protected GET/HEAD requests receive challenge
HTML at the requested URL. Other protected methods return 401, allowing the
client to retry after authentication. Internal APIs and static resources live
under site.base_path, which defaults to /.well-known/rilgate.
Fast proofs run in a browser worker. RandomX uses roughly 256 MiB for its cache, plus scratchpads and runtime memory, and requires WebAssembly SIMD128. Both RandomX modes obtain work from a P2Pool Stratum endpoint.
See gateway behavior and proof of work for protocol, host binding, lifetime and enforcement details.
Rilgate reads config/rilgate.yml, or a file selected by --config or
RILGATE_CONFIG. Only the upstream URL and signing secret are required:
server:
upstream:
url: http://127.0.0.1:3000
security:
secret: "${RILGATE_SECURITY_SECRET}"The defaults are production, embedded resources, local Fast verification and
policy.mode: balanced. HKDF derives independent purpose-specific signing keys.
Unknown fields and conflicting settings fail validation in every environment.
Use rilgate config check to validate and rilgate config show --defaults to
inspect all defaults with secrets redacted. The schema has no version field and
replaces the unreleased previous format.
See the commented template, configuration, request policies, web resources, and production operations.
Install a release binary on Linux or macOS (Windows archives are on the releases page):
curl -fsSL https://github.com/ViGrise/rilgate/releases/latest/download/install.sh | bashSet VERSION=v<version> to pin a release and INSTALL_DIR to change the target
directory; rilgate upgrade later installs newer releases. Multi-architecture
images are published to ghcr.io/vigrise/rilgate. Every setting can also be
given as a flag or RILGATE_* variable; see rilgate --help.
To build a release binary with embedded web assets from source:
scripts/build.sh --release
./target/release/rilgate --config /path/to/rilgate.ymlDocker and Compose examples are included:
docker build -f deploy/docker/Dockerfile -t rilgate:local .
export RILGATE_SECURITY_SECRET="$(openssl rand -hex 32)"
docker compose -f deploy/docker/compose.yml up --buildThe Compose example mounts config/rilgate.production.yml, requires signing
secrets, and expects an upstream application on the host. It binds to loopback;
configure TLS and client quotas at the edge before public use.
See deployment examples for configuration, systemd, Caddy
and nginx integration.
| Guide | Contents |
|---|---|
| Architecture | Crate boundaries, dependencies and detailed source tree |
| Configuration | Loading, precedence, scaling and a full example |
| Gateway | Routing, reverse proxy behavior and resource limits |
| Policies | Matchers, request weights and algorithm selection |
| Proof of work | Fast, RandomX, P2Pool modes and token lifecycle |
| Web resources | Branding, templates, translation fallback and reloads |
| Adding an algorithm | Backend, provider and browser contracts |
| Production operations | Deployment hardening, monitoring, rotation and rollback |
| Development | Build, tests and RandomX reference validation |
Rilgate is experimental. Fast and RandomX are implemented; GhostRider and BLAKE3 are potential extensions. HTTP serving and upstream forwarding use Pingora, including application WebSocket proxying. Key rotation, Prometheus metrics and production deployment defaults are available. Rate limits remain local to each gateway instance; shared quotas can be enforced at the edge. See production operations for rollout and validation requirements.
Local proofs and access tokens are reusable within their signed lifetime. Single-use verification across gateway instances would require shared state or a different protocol. RandomX solve time depends heavily on the device and configured difficulty; test the policy against the browsers you intend to server.
Bug reports, documentation improvements and pull requests are welcome. Include reproduction steps, the expected and actual behavior, and relevant Rust/browser versions. Remove secrets from configuration and logs before sharing them.
For code changes, start with the architecture and keep changes within the owning crate. New algorithms follow the algorithm guide. Run the default checks before submitting:
scripts/test.shNative RandomX reference tests are opt-in because they allocate a 256 MiB cache. See development for those commands.
Copyright 2026 Thinh Hoang and ViGrise Technology. Licensed under the Apache License 2.0.