Neo4j Community Edition 5.x (Amazon Linux 2023) AMI Administrator Guide
1. Quick Start Information
Connection Methods:
- Access the instance via SSH using the
ec2-useruser. Usesudoto run commands requiring root privileges. To switch to the root user, usesudo su - root.
Install Information:
- OS: Amazon Linux 2023
- Neo4j edition: Community Edition 5.x
- Java: Amazon Corretto 17 (AWS-optimized OpenJDK 17)
- Web UI:
http://YOUR_PUBLIC_IP:7474 - Bolt endpoint:
bolt://YOUR_PUBLIC_IP:7687 - Config file:
/etc/neo4j/neo4j.conf - Data directory:
/var/lib/neo4j/data - Log directory:
/var/log/neo4j/
Default Credentials:
- Username:
neo4j - Password: Your AWS Instance ID (e.g.,
i-0abc123def456789) - How to find: Read the file
/home/ec2-user/readmeafter the instance starts
cat /home/ec2-user/readme
Neo4j Service Management:
- Start Neo4j:
sudo systemctl start neo4j - Stop Neo4j:
sudo systemctl stop neo4j - Restart Neo4j:
sudo systemctl restart neo4j - Check status:
sudo systemctl status neo4j - Enable auto-start:
sudo systemctl enable neo4j
Required Ports (Security Group):
| Port | Protocol | Purpose | Required |
|---|---|---|---|
| 22 | TCP | SSH access | Yes |
| 7474 | TCP | Neo4j Web Browser (HTTP) | Yes |
| 7687 | TCP | Bolt protocol (drivers/code) | Yes |
| 7473 | TCP | Neo4j Web Browser (HTTPS) | Optional |
2. First Launch & Verification
Step 1: Configure Security Group
Before accessing Neo4j, open the required ports in your AWS EC2 security group:
- Go to EC2 Console → Security Groups
- Select the security group attached to your instance
- Add inbound rules:
- Port 7474 (TCP) — Neo4j Web Browser
- Port 7687 (TCP) — Bolt Protocol
- Source: Your IP or
0.0.0.0/0(for public access)
Step 2: Retrieve Your Credentials
Connect via SSH and read the auto-generated credentials file:
ssh -i your-key.pem ec2-user@YOUR_PUBLIC_IP
cat /home/ec2-user/readme
Expected Output:
========================================================================
Neo4j Credentials (Auto-configured)
========================================================================
Login URL: http://YOUR_PUBLIC_IP:7474
Username : neo4j
Password : i-0abc123def456789
(This is your AWS Instance ID)
========================================================================
Note: The password initialization script runs automatically on first boot via cloud-init. It may take 1–2 minutes after launch for the readme file to appear and Neo4j to be fully ready.
Step 3: Access the Neo4j Browser
Open a web browser and navigate to:
http://YOUR_PUBLIC_IP:7474
You will see the Neo4j Browser login page.
Step 4: Log In
Enter your credentials:
- Username:
neo4j - Password: Your AWS Instance ID (from
~/readme)
After successful login, you will be connected to the Neo4j database and can start running Cypher queries.
Step 5: Verify Neo4j is Running
Check service status via SSH:
sudo systemctl status neo4j --no-pager
Expected Output:
● neo4j.service - Neo4j Graph Database
Loaded: loaded (/usr/lib/systemd/system/neo4j.service; enabled; ...)
Active: active (running) since ...
Run a test Cypher query via cypher-shell:
cypher-shell -u neo4j -p YOUR_INSTANCE_ID "RETURN 'Neo4j is working!' AS message;"
Expected Output:
message
"Neo4j is working!"
3. Architecture & Detailed Configuration
This AMI runs Neo4j Community Edition 5.x on Amazon Linux 2023, with a secure auto-credential system that sets each instance's password to its unique AWS Instance ID on first boot.
Deployment Architecture:
[Amazon Corretto 17]
↓
[Neo4j Community Edition 5.x]
/etc/neo4j/neo4j.conf → configuration (remote access enabled)
/var/lib/neo4j/data/ → graph database storage
/var/log/neo4j/ → logs
↓
[Systemd Service]
neo4j.service → Auto-start on boot
↓
[Cloud-Init (per-instance, first boot only)]
/var/lib/cloud/scripts/per-instance/set_neo4j_password.sh
↓
[Password = AWS Instance ID]
↓
[README at /home/ec2-user/readme]
Login URL + credentials for the customer
Key Design Decisions:
- Password = Instance ID: Each deployed instance has a unique, cryptographically distinct password — no shared credentials across instances
- Cloud-init per-instance: The password script runs exactly once per instance lifecycle, not on every reboot
- IMDSv2 support: The script uses the secure token-based metadata API (IMDSv2) with fallback to IMDSv1
- 15-minute retry loop: Neo4j 5.x takes time to initialize on first boot — the script retries for up to 15 minutes before timing out
- Fallback password: If Instance ID cannot be retrieved, a random hex string is used as a fallback
- Remote access enabled:
server.default_listen_address=0.0.0.0configured so customers can access the web UI immediately
3.1. Neo4j Configuration File
File Location: /etc/neo4j/neo4j.conf
Key Modified Setting:
# Allow connections from any IP address (required for remote web UI access)
server.default_listen_address=0.0.0.0
How This Works:
By default, Neo4j binds only to localhost, making it inaccessible from outside the server. Setting server.default_listen_address=0.0.0.0 tells Neo4j to listen on all network interfaces, allowing customers to connect via browser or Bolt drivers from their machines.
Access control is enforced through:
- AWS Security Groups (firewall — only open ports 7474 and 7687)
- Neo4j authentication (username + password required)
3.2. Password Initialization Script
File Location: /opt/neo4j/init_password.sh
Complete Contents:
#!/bin/bash
# /opt/neo4j/init_password.sh
# Purpose: Auto-set Neo4j password to AWS Instance ID on first boot (AL2023)
# Logic: V5 High Availability (15min timeout) + Simple README format.
LOG_FILE="/var/log/neo4j_init.log"
echo "Starting Neo4j password initialization..." > "$LOG_FILE"
# --- 1. Retrieve AWS Instance ID ---
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" -s)
if [ -z "$TOKEN" ]; then
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
else
INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id)
fi
if [ -z "$INSTANCE_ID" ]; then
INSTANCE_ID=$(openssl rand -hex 8)
fi
echo "Target Password: $INSTANCE_ID" >> "$LOG_FILE"
# --- 2. Change Password Loop (15 min timeout) ---
MAX_RETRIES=300
COUNT=0
SUCCESS=0
echo "Attempting to set password on 'system' database..." >> "$LOG_FILE"
while [ $COUNT -lt $MAX_RETRIES ]; do
# Try to change password using 'ALTER CURRENT USER'
echo "ALTER CURRENT USER SET PASSWORD FROM 'neo4j' TO '$INSTANCE_ID';" | cypher-shell -u neo4j -p neo4j -d system >> "$LOG_FILE" 2>&1
if [ $? -eq 0 ]; then
echo "Success: Password changed." >> "$LOG_FILE"
SUCCESS=1
break
else
# Wait 3 seconds and retry
sleep 3
let COUNT=COUNT+1
fi
done
if [ $SUCCESS -eq 0 ]; then
echo "Error: Timed out after 15 minutes." >> "$LOG_FILE"
exit 1
fi
# --- 3. Generate README (Simple Format) ---
PUBLIC_IP=$(curl -s http://checkip.amazonaws.com || echo "<Your-Public-IP>")
cat > /home/ec2-user/readme <<EOF
========================================================================
Neo4j Credentials (Auto-configured)
========================================================================
Login URL: http://${PUBLIC_IP}:7474
Username : neo4j
Password : $INSTANCE_ID
(This is your AWS Instance ID)
========================================================================
EOF
chown ec2-user:ec2-user /home/ec2-user/readme
chmod 644 /home/ec2-user/readme
How This Works:
- IMDSv2 token: Uses the secure AWS metadata API (IMDSv2) with a 6-hour token; falls back to IMDSv1 if the token request fails
- Instance ID as password: Each EC2 instance has a globally unique Instance ID — using it as the password means no two instances share the same credentials
- Retry loop: Neo4j 5.x requires the
systemdatabase to be fully initialized before accepting password changes. The loop retries every 3 seconds for up to 15 minutes (300 × 3s) cypher-shell -d system: Password changes in Neo4j 5.x must target thesystemdatabase explicitly- README generation: After success, creates a human-readable credentials file owned by
ec2-user
3.3. Cloud-Init Deployment
Script Location: /var/lib/cloud/scripts/per-instance/set_neo4j_password.sh
This is a symlink/copy of the initialization script placed in cloud-init's per-instance directory.
How Cloud-Init Works:
- Scripts in
/var/lib/cloud/scripts/per-instance/run exactly once per instance — on first boot after launch - They do NOT run on subsequent reboots (unlike
per-bootscripts) - This ensures the password is set once when a customer first launches the AMI, not reset on every restart
Cloud-Init Execution Timeline:
Instance launches (first boot)
↓
cloud-init starts
↓
Neo4j systemd service starts (auto-start)
↓
set_neo4j_password.sh runs (per-instance)
↓
Neo4j initializes system database (~10-20 seconds)
↓
Script successfully changes password
↓
/home/ec2-user/readme created with credentials
↓
Customer reads readme → logs in to Neo4j Browser
4. How-To-Create: Reproduce This Environment
This section explains exactly how this AMI was built.
Step 1: Update System and Install Java 17
sudo dnf update -y
sudo dnf install java-17-amazon-corretto-devel -y
Verify:
java -version
Expected Output:
openjdk version "17.0.x" 2024-xx-xx LTS
OpenJDK Runtime Environment Corretto-17.x.x.x (build 17.0.x+x-LTS)
Step 2: Add Neo4j Official Repository
Import the GPG key:
sudo rpm --import https://debian.neo4j.com/neotechnology.gpg.key
Create the repository file:
sudo tee /etc/yum.repos.d/neo4j.repo > /dev/null << 'EOF'
[neo4j]
name=Neo4j RPM Repository
baseurl=https://yum.neo4j.com/stable/5
enabled=1
gpgcheck=1
EOF
How This Works:
rpm --import: Registers Neo4j's GPG signing key so packages can be verified- The repo points to
yum.neo4j.com/stable/5— the official Neo4j 5.x RPM channel gpgcheck=1: Ensures every package is verified against the imported key
Step 3: Install Neo4j
sudo dnf install neo4j -y
This installs:
neo4jserver binarycypher-shellCLI tool- Default configuration at
/etc/neo4j/neo4j.conf - Systemd service unit
- Data and log directories
Step 4: Enable Remote Access
sudo sed -i 's/#server.default_listen_address=0.0.0.0/server.default_listen_address=0.0.0.0/' /etc/neo4j/neo4j.conf
Verify:
grep "server.default_listen_address" /etc/neo4j/neo4j.conf
Expected Output:
server.default_listen_address=0.0.0.0
Step 5: Start Neo4j and Verify
sudo systemctl enable --now neo4j
sudo systemctl status neo4j --no-pager
Wait 10–20 seconds for the first-time database initialization to complete.
Step 6: Create the Password Initialization Script
sudo mkdir -p /opt/neo4j
sudo tee /opt/neo4j/init_password.sh > /dev/null << 'SCRIPT'
#!/bin/bash
LOG_FILE="/var/log/neo4j_init.log"
echo "Starting Neo4j password initialization..." > "$LOG_FILE"
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" -s)
if [ -z "$TOKEN" ]; then
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
else
INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id)
fi
if [ -z "$INSTANCE_ID" ]; then
INSTANCE_ID=$(openssl rand -hex 8)
fi
echo "Target Password: $INSTANCE_ID" >> "$LOG_FILE"
MAX_RETRIES=300
COUNT=0
SUCCESS=0
echo "Attempting to set password on 'system' database..." >> "$LOG_FILE"
while [ $COUNT -lt $MAX_RETRIES ]; do
echo "ALTER CURRENT USER SET PASSWORD FROM 'neo4j' TO '$INSTANCE_ID';" | cypher-shell -u neo4j -p neo4j -d system >> "$LOG_FILE" 2>&1
if [ $? -eq 0 ]; then
echo "Success: Password changed." >> "$LOG_FILE"
SUCCESS=1
break
else
sleep 3
let COUNT=COUNT+1
fi
done
if [ $SUCCESS -eq 0 ]; then
echo "Error: Timed out after 15 minutes." >> "$LOG_FILE"
exit 1
fi
PUBLIC_IP=$(curl -s http://checkip.amazonaws.com || echo "<Your-Public-IP>")
cat > /home/ec2-user/readme <<EOF
========================================================================
Neo4j Credentials (Auto-configured)
========================================================================
Login URL: http://${PUBLIC_IP}:7474
Username : neo4j
Password : $INSTANCE_ID
(This is your AWS Instance ID)
========================================================================
EOF
chown ec2-user:ec2-user /home/ec2-user/readme
chmod 644 /home/ec2-user/readme
SCRIPT
sudo chmod +x /opt/neo4j/init_password.sh
Step 7: Deploy to Cloud-Init and Clean Up for AMI
# Stop Neo4j
sudo systemctl stop neo4j
# Reset database to default state (removes any test data and resets password to 'neo4j')
sudo rm -rf /var/lib/neo4j/data/dbms/auth
sudo rm -rf /var/lib/neo4j/data/databases/system
sudo rm -rf /var/lib/neo4j/data/transactions/system
# Fix ownership
sudo chown -R neo4j:neo4j /var/lib/neo4j/data
# Register the script with cloud-init
sudo mkdir -p /var/lib/cloud/scripts/per-instance
sudo cp /opt/neo4j/init_password.sh /var/lib/cloud/scripts/per-instance/set_neo4j_password.sh
sudo chmod +x /var/lib/cloud/scripts/per-instance/set_neo4j_password.sh
# Clean cloud-init state so it runs fresh on next launch
sudo systemctl stop cloud-init
sudo cloud-init clean --logs
# Remove instance-specific files
sudo rm -f /home/ec2-user/readme
sudo rm -f /var/log/neo4j_init.log
# Reset machine ID (important for AMI uniqueness)
sudo rm -f /etc/machine-id && sudo touch /etc/machine-id
How This Works:
- Removing
data/dbms/authdeletes the stored password hash — Neo4j will use the defaultneo4j/neo4jon next start - Removing
data/databases/systemanddata/transactions/systemforces Neo4j to reinitialize the system database on next boot — required for the password change script to work cloud-init clean --logsresets cloud-init's "already run" marker so the per-instance script executes on the next instance launch- Removing
/etc/machine-idensures each launched instance gets a unique system ID
5. Credentials and Security
How Credentials Work
| Phase | Details |
|---|---|
| AMI state | Default neo4j/neo4j password (reset during AMI prep) |
| First boot | cloud-init runs set_neo4j_password.sh |
| After ~1-2 min | Password changed to Instance ID; ~/readme created |
| Customer access | Reads ~/readme, logs in with Instance ID as password |
Retrieve Your Password
cat /home/ec2-user/readme
Or directly find your Instance ID:
# From inside the instance
curl -s http://169.254.169.254/latest/meta-data/instance-id
# Or from AWS CLI (outside the instance)
aws ec2 describe-instances --instance-ids YOUR_INSTANCE_ID --query 'Reservations[0].Instances[0].InstanceId'
Change Your Password
After logging in to the Neo4j Browser, go to the top-right user menu and select Change Password, or use cypher-shell:
cypher-shell -u neo4j -p YOUR_INSTANCE_ID -d system \
"ALTER CURRENT USER SET PASSWORD FROM 'YOUR_INSTANCE_ID' TO 'NewStrongPassword!';"
Security Recommendations
- Change the default password after first login — do not keep the Instance ID as a permanent password
- Restrict security group access — limit port 7474 and 7687 to trusted IP ranges rather than
0.0.0.0/0 - Use HTTPS — configure Neo4j with an SSL certificate and use port 7473 for production
- Enable Neo4j authentication — authentication is enabled by default; do not disable
dbms.security.auth_enabled
6. Using Neo4j
6.1. Neo4j Browser (Web UI)
Access at http://YOUR_PUBLIC_IP:7474
The Neo4j Browser provides:
- Interactive Cypher query editor
- Visual graph visualization
- Schema explorer
- Query history
6.2. Cypher Queries (Getting Started)
Connect via cypher-shell:
cypher-shell -u neo4j -p YOUR_PASSWORD
Create nodes:
CREATE (:Person {name: 'Alice', age: 30});
CREATE (:Person {name: 'Bob', age: 25});
Create relationships:
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
CREATE (a)-[:KNOWS]->(b);
Query the graph:
MATCH (p:Person)-[:KNOWS]->(q:Person)
RETURN p.name, q.name;
Count nodes:
MATCH (n) RETURN count(n);
6.3. Connecting with Drivers
Python (neo4j driver):
from neo4j import GraphDatabase
driver = GraphDatabase.driver(
"bolt://YOUR_PUBLIC_IP:7687",
auth=("neo4j", "YOUR_PASSWORD")
)
with driver.session() as session:
result = session.run("RETURN 'Hello, Neo4j!' AS message")
print(result.single()["message"])
driver.close()
JavaScript (neo4j-driver):
const neo4j = require('neo4j-driver');
const driver = neo4j.driver(
'bolt://YOUR_PUBLIC_IP:7687',
neo4j.auth.basic('neo4j', 'YOUR_PASSWORD')
);
const session = driver.session();
session.run("RETURN 'Hello!' AS msg")
.then(result => console.log(result.records[0].get('msg')))
.finally(() => driver.close());
7. Important File Locations
| File Path | Purpose |
|---|---|
/etc/neo4j/neo4j.conf | Main Neo4j configuration file |
/var/lib/neo4j/data/ | Graph database data directory |
/var/log/neo4j/ | Neo4j log files |
/var/log/neo4j/neo4j.log | Main application log |
/var/log/neo4j/debug.log | Detailed debug log |
/opt/neo4j/init_password.sh | Password initialization script |
/var/lib/cloud/scripts/per-instance/set_neo4j_password.sh | Cloud-init deployment of init script |
/var/log/neo4j_init.log | Password initialization log |
/home/ec2-user/readme | Auto-generated credentials file |
/etc/yum.repos.d/neo4j.repo | Neo4j RPM repository configuration |
/usr/bin/cypher-shell | Neo4j command-line query tool |
/usr/lib/systemd/system/neo4j.service | Systemd service file |
8. Troubleshooting
Issue 1: ~/readme File Not Found After Launch
Symptoms:
$ cat /home/ec2-user/readme
cat: /home/ec2-user/readme: No such file or directory
Cause:
The password initialization script is still running — Neo4j needs 1–2 minutes to fully start and accept password changes.
Solution:
Wait 2 minutes and check the initialization log:
cat /var/log/neo4j_init.log
If the script is still running, you will see retry attempts. Wait for Success: Password changed.
Issue 2: Cannot Access Neo4j Browser
Symptoms:
Browser shows "Connection refused" or times out on http://YOUR_IP:7474.
Diagnosis:
Check Neo4j is running:
sudo systemctl status neo4j
Check port is listening:
sudo ss -tlnp | grep 7474
Solutions:
- Verify port 7474 is open in your AWS security group
- Start Neo4j if not running:
sudo systemctl start neo4j - Check logs for errors:
sudo tail -50 /var/log/neo4j/neo4j.log
Issue 3: Login Fails with Correct Password
Symptoms:
Neo4j Browser shows "Invalid username or password" even with the Instance ID.
Diagnosis:
Check initialization log:
cat /var/log/neo4j_init.log
Solution:
If the script failed (shows "Error: Timed out"), run it manually:
sudo bash /opt/neo4j/init_password.sh
Then read the newly generated readme:
cat /home/ec2-user/readme
Issue 4: Neo4j Service Fails to Start
Symptoms:
$ sudo systemctl status neo4j
Active: failed
Diagnosis:
sudo journalctl -u neo4j -n 50 --no-pager
sudo tail -50 /var/log/neo4j/neo4j.log
Common Causes:
- Java not found or wrong version:
java -version
Ensure it shows Corretto-17. If not, reinstall:
sudo dnf install java-17-amazon-corretto-devel -y
- Port already in use:
sudo lsof -i :7474
sudo lsof -i :7687
- Data directory permission issue:
sudo chown -R neo4j:neo4j /var/lib/neo4j/
sudo chown -R neo4j:neo4j /var/log/neo4j/
sudo systemctl start neo4j
Issue 5: Forgot Password
Solution:
Stop Neo4j, reset the auth database, and let cloud-init set a new password:
sudo systemctl stop neo4j
sudo rm -rf /var/lib/neo4j/data/dbms/auth
sudo rm -rf /var/lib/neo4j/data/databases/system
sudo rm -rf /var/lib/neo4j/data/transactions/system
sudo chown -R neo4j:neo4j /var/lib/neo4j/data
sudo rm -f /home/ec2-user/readme
sudo systemctl start neo4j
sudo bash /opt/neo4j/init_password.sh
cat /home/ec2-user/readme
9. Final Notes
Key Takeaways
- Neo4j Community Edition 5.x running on Amazon Linux 2023 with Java 17 (Corretto)
- Password = AWS Instance ID — unique per instance, auto-configured on first boot
- Read
~/readmefor credentials immediately after launch - Open ports 7474 and 7687 in your security group to access the web UI and Bolt protocol
- The installation is production-ready and AMI-optimized
Neo4j Use Cases
- Knowledge Graphs: Connect entities and relationships for AI/ML applications
- Fraud Detection: Trace transaction networks and suspicious patterns
- Recommendation Engines: "Customers who bought X also bought Y"
- Network & IT Operations: Map infrastructure dependencies
- Social Networks: Model user connections and communities
Recommended Instance Types
| Workload | Instance | Reason |
|---|---|---|
| Development / Testing | t3.medium | 2 vCPU, 4GB RAM minimum for Neo4j |
| Small production | t3.large | 8GB RAM, good for moderate graphs |
| Medium production | m5.xlarge | 16GB RAM, better for large datasets |
| Analytics workloads | r5.xlarge+ | Memory-optimized for large graphs |
Note: Neo4j Community Edition requires at least 2GB RAM. t3.small (2GB) is the absolute minimum; t3.medium (4GB) is recommended for comfortable operation.
Additional Resources
- Neo4j Documentation: https://neo4j.com/docs/
- Cypher Query Language: https://neo4j.com/docs/cypher-manual/current/
- Neo4j Browser Guide: https://neo4j.com/docs/browser-manual/current/
- Neo4j Drivers: https://neo4j.com/docs/create-applications/
For support or questions, please contact the Easycloud team.