Databases AWS

Neo4j 5.26 LTS Community on AWS User Guide

| Product: Neo4j 5.26 LTS Community on Rocky Linux 9

Overview

This guide covers launching and using the Neo4j 5.26.32 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 5.26.32 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.

Neo4j 5.26 LTS or Neo4j 2026?

Neo4j 5.26 is the long-term support (LTS) release of Neo4j 5: Neo4j supports it until June 2028 and ships patch releases (5.26.x) with security and bug fixes only, no new features and no breaking changes. Choose this version when your applications, drivers, plugins or procedures were built and tested against Neo4j 5, when you are upgrading an existing Neo4j 4.4 or 5.x deployment, or when you want a fixed feature set for a regulated or long-lived system. Choose the Neo4j 2026 Community version in the same listing for new projects that want the newest Cypher features and the faster release cadence of Neo4j's calendar-versioned releases. Both versions carry the same cloudimg security defaults.

What cloudimg adds to the upstream build:

  • No default login. Neo4j normally starts with the user neo4j and the password neo4j. 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 with no Linux capabilities in a systemd sandbox: it can write only its data, log and run directories, and it cannot read the credentials file, SSH keys, /root or /etc/shadow. LOAD CSV file URLs are confined to the import directory, and neither the Neo4j service nor its first-boot service can reach the EC2 instance metadata service, so a LOAD CSV FROM 'http://...' cannot be used to read instance credentials.
  • Rocky Linux 9 hardened. SELinux stays enforcing, firewalld allows only SSH and the two Neo4j ports, SSH accepts keys only (no passwords, no root login), and dnf-automatic applies Rocky Linux security updates every day (OpenJDK included).
  • No plugins. The Neo4j package also carries the APOC, GenAI and Fleet Management plugin jars. None is installed on this image, and package 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 Rocky Linux 9 at build time, with Neo4j from Neo4j's official signed package repository.

What is on the image: Rocky Linux 9, OpenJDK 21 (the Java runtime from Rocky Linux AppStream), Neo4j 5.26.32 Community and cypher-shell from yum.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 services.

Connecting to your instance

Version SSH user Neo4j Browser Bolt (drivers, cypher-shell)
Neo4j 5.26 LTS Community on Rocky Linux 9 rocky https://<public-dns>:7473/browser/ neo4j+s://<public-dns>:7687

Prerequisites

  1. An AWS account and permission to launch EC2 instances
  2. An EC2 key pair in the Region you launch in
  3. 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

  1. 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.
  2. Choose Launch your software, then in Version choose Neo4j 5.26 LTS Community on Rocky Linux 9 - YYYY-MM-DD and your Region.
  3. Instance type: m5.large is recommended.
  4. Key pair: choose your EC2 key pair.
  5. Security group: TCP 22 from your own address; TCP 7473 and 7687 from your clients.
  6. 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 (instance metadata service version 2), 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 rocky@<vm-ip>

The login message 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 *:7473 (HTTPS) and *:7687 (Bolt with TLS); nothing listens on 7474. The data volume is mounted at /var/lib/neo4j/data:

df -hT /var/lib/neo4j/data

The host firewall (firewalld) admits only SSH and the two Neo4j ports, and SELinux is enforcing:

sudo firewall-cmd --list-services
sudo firewall-cmd --list-ports
getenforce

firewalld lists the ssh service (with dhcpv6-client, the reply port for IPv6 addressing) and the ports 7473/tcp 7687/tcp; getenforce prints Enforcing. Your EC2 security group is still the first boundary: open 7473 and 7687 only to the networks that need them.

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", "5.26.32", "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:

Neo4j Browser Connect to instance dialog with the neo4j+s protocol, the instance's Bolt address on port 7687 and the neo4j user

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:

Neo4j Browser showing the Person and Topic graph with KNOWS and INTERESTED_IN relationships

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

Neo4j Browser table result of a two-hop KNOWS traversal from Alice to Bob and Carol

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

Neo4j Browser sysinfo panel with the neo4j and system databases online

Step 8: Connect from an application

Every Neo4j driver (Python, Java, JavaScript, .NET, Go) connects over Bolt on port 7687 with TLS; the Neo4j 5 drivers are the matching choice for this LTS server. 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 instance metadata service (IMDSv2). 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. The Bolt addresses Neo4j hands to drivers always come from this configured name, never from a request header.

Neo4j's memory recommendation for this instance size can be printed with:

sudo -u neo4j NEO4J_CONF=/etc/neo4j NEO4J_HOME=/var/lib/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 df -hT /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 (Couldn't load the 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

Updates. dnf-automatic installs Rocky Linux security updates daily (/etc/dnf/automatic.conf, upgrade_type = security); check its timer with systemctl status dnf-automatic.timer. Neo4j itself is updated only when you choose to, within the 5.26 LTS line, from Neo4j's repository (/etc/yum.repos.d/neo4j.repo, https://yum.neo4j.com/stable/5): sudo dnf upgrade neo4j cypher-shell, then sudo systemctl restart neo4j. The first time you use that repository dnf asks you to confirm Neo4j's signing key; check that the fingerprint is 1EEF B876 7D49 24B8 6EAD 08A4 59D7 00E4 D37F 5F19 (Neo4j Admins) and answer y. That key is valid until 31 December 2026; when Neo4j publishes its renewed key, refresh it with sudo curl -fsSL -o /etc/pki/rpm-gpg/RPM-GPG-KEY-neo4j https://debian.neo4j.com/neotechnology.gpg.key && sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-neo4j after checking the fingerprint. The repository is marked skip_if_unavailable, so a problem with it never stops the operating system updates.

SELinux stays enforcing; Neo4j runs as unconfined_service_t under the targeted policy. If you move the data directory or the import directory, give the new path the right label with sudo semanage fcontext -a -e /var/lib/neo4j <new-path> and sudo restorecon -R <new-path> rather than turning SELinux off.

HTTP API links. Neo4j 5.26 builds the HTTP API link templates in its discovery document from the request it receives (2026.x added a setting to turn this off); those links are returned only to the client that sent the request, and the Bolt addresses Neo4j advertises always come from the configured hostname.

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. Rocky Linux is a trademark of the Rocky Enterprise Software Foundation. cloudimg is not affiliated with or endorsed by Neo4j, Inc. or the Rocky Enterprise Software Foundation. This image packages Neo4j Community Edition, which is open source software licensed under the GNU General Public License version 3.