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

  1. Your browser generates a random key, and encrypts the paste locally.
  2. Only the ciphertext is uploaded.
  3. The share link looks like https://paste.example.com/?abc123#KEY. The part after # stays on the client side.
  4. 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 fileupload off unless needed, and keep sizelimit small.
  • 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.

  • Self-Hosting
  • Privacy
  • Security