Neo4j 2026 on AWS User Guide
Overview
This guide covers launching and using the Neo4j 2026.10.1 Community AMI from cloudimg on Amazon EC2. It is one version of the cloudimg Hardened Neo4j & Graph and RDF Databases AMIs listing on AWS Marketplace; you pick it as the software version when you subscribe and launch. Every product in the listing is described at /guides/graph-databases-aws/.
Neo4j is a native graph database: data is stored as nodes, relationships and properties, and queried with the Cypher query language. It is used for knowledge graphs, fraud detection, recommendations, network and IT topology, identity and access graphs, and as the graph store behind retrieval-augmented generation (GraphRAG). This image ships Neo4j Community Edition 2026.10.1 with Neo4j Browser (the web query interface), the HTTP API and the Bolt protocol used by every official Neo4j driver, plus cypher-shell. Neo4j Community Edition is licensed under the GNU General Public License version 3.
What cloudimg adds to the upstream build:
- No default login. Neo4j normally starts with the user
neo4jand the passwordneo4j. On this image the database is created on first boot with a 24-character password that is unique to the instance, set before Neo4j ever starts, so the default login never exists. Nothing listens until that password and the certificate exist. - Encrypted from the first boot. A certificate generated on the instance for its own hostname protects Neo4j Browser and the HTTP API (HTTPS on port 7473) and the Bolt protocol (port 7687). Bolt requires TLS: plain
bolt://connections are refused. The unencrypted HTTP port 7474 is turned off, and every other Neo4j listener is off or bound to loopback. - A sandboxed database service. Neo4j runs as an unprivileged service account in a systemd sandbox: it can write only its data, log and run directories, and it cannot read the credentials file, SSH keys,
/rootor/etc/shadow.LOAD CSVfile URLs are confined to the import directory, and the service cannot reach the EC2 instance metadata service, so aLOAD CSV FROM 'http://...'cannot be used to read instance credentials. - No plugins. The Neo4j package also carries the APOC, Graph Data Science and GenAI plugin jars. None is installed on this image, and upgrades do not restore them. Usage reporting to Neo4j is turned off.
- Data on its own disk. The databases and transaction logs live on a separate EBS volume mounted at
/var/lib/neo4j/data, which you can grow independently of the operating system disk. - Fully patched Ubuntu 24.04 at build time, from Neo4j's official signed package repository, with the cloudimg security defaults.
What is on the image: Ubuntu 24.04 LTS, OpenJDK 25 (Java runtime), Neo4j 2026.10.1 Community and cypher-shell from debian.neo4j.com, the configuration in /etc/neo4j/, the data directory /var/lib/neo4j/data on its own volume (empty until first boot creates the databases), and the cloudimg first-boot service.
Connecting to your instance
| Version | SSH user | Neo4j Browser | Bolt (drivers, cypher-shell) |
|---|---|---|---|
| Neo4j 2026 Community on Ubuntu 24.04 | ubuntu |
https://<public-dns>:7473/browser/ |
neo4j+s://<public-dns>:7687 |
Prerequisites
- An AWS account and permission to launch EC2 instances
- An EC2 key pair in the Region you launch in
- A security group that allows TCP 22 from your own address, and TCP 7473 (Neo4j Browser and the HTTP API, HTTPS) and TCP 7687 (Bolt, TLS) from the clients and applications that will use the database. Port 7474 is not used: plain HTTP is turned off.
Recommended instance type: m5.large (2 vCPU, 8 GiB). Neo4j sizes its heap and page cache from the instance memory at start-up; choose a memory-optimised instance (for example r5.large or larger) for big graphs, and see Step 9 for tuning.
Step 1: Launch the instance
Option A: AWS Marketplace console
- Open the cloudimg Hardened Neo4j & Graph and RDF Databases AMIs listing on AWS Marketplace and choose View purchase options, then Subscribe. One subscription covers every version in the listing.
- Choose Launch your software, then in Version choose Neo4j 2026 Community on Ubuntu 24.04 - YYYY-MM-DD and your Region.
- Instance type:
m5.largeis recommended. - Key pair: choose your EC2 key pair.
- Security group: TCP 22 from your own address; TCP 7473 and 7687 from your clients.
- Launch. First boot takes one to two minutes after the instance is reachable, while it generates this instance's certificate and password, creates the databases and starts Neo4j.
Option B: AWS CLI
Run this on your own workstation. Replace the AMI ID with the one shown for your Region on the Marketplace launch page, and the key pair, security group and subnet with your own:
aws ec2 run-instances \
--image-id ami-0123456789abcdef0 \
--instance-type m5.large \
--key-name my-key-pair \
--security-group-ids sg-0123456789abcdef0 \
--subnet-id subnet-0123456789abcdef0 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=neo4j}]'
The AMI already requires IMDSv2, so you do not need --metadata-options. The data volume is part of the AMI and is created with the instance.
Step 2: Connect via SSH
ssh -i my-key-pair.pem ubuntu@<vm-ip>
The login banner shows the Neo4j Browser and Bolt addresses for this instance.
Step 3: Check the service and its listeners
Confirm Neo4j is running and listening only on the HTTPS and Bolt ports:
systemctl is-active neo4j.service
sudo ss -Htln '( sport = :7473 or sport = :7474 or sport = :7687 )'
The service reports active. Neo4j listens on 0.0.0.0:7473 (HTTPS) and 0.0.0.0:7687 (Bolt with TLS); nothing listens on 7474. The data volume is mounted at /var/lib/neo4j/data:
findmnt -no SOURCE,FSTYPE,SIZE /var/lib/neo4j/data
Step 4: Read the per-instance credentials
The neo4j password is unique to this instance and is written to a root-only file at first boot. Print only the field names, never the password itself:
sudo grep -oE '^[A-Z0-9_]+=' /root/neo4j-credentials.txt
This lists NEO4J_HOST (the hostname Neo4j advertises), NEO4J_USER (neo4j), NEO4J_PASSWORD (the per-instance password), NEO4J_BROWSER_URL, NEO4J_HTTPS_URL and NEO4J_BOLT_URI. Read the password with sudo sed -n 's/^NEO4J_PASSWORD=//p' /root/neo4j-credentials.txt when you need it, and keep it safe: it is the database administrator's password.
Step 5: The authentication gate
Neo4j's HTTP API (the Query API at /db/neo4j/query/v2) refuses an anonymous request, a wrong password and the documented default neo4j/neo4j with 401 Unauthorized. Save the instance's certificate so curl can verify the connection:
sudo cat /var/lib/neo4j/certificates/cloudimg/public.crt > /tmp/neo4j.crt
H=$(sudo sed -n 's/^NEO4J_HOST=//p' /root/neo4j-credentials.txt)
Q='{"statement":"RETURN 1 AS one"}'
curl -s --cacert /tmp/neo4j.crt --resolve "$H:7473:127.0.0.1" -o /dev/null -w 'anonymous: HTTP %{http_code}\n' -H 'Content-Type: application/json' -d "$Q" "https://$H:7473/db/neo4j/query/v2"
curl -s --cacert /tmp/neo4j.crt --resolve "$H:7473:127.0.0.1" -u 'neo4j:wrong-password' -o /dev/null -w 'wrong password: HTTP %{http_code}\n' -H 'Content-Type: application/json' -d "$Q" "https://$H:7473/db/neo4j/query/v2"
curl -s --cacert /tmp/neo4j.crt --resolve "$H:7473:127.0.0.1" -u 'neo4j:neo4j' -o /dev/null -w 'neo4j/neo4j: HTTP %{http_code}\n' -H 'Content-Type: application/json' -d "$Q" "https://$H:7473/db/neo4j/query/v2"
Each returns HTTP 401. Neo4j locks an account for a few seconds after three failed logins in a row, so wait a moment before using the real password. With the per-instance password the query runs:
sleep 6
H=$(sudo sed -n 's/^NEO4J_HOST=//p' /root/neo4j-credentials.txt)
printf 'user = "neo4j:%s"\n' "$(sudo sed -n 's/^NEO4J_PASSWORD=//p' /root/neo4j-credentials.txt)" | \
curl -s --cacert /tmp/neo4j.crt --resolve "$H:7473:127.0.0.1" -K - -w '\nHTTP %{http_code}\n' \
-H 'Content-Type: application/json' -d '{"statement":"RETURN 1 AS one"}' "https://$H:7473/db/neo4j/query/v2"
The response is HTTP 202 with "data":{"fields":["one"],"values":[[1]]}. (The password is passed to curl on standard input, so it does not appear in the process list.)
Step 6: Use cypher-shell over TLS
cypher-shell reads the password from the NEO4J_PASSWORD environment variable (set it in each new shell, as below). Because Bolt requires TLS, use the bolt+ssc:// scheme on the instance itself (encrypted; the self-signed certificate is not checked):
export NEO4J_PASSWORD="$(sudo sed -n 's/^NEO4J_PASSWORD=//p' /root/neo4j-credentials.txt)"
echo "CALL dbms.components() YIELD name, versions, edition RETURN name, versions[0] AS version, edition;" | \
cypher-shell -a bolt+ssc://localhost:7687 -u neo4j --format plain
It prints "Neo4j Kernel", "2026.10.1", "community". A plain, unencrypted connection is refused:
export NEO4J_PASSWORD="$(sudo sed -n 's/^NEO4J_PASSWORD=//p' /root/neo4j-credentials.txt)"
echo "RETURN 1;" | cypher-shell -a bolt://localhost:7687 -u neo4j --format plain 2>&1 | head -3 || true
Create a small graph and query it:
export NEO4J_PASSWORD="$(sudo sed -n 's/^NEO4J_PASSWORD=//p' /root/neo4j-credentials.txt)"
cat <<'EOF' | cypher-shell -a bolt+ssc://localhost:7687 -u neo4j --format plain
MERGE (alice:Person {name: 'Alice'})
MERGE (bob:Person {name: 'Bob'})
MERGE (carol:Person {name: 'Carol'})
MERGE (graphs:Topic {name: 'Graph databases'})
MERGE (alice)-[:KNOWS]->(bob)
MERGE (bob)-[:KNOWS]->(carol)
MERGE (alice)-[:INTERESTED_IN]->(graphs)
MERGE (carol)-[:INTERESTED_IN]->(graphs);
MATCH (p:Person)-[:KNOWS*1..2]->(friend:Person)
WHERE p.name = 'Alice'
RETURN friend.name AS reachable_from_alice ORDER BY reachable_from_alice;
EOF
The query returns Bob and Carol: Carol is reached through Bob, a two-hop traversal.
Step 7: Open Neo4j Browser
Open https://<public-dns>:7473/browser/ in your browser. The certificate is self-signed and unique to the instance, so your browser warns once; accept it for this host (for production, see Step 9). The Connect to instance dialog already shows this instance's address (the hostname Neo4j advertises) and port 7687. Choose neo4j+s:// as the protocol, keep neo4j as the database user, and enter the per-instance password:

If the connection fails with a security or certificate message, your browser has not yet accepted the certificate for the Bolt port: open https://<public-dns>:7687 once in a new tab, accept the warning (the page itself then shows an error, which is expected), and connect again.
Once connected, type Cypher in the editor at the top and choose Run. The graph from Step 6 is drawn as nodes and relationships, with a summary of the labels and relationship types:

Queries that return values are shown as a table, here the two-hop traversal from Alice:

:sysinfo lists the databases (neo4j and system), the address they are served on and their status:

Step 8: Connect from an application
Every Neo4j driver (Python, Java, JavaScript, .NET, Go) connects over Bolt on port 7687 with TLS. With the self-signed certificate use the neo4j+ssc:// scheme (encrypted, certificate not checked); to verify the server, copy /var/lib/neo4j/certificates/cloudimg/public.crt from the instance and add it to the client's trust store, or replace the certificate with one from your own certificate authority, and use neo4j+s://. For example, in Python (pip install neo4j):
from neo4j import GraphDatabase
driver = GraphDatabase.driver("neo4j+ssc://<public-dns>:7687", auth=("neo4j", "<NEO4J_PASSWORD>"))
with driver.session() as session:
print(session.run("MATCH (n) RETURN count(n) AS nodes").single()["nodes"])
driver.close()
Create a separate user for each application instead of sharing the neo4j administrator (Community Edition users all have full access, so keep the list short), for example in cypher-shell or Neo4j Browser connected to the system database: CREATE USER app SET PASSWORD 'a-long-random-password' CHANGE NOT REQUIRED;
To change the neo4j password, run ALTER CURRENT USER SET PASSWORD FROM 'current-password' TO 'new-password'; in Neo4j Browser or cypher-shell, then update /root/neo4j-credentials.txt yourself (it is not rewritten).
Step 9: Serve under your own DNS name, and tune memory
Neo4j advertises one hostname to its clients (the Bolt routing table and Neo4j Browser use it). On first boot it is the instance's public DNS name from the EC2 metadata service. After you point a DNS record at the instance, set it and issue a new certificate for that name:
sudo neo4j-set-hostname neo4j.example.com
This regenerates the self-signed certificate (replace it with your own CA-issued certificate for production by putting private.key and public.crt in /var/lib/neo4j/certificates/cloudimg/ and restarting Neo4j), records the name in /etc/cloudimg/neo4j-hostname and restarts Neo4j.
Neo4j's memory recommendation for this instance size can be printed with:
sudo -u neo4j neo4j-admin server memory-recommendation 2>/dev/null | grep -E '^server\.memory'
Copy the server.memory.heap.initial_size, server.memory.heap.max_size and server.memory.pagecache.size lines into /etc/neo4j/neo4j.conf and run sudo systemctl restart neo4j. To grow the data disk, enlarge its EBS volume in the EC2 console and run sudo resize2fs on the device that findmnt /var/lib/neo4j/data shows.
Security notes
LOAD CSV reads data from files and URLs on the server. On this image a file:/// URL is resolved inside /var/lib/neo4j/import (copy your CSV files there with sudo cp data.csv /var/lib/neo4j/import/), so a query cannot read other files on the instance, and the Neo4j service cannot reach the instance metadata service:
export NEO4J_PASSWORD="$(sudo sed -n 's/^NEO4J_PASSWORD=//p' /root/neo4j-credentials.txt)"
echo "LOAD CSV FROM 'file:///etc/shadow' AS row RETURN row LIMIT 1;" | \
cypher-shell -a bolt+ssc://localhost:7687 -u neo4j --format plain 2>&1 | head -2 || true
Neo4j refuses it (22N43: ... unable to load external resource): file:/// paths are resolved inside the import directory, so /etc/shadow is never reached. When you have finished with the example graph, remove it:
export NEO4J_PASSWORD="$(sudo sed -n 's/^NEO4J_PASSWORD=//p' /root/neo4j-credentials.txt)"
echo "MATCH (n) WHERE n:Person OR n:Topic DETACH DELETE n RETURN count(*) AS removed;" | \
cypher-shell -a bolt+ssc://localhost:7687 -u neo4j --format plain
rm -f /tmp/neo4j.crt
Keep your instance patched (sudo apt-get update && sudo apt-get upgrade; Neo4j updates come from the same official repository), back up your databases with neo4j-admin database dump while Neo4j is stopped, keep the neo4j password safe, and expose ports 7473 and 7687 only to the networks that need them.
Support
cloudimg provides 24/7 technical support for every version in this listing by email and live chat, 365 days a year, with a 24-hour response SLA: support@cloudimg.co.uk.
Trademarks
Neo4j is a registered trademark of Neo4j, Inc. cloudimg is not affiliated with or endorsed by Neo4j, Inc. This image packages Neo4j Community Edition, which is open source software licensed under the GNU General Public License version 3.