Go to file
nak0x 2b017197d0 Add a usage guide and an install script
GUIDE.md covers the parts a README does not: what happens when you click a
link, making the proxy stick, the handful of commands worth knowing, and
what to do when a page comes out wrong — which it will, since extraction is
heuristic.

install.sh builds the workspace, installs the four binaries, writes starter
configs, fetches the blocklists, sets up a systemd user service for the
proxy, and offers to register furst as the default browser. Every
system-changing step can be skipped, and the default-browser change is
prompted rather than assumed; a non-interactive run declines it.

Re-running never overwrites a config that already exists, so it is safe
after editing rules. --uninstall removes binaries, service and desktop
entry while keeping configs, and --purge takes those too.

The script passes --workspace to cargo, which is the mistake to avoid here:
the root package is only furst, so a bare build silently skips the other
three binaries.
2026-09-06 23:19:34 +02:00
furst-proxy Add furst-proxy, a filtering proxy that does not decrypt traffic 2026-09-06 20:29:23 +02:00
furst-read Add search, feeds and listing views to the reader server 2026-09-06 20:07:49 +02:00
furst-serve Make the reader the default route and document the toolset 2026-09-06 20:10:11 +02:00
src Make the reader the default route and document the toolset 2026-09-06 20:10:11 +02:00
.gitignore Add furst, a URL router for low-end hardware 2026-09-06 19:18:13 +02:00
Cargo.lock Add furst-proxy, a filtering proxy that does not decrypt traffic 2026-09-06 20:29:23 +02:00
Cargo.toml Add furst-proxy, a filtering proxy that does not decrypt traffic 2026-09-06 20:29:23 +02:00
GUIDE.md Add a usage guide and an install script 2026-09-06 23:19:34 +02:00
install.sh Add a usage guide and an install script 2026-09-06 23:19:34 +02:00
LICENSE Add furst, a URL router for low-end hardware 2026-09-06 19:18:13 +02:00
README.md Add furst-proxy, a filtering proxy that does not decrypt traffic 2026-09-06 20:29:23 +02:00

furst

A toolset for browsing the modern web on hardware that cannot run a modern browser. Built for a Core2 Duo with 4GB of RAM and a minimal Arch install, where Firefox is the bottleneck.

The idea

A news page is 25MB across 80+ requests with 13MB of JavaScript to parse and JIT. The same article, extracted, is ~20KB. Choosing a lighter browser engine buys 23×. Not loading the payload at all buys considerably more.

So the goal is not a faster browser. It is to keep a browser engine out of the loop wherever possible, and to make the cases where you still need one rare and deliberate.

   link click
        │
   ┌────▼─────┐   video ──────────────► mpv (H.264 forced)
   │  furst   │   pdf / image ────────► zathura / nsxiv
   │  router  │   mailto / magnet ────► xdg-email / transmission
   └────┬─────┘   a short "heavy" list ► firefox ──┐
        │                                          │
        ▼  everything else                         │
   ┌──────────────┐        ┌──────────────┐        │
   │ furst-serve  │───────►│  furst-read  │        │
   │ local reader │        │   library    │        │
   └──────┬───────┘        └──────────────┘        │
          │  minimal HTML, no JS/CSS/fonts         │
          ▼                                        ▼
     a light browser (surf, luakit, …) ──────► furst-proxy
                                          ad and tracker hosts refused
                                          before the TLS handshake

The pieces

furst the router. Sits where the default browser used to and dispatches each URL to the cheapest tool that can handle it. Two dependencies, 541K binary.
furst-read fetch, extract the article, render it as a self-contained document. Library and CLI.
furst-serve the local reader. Rewrites in-page links so browsing stays in reader mode, caches pages, and handles what extraction cannot: search, feeds, listings, comment threads.
furst-proxy filtering proxy for the times you do use a browser. Refuses ad and tracker hosts at CONNECT, before any TLS handshake, so nothing is decrypted. 80k rules in 9MB.

Install

cargo build --release --workspace
install -Dm755 target/release/furst target/release/furst-read \
               target/release/furst-serve -t ~/.local/bin/

furst --init          # rules tuned for low-end hardware
furst --install       # become the system default browser
furst-serve --init    # home page links and feeds
furst-proxy --init && furst-proxy --update    # 80k blocklist rules

sudo pacman -S mpv yt-dlp zathura zathura-pdf-mupdf nsxiv surf

To filter what a browser still loads directly, run furst-proxy and eval "$(furst-proxy --env)". This is what gives surf ad blocking, since WebKitGTK has no extension mechanism.

Then every link click in every application goes through the router, and most of them never reach a browser engine.

Measured

page raw HTML scripts stylesheets through furst
wiki.archlinux.org/title/Zram 64K 4 2 16K
en.wikipedia.org/wiki/Core_2 207K 5 2 47K
theverge.com 770K 55 71 2.4K
lwn.net headlines (feed) 11K, 15 entries

The HTML column understates it. The script and stylesheet columns are the real story: those become zero, along with every webfont and tracker, which is where an old CPU actually spends its time. A cached revisit is ~0.4ms.

Two details that matter on this hardware

Video is forced to H.264. A Core2 handles 720p avc1 in software but stalls on VP9 and AV1, which is what YouTube serves by default. The format string in the video rule is doing more work than the resolution cap, and playing it in mpv skips the browser entirely.

Blocking needs no certificate authority. A proxy sees CONNECT doubleclick.net:443 before any TLS handshake, so it can refuse the connection without decrypting anything. Ads and trackers are third-party hosts, so that captures nearly all of the weight while leaving your traffic sealed.

The reader is the catch-all, not a special case. Rules fall through when their command is missing, so the last rule can be "send it to the reader" while default stays a plain browser. Firefox is left for a short list of sites that genuinely need it — and every reader page has a browser link for the rest.

Limits

  • Anything that renders client-side arrives empty. There is no JavaScript here; that is the point, not an oversight.
  • Free search endpoints rate-limit repeat visitors. The reader detects a challenge page and tells you which engine refused, rather than showing an empty list. See furst-serve.
  • Paywalls and DRM are not defeated, only rendered plainly or handed off.

Development

cargo test --workspace     # note: --workspace, the root package is just furst
cargo clippy --workspace --all-targets

License

MIT