wastebin: a single-binary Rust pastebin with SQLite, zstd and optional ChaCha20Poly1305 encryption
wastebin is a pastebin 📝
At a glance
- What is it?
- wastebin is a minimal self-hosted pastebin built on axum and SQLite, shipped as one statically compiled binary. It is easy to run and deliberately incomplete: no user accounts, no admin panel, and no DoS mitigations, which the README states plainly.
- Who is it for?
- wastebin fits a single operator who wants a small internal paste service on one host, behind a reverse proxy that already does rate limiting, with the SQLite file on a backed-up volume. It does not fit anyone who needs accounts, per-user quotas, audit trails or an internet-facing deployment without that proxy, because the README states there is no authentication and no DoS mitigation.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 16, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What wastebin is for, and who should not run it
wastebin solves a narrow problem: moving a block of text from one machine or person to another without email, chat scrollback, or a shared drive. It is a pastebin, and the README describes it as minimal. Pastes are stored in SQLite, served by an axum HTTP server, and the whole thing compiles to a single binary. The stated audience is someone who wants to self-host that service rather than depend on a public paste site, and who is comfortable with environment variables and a container runtime.
The README is unusually direct about scope. Under a heading called Non-features it lists user authentication and admin functionality, arbitrary file uploads, and mitigations for all kinds of DoS attack vectors. A caution block follows: because of the lack of authentication and further DoS mitigations, it is not advised to run wastebin facing the internet as is, and anyone who does should rate limit inbound requests via iptables rules or a properly configured reverse proxy. That single paragraph should decide the deployment for most readers. If you need accounts, per-user storage limits, or an audit log of who read what, wastebin is the wrong tool, not a tool you can extend into one without writing the missing layer yourself.
The request path: axum, SQLite and zstd on one host
The architecture is a single process with two dependencies. axum handles HTTP; SQLite holds the pastes. There is no separate cache, queue or object store mentioned in the README, so the database file is the entire state of the instance. That is why the Docker instructions mount a volume at /data and set WASTEBIN_DATABASE_PATH=/data/state.db: lose that file and you lose every paste.
On write, pastes are compressed with zstd before storage. On read, syntax highlighting is applied for more than 170 languages through syntect, and pastes whose extension is md or markdown can be rendered to HTML. The rendered view lives at /md/{id}, with a toggle in the paste view switching between highlighted source and rendered output. The renderer handles GitHub-flavored Markdown including tables, task lists and admonitions such as > [!NOTE] and > [!WARNING], and fenced code blocks inside Markdown are highlighted with the same theme as ordinary pastes.
The security detail worth noting is how Markdown rendering handles raw HTML. The README states that raw HTML in the Markdown source is passed through the ammonia sanitizer, so tags like <details>, <summary> and <kbd> survive while <script>, inline event handlers and javascript: URLs are stripped. To allow external images embedded with , the Content Security Policy is relaxed to img-src * for /md/* responses only; every other route keeps the strict default. That is a deliberate, narrow widening of the policy rather than a global one, and it is the kind of trade-off a reviewer should acknowledge: rendered Markdown can now cause the reader's browser to fetch third-party image URLs, which leaks the fact that the paste was opened.
Encryption, expiry and the deletion modes
wastebin supports encrypted entries using ChaCha20Poly1305 with argon2-hashed passwords. The README lists this as a feature without describing the key derivation parameters, so the practical strength of the password hashing is something you would have to read the source to confirm. What is documented is the set of lifetime behaviours: pastes can be deleted after expiration, after reading, or by anonymous owners. Delete-after-read is the interesting one. It is a genuine fit for one-time secrets, and a genuine misfire for a link you expect two colleagues to open, because the first reader consumes it.
Because there is no user model, ownership is anonymous. The README does not describe how an anonymous owner is identified or how the deletion credential is transmitted, so treat that mechanism as something to inspect before you rely on it for anything sensitive. The same caution applies to encryption: a paste that is encrypted at rest is still served over whatever transport your deployment provides, and wastebin itself is documented as having no authentication layer in front of it.
Getting it running: binaries, Docker, Nix and source
There are four documented installation paths. Pre-built statically compiled Linux and macOS binaries are published on the releases page; you extract the archive and run the contained wastebin binary. For Docker, the image is published as quxfoo/wastebin:<VERSION> and quxfoo/wastebin:latest, and the README gives this invocation:
docker run -e WASTEBIN_DATABASE_PATH=/data/state.db -v /path/for/storage:/data -u $(id -u):$(id -g) quxfoo/wastebin:latest
A docker-compose example is also provided, mapping port 8088 and mounting ./data, with a note that the ./data folder must be writable by user 10001. Nix users can run nix run 'github:matze/wastebin#wastebin' or install the provided package. From source, the requirement is a Rust 2024 toolchain containing Rust 1.85, installed with rustup, after which cargo run --release starts the server.
The image is based on scratch, which the README flags as a real operational detail: there is no shell and TMPDIR is not set. If database migrations fail with an extended sqlite error code 6410, the fix given is to pass TMPDIR pointing at a location sqlite can write to. Container images can also be built locally with Docker or Podman using the --target amd64 and --target arm64 flags, with the caveat that aarch64 images cannot be built on aarch64 hosts with the provided Dockerfile. The bundled wastebin-ctl tool is documented for interacting with a running instance, for example podman exec -e RUST_LOG=debug -it wastebin /app/wastebin-ctl.
Configuration is environment variables, and the table is the contract
All configuration is done through environment variables that control the server and run-time behaviour. The README begins a table of them, and the supplied material is truncated partway through that table, so the complete list of keys is not something this article can enumerate. What is confirmed is the pattern: WASTEBIN_DATABASE_PATH sets the SQLite file location, and RUST_LOG controls log verbosity, as shown in the wastebin-ctl example that passes RUST_LOG=debug. Anything beyond those two should be read from the configuration table in the README for the exact version you deploy.
That truncation is itself a reason to pin a version rather than track latest. The README you are reading documents an unreleased version and links to released trees for 3.7.0, 3.6.2, 3.5.0, 3.4.1, 3.3.0, 3.2.0, 3.1.0, 2.7.1 and 3.0.0. Recent releases listed for the repository are 3.7.2, 3.7.1 and 3.7.0. If you deploy from a tag, read the README at that tag, because the environment variable surface and the Markdown and CSP behaviour have changed across these releases.
Where wastebin stops: the DoS and trust boundary
The most concrete limitation is stated by the project itself. There are no mitigations for all kinds of DoS attack vectors, and no authentication. Rate limiting is left to iptables or a reverse proxy. That means the operator owns the abuse problem entirely: request throttling, body size limits, and any blocking of repeat offenders happen outside wastebin. If your threat model includes a hostile public, this is not a component that helps you.
There are smaller edges too. Arbitrary file uploads are explicitly a non-feature, so binary artefacts are out of scope. There is no admin functionality, which means no web view of stored pastes, no bulk deletion, and no usage reporting beyond whatever you can query from SQLite directly. The scratch-based image removes the shell you might otherwise use for debugging inside the container, which is why wastebin-ctl exists. And the relaxed img-src * policy on /md/* routes means rendered Markdown pastes can trigger outbound image requests from the reader's browser; if your deployment is on an internal network, that is a small but real egress path you should be aware of.
Alternatives and the difference in approach
The README itself points at the design ancestor: bin by WantGuns, described as the source of the design wastebin shamelessly copied. That is a comparison of interface, not of backend, and it tells you where the visual language came from rather than how the two differ in operation.
A more useful contrast is with a general-purpose pastebin that ships accounts and an admin UI. Those projects put a user table, sessions and an administrative surface in front of the same core feature. wastebin removes that layer on purpose, which is why it can be a single binary with a low memory footprint and a SQLite file. The trade is explicit: you get a smaller operational surface and no identity model, and in exchange you cannot answer who created a paste or revoke a user's access. If your requirement is a shared internal scratchpad for a trusted team, the smaller surface is the point. If your requirement is a service with accountability, the missing layer is the whole product, and you should pick something that has it rather than building it onto wastebin.
On the storage side, the SQLite choice is also a boundary. A single file is trivial to back up and trivial to move between hosts, but it is not a clustered store, and nothing in the README describes replication or multi-node operation. One host, one file.
Maintenance cost and the MIT licence
Maintenance here is mostly version pinning. The project ships frequent point releases (3.7.0, 3.7.1, 3.7.2 within roughly two months according to the release list), and the README maintains separate documentation trees per release, which suggests behaviour does shift between them. Upgrading means replacing a binary or an image tag and letting SQLite migrations run, and the README documents one migration failure mode: extended sqlite error code 6410 on the scratch image, resolved by setting TMPDIR. Budget for that check on every upgrade rather than assuming a clean start.
Backups are your responsibility: the database is one file at whatever path WASTEBIN_DATABASE_PATH points to, so a file-level backup of that path, taken while the service is stopped or with SQLite's own backup mechanism, is the whole disaster recovery plan. There is no documented export format.
The licence is MIT, which is permissive and places few obligations on how you redistribute or modify the software. This article is not legal advice, and if you are embedding wastebin in a commercial product or redistributing a modified binary, read the LICENSE file in the repository and take your own counsel on notice requirements.
Editorial conclusion
wastebin fits a single operator who wants a small internal paste service on one host, behind a reverse proxy that already does rate limiting, with the SQLite file on a backed-up volume. It does not fit anyone who needs accounts, per-user quotas, audit trails or an internet-facing deployment without that proxy, because the README states there is no authentication and no DoS mitigation. Before adopting it, verify three things on the version you pin: the full environment variable table, the migration behaviour of the scratch-based image when TMPDIR is unset, and whether deletion-after-read matches how your team actually shares links.
Community notes