Skip to main content

Overview

Graph Node can be installed in several ways depending on your use case:
  • Docker (Recommended): Best for subgraph developers testing locally
  • Docker with existing services: When you already have IPFS and PostgreSQL
  • From source: For contributors and advanced users who need to modify Graph Node
Most subgraph developers should use the Quickstart guide which covers Docker setup. This page provides comprehensive installation details for all methods.
The easiest way to get started with Graph Node is using the pre-configured Docker Compose setup.

Prerequisites

  • Docker 20.10+ and Docker Compose v2.0+
  • An Ethereum RPC endpoint (Infura, Alchemy, or local node)
  • 8GB+ RAM (16GB recommended for Apple Silicon)
  • 20GB+ free disk space

Installation Steps

1

Clone the repository

git clone https://github.com/graphprotocol/graph-node.git
cd graph-node/docker
2

Configure Ethereum connection

Edit docker-compose.yml and update the ethereum environment variable:
environment:
  postgres_host: postgres
  postgres_user: graph-node
  postgres_pass: let-me-in
  postgres_db: graph-node
  ipfs: 'ipfs:5001'
  ethereum: 'mainnet:http://host.docker.internal:8545'
  GRAPH_LOG: info
Replace http://host.docker.internal:8545 with your Ethereum node URL.
3

Start the services

docker-compose up
For production, use detached mode:
docker-compose up -d
4

Verify installation

Check that all services are running:
docker-compose ps
Test the GraphQL endpoint:
curl http://localhost:8000/

Docker Compose Configuration

The docker-compose.yml file defines three services:

Graph Node

graph-node:
  image: graphprotocol/graph-node
  ports:
    - '8000:8000'  # GraphQL HTTP
    - '8001:8001'  # GraphQL WebSocket
    - '8020:8020'  # Admin/Deploy
    - '8030:8030'  # Index node server
    - '8040:8040'  # Metrics
  depends_on:
    - ipfs
    - postgres

IPFS

ipfs:
  image: ipfs/kubo:v0.17.0
  ports:
    - '5001:5001'
  volumes:
    - ./data/ipfs:/data/ipfs:Z

PostgreSQL

postgres:
  image: postgres
  ports:
    - '5432:5432'
  command:
    [
      "postgres",
      "-cshared_preload_libraries=pg_stat_statements",
      "-cmax_connections=200"
    ]
  environment:
    POSTGRES_USER: graph-node
    POSTGRES_PASSWORD: let-me-in
    POSTGRES_DB: graph-node
    POSTGRES_INITDB_ARGS: "-E UTF8 --locale=C"
  volumes:
    - ./data/postgres:/var/lib/postgresql/data:Z

Data Persistence

Docker Compose stores data in ./data/ with two subdirectories:
  • ./data/ipfs - IPFS blocks and metadata
  • ./data/postgres - PostgreSQL database files
These persist across container restarts. To completely reset:
docker-compose down -v
rm -rf data/
docker-compose up

Method 2: Docker with Existing Services

If you already have IPFS and PostgreSQL running, you can run only the Graph Node container.

Prerequisites

  • PostgreSQL 12+ with the following extensions:
    • pg_trgm
    • btree_gist
    • postgres_fdw
  • IPFS (Kubo) running and accessible
  • Ethereum RPC endpoint

Running Graph Node

docker run -it \
  -p 8000:8000 \
  -p 8001:8001 \
  -p 8020:8020 \
  -p 8030:8030 \
  -p 8040:8040 \
  -e postgres_host=<POSTGRES_HOST> \
  -e postgres_port=5432 \
  -e postgres_user=<USER> \
  -e postgres_pass=<PASSWORD> \
  -e postgres_db=<DBNAME> \
  -e ipfs=<IPFS_HOST>:5001 \
  -e ethereum=mainnet:https://mainnet.infura.io/v3/YOUR_KEY \
  -e GRAPH_LOG=info \
  graphprotocol/graph-node:latest
For Linux hosts connecting to services on the host machine, use --network="host" or your machine’s IP address instead of localhost.

Docker Environment Variables

VariableDescriptionExample
postgres_hostPostgreSQL hostnamepostgres or 192.168.1.100
postgres_portPostgreSQL port5432
postgres_userDatabase usergraph-node
postgres_passDatabase passwordsecure-password
postgres_dbDatabase namegraph-node
ipfsIPFS API endpoint127.0.0.1:5001
ethereumNetwork and RPC URLmainnet:https://...
GRAPH_LOGLog levelinfo, debug, trace

Method 3: Building from Source

Building from source is necessary for Graph Node contributors or when you need to modify the code.

Prerequisites

  • OS: Linux, macOS, or Windows (WSL2)
  • RAM: 8GB minimum, 16GB recommended
  • Disk: 20GB+ free space
  • CPU: Multi-core processor recommended

Step 1: Install Rust

Graph Node requires the latest stable Rust compiler:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env

# Install stable toolchain
rustup install stable
Verify installation:
rustc --version
cargo --version

Step 2: Install PostgreSQL

sudo apt update
sudo apt install postgresql postgresql-contrib libpq-dev
sudo systemctl start postgresql
sudo systemctl enable postgresql

Step 3: Configure PostgreSQL

Create a database user and database for Graph Node:
# Connect as superuser (usually 'postgres' or your username)
psql -U postgres <<EOF
create user graph with password 'your-password-here';
create database "graph-node" with owner=graph template=template0 encoding='UTF8' locale='C';
\c graph-node
create extension pg_trgm;
create extension btree_gist;
create extension postgres_fdw;
grant usage on foreign data wrapper postgres_fdw to graph;
EOF
On macOS with Postgres.app, use your username instead of postgres. On fresh Linux installations, you may need to sudo -u postgres psql.
Set the database connection string as an environment variable:
export POSTGRES_URL=postgresql://graph:your-password-here@localhost:5432/graph-node

# Add to ~/.bashrc or ~/.zshrc for persistence
echo 'export POSTGRES_URL=postgresql://graph:your-password-here@localhost:5432/graph-node' >> ~/.bashrc
Test the connection:
psql $POSTGRES_URL -c "SELECT version();"

Step 4: Install IPFS

wget https://dist.ipfs.tech/kubo/v0.17.0/kubo_v0.17.0_linux-amd64.tar.gz
tar -xvzf kubo_v0.17.0_linux-amd64.tar.gz
cd kubo
sudo bash install.sh
ipfs init
ipfs daemon &
Verify IPFS is running:
curl http://localhost:5001/api/v0/version

Step 5: Install Protobuf Compiler

sudo apt install protobuf-compiler
Verify installation:
protoc --version

Step 6: Clone and Build Graph Node

1

Clone the repository

git clone https://github.com/graphprotocol/graph-node.git
cd graph-node
2

Install Rust dependencies

rustup install stable
3

Build Graph Node

cargo build --release
The first build can take 15-30 minutes and requires significant disk space (~10GB for build artifacts).
4

Verify the build

./target/release/graph-node --version

Step 7: Run Graph Node

Start Graph Node with your configuration:
export GRAPH_LOG=debug
export POSTGRES_URL=postgresql://graph:your-password@localhost:5432/graph-node

./target/release/graph-node \
  --postgres-url $POSTGRES_URL \
  --ethereum-rpc mainnet:https://mainnet.infura.io/v3/YOUR_PROJECT_ID \
  --ipfs 127.0.0.1:5001
Graph Node will print the ports it’s listening on when it starts. The GraphQL HTTP server defaults to http://localhost:8000.

Ethereum RPC Configuration

The --ethereum-rpc argument format is:
NETWORK_NAME:[CAPABILITIES]:URL
Examples:
--ethereum-rpc mainnet:https://mainnet.infura.io/v3/YOUR_KEY
Provider Capabilities:
  • archive: Full historical state (required for many subgraphs)
  • traces: Supports debug_traceBlockByNumber (for call handlers)
  • No capabilities: Regular full node

Running as a System Service

For production deployments, run Graph Node as a systemd service:
/etc/systemd/system/graph-node.service
[Unit]
Description=Graph Node
After=network.target postgresql.service
Requires=postgresql.service

[Service]
Type=simple
User=graph
WorkingDirectory=/opt/graph-node
Environment="POSTGRES_URL=postgresql://graph:password@localhost:5432/graph-node"
Environment="GRAPH_LOG=info"
ExecStart=/opt/graph-node/target/release/graph-node \
  --postgres-url $POSTGRES_URL \
  --ethereum-rpc mainnet:https://mainnet.infura.io/v3/YOUR_KEY \
  --ipfs 127.0.0.1:5001
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable graph-node
sudo systemctl start graph-node
sudo systemctl status graph-node
View logs:
sudo journalctl -u graph-node -f

Advanced Configuration

Using a Configuration File

For complex setups (multiple chains, database sharding, multiple nodes), use a TOML configuration file:
config.toml
[store]
[store.primary]
connection = "postgresql://graph:password@localhost:5432/graph-node"
pool_size = 10

[chains]
ingestor = "block_ingestor_node"

[chains.mainnet]
shard = "primary"
provider = [
  { label = "mainnet", url = "https://mainnet.infura.io/v3/YOUR_KEY", features = ["archive", "traces"] }
]

[chains.sepolia]
shard = "primary"
provider = [
  { label = "sepolia", url = "https://sepolia.infura.io/v3/YOUR_KEY", features = [] }
]

[deployment]
[[deployment.rule]]
indexers = [ "index_node_0" ]
Run with config file:
graph-node --config config.toml --node-id index_node_0
See the Configuration page for complete details.

Environment Variables

Graph Node behavior can be tuned with environment variables:
# Logging
export GRAPH_LOG=info  # error, warn, info, debug, trace

# Ethereum
export ETHEREUM_POLLING_INTERVAL=500  # ms
export ETHEREUM_REORG_THRESHOLD=250   # blocks

# IPFS
export GRAPH_IPFS_TIMEOUT=60  # seconds

# GraphQL
export GRAPH_GRAPHQL_QUERY_TIMEOUT=300        # seconds
export GRAPH_GRAPHQL_MAX_COMPLEXITY=10000000
export GRAPH_GRAPHQL_MAX_FIRST=1000

# Database
export STORE_CONNECTION_POOL_SIZE=10

Monitoring and Metrics

Graph Node exposes Prometheus metrics on port 8040:
curl http://localhost:8040/metrics
Common metrics:
  • deployment_sync_progress - Sync progress per subgraph
  • ethereum_chain_head_number - Latest block number
  • query_execution_time - Query performance

Verifying Installation

Test your Graph Node installation:
1

Check GraphQL endpoint

curl http://localhost:8000/
Should return the GraphiQL interface HTML.
2

Check available subgraphs

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"query": "{ indexingStatuses { subgraph chains { network } } }"}' \
  http://localhost:8000/graphql
3

Verify Ethereum connection

Check the logs for:
Connected to Ethereum node at ...
Starting block ingestor
4

Test IPFS

curl http://localhost:5001/api/v0/version
5

Test PostgreSQL

psql $POSTGRES_URL -c "SELECT COUNT(*) FROM subgraphs.subgraph;"

Troubleshooting

Solution: Install build essentials
# Ubuntu/Debian
sudo apt install build-essential

# macOS
xcode-select --install

# Fedora/RHEL
sudo dnf groupinstall "Development Tools"
Symptoms: ERROR: could not open extension control fileSolution: Install PostgreSQL contrib package
# Ubuntu/Debian
sudo apt install postgresql-contrib

# macOS with Homebrew
# Extensions are included by default

# Fedora/RHEL
sudo dnf install postgresql-contrib
Then reconnect and create extensions.
Symptoms: Connection refused on port 5001Solutions:
# Check if IPFS is installed
ipfs version

# Initialize if needed
ipfs init

# Start daemon
ipfs daemon

# Check if port is in use
lsof -i :5001
Symptoms: Build process killed or panicsSolutions:
  • Increase swap space
  • Use cargo build --release -j 2 to limit parallel jobs
  • Build on a machine with more RAM
  • Use pre-built Docker images instead
Common causes:
  1. Database migration fails: Check PostgreSQL logs
  2. Can’t connect to Ethereum: Verify RPC URL
  3. IPFS unreachable: Ensure IPFS daemon is running
  4. Port already in use: Check if another instance is running
# Check for existing Graph Node process
ps aux | grep graph-node

# Check port usage
lsof -i :8000
lsof -i :8001
lsof -i :8020
Symptoms: ERROR: could not load library... postgres_fdwSolution: This usually means PostgreSQL development files are missing:
# Ubuntu/Debian
sudo apt install postgresql-server-dev-14  # Match your PG version

# macOS
brew reinstall postgresql

# Then reconnect and create the extension

Platform-Specific Notes

macOS

  • Use Postgres.app for the easiest PostgreSQL setup
  • Homebrew installs work well for all dependencies
  • Apple Silicon users should expect longer build times
  • Graph Node Docker images are x86_64 only; build locally for ARM64

Linux

  • Prefer system package managers for dependencies
  • On host.docker.internal doesn’t work; use 172.17.0.1 or --network="host"
  • Ensure PostgreSQL accepts local connections in pg_hba.conf
  • Increase file descriptor limits for production: ulimit -n 65536

Windows (WSL2)

  • All development should occur within WSL2, not native Windows
  • Use Ubuntu 20.04+ or Debian for best compatibility
  • Docker Desktop integration with WSL2 works well
  • PostgreSQL should run inside WSL2, not as Windows service

Performance Tuning

PostgreSQL Configuration

For production, tune PostgreSQL settings in postgresql.conf:
# Memory
shared_buffers = 4GB                # 25% of RAM
effective_cache_size = 12GB         # 75% of RAM
work_mem = 256MB
maintenance_work_mem = 1GB

# Connections
max_connections = 200

# Query planner
random_page_cost = 1.1              # SSD: 1.1, HDD: 4.0
effective_io_concurrency = 200      # SSD: 200, HDD: 2

# Logging
shared_preload_libraries = 'pg_stat_statements'
log_min_duration_statement = 1000   # Log slow queries > 1s
Restart PostgreSQL after changes:
sudo systemctl restart postgresql

Graph Node Optimization

# Connection pooling
export STORE_CONNECTION_POOL_SIZE=25

# Ethereum batch size
export ETHEREUM_BLOCK_BATCH_SIZE=10

# Query limits
export GRAPH_GRAPHQL_MAX_COMPLEXITY=100000000
export GRAPH_GRAPHQL_MAX_FIRST=1000

# Disable features you don't need
export DISABLE_BLOCK_INGESTOR=false  # Set true on query-only nodes

Next Steps

Quickstart

Get Graph Node running quickly with Docker

Configuration

Advanced TOML configuration for production

Deploy a Subgraph

Learn how to create and deploy subgraphs

Environment Variables

Complete environment variable reference

Build docs developers (and LLMs) love