Dgraph Graph Database on AWS User Guide
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 theX-Dgraph-AuthTokenheader.
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)

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"}]},...}

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-AuthTokenheader is refused for admin ops. - Loopback binding.
dgraph-zeroanddgraph-alphastart with--bindall=false, so ports 5080, 6080, 7080, 8080 and 9080 listen on127.0.0.1only. 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)"

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.