D1
Databases AWS

DoltgreSQL 1.4.0 on AWS User Guide

| Product: DoltgreSQL 1.4.0 on Ubuntu 24.04 on AWS

Overview

This guide covers launching and using DoltgreSQL 1.4.0 on Ubuntu 24.04 from cloudimg on Amazon EC2. It is one version of cloudimg's distributed and embedded SQL databases listing on AWS Marketplace; you pick it as the software version when you subscribe and launch. The other databases in the listing are described on the listing's guide hub.

DoltgreSQL is an open source database that does two things at once. It speaks the PostgreSQL wire protocol, so the ordinary psql client and standard PostgreSQL drivers connect to it unchanged. And it stores its tables in a Dolt repository, so the data itself is version controlled: you commit a set of rows, branch the database, change the branch without touching main, diff the two branches row by row, merge one into the other, and read any table as it stood at an earlier commit. All of it is driven from SQL.

What the cloudimg image adds:

  • No default login, a password unique to your instance. DoltgreSQL's built-in bootstrap superuser is postgres with the password password, and that password can only be replaced at the moment the database is first created. So the image ships no database at all: first boot creates this instance's own data directory on the data volume, with a 32 character superuser password generated on the instance and handed to the server on standard input (never on a command line, in a log or in the journal). The upstream default never exists on your instance, and first boot proves it is refused. The password is written to the root only file /root/doltgres-credentials.txt. DoltgreSQL refuses to start until first boot has finished.
  • TLS on the database port, required from any other address. First boot generates a certificate for your instance, and DoltgreSQL serves TLS on port 5432. The image sets require_secure_transport, and enforces it: any client connecting from an address other than the instance itself must use TLS, and a plaintext connection is refused before it can send a password. Upstream DoltgreSQL 1.4.0 reads this option but does not apply it, so the enforcement is a cloudimg modification of DoltgreSQL (two source files, under section 4(b) of the Apache License 2.0); the exact change ships on the instance as /usr/share/doc/doltgres/cloudimg-require-secure-transport.patch (Step 10). Out of the box DoltgreSQL listens on 127.0.0.1:5432 only, so nothing but SSH is reachable from the network until you choose to open it (Step 9).
  • A DoltgreSQL built for this image. The DoltgreSQL 1.4.0 release binary was built with Go 1.26.8 and modules that now carry fixed security advisories, so cloudimg compiles DoltgreSQL 1.4.0 from its release source with Go 1.26.10 and the fixed module releases. govulncheck reports no vulnerability reachable from DoltgreSQL's code. The build's provenance is on the instance (/usr/share/doc/doltgres/BUILD-PROVENANCE.txt).
  • Hardened service. DoltgreSQL runs as an unprivileged doltgres user with no capabilities, a read-only view of the system and no access to /root; DoltgreSQL and its first boot service are blocked from the instance metadata service (DoltgreSQL can fetch a URL you name from SQL, for example dolt_clone), and the AMI requires IMDSv2. DoltgreSQL's usage telemetry is off.
  • Your data on its own disk. The data directory (/var/lib/doltgres) is on a separate 20 GiB EBS volume you can grow or snapshot on its own.
  • Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.

What is on the image: DoltgreSQL 1.4.0 (/usr/local/bin/doltgres, running as doltgres.service), the PostgreSQL 16 client psql from Ubuntu, a helper doltgres-psql that signs psql in as the superuser, a demo database versioned with a commit history and a second branch to explore, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. There is no PostgreSQL server on the image.

Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large

What this is not

DoltgreSQL targets the PostgreSQL 15 dialect and is a young project. It is compatible for a large and useful subset of SQL, but it is not a drop in replacement for PostgreSQL. Check your workload against Compatibility with PostgreSQL before you migrate anything.

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) from your admin network. DoltgreSQL listens on the loopback address only, so no database port needs to be open; you reach it through an SSH tunnel (Step 8), or open it with TLS to your application subnet later (Step 9).

Step 1: Launch the instance

In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick DoltgreSQL 1.4.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 root volume and a 20 GiB data volume (/dev/sdf) for /var/lib/doltgres. Make the data volume as large as your data needs at launch.

With the AWS CLI (replace the values in angle brackets; this example grows the data volume to 100 GiB):

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> \
  --block-device-mappings 'DeviceName=/dev/sdf,Ebs={VolumeSize=100,VolumeType=gp3}' \
  --metadata-options HttpTokens=required,HttpEndpoint=enabled \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=doltgres}]'

If you make the data volume larger at launch, grow the file system once after first boot with sudo resize2fs "$(findmnt -no SOURCE /var/lib/doltgres)". First boot takes well under a minute once the instance is running.

Step 2: Connect to your instance

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

Step 3: Check the services

Both the first boot service and DoltgreSQL itself should be active:

systemctl is-active doltgres-firstboot.service doltgres.service
active
active

DoltgreSQL listens on the loopback address only; from the network, only SSH is reachable:

sudo ss -Htln
LISTEN 0      128        127.0.0.1:5432 0.0.0.0:*
LISTEN 0      4096   127.0.0.53%lo:53   0.0.0.0:*
LISTEN 0      4096      127.0.0.54:53   0.0.0.0:*
LISTEN 0      4096         0.0.0.0:22   0.0.0.0:*
LISTEN 0      4096            [::]:22      [::]:*

(The two port 53 lines are Ubuntu's local DNS resolver, also loopback only.)

Step 4: Get your superuser password

sudo cat /root/doltgres-credentials.txt
# DoltgreSQL 1.4.0 on Ubuntu 24.04 - generated on first boot by doltgres-firstboot.service
# This password is unique to this instance; none was baked into the image. Keep this file secret.

DOLTGRES_USER=postgres
DOLTGRES_PASSWORD=<DOLTGRES_PASSWORD>
DOLTGRES_HOST=127.0.0.1
DOLTGRES_PORT=5432
DOLTGRES_DATABASE=versioned
DOLTGRES_TLS_CA=/etc/doltgres/tls/doltgres.crt
DOLTGRES_SERVER_VERSION=15.17 (Homebrew)
DEMO_BASE_COMMIT=p5leaaaq84asau2ccnith4bip12s0f83
DEMO_FEATURE_COMMIT=v0sr5jjqf784jqifnc14h1j0h90q51gu
...

The password is unique to this instance: another instance launched from the same AMI has a different one. (15.17 (Homebrew) is the literal server_version string DoltgreSQL reports.)

Step 5: Connect with psql

sudo doltgres-psql runs the stock psql signed in as postgres, over TLS with your instance's certificate verified; the password goes to psql through a temporary root only file, never a command line. Any psql option works:

sudo doltgres-psql -d postgres -c 'SELECT version();'
     version
-----------------
 PostgreSQL 15.5
(1 row)

That is an ordinary PostgreSQL client talking to DoltgreSQL. From your own tools, connect to 127.0.0.1:5432 as postgres with the password from Step 4 (on the instance, or through the tunnel in Step 8), for example postgresql://postgres:<password>@127.0.0.1:5432/versioned.

Step 6: Explore the demo database

The versioned database ships with a small employees table, already committed:

sudo doltgres-psql -d versioned -c 'SELECT * FROM employees ORDER BY id;'
 id | last_name | first_name
----+-----------+------------
  1 | Sehn      | Tim
  2 | Hendriks  | Brian
(2 rows)

The commit history

Version control state is exposed as ordinary tables in the dolt schema:

sudo doltgres-psql -d versioned -c 'SELECT commit_hash, committer, message FROM dolt.log ORDER BY date DESC;'
           commit_hash            | committer |              message
----------------------------------+-----------+------------------------------------
 p5leaaaq84asau2ccnith4bip12s0f83 | postgres  | Create employees and seed two rows
 j00l5jjt08eoc5qhi78napsnvp9ucvis | postgres  | CREATE DATABASE
 l1suev5lfldg1shs0rjjhmjb7csf93em | doltgres  | Initialize data repository
(3 rows)

Your commit hashes differ from these: your instance created its own history on first boot.

Branches

The demo has a second branch, feature, which carries a change main does not:

sudo doltgres-psql -d versioned -c 'SELECT name, latest_commit_message FROM dolt.branches ORDER BY name;'
  name   |       latest_commit_message
---------+------------------------------------
 feature | Add Aaron on the feature branch
 main    | Create employees and seed two rows
(2 rows)

To work on a branch, put it in the database name as <database>/<branch>. This is how DoltgreSQL selects a branch over the PostgreSQL wire protocol:

sudo doltgres-psql -d versioned/feature -c 'SELECT * FROM employees ORDER BY id;'
 id | last_name | first_name
----+-----------+------------
  1 | Sehn      | Tim
  2 | Hendriks  | Brian
  3 | Son       | Aaron
(3 rows)

Three rows on feature, two on main. Create your own branch with SELECT dolt_branch('my-branch');. The version control operations are functions, called with SELECT.

Diff two branches

dolt_diff returns a row by row difference between any two branches or commits:

sudo doltgres-psql -d versioned -c "SELECT to_id, to_last_name, to_first_name, from_id, diff_type FROM dolt_diff('main','feature','employees');"
 to_id | to_last_name | to_first_name | from_id | diff_type
-------+--------------+---------------+---------+-----------
     3 | Son          | Aaron         |         | added
(1 row)

The to_ columns are the state on the second branch and the from_ columns the state on the first, so an edited row shows both and a deleted row shows only from_ values.

Merge a branch

Merge feature into main with dolt_merge:

sudo doltgres-psql -d versioned -c "SELECT dolt_merge('feature');"
                        dolt_merge
-----------------------------------------------------------
 (v0sr5jjqf784jqifnc14h1j0h90q51gu,1,0,"merge successful")
(1 row)

The result is the commit main now points at, a fast forward flag, a conflict count and a status message. Here main had not moved since feature branched off, so the merge is a fast forward and the commit is the feature commit (DEMO_FEATURE_COMMIT in your credentials file). main now carries the merged row:

sudo doltgres-psql -d versioned -c 'SELECT * FROM employees ORDER BY id;'
 id | last_name | first_name
----+-----------+------------
  1 | Sehn      | Tim
  2 | Hendriks  | Brian
  3 | Son       | Aaron
(3 rows)

Time travel to an earlier commit

AS OF reads a table as it stood at a commit. The seed commit is recorded in your credentials file as DEMO_BASE_COMMIT:

BASE=$(sudo sed -n 's/^DEMO_BASE_COMMIT=//p' /root/doltgres-credentials.txt)
sudo doltgres-psql -d versioned -c "SELECT * FROM employees AS OF '${BASE}' ORDER BY id;"
 id | last_name | first_name
----+-----------+------------
  1 | Sehn      | Tim
  2 | Hendriks  | Brian
(2 rows)

Two rows at the earlier commit, three at HEAD. AS OF sees committed state only.

Step 7: Commit your own changes

Changes are staged and committed much as in Git. dolt.status shows what has changed but is not yet committed:

SELECT * FROM dolt.status;
SELECT dolt_add('-A');
SELECT dolt_commit('-m', 'Describe what changed');

dolt_commit returns the new commit hash. Until you commit, your changes live in the branch's working set: visible to queries on that branch, invisible to AS OF, and not yet part of the history.

Step 8: Connect from your own computer through an SSH tunnel

The SSH tunnel reuses the access you already have and needs no extra port. Local port 15432 avoids a clash with a PostgreSQL you may run locally:

ssh -i <your-key.pem> -N -L 15432:127.0.0.1:5432 ubuntu@<public-ip>

Then, in a second terminal on your computer, connect with any PostgreSQL client, for example psql "postgresql://postgres@127.0.0.1:15432/versioned" (it asks for the password from Step 4).

Step 9: Allow TLS connections from your VPC

To let applications in your VPC connect directly, bind DoltgreSQL to the instance's network interface and open port 5432 to their subnet only. require_secure_transport: true stays on, so every one of those clients must use TLS: a plaintext connection from another address is refused with FATAL: SSL is required before any password is exchanged (clients on the instance itself may still connect without TLS).

sudo sed -i 's/^  host: 127.0.0.1$/  host: 0.0.0.0/' /etc/doltgres/config.yaml
sudo systemctl restart doltgres

Then add an inbound rule for TCP 5432 from your application subnet to the instance's security group. Give your clients the instance's certificate (/etc/doltgres/tls/doltgres.crt) as the CA file and connect with full verification, for example postgresql://postgres:<password>@<private-ip>:5432/versioned?sslmode=verify-full&sslrootcert=doltgres.crt. The certificate covers localhost, 127.0.0.1 and the instance's private and public names and addresses; add more names with sudo doltgres-tls-cert --renew <name> ..., which issues a new certificate and restarts DoltgreSQL.

Step 10: Security checks

The certificate DoltgreSQL serves on 5432 is your instance's own:

echo | openssl s_client -starttls postgres -connect 127.0.0.1:5432 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
subject=CN = ip-172-31-87-125.ec2.internal, O = cloudimg DoltgreSQL
X509v3 Subject Alternative Name:
    DNS:ip-172-31-87-125.ec2.internal, IP Address:172.31.87.125, DNS:ec2-3-87-71-112.compute-1.amazonaws.com, IP Address:3.87.71.112, DNS:localhost, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1

TLS is required from any other address, and DoltgreSQL listens on loopback:

grep -E '^  (host|require_secure_transport|tls_cert):' /etc/doltgres/config.yaml
  host: 127.0.0.1
  tls_cert: /etc/doltgres/tls/doltgres.crt
  require_secure_transport: true

DoltgreSQL and its first boot service cannot reach the instance metadata service:

systemctl show -p IPAddressDeny doltgres.service doltgres-firstboot.service
IPAddressDeny=fd00:ec2::254/128 168.63.129.16/32 169.254.169.254/32

IPAddressDeny=fd00:ec2::254/128 168.63.129.16/32 169.254.169.254/32

The image's own round trip: your password works over verified TLS and the demo history reads back (it reads the recorded demo commits, so it still passes after the merge above), while the upstream default, blank, common and random passwords are all refused:

sudo /usr/local/sbin/doltgres-roundtrip.sh | tail -1
OK-doltgres-scram-tls-roundtrip

How DoltgreSQL was built, and what govulncheck found:

grep -E '^(toolchain|govulncheck|source change)' /usr/share/doc/doltgres/BUILD-PROVENANCE.txt
toolchain         go1.26.10 linux/amd64, official tarball https://go.dev/dl/go1.26.10.linux-amd64.tar.gz
toolchain sha256  ccfe7ae822d2c2f41f4fe7c956199967a4dac22d0ee0d2b2bfdb440aab3b20c5
source change     cloudimg modification (Apache-2.0 section 4(b); diff /usr/share/doc/doltgres/cloudimg-require-secure-transport.patch):
govulncheck       v1.9.0, source: No vulnerabilities found.; binary: Your code is affected by 1 vulnerability from 1 module. (GO-2026-5932: no fixed release exists; not called per source mode)

The require_secure_transport enforcement is cloudimg's change to DoltgreSQL. The complete diff is on the instance, with the modification notice:

sha256sum /usr/share/doc/doltgres/cloudimg-require-secure-transport.patch
grep -E '^(---|\+\+\+) ' /usr/share/doc/doltgres/cloudimg-require-secure-transport.patch
grep -A1 '^Modified by cloudimg' /usr/share/doc/doltgres/BUILD-PROVENANCE.txt
fca919acfb1b2ec3f5b34787cf42399baf693127bcade404993f01d8a34e52b8  /usr/share/doc/doltgres/cloudimg-require-secure-transport.patch
--- a/server/server.go
+++ b/server/server.go
--- a/server/connection_startup.go
+++ b/server/connection_startup.go
Modified by cloudimg (Apache License 2.0, section 4(b)): on 2026-10-24 cloudimg changed server/server.go and
server/connection_startup.go of DoltgreSQL v1.4.0, so that listener.require_secure_transport is ENFORCED on the

GO-2026-5932 is the golang.org/x/crypto/openpgp package, which is unmaintained and has no fixed release anywhere; it is linked through a dependency, and govulncheck's source analysis shows DoltgreSQL never calls it.

Step 11: Change the superuser password

Choose a new password, set it, then update the credentials file so doltgres-psql keeps working:

sudo doltgres-psql -d postgres
postgres=# ALTER USER postgres WITH PASSWORD '<new-password>';
postgres=# \q
sudo sed -i 's/^DOLTGRES_PASSWORD=.*/DOLTGRES_PASSWORD=<new-password>/' /root/doltgres-credentials.txt

Step 12: Backup, updates and maintenance

  • Back up by snapshotting the data volume, or by copying /var/lib/doltgres with the service stopped (sudo systemctl stop doltgres). Dolt can also push a database to a remote of your own (dolt_remote and dolt_push).
  • Logs: sudo journalctl -u doltgres.service -n 50.
  • Configuration lives in /etc/doltgres/config.yaml; restart the service after editing it.
  • Updates: Ubuntu security updates install automatically. DoltgreSQL is pinned to the version this image was built with; upgrade it deliberately, after taking a copy of the data directory.

Compatibility with PostgreSQL

DoltgreSQL targets the PostgreSQL 15 dialect. On this image, for example, jsonb, the uuid-ossp and vector (pgvector) extensions, PL/pgSQL functions, row level triggers, DO blocks and COPY ... TO STDOUT all work. Some PostgreSQL features are not available in DoltgreSQL 1.4.0; each of these was refused on this image:

  • network types such as inet, geometric types such as point, and full text search (to_tsvector)
  • MERGE, LISTEN / NOTIFY, materialized views, CREATE POLICY (no row level security) and locking clauses such as FOR UPDATE

DoltgreSQL is under active development; DoltHub's documentation at docs.doltgres.com lists what each release supports.

Support and licensing

DoltgreSQL is open source software under the Apache License 2.0 (/usr/share/doc/doltgres/LICENSE). The DoltgreSQL on this image is modified by cloudimg: server/server.go and server/connection_startup.go were changed so that require_secure_transport is enforced on the wire; the notice is in /usr/share/doc/doltgres/BUILD-PROVENANCE.txt and the change is /usr/share/doc/doltgres/cloudimg-require-secure-transport.patch. cloudimg drops the change once an upstream release enforces the option itself; the CockroachDB PostgreSQL parser it includes was released under the Business Source License 1.1, which converted to the Apache License 2.0 on its change date, 1 October 2023 (/usr/share/doc/doltgres/BSL-cockroachdb-parser.txt). cloudimg provides 24/7 technical support for this image by email and live chat: support@cloudimg.co.uk. DoltgreSQL and Dolt are trademarks of DoltHub, Inc.; cloudimg is not affiliated with or endorsed by DoltHub.