Neo4j
Overview
This image runs Neo4j Community Edition, the leading open source native graph database, on a single node. Neo4j stores connected data as nodes and relationships and exposes the Cypher query language over the Bolt protocol. It ships with the Neo4j Browser web interface for ad hoc queries, visualisation and schema exploration. Neo4j 5 runs on the OpenJDK 21 Java virtual machine, which is also installed on the image.
The neo4j superuser password is created on the first boot of every deployed instance, so two instances launched from the same Amazon Machine Image never share a password.
What you get:
- Neo4j Community Edition 5 on a single node, with OpenJDK 21 installed
- The HTTP REST API and the Neo4j Browser on port 7474
- The Bolt protocol, used by every Neo4j driver and the
cypher-shellcommand line, on port 7687 - An optional HTTPS endpoint on port 7473, disabled in the default configuration
- nginx as a reverse proxy on port 80, fronting the Neo4j Browser so it is reachable on the standard HTTP port. The nginx configuration forwards WebSocket upgrade headers, so the Bolt over WebSocket path that the Browser uses also passes through the proxy.
- No active credential in the image, so the database is never left on the default
neo4j/ neo4j credentials that vanilla Neo4j installations carry. A first boot systemd service creates a fresh password and applies it withneo4j-admin dbms set-initial-passwordbefore Neo4j first starts. It writes the plain text value to/root/neo4j-credentials.txtwith mode 0600, so only the root user can read it. - Database files under
/var/lib/neo4j/dataon the root EBS volume captured into the AMI. If your graph outgrows the initial allocation, you can resize the root volume after launch, or attach a dedicated EBS volume and move the data directory.
Prerequisites
Before you deploy this image, make sure you have:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region, for SSH access to the instance
- A VPC and subnet in the target Region, with a security group that allows inbound port 22 from your management network and inbound ports 80, 7474 and 7687 from the trusted networks that host the applications that will talk to Neo4j
- The AWS CLI version 2 installed locally, if you plan to deploy from the command line
Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console and open the EC2 service. Select Launch instance.
Under Application and OS Images, choose AWS Marketplace AMIs and search for Neo4j Community. Select the SecureAnyCloud listing, choose Select, then choose Continue on the subscription summary.
Choose an instance type of m5.large or larger. Neo4j 5 needs at least 4 GiB of memory to leave headroom for the Java heap and the page cache. Choose your EC2 key pair under Key pair (login).
Under Network settings, select your VPC and subnet. Create or select a security group that allows inbound port 22 from your management network and inbound ports 80, 7474 and 7687 from the trusted networks that will reach Neo4j. Do not open these ports to the public internet, because the Bolt protocol and the Neo4j Browser both expose database access. Leave the root volume at the default size or larger.
Select Launch instance. First boot takes approximately one minute after the instance state becomes Running and the status checks pass.
Launch the Instance from the AWS CLI
Run the following command to launch an instance from the SecureAnyCloud Neo4j Community Edition Marketplace AMI into an existing subnet and security group. Replace these values:
- <ami-id> with the AMI ID shown on the Marketplace listing
- <key-name> with your EC2 key pair name
- <subnet-id> with your subnet ID
- <security-group-id> with a security group that opens ports 22, 80, 7474 and 7687 as described above
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":20,"VolumeType":"gp3"}}]' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=neo4j-01}]'On success, the command prints a JSON document. Note the instance ID. Once the instance is running, get its public address with aws ec2 describe-instances --instance-ids <instance-id> --query "Reservations[].Instances[].PublicIpAddress" --output text.
Connect and Retrieve the Neo4j Password
Connect over SSH with the key pair you selected and the public IP address from Step 2. The SSH login user depends on the AMI variant you launched. For Neo4j Community 5 on Ubuntu 24.04, the login user is ubuntu.
The first boot service runs before the SSH daemon becomes ready, so the credentials file is always in place when you log in for the first time.
ssh <login-user>@<public-ip>
sudo cat /root/neo4j-credentials.txtThe plain text file contains the Neo4j Browser URL, the HTTP API URL, the Bolt URL, the superuser username (neo4j) and the password for this instance.
# Neo4j Community Edition 5 — generated on first boot by neo4j-firstboot.service.
# This neo4j superuser password is unique to this instance. Store it somewhere safe;
# it is shown in plain text only here. neo4j.browser.url=http://<your-instance-public-ip>/ neo4j.http.url=http://<your-instance-public-ip>:7474/ neo4j.bolt.url=bolt://<your-instance-public-ip>:7687 neo4j.admin.user=neo4j neo4j.admin.pass=<NEO4J_PASSWORD>Copy these values somewhere secure, such as a password manager or an encrypted vault. Do not commit them to source control.
Each command block in this guide that talks to Neo4j begins by reading the password from the credentials file into a shell variable, so every block is self-contained.
NEO4J_PASS="$(sudo awk -F= '/^neo4j.admin.pass=/ {print $2}' /root/neo4j-credentials.txt)" echo "neo4j password length: ${#NEO4J_PASS}"Verify the Server Is Healthy
Three checks confirm the server is running: the systemd unit state, the listening ports and a Cypher round trip over the Bolt protocol.
sudo systemctl is-active neo4j.service nginx.service
sudo ss -tln | grep -E ':80 |:7474 |:7687 'The systemd command reports active for both services. The ss output shows nginx listening on :80, the Neo4j Browser and HTTP API on :7474, and the Bolt protocol on :7687.
active active LISTEN 0 511 0.0.0.0:80 0.0.0.0:* LISTEN 0 511 [::]:80 [::]:* LISTEN 0 50 *:7474 *:* LISTEN 0 4096 *:7687 *:*Run a Cypher round trip with the bundled cypher-shell command line client. This confirms the daemon is answering Bolt and the password works.
NEO4J_PASS="$(sudo awk -F= '/^neo4j.admin.pass=/ {print $2}' /root/neo4j-credentials.txt)" echo "CALL dbms.components() YIELD name, versions, edition RETURN name, versions[0] AS version, edition;" \
| cypher-shell -a bolt://localhost:7687 -u neo4j -p "$NEO4J_PASS" --format verboseThe response reports the installed Neo4j version and edition.
+------------------------------------------+ | name | version | edition | +------------------------------------------+ | "Neo4j Kernel" | "5.26.26" | "community" | +------------------------------------------+ 1 row ready to start consuming query after 59 ms, results consumed after another 2 msServer Components
The image includes these components:
- Neo4j Community 5.26.26: from the official Neo4j APT repository at debian.neo4j.com (stable / 5 component)
- OpenJDK 21.0.10 (headless): from the Ubuntu 24.04 distribution package openjdk-21-jre-headless
- nginx 1.24.0: from the Ubuntu 24.04 distribution package nginx
- Ubuntu 24.04 LTS (Noble Numbat): the AWS Marketplace Canonical AMI, fully apt dist-upgraded at build time
Open the Neo4j Browser
The Neo4j Browser is the official web client for Neo4j. It runs entirely inside your browser, talks to the database over Bolt (via the WebSocket transport), and lets you sign in, run Cypher queries, visualise the result as a graph, browse the database information panel and inspect the schema.
The SecureAnyCloud image exposes the Browser on port 80 through the nginx reverse proxy, so any modern browser reaches it without a port suffix. Open this URL.
http://<your-instance-public-ip>/The first request returns an HTTP 302 redirect to /browser/, where the React application loads. After a moment, the Connect to instance dialog appears.
Fill in the dialog:
- Connection URL: the Bolt URL of your instance (
bolt://<your-instance-public-ip>:7687) - Database user:
neo4j - Password: the value from
/root/neo4j-credentials.txt
Select Connect. The Browser establishes a Bolt over WebSocket session and shows the workspace.
The left rail carries the Database information panel, which shows the database, schema, node count, relationship count and property keys. The top bar is the Cypher query editor, and the centre pane is where each query renders its result.
The "Connect your instance to AuraDB" banner in the top right links to Neo4j's managed service. It is informational only and does not change the local instance.
Run Your First Cypher Query
Cypher is Neo4j's declarative query language for graphs. Type a small query into the editor at the top of the workspace and press the Run button or Ctrl+Enter. The following one-liner creates a tiny graph of two people who know each other and returns both nodes.
CREATE (a:Person {name:'Alice'})-[:KNOWS]->(b:Person {name:'Bob'}) RETURN a, bNeo4j Browser draws the result as a graph in the Graph tab of the result frame. Switch to the Table or RAW tab to see the same result as JSON rows. The left panel updates immediately with the new node and relationship counts.
You can also run Cypher from the shell with cypher-shell. The same query runs end to end like this.
NEO4J_PASS="$(sudo awk -F= '/^neo4j.admin.pass=/ {print $2}' /root/neo4j-credentials.txt)" echo "MATCH (n:Person) RETURN n.name AS person ORDER BY person;" \
| cypher-shell -a bolt://localhost:7687 -u neo4j -p "$NEO4J_PASS" --format verbose+----------+ | person | +----------+ | "Alice" | | "Bob" | +----------+ 2 rowsWhen you are done exploring, clean up the two probe nodes.
NEO4J_PASS="$(sudo awk -F= '/^neo4j.admin.pass=/ {print $2}' /root/neo4j-credentials.txt)" echo "MATCH (n:Person) DETACH DELETE n;" \
| cypher-shell -a bolt://localhost:7687 -u neo4j -p "$NEO4J_PASS"Inspect the Database from the Browser
The Browser ships with a set of : commands that drive the workspace from the editor bar. Two are worth knowing on day one.
:sysinfoopens the System information panel. It lists the databases on the server, with their addresses, role, online state and last update timestamp. Community Edition shows only the core overview. Enterprise Edition adds memory pool, transaction and store metrics.:server statusprints the connection record (the URL, the user, the connection age).
Run :sysinfo from the editor bar. The result frame splits in two. The top frame shows the System information table, and the previous query result stays pinned below it.
Modelling Data: Indexes and Constraints
A unique constraint is the most useful schema object on a fresh Neo4j database. It guarantees that no two nodes of a given label share a value for a property. Neo4j automatically backs it with an index, so lookups by that property become point reads instead of label scans.
NEO4J_PASS="$(sudo awk -F= '/^neo4j.admin.pass=/ {print $2}' /root/neo4j-credentials.txt)" cypher-shell -a bolt://localhost:7687 -u neo4j -p "$NEO4J_PASS" <<'CYPHER' CREATE CONSTRAINT person_email_unique IF NOT EXISTS FOR (p:Person) REQUIRE p.email IS UNIQUE; SHOW CONSTRAINTS; CYPHERSHOW CONSTRAINTS lists the constraint and the index it created. To list every index separately, run SHOW INDEXES. To drop a constraint or index, run DROP CONSTRAINT <name> or DROP INDEX <name>.
For larger graphs, add a range index on properties you filter by and a text index on properties you match by prefix or substring.
CREATE INDEX person_name_range IF NOT EXISTS FOR (p:Person) ON (p.name); CREATE TEXT INDEX person_name_text IF NOT EXISTS FOR (p:Person) ON (p.name);Backup and Restore
Community Edition does not include the online neo4j-admin database backup command, which is an Enterprise feature. The supported offline path is neo4j-admin database dump. Stop the daemon, dump the named database to a .dump archive on the data volume, then restart.
sudo install -d -o neo4j -g neo4j -m 0750 /var/lib/neo4j/backups
sudo systemctl stop neo4j
sudo -u neo4j neo4j-admin database dump neo4j --to-path=/var/lib/neo4j/backups sudo systemctl start neo4j
sudo ls -la /var/lib/neo4j/backups/To restore on a fresh instance, run neo4j-admin database load, again with the daemon stopped. Then start the daemon and verify.
sudo systemctl stop neo4j
sudo -u neo4j neo4j-admin database load neo4j --from-path=/var/lib/neo4j/backups --overwrite-destination=true sudo systemctl start neo4j NEO4J_PASS="$(sudo awk -F= '/^neo4j.admin.pass=/ {print $2}' /root/neo4j-credentials.txt)" echo "MATCH (n) RETURN count(n) AS nodes;" \
| cypher-shell -a bolt://localhost:7687 -u neo4j -p "$NEO4J_PASS" --format verboseCopy the .dump archive off the instance with aws s3 cp or scp, so the backup is stored separately from the instance.
HTTPS Termination
The default nginx site terminates plain HTTP only. For production traffic, add a TLS certificate (Let's Encrypt via certbot, or AWS Certificate Manager behind an Application Load Balancer) and switch the nginx server block to listen 443 ssl;.
A minimal TLS server block, with paths to a fullchain certificate and a private key, looks like this.
server { listen 443 ssl default_server; server_name your-domain.example.com; ssl_certificate /etc/letsencrypt/live/your-domain.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your-domain.example.com/privkey.pem; location = / { return 302 /browser/; } location / { proxy_pass http://127.0.0.1:7474; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_read_timeout 86400; } }Open port 443 on the security group and run sudo nginx -t && sudo systemctl reload nginx. The Neo4j Browser is then reachable over HTTPS on the same hostname.
For Bolt over TLS, create a certificate for the bolt:// port and enable dbms.connector.bolt.tls_level=REQUIRED in /etc/neo4j/neo4j.conf.
Security Posture
- Restrict ports 80, 7474 and 7687 in the AWS security group to the application subnets that need them. Do not open them to
0.0.0.0/0. - Rotate the neo4j superuser password regularly with
ALTER USER neo4j SET PASSWORD '<new>';. Update/root/neo4j-credentials.txtafterwards. - Create application users with
CREATE USERand grant them the minimum role they need (reader,editor,publisheroradmin). Never use theneo4jsuperuser for application traffic. - Front Neo4j with a reverse proxy that terminates TLS, as covered in Step 11, so credentials never travel in clear text.
- Take regular dumps as in Step 10. If the graph is your source of truth, copy the dumps to S3 with object lock.
Reference: Where Things Live on the Instance
These are the paths that matter most, and what each one is for.
- /usr/bin/neo4j: the Neo4j daemon launcher script
- /usr/bin/neo4j-admin: the administrative command line (dump, load, set-initial-password)
- /usr/bin/cypher-shell: the bundled Cypher shell client
- /etc/neo4j/neo4j.conf: the main Neo4j configuration file
- /var/lib/neo4j/data/: database files (system database and any user-created databases)
- /var/lib/neo4j/data/dbms/auth: the auth file written by neo4j-admin dbms set-initial-password
- /var/log/neo4j/: Neo4j log files (neo4j.log, query.log, security.log)
- /root/neo4j-credentials.txt: the plain text per-instance neo4j superuser password (mode 0600 root)
- /etc/nginx/sites-available/neo4j-browser: the SecureAnyCloud nginx reverse proxy site for the Browser
- /etc/systemd/system/neo4j-firstboot.service: the first boot password rotation unit
- /usr/local/sbin/neo4j-firstboot.sh: the first boot rotation script that the unit runs
- /var/lib/sac/data/neo4j-firstboot.done: the sentinel that disables the first boot service after its first successful run
Reference: Useful Commands
These commands cover day-to-day service management, a connection check and an offline dump copied to S3.
# Check service state
sudo systemctl status neo4j
sudo journalctl -u neo4j -n 50
# Tail Neo4j's main log sudo tail -f /var/log/neo4j/neo4j.log # Stop, start, restart sudo systemctl stop neo4j sudo systemctl start neo4j sudo systemctl restart neo4j # Re-read configuration after editing /etc/neo4j/neo4j.conf sudo systemctl restart neo4j # Connect with cypher-shell over Bolt cypher-shell -a bolt://localhost:7687 -u neo4j # List databases (Community has neo4j and system)
echo "SHOW DATABASES;" | cypher-shell -a bolt://localhost:7687 -u neo4j -p "$NEO4J_PASS"
# Take an offline dump and put it on S3
sudo systemctl stop neo4j
sudo -u neo4j neo4j-admin database dump neo4j --to-path=/var/lib/neo4j/backups sudo systemctl start neo4j aws s3 cp /var/lib/neo4j/backups/neo4j.dump s3://your-bucket/neo4j/$(date +%Y-%m-%d).dumpScreenshots
Here is what you see as you work through this guide:
- The Neo4j Browser sign-in page, served on first boot with no manual setup
- The Neo4j Browser welcome panel, after signing in as the neo4j user with the rotated password
- A small Cypher query rendered as a graph in the Neo4j Browser
- The Neo4j Browser database information panel, showing the running Neo4j 5 instance
Support
For help with deployment, upgrades, Cypher tuning, indexing strategy, graph data modelling or any other Neo4j question, contact SecureAnyCloud support at sales@secureanycloud.com. 24/7 support is included with every Marketplace subscription.
Deploy on AWS
Launch Neo4j Community Edition on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com