Skip to content
ViGrisePublic

About

Rilgate is a proof-of-work reverse proxy that protects upstream services with browser challenges.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Rilgate

CI License: Apache 2.0 Rust: stable WebAssembly: SIMD128 Status: experimental

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

Features

  • 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.

Quick start

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.sh

In 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.yml

Open 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/health

How it works

flowchart 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
Loading

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.

Configuration

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.

Deployment

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 | bash

Set 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.yml

Docker 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 --build

The 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.

Documentation

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

Project status

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.

Contributing

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.sh

Native RandomX reference tests are opt-in because they allocate a 256 MiB cache. See development for those commands.

License

Copyright 2026 Thinh Hoang and ViGrise Technology. Licensed under the Apache License 2.0.

About

Rilgate is a proof-of-work reverse proxy that protects upstream services with browser challenges.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages