Databases AWS

Dgraph Graph Database on AWS User Guide

| Product: Dgraph

Dgraph Graph Database on AWS User Guide

This guide covers the cloudimg Dgraph AMI on AWS Marketplace. Dgraph is a distributed, open source graph database written in Go. It stores data as a graph of nodes and typed relationships and answers deeply joined traversals plus full-text, geo and regular-expression queries through its own DQL query language and a native GraphQL API, over HTTP and gRPC.

The cloudimg image runs Dgraph as two coordinated systemd services from a single binary — a cluster coordinator (dgraph-zero) and a data node (dgraph-alpha) — behind an nginx TLS reverse proxy on port 443. Open source Dgraph ships with no built-in access control, so this image never exposes an open database: every instance generates a unique HTTP password and a unique admin token on first boot, and the database ports bind to loopback only.

Connecting to your instance

Connect over SSH using the key pair you selected at launch. The login user depends on the OS variant you subscribed to:

OS variant SSH login user
Ubuntu 24.04 ubuntu
ssh -i /path/to/your-key.pem ubuntu@<public-ip>

Retrieve your per-instance credentials

On first boot the instance generates its own nginx HTTP basic-auth username and password and its own Dgraph admin security token. They are written to a root-only file. Read them with:

sudo cat /root/dgraph-info.txt

The file looks like this (values are unique to your instance):

DGRAPH_HTTP_USER=dgraph_ab12cd
DGRAPH_HTTP_PASSWORD=<64-hex-characters>
DGRAPH_SECURITY_TOKEN=<64-hex-characters>
DGRAPH_URL=https://203.0.113.24/
DGRAPH_HEALTH_URL=https://203.0.113.24/health
  • DGRAPH_HTTP_USER / DGRAPH_HTTP_PASSWORD — nginx HTTP basic-auth credentials. Every request to the HTTP API needs them.
  • DGRAPH_SECURITY_TOKEN — required, in addition to basic-auth, for any administrative operation (altering the schema, /admin, export, backup) via the X-Dgraph-AuthToken header.

The TLS certificate is self-signed per instance, so the examples below use curl -k. For production, front the instance with your own domain and a CA-signed certificate.

Check the service health

Confirm the two Dgraph services and nginx are running and that the endpoints respond. The unauthenticated /healthz probe is a static nginx response for load balancers; the Dgraph /health endpoint is behind basic-auth.

systemctl is-active dgraph-zero dgraph-alpha nginx
echo "--- static LB probe (no auth) ---"
curl -ks -o /dev/null -w '/healthz -> %{http_code}\n' https://127.0.0.1/healthz
echo "--- Dgraph /health requires basic-auth ---"
curl -ks -o /dev/null -w '/health without auth -> %{http_code} (expect 401)\n' https://127.0.0.1/health
U=$(sudo grep '^DGRAPH_HTTP_USER=' /root/dgraph-info.txt | cut -d= -f2-)
P=$(sudo grep '^DGRAPH_HTTP_PASSWORD=' /root/dgraph-info.txt | cut -d= -f2-)
curl -ks -o /dev/null -w '/health with auth -> %{http_code} (expect 200)\n' -u "$U:$P" https://127.0.0.1/health

Expected output resembles:

active
active
active
--- static LB probe (no auth) ---
/healthz -> 200
--- Dgraph /health requires basic-auth ---
/health without auth -> 401 (expect 401)
/health with auth -> 200 (expect 200)

Dgraph services active, version and loopback-bound network

Run your first query

This example sets a schema, inserts a node and queries it back — a complete graph round-trip. Setting the schema is an administrative operation, so it carries the X-Dgraph-AuthToken header in addition to basic-auth; mutations and queries need basic-auth only.

U=$(sudo grep '^DGRAPH_HTTP_USER=' /root/dgraph-info.txt | cut -d= -f2-)
P=$(sudo grep '^DGRAPH_HTTP_PASSWORD=' /root/dgraph-info.txt | cut -d= -f2-)
T=$(sudo grep '^DGRAPH_SECURITY_TOKEN=' /root/dgraph-info.txt | cut -d= -f2-)
BASE=https://127.0.0.1

echo "1) set the schema (admin op: basic-auth + token)"
curl -ks -u "$U:$P" -H "X-Dgraph-AuthToken: $T" -X POST $BASE/alter -d 'name: string @index(exact) .'
echo

echo "2) insert a node (RDF mutation)"
curl -ks -u "$U:$P" -H 'Content-Type: application/rdf' -X POST "$BASE/mutate?commitNow=true" \
  -d '{ set { _:city <name> "Reykjavik" . } }'
echo

echo "3) query it back (DQL)"
curl -ks -u "$U:$P" -H 'Content-Type: application/dql' -X POST $BASE/query \
  -d '{ q(func: eq(name, "Reykjavik")) { name } }'
echo

The query returns the node you just inserted:

1) set the schema (admin op: basic-auth + token)
{"data":{"code":"Success","message":"Done"}}
2) insert a node (RDF mutation)
{"data":{"code":"Success","message":"Done","uids":{"city":"0x4e21"}},...}
3) query it back (DQL)
{"data":{"q":[{"name":"Reykjavik"}]},...}

Dgraph graph round-trip: set schema, insert a node, query it back

To reach the API from your own machine, use the instance public IP and the same credentials (the certificate is self-signed, so keep -k or trust it):

curl -k -u USER:PASS -H 'Content-Type: application/dql' -X POST https://<public-ip>/query \
  -d '{ q(func: has(name)) { name } }'

Dgraph also serves a native GraphQL API at /graphql (with the admin surface at /admin), reached through the same authenticated proxy.

Security model

The image is hardened so the database is never open:

  • nginx HTTP basic-auth gates every request to the HTTP API. Without the per-instance username and password the API returns 401.
  • A per-instance admin token is required for every administrative operation. A request that authenticates with basic-auth but omits the X-Dgraph-AuthToken header is refused for admin ops.
  • Loopback binding. dgraph-zero and dgraph-alpha start with --bindall=false, so ports 5080, 6080, 7080, 8080 and 9080 listen on 127.0.0.1 only. nginx on port 443 is the sole network-facing surface, and /debug/ is blocked.

You can confirm both layers are enforced:

echo "admin op with NO basic-auth is rejected:"
curl -ks -o /dev/null -w '  POST /alter (no auth) -> %{http_code} (expect 401)\n' -X POST https://127.0.0.1/alter -d 'x: string .'

U=$(sudo grep '^DGRAPH_HTTP_USER=' /root/dgraph-info.txt | cut -d= -f2-)
P=$(sudo grep '^DGRAPH_HTTP_PASSWORD=' /root/dgraph-info.txt | cut -d= -f2-)
echo "admin op authenticated but WITHOUT the token is rejected:"
curl -ks -u "$U:$P" -X POST https://127.0.0.1/alter -d 'y: string .' | grep -o 'No Auth Token found' || echo "  (token missing -> refused)"

Dgraph authentication enforced: 401 without credentials, admin ops require the token

Only ports 22, 80 and 443 are opened by the default Security Group. Restrict port 443 ingress to trusted networks, and enable EBS encryption on the data volume at launch for encryption at rest.

Dedicated data volume

All Dgraph state — the zero raft write-ahead log and the alpha postings, WAL and temp directories — lives on a dedicated EBS volume mounted at /var/lib/dgraph, separate from the OS root volume so you can resize or snapshot it independently.

findmnt -no SOURCE,TARGET,FSTYPE,SIZE /var/lib/dgraph

The mount is pinned by filesystem UUID in /etc/fstab, so it survives reboots and re-launch. To grow storage, expand the EBS volume in the AWS console and then extend the filesystem with resize2fs.

Rotating the credentials

To regenerate a fresh per-instance HTTP password, admin token and TLS certificate, remove the first-boot sentinel and re-run the first-boot service. This mutates the running instance, so run it only when you intend to rotate:

sudo rm -f /var/lib/cloudimg/dgraph-firstboot.done
sudo /usr/local/sbin/dgraph-firstboot.sh
sudo systemctl restart dgraph-alpha nginx

Production TLS with your own domain

The per-instance certificate is self-signed. For production, point a DNS record at the instance and install a CA-signed certificate — for example with certbot and your-domain.example — then replace the certificate and key referenced by the nginx site at /etc/nginx/sites-available/cloudimg-dgraph and reload nginx.

Support

24/7 technical support is included with this product from cloudimg. Contact support@cloudimg.co.uk or use live chat for help with Dgraph deployment, schema and index design, TLS and reverse-proxy configuration, credential rotation, and performance tuning.