PrivateBin is a minimalist, open-source pastebin where the server has zero knowledge of what’s stored. Pastes are encrypted and decrypted in the browser with AES-256-GCM. The key lives in the URL fragment (after #), which browsers never send to the server. Self-host it to share logs, config snippets, credentials or notes with an expiry date, or a “burn after reading” option.
How the encryption works
- Your browser generates a random key, and encrypts the paste locally.
- Only the ciphertext is uploaded.
- The share link looks like
https://paste.example.com/?abc123#KEY. The part after#stays on the client side. - The recipient’s browser fetches the ciphertext, and decrypts it with the key from the URL.
Anyone with the full link can read the paste, so share it over a trusted channel. Add a password for a second factor.
Requirements
- Any small VPS. PrivateBin is a few MB of PHP and JavaScript.
- Storage: the filesystem (default), or a database (MySQL, PostgreSQL, SQLite), or S3/GCS.
Option 1: Docker
# /opt/privatebin/compose.yaml
services:
privatebin:
image: privatebin/nginx-fpm-alpine:latest
restart: unless-stopped
read_only: true
ports:
- "127.0.0.1:8080:8080"
volumes:
- ./data:/srv/data
- ./conf.php:/srv/cfg/conf.php:ro
mkdir -p /opt/privatebin/data && sudo chown 65534:82 /opt/privatebin/data # nobody:www-data in the image
curl -o /opt/privatebin/conf.php https://raw.githubusercontent.com/PrivateBin/PrivateBin/master/cfg/conf.sample.php
cd /opt/privatebin && docker compose up -d
Option 2: PHP on an existing LEMP server
cd /var/www
sudo git clone --depth 1 --branch <latest-release> https://github.com/PrivateBin/PrivateBin.git paste.example.com
sudo cp paste.example.com/cfg/conf.sample.php paste.example.com/cfg/conf.php
sudo chown -R www-data:www-data paste.example.com
Point an Nginx server block with PHP-FPM at that directory. For extra safety, PrivateBin supports moving cfg/, lib/, tpl/ and data/ outside the web root (see the install docs). See Nginx with PHP-FPM.
Key settings in conf.php
[main]
discussion = true ; allow comments on pastes
burnafterreadingselected = false
defaultformatter = "plaintext" ; or "syntaxhighlighting", "markdown"
sizelimit = 10485760 ; 10 MB
fileupload = false ; enable attachments only if you need them
password = true
[expire]
default = "1week"
[expire_options]
5min = 300
1hour = 3600
1day = 86400
1week = 604800
1month = 2592000
; remove "never" to force every paste to expire
[traffic]
limit = 10 ; seconds between pastes from one IP
header = "X_FORWARDED_FOR" ; when behind a reverse proxy
[purge]
limit = 300 ; seconds between purges of expired pastes
Nginx with HTTPS
server {
server_name paste.example.com;
client_max_body_size 15M;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# listen 443 ssl; certbot --nginx -d paste.example.com
}
HTTPS is mandatory: browsers only allow the Web Crypto API on secure origins, and the security model depends on serving untampered JavaScript. See Let’s Encrypt.
Abuse prevention
An open pastebin attracts spam, malware links and leaked data. Options:
- Keep it private: put it behind basic auth, SSO or a VPN. (Recipients need access too, so this suits internal teams.)
- Set short expiry defaults, and remove “never”.
- Keep
fileuploadoff unless needed, and keepsizelimitsmall. - Use the traffic limit, and Fail2ban on the access log. See Fail2ban.
- Because the server can’t read pastes, you can only delete by paste ID when abuse is reported. Keep the access logs to respond to complaints, within your privacy policy.
Command-line clients
Tools like privatebin-cli and PBinCLI encrypt locally and upload, which is handy for sharing logs straight from a server:
journalctl -u nginx -n 200 | pbincli send --server https://paste.example.com/ -E 1day
Backups
Pastes are meant to be temporary, so many admins don’t back up data/ at all. Back up conf.php and your customisations.
Quick reference
| Item | Value |
|---|---|
| Config | cfg/conf.php |
| Data | data/ (or a database) |
| Encryption | AES-256-GCM in the browser; key after # |
| Expiry options | [expire_options] |
| Rate limit | [traffic] limit |
Related: Vaultwarden for passwords, and secrets management.