MicroBin 2.1.0 on AWS User Guide
Overview
This guide covers launching and using the MicroBin 2.1.0 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg documents, forms and scheduling listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.
MicroBin is a small, self hosted pastebin and file sharing web application. Your team pastes text such as code, configuration, notes and logs (with syntax highlighting), uploads files, shortens URLs and makes QR codes, then shares the link. Pastes can expire after a set time or after a number of reads, can be unlisted, and can be encrypted on the server with a password or in the browser before they are sent. Everything stays on your own instance in your own VPC.
Upstream MicroBin listens on plain HTTP, lets anyone create pastes and upload files, lists every public paste, and ships with the admin login admin / m1cr0b1n. The cloudimg image changes that:
- HTTPS from the first boot. nginx serves MicroBin on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS. MicroBin itself listens on
127.0.0.1:8080only. - Two passwords unique to your instance. The uploader password is needed to create a paste or upload a file, so the instance is not an open file host for the internet. The admin password opens the
/adminpanel and is needed to delete a paste. Both are generated on first boot and written to/root/microbin-credentials.txt(root only). The upstream default admin login is refused. Anyone you give a paste's link can read it, which is what a pastebin is for. - No public paste list, unlisted, server encrypted ("private") and browser encrypted ("secret") pastes, burn after reading, and a 24 hour default expiry.
- Fail closed. MicroBin and nginx refuse to start until first boot has generated the certificate and both passwords, so the app is never served with a default or empty login.
- Hardened. Requests for host names the instance does not serve are dropped, the client address nginx passes on is always the real one (a forged
X-Forwarded-Foris overwritten), cross site form posts are refused, admin logins and deletes are rate limited, MicroBin runs as its own user in a systemd sandbox, MicroBin and nginx are blocked from the instance metadata service, the AMI requires IMDSv2, and telemetry and update checks are off. - Your data on its own disk. Pastes, uploaded files and MicroBin's database live on a separate 32 GiB EBS volume mounted at
/var/lib/microbin, which you can resize or snapshot on its own. - The official release, verified. The MicroBin 2.1.0 release binary is checked against a pinned SHA-256 checksum before it is installed, and the image is fully patched Ubuntu 24.04 LTS with unattended security upgrades on.
What is on the image: MicroBin 2.1.0 (the official static release binary in /usr/local/bin/microbin, licence in /usr/share/doc/microbin), 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 with a route to the internet (or a private route you use for management).
- A security group that allows TCP 22 (SSH), TCP 443 (MicroBin) and TCP 80 (redirects to HTTPS). Open 22 from your own networks only; open 443 and 80 to the people you share pastes with.
Step 1: Launch the instance
In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick MicroBin 2.1.0 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large, your key pair and a security group as above. The AMI brings two volumes: the 8 GiB root volume and the 32 GiB data volume for /var/lib/microbin; increase the data volume at launch if you expect large uploads.
With the AWS CLI (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=microbin}]'
Step 2: Connect to your instance
| Version | SSH user |
|---|---|
| MicroBin 2.1.0 on Ubuntu 24.04 | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
Step 3: Check the services
First boot generates the certificate and the passwords, then MicroBin and nginx start:
systemctl is-active microbin nginx microbin-firstboot
sudo test -f /var/lib/cloudimg/microbin-firstboot.done && echo FIRSTBOOT_DONE
All three units are active and the first boot marker is present:
active
active
active
FIRSTBOOT_DONE
Only SSH and nginx listen on the network; MicroBin listens on loopback only, behind nginx:
sudo ss -lntp | awk 'NR>1 {print $4, $6}' | sed -E 's/pid=[0-9]+,fd=[0-9]+/.../g' | sort
0.0.0.0:22 users:(("sshd",...),("systemd",...))
0.0.0.0:443 users:(("nginx",...),("nginx",...),("nginx",...))
0.0.0.0:80 users:(("nginx",...),("nginx",...),("nginx",...))
127.0.0.1:8080 users:(("microbin",...))
127.0.0.53%lo:53 users:(("systemd-resolve",...))
127.0.0.54:53 users:(("systemd-resolve",...))
[::]:22 users:(("sshd",...),("systemd",...))
[::]:443 users:(("nginx",...),("nginx",...),("nginx",...))
[::]:80 users:(("nginx",...),("nginx",...),("nginx",...))
Step 4: Get your URL and passwords
sudo cat /root/microbin-credentials.txt
The file is readable by root only and holds the URL, the admin login and the uploader password of this instance:
# MicroBin 2.1.0 - generated on first boot by microbin-firstboot.service
# These credentials are unique to this instance; none was baked into the image. Keep this file secret.
MICROBIN_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/
MICROBIN_ADMIN_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/admin
MICROBIN_ADMIN_USERNAME=admin
MICROBIN_ADMIN_PASSWORD=<MICROBIN_ADMIN_PASSWORD>
MICROBIN_UPLOADER_PASSWORD=<MICROBIN_UPLOADER_PASSWORD>
#
# Open MICROBIN_URL in a browser (self-signed certificate minted on this instance's first boot; port 80
# redirects to https). Creating a paste or uploading a file needs MICROBIN_UPLOADER_PASSWORD. Anyone you
# give a paste's link can read it. The admin panel (MICROBIN_ADMIN_URL) and deleting a paste need the
# admin username and password.
# New admin password: sudo microbin-set-password --admin
# New uploader password: sudo microbin-set-password --uploader
# Change the name it serves as: sudo microbin-set-hostname <your-dns-name>
# User guide: https://www.cloudimg.co.uk/guides/microbin-2-1-0-on-ubuntu-24-04-aws/
The URL uses the instance's public DNS name from EC2 instance metadata, and the links and QR codes MicroBin shows are built from that configured name, never from the request. The certificate also names the public and private IP addresses, so https://<public-ip>/ works too. To serve MicroBin under your own DNS name, see Step 9.
Give the uploader password to the people who should be able to create pastes. Keep the admin password for whoever looks after the instance.
Step 5: Create a paste
Open the MICROBIN_URL in your browser. The certificate is self signed, so your browser asks you to confirm it the first time (or install your own certificate, Step 9). Type or paste your text into Content, choose how long it should live (Expiration), whether it should disappear after a number of reads (Burn After), the Syntax for highlighting and the Privacy level, enter the uploader password next to Save, and select Save:

MicroBin opens the new paste at a link made of three animal names, such as /upload/monkey-bee-fish. Copy URL copies the link to share, Raw Text Content gives the plain text (handy for curl), and QR shows a QR code of the link:

To share a file, select Select or drop file attachment (or drop the file on the page) before you save. Files up to 256 MB are accepted, and recipients download them with Download:

Step 6: Private and secret pastes
The Privacy list offers:
| Privacy | What it does |
|---|---|
| Public | Anyone with the link can read it. There is no public list of pastes on this image. |
| Unlisted | The same as Public here, since no list is shown. |
| Private | Encrypted on the server with the password you type in Password; readers need the link and the password. |
| Secret | Encrypted in your browser before it is sent, so the server only stores ciphertext; readers need the link and the password. |
Someone who opens a private paste is asked for its password first:

With the right password the paste opens:

Step 7: The admin panel
Open the MICROBIN_ADMIN_URL and sign in as admin with the admin password. The panel lists every paste with its expiry, size and type, and lets you remove any of them:

The panel shows "Version 2.0.4": that is a display string upstream did not update in the 2.1.0 release. The binary is 2.1.0 (microbin --version, Step 11).
Deleting a paste (the Remove link on a paste or in the panel) asks for the admin username and password in a browser login box. Upstream MicroBin lets anyone holding a public link delete it; on this image only the admin can.
Step 8: Check the security posture from the command line
Port 80 redirects to HTTPS, there is no paste list (it redirects to the home page), an upload without the uploader password is refused, and a request for a host name the instance does not serve is dropped without an answer:
H=$(sudo grep '^MICROBIN_URL=' /root/microbin-credentials.txt | sed -E 's#^MICROBIN_URL=https://([^/]+)/.*#\1#')
curl -s -o /dev/null -w 'http:// -> %{http_code} %{redirect_url}\n' --resolve "$H:80:127.0.0.1" "http://$H/"
curl -sk -o /dev/null -w 'home page -> HTTP %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/"
curl -sk -o /dev/null -w 'paste list -> %{http_code} %{redirect_url}\n' --resolve "$H:443:127.0.0.1" "https://$H/list"
curl -sk -o /dev/null -w 'upload without password -> %{http_code} %{redirect_url}\n' --resolve "$H:443:127.0.0.1" -H "Origin: https://$H" -F content=test "https://$H/upload"
curl -sk -o /dev/null -w 'unknown host -> %{http_code}\n' --resolve "evil.example:443:127.0.0.1" "https://evil.example/" || true
http:// -> 301 https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/
home page -> HTTP 200
paste list -> 302 https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/
upload without password -> 302 https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/incorrect
unknown host -> 000
000 means nginx closed the connection without answering, which is how it treats any host name it does not serve.
With the uploader password a paste is created and can be read back as plain text; deleting it needs the admin login. The passwords are passed to curl on standard input, so they never appear in the process list or your shell history:
sudo bash -c '
F=/root/microbin-credentials.txt
U=$(grep "^MICROBIN_UPLOADER_PASSWORD=" $F | cut -d= -f2-)
A=$(grep "^MICROBIN_ADMIN_PASSWORD=" $F | cut -d= -f2-)
H=$(grep "^MICROBIN_URL=" $F | sed -E "s#^MICROBIN_URL=https://([^/]+)/.*#\1#")
R="--resolve $H:443:127.0.0.1"
L=$(printf "form = \"content=Hello from MicroBin on AWS\"\nform = \"expiration=1hour\"\nform = \"uploader_password=%s\"\n" "$U" \
| curl -K - -sk $R -H "Origin: https://$H" -o /dev/null -w "%{redirect_url}" "https://$H/upload")
echo "new paste -> $L"
ID=${L##*/upload/}
curl -sk $R "https://$H/raw/$ID"; echo
curl -sk $R -o /dev/null -w "delete without admin login -> HTTP %{http_code}\n" "https://$H/remove/$ID"
printf "user = \"admin:%s\"\n" "$A" | curl -K - -sk $R -o /dev/null -w "delete with admin login -> HTTP %{http_code}\n" "https://$H/remove/$ID"
curl -sk $R -o /dev/null -w "paste after delete -> HTTP %{http_code}\n" "https://$H/raw/$ID"
'
new paste -> https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/upload/<three-animal-names>
Hello from MicroBin on AWS
delete without admin login -> HTTP 401
delete with admin login -> HTTP 302
paste after delete -> HTTP 404
The passwords live in two root only files: the credentials note and /etc/microbin/secrets.env, which systemd hands to MicroBin as its environment. nginx keeps only a SHA-512 crypt hash of the admin password for deletes:
sudo stat -c '%a %U:%G %n' /root/microbin-credentials.txt /etc/microbin/secrets.env /etc/nginx/.microbin-htpasswd /etc/microbin/microbin.env
sudo sed -E 's/=.*/=<value>/' /etc/microbin/secrets.env
600 root:root /root/microbin-credentials.txt
600 root:root /etc/microbin/secrets.env
640 root:www-data /etc/nginx/.microbin-htpasswd
644 root:root /etc/microbin/microbin.env
MICROBIN_ADMIN_USERNAME=<value>
MICROBIN_ADMIN_PASSWORD=<value>
MICROBIN_UPLOADER_PASSWORD=<value>
The certificate was generated on this instance and names its own addresses:
H=$(sudo grep '^MICROBIN_URL=' /root/microbin-credentials.txt | sed -E 's#^MICROBIN_URL=https://([^/]+)/.*#\1#')
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
subject=CN = ec2-<public-ip-dashed>.<region>.compute.amazonaws.com, O = cloudimg
X509v3 Subject Alternative Name:
DNS:ec2-<public-ip-dashed>.<region>.compute.amazonaws.com, IP Address:<public-ip>, IP Address:<private-ip>, IP Address:127.0.0.1, DNS:localhost
MicroBin and nginx cannot reach the instance metadata service, MicroBin runs as its own user with the passwords from a root only file, and it will not start until first boot has finished and both passwords are in place:
systemctl show microbin nginx -p Id -p IPAddressDeny
systemctl cat microbin | grep -E '^(ExecStartPre|ExecStart|EnvironmentFile|User)='
IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128
Id=microbin.service
IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128
Id=nginx.service
User=microbin
EnvironmentFile=/etc/microbin/microbin.env
EnvironmentFile=/etc/microbin/host.env
EnvironmentFile=/etc/microbin/secrets.env
ExecStartPre=/usr/bin/test -f /var/lib/cloudimg/microbin-firstboot.done
ExecStartPre=+/usr/local/sbin/microbin-auth-guard
ExecStart=/usr/local/bin/microbin --json-db --no-listing --readonly --private --encryption-client-side --encryption-server-side --enable-burn-after --highlightsyntax --qr --disable-telemetry --disable-update-checking
The flags on the ExecStart line are the MicroBin features this image turns on. --readonly together with the uploader password is what makes uploads password protected. To change a feature, run sudo systemctl edit --full microbin, then sudo systemctl restart microbin.
Step 9: Your own DNS name and certificate
Point a DNS record at the instance, then set the name MicroBin is served as. This mints a new self signed certificate for the name, updates nginx, MicroBin's links and the URL in the credentials file, restarts MicroBin and keeps the name across reboots:
sudo microbin-set-hostname <your-domain>
To use a certificate from your own certificate authority instead, copy it over the generated pair and reload nginx (running microbin-set-hostname again replaces it with a self signed one):
sudo install -m 0644 <your-domain>.crt /etc/ssl/microbin/microbin.crt
sudo install -m 0600 <your-domain>.key /etc/ssl/microbin/microbin.key
sudo nginx -t && sudo systemctl reload nginx
Step 10: Change the passwords
microbin-set-password generates a new random admin password (--admin, the default) or uploader password (--uploader), writes it to /etc/microbin/secrets.env and /root/microbin-credentials.txt, updates nginx's hash of the admin password and restarts MicroBin:
sudo microbin-set-password --uploader
To choose a password yourself, hand it over on standard input (printf is a shell builtin, so the password never appears in the process list; start the line with a space so most shells keep it out of your history). Passwords are 12 to 128 characters from A-Z a-z 0-9 . _ ~ @ % + = , -:
printf '%s\n' '<new-password>' | sudo microbin-set-password --admin --stdin
Step 11: Data, backups and server components
Pastes, uploaded files and MicroBin's JSON database live on the data volume:
df -h /var/lib/microbin | sed 1d
grep /var/lib/microbin /etc/fstab | sed -E 's/UUID=[0-9a-f-]+/UUID=<uuid>/'
microbin --version
nginx -v 2>&1
/dev/nvme1n1 32G 40K 30G 1% /var/lib/microbin
UUID=<uuid> /var/lib/microbin ext4 defaults,nofail 0 2
microbin 2.1.0
nginx version: nginx/1.24.0 (Ubuntu)
To back up MicroBin, take an EBS snapshot of the data volume (or copy /var/lib/microbin while microbin is stopped). To give it more room, grow the volume in the EC2 console and run sudo resize2fs on its device.
| Component | Path |
|---|---|
| MicroBin binary | /usr/local/bin/microbin |
| Licence and source note | /usr/share/doc/microbin/ |
| Settings | /etc/microbin/microbin.env |
Public URL (set by microbin-set-hostname) |
/etc/microbin/host.env |
Passwords (set by microbin-set-password) |
/etc/microbin/secrets.env (mode 0600) |
| Data: database, uploads | /var/lib/microbin (its own EBS volume) |
| nginx site | /etc/nginx/sites-available/cloudimg-microbin |
| Delete login file | /etc/nginx/.microbin-htpasswd (SHA-512 crypt) |
| Certificate and key | /etc/ssl/microbin/ |
| First boot script | /usr/local/sbin/microbin-firstboot.sh |
| Credentials | /root/microbin-credentials.txt (mode 0600) |
Step 12: Security recommendations
- Allow port 22 in the security group from your own networks only, and ports 443 and 80 only to the people you share pastes with.
- Give the uploader password only to people who should create pastes, and rotate both passwords if they may have leaked (Step 10).
- Use your own DNS name and a certificate your clients trust (Step 9).
- Use Private or Secret for anything sensitive, and short expiries.
- Keep the operating system patched; unattended security upgrades are on, and
sudo apt-get update && sudo apt-get upgradeapplies everything else.
Support and licensing
MicroBin is open source under the BSD 3-Clause License; there is no per user or per CPU licence fee. The licence is in /usr/share/doc/microbin/. cloudimg is not affiliated with or endorsed by the MicroBin project. The AMI price covers cloudimg's hardening, first boot setup and support.
- Email: support@cloudimg.co.uk
- Website: https://www.cloudimg.co.uk
- Support: 24/7, with a 24 hour response SLA