Skip to content

One binary. HTTPS, proxy, done.

A web server and reverse proxy with automatic HTTPS from Let's Encrypt, HTTP/3, load balancing, and auth — configured in one TOML file. When you outgrow configuration, the same engine is a Rust library.
Terminal window
brew install bohdaq/tap/rws # or: cargo binstall rust-web-server
docker run -p 7878:7878 -v "$PWD:/srv" ghcr.io/bohdaq/rws
HTTP/1.1HTTP/2HTTP/3 / QUICLet’s EncryptTLS (rustls)WebSocketgRPCSSE
Terminal window
cd my-site && rws

Serves the directory on http://localhost:7878 — index.html, directory listings, ETags, gzip, byte ranges, and an optional SPA fallback for client-side routers.

Automatic HTTPS

Built-in ACME client: Let’s Encrypt or a private CA, HTTP→HTTPS redirects, background renewal with hot reload, IPv4 and IPv6.

Reverse proxy & gateway

Load balancing, health checks, bearer / JWT / basic auth that fails closed, rate limits, caching, rewrites, IP filters — plus TCP, UDP, WebSocket, and gRPC proxying.

One TOML file

Every setting lives in rws.config.toml (or env vars, or flags). Unknown keys are reported at startup instead of silently ignored.

No hyper, no Tower, no OpenSSL

HTTP/1.1, routing, middleware, WebSocket, SSE, and the ACME client are implemented in-crate. HTTP/2 and HTTP/3 use h2 and quinn; TLS uses rustls.

Kubernetes-ready

/healthz, /readyz, Prometheus /metrics, graceful SIGTERM shutdown, and a Kubernetes Ingress watcher.

MCP server

Expose tools, resources, and prompts to Claude and other AI agents over MCP Streamable HTTP with a builder API.

The server above is the rust-web-server crate. Use it directly for routes, middleware, an MCP server, an ORM, background jobs, and more:

Cargo.toml
[dependencies]
rust-web-server = "17"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
src/main.rs
use rust_web_server::prelude::*;
fn hello(_: &Request, _: &PathParams, _: &ConnectionInfo, _: &()) -> Response {
Response::text(STATUS_CODE_REASON_PHRASE.n200_ok, "Hello, world!")
}
#[tokio::main]
async fn main() {
let app = routes! {
App::with_state(()),
GET "/hello" => hello,
};
let (listener, pool) = Server::setup().unwrap();
tokio::join!(
Server::run_tls(listener, pool, app.clone()),
Server::run_quic(app),
Server::run_redirect(),
);
}

One middleware trait

Auth, rate limiting, caching, tracing, rewriting, and the reverse proxy itself share one handle(request, connection, next) signature.

Model layer ORM

#[derive(Model)], a type-safe QueryBuilder, migrations, and relations — SQLite, PostgreSQL, or MySQL.

Login & auth

OAuth 2.0 / OIDC (“Login with Google”), SAML 2.0, its own OAuth authorization server, sessions, CSRF.

In-process test client

TestClient::new(app) dispatches requests without opening a socket — fast, hermetic tests.

http1 http2 http3 (default)
Runtime sync thread pool tokio tokio
TLS — rustls rustls
HTTP/2 — ALPN ALPN
QUIC — — quinn
MSRV 1.88 1.88 1.88

The prebuilt binaries are the default build plus the acme and auth features.