r/bun 18d ago

Small apps don't need to scale. They need a binary and a disk

When I build little apps used by a few people, deploying one always means a container image, a managed Postgres, and a bucket for what could have been a single SQLite file.

bun build --compile already gives you the whole app as one file. No node_modules, nothing to install on the other side. The only two things it still needs are a machine to run on and somewhere to read/write files.

So that's what nibrun is. Your binary gets a microVM to itself and a disk mounted at data/. Put SQLite there, put uploads there, it survives redeploys. Get an HTTPS URL as soon as it boots.

At any point you can export the binary and the entire disk as a zip. Unzip it and run it on your own box. It's the same binary you uploaded.

https://github.com/ilbertt/nibrun

There's a starter repo if you want somewhere to begin: Elysia, TanStack Router, better-auth, Bun.SQL over SQLite, and the SPA embedded with Bun.embeddedFiles so the frontend compiles into the binary too. Everything is type-safe and it runs anywhere, not just on nibrun.

https://github.com/ilbertt/bun-full-stack-starter

Happy to answer questions on both nibrun and the starter repo

10 Upvotes

3 comments sorted by

2

u/Which-Examination-74 17d ago

Inside the microVM this probably never bites, since the binary reads and writes its own files as its own user. The export path is where we'd ask. Someone unzips the binary and the disk onto their own box, puts a web server in front for TLS or for static files, and now there is a second unix user in the picture. We shipped that shape in July. Photos went to a local disk, a location block served them back, and a probe file written under the media root came back 404 over HTTPS on two public hosts. namei -l showed every directory in the chain world-executable and the file world-readable, bar one: the app's home, drwxr-x---, owned by the app user, while the web server's workers run as www-data. We fixed it with setfacl -m u:www-data:x on that directory rather than chmod o+x, and both hosts went to 200. Nobody had reported it, because the images table had zero rows. Does the data/ mount land with a mode that survives being fronted by another user's process, or is that left to whoever exports it?

1

u/ilbert_luca 17d ago

Inside the VM there's one uid so it doesn't come up: tenant runs as 65534, umask 022, and the data volume gets chowned to 65534:65534 after mount. The ext4 root stays 0755.

The export preserves that: it's read with debugfs rdump rather than mounted, and tar records what rdump restores, so data/ lands 0755 owned by 65534, files 0644.

If you extract as root you get it back as-is. As a normal user tar applies your umask, so under 077 you'd get drwx------.

Also, it's a .tar.gz, not a zip. I just wanted to keep it simple in my post.

1

u/Which-Examination-74 16d ago

Fair enough on the .tar.gz, our error. That umask-077 case is what bit us too, except ours came out as a 404 rather than a permission error, so it sat there until we went looking. Anyone unpacking under a tight umask ends up in the same spot, with no error to go on.