Installation
How to install rust-web-server as a library crate, as a standalone binary, or from source — including feature flags and MSRV.
Requirements
Minimum Supported Rust Version (MSRV): 1.99
Install or update Rust via rustup:
rustup update stable
rustc --version # should print 1.99.0 or newerAs a library crate
Add rust-web-server to your Cargo.toml:
cargo add rust-web-serverOr pin the major version manually:
[dependencies]
rust-web-server = "18"The default feature set (http3) pulls in HTTP/3, HTTP/2, TLS, and a tokio async runtime. If you need a lighter build, opt out and select a lower feature tier (see the feature flags table below).
Prelude
A single glob import covers the types you need in almost every handler:
use rust_web_server::prelude::*;
// Re-exports: App, Server, ConnectionInfo, Request, Response,
// STATUS_CODE_REASON_PHRASE, Range, MimeType,
// PathParams, New, routes!As a standalone binary
Every release ships prebuilt binaries, so no Rust toolchain is needed:
| Method | Command | Platforms |
|---|---|---|
| Install script | curl -fsSL https://rws8.tech/install.sh | sh (sh -s -- --version 18.8.3 --dir ~/bin to pin a release or a directory) — downloads the release archive, checks its .sha256 and installs to /usr/local/bin, else ~/.local/bin (since 18.8.4) |
Linux (x86_64, arm64), macOS (Apple Silicon, Intel) |
| Homebrew | brew install bohdaq/tap/rws |
macOS (Apple Silicon, Intel), Linux (x86_64, arm64) |
| cargo-binstall | cargo binstall rust-web-server |
everything below, without compiling |
| apt / dnf | sudo apt install rws, sudo dnf install rws after adding the repository — systemd: install from a package; installs and starts the rws service (since 18.2.0) |
Debian, Ubuntu, Fedora, RHEL and derivatives (x86_64, arm64) |
| Docker | docker run -p 7878:7878 -v "$PWD:/srv" bohdaq/rws (also ghcr.io/bohdaq/rws) |
linux/amd64, linux/arm64 |
| Download | GitHub Releases | x86_64/aarch64-unknown-linux-musl, x86_64/aarch64-apple-darwin, x86_64-pc-windows-msvc |
| From source | cargo install rust-web-server |
anywhere Rust 1.99+ runs |
On Windows, rws.exe also runs as a Windows service — see Windows.
Linux binaries are statically linked against musl, so they run on any distribution regardless of glibc version. Each archive has a matching .sha256 file.
rws --version
rws --help # every option, with its environment-variable equivalentRun it in any directory that contains static files and it will serve them on http://localhost:7878 with no configuration file needed.
Verifying a release
From 18.0.0, releases can be checked end to end:
# The archive was built by this repository's release workflow
gh attestation verify rws-18.0.0-x86_64-unknown-linux-musl.tar.gz --repo bohdaq/rust-web-server
# The image too — attestation, or the keyless cosign signature
gh attestation verify oci://ghcr.io/bohdaq/rws:18.0.0 --repo bohdaq/rust-web-server
cosign verify ghcr.io/bohdaq/rws:18.0.0 \
--certificate-identity-regexp 'https://github.com/bohdaq/rust-web-server/.github/workflows/release.yml@.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
# Known vulnerabilities in the dependencies compiled into a binary
# (built with cargo-auditable, so the list travels with it)
cargo audit bin ./rwsEach release also has a CycloneDX SBOM (rws-<version>.cdx.json) of the
binary's dependency tree. CI checks every change with cargo audit and
cargo deny (advisories; permissive licenses only; crates.io sources only —
deny.toml).
Build from source
git clone https://github.com/bohdaq/rust-web-server.git
cd rust-web-server
cargo build --release
# binary is at: target/release/rwsTo build a specific feature tier from source:
# HTTP/2 + TLS only (no QUIC)
cargo build --release --no-default-features --features http2
# HTTP/1.1 only — no TLS, no async runtime, smallest binary
cargo build --release --no-default-features --features http1Feature flags
Presets
Since 18.32.0 four presets turn on common sets of the features below. They only enable other features, so they combine with each other and with single features:
[dependencies]
rust-web-server = { version = "18.32", features = ["api"] }
# HTTP/2 + TLS without QUIC: default-features = false, features = ["api"]| Preset | For | Features |
|---|---|---|
web |
Server-rendered apps | http2, serde, macros, tera, auth, crypto (password hashing, signed and encrypted cookies), csrf, model-sqlite, jobs, mailer, storage-local |
api |
JSON APIs | http2, serde, macros, openapi, auth, auth-asymmetric, model-sqlite, jobs |
proxy |
The reverse proxy / edge server | http3, brotli, zstd, acme, auth, auth-asymmetric, sso, rewrite-regex, secrets |
full |
Everything that builds with Rust and a C compiler alone | every feature except fips (needs CMake and Go), pkcs11 (only useful with an HSM), http1 (the synchronous server, an alternative to http2) and mimalloc (the rws binary's allocator) |
Sessions, routing, middleware, MCP, WebSocket and SSE need no feature. Add
model-postgres or model-mysql beside a preset for another database.
Build times. A clean debug cargo build --lib of rust-web-server, each
preset on top of the default features (http3, brotli, zstd), measured
2026-11-04 on a 4-core Linux container (rustc 1.97) with other builds
sharing the CPU — read them as relative:
| Features | Clean build | target/ size |
|---|---|---|
| default | 49 s | 1.1 GB |
proxy |
52 s | 1.4 GB |
web |
59 s | 1.8 GB |
api |
62 s | 1.6 GB |
full |
1 min 47 s | 3.9 GB |
Rebuilds after a change to your own code only recompile your crate.
On docs.rs
docs.rs documents the crate with full,
http1 and pkcs11 — every item, each labelled with the features it needs
(for example Available on crate feature sso only). fips and mimalloc
add no items.
All features
fips (since 18.23.0) builds TLS on aws-lc's FIPS 140-3 validated module
and needs CMake and Go; see FIPS 140-3.
pkcs11 (since 18.23.0) lets tls_key_file name a key on an HSM or cloud
KMS; see PKCS#11.
| Feature | What it adds | Required deps |
|---|---|---|
http1 |
Synchronous thread-pool server, no async runtime, no TLS | ctrlc, libc |
http2 |
tokio runtime, TLS via rustls (aws-lc-rs), HTTP/2 via ALPN | h2, rustls, tokio, tokio-rustls, … |
http3 (default) |
QUIC transport and HTTP/3 on top of http2 |
quinn, h3, h3-quinn |
geo (default) |
The country table of the admin UI's Traffic page (DB-IP Lite, CC BY 4.0, ~700 KB), since 18.31.0 | flate2 |
http-client |
HTTPS support in the outbound Client |
rustls, webpki-roots |
serde |
JSON serialization/deserialization via serde | serde, serde_json |
auth |
BasicAuthLayer, JwtLayer (HS256), ForwardAuthLayer, JWT helpers |
hmac, sha2 |
auth-asymmetric |
RS256 / ES256 in JwtLayer (in-crate RSA verification) |
auth, p256, rand_core |
macros |
#[derive(Model)], #[derive(FromRequest)], #[derive(Validate)], #[derive(Config)], #[get]/#[post]/… route attributes |
rws-macros |
acme |
Automatic TLS certificate provisioning (ACME/Let's Encrypt) | http2, rcgen, aws-lc-rs, … |
mimalloc |
The rws binary allocates with mimalloc v3 (about 5% less CPU per request than glibc's allocator; more memory under load); release binaries and images have it. The library never sets a global allocator |
mimalloc |
tera |
Tera template engine integration | tera, serde, serde_json |
model-sqlite |
Async ORM backend for SQLite | http2, sqlx (sqlite) |
model-postgres |
Async ORM backend for PostgreSQL | http2, sqlx (postgres) |
model-mysql |
Async ORM backend for MySQL / MariaDB | http2, sqlx (mysql) |
crypto |
Argon2id password hashing, signed (HMAC) and encrypted (AES-GCM) cookies | argon2, rand_core, hmac, sha2, aes-gcm |
csrf |
CSRF token generation and validation | rand_core |
mailer |
SMTP client (STARTTLS/SMTPS also need http-client or http2) |
— |
sso |
OAuth 2.0 / OIDC client (RS256/ES256 id_token verification, outbound HTTPS) |
p256, sha2, rand_core, serde, serde_json, http-client |
sso-server |
AuthServer: rws as an OAuth 2.0 authorization server (HS256 tokens) |
sso, auth |
sso-saml |
SamlSp: SAML 2.0 Service Provider |
sso |
jobs |
In-memory JobQueue (PersistentJobQueue also needs a model-* feature) |
— |
storage-local |
LocalStorage |
— |
storage-s3 |
S3Storage (AWS SigV4, no SDK) |
hmac, sha2, http-client |
storage-azure |
AzureBlobStorage (Shared Key / Managed Identity, no SDK) |
hmac, sha2, http-client |
storage-gcs |
GcsStorage (service-account JWTs, metadata server, no SDK) |
http-client, aws-lc-rs |
brotli (default) |
br content coding |
brotli |
zstd (default) |
zstd content coding |
zstd (C libzstd, built with the crate) |
tower |
Tower layers as middleware, Tower services as apps, an app as a Tower service | http2, tower-service, tower-layer, http-body |
gateway-api |
Kubernetes Gateway API controller | http2, serde, kube, k8s-openapi |
wasm-plugins |
WasmLayer: middleware as WebAssembly modules |
wasmtime |
fips |
TLS on aws-lc's FIPS 140-3 module (needs CMake and Go) | http2 |
pkcs11 |
TLS private keys on an HSM or cloud KMS | http2, cryptoki |
openapi |
GET /openapi.json + GET /docs from registered routes |
— |
webhook |
verify_webhook_signature (GitHub, Shopify, Stripe) |
hmac, sha2 |
rewrite-regex |
RewriteLayer::request_uri_regex_rewrite |
regex |
secrets |
secrets::resolve() for vault://, aws-sm://, azkv:// references |
hmac, sha2, http-client |
Features compose freely. For example, to build HTTP/2 + TLS + JSON + SQLite:
rust-web-server = { version = "18", default-features = false, features = ["http2", "serde", "model-sqlite"] }Approximate binary sizes
These measurements are for a release build (cargo build --release) of the rws binary with only the core transport feature active. Enabling additional features (serde, tera, ORM backends, etc.) increases the size.
| Feature tier | Approx. binary size |
|---|---|
http1 |
~3 MB |
http2 |
~8 MB |
http3 (default) |
~12 MB |
TLS uses rustls with the aws-lc-rs crypto backend. There is no dependency on a system OpenSSL installation. Binaries are fully static with respect to TLS and are compatible with FIPS-validated environments.
What's built in, and what isn't
HTTP/1.1 parsing, CORS, MIME types, range requests, WebSocket, SSE, and routing are implemented inside this crate. The transitive dependency tree has no hyper, tower, or actix-net.
The HTTP/2 server is rws's own (h2_server: framing, HPACK, flow control — conformance-checked with h2spec and fuzzed); the h2 crate remains a dependency as the HTTP/2 client of H2ReverseProxy/GrpcProxy. HTTP/3 and QUIC use h3 and quinn, and TLS uses rustls. tokio-util appears transitively in the default build through h2.