Features & why to use Kvarn
All of these are available in Mölla!
Kvarn tries to package many useful features without being bloated. Optional extensions are available in the extensions crate.
When using Kvarn as a library: some require certain Cargo “features” to be compiled in, and some require
kvarn_extensions
. This will be explicitly noted.
Batteries included, but not required
The Kvarn ecosystem has extensions for many common website features.
- Automatic HTTPS certificates: Kvarn handles your
certificates for you—no need to renew or use
certbot
to get certificates. - Kvarn auth: A fast, simple, and customizable authentication extension. It provides a JWT implementation with support for persistent logins and validation servers.
- Kvarn search: A site search engine. You can try it out on the front page.
- Kvarn extensions: a crate with several useful extensions, including a reverse proxy, PHP support, and templates.
Sane defaults
The example of running a Kvarn server provides sane defaults, which optimize security; speed; and help mitigate DOS attacks.
HTTP/3
Requires the feature
http3
(part ofdefault
andfull
)
Using a modern transport protocol, QUIC, enables HTTP/3 to be what HTTP/2 aimed to be: fault-tolerant and massively parallel. Add way faster handshakes on top on that, and HTTP/3 is groundbreaking. You can naturally disable the feature.
HTTP/2
Requires the feature
http2
(part ofdefault
andfull
)
HTTP/2 is abstracted from all other internal and extension logic; offering complete parity. This means you get all the pros of the latest protocols without any code.
Kvarn passes the h2spec test. If something doesn’t work, it’s the user agent not conforming.
io_uring
Requires the feature
uring
(notdefault
)
Kvarn can be compiled to use
io_uring
, the hottest IO platform
under Linux. io_uring can be used with both HTTP over TCP (HTTP/1 & HTTP/2), and
HTTP/3 (using a custom QUIC interop).
HTTP/2 Push
Part of
kvarn_extensions
under the featurepush
(part ofdefault
)
HTTP/2 introduced a features where the server can push other resources before the client requests them. This has not been widely used because of the problem with pushing to the client when it’s already got the resource in a cache.
Kvarn aims to solve this by making it simple to integrate, not requiring any configuration and not sending the same resource twice to a client.
HTTPS
Requires the feature
https
(part ofdefault
andfull
)
HTTPS makes the web more secure. Kvarn’s design is not only influenced by HTTPS, but encourages you to use it.
When creating a virtual host, the recommended constructor redirects all HTTP requests to HTTPS before the request reaches your code.
Kvarn also suggest using HSTS. When you’re ready, you only need to add one line of code to enable it for a host, improving security further.
If you want maximum security, you can of course simply not listen on port 80
,
reducing the code you write.
Automatic certificates
If you’re using Mölla (which is recommended), you can enable HTTPS and automatic certificates through Let’s Encrypt:
(
// --snip--
hosts: [
Plain (
name: "icelk.dev",
// the path to store the certificate chain at
cert: "icelk-cert.pem",
// the path to store the private key at
pk: "icelk-pk.pem"
path: "./",
// all the magic happens here!
auto_cert: true,
// if you'd like, you can customize it (completely optional)
addons: [
AutomaticCertificate (
// Get notices from Let's Encrypt
contact: "mailto:main@icelk.dev",
// saved in the ron format, same as this config
// not security critical
account_path: "my-lets-encrypt-account.ron",
)
]
)
].
)
We’re coming for you, Caddy…
Full documentation coverage
Documentation and examples are key to a good library.
You can always read Kvarn’s documentation online. Under
Crates
to the left, you can explore all other crates part of
the ecosystem.
The full coverage is enforced by the compiler. All examples are enforced to run correctly by Rust’s builtin testing.
Extensions
Kvarn in it’s default acts as a file-server. That in itself isn’t useful for building a backend. To build a API, implement authentication, add dynamic language support, or CORS, extensions provides the data and tools you need.
As there are few and small performance benefits of implementing features directly into Kvarn, but great flexibility advantages. Therefore, as many features as possible are built as extensions.
When writing an API, Kvarn handles all HTTP boilerplate. It’ll cache, compress,
encrypt, set content-length
, and secure the response, with
minimal info from the implementation.
There exists several types of extensions, all of which have a separate function
for complete control over the response pipeline. A present extension can be
called from within a file. If it start with !>
you can specify present
extensions like this
!> my-extension arg1 arg2 &> another-extension argument...
. These are
evaluated in order, first to last.
Here, server-side caching is critical for heavy workloads. The flexibility of Kvarn is advantageous; if you have frequent changes, content is recalculated on the fly, but if you need performance, it’ll cache the results as a complete response, ready to be sent. Kvarn tries to generalize requests, reducing cache misses. This also acts as a primitive anti-DOS strategy; if no new content is calculated (or read from disk), the requests are very cheap.
Cache
When Kvarn was created, a reverse-proxy caching the responses from a web application seemed slow. It holds up to this day.
The built in cache in Kvarn is in-memory for performance and integration with extensions is seamless.
If you build extensions directly in Kvarn with it’s convenient
macros with C-like performance.
It’s much faster, and easier to manage, than a reverse-proxy fighting with
Node’s transfer-encoding: chunked
and not being sure of exactly how to cache
the content.
If you need the maintenance advantage of a modular system, look no further than Kvarn’s handover.
PHP
Part of
kvarn_extensions
under the featurephp
(part ofdefault
)
Kvarn can interpret .php
files and send them back, with all of Kvarn’s other
features. Server caching can be set with the
kvarn-cache-control
header.
MarkDown
Part of Chute
Sometimes you need to write a consistent website easily, with minimal effort. That’s where Kvarn Chute comes in. You write MarkDown, Chute translates it to HTML, using Kvarn’s templating system.
Long pages are hard to navigate. Therefore, Chute offers a table of contents
generator. Just insert ${toc}
in your document, run chute -y <doc>
. You now
have a high-quality HTML-only TOC.
This page is written using this features, reducing boilerplate even more and speeding up documentation.
You can add tags to the head of the HTML by starting the MD document (after the
extensions declaration) with a <head>
tag. You’ll of course have to close it
when all the metadata is written.
As with normal files, you can run extensions. Chute will automatically add the
tmpl
(template) extension with the standard.html
and md.html
templates
present. If you add !> hide
to hide the MD source, it’ll be removed, so users
can view the HTML.
Templates
Part of
kvarn_extensions
under the featuretemplates
(part ofdefault
)
To build a consistent website, you need templates. Copying your header and
footer isn’t viable! As a simple, fast, and easy to use template system, this
can virtually copy-paste bytes from a template file (located in
<webroot>/templates/
), but does not, for example, handle conditional inclusion
or loops. Only simple inclusion.
The nav-bar on this page is powered by the templates. HTML documents are about 15 lines for a title, heading, and a paragraph, and of course the nav-bar.
See this directory in the source code of this website for an example of the format of templates.
Full text search engine
A search engine with typo tolerance, no index set-up, and fast (1-4ms) responses.
Boasts an API for accessing the search hits. This means you can implement your own frontend, or use mine at icelk.dev. All the code for that is summarized at the example.
See the link for more information.
CORS
As the web has expanded and complexity increased, cross-site requests have become essential.
Many of the best-practises of HTTP/1.1; loading from multiple domains and chunking together content is irrelevant when using HTTP/2, as it resolves these issues.
Kvarn features a CORS handling (using extensions), backed by testing, which blocks unauthorized CORS requests before they get to your API. This ensures all CORS requests, even from faulty user agents, don’t change server state.
Graceful shutdown & handover
Requires the feature
graceful-shutdown
(part ofdefault
andfull
)
To enable upgrade of the server, you need to shut it down and then start it up, with no downtime. The way Kvarn solves this is through graceful shutdown and handover.
Reverse proxy
Part of
kvarn_extensions
under the featurereverse-proxy
(part ofdefault
)
If you want to develop your web application in another language, Kvarn can act as a reverse proxy, with all the benefits of HTTP/2, caching, and easy upgrades.
In contrast to writing extensions in Rust, the speed and throughput is greatly reduced.
Guaranteed memory-safety
Kvarn is written in Rust.
This greatly improves security (resilience against buffer overflows) and reliability, as Rust guarantees pointers to be valid through it’s strict borrowing rules. This, together with phenomenal error handling and strong tooling makes for maintainable and predictable code.
The borrow rules ensure memory safety without runtime overhead, while being as fast as C (assuming the code is optimal, which is easier to accomplish with Rust).
The compiler catches nearly all errors. The quote, “if it compiles, it runs” is indeed true. Compare Rust vs C++ to TS vs JS, only in one case silly bugs cause production to go offline.
Other fundamental features & systems
- Completely asynchronous, powered by Tokio, the runtime used by Deno.
- Limiting of requests to provide availability to all users. This is a primitive defence against small DOS attacks.
- Error handling for customizing HTTP errors, with support for all extensions, including templates. If you visit a page which doesn’t exist on kvarn.org, you’ll see the same nav-bar as everywhere else. That took 10 lines of HTML to set up.
- Optional features offer the best of both worlds; HTTP/2, HTTPS, and graceful shutdown results in a larger binary and slower compile-times, but disabling those features makes Kvarn viable to compile on a Raspberry Pi.
- Virtual hosts allow multiple domains and sub-domains to be hosted on the same system. All configuration is defined per host.
- IPv6 support.
- Utilities for extracting data from HTTP requests. This will include a basic authentication system soon.
- Testing with a public frontend to test your APIs before production. To run a Kvarn server and send a request takes 2 lines of code.
Back to the basics
Doesn’t mean they’re more simple or easier to implement, as development time has shown. ಠ_ಠ
- Compression automatically applied to the response. This handles negotiating the algorithm. Brotli and Gzip support.
- CSP support.
- Extremely simple to use nonce support.
- If-Modified-Since for more effective caching. This is directly integrated
with
lifetime
s in the Kvarn cache. - URL handling of requests ending in
/
(becomes/index.html
by default) and.
(becomes.html
by default). - Logging using Rust’s standard logger, enabling you to chose a log implementation which works for you.
- Idiomatic Rust, guaranteed by Clippy.