Deployment guide

Neo4j 2026

Videos

Overview: Neo4j 2026 Community Ubuntu 24.04 on Azure: overview (watch on YouTube)

Launch and log in: Neo4j 2026 Community Ubuntu 24.04 on Azure: launch and log in (watch on YouTube)

Deep Dive: Neo4j 2026 Community Ubuntu 24.04 on Azure: deep dive (watch on YouTube)

Overview

Neo4j is a native graph database. It stores data as nodes, relationships and properties, and you query it with the Cypher query language. Teams use it 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 guide covers deploying and using Neo4j 2026 Community on Ubuntu 24.04 from SecureAnyCloud on Microsoft Azure. The image ships Neo4j Community Edition 2026.10.1, which is licensed under the GNU General Public License version 3.

What you get:

  • Neo4j Browser (the web query interface), the HTTP API and the Bolt protocol used by every official Neo4j driver, plus cypher-shell.
  • 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 VM. The password is 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 VM for its own address protects Neo4j Browser and the HTTP API (HTTPS on port 7473) and the Bolt protocol (port 7687). Bolt requires TLS, so plain bolt:// connections are refused. The unencrypted HTTP port 7474 is turned off, and every other Neo4j listener is off or bound to loopback. The only ports the VM listens on are 22, 7473 and 7687.
  • 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, /root or /etc/shadow. LOAD CSV file URLs are confined to the import directory.
  • Blocked from the Azure metadata service. The Neo4j service and its first-boot setup cannot reach the Azure Instance Metadata Service (169.254.169.254) or the Azure wire server (168.63.129.16). A LOAD CSV FROM 'http://...' therefore cannot read VM metadata. The Azure Linux Agent and cloud-init keep their access, so provisioning and extensions work as usual.
  • No plugins. The Neo4j package also carries the APOC, Graph Data Science and GenAI plugin jars. None is installed on this image, the plugins directory is empty, and upgrades do not restore them. Usage reporting to Neo4j is turned off.
  • Fully patched Ubuntu 24.04 at build time, Neo4j from Neo4j's official signed package repository, OpenJDK 25 from Ubuntu, and the SecureAnyCloud security defaults.
  • On the image: Ubuntu 24.04 LTS, OpenJDK 25 (Java runtime, from Ubuntu), Neo4j 2026.10.1 Community and cypher-shell from debian.neo4j.com, the configuration in /etc/neo4j/, the data directory /var/lib/neo4j/data (empty until first boot creates the databases), and the SecureAnyCloud first-boot service.

Connecting to your VM

Item Value

SSH user the administrator you choose at deployment (for example azureuser)

Neo4j Browser https://<vm-ip>:7473/browser/

Bolt (drivers, cypher-shell) neo4j+s://<vm-ip>:7687 (or neo4j+ssc:// with the self-signed certificate)

Neo4j user neo4j, password in /root/neo4j-credentials.txt

Open ports 22 (SSH), 7473 (HTTPS), 7687 (Bolt, TLS). Port 7474 is not used.

Prerequisites

  • An Azure subscription, an SSH public key, and a virtual network in the target region
  • A network security group that allows TCP 22 from your own address. It must also allow TCP 7473 (Neo4j Browser and the HTTP API, HTTPS) and TCP 7687 (Bolt, TLS) from the clients and applications that will use the database. Expose 7473 and 7687 only to the networks that need them. You can also keep them closed and use an SSH tunnel (Step 7).
  • Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) for development and small graphs. Neo4j sizes its heap and page cache from the VM's memory at start-up. For production graphs, choose a memory-optimized size such as Standard_E4s_v5 (4 vCPU, 32 GB RAM) or larger. See Step 9 for tuning.
1

Deploy from the Azure Portal

Search for Neo4j 2026 in the Azure Marketplace. Select the SecureAnyCloud entry and choose Create.

In Networking, allow SSH (22) from your address. Add inbound rules for TCP 7473 and TCP 7687 from your client networks.

First boot takes one to two minutes after the VM is running. During this time, the VM generates its certificate and password, creates the databases and starts Neo4j.

2

Deploy from the Azure CLI

RG="neo4j-prod"; LOCATION="eastus"; VM_NAME="neo4j-01" IMAGE_URN="sac1647283583153:neo4j-2026-ubuntu-24-04:default:latest" CLIENT_CIDR="<your-mgmt-cidr>" az group create --name "$RG" --location "$LOCATION" az network nsg create -g "$RG" --name neo4j-nsg az network nsg rule create -g "$RG" --nsg-name neo4j-nsg --name allow-ssh --priority 100 \
  --source-address-prefixes "$CLIENT_CIDR" --destination-port-ranges 22 --access Allow --protocol Tcp az network nsg rule create -g "$RG" --nsg-name neo4j-nsg --name allow-neo4j --priority 110 \
  --source-address-prefixes "$CLIENT_CIDR" --destination-port-ranges 7473 7687 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn "$IMAGE_URN"
az vm create -g "$RG" --name "$VM_NAME" --image "$IMAGE_URN" \
  --size Standard_B2s --admin-username azureuser --ssh-key-values ~/.ssh/id_rsa.pub \
  --nsg neo4j-nsg --public-ip-sku Standard

First boot takes a minute or two. If you connect as soon as the VM shows as running, wait for the per-VM setup to finish before you continue:

bash sudo cloud-init status --wait

The command prints status: done. Then systemctl is-active neo4j-firstboot.service reports active.

3

Connect via SSH and check the service

ssh azureuser@<vm-ip>

The login banner shows the Neo4j Browser and Bolt addresses for this VM. Confirm that Neo4j is running and listening only on the HTTPS and Bolt ports:

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

Both services report active. Neo4j listens on port 7473 (HTTPS) and port 7687 (Bolt with TLS) on all addresses. Nothing listens on 7474.

4

Read the per-VM credentials

The neo4j password is unique to this VM. It is written to a root-only file (mode 0600) at first boot. Print only the field names, never the password itself:

sudo grep -oE '^[A-Z0-9_]+=' /root/neo4j-credentials.txt

The command lists these fields:

  • NEO4J_HOST: the address Neo4j advertises, which is the VM's public IP, or its private IP when it has none
  • NEO4J_USER: neo4j
  • NEO4J_PASSWORD: the per-VM 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. Keep it safe, because it is the database administrator's password.

The VM's certificate covers its public and private IP addresses, its host name, localhost and 127.0.0.1.

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. Each gets 401 Unauthorized.

Save the VM's certificate so curl can verify the connection:

sudo cat /var/lib/neo4j/certificates/sac/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 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. With the per-VM 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.

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.

Bolt requires TLS, so use the bolt+ssc:// scheme on the VM itself. The connection is encrypted, but 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

The command 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, which is a two-hop traversal.

7

Open Neo4j Browser

With TCP 7473 and 7687 open to your address in the network security group, open https://<vm-ip>:7473/browser/ in your browser.

If you prefer to keep those ports closed, use an SSH tunnel and open https://localhost:7473/browser/ instead. The VM's certificate also covers localhost:

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

The certificate is self-signed and unique to the VM, so your browser warns once. Accept it for this host. For production, see Step 9.

In the Connect to instance dialog, choose neo4j+s:// as the protocol. Enter the VM's address and port 7687 as the connection URL (localhost:7687 through the tunnel). Keep neo4j as the database user, and enter the per-VM 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://<vm-ip>:7687 (or https://localhost:7687) once in a new tab and accept the warning. The page itself then shows an error, which is expected. 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:

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. The connection is encrypted, but the certificate is not checked.

To verify the server, copy /var/lib/neo4j/certificates/sac/public.crt from the VM and add it to the client's trust store. Alternatively, replace the certificate with one from your own certificate authority. Then use neo4j+s://.

For example, in Python (pip install neo4j):

from neo4j import GraphDatabase driver = GraphDatabase.driver("neo4j+ssc://<vm-ip>: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, run this 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, because the file is not rewritten.

9

Serve under your own DNS name, and tune memory

Neo4j advertises one address to its clients. The Bolt routing table and Neo4j Browser use it. On first boot, the address is the VM's public IP address from the Azure metadata service, or its private IP when the VM has no public IP.

After you point a DNS record at the VM, set the name and issue a new certificate for it:

sudo neo4j-set-hostname neo4j.<your-domain>

The command regenerates the self-signed certificate, records the name in /etc/sac/neo4j-hostname and restarts Neo4j.

For production, replace the self-signed certificate with your own CA-issued certificate. Put private.key and public.crt in /var/lib/neo4j/certificates/sac/ and restart Neo4j.

Print Neo4j's memory recommendation for this VM size 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. Then run sudo systemctl restart neo4j.

Security notes

LOAD CSV and the metadata service. LOAD CSV reads data from files and URLs on the server. On this image, a file:/// URL is resolved inside /var/lib/neo4j/import, so a query cannot read other files on the VM. Copy your CSV files there with sudo cp data.csv /var/lib/neo4j/import/.

Try to read a file outside the import directory to see the restriction:

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

A systemd IPAddressDeny rule also denies the Neo4j service access to the Azure Instance Metadata Service and the wire server. A LOAD CSV FROM 'http://169.254.169.254/...' therefore never reaches it.

You can prove this from inside the service's own control group. The Azure Linux Agent is not in that group, so it keeps its access:

CG=$(systemctl show -p ControlGroup --value neo4j.service)
sudo bash -c "echo \$\$ > /sys/fs/cgroup${CG}/cgroup.procs; exec sac-egress-probe neo4j.service"

It prints verdict=BLOCKED, with loopback reachable and the metadata addresses timing out:

Plugins. No plugin ships, and /etc/dpkg/dpkg.cfg.d/sac-neo4j-no-plugins keeps package upgrades from restoring the APOC, Graph Data Science and GenAI jars.

Adding a plugin is your own security decision. Plugins run inside the database with its permissions, and procedures such as APOC's apoc.load.* read files and URLs. To add one, follow these steps:

  • Download the plugin version that matches Neo4j 2026.10.1 from its official release page.
  • Copy the jar into /var/lib/neo4j/plugins/ (owned by neo4j).
  • Allow only the procedures you need with dbms.security.procedures.allowlist in /etc/neo4j/neo4j.conf.
  • Restart Neo4j.

The service sandbox and the metadata block still apply to a plugin.

The Neo4j package signing key expires on 31 December 2026. Neo4j's repository is signed with key 1EEF B876 7D49 24B8 6EAD 08A4 59D7 00E4 D37F 5F19 (Neo4j Admins), which expires on 2026-12-31.

Nothing on this image needs the repository to boot or to run Neo4j, and Ubuntu's own security updates are unaffected. After that date, apt-get update reports an error for the Neo4j repository and exits non-zero. Ubuntu's package lists still refresh, and unattended security upgrades keep running, until you load Neo4j's renewed key.

When Neo4j publishes the renewed key, refresh it and check its fingerprint and expiry:

curl -fsSL https://debian.neo4j.com/neotechnology.gpg.key -o /tmp/neo4j.key gpg --show-keys --with-colons /tmp/neo4j.key | awk -F: '/^fpr:/{print "fingerprint " $10; exit} /^pub:/{system("date -u -d @" $7 " +\"expires %Y-%m-%d\"")}'

If the fingerprint is the one above, install the key with sudo gpg --dearmor --yes -o /usr/share/keyrings/neo4j-archive-keyring.gpg /tmp/neo4j.key. Then run sudo apt-get update.

If Neo4j announces a different key, verify it against the instructions on https://debian.neo4j.com before you install it.

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 /tmp/neo4j.key

General recommendations:

  • Keep your VM patched with 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.
  • Expose ports 7473 and 7687 only to the networks that need them.

Server components

Component Path

Configuration /etc/neo4j/neo4j.conf

Data directory /var/lib/neo4j/data

Import directory (LOAD CSV) /var/lib/neo4j/import

Plugins directory (empty) /var/lib/neo4j/plugins

Certificate and key /var/lib/neo4j/certificates/sac/

Logs /var/log/neo4j/

Credentials file /root/neo4j-credentials.txt (mode 0600)

First-boot service neo4j-firstboot.service (/usr/local/sbin/neo4j-firstboot.sh)

Hostname and certificate helper /usr/local/sbin/neo4j-set-hostname

Support and licensing

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

SecureAnyCloud provides 24/7 technical support for this image by email, 365 days a year, with a 24-hour response SLA: sales@secureanycloud.com.

Neo4j is a registered trademark of Neo4j, Inc. SecureAnyCloud is not affiliated with or endorsed by Neo4j, Inc.

Deploy on Azure

Launch Neo4j 2026 Community on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure