PrivateBin
Overview
PrivateBin is a minimalist, open-source pastebin where the server has zero knowledge of the data it stores. Your browser encrypts and decrypts every paste using 256-bit AES-GCM. The decryption key lives only in the URL fragment and is never sent to the server, so the server holds only ciphertext.
The SecureAnyCloud image serves PrivateBin over nginx and PHP-FPM on port 80. The paste store sits on a dedicated data disk, so your encrypted pastes are captured into the image and re-provisioned on every VM. There is no database and, by design, no login or admin account. The image is built from PrivateBin 2.0.5 and backed by 24/7 SecureAnyCloud support.
What you get:
- PrivateBin 2.0.5 served from
/var/www/privatebinby nginx on:80in front of PHP 8.3 FPM - The Filesystem storage model pointed at a dedicated Azure data disk mounted at
/var/lib/privatebin-data nginx.serviceandphp8.3-fpm.serviceas systemd units, enabled and active on every boot- A first-boot service that writes an MOTD banner and a non-secret info note (PrivateBin has no credentials to rotate)
- A static
/healthzendpoint for Azure Load Balancer health probes, with the config directory blocked from the web - 24/7 SecureAnyCloud support
Prerequisites
You need the following:
- An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region
- A VM size of Standard_B2s (2 vCPU / 4 GiB RAM), which is a good starting point
- NSG inbound rules that allow
22/tcpfrom your management network and80/tcpfor the web interface
PrivateBin serves plain HTTP on port 80. For a live site, terminate TLS in front of it with your own domain so that the site runs over HTTPS. The browser Web Crypto API that PrivateBin relies on requires a secure context, which both localhost and HTTPS provide.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure portal, choose Create a resource, search the Marketplace for PrivateBin by SecureAnyCloud, and select Create. On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80). Then choose Review + create and Create.
Step 2 - Deploy from the Azure CLI
Accept the Marketplace terms, create the VM, and open port 80:
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:privatebin-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name privatebin \
--image sac1647283583153:privatebin-ubuntu-24-04:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name privatebin --port 80 --priority 1010Step 3 - Connect to your VM
Connect over SSH as azureuser:
ssh azureuser@<vm-public-ip>Step 4 - Confirm the services are running
nginx serves PrivateBin in front of PHP-FPM, and a one-shot first-boot service writes the per-VM info note. Confirm that all three services are healthy:
systemctl is-active nginx.service php8.3-fpm.service privatebin-firstboot.serviceAll three report active.
Step 5 - Verify the stack and endpoints
Confirm the PrivateBin version, the PHP runtime, the health endpoint and the app itself. Also confirm that the configuration file is never reachable from the web:
grep -m1 'const VERSION' /var/www/privatebin/lib/Controller.php php -r 'echo "PHP " . PHP_VERSION . "\n";' curl -s -o /dev/null -w 'healthz: HTTP %{http_code}\n' http://127.0.0.1/healthz curl -s -o /dev/null -w 'PrivateBin app: HTTP %{http_code}\n' http://127.0.0.1/ curl -s -o /dev/null -w 'cfg/conf.php: HTTP %{http_code} (denied)\n' http://127.0.0.1/cfg/conf.phpThe app and /healthz return 200, while cfg/conf.php returns 403 because nginx blocks the config directory.
Step 6 - The encrypted paste store on a dedicated data disk
PrivateBin stores every paste as ciphertext under /var/lib/privatebin-data. This path is a dedicated Azure data disk, mounted separately from the OS disk and outside the web root. A non-secret info note records the app URL for this VM:
findmnt -no SOURCE,TARGET,FSTYPE /var/lib/privatebin-data grep -m1 'dir =' /var/www/privatebin/cfg/conf.php cat /root/privatebin-credentials.txtThe data disk is mounted at /var/lib/privatebin-data, and the PrivateBin config points its storage dir at it.
The info note is not a credential, because PrivateBin has no login. It records only the URL to open in a browser.
Step 7 - Open PrivateBin and start a new paste
Browse to http://<vm-public-ip>/ in any modern browser, or use your own HTTPS domain. The New Paste editor loads with a toolbar across the top: an expiry selector, Burn after reading, Open discussion, an optional password and a format selector. There is no sign-in, because the server never holds a decryption key.
Step 8 - Compose a paste
Type or paste your content into the editor. Choose how long the paste should live from Expires (from 5 minutes to never). Pick a Format: Plain Text, Source Code with syntax highlighting, or Markdown. Optionally, select Burn after reading to destroy the paste the moment it is first opened, or set a Password for a second decryption factor.
Step 9 - Create and share the encrypted link
Click Create. PrivateBin encrypts the content in your browser, sends only the ciphertext to the server, and shows you a shareable link. The part of the link after the # is the decryption key. It stays in your browser and is never transmitted, so anyone with the full link can read the paste, but the server never can. Use Copy link, Email or QR code to share it.
Step 10 - Read a paste back
When a recipient opens the full link in any browser, the browser fetches the ciphertext and decrypts it locally using the key from the URL fragment. The recipient sees the original content with an expiry notice. The recipient can clone the paste, download the raw text, or discuss it if you enabled comments.
Step 11 - Create a paste from the command line
PrivateBin also has a JSON API, so you can create pastes from scripts. The following command creates a paste and reads it back, which proves the round trip end to end. The payload is opaque ciphertext, exactly what a browser would send:
IV="$(openssl rand -base64 16 | tr -d '\n')"; SALT="$(openssl rand -base64 8 | tr -d '\n')"; CT="$(openssl rand -base64 48 | tr -d '\n')" REQ="$(printf '{"v":2,"adata":[["%s","%s",100000,256,128,"aes","gcm","none"],"plaintext",0,0],"ct":"%s","meta":{"expire":"5min"}}' "$IV" "$SALT" "$CT")" CREATE="$(curl -s -H 'X-Requested-With: JSONHttpRequest' -H 'Content-Type: application/json' --data-binary "$REQ" http://127.0.0.1/)" PID="$(printf '%s' "$CREATE" | sed -n 's/.*"id":"\([0-9a-f]*\)".*/\1/p')" READ="$(curl -s -H 'X-Requested-With: JSONHttpRequest' "http://127.0.0.1/?$PID")" case "$CREATE$READ" in *'"status":0'*'"ct":'*) echo "OK - created and read paste $PID" ;; *) echo "FAILED"; exit 1 ;; esacIt prints OK - created and read paste <id>. The server stores only the ciphertext that you send. A real client encrypts the content and keeps the key in the URL fragment.
Maintenance
- Data: encrypted pastes live under
/var/lib/privatebin-dataon the dedicated data disk. Back up that directory (for example with an Azure disk snapshot) to preserve pastes. The image purges expired and burn-after-reading pastes automatically. - Traffic limiter: the image ships with PrivateBin's IP-based traffic limiter disabled (
limit = 0in/var/www/privatebin/cfg/conf.php), because it is single-tenant behind your NSG. To rate-limit posting again, setlimit = 10and reload nginx. - File upload: file attachments are off by default. To enable them, set
fileupload = trueunder[main]in/var/www/privatebin/cfg/conf.php. - TLS: PrivateBin serves plain HTTP on port 80. Front it with TLS (for example certbot) and your own domain, so that the browser runs in a secure context over HTTPS.
- Restart: run
sudo systemctl restart nginx.service php8.3-fpm.serviceto restart the web stack. - Security patches: unattended-upgrades remains enabled, so the OS continues to receive security updates automatically.
Support
SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.
This image packages the open-source PrivateBin software (Zlib/libpng License) for convenient deployment on Microsoft Azure. SecureAnyCloud is not affiliated with, endorsed by, or sponsored by the PrivateBin project.
Deploy on Azure
Launch PrivateBin on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
PrivateBin is a minimalist, open-source pastebin where the server has zero knowledge of the data it stores. Your browser encrypts and decrypts every paste using 256-bit AES-GCM. The decryption key lives only in the fragment of the share link and is never sent to the server, so the server holds only ciphertext.
The SecureAnyCloud image serves PrivateBin over nginx and PHP-FPM on port 80. The paste store sits on a dedicated data volume, so your encrypted pastes are captured into the AMI and re-provisioned on every instance. There is no database and, by design, no login or admin account. The image is built from PrivateBin 2.0.5 and backed by 24/7 SecureAnyCloud support.
What you get:
- PrivateBin 2.0.5 served from
/var/www/privatebinby nginx on:80in front of PHP 8.3 FPM - The Filesystem storage model pointed at a dedicated EBS data volume mounted at
/var/lib/privatebin-data nginx.serviceandphp8.3-fpm.serviceas systemd units, enabled and active on every boot- A first-boot service that writes an MOTD banner and a non-secret info note recording the access URL for this instance (PrivateBin has no credentials to rotate)
- A static
/healthzendpoint for load-balancer health checks, with the config directory blocked from the web - 24/7 SecureAnyCloud support
Prerequisites
You need the following:
- An AWS account, an EC2 key pair in the target region, and a VPC with a public subnet
- The recommended instance type, m5.large (2 vCPU / 8 GiB RAM)
- Security group inbound rules that allow
22/tcpfrom your management network and80/tcpfor the web interface, plus443/tcpif you terminate TLS
PrivateBin serves plain HTTP on port 80. For a live site, terminate TLS in front of it with your own domain so that the site runs over HTTPS. The browser Web Crypto API that PrivateBin relies on requires a secure context, which both localhost and HTTPS provide.
Step 1 - Launch the AMI
Subscribe to the listing in AWS Marketplace, choose Continue to Launch, and launch through the EC2 console or the AWS CLI. Select the m5.large instance type, your key pair, and a security group that opens ports 22 and 80 (and 443 for TLS). To launch from the AWS CLI, run:
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <your-key-pair> \
--security-group-ids <security-group-id> \
--subnet-id <subnet-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=privatebin}]'Step 2 - Connect to your instance
Connect over SSH as the default login user for the OS variant that you launched. This listing may ship more than one OS variant, so use the matching login user.
For the Ubuntu 24.04 LTS variant, the SSH login user is ubuntu. Connect with ssh ubuntu@<instance-public-ip>.
Step 3 - Confirm the services are running
nginx serves PrivateBin in front of PHP-FPM, and a one-shot first-boot service writes the per-instance info note. Confirm that all three services are healthy:
systemctl is-active nginx.service php8.3-fpm.service privatebin-firstboot.serviceAll three report active.
Step 4 - Verify the stack and endpoints
Confirm the PrivateBin version, the PHP runtime, the health endpoint and the app itself. Also confirm that the configuration file is never reachable from the web:
grep -m1 'const VERSION' /var/www/privatebin/lib/Controller.php php -r 'echo "PHP " . PHP_VERSION . "\n";' curl -s -o /dev/null -w 'healthz: HTTP %{http_code}\n' http://127.0.0.1/healthz curl -s -o /dev/null -w 'PrivateBin app: HTTP %{http_code}\n' http://127.0.0.1/ curl -s -o /dev/null -w 'cfg/conf.php: HTTP %{http_code} (denied)\n' http://127.0.0.1/cfg/conf.phpThe app and /healthz return 200, while cfg/conf.php returns 403 because nginx blocks the config directory.
Step 5 - The encrypted paste store on a dedicated data volume
PrivateBin stores every paste as ciphertext under /var/lib/privatebin-data. This path is a dedicated EBS data volume, mounted separately from the OS disk and outside the web root. A non-secret info note records the app URL for this instance:
findmnt -no SOURCE,TARGET,FSTYPE /var/lib/privatebin-data
sudo grep -m1 'dir =' /var/www/privatebin/cfg/conf.php
sudo cat /root/privatebin-credentials.txtThe data volume is mounted at /var/lib/privatebin-data, and the PrivateBin config points its storage dir at it. The info note is not a credential, because PrivateBin has no login. It records only the URL to open in a browser.
Step 6 - Open PrivateBin and start a new paste
Browse to http://<instance-public-ip>/ in any modern browser, or use your own HTTPS domain. The New Paste editor loads with a toolbar across the top: an expiry selector, Burn after reading, Open discussion, an optional password and a format selector. There is no sign-in, because the server never holds a decryption key.
Step 7 - Compose a paste
Type or paste your content into the editor. Choose how long the paste should live from Expires (from 5 minutes to never). Pick a Format: Plain Text, Source Code with syntax highlighting, or Markdown. Optionally, select Burn after reading to destroy the paste the moment it is first opened, or set a Password for a second decryption factor.
Step 8 - Create and share the encrypted link
Click Create. PrivateBin encrypts the content in your browser, sends only the ciphertext to the server, and shows you a shareable link. The part of the link after the # is the decryption key. It stays in your browser and is never transmitted, so anyone with the full link can read the paste, but the server never can. Use Copy link, Email or QR code to share it.
Step 9 - Share by QR code
The QR code action renders the full share link, decryption key included, as a QR code. A recipient can then open the encrypted paste on a phone without retyping the link.
Step 10 - Create a paste from the command line
PrivateBin also has a JSON API, so you can create pastes from scripts. The following command creates a paste and reads it back, which proves the round trip end to end. The payload is opaque ciphertext, exactly what a browser would send:
IV="$(openssl rand -base64 16 | tr -d '\n')"; SALT="$(openssl rand -base64 8 | tr -d '\n')"; CT="$(openssl rand -base64 48 | tr -d '\n')" REQ="$(printf '{"v":2,"adata":[["%s","%s",100000,256,128,"aes","gcm","none"],"plaintext",0,0],"ct":"%s","meta":{"expire":"5min"}}' "$IV" "$SALT" "$CT")" CREATE="$(curl -s -H 'X-Requested-With: JSONHttpRequest' -H 'Content-Type: application/json' --data-binary "$REQ" http://127.0.0.1/)" PID="$(printf '%s' "$CREATE" | sed -n 's/.*"id":"\([0-9a-f]*\)".*/\1/p')" READ="$(curl -s -H 'X-Requested-With: JSONHttpRequest' "http://127.0.0.1/?$PID")" case "$CREATE$READ" in *'"status":0'*'"ct":'*) echo "OK - created and read paste $PID" ;; *) echo "FAILED"; exit 1 ;; esacIt prints OK - created and read paste <id>. The server stores only the ciphertext that you send. A real client encrypts the content and keeps the key in the URL fragment.
Maintenance
- Data: encrypted pastes live under
/var/lib/privatebin-dataon the dedicated data volume. Back up that directory (for example with an EBS snapshot) to preserve pastes. The image purges expired and burn-after-reading pastes automatically. - Traffic limiter: the image ships with PrivateBin's IP-based traffic limiter disabled (
limit = 0in/var/www/privatebin/cfg/conf.php), because it is single-tenant behind your security group. To rate-limit posting again, setlimit = 10and reload nginx. - File upload: file attachments are off by default. To enable them, set
fileupload = trueunder[main]in/var/www/privatebin/cfg/conf.php. - TLS: PrivateBin serves plain HTTP on port 80. Front it with TLS (for example certbot) and your own domain, so that the browser runs in a secure context over HTTPS.
- Restart: run
sudo systemctl restart nginx.service php8.3-fpm.serviceto restart the web stack. - Security patches: unattended-upgrades remains enabled, so the OS continues to receive security updates automatically.
Support
SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.
This image packages the open-source PrivateBin software (Zlib/libpng License) for convenient deployment on AWS. SecureAnyCloud is not affiliated with, endorsed by, or sponsored by the PrivateBin project.
Deploy on AWS
Launch PrivateBin with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com