Deployment guide

Neo4j 5 Community on Rocky Linux 8

Overview

Neo4j is a native graph database. It stores data as nodes, relationships and properties, and you query it with the Cypher query language. Typical uses include knowledge graphs, fraud detection, recommendations, and network and IT topology.

This SecureAnyCloud image runs Neo4j Community Edition 5.26 on Rocky Linux 8 on Microsoft Azure. 5.26 is the Neo4j 5 long-term support line, and image version 1.0.1 carries 5.26.32. Neo4j Community Edition is licensed under the GNU General Public License version 3.

Every command and every output in this guide was run on a VM deployed from the public Marketplace image (image version 1.0.1), as the azureuser account that a customer gets.

What SecureAnyCloud adds to the upstream packages:

  • No default login. Neo4j normally starts with the user neo4j and the password neo4j. On this image, first boot creates the database with a 24-character password that is unique to the VM. The password is set before Neo4j ever starts, so the default login never exists.
  • Localhost only. Neo4j listens on 127.0.0.1 only: Neo4j Browser and the HTTP API on port 7474, and Bolt on port 7687. Nothing from the network reaches the database until you decide how it should. You reach Neo4j Browser through an SSH tunnel (Step 7).
  • Data on its own disk. The database lives on a separate Azure data disk mounted at /var/lib/neo4j, apart from the operating system disk.
  • Signed packages. Rocky Linux 8 with SELinux enforcing, OpenJDK 17 from Rocky Linux, and Neo4j and cypher-shell from Neo4j's official signed package repository (yum.neo4j.com/stable/5). Running dnf upgrade keeps Neo4j on the latest 5.26 release.

What's included

The image includes:

  • 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 5.26 (5.26.32 on image version 1.0.1) and cypher-shell, from yum.neo4j.com/stable/5
  • OpenJDK 17 (java-17-openjdk) from Rocky Linux AppStream
  • Rocky Linux 8 (8.10 on image version 1.0.1), SELinux enforcing
  • Azure Linux Agent (waagent) and cloud-init for Azure provisioning, and Python 3
  • A 10 GB Azure data disk for the database, mounted at /var/lib/neo4j
  • The SecureAnyCloud first-boot service that sets the per-VM neo4j password
  • 24/7 SecureAnyCloud support

The Azure CLI is not installed on the image. To add it to the VM, follow Microsoft's instructions for RHEL-based distributions.

Connecting to your VM

Use these connection details:

  • SSH user: the administrator you choose at deployment (for example azureuser)
  • Neo4j Browser: http://localhost:7474/browser/ through an SSH tunnel (Step 7)
  • Bolt (drivers, cypher-shell): neo4j://localhost:7687 or bolt://localhost:7687, on the VM or through the tunnel
  • Neo4j user: neo4j, with the password in /root/neo4j-credentials.txt
  • Open ports: 22 (SSH) only. Neo4j's ports 7474 and 7687 listen on localhost.

Prerequisites

You need:

  • An Azure subscription and an SSH public key
  • The Azure CLI on your workstation, signed in with az login
  • A network security group that allows TCP 22 from your own address only. Neo4j needs no inbound rule.

Choose a VM size that suits your workload. Neo4j sizes its heap and page cache from the VM's memory when it starts (Step 9).

1

Deploy from the Azure CLI

The image carries a Marketplace purchase plan, so accept its terms once per subscription, then create the VM.

The offer and the plan are named by the same identifier, which is why it appears twice in the image URN. The plan's Gen2 image adds -gen2. Replace <your-vm-size> with the size you chose:

az vm image terms accept --urn sac1647283583153:899b6cd4-46fb-436f-a23a-09c0724c831f:899b6cd4-46fb-436f-a23a-09c0724c831f-gen2:latest
az vm create \
  --resource-group myResourceGroup \
  --name my-neo4j-vm \
  --image sac1647283583153:899b6cd4-46fb-436f-a23a-09c0724c831f:899b6cd4-46fb-436f-a23a-09c0724c831f-gen2:latest \
  --size <your-vm-size> \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --nsg my-ssh-only-nsg \
  --public-ip-sku Standard

The data disk for /var/lib/neo4j comes with the image, so there is nothing to attach.

A Gen1 image of the same release is published under the plan identifier without -gen2, for sizes that do not support Gen2 VMs.

2

Connect via SSH

On your own workstation, find the VM's public IP, then connect:

az vm show --resource-group myResourceGroup --name my-neo4j-vm --show-details --query publicIps -o tsv ssh azureuser@<vm-ip>

First boot takes a minute or two after the VM is running, while it sets the VM's password and starts Neo4j. If you connect straight away, wait for it to finish:

sudo cloud-init status --wait

The command prints status: done.

3

Check the service

Check that both services are active and see which ports Neo4j listens on:

systemctl is-active neo4j.service sac-firstboot-neo4j.service
sudo ss -Htln '( sport = :7474 or sport = :7687 )'

Both services report active. Neo4j listens on 127.0.0.1 only, on ports 7474 and 7687. Java prints the address as [::ffff:127.0.0.1].

To check the release and the Java runtime, run:

grep PRETTY_NAME /etc/os-release rpm -q neo4j cypher-shell java-17-openjdk-headless
4

Read the per-VM credentials

The neo4j password is unique to this VM. First boot writes it to a root-only file (mode 0600). Check the file's permissions:

sudo stat -c '%a %U:%G %n' /root/neo4j-credentials.txt

The command prints 600 root:root /root/neo4j-credentials.txt. The file holds the user (neo4j), the password, and the Bolt and Browser addresses.

When you need the password, read it into a variable rather than onto the screen. cypher-shell reads it from the NEO4J_PASSWORD environment variable, so set the variable in each new shell like this:

export NEO4J_PASSWORD="$(sudo sed -n 's/^Neo4j password: //p' /root/neo4j-credentials.txt)"

Keep the password safe. It is the database administrator's password.

5

Confirm 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. Run these requests to see it:

Q='{"statement":"RETURN 1 AS one"}' curl -s -o /dev/null -w 'anonymous: HTTP %{http_code}\n' -H 'Content-Type: application/json' -d "$Q" http://127.0.0.1:7474/db/neo4j/query/v2 curl -s -u 'neo4j:not-the-real-one' -o /dev/null -w 'wrong login: HTTP %{http_code}\n' -H 'Content-Type: application/json' -d "$Q" http://127.0.0.1:7474/db/neo4j/query/v2 curl -s -u 'neo4j:neo4j' -o /dev/null -w 'neo4j/neo4j: HTTP %{http_code}\n' -H 'Content-Type: application/json' -d "$Q" http://127.0.0.1:7474/db/neo4j/query/v2

Each request returns HTTP 401. Neo4j locks an account for a few seconds after three failed logins in a row, so wait a moment before you use the real password.

6

Use cypher-shell

With NEO4J_PASSWORD set (Step 4), ask Neo4j for its version and edition:

echo "CALL dbms.components() YIELD name, versions, edition RETURN name, versions[0] AS version, edition;" | \
  cypher-shell -a bolt://localhost:7687 -u neo4j --format plain

The command prints "Neo4j Kernel", "5.26.32", "community".

Now create a small graph and query it:

cat <<'EOF' | cypher-shell -a bolt://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, which makes it a two-hop traversal.

7

Open Neo4j Browser through an SSH tunnel

Neo4j listens on localhost, so you reach Neo4j Browser through SSH. On your workstation, open a tunnel:

ssh -N -L 7474:localhost:7474 -L 7687:localhost:7687 azureuser@<vm-ip>

Leave the tunnel running and open http://localhost:7474/browser/ in your browser. The traffic travels inside the encrypted SSH connection.

In the Connect to instance dialog, keep the protocol neo4j://, the connection URL localhost:7687 and the database user neo4j. Enter the per-VM password and choose Connect.

Type Cypher in the editor at the top and choose Run. MATCH (n)-[r]->(m) RETURN n, r, m draws the graph from Step 6 as nodes and relationships. A query that returns values, such as the two-hop traversal from Alice, is shown as a table.

8

Connect from an application

Every Neo4j driver (Python, Java, JavaScript, .NET, Go) connects over Bolt on port 7687. An application on the VM itself connects to neo4j://localhost:7687. From another machine, the simplest secure route is the SSH tunnel from Step 7.

If your applications must reach Neo4j over the network, first follow Neo4j's operations manual to configure TLS for Bolt and HTTPS (SSL framework). Do this before you change server.default_listen_address in /etc/neo4j/neo4j.conf. Then open 7687 in the network security group only to the networks that need it.

Create a separate user for each application instead of sharing the neo4j administrator. For example, run this in cypher-shell or Neo4j Browser: CREATE USER app SET PASSWORD 'a-long-random-password' CHANGE NOT REQUIRED;. All Community Edition users have full access, so keep the list short.

To change the neo4j password, run ALTER CURRENT USER SET PASSWORD FROM 'current-password' TO 'new-password';. Then update /root/neo4j-credentials.txt yourself, because the image does not rewrite it.

9

Manage the data disk, backups and memory

The database is on its own Azure data disk. Show the mount with:

findmnt /var/lib/neo4j

The output shows the data disk mounted at /var/lib/neo4j. It is an ext4 device such as /dev/sdc, and the device name can differ from one VM to another.

To grow the disk, resize the data disk in Azure. Then grow the file system with sudo resize2fs "$(findmnt -n -o SOURCE /var/lib/neo4j)".

Community Edition takes a backup with neo4j-admin database dump while Neo4j is stopped:

sudo mkdir -p /var/lib/neo4j/backups && sudo chown neo4j:neo4j /var/lib/neo4j/backups
sudo systemctl stop neo4j
sudo -u neo4j neo4j-admin database dump neo4j --to-path=/var/lib/neo4j/backups --overwrite-destination=true sudo systemctl start neo4j

The command ends with Dump completed successfully and writes /var/lib/neo4j/backups/neo4j.dump. Copy the dump off the VM, for example to Azure Blob Storage. Consider Azure Backup or disk snapshots for the whole VM as well.

To print Neo4j's memory recommendation for this VM's size, run:

sudo 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.

10

Keep the VM updated

The image was patched when it was built. Updates published since then are not applied automatically. Update a new VM before you put it into service, and update it regularly afterwards:

sudo dnf -y upgrade

This updates Rocky Linux and, from Neo4j's repository, Neo4j and cypher-shell within the 5.26 line. Reboot if a new kernel was installed.

Security notes

  • Firewall. firewalld is not installed on this image. The network security group is the firewall, so allow SSH only from the networks you manage from.
  • rpcbind. The image includes the NFS client tools, so rpcbind listens on port 111. If you do not mount NFS shares, turn it off with sudo systemctl disable --now rpcbind.socket rpcbind.service. Either way, keep port 111 closed in the network security group.
  • SELinux is enforcing (getenforce prints Enforcing). Keep it on.
  • LOAD CSV file URLs are resolved inside /var/lib/neo4j/import (server.directories.import). Copy CSV files there with sudo cp data.csv /var/lib/neo4j/import/.

When you have finished with the example graph, remove it:

echo "MATCH (n) WHERE n:Person OR n:Topic DETACH DELETE n RETURN count(*) AS removed;" | \
  cypher-shell -a bolt://localhost:7687 -u neo4j --format plain

Server components

The installation uses the following files and services:

  • Configuration: /etc/neo4j/neo4j.conf
  • Data directory (Azure data disk): /var/lib/neo4j/data
  • Import directory (LOAD CSV): /var/lib/neo4j/import
  • Plugins directory: /var/lib/neo4j/plugins
  • Logs: /var/log/neo4j/
  • Credentials file: /root/neo4j-credentials.txt (mode 0600)
  • First-boot service: sac-firstboot-neo4j.service
  • Data disk service: sac-datadisk.service (/etc/sac/datadisk.conf)

Support and licensing

Neo4j Community Edition is licensed under the GNU General Public License version 3. This image ships Community Edition only. Neo4j Enterprise requires a commercial licence from Neo4j, Inc.

SecureAnyCloud provides round-the-clock technical support for this image by email, with a 24-hour response time: sales@secureanycloud.com.

Neo4j is a registered trademark of Neo4j, Inc. Rocky Linux is a trademark of the Rocky Enterprise Software Foundation. SecureAnyCloud is not affiliated with or endorsed by either of them.

Deploy on Azure

Launch Neo4j 5 Community Edition on Rocky Linux 8 on Azure with 24/7 support from SecureAnyCloud.

View on Marketplace

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure