Why Neo4j?
Unlike traditional relational databases that struggle with highly connected data, Neo4j excels at traversing relationships, making it ideal for recommendation engines, fraud detection, knowledge graphs, network analysis, and social platforms.
Prerequisites
System Requirements
- RamNode VPS running Ubuntu 22.04 or 24.04 LTS (Debian 11/12 also supported)
- Root or sudo access
- Minimum 2GB RAM (4GB+ recommended for production)
- At least 10GB available disk space
- Optional: domain name for remote access with SSL
Memory Configuration
| VPS RAM | Heap Size | Page Cache | Recommended For |
|---|---|---|---|
| 2GB | 512m | 256m | Development only |
| 4GB | 1g | 512m | Small production |
| 8GB | 2g | 2g | Medium production |
| 16GB | 4g | 6g | Large production |
💡 Neo4j Editions: Community Edition is free and open-source. Enterprise Edition includes clustering, advanced security, and hot backups (30-day trial available).
Native Installation (Recommended)
apt update && apt upgrade -y
apt install -y openjdk-17-jre-headless
# Verify installation
java -version# Import GPG key
curl -fsSL https://debian.neo4j.com/neotechnology.gpg.key | gpg --dearmor -o /usr/share/keyrings/neo4j-archive-keyring.gpg
# Add repository
echo "deb [signed-by=/usr/share/keyrings/neo4j-archive-keyring.gpg] https://debian.neo4j.com stable latest" | tee /etc/apt/sources.list.d/neo4j.listapt update
apt install -y neo4j
# For a specific version:
# apt install -y neo4j=1:5.26.0Configure Neo4j
# Network connector configuration
server.default_listen_address=0.0.0.0
# Bolt connector (for drivers and applications)
server.bolt.enabled=true
server.bolt.listen_address=0.0.0.0:7687
# HTTP connector (for REST API and browser)
server.http.enabled=true
server.http.listen_address=0.0.0.0:7474
# HTTPS connector (recommended for production)
server.https.enabled=true
server.https.listen_address=0.0.0.0:7473
# Memory configuration (4GB RAM VPS)
server.memory.heap.initial_size=1g
server.memory.heap.max_size=1g
server.memory.pagecache.size=512m
# Enable query logging
db.logs.query.enabled=INFO
db.logs.query.threshold=0ssystemctl enable neo4j
systemctl start neo4j
# Check status
systemctl status neo4j
# Monitor logs
journalctl -u neo4j -f# Set password before first login
neo4j-admin dbms set-initial-password YourSecurePassword123!
# Or change via cypher-shell (if already running)
cypher-shell -u neo4j -p neo4j
# Then run: ALTER CURRENT USER SET PASSWORD FROM 'neo4j' TO 'YourSecurePassword123!';ufw allow 7474/tcp # HTTP Browser
ufw allow 7473/tcp # HTTPS Browser
ufw allow 7687/tcp # Bolt protocol
ufw reload
ufw statusDocker Installation
curl -fsSL https://get.docker.com | sh
systemctl enable docker
systemctl start dockermkdir -p /opt/neo4j/{data,logs,import,plugins,conf}services:
neo4j:
image: neo4j:5.26.0-community
container_name: neo4j
restart: unless-stopped
ports:
- "7474:7474" # HTTP
- "7473:7473" # HTTPS
- "7687:7687" # Bolt
volumes:
- /opt/neo4j/data:/data
- /opt/neo4j/logs:/logs
- /opt/neo4j/import:/var/lib/neo4j/import
- /opt/neo4j/plugins:/plugins
- /opt/neo4j/conf:/conf
environment:
- NEO4J_AUTH=neo4j/YourSecurePassword123!
- NEO4J_PLUGINS=["apoc"]
- NEO4J_server_memory_heap_initial__size=1G
- NEO4J_server_memory_heap_max__size=1G
- NEO4J_server_memory_pagecache_size=512M
- NEO4J_dbms_security_procedures_unrestricted=apoc.*
- NEO4J_dbms_security_procedures_allowlist=apoc.*
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:7474"]
interval: 30s
timeout: 10s
retries: 5cd /opt/neo4j
docker compose up -d
# Check logs
docker logs -f neo4jAccess Neo4j Browser
Access the web-based Neo4j Browser:
http://your-server-ip:7474- Connect using Bolt URL:
bolt://your-server-ip:7687 - Enter username
neo4jand your password - Click "Connect"
Cypher Query Basics
Create Nodes
CREATE (p:Person {name: 'Alice', age: 30, email: 'alice@example.com'})
RETURN p;
CREATE (p1:Person {name: 'Bob', age: 25}),
(p2:Person {name: 'Charlie', age: 35}),
(c:Company {name: 'TechCorp', founded: 2010});Create Relationships
// Create a relationship between existing nodes
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
CREATE (a)-[:KNOWS {since: 2020}]->(b);
// Create nodes and relationships together
CREATE (a:Person {name: 'Diana'})-[:WORKS_AT {role: 'Engineer'}]->(:Company {name: 'StartupXYZ'});Query Data
// Find all Person nodes
MATCH (p:Person) RETURN p;
// Find people who know each other
MATCH (a:Person)-[:KNOWS]->(b:Person)
RETURN a.name AS Person, b.name AS Knows;
// Find paths between nodes
MATCH path = (a:Person {name: 'Alice'})-[*1..3]-(b:Person {name: 'Charlie'})
RETURN path;
// Count relationships
MATCH (p:Person)-[r:KNOWS]->()
RETURN p.name, count(r) AS connections
ORDER BY connections DESC;Update and Delete
// Update node properties
MATCH (p:Person {name: 'Alice'})
SET p.age = 31, p.updated = datetime();
// Delete a relationship
MATCH (a:Person {name: 'Alice'})-[r:KNOWS]->(b:Person {name: 'Bob'})
DELETE r;
// Delete a node (must delete relationships first)
MATCH (p:Person {name: 'Bob'})
DETACH DELETE p;Install APOC Plugin
APOC (Awesome Procedures on Cypher) extends Neo4j with hundreds of useful procedures and functions.
# Download APOC matching your Neo4j version
cd /var/lib/neo4j/plugins
wget https://github.com/neo4j/apoc/releases/download/5.26.0/apoc-5.26.0-core.jar
chown neo4j:neo4j apoc-5.26.0-core.jardbms.security.procedures.unrestricted=apoc.*
dbms.security.procedures.allowlist=apoc.*systemctl restart neo4j
# In cypher-shell or Neo4j Browser:
RETURN apoc.version();
# List available procedures
CALL apoc.help('');SSL/TLS Configuration
Using Let's Encrypt
apt install -y certbot
certbot certonly --standalone -d neo4j.yourdomain.com# Create certificate directories
mkdir -p /var/lib/neo4j/certificates/bolt/trusted
mkdir -p /var/lib/neo4j/certificates/https/trusted
# Copy certificates
cp /etc/letsencrypt/live/neo4j.yourdomain.com/fullchain.pem /var/lib/neo4j/certificates/bolt/
cp /etc/letsencrypt/live/neo4j.yourdomain.com/privkey.pem /var/lib/neo4j/certificates/bolt/
cp /etc/letsencrypt/live/neo4j.yourdomain.com/fullchain.pem /var/lib/neo4j/certificates/https/
cp /etc/letsencrypt/live/neo4j.yourdomain.com/privkey.pem /var/lib/neo4j/certificates/https/
chown -R neo4j:neo4j /var/lib/neo4j/certificates# Bolt SSL
dbms.ssl.policy.bolt.enabled=true
dbms.ssl.policy.bolt.base_directory=/var/lib/neo4j/certificates/bolt
dbms.ssl.policy.bolt.private_key=privkey.pem
dbms.ssl.policy.bolt.public_certificate=fullchain.pem
server.bolt.tls_level=REQUIRED
# HTTPS SSL
dbms.ssl.policy.https.enabled=true
dbms.ssl.policy.https.base_directory=/var/lib/neo4j/certificates/https
dbms.ssl.policy.https.private_key=privkey.pem
dbms.ssl.policy.https.public_certificate=fullchain.pemSecurity Hardening
Create Additional Users
// Create a read-only user
CREATE USER reader SET PASSWORD 'ReaderPass123!' SET PASSWORD CHANGE NOT REQUIRED;
GRANT ROLE reader TO reader;
// Create a custom role with specific permissions
CREATE ROLE analyst;
GRANT MATCH {*} ON GRAPH * TO analyst;
GRANT TRAVERSE ON GRAPH * TO analyst;
CREATE USER analyst_user SET PASSWORD 'AnalystPass123!' SET PASSWORD CHANGE NOT REQUIRED;
GRANT ROLE analyst TO analyst_user;Restrict Network Access
# In neo4j.conf - bind to localhost only
server.default_listen_address=127.0.0.1
server.bolt.listen_address=127.0.0.1:7687
server.http.listen_address=127.0.0.1:7474Backup and Recovery
# Stop Neo4j for consistent backup
systemctl stop neo4j
neo4j-admin database dump neo4j --to-path=/backup/
systemctl start neo4j#!/bin/bash
BACKUP_DIR="/backup/neo4j"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7
mkdir -p $BACKUP_DIR
# Stop Neo4j for consistent backup
systemctl stop neo4j
# Create backup
neo4j-admin database dump neo4j --to-path=$BACKUP_DIR/neo4j_$DATE.dump
# Start Neo4j
systemctl start neo4j
# Remove old backups
find $BACKUP_DIR -name "*.dump" -mtime +$RETENTION_DAYS -delete
echo "Backup completed: neo4j_$DATE.dump"chmod +x /opt/scripts/neo4j-backup.sh
# Add to crontab (daily at 2 AM)
crontab -e
0 2 * * * /opt/scripts/neo4j-backup.sh >> /var/log/neo4j-backup.log 2>&1systemctl stop neo4j
neo4j-admin database load neo4j --from-path=/backup/neo4j_20250106_020000.dump --overwrite-destination
systemctl start neo4jPerformance Tuning
Index Creation
// Single property index
CREATE INDEX person_name FOR (p:Person) ON (p.name);
// Composite index
CREATE INDEX person_name_age FOR (p:Person) ON (p.name, p.age);
// Full-text search index
CREATE FULLTEXT INDEX personSearch FOR (p:Person) ON EACH [p.name, p.email];
// Check existing indexes
SHOW INDEXES;Query Optimization
// Use EXPLAIN to see query plan
EXPLAIN MATCH (p:Person)-[:KNOWS]->(f) RETURN p, f;
// Use PROFILE to see actual execution metrics
PROFILE MATCH (p:Person)-[:KNOWS]->(f) RETURN p, f;Monitoring
// Database information
CALL dbms.listConfig() YIELD name, value WHERE name CONTAINS 'memory';
// Current connections
CALL dbms.listConnections();
// Running queries
CALL dbms.listQueries();
// Kill a long-running query
CALL dbms.killQuery('query-id');# Main Neo4j logs
tail -f /var/lib/neo4j/logs/neo4j.log
# Query logs
tail -f /var/lib/neo4j/logs/query.logserver.metrics.enabled=true
server.metrics.prometheus.enabled=true
server.metrics.prometheus.endpoint=localhost:2004Troubleshooting
Neo4j Won't Start
journalctl -u neo4j -n 100
tail -100 /var/lib/neo4j/logs/neo4j.logCommon Issues
- Insufficient memory: Reduce heap and page cache sizes
- Port conflicts: Check if ports 7474, 7473, 7687 are in use
- Permission issues: Ensure neo4j user owns data directories
Connection Refused
- Verify Neo4j is running:
systemctl status neo4j - Check listen addresses in configuration
- Verify firewall rules allow the ports
- Test local connection:
cypher-shell -a bolt://localhost:7687
Slow Queries
- Check for missing indexes on frequently queried properties
- Use PROFILE to identify bottlenecks
- Verify adequate memory allocation
- Review query patterns for full graph scans
Deployment Complete!
You now have a fully functional Neo4j graph database running on your RamNode VPS. This setup provides a solid foundation for building graph-powered applications, from social networks to recommendation engines.
