Databunker 0.8.36 on AWS User Guide
Overview
This guide covers launching and using the Databunker 0.8.36 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg identity, secrets and PKI listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.
Databunker is an open source vault for personal data (PII). Your applications store a person's record (name, e-mail, phone, address, anything in JSON) through its API and keep only the record token it returns. Databunker encrypts every record with a master key, looks records up by token, login, e-mail or phone without storing those values in plain text, records consent, supports the "right to be forgotten", and keeps an audit trail of every access.
The cloudimg image is a hardened, ready-to-use Databunker server:
- nginx in front, Databunker behind it. nginx is the only public listener (ports 80 and 443). Databunker listens on
127.0.0.1:3000, the loopback address only, set in its own configuration. - Per-instance secrets, generated on your instance. First boot generates the master key that encrypts every record and the API root token that authenticates every privileged call. Nothing secret is baked into the image, and no vault ships in it: your vault is created empty on first boot.
- Secrets kept out of logs and process listings. The two values are handed to Databunker's initialisation on pipes, never on a command line; its output (which only shows
****) is checked and destroyed. The master key is a root-only file that systemd passes to the service through a private credentials directory, so it is never in a process environment. The root token is only in a root-only credentials file; the vault keeps a salted hash of it. - Record creation requires the root token. Anonymous clients cannot add records.
- HTTPS from the first boot with a certificate generated on your instance (an end-entity certificate, not a certificate authority). Port 80 redirects to HTTPS. The instance's name is set from its own EC2 public DNS name at first boot; you can change it to your own domain.
- No outbound traffic. No SMTP server, SMS gateway, notification webhook or lookup service is configured, so Databunker sends nothing anywhere. The data-subject self-service login (codes by e-mail or SMS) is closed until you configure a gateway (Step 9).
- Real client addresses, fixed host name, rate limits. The API is rate limited per real TCP peer address; forged forwarding headers are ignored and never logged. Requests for any host name other than the instance's configured names are dropped. The nginx access log never records an e-mail address, phone number or record token.
- Locked down. TLS 1.2 and 1.3 only; Databunker, nginx and the first-boot service are blocked from the instance metadata service, and the AMI requires IMDSv2.
- Built from source, verified, and fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on. See Step 11 for exactly how it is built.
What is on the image: Databunker 0.8.36 (a cloudimg build of the upstream source, /usr/local/bin/databunker, with its admin console built in), nginx from Ubuntu 24.04, 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) from your own networks only, and TCP 443 (the API and admin console) and TCP 80 (redirects to HTTPS) only from the networks that should reach the vault: your application servers, your office or VPN, or your VPC CIDR. A personal-data vault should not be open to
0.0.0.0/0. Do not open 3000: Databunker listens on the loopback address only. - For production, a DNS name you control (for example
vault.example.com) and, ideally, a certificate from a certificate authority. Until then the instance uses its EC2 public DNS name with its own self-signed certificate.
Step 1: Launch the instance
In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick Databunker 0.8.36 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.
With the AWS CLI (replace the values in angle brackets):
aws ec2 run-instances --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=databunker}]'
First boot takes a few seconds after the instance is running. To use your own name from the start, put it in /etc/cloudimg/databunker-domain with user data (for example a cloud-init write_files entry); otherwise first boot uses the instance's public DNS name, or its public IP address if it has no DNS name.
Step 2: Connect to your instance
| Operating system | SSH user |
|---|---|
| Ubuntu 24.04 | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
Step 3: Check the services
systemctl is-active databunker-firstboot databunker nginx
active
active
active
Only SSH, HTTP and HTTPS are public; Databunker listens on the loopback address:
sudo ss -tln | grep -E ':(22|80|443|3000) '
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:*
LISTEN 0 511 0.0.0.0:443 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:3000 0.0.0.0:*
LISTEN 0 511 [::]:80 [::]:*
LISTEN 0 4096 [::]:22 [::]:*
LISTEN 0 511 [::]:443 [::]:*
A local health check (answered only on the loopback address) confirms that Databunker can reach its vault:
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/status
200
Step 4: Read the root token and the certificate fingerprint
sudo cat /root/databunker-credentials.txt
The file (root only, mode 0600) gives this instance's address, the SHA-256 fingerprint of its certificate and the API root token:
# Databunker 0.8.36 - written on first boot by databunker-firstboot.service. Unique to this instance.
DATABUNKER_URL=https://ec2-54-164-141-163.compute-1.amazonaws.com/
DATABUNKER_TLS_SHA256=EE:16:5A:E9:...:(64 hex digits in pairs)
DATABUNKER_ROOT_TOKEN=<the 36-character root token>
...
The root token is the administrator credential: keep it secret and give your applications their own copy through your secrets manager. The master key that encrypts every record is /etc/databunker/masterkey (mode 0600, root). Back up the master key off the instance, and keep it apart from your vault backups: without it nobody, including cloudimg, can decrypt the vault.
sudo stat -c '%a %U:%G %n' /etc/databunker /etc/databunker/masterkey /var/lib/databunker/databunker.db /root/databunker-credentials.txt
750 root:databunker /etc/databunker
600 root:root /etc/databunker/masterkey
600 databunker:databunker /var/lib/databunker/databunker.db
600 root:root /root/databunker-credentials.txt
The certificate is self-signed and unique to your instance, so your browser and clients warn about it. Check that its SHA-256 fingerprint matches DATABUNKER_TLS_SHA256 before you trust it. Do not add it to your operating system's trust store; for production, replace it with a certificate from a certificate authority (Step 8). It is an end-entity certificate for this instance's names only:
openssl x509 -in /etc/ssl/databunker/databunker.crt -noout -subject -ext basicConstraints,keyUsage,extendedKeyUsage,subjectAltName
subject=CN = ec2-54-164-141-163.compute-1.amazonaws.com, O = cloudimg
X509v3 Subject Alternative Name:
DNS:ec2-54-164-141-163.compute-1.amazonaws.com, IP Address:54.164.141.163, IP Address:172.31.82.9
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
Step 5: Store and read personal data through the API
Every privileged call carries the root token in the X-Bunker-Token header. On the instance, put the header in a file only you can read (so the token never appears on a command line), and use the instance's own certificate as the trust anchor:
U=$(sudo sed -n 's/^DATABUNKER_URL=//p' /root/databunker-credentials.txt)
( umask 077; sudo sed -n 's/^DATABUNKER_ROOT_TOKEN=/X-Bunker-Token: /p' /root/databunker-credentials.txt > ~/databunker-token.hdr )
curl -s --cacert /etc/ssl/databunker/databunker.crt "${U}status"; echo
OK
Without the token, Databunker refuses to store a record:
U=$(sudo sed -n 's/^DATABUNKER_URL=//p' /root/databunker-credentials.txt)
curl -s --cacert /etc/ssl/databunker/databunker.crt -w ' %{http_code}\n' -H 'Content-Type: application/json' \
--data '{"login":"alice","email":"alice@example.com"}' "${U}v1/user"
Access denied 403
With the token, create a record, read it back by its token and by its login, update it, and delete it:
U=$(sudo sed -n 's/^DATABUNKER_URL=//p' /root/databunker-credentials.txt)
C="curl -s --cacert /etc/ssl/databunker/databunker.crt -H @$HOME/databunker-token.hdr"
R=$($C -H 'Content-Type: application/json' --data '{"login":"alice","email":"alice@example.com","name":"Alice Example","phone":"+447700900123"}' "${U}v1/user"); echo "$R"
T=$(python3 -c 'import json,sys; print(json.loads(sys.argv[1])["token"])' "$R")
$C "${U}v1/user/token/${T}"; echo
$C "${U}v1/user/login/alice"; echo
$C -X PUT -H 'Content-Type: application/json' --data '{"name":"Alice Smith"}' "${U}v1/user/token/${T}"; echo
$C "${U}v1/user/token/${T}"; echo
$C -X DELETE "${U}v1/user/token/${T}"; echo
$C "${U}v1/user/token/${T}"; echo
{"status":"ok","token":"72563461-dbe9-3006-01b5-c7c18858bbf6"}
{"status":"ok","token":"72563461-dbe9-3006-01b5-c7c18858bbf6","data":{"email":"alice@example.com","login":"alice","name":"Alice Example","phone":"+447700900123"}}
{"status":"ok","token":"72563461-dbe9-3006-01b5-c7c18858bbf6","data":{"email":"alice@example.com","login":"alice","name":"Alice Example","phone":"+447700900123"}}
{"status":"ok","token":"72563461-dbe9-3006-01b5-c7c18858bbf6"}
{"status":"ok","token":"72563461-dbe9-3006-01b5-c7c18858bbf6","data":{"email":"alice@example.com","login":"alice","name":"Alice Smith","phone":"+447700900123"}}
{"status":"ok","result":"done"}
{"status":"ok","token":"72563461-dbe9-3006-01b5-c7c18858bbf6","data":{}}
Your application keeps only the record token; the record itself is stored encrypted. Deleting a record ("forget me") erases its data and keeps an empty stub plus the audit trail. Every access is recorded:
U=$(sudo sed -n 's/^DATABUNKER_URL=//p' /root/databunker-credentials.txt)
curl -s --cacert /etc/ssl/databunker/databunker.crt -H @$HOME/databunker-token.hdr "${U}v1/audit/admin" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d["total"], "audit events; latest:", d["rows"][0]["title"])'
13 audit events; latest: delete user record by token
(Your counts and the latest event differ.)
The full API (consents, legal bases, processing activities, sessions, shared records, user apps) is described in upstream's API documentation. Lookups by e-mail or phone put that value in the request path: prefer lookups by token, which Databunker also writes to its own service log.
Step 6: The admin console
Browse to the DATABUNKER_URL address, choose Root Token as the login method, paste the root token and choose Login:

The console opens on the data-subject requests page:

Audit lists every operation on user records:

Processing settings manage legal bases (consents) and processing activities:

The console keeps the root token in your browser's local storage for the session; choose Logout when you are done. Some console pages load their table and JSON viewer scripts and icons from public CDNs (cdnjs.cloudflare.com, use.fontawesome.com, stackpath.bootstrapcdn.com) without integrity pins; for routine work prefer the API, or use the console from a browser you trust.
Step 7: Configuration, routes and limits
The configuration is /etc/databunker/databunker.yaml (no secret is in it). Record creation requires the root token, and every outbound feature is empty:
sudo grep -E '^( create_user_without_access_token| notification_url| server| host| port| url)' /etc/databunker/databunker.yaml
create_user_without_access_token: false
notification_url: ""
url: ""
server: ""
port: ""
host: "127.0.0.1"
port: "3000"
After a change, run sudo systemctl restart databunker. Keep create_user_without_access_token: false on any instance reachable from a network you do not control.
What is reachable without the root token (by Databunker's design): /status, the console's static pages, /v1/sys/uiconfiguration and /v1/sys/cookiesettings (the console's settings), recording a consent for an e-mail or phone (POST /v1/agreement/<legal-basis>/email|phone/<id>, so a website can capture consent without a login; rate limited to 30 per minute per client address), and two kinds of capability links whose UUID is the credential: shared records (/v1/get/<record-id>) and expiry links (/v1/exp/retain|delete/<token>). Everything else needs the root token. Prometheus metrics are only on the loopback address (http://127.0.0.1/v1/metrics); the public /v1/metrics returns 404.
nginx limits each client address to 50 API requests per second (burst 200). The address is the real TCP peer; a forged X-Forwarded-For header neither changes it nor appears in the log, and the access log replaces every path parameter with :redacted:
sudo grep -E 'limit_req_zone' /etc/nginx/conf.d/cloudimg-databunker-maps.conf
sudo tail -3 /var/log/nginx/access.log | sed -E 's/^[0-9.]+ /<client-ip> /'
limit_req_zone $binary_remote_addr zone=db_api:10m rate=50r/s;
limit_req_zone $db_consent_key zone=db_consent:10m rate=30r/m;
<client-ip> - - [29/Oct/2026:11:33:45 +0000] "GET /v1/prelogin/:redacted HTTP/2.0" 403 146 "curl/8.5.0"
<client-ip> - - [29/Oct/2026:11:33:45 +0000] "GET /v1/metrics HTTP/2.0" 404 146 "curl/8.5.0"
<client-ip> - - [29/Oct/2026:11:33:45 +0000] "POST /v1/agreement/:redacted HTTP/2.0" 200 15 "curl/8.5.0"
To change the limits or the 2 MiB request size, edit /usr/local/lib/cloudimg/databunker/nginx-site.tmpl or /etc/nginx/conf.d/cloudimg-databunker-maps.conf, run sudo databunker-set-domain --boot, then sudo systemctl reload nginx.
Step 8: Use your own domain and certificate
Point a DNS record (for example vault.example.com) at the instance, then:
sudo databunker-set-domain vault.example.com
nginx then serves that name (the instance's EC2 name and addresses keep working) and, if the certificate is still the cloudimg self-signed one, a new self-signed certificate is issued for the new name; the credentials file is updated. To use a certificate from a certificate authority, replace /etc/ssl/databunker/databunker.crt (full chain) and /etc/ssl/databunker/databunker.key (mode 0600, root) and run sudo systemctl reload nginx; databunker-set-domain never overwrites a certificate that is not cloudimg's own. Check the current name and fingerprint with sudo databunker-set-domain --show.
Step 9: Optional: data-subject self-service
Databunker can let the people whose data you hold sign in with a one-time code sent by e-mail or SMS. That needs a mail or SMS gateway, so on this image the login routes (/v1/prelogin, /v1/login, /v1/captcha) are closed by nginx:
U=$(sudo sed -n 's/^DATABUNKER_URL=//p' /root/databunker-credentials.txt)
curl -s --cacert /etc/ssl/databunker/databunker.crt -o /dev/null -w '%{http_code}\n' "${U}v1/prelogin/email/alice@example.com/123456/00"
403
Before you open it, know its limits: upstream's login codes are 6 digits with no attempt limit and are written to Databunker's own log, and its captcha is weak. To open it, configure smtp: (or sms:) in /etc/databunker/databunker.yaml, restart Databunker, replace /etc/nginx/cloudimg/databunker-selfservice-off.conf with an empty file and run sudo systemctl reload nginx. The upstream demo identities (test@securitybunker.io and phone 4444, which always receive the code 4444) stay blocked either way.
Step 10: Back up and restore
Upstream's GET /v1/sys/backup returns nothing for this SQLite vault, so the image ships a helper that takes a consistent online copy while Databunker keeps running:
sudo databunker-backup
BACKUP_OK /var/backups/databunker/databunker-20261029T113345Z.db 147456 bytes (records encrypted; back up /etc/databunker/masterkey separately)
The copy (mode 0600, root) holds every record encrypted. Copy it off the instance together with, but stored separately from, /etc/databunker/masterkey. To restore onto an instance, stop Databunker, put the copy in place as the databunker user, keep the master key that encrypted it, and start Databunker again:
sudo systemctl stop databunker
sudo install -o root -g root -m 0600 /path/to/masterkey /etc/databunker/masterkey
sudo -u databunker sh -c 'rm -f /var/lib/databunker/databunker.db-wal /var/lib/databunker/databunker.db-shm; cat > /var/lib/databunker/databunker.db' < /path/to/databunker-backup.db
sudo systemctl start databunker
The root token of the instance that made the backup works against the restored vault.
Step 11: Licences and source
Databunker is MIT licensed. The image ships its licence, the exact source reference and the build record:
cat /usr/share/doc/cloudimg-databunker/SOURCE.txt
sed -n '1,4p' /usr/share/doc/cloudimg-databunker/BUILD-INFO
cloudimg Databunker 0.8.36 appliance - source and third-party notices
Databunker (MIT licence, LICENSE-databunker-MIT.txt, Copyright (c) 2020, 2021 Yuli Stremovsky):
https://github.com/securitybunker/databunker/tree/1d96827d1cd6faf880f918595cdd104511aa8b7b
Upstream publishes no tags or releases; that commit (master, 2026-07-28) carries version.txt 0.8.36.
Built from that commit with go1.27.3; no Go source file is changed. Changes (tree-delta.txt, BUILD-INFO):
- golang.org/x/image v0.45.0 and golang.org/x/mod v0.40.0 (in-range updates of indirect modules; go.mod/go.sum here);
- two files of the embedded web console replaced under the same paths because their licences forbid
redistribution: site/fonts/comic.ttf (Microsoft Comic Sans MS, the captcha font) is DejaVu Sans Bold from Ubuntu
fonts-dejavu-core 2.37-8 (Bitstream Vera licence, LICENSE-dejavu-fonts.txt), and site/GeoLite2-Country.mmdb
(MaxMind GeoLite2) is DB-IP IP to Country Lite 2026-10.
IP Geolocation by DB-IP (https://db-ip.com): the DB-IP IP to Country Lite database is licensed under the Creative
Commons Attribution 4.0 International License (https://creativecommons.org/licenses/by/4.0/).
Databunker is a trademark of its respective owner; cloudimg is not affiliated with or endorsed by it.
Databunker 0.8.36 - cloudimg rebuild of the pinned upstream commit
source: https://github.com/securitybunker/databunker.git commit 1d96827d1cd6faf880f918595cdd104511aa8b7b (master, version.txt 0.8.36; upstream publishes no tags or releases) (MIT)
toolchain: go version go1.27.3 linux/amd64
command: packr v1.30.1; CGO_ENABLED=0 go build -trimpath -buildvcs=false -ldflags="-s -w -buildid= -X main.version=0.8.36-1d96827d1cd6-cloudimg"
Databunker publishes no tagged releases: version 0.8.36 is upstream commit 1d96827d1cd6 on its master branch, which this image pins. cloudimg builds the binary from that commit on a separate build host with the current Go toolchain (the image never contains a compiler); govulncheck reports no known vulnerability in the result. Two console files are replaced for licensing: the captcha font (DejaVu Sans) and the IP-to-country database (IP Geolocation by DB-IP, licensed under CC BY 4.0); nothing else changes. All product and company names are trademarks or registered trademarks of their respective holders; cloudimg is not affiliated with or endorsed by them.
Security notes
- Metadata service. The AMI requires IMDSv2, and Databunker, nginx and the first-boot service are denied the instance metadata addresses by systemd. Databunker makes no outbound requests on this image.
systemctl show -p IPAddressDeny databunker nginx databunker-firstboot
IPAddressDeny=fd00:ec2::254/128 169.254.169.254/32 ::ffff:169.254.169.254/128 168.63.129.16/32
IPAddressDeny=fd00:ec2::254/128 169.254.169.254/32 ::ffff:169.254.169.254/128 168.63.129.16/32
IPAddressDeny=fd00:ec2::254/128 169.254.169.254/32 ::ffff:169.254.169.254/128 168.63.129.16/32
- The service log. Databunker writes each request's method and path to its own log (
journalctl -u databunker), so a lookup by e-mail or phone, or a shared-record link, appears there. Look records up by token, and limit who can read the system journal (theadmandsystemd-journalgroups). - Console scripts. The admin console bundles bootstrap-table 1.15.5 and loads highlight.js 9.15.10 and jsoneditor 7.0.4 from cdnjs. Those versions have published moderate, browser-side advisories (cross-site scripting through crafted table or JSON content, prototype pollution and slow regular expressions); jsoneditor is used only on the data-subject pages, which are closed here. Treat the console as an administrator tool on a browser you trust, and use the API for automation.
- Upgrades. Ubuntu security updates (including nginx) install automatically. Databunker itself is a single binary; cloudimg publishes new versions of this AMI for new Databunker versions.
Support
cloudimg supports this image: email support@cloudimg.co.uk. See the identity, secrets and PKI listing guide for the other versions in this listing.