wastebin 3.9.0
Overview
wastebin is a minimal, fast pastebin that you host yourself. Paste text or code into a web form and get back a short link to share. Pastes get syntax highlighting for more than 170 languages, and Markdown pastes render as formatted pages (tables, task lists, notes). Each paste can expire, be deleted the first time it is read (burn after reading), or be encrypted with a password.
wastebin is a single program with an embedded SQLite database, so it starts instantly and needs very little memory. This guide covers launching and using the wastebin 3.9.0 on Ubuntu 24.04 AMI from SecureAnyCloud on Amazon EC2. It is one version of the SecureAnyCloud developer and API tools listing on AWS Marketplace, and you pick it as the software version when you subscribe and launch.
What you get:
- Never an open pastebin. An anonymous pastebin that anyone on the internet can write to is soon used to host malware and phishing pages. The whole site therefore sits behind an HTTP Basic Auth prompt whose password is generated on your instance's first boot. The image ships with an empty password file, so if anything goes wrong at first boot, nobody gets in, not even by guessing. Share the gate password with the people who should use your pastebin. Step 10 shows how to open the instance to the public if you really want that.
- HTTPS from the first boot. nginx serves wastebin on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS.
- Per-instance secrets. wastebin's signing key (which lets the creator of a paste delete it) and the salt it uses to turn paste passwords into encryption keys are generated on your instance's first boot. They are kept in a file that only root can read. Upstream wastebin otherwise uses a random key that changes at every restart, and the same fixed salt everywhere.
- Pastes that expire. The web form offers 10 minutes, 1 hour, 1 day (the default), 1 week and 1 month, with no "never" option. Expired pastes are deleted from the database once a day. Pastes are limited to 4 MiB, and nginx limits how fast any one address can send requests.
- A host name taken from configuration, never from the request. Paste links and QR codes use the name set on first boot (the instance's public DNS name). nginx refuses requests for host names the instance does not serve, and the real client address is always the one nginx sees, whatever forwarding headers a request carries.
- Protection against other web sites acting with your login. nginx refuses any state-changing request (creating, confirming or deleting a paste) whose browser
Originis not this instance. Reading a burn-after-reading paste through its raw or download link also deletes it, so those links refuse requests that another web site's page makes in your browser. - No access to the instance metadata service. wastebin listens on a local socket only (nginx is its only client) and is allowed to open local sockets only. nginx and wastebin are blocked at the kernel level from the EC2 instance metadata service (IPv4 and IPv6), and the application cannot reach anything else on the network.
- Built from source, with current fixes. wastebin 3.9.0 is built from its official release source (checksum pinned) with upstream's own Rust compiler release. Five of the libraries it is built with received security fixes after 3.9.0 was released, and the image uses those fixed releases. The exact dependency list is in
/usr/share/doc/sac-wastebin/Cargo.lock, with no known vulnerabilities at build time. There is no compiler on the image. - Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
- QR codes, raw and download views, and a JSON API. Open a paste on a phone from its QR code, fetch it raw or as a download, and script against the small JSON API.
The image contains wastebin 3.9.0 and wastebin-ctl (in /usr/local/bin, with settings in /etc/wastebin and pastes in /var/lib/wastebin), nginx, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.
Default user: ubuntu. Architecture: x86_64. Recommended instance type: m5.large.
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet
- A security group that allows TCP 22 (SSH), TCP 443 (wastebin) and TCP 80 (redirects to HTTPS). Open these ports to the networks your users work from. wastebin needs no other port.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick wastebin 3.9.0 on Ubuntu 24.04 as the software version, pick your Region, then choose Launch through EC2.
Choose m5.large, your key pair, a security group as described above, and a subnet. wastebin itself needs very little, so a smaller instance also works for a small team. Pastes are stored on the root volume.
To launch with the AWS CLI instead, replace the values in angle brackets:
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=wastebin}]'Connect to your instance
The SSH user for wastebin 3.9.0 on Ubuntu 24.04 is ubuntu. Connect with your key pair:
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services
On first boot, the instance sets the host name and certificate and creates the secrets. Then wastebin and nginx start. Check the units and the first-boot marker:
systemctl is-active wastebin-firstboot wastebin nginx wastebin-purge.timer
sudo test -f /var/lib/sac/data/wastebin-firstboot.done && echo FIRSTBOOT_DONEAll four units are active, and the first-boot marker is present:
active active active active FIRSTBOOT_DONEOnly SSH and nginx listen on the network. wastebin listens on a local socket that only nginx can use. Confirm the listeners:
sudo ss -lntpH | grep -v '127.0.0.5' | awk '{print $4, $6}' | sed -E 's/users:\(\("([^"]+)".*/\1/' | sort -u sudo ss -lxpH | grep -F wastebin.sock | awk '{print $5, $9}' | sed -E 's/users:\(\("([^"]+)".*/\1/' | sort -u0.0.0.0:22 sshd 0.0.0.0:443 nginx 0.0.0.0:80 nginx [::]:22 sshd [::]:443 nginx [::]:80 nginx /run/wastebin/wastebin.sock wastebinGet your URL and gate password
Read the credentials file. It is readable by root only and holds the URL and the gate's user name and password for this instance:
sudo cat /var/lib/sac/data/wastebin-credentials.txtThe file looks like this:
# wastebin 3.9.0 - generated on first boot by wastebin-firstboot.service
# These credentials are unique to this instance; none was baked into the image. Keep this file secret. WASTEBIN_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/ WASTEBIN_BASIC_USER=wastebin WASTEBIN_BASIC_PASSWORD=<WASTEBIN_BASIC_PASSWORD>
#
# Open WASTEBIN_URL in a browser (self-signed certificate minted on this instance's first boot; port 80 redirects to # https) and pass the HTTP Basic Auth prompt with WASTEBIN_BASIC_USER / WASTEBIN_BASIC_PASSWORD. wastebin has no # accounts of its own: everyone who has the gate password can create pastes and read any paste whose link they have. # Pastes expire (10 minutes to 1 month, default 1 day); expired pastes are deleted daily. # Self-test:
sudo wastebin-selftest Change the served name:
sudo wastebin-set-hostname <your-domain>
# User guide: https://secureanycloud.com/stacks/wastebin-3-9-0/The URL uses the instance's public DNS name from EC2 instance metadata. Opening https://<public-ip>/ redirects you to that name.
wastebin has no user accounts. The gate password is what separates your users from everyone else, so give it only to the people who should use this pastebin, and change it if it leaks (Step 11).
The image includes a self-test. Through nginx, it passes the gate, creates, reads and deletes test pastes (a plain one, a password-protected one and a burn-after-reading one), and checks the security settings:
sudo wastebin-selftestSELFTEST-OK https 301 + healthz + gate 401/401/200 + paste round trip (raw + view) + password paste refused without/with a wrong password, opened with it + burn-after-reading confirmed then gone after one read + owner-only delete (403 without the cookie) + 403 cross-site raw GET + 403 cross-origin POST + 444 unknown hostCreate a paste in the browser
Open the WASTEBIN_URL in your browser. The certificate is self-signed, so your browser asks you to confirm it the first time. (To avoid the prompt, install your own certificate, as described in Step 9.)
The browser then asks for a user name and password. Enter WASTEBIN_BASIC_USER and WASTEBIN_BASIC_PASSWORD. The paste form appears. Paste or type your text and optionally give it a title. Pick the language (type a few letters to filter the list), choose how long the paste should live, and choose paste.
wastebin opens the new paste with syntax highlighting and line numbers. The address in your browser is the link to share. The buttons at the top right delete the paste (you created it, so your browser may), download it, show it raw, copy it and show a QR code.
Choose Markdown as the language to get a rendered view, with headings, tables, task lists and notes.
A rendered Markdown paste shows images only when they are inline (data: URLs). This image does not let a paste make its readers' browsers fetch images from other web sites, a common way to track who opened a link.
Burn after reading and password-protected pastes
To share a paste that can be read only once, switch on burn after reading before you choose paste. wastebin shows you the link to send instead of the paste. When the recipient opens the link, wastebin first asks them to confirm. The paste is deleted the moment they choose reveal, so it can be read exactly once.
To protect a paste with a password, switch on encrypt and enter a password. wastebin encrypts the paste with a key derived from that password before storing it. Anyone who opens the link must enter the password to see the paste. Without the password, the paste cannot be read, even from the database file.
Send the password through a different channel from the link.
Use the command line and the API
wastebin has a small JSON API. Send a POST to / with the text and options, and it answers with the path of the new paste. Pass the gate password with curl. On the instance itself, run:
H=$(sudo sed -n 's#^WASTEBIN_URL=https://\([^/]*\)/$#\1#p' /var/lib/sac/data/wastebin-credentials.txt)
CFG=$(mktemp)
# the gate password goes into a private temporary curl config, never onto a command line
sudo sed -n 's/^WASTEBIN_BASIC_PASSWORD=\(.*\)/user = "wastebin:\1"/p' /var/lib/sac/data/wastebin-credentials.txt > "$CFG"
P=$(printf '%s' '{"text":"hello from the wastebin API","extension":"txt","expires":3600}' \
| curl -sk -K "$CFG" --resolve "$H:443:127.0.0.1" -H 'Content-Type: application/json' --data-binary @- "https://$H/" \
| python3 -c 'import json, sys; print(json.load(sys.stdin)["path"])')
curl -sk -K "$CFG" --resolve "$H:443:127.0.0.1" -H 'Sec-Fetch-Site: same-origin' "https://$H/raw$P"; echo
curl -sk -K "$CFG" --resolve "$H:443:127.0.0.1" -o /dev/null -w 'paste view: HTTP %{http_code}\n' "https://$H$P" rm -f "$CFG"hello from the wastebin API paste view: HTTP 200The fields are text (required), extension (the language, for example py, rs, md), title, expires (seconds), burn_after_reading (true or false) and password. The answer also carries an owner token. Opening https://<your-wastebin>/<id>?owner=<token> (with the token URL-encoded) in a browser lets that browser delete the paste.
From your own computer, use the instance's URL and the gate credentials. Keep the password out of your shell history by putting it in a curl config file (user = "wastebin:<gate-password>", mode 600) and passing the file with -K. Two notes:
- The raw (
/raw/<id>) and download (/dl/<id>) links answer only requests that show they come from the instance's own pages, because reading a burn-after-reading paste there deletes it. Browsers send that proof by themselves. With curl, add-H 'Sec-Fetch-Site: same-origin'as above. - An API request can leave out
expires, and the paste then never expires. The web form always sets an expiry. Everyone who can create pastes has the gate password, so this is a choice for your users rather than for strangers.
To try burn after reading from the command line, read a paste twice:
H=$(sudo sed -n 's#^WASTEBIN_URL=https://\([^/]*\)/$#\1#p' /var/lib/sac/data/wastebin-credentials.txt)
CFG=$(mktemp)
sudo sed -n 's/^WASTEBIN_BASIC_PASSWORD=\(.*\)/user = "wastebin:\1"/p' /var/lib/sac/data/wastebin-credentials.txt > "$CFG"
P=$(printf '%s' '{"text":"read me once","expires":600,"burn_after_reading":true}' \
| curl -sk -K "$CFG" --resolve "$H:443:127.0.0.1" -H 'Content-Type: application/json' --data-binary @- "https://$H/" \
| python3 -c 'import json, sys; print(json.load(sys.stdin)["path"])')
echo "first read: $(curl -sk -K "$CFG" --resolve "$H:443:127.0.0.1" -H 'Sec-Fetch-Site: same-origin' "https://$H/raw$P")"
echo "second read: HTTP $(curl -sk -K "$CFG" --resolve "$H:443:127.0.0.1" -H 'Sec-Fetch-Site: same-origin' -o /dev/null -w '%{http_code}' "https://$H/raw$P")" rm -f "$CFG"first read: read me once second read: HTTP 404Expiry, size limit and storage
The settings are in /etc/wastebin/wastebin.conf. Check the current values:
grep -E '^WASTEBIN_(UNIX_SOCKET_PATH|MAX_BODY_SIZE|PASTE_EXPIRATIONS)=' /etc/wastebin/wastebin.conf systemctl is-enabled wastebin-purge.timerWASTEBIN_UNIX_SOCKET_PATH=/run/wastebin/wastebin.sock WASTEBIN_MAX_BODY_SIZE=4194304 WASTEBIN_PASTE_EXPIRATIONS=10m,1h,1d=d,1w,1M enabledWASTEBIN_PASTE_EXPIRATIONS lists the choices that the web form offers. The unit letters are m for minutes, h for hours, d for days, w for weeks, M for months and y for years, and =d marks the default. Adding 0 would offer pastes that never expire.
To change the choices or the 4 MiB size limit, edit the file. For the size limit, also set the same number of bytes in client_max_body_size in /etc/nginx/sites-available/sac-wastebin. Then restart:
sudo nano /etc/wastebin/wastebin.conf
sudo systemctl restart wastebin && sudo nginx -t && sudo systemctl reload nginxPastes are stored in the SQLite database /var/lib/wastebin/state.db, and wastebin-purge.timer deletes expired pastes from it once a day. To back up the database, stop wastebin for a moment and copy the file:
sudo systemctl stop wastebin && sudo cp -a /var/lib/wastebin/state.db <backup-dir>/wastebin-$(date +%F).db;
sudo systemctl start wastebinKeep copies off the instance too, for example in Amazon S3, or take EBS snapshots of the volume. Password-protected pastes stay encrypted in the backup. The per-instance salt in /etc/wastebin/secrets.env is part of how their keys are made, so restore a database only together with that file.
Use your own domain and certificate
- In your DNS, point
<your-domain>(an A record) at the instance's public IP address. An Elastic IP keeps that address stable. - Tell wastebin to use the domain. This sets the name in paste links and QR codes and the name that nginx and the request guards accept. It also generates a new self-signed certificate for the domain:
sudo wastebin-set-hostname <your-domain>- For a certificate that your users' browsers trust, put the certificate chain for
<your-domain>in/etc/ssl/wastebin/wastebin.crtand its private key in/etc/ssl/wastebin/wastebin.key(root only, mode 600). Then runsudo systemctl reload nginx. Alternatively, put the instance behind an Application Load Balancer with an AWS Certificate Manager certificate that forwards to port 443 on the instance.
Open the pastebin to the public (opt-in)
Think twice before you do this. A pastebin that anyone on the internet can write to is soon found and used to host malware, phishing pages and stolen data, and you are responsible for what it serves. Keep the gate on unless you will watch what is pasted.
If you still want to open the pastebin, switch the gate off and allow port 443 (and 80) from anywhere in the security group:
# anyone can now create and read pastes at https://<your-domain>/
sudo sed -i -E 's/^(auth_basic)/# \1/' /etc/nginx/wastebin-gate.conf && sudo nginx -t && sudo systemctl reload nginxTo put the gate back, remove the # in front of the two auth_basic lines in /etc/nginx/wastebin-gate.conf and reload nginx.
Security notes
nginx, wastebin and the purge job are blocked from the instance metadata service. Verify the deny list:
for u in nginx wastebin wastebin-purge; do printf '%s ' "$u"; systemctl show -p IPAddressDeny --value "$u" | tr ' ' '\n' | sort | tr '\n' ' '; echo; donenginx 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128 wastebin 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128 wastebin-purge 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128The gate answers before wastebin does. nginx refuses a state-changing request or a raw read that another web site's page sends, and a request for a host name the instance does not serve gets no answer at all. Test each case:
H=$(sudo sed -n 's#^WASTEBIN_URL=https://\([^/]*\)/$#\1#p' /var/lib/sac/data/wastebin-credentials.txt)
curl -sk -o /dev/null -w 'no password: %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/"
curl -sk -o /dev/null -w 'cross-origin POST: %{http_code}\n' --resolve "$H:443:127.0.0.1" -X POST -H 'Origin: https://evil.example' --data 'text=x' "https://$H/new"
curl -sk -o /dev/null -w 'cross-site raw read: %{http_code}\n' --resolve "$H:443:127.0.0.1" -H 'Sec-Fetch-Site: cross-site' "https://$H/raw/x"
curl -sk -o /dev/null -w 'unknown host name: %{http_code}\n' --resolve evil.example:443:127.0.0.1 https://evil.example/ || trueno password: 401 cross-origin POST: 403 cross-site raw read: 403 unknown host name: 000The secrets are readable by root only, and the pastes are readable by root and the wastebin service user only. The build is recorded on the image. Check the permissions and the build record:
sudo stat -c '%a %U:%G %n' /etc/wastebin/secrets.env /var/lib/sac/data/wastebin-credentials.txt /etc/nginx/wastebin.htpasswd /var/lib/wastebin wastebin-ctl --version sha256sum /usr/share/doc/sac-wastebin/Cargo.lock | cut -c1-16600 root:root /etc/wastebin/secrets.env 600 root:root /var/lib/sac/data/wastebin-credentials.txt 640 root:www-data /etc/nginx/wastebin.htpasswd 700 wastebin:wastebin /var/lib/wastebin wastebin-ctl 3.9.0 48ccb6677802dbddOther notes:
- The gate password is a 24-character random string, stored as a SHA-512 crypt hash in
/etc/nginx/wastebin.htpasswd. To change it, write a new hash there.printf '%s\n' '<new-password>' | openssl passwd -6 -stdingives the hash, and the line iswastebin:<hash>. Then update the credentials file and reload nginx. - Deleting pastes. The browser that created a paste can delete it (a signed cookie). There is no administrator view. On the instance,
sudo -u wastebin wastebin-ctl list --database /var/lib/wastebin/state.dblists pastes, andwastebin-ctl deleteremoves one by its ID. - The build.
/usr/share/doc/sac-wastebin/BUILD-INFO.txtrecords the release, the compiler and the five dependency updates (ammonia, ctutils, zstd, zstd-safe and zstd-sys, each to the release with the published fix).Cargo.locknext to it lists every library in the program. - Logs. nginx logs are in
/var/log/nginx. wastebin logs warnings and errors to the journal (journalctl -u wastebin).
Keep it up to date
Ubuntu security updates install automatically. To apply all updates now:
sudo apt-get update && sudo apt-get upgrade -yNew wastebin releases arrive as new versions of this listing, built and checked the same way. To move to a new version, back up the database and /etc/wastebin/secrets.env (Step 8), launch the new version and restore both. Read the wastebin changelog before you move.
Support and licensing
wastebin is open source under the MIT licence (Matthias Vogelgesang and contributors). The licence text is in /usr/share/doc/sac-wastebin/, and the source code is at github.com/matze/wastebin. The Rust libraries it is built with are open source under permissive licences (MIT, Apache 2.0 and similar).
There is no per-user licence fee. The AMI price covers SecureAnyCloud's build, hardening, first-boot setup and support.
- Email: sales@secureanycloud.com
- Website: https://secureanycloud.com
- Support: 24/7, with a 24-hour response SLA
The other versions on this listing are covered in the developer and API tools guide.
Deploy on AWS
Launch wastebin 3.9.0 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com