Databases AWS

Databasus 3.66.0 on AWS User Guide

| Product: Databasus 3.66.0 on Ubuntu 24.04 on AWS

Overview

This guide covers launching and using Databasus 3.66.0 on Ubuntu 24.04 from cloudimg on Amazon EC2. It is one version of the cloudimg Hardened Adminer & Database Admin and Backup Tools AMIs listing on AWS Marketplace; you pick it as the software version when you subscribe and launch. The other tools in the listing are described on the listing's guide hub.

Databasus (formerly Postgresus) is a self-hosted backup tool with a web interface. You add each database once, choose where its backups go (a directory on this instance or an S3 bucket, among others), set a schedule and a retention policy, and Databasus runs the dumps, keeps the history, restores a backup on request and tells you when something fails. It backs up PostgreSQL, MySQL, MariaDB and MongoDB.

The cloudimg image makes Databasus safe to run on EC2:

  • Your own administrator, no open sign-up. On its first boot each instance creates one Databasus administrator with a random password before the web server starts. The image contains no account, no password and no setup token, and open sign-up is closed: you add other people from the Users page.
  • Per-instance secrets. Databasus's master key (/databasus-data/secret.key) signs sign-in sessions and encrypts every database password, storage key and notifier credential Databasus stores, and the backups you choose to encrypt. Each instance generates its own key on first boot, together with its own password for Databasus's PostgreSQL metadata database. The service refuses to start with a missing, short or malformed key.
  • HTTPS from the first boot. nginx serves Databasus on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS. Requests for a host name the instance does not serve get no answer.
  • Everything else on localhost. Databasus's own PostgreSQL 17 listens on 127.0.0.1:5437 only with scram-sha-256 passwords. Databasus itself listens on port 4005, and a firewall table on the instance drops every connection to that port that does not come from nginx on the instance itself.
  • Other web sites cannot act with your login. nginx refuses a backup, restore, connection test or download that another web site's page sends in your browser, refuses any form post whose browser Origin is not this instance, and rate limits sign-in and sign-up attempts per address. Databasus records the real client address of each request.
  • No access to the instance metadata service. Databasus and every pg_dump, mysqldump, mariadb-dump, mongodump and webhook it starts, PostgreSQL and nginx are blocked at the kernel level from the EC2 instance metadata service (IPv4 and IPv6) and from the special-purpose address ranges no database or bucket uses (multicast, reserved, benchmarking and IETF protocol ranges). Private addresses in your own VPC stay reachable, so Databasus can back up RDS and EC2 databases there. This also means Databasus cannot use the instance's IAM role: S3 storages use an access key and secret key (Step 7).
  • MySQL and MariaDB clients that never hand over local files. A database server can ask its client to upload a local file (LOAD DATA LOCAL INFILE). On this image the MySQL and MariaDB clients Databasus runs refuse every such request, so a database you add cannot read Databasus's key, settings or backups through them.
  • Built from source, checked. Databasus 3.66.0 is built from its release source (checksum pinned) with Go 1.27.3 and current versions of its libraries, with no known reachable vulnerabilities at build time. The service runs as the unprivileged databasus user with no Linux capabilities. There is no compiler on the image.
  • Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.

What is on the image: Databasus 3.66.0 (/opt/databasus), PostgreSQL 17 for Databasus's own data, the client tools Databasus runs (PostgreSQL 12 to 18, MySQL 8.0, 8.4, 9.7 and 26.10, MariaDB 12.3 and 13.0, MongoDB Database Tools 100.20.1), nginx, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.

Prerequisites

  • An AWS account subscribed to the listing, an EC2 key pair, and a VPC subnet that can reach the databases you want to back up (and your S3 endpoint, if you use one).
  • A security group that allows TCP 22 (SSH), TCP 443 (Databasus) and TCP 80 (redirects to HTTPS) from the networks your administrators work from. Databasus needs no other inbound port.
  • On each database server, a security group rule that lets this instance connect, and a database user that can read everything you want in the backup.

Step 1: Launch the instance

In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick Databasus 3.66.0 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large (a smaller instance also works for a few small databases), your key pair, the subnet and a security group as above. Local backups are written to the root volume, so size it for the backups you plan to keep there, or send them to S3.

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 \
  --block-device-mappings 'DeviceName=/dev/sda1,Ebs={VolumeSize=50,VolumeType=gp3}' \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=databasus}]'

Step 2: Connect to your instance

Version SSH user
Databasus 3.66.0 on Ubuntu 24.04 ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>

Step 3: Check the services

First boot sets the host name, generates the certificate, creates this instance's PostgreSQL cluster, master key and Databasus administrator, and then starts Databasus and nginx:

systemctl is-active databasus-firstboot databasus postgresql@17-main nginx databasus-port-guard
sudo test -f /var/lib/cloudimg/databasus-firstboot.done && echo FIRSTBOOT_DONE

All five units are active and the first boot marker is present:

active
active
active
active
active
FIRSTBOOT_DONE

Only SSH and nginx are reachable from the network. Databasus's PostgreSQL listens on localhost only. Databasus itself always binds port 4005 on every address; the databasus-port-guard firewall table drops any connection to it that does not arrive on the loopback interface, so only nginx on this instance reaches it:

sudo ss -lntpH | awk '{print $4, $6}' | sed -E 's/users:\(\("([^"]+)".*/\1/' | grep -v '127.0.0.5' | sort -u
*:4005 databasus
0.0.0.0:22 sshd
0.0.0.0:443 nginx
0.0.0.0:80 nginx
127.0.0.1:5437 postgres
[::]:22 sshd
[::]:443 nginx
[::]:80 nginx

A health check for a load balancer or uptime monitor answers without signing in:

curl -sk https://127.0.0.1/healthz
ok

Step 4: Get your URL and password

sudo cat /var/lib/cloudimg/databasus-credentials.txt

The file is readable by root only and holds the URL and the administrator's e-mail and password for this instance:

# Databasus 3.66.0 - generated on first boot by databasus-firstboot.service
# These credentials are unique to this instance; none was baked into the image. Keep this file secret.

DATABASUS_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/
DATABASUS_ADMIN_EMAIL=admin@databasus.local
DATABASUS_ADMIN_PASSWORD=<DATABASUS_ADMIN_PASSWORD>
#
# Open DATABASUS_URL in a browser (self-signed certificate minted on this instance's first boot; port 80 redirects to
# https) and sign in with DATABASUS_ADMIN_EMAIL / DATABASUS_ADMIN_PASSWORD. Change the e-mail and password from your
# profile after the first sign-in. Open sign-up is CLOSED: add people from the Users page (Settings).
# Databasus's master key /databasus-data/secret.key (it signs sign-in sessions and encrypts every stored database,
# storage and notifier credential, and backups you choose to encrypt), its PostgreSQL 17 metadata database
# (127.0.0.1:5437) and that database's password (/etc/databasus/databasus.env, root only) are unique to this instance.
# BACK UP secret.key: without it the stored credentials and encrypted backups cannot be read.
# Local backups go to /databasus-data/backups (0700). Instance metadata is blocked for Databasus: S3 storages use
# access keys, not the instance role.
# Self-test:  sudo databasus-selftest      Change the served name:  sudo databasus-set-hostname <your-domain>
# Forgot the password:  sudo databasus-reset-password      Administrators:  sudo databasus-admin --list-admins
# User guide: https://www.cloudimg.co.uk/guides/databasus-3-66-0-on-ubuntu-24-04-aws/

The URL uses the instance's public DNS name from EC2 instance metadata. Opening https://<public-ip>/ sends you on to that name.

The image includes a self test. Through nginx it signs in as the administrator and checks the API, the closed sign-up, the request guards, Databasus's privileges, the port guard, the localhost database and the metadata block:

sudo databasus-selftest
SELFTEST-OK https 301 + healthz + health HEALTHY + version 3.66.0 + UI + anonymous 401 + exactly 1 user admin@databasus.local ADMIN + sign-up closed (403) + sign-in COMPLETED + wrong password refused (401) + 403 cross-site test + 403 cross-origin POST + 444 unknown host + databasus uid databasus, no capabilities, :4005 loopback-only (private 000, nobody 000) + PostgreSQL 127.0.0.1:5437 only + metadata 000 inside databasus, nginx and PostgreSQL (control 200) + secret guard OK

Step 5: Sign in

Open the URL from the credentials file. Your browser warns about the self-signed certificate the first time; accept it for this host (Step 11 replaces it with your own). Sign in with the administrator e-mail and password.

Change the administrator's e-mail address and password from your profile after your first sign-in. To give colleagues access, add them from the Users page under Settings; nobody can create an account on their own.

Step 6: Add a database

Databasus groups databases, storages and notifiers into workspaces. Create a workspace, then choose Add database, pick the engine and enter the host, port, user, password and database name. Test connection checks it before you save. The password is encrypted with your instance's master key before it is stored.

The image carries the client tools for every server version Databasus supports, and Databasus picks the matching one for each database:

Engine Server versions Client tools on the image
PostgreSQL 12, 13, 14, 15, 16, 17, 18 pg_dump, pg_restore, psql 12 to 18 (PGDG packages, kept patched by apt); pg_basebackup, pg_receivewal, pg_combinebackup 17 and 18
MySQL 8.0, 8.4, 9.x, 26.x mysql and mysqldump 8.0.46, 8.4.13, 9.7.4, 26.10.0
MariaDB 10.2 to 13.0 mariadb and mariadb-dump 12.3.3 (servers 10.2 to 12.x) and 13.0.2 (13.x)
MongoDB the versions MongoDB Database Tools 100.20.1 supports mongodump, mongorestore 100.20.1 (kept patched by apt)

MySQL 5.7 and MariaDB 5.5 and 10.1 servers are not supported on this image: there are no Ubuntu 24.04 client builds for them.

T=/opt/databasus/assets/tools/x64
for v in 12 13 14 15 16 17 18; do $T/postgresql/postgresql-$v/bin/pg_dump --version; done
for v in 8.0 8.4 9 26; do $T/mysql/mysql-$v/bin/mysqldump --version; done
$T/mongodb/bin/mongodump --version | head -1
pg_dump (PostgreSQL) 12.22 (Ubuntu 12.22-3.pgdg24.04+1)
pg_dump (PostgreSQL) 13.23 (Ubuntu 13.23-1.pgdg24.04+1)
pg_dump (PostgreSQL) 14.24 (Ubuntu 14.24-1.pgdg24.04+2)
pg_dump (PostgreSQL) 15.19 (Ubuntu 15.19-1.pgdg24.04+2)
pg_dump (PostgreSQL) 16.15 (Ubuntu 16.15-1.pgdg24.04+2)
pg_dump (PostgreSQL) 17.11 (Ubuntu 17.11-1.pgdg24.04+2)
pg_dump (PostgreSQL) 18.6 (Ubuntu 18.6-1.pgdg24.04+2)
mysqldump  Ver 8.0.46 for Linux on x86_64 (MySQL Community Server - GPL)
mysqldump  Ver 8.4.13 for Linux on x86_64 (MySQL Community Server - GPL)
mysqldump  Ver 9.7.4 for Linux on x86_64 (MySQL Community Server - GPL)
mysqldump  Ver 26.10.0 for Linux on x86_64 (MySQL Community Server - GPL)
mongodump version: 100.20.1

For an Amazon RDS or Aurora database, use its endpoint as the host and allow this instance's security group on the database port in the database's security group. Give Databasus a database user that can read every table you want in the backup; a table it cannot read makes the dump fail, and Databasus records that run as failed with the error.

Step 7: Choose where backups go

Local. A Local storage writes into /databasus-data/backups on this instance, which only the databasus service user can open:

sudo stat -c '%a %U:%G %n' /databasus-data /databasus-data/backups
700 databasus:databasus /databasus-data
700 databasus:databasus /databasus-data/backups

Local backups share the root volume. Give the instance a larger volume at launch, or use S3 so that losing the instance does not take its backups with it.

S3. Add an S3 storage with the bucket, its region, the endpoint (https://s3.<region>.amazonaws.com for Amazon S3; S3-compatible stores work too), an access key and a secret key. Both keys are encrypted with your instance's master key before they are stored.

Databasus on this image cannot use the instance's IAM role: the instance metadata service, where the role's temporary credentials come from, is blocked for Databasus so that a database host or webhook URL entered in the interface can never be used to read it. Create an IAM user (or access key) for Databasus that can only reach its own bucket, for example:

{
  "Version": "2012-10-17",
  "Statement": [
    { "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": "arn:aws:s3:::<your-bucket>" },
    { "Effect": "Allow", "Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject"], "Resource": "arn:aws:s3:::<your-bucket>/*" }
  ]
}

Rotate that key in IAM like any other long-lived credential, and update it in the storage's settings when you do.

Step 8: Schedule backups and encrypt them

Open the database's backup settings: choose the storage, the schedule and how long to keep backups, and set Encryption to Encrypted. Encrypted backups are written with a key derived from this instance's master key, so a copy of the bucket or the backup directory is unreadable on its own. Each backup is stored with a small .metadata file next to it that records its encryption salt and IV (not secret without the master key).

Make backup right now runs one immediately. The backup list shows each run with its status, size and duration, and lets you download it (Databasus decrypts it for the download) or restore it.

A backup is only as good as the master key that decrypts it: see Step 10.

Step 9: Restore and notifications

Open a successful backup and choose Restore to restore it into the same database or another one you have added. Restore into an empty database so existing objects do not clash. Databasus refuses to restore a backup into an older server version than the one it came from.

Notifiers tell you when a backup fails or succeeds: e-mail (set the SMTP settings in /etc/databasus/databasus.env, then sudo systemctl restart databasus), Slack, Telegram, Discord, Microsoft Teams, Mattermost and webhooks are supported.

Step 10: Back up the master key

/databasus-data/secret.key holds this instance's master key (64 hexadecimal characters). It decrypts every database password, storage key and notifier credential Databasus has stored and every encrypted backup: without it, those backups cannot be restored and every database and storage would have to be entered again. Only the service user can read it:

sudo stat -c '%a %U:%G %n' /databasus-data/secret.key /etc/databasus/databasus.env
sudo grep -oE '^[A-Z_]+=' /etc/databasus/databasus.env
600 databasus:databasus /databasus-data/secret.key
640 root:databasus /etc/databasus/databasus.env
ENV_MODE=
DATABASE_DSN=
IS_DISABLE_ANONYMOUS_TELEMETRY=
APP_VERSION=
DATABASUS_URL=
LOG_LEVEL=

DATABASE_DSN holds the password of Databasus's own PostgreSQL database, which listens on localhost only. Copy the master key into the place your team keeps secrets (for example AWS Secrets Manager or a password manager) before you rely on the instance; to print it, run sudo cat /databasus-data/secret.key in your own session. To protect Databasus's own settings and history as well, back up its database, the key and the environment file together:

sudo -u postgres pg_dump -p 5437 -Fc databasus > /root/databasus-db.dump
sudo cp -p /databasus-data/secret.key /root/databasus-secret.key.backup
sudo cp -p /etc/databasus/databasus.env /root/databasus.env.backup

Step 11: Use your own domain and certificate

  1. In your DNS, point <your-domain> (an A record) at the instance's public IP address. An Elastic IP keeps that address stable.
  2. Tell the instance to use it. This sets the name nginx accepts and its request guards, sets the URL Databasus uses in e-mails, and generates a new self-signed certificate for it:
sudo databasus-set-hostname <your-domain>
  1. For a certificate your browser trusts, put the certificate chain for <your-domain> in /etc/ssl/databasus/databasus.crt and its private key in /etc/ssl/databasus/databasus.key (root only, mode 600), and run sudo 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.

Step 12: Security checks

Databasus, PostgreSQL and nginx are blocked from the instance metadata service:

for u in nginx databasus postgresql@17-main; do printf '%s ' "$u"; systemctl show -p IPAddressDeny --value "$u" | tr ' ' '\n' | sort | tr '\n' ' '; echo; done
nginx 168.63.129.16/32 169.254.169.254/32 192.0.0.0/24 198.18.0.0/15 224.0.0.0/4 240.0.0.0/4 fd00:ec2::254/128 
databasus 168.63.129.16/32 169.254.169.254/32 192.0.0.0/24 198.18.0.0/15 224.0.0.0/4 240.0.0.0/4 fd00:ec2::254/128 
postgresql@17-main 168.63.129.16/32 169.254.169.254/32 192.0.0.0/24 198.18.0.0/15 224.0.0.0/4 240.0.0.0/4 fd00:ec2::254/128 

The block applies to the whole service, so every dump, restore and webhook request Databasus starts is blocked too: a database registered at 169.254.169.254 fails its connection test, and a webhook to it is never delivered. The same applies to the special-purpose ranges in the list (192.0.0.0/24, 198.18.0.0/15, multicast 224.0.0.0/4 and reserved 240.0.0.0/4).

Private addresses in your own VPC are deliberately not blocked: Databasus has to reach them to back up an Amazon RDS, Aurora or EC2 database in the same VPC. What it can reach there is decided by your security groups and each database's own access rules, so allow this instance only to the databases it should back up. IPv6 egress is unchanged, for databases and S3 endpoints you reach over IPv6.

Databasus runs as databasus with no Linux capabilities and cannot gain any:

P=$(systemctl show -p MainPID --value databasus)
ps -o user= -p "$P"
grep -E '^(CapEff|CapBnd|CapAmb|NoNewPrivs)' /proc/"$P"/status
databasus
CapEff: 0000000000000000
CapBnd: 0000000000000000
CapAmb: 0000000000000000
NoNewPrivs: 1

Databasus's PostgreSQL accepts only the databasus role, from localhost, with a password, plus the postgres superuser over the local socket for root's maintenance:

sudo -u postgres psql -p 5437 -w -tA -c "SELECT type, database, user_name, address, auth_method FROM pg_hba_file_rules ORDER BY rule_number"
local|{all}|{postgres}||peer
host|{databasus}|{databasus}|127.0.0.1|scram-sha-256

The MySQL and MariaDB clients Databasus runs are small root-owned wrappers around the real programs. Each one turns LOCAL INFILE off (mysql and mariadb; the dump tools never answer such a request), and starts the real client with a clean environment and an empty home directory, so neither Databasus's settings nor a .my.cnf in its data directory reach it:

tail -1 /opt/databasus/assets/tools/x64/mysql/mysql-8.4/bin/mysql
exec /usr/bin/env -i PATH=/usr/bin:/bin HOME=/opt/databasus/assets/tools/x64/.client-home LC_ALL=C.UTF-8 LANG=C.UTF-8 /opt/databasus/assets/tools/x64/mysql/mysql-8.4/libexec/mysql "${pre[@]}" --local-infile=0 "$@"

Signed-out callers are refused, sign-up is closed, nginx refuses a connection test that another web site's page sends and a sign-in posted from a foreign Origin, and a request for a host name the instance does not serve gets no answer at all:

H=$(sudo sed -n 's#^DATABASUS_URL=https://\([^/]*\)/$#\1#p' /var/lib/cloudimg/databasus-credentials.txt)
curl -sk -o /dev/null -w 'signed-out workspaces: %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/api/v1/workspaces"
curl -sk -o /dev/null -w 'sign-up: %{http_code}\n' --resolve "$H:443:127.0.0.1" -X POST -H 'Sec-Fetch-Site: same-origin' -H "Origin: https://$H" -H 'Content-Type: application/json' --data '{"email":"someone@example.com","password":"Cloudimg-Probe-1","name":"Someone"}' "https://$H/api/v1/users"
curl -sk -o /dev/null -w 'cross-site connection test: %{http_code}\n' --resolve "$H:443:127.0.0.1" -X POST -H 'Sec-Fetch-Site: cross-site' "https://$H/api/v1/database-tests"
curl -sk -o /dev/null -w 'cross-origin sign-in: %{http_code}\n' --resolve "$H:443:127.0.0.1" -X POST -H 'Origin: https://evil.example' "https://$H/api/v1/sessions"
curl -sk -o /dev/null -w 'unknown host name: %{http_code}\n' --resolve evil.example:443:127.0.0.1 https://evil.example/ || true
signed-out workspaces: 401
sign-up: 403
cross-site connection test: 403
cross-origin sign-in: 403
unknown host name: 000

The credentials, the TLS key, the environment file, the master key and the backups are readable by root (and the last three by the databasus service user) only:

sudo stat -c '%a %U:%G %n' /var/lib/cloudimg/databasus-credentials.txt /etc/ssl/databasus/databasus.key /etc/databasus/databasus.env /databasus-data/secret.key /databasus-data/backups
600 root:root /var/lib/cloudimg/databasus-credentials.txt
600 root:root /etc/ssl/databasus/databasus.key
640 root:databasus /etc/databasus/databasus.env
600 databasus:databasus /databasus-data/secret.key
700 databasus:databasus /databasus-data/backups

Other notes:

  • Sign-in limits. nginx allows about 10 sign-in attempts and 10 sign-up attempts a minute per address and answers more with 429. It uses the address that connected to nginx: forwarding headers sent by a client are replaced.
  • Who can reach it. An administrator can read every registered database through its backups. Open ports 80 and 443 in the security group only to the networks your administrators work from.
  • The build. /usr/share/doc/cloudimg-databasus/BUILD-INFO.txt records the release, its checksums, the toolchain and the library versions; the *.go-version-m.txt files next to it list every library in each program.
  • Logs. nginx logs are in /var/log/nginx; Databasus logs to the journal (journalctl -u databasus), including each request with its client address.

Step 13: Keep it up to date

Ubuntu security updates, the PostgreSQL client tools and the MongoDB tools install automatically. To apply all updates now:

sudo apt-get update && sudo apt-get upgrade -y

New Databasus releases arrive as new versions of this listing, built and checked the same way. To move to one, back up Databasus's database, secret.key and /etc/databasus/databasus.env (Step 10), launch the new version, restore all three and restart databasus. Read the Databasus release notes before you move.

Troubleshooting

The page does not load. Check that first boot finished: until it has created the master key and the administrator, Databasus and nginx stay stopped on purpose.

systemctl is-active databasus-firstboot
sudo journalctl -u databasus-firstboot --no-pager -n 20 -o cat | tail -5

Databasus does not start. Its start-up guard says why in the journal (sudo journalctl -u databasus -b), for example a master key that was emptied or changed.

A backup failed. The error is shown on the backup. The usual causes are a security group or database access rule that does not let this instance in, a wrong password, TLS settings the server does not accept, or a user that cannot read a table.

Forgot the administrator password. Run sudo databasus-reset-password; it sets a new random password for the administrator and writes it to the credentials file:

sudo databasus-reset-password

Support and licensing

Databasus is free software under the Apache License 2.0 (the Databasus authors); the licence and the project's NOTICE are in /usr/share/doc/cloudimg-databasus/. The MySQL client programs are under the GPL version 2 with the Universal FOSS Exception and the MariaDB client programs under the GPL version 2; their copyright files and a written offer of their source code are in /usr/share/doc/cloudimg-databasus/third-party/. The Go libraries are under permissive licences (MIT, BSD, Apache 2.0, MPL 2.0), PostgreSQL under the PostgreSQL licence, MongoDB Database Tools under the Apache License 2.0 and nginx under the BSD licence. There is no per user licence fee. The AMI price covers cloudimg's build, hardening, first boot setup and support. cloudimg is not affiliated with or endorsed by the Databasus project.

  • Email: support@cloudimg.co.uk
  • Website: https://www.cloudimg.co.uk
  • Support: 24/7, with a 24 hour response SLA

The other versions on this listing are on the database admin and backup tools guide.