Self-hosted service
WardPearce/paaster avatar
WardPearce/paaster

paaster encrypts pastes in the browser and keeps the key in the URL fragment

Paaster is a secure and user-friendly pastebin application that prioritizes privacy and simplicity. With end-to-end encryption and paste history, Paaster ensures that your pasted code remains confidential and accessible.

566 stars27 forksTypeScriptAGPL-3.0

At a glance

What is it?
paaster is a self-hostable pastebin where content is encrypted locally with libsodium and the secret travels as a URI fragment the server never sees. It suits people sharing code or text over a link without handing the host a readable copy.
Who is it for?
Adopt paaster if you want to share a paste over a link and want the host to be unable to read it, and you are willing to host the instance yourself or trust the one you use. Do not adopt it if you need the host operator to be able to read, index or moderate pastes, because the encryption is unconditional by design, and do not trust a third party instance with anything sensitive, because the project says so directly.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The server never holds the key, and that is the design

paaster is described as a secure and user-friendly pastebin application that prioritizes privacy and simplicity, with end-to-end encryption and paste history so that pasted code remains confidential and accessible. The security model is described as a zero-trust encryption methodology: when you paste code into paaster it is encrypted locally in your browser using a secret that is never shared with the server, and only people you share the link with can view the paste. The consequence is worth stating plainly, because it is unusual for a pastebin. The server stores ciphertext and a link that contains no usable secret, so an operator with full database access cannot read your paste. The project is also unusually direct about the trust question. Asked whether you can trust an instance of paaster that you do not host yourself, the answer is no, because anyone could modify the functionality to expose your secret key to the server, and the recommendation is to use an instance you host or trust. The application is written in TypeScript, licensed under AGPL-3.0, and the repository holds a docker-compose.yml, a paaster/ directory, docs/, previews/ and assets/.

Secrets travel in the fragment, not the request

The transport mechanism is the part that makes the scheme work, and it is worth understanding. Paaster uses URI fragments to transport secrets, and the reason is that URI fragments are not meant to be sent to the server, so a paste link and its secret can travel in the same string while the server only ever receives the part before the hash. The documentation cites the Mozilla Foundation's web mechanics documentation for that behaviour and points at a Bitwarden article covering the same pattern. The key is then stored client side, in IndexedDB, when the paste is created, which is what allows the paste history feature to list and reopen your own pastes. The project is clear that this has a downside. Storing client secrets in IndexedDB makes paaster vulnerable to malicious JavaScript, and the mitigation given is that it would require malicious code to be present at the application build time, which connects directly to the supply chain measures in the feature list. The same section notes that server secrets are also stored in IndexedDB at paste creation time, which is what allows later modification or deletion of pastes. So the same browser storage holds both halves of the scheme, and the security of the whole thing rests on the build being trustworthy.

libsodium does the cryptography, through a narrow set of calls

The cipher section is short and specific, and it tells you exactly what the scheme is built on. Paaster uses three families of libsodium functions: the crypto_secretstream_xchacha20poly1305 family, crypto_pwhash, and crypto_secretbox_easy. These are implemented with the libsodium-wrappers-sumo library. The choice of a secret stream cipher with XChaCha20 and Poly1305 is the interesting part, because a secret stream construction is what lets a paste be read progressively rather than requiring the whole payload at once, which is what a paste of unknown length needs. crypto_pwhash handles the password derivation, and the secret box is the authenticated encryption for the small payloads such as the metadata. The important structural point is that all of this happens in the browser before the content is transmitted, and none of the key is available to the server. The list of cipher functions is also the honest bound on the security claim, since a reader can check the whole surface area of the cryptography in one screen.

Send to device moves a paste without a link

One feature is worth isolating because it solves a problem the other pastebins do not. Send to device securely transfers the paste you are viewing to another of your own devices, for example from your phone to your desktop, without manually copying the link. The mechanism is a short-lived code that is valid for five minutes, which you enter on the other device, after which you solve a captcha and the paste is transferred directly. The transfer is protected with end to end encryption using crypto_box_seal, so the server never sees the paste contents or the secret key. The design is a good illustration of what the zero-trust model buys you. Since the server cannot read a paste, it cannot copy one between your devices either, so a capability based transfer scheme with a short code and an explicit human presence check is the only way to do it. The five minute lifetime and the captcha are both deliberate limits on who can complete a transfer, which is a reasonable answer to the question of what stops someone who observes a code from taking your paste.

The compose file shows a two service data path

The deployment story is a Docker compose file, and it is worth reading because it shows the whole data path. The application service runs the wardpearce/paaster image with a restart policy, publishes port 3015 on the host to port 3000 in the container, and takes a block of environment variables for the S3 side: endpoint, region, access key id, secret access key and bucket, all empty by default. Alongside it are MongoDB settings, a database name of paasterv3 and a connection URL pointing at the mongodb service on port 27017. A separate MongoDB service runs the mongo image with a data directory and its log directory pointed at /dev/null, which is a small touch that keeps container logs quiet. A third service, paaster_garage, runs the dxflrs/garage image with an S3 compatible API on port 3900 and two named volumes for its data and metadata, and the comment in the file notes it is not required if you use a hosted S3 solution. So the default topology is an application, a Mongo database and a self-hosted S3 compatible object store, with named volumes for the object store state. You can replace the object store with anything that speaks S3, and you can point the application at an existing MongoDB by changing the two variables.

Supply chain and scope choices the project makes explicit

The feature list includes two items that are about how the project is built rather than what it does, and they are unusual enough to note. There are no dynamically loaded third party dependencies, with the reasoning stated as that malicious code must be present at build time, and the project uses a package lock file together with Socket.dev to fight supply chain attacks. For an application whose entire value proposition is that the server cannot read your data, the build pipeline becomes part of the security model rather than a separate concern, and the documentation is consistent about that. The scope is equally explicit in the section on features that will not be added. Paste editing is refused because paaster is not a text editor, a paste button is refused on the same grounds since content is always uploaded automatically when entered, and optional encryption is refused outright because encryption will always be present. The last one is the most consequential. A pastebin with optional encryption has users who believe their paste is private when it is not, and removing the switch removes that class of mistake, at the cost of ruling out uses where the server needs to read the content. There is a separate CLI tool, a Matrix chat, a documentation site for deployment, configuration, API reference and architecture, and translation through inlang with automatic or manual language detection.

Editorial conclusion

Adopt paaster if you want to share a paste over a link and want the host to be unable to read it, and you are willing to host the instance yourself or trust the one you use. Do not adopt it if you need the host operator to be able to read, index or moderate pastes, because the encryption is unconditional by design, and do not trust a third party instance with anything sensitive, because the project says so directly. Before you deploy, read the security notes on client secret storage in IndexedDB, and decide whether the S3 and MongoDB services in the compose file are what you want, since the default configuration starts both.

Frequently asked questions

How does paaster keep pasted content private from the server?

Content is encrypted locally in your browser with a secret that is never shared with the server, using libsodium's crypto_secretstream_xchacha20poly1305, crypto_pwhash and crypto_secretbox_easy. The secret travels in the URI fragment of the link, which browsers do not send to the server, and only people you share the link with can view the paste.

Can I trust a paaster instance that I do not host?

The project says no, because anyone could modify the functionality to expose your secret key to the server, and it recommends using an instance you host or trust. Client secrets are stored in IndexedDB, which the documentation notes makes the application vulnerable to malicious JavaScript unless malicious code is present at build time.

How do I self-host paaster?

The repository ships a docker-compose.yml that starts the application on port 3015, a MongoDB service, and an optional S3 compatible object store called garage on port 3900 with named volumes for its data and metadata. The S3 endpoint, region, credentials and bucket are set through environment variables that are empty by default, and the object store is not required if you use a hosted S3 solution.

What is the Send to device feature in paaster?

It transfers the paste you are viewing to another of your devices without copying the link. Paaster generates a short-lived code valid for five minutes, you enter it on the other device and solve a captcha, and the transfer is protected with end-to-end encryption using crypto_box_seal so the server never sees the contents or the key.

Does paaster support optional encryption or paste editing?

Neither. The project states it will never have opt-in or opt-out encryption, so encryption is always present, and it will not add paste editing or a paste button, because paaster is a pastebin rather than a text editor and uploaded content is always uploaded automatically.

Official sources

  1. License: AGPL-3.0
  2. Project website
  3. README
  4. Releases
  5. WardPearce/paaster on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/wardpearce-paaster.svg)](https://hysenlabs.com/projects/wardpearce-paaster)

Was this useful?