ChartDB 1.20.1
Overview
This guide covers launching and using the ChartDB 1.20.1 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. You pick it as the software version when you subscribe and launch.
ChartDB is an open source, web-based database schema visualizer and entity relationship (ER) diagram editor. You import the schema of an existing PostgreSQL, MySQL, MariaDB, SQL Server, SQLite, Oracle or ClickHouse database. To do this, run the one "smart query" that ChartDB gives you and paste its result, or paste a CREATE TABLE script.
ChartDB then draws the diagram. You can edit tables, columns and relationships on the canvas or as DBML, and export the result as SQL, DBML or an image. ChartDB runs entirely in your browser. Your diagrams are stored in your own browser's storage, and there is no backend or database on the server.
Upstream ChartDB is a public web page with no login. The SecureAnyCloud image turns it into a private diagram editor for your team.
What you get:
- HTTPS from the first boot. nginx serves ChartDB on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS.
- A password unique to your instance. HTTP Basic Auth is required for the user
adminon every page, script and setting file. The password is generated on first boot and written to/var/lib/sac/data/chartdb-credentials.txt(root only). nginx stores only a bcrypt hash of it. No password is baked into the image. - No analytics. Unless a runtime setting turns it off, the upstream build loads a third-party analytics script into every visitor's browser. This image ships that setting (
/var/www/chartdb/config.js) with analytics and the ChartDB Cloud links switched off, and with no AI API key. The page still loads its Raleway web font from Google Fonts and the GitHub star button in the header, as upstream does. - Fail closed. nginx refuses to start until first boot has generated the certificate and the password, so the editor is never served without a login.
- Hardened defaults. Requests for any host name the instance does not serve are dropped, only
GETandHEADare accepted, and cross-site requests are refused. nginx is blocked from the instance metadata service, and the AMI requires IMDSv2. - Patched dependencies, no build toolchain on the image. ChartDB is built from the pinned 1.20.1 release, with its JavaScript dependencies raised to versions that fix published advisories (within the same major versions). Node.js is used only during the build and is removed again, so only the static files and nginx ship.
- Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
What is on the image: ChartDB 1.20.1 (the static build in /var/www/chartdb, with the source in /usr/share/chartdb), 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 (ChartDB) and TCP 80 (redirects to HTTPS) from your own networks only.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick ChartDB 1.20.1 on Ubuntu 24.04 as the software version, choose your Region, then choose Launch through EC2.
Choose m5.large, your key pair, and a security group as described above. ChartDB itself needs very little, because the editor runs in your users' browsers.
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=chartdb}]'Connect to your instance
Connect to ChartDB 1.20.1 on Ubuntu 24.04 over SSH as the ubuntu user.
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services
First boot generates the certificate and the password, and then nginx starts:
systemctl is-active nginx chartdb-firstboot
sudo test -f /var/lib/sac/data/chartdb-firstboot.done && echo FIRSTBOOT_DONEBoth units are active and the first boot marker is present:
active active FIRSTBOOT_DONEOnly SSH and nginx listen on the network:
sudo ss -lntp | awk 'NR>1 {print $4, $6}' | grep -v '127.0.0.5' | sort0.0.0.0:22 users:(("sshd",...)) 0.0.0.0:443 users:(("nginx",...)) 0.0.0.0:80 users:(("nginx",...)) [::]:22 users:(("sshd",...)) [::]:443 users:(("nginx",...)) [::]:80 users:(("nginx",...))Get your URL and password
sudo cat /var/lib/sac/data/chartdb-credentials.txtThe file is readable by root only and holds the URL, the user name and this instance's password:
CHARTDB_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/ CHARTDB_USERNAME=admin CHARTDB_PASSWORD=<CHARTDB_PASSWORD>The URL uses the instance's public DNS name from EC2 instance metadata. The certificate also names the public and private IP addresses, so https://<public-ip>/ works too. To serve ChartDB under your own DNS name, see Step 10.
Sign in from your browser
Open the CHARTDB_URL in your browser. The certificate is self-signed, so your browser asks you to confirm it the first time. Alternatively, install your own certificate (Step 10). Sign in as admin with the password from Step 4. The browser remembers the login for the session.
ChartDB opens with What is your Database?. Pick the engine your schema comes from. MySQL, PostgreSQL, MariaDB, SQLite, SQL Server and Oracle are on the Transactional tab, analytical engines such as ClickHouse are on the Analytical tab, and more are under More Databases.
Import a schema
Next, ChartDB shows Import your Database. On the Smart Query tab, it gives you one query to run against your live database, with psql, mysql, sqlcmd or any client. Paste the JSON it returns, and ChartDB reads every table, column, index and foreign key.
Nothing connects to your database from the server. You run the query yourself and paste the result into your browser.
You can also switch to SQL Script and paste CREATE TABLE statements directly, for example the output of pg_dump --schema-only. In this example, four tables of a small shop schema are pasted, and ChartDB reports Found 4 tables to import.
Explore and edit the diagram
Choose Import, and ChartDB draws the ER diagram. Each table lists its columns and types, primary keys are marked, and foreign keys are drawn as relationships.
Drag tables to arrange them, and add or edit tables and columns on the canvas. Use the side panel to browse Tables, relationships (Refs) and Custom Types.
Edit as DBML and export
Open DBML in the side panel to see the diagram as DBML (Database Markup Language). Edits in either view update the other.
Actions > Export SQL generates the DDL for the same database type. Actions > Export as saves an image of the canvas.
Your diagrams are stored in your browser (IndexedDB), not on the server. Use Backup > Export Diagram to save a diagram as a file. Use Backup > Restore Diagram to load it in another browser or share it with a colleague.
Exporting SQL for a different database type uses an OpenAI model and needs an API key, which this image does not ship (see Step 11).
Check the security posture from the command line
Without a login, ChartDB is refused. Port 80 redirects to HTTPS, the health check stays open for load balancers, and a request for a host name the instance does not serve is dropped without an answer:
H=$(sudo grep '^CHARTDB_URL=' /var/lib/sac/data/chartdb-credentials.txt | sed -E 's#^CHARTDB_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 'no login -> HTTP %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/"
curl -sk -o /dev/null -w 'config.js, no login -> HTTP %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/config.js"
curl -sk -o /dev/null -w 'health -> HTTP %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/health"
curl -sk -o /dev/null -w 'unknown host -> %{http_code}\n' --resolve "evil.example:443:127.0.0.1" "https://evil.example/" || true
curl -sk --resolve "$H:443:127.0.0.1" "https://$H/" | grep -o '401 Authorization Required' | sort -uhttp:// -> 301 https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/ no login -> HTTP 401 config.js, no login -> HTTP 401 health -> HTTP 200 unknown host -> 000 401 Authorization Required000 means that nginx closed the connection without answering, which is how it treats any host name it does not serve.
With the password, ChartDB and its runtime settings are served. The password is passed to curl on standard input, so it never appears in the process list or your shell history:
sudo bash -c ' F=/var/lib/sac/data/chartdb-credentials.txt P=$(grep "^CHARTDB_PASSWORD=" $F | cut -d= -f2-) H=$(grep "^CHARTDB_URL=" $F | sed -E "s#^CHARTDB_URL=https://([^/]+)/.*#\1#") auth() { printf "user = \"admin:%s\"\n" "$P"; } auth | curl -K - -sk --resolve "$H:443:127.0.0.1" -o /dev/null -w "with login -> HTTP %{http_code}\n" "https://$H/" auth | curl -K - -sk --resolve "$H:443:127.0.0.1" "https://$H/" | grep -o "<title>[^<]*</title>" auth | curl -K - -sk --resolve "$H:443:127.0.0.1" "https://$H/config.js" | grep -E "DISABLE_ANALYTICS|HIDE_CHARTDB_CLOUD" 'with login -> HTTP 200 <title>ChartDB - Create & Visualize Database Schema Diagrams</title> HIDE_CHARTDB_CLOUD: "true", DISABLE_ANALYTICS: "true"nginx keeps only a bcrypt hash of the password. The plain text is in the root-only credentials file:
sudo sed -E 's/\$2y\$12\$.*/$2y$12$<bcrypt-hash>/' /etc/nginx/.chartdb-htpasswd
sudo stat -c '%a %U:%G %n' /etc/nginx/.chartdb-htpasswd /var/lib/sac/data/chartdb-credentials.txtadmin:$2y$12$<bcrypt-hash> 640 root:www-data /etc/nginx/.chartdb-htpasswd 600 root:root /var/lib/sac/data/chartdb-credentials.txtThe certificate was generated on this instance and names its own addresses:
H=$(sudo grep '^CHARTDB_URL=' /var/lib/sac/data/chartdb-credentials.txt | sed -E 's#^CHARTDB_URL=https://([^/]+)/.*#\1#')
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -subject -ext subjectAltNamesubject=CN = ec2-<public-ip-dashed>.<region>.compute.amazonaws.com, O = sac 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:localhostnginx cannot reach the instance metadata service, and it does not start until first boot has finished:
systemctl show nginx -p IPAddressDeny | grep 169.254.169.254
systemctl cat nginx | grep -E '^ExecStartPre=/usr/bin/test'IPAddressDeny=168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128 ExecStartPre=/usr/bin/test -f /var/lib/sac/data/chartdb-firstboot.done ExecStartPre=/usr/bin/test -s /etc/nginx/.chartdb-htpasswdnginx also refuses a request whose Origin is another website (HTTP 403), because browsers resend Basic Auth credentials on cross-site requests:
H=$(sudo grep '^CHARTDB_URL=' /var/lib/sac/data/chartdb-credentials.txt | sed -E 's#^CHARTDB_URL=https://([^/]+)/.*#\1#')
curl -sk --resolve "$H:443:127.0.0.1" -H 'Origin: https://evil.example' -d x=1 "https://$H/" | grep -o '403 Forbidden'403 ForbiddenYour own DNS name and certificate
Point a DNS record at the instance, then set the name that ChartDB is served as. This creates a new self-signed certificate for the name, updates nginx and the URL in the credentials file, and keeps the name across reboots:
sudo chartdb-set-hostname <your-domain>To use a certificate from your own certificate authority instead, copy it over the generated pair and reload nginx. Running chartdb-set-hostname again replaces it with a self-signed one:
sudo install -m 0644 <your-domain>.crt /etc/ssl/chartdb/chartdb.crt
sudo install -m 0600 <your-domain>.key /etc/ssl/chartdb/chartdb.key
sudo nginx -t && sudo systemctl reload nginxChange the password, add users, or enable the AI export
The login is an nginx Basic Auth file. To set a new password for admin, hand it to htpasswd on standard input, then reload nginx. printf is a shell builtin, so the password never appears in the process list. Start the line with a space so that most shells keep it out of your history.
printf '%s\n' '<new-password>' | sudo htpasswd -i -B -C 12 /etc/nginx/.chartdb-htpasswd admin
sudo systemctl reload nginxRunning sudo htpasswd -B -C 12 /etc/nginx/.chartdb-htpasswd <user> without -i prompts for the password instead. Use it with another user name to give a colleague their own login. Use sudo htpasswd -D /etc/nginx/.chartdb-htpasswd <user> to remove one.
Then update or delete CHARTDB_PASSWORD in /var/lib/sac/data/chartdb-credentials.txt, so that it does not hold an old password.
ChartDB's SQL export to a different database type calls OpenAI, or an OpenAI-compatible endpoint, from the user's browser. To enable it, add OPENAI_API_KEY (and optionally OPENAI_API_ENDPOINT and LLM_MODEL_NAME) to /var/www/chartdb/config.js.
Every browser that signs in can read that file. Only do this with a key created for this purpose and with a spending limit.
Server components
These are the server components and their paths:
- ChartDB static build: /var/www/chartdb
- Runtime settings (analytics off, no API key): /var/www/chartdb/config.js
- Source, dependency pins and licence: /usr/share/chartdb/
- nginx site: /etc/nginx/sites-available/sac-chartdb
- Basic Auth file: /etc/nginx/.chartdb-htpasswd (bcrypt)
- Certificate and key: /etc/ssl/chartdb/
- First boot script: /usr/local/sbin/chartdb-firstboot.sh
- Host name helper: /usr/local/sbin/chartdb-set-hostname
- Credentials: /var/lib/sac/data/chartdb-credentials.txt (mode 0600)
ls -l /usr/share/chartdb/ | awk 'NR>1{print $1,$5,$9}' command -v node || echo "no node runtime" nginx -v 2>&1-rw-r--r-- 984 BUILD-INFO.txt -rw-r--r-- 34523 LICENSE -rw-r--r-- 948 README.source.txt -rw-r--r-- 52331362 chartdb-v1.20.1-source.tar.gz -rw-r--r-- 518442 sac-package-lock.json -rw-r--r-- 4718 sac-package.json no node runtime nginx version: nginx/1.24.0 (Ubuntu)BUILD-INFO.txt records the exact versions and the one remaining npm advisory: zod 3.25.76 (GHSA-mrhx-c7xc-m3w5, a memory exhaustion issue when validating very large input, fixed only in the next major version of zod).
zod runs only in a signed-in user's own browser tab, on schema data that the user pastes, so it cannot be reached from the network. Nothing on the server runs JavaScript. SecureAnyCloud rechecks the advisory at every ChartDB release.
Security recommendations
- Allow ports 22, 80 and 443 in the security group from your own networks only.
- Keep the per-instance password secret, and rotate it if it may have been shared (Step 11).
- Use your own DNS name and a certificate your clients trust (Step 10).
- Keep the operating system patched. Unattended security upgrades are on, and
sudo apt-get update && sudo apt-get upgradeapplies everything else.
Support and licensing
ChartDB is open source under the GNU Affero General Public License v3.0. There is no per-user or per-CPU licence fee.
The source of the version on the image is in /usr/share/chartdb/. It consists of the unmodified release archive plus the dependency version file that this image builds with. The AMI price covers SecureAnyCloud's hardening, first-boot setup and support.
- Email: sales@secureanycloud.com
- Website: https://secureanycloud.com
- Support: 24/7, with a 24-hour response SLA
Deploy on AWS
Launch ChartDB 1.20.1 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