Deployment guide

Databunker 0.8.36

Overview

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 that it returns. Databunker encrypts every record with a master key, and it looks records up by token, login, e-mail or phone without storing those values in plain text. It also records consent, supports the "right to be forgotten", and keeps an audit trail of every access.

This guide covers launching and using the SecureAnyCloud Databunker 0.8.36 on Ubuntu 24.04 AMI on Amazon EC2. It is one version of the SecureAnyCloud identity, secrets and PKI listing on AWS Marketplace, and you select it as the software version when you subscribe and launch. The image is a hardened, ready-to-use Databunker server.

What you get:

  • 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, as 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, so 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, and 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, and 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, and 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, and 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. Only TLS 1.2 and 1.3 are enabled. 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 is patched at build time, with unattended security upgrades switched on. See Step 11 for exactly how the image is built.

What is on the image: Databunker 0.8.36 (a SecureAnyCloud 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

Before you deploy, make sure you have:

  • 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, such as 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 port 3000, because Databunker listens on the loopback address only.
  • For production, a DNS name that 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.
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, select your Region, and choose Launch through EC2. Choose m5.large, your key pair, and a security group as described above.

To launch with the AWS CLI instead, 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/sac/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.

2

Connect to your instance

Operating system SSH user

Ubuntu 24.04 ubuntu

ssh -i <your-key.pem> ubuntu@<public-ip>
3

Check the services

systemctl is-active databunker-firstboot databunker nginx
active active active

Only SSH, HTTP and HTTPS are public, and 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 [::]:*

Run a local health check, which is answered only on the loopback address, to confirm that Databunker can reach its vault:

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/status
200
4

Read the root token and the certificate fingerprint

sudo cat /root/databunker-credentials.txt

The file (root only, mode 0600) contains 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 SecureAnyCloud, 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).

The certificate 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 = sac 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
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 that only you can read, so the token never appears on a command line. 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, and 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 will differ from this output.

Upstream's API documentation describes the full API (consents, legal bases, processing activities, sessions, shared records, user apps). Lookups by e-mail or phone put that value in the request path, and Databunker also writes the path to its own service log. Prefer lookups by token.

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 that you trust.

7

Configuration, routes and limits

The configuration is /etc/databunker/databunker.yaml, and it contains no secret. 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 that is reachable from a network you do not control.

What is reachable without the root token. By Databunker's design, the following are reachable: /status, the console's static pages, and /v1/sys/uiconfiguration and /v1/sys/cookiesettings (the console's settings). Recording a consent for an e-mail or phone is also reachable (POST /v1/agreement/<legal-basis>/email|phone/<id>), so a website can capture consent without a login. This route is rate-limited to 30 per minute per client address.

Two kinds of capability links are reachable, and their 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), and 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/sac-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/sac/databunker/nginx-site.tmpl or /etc/nginx/conf.d/sac-databunker-maps.conf, run sudo databunker-set-domain --boot, then sudo systemctl reload nginx.

8

Use your own domain and certificate

Point a DNS record (for example vault.example.com) at the instance, then run the following command:

sudo databunker-set-domain vault.example.com

nginx then serves that name, and the instance's EC2 name and addresses keep working. If the certificate is still the SecureAnyCloud 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), then run sudo systemctl reload nginx. The databunker-set-domain command never overwrites a certificate that is not SecureAnyCloud's own. Check the current name and fingerprint with sudo databunker-set-domain --show.

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 nginx closes the login routes (/v1/prelogin, /v1/login, /v1/captcha):

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 the login routes, note their 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 the login routes, configure smtp: (or sms:) in /etc/databunker/databunker.yaml and restart Databunker. Then replace /etc/nginx/sac/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.

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, and store it separately from /etc/databunker/masterkey, which you must also copy off the instance.

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.

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/sac-databunker/SOURCE.txt sed -n '1,4p' /usr/share/doc/sac-databunker/BUILD-INFO
sac 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; sac is not affiliated with or endorsed by it. Databunker 0.8.36 - sac 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-sac"

Databunker publishes no tagged releases. Version 0.8.36 is upstream commit 1d96827d1cd6 on its master branch, which this image pins. SecureAnyCloud builds the binary from that commit on a separate build host with the current Go toolchain, and 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. SecureAnyCloud is not affiliated with or endorsed by them.

Security notes

  • Metadata service. The AMI requires IMDSv2, and systemd denies Databunker, nginx and the first-boot service access to the instance metadata addresses. 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 (the adm and systemd-journal groups).
  • 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 that you trust, and use the API for automation.
  • Upgrades. Ubuntu security updates (including nginx) install automatically. Databunker itself is a single binary, and SecureAnyCloud publishes new versions of this AMI for new Databunker versions.

Support

SecureAnyCloud supports this image. To reach the support team, email sales@secureanycloud.com. See the identity, secrets and PKI listing guide for the other versions in this listing.

Deploy on AWS

Launch Databunker 0.8.36 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

Deploy on AWS