Sovereign-Computing.com

Reclaim your digital life. Own your sovereignty.

Server rack units with teal status lights, illustration for the article BentoPDF: 42 PDF Tools That Never Leave Your Browser

BentoPDF: 42 PDF Tools That Never Leave Your Browser

Picture a signed contract, a bank statement, a scan of your passport, and a website offering PDF services to merge them for free. No account, no upload limit, no fuss. You drag the file in, it does the work, you download the result, and you close the tab.

The file did not go anywhere. Except it did. It went to their server, and what happens to it there is governed by a policy you have not read, inside a click-through you did not see. There is no undo for that.

So the file stays in the house now. It has been running that way here for a while, and the numbers involved are small enough to be slightly funny.

What it actually is

BentoPDF, a PDF toolkit that runs entirely inside your browser. There is no upload step because there is no upload: the container that serves it is a static file host, and the PDF engines are WebAssembly payloads your browser downloads and runs locally. The build I run ships two of them, qpdf at 1.33 MB of WASM and coherentpdf at 1.33 MB of JavaScript, which is what makes the privacy claim mechanical rather than a promise.

42 tools, in 7 groups: organise and manage (merge, split, rotate, extract), edit and modify (annotate, watermark, redact, page numbers), convert to/from PDF, secure and optimise (compress, protect, sign). TypeScript, AGPL-3.0, and about 16,000 stars on GitHub for a project that was created in October 2025. A year old, and moving.

Why the browser is the right place for it

Every cloud PDF tool is built on the same trade. You get the convenience; they get the document. Sometimes that’s a fine trade. A restaurant menu, go ahead. A contract, a statement, or a scan of an identity document, no — because the failure mode is not only “their server was breached”. The failure mode is that the file is simply there. Archived, indexed, backed up, subject to a retention policy that quietly changes when a holding company changes.

Client-side processing removes the trade instead of managing it. The server sends files one way, the browser does the work, the result is written to your disk. Nothing to retain, nothing to leak, and nothing to delete, because there was never a second copy.

You can also check that claim rather than believe it, which is the part I like.

The build, with the actual numbers

An unprivileged LXC on the Proxmox box: 1 core, 2 GB of RAM, 4 GB of disk, Debian 13 under a static web server.

ss -ltnp | grep 8080
LISTEN 0  511  *:8080  *:*  users:(("MainThread",pid=335,fd=22))

That is the whole service. No database, no queue, no worker pool, one process handing out static files.

What it costs to run:

  • 118 MB of RAM in use, against the 2 GB the container is allowed. Most of that is Debian.
  • 11 MB of served application: the build, the images, and the two WASM engines.
  • 1.8 GB of the 4 GB disk, which is where the honesty starts, below.
  • No CPU worth measuring, because the container does not process anything. Your browser does.

The privacy claim has a cost, and it is paid in the tab. A 600-page scanned document will make your browser work for it, and the server cannot help, because the server has no idea what a PDF is. I would rather have it that way. But it is a real trade, and you should know which side of it you are standing on.

What you give up, honestly

You become the update scheduler. Mine was built on 17 November 2025 and reports version 1.6.2. Upstream is at 2.8.8, released in August 2026, with a release roughly every month. Self-hosting does not only mean you own the uptime; it means nobody patches your copy while you sleep. The appliance here has an update helper, but it re-runs the installer script that created the container in the first place. The project’s own container image is the cleaner path if you want a deployment you can reproduce.

Disk goes to the toolchain, not the tool. The application tree on disk is 543 MB, and 529 MB of that is node_modules — a complete build toolchain sitting on a server that serves static files and will never compile anything again. The part that actually runs is 11 MB. If that ratio irritates you as much as it irritates me, run a prebuilt image rather than a source checkout.

42 tools is breadth, not depth. It will merge, split, rotate, compress and sign, offline, quickly. It is not a desktop application on a genuinely heavy job, and some of the converters produce output you should eyeball before you send the file to a client.

AGPL-3.0. Fine for a personal lab. If you were considering embedding it in something you sell, that is a lawyer’s ten minutes, not a blog post.

Update, 15 October 2026 — upgraded the same day

I did the job the same afternoon. The paragraph above calls me the update scheduler; a few hours after this went up, the container was rebuilt on 2.8.8, which is upstream’s own latest release (v2.8.8, 29 August 2026). Everything above was measured before that, so here is the after.

Disk, honestly worse. The build tree is now 1.6 GB: 1.2 GB of it node_modules and 229 MB of built application. The part that actually runs went from 11 MB to 229 MB, and most of that is the new engine below. The disk sits at 85% of its 4 GB, so the toolchain bill I complained about upstairs is now about three times the size.

More machine to build it. 2 cores and 4 GB, against the 1 core and 2 GB in the numbers above. Building in place wants the memory; 43 MB of it is in use now that the build is done.

It is no longer one static port. nginx serves it over HTTPS on 8443, the port in that ss output now answers only a redirect, and the server sends the cross-origin isolation headers (COOP same-origin, COEP require-corp) without which the new engine will not start at all.

Word, Excel and PowerPoint to PDF is new — a 46.5 MB LibreOffice WebAssembly engine, soffice.wasm.gz, that runs in your browser like everything else here. Editing text inside a PDF is the other new capability. That is where the 229 MB went, and for a converter that never sees the network it is a fair trade.

One lesson the upgrade taught me. It moves the port. Anything in front of the container that was told the old one has to be told the new one: a reverse proxy still pointing at 8080 gets a redirect from the app instead of the app, and if it passes its own host name through, you get a loop rather than an error page. Mine did exactly that, and it is the kind of failure that reads as the proxy breaking when it is the app that moved.

And you are still the scheduler. That has not changed, and it is the honest price of the whole approach: nothing here phones home, which is the point, and also the bill.

The part that matters

The pitch for online PDF tools has always been convenience, and it has always been true. The bill for it is a document you cannot un-send.

I moved the convenience inside the house. 118 MB of RAM, one core, a static file server, and a browser doing the work. It is a small thing, and small things are how a lab stops being somebody else’s customer.

Project and source: https://github.com/alam00000/bentopdf — AGPL-3.0.

Homepage: https://bentopdf.com/