Skip to content

đŸ–„ Developer Setup - Pre-requisites and Installation

This guide assists you in setting up the Teranode project on your machine. The below assumes you are running a recent version of Mac OS.

Index

  1. Install Go
  2. Set Go Environment Variables
  3. Python and Dependencies
  4. Clone the Project and Install Dependencies
  5. Configure Settings
  6. Prerequisites for Running the Node
  7. Run the Node
  8. Troubleshooting

1. Install Go

Download and install the latest version of Go. As of February 2026, it's 1.26.0.

Go Installation Guide

Test Installation:

Open a new terminal and execute:

go version

It should display go1.26.0 or above.

2. Set Go Environment Variables

Add these lines to .zprofile or .bash_profile, depending on which one your development machine uses:

export PATH="$PATH:$(go env GOPATH)/bin"
export GOPATH="$(go env GOPATH)"
export GOBIN="$(go env GOPATH)/bin"

Test Configuration:

Open a new terminal and execute:

echo $GOPATH
echo $GOBIN

Both should display paths related to Go.

3. Python and Dependencies

3.1 Install Python (via Homebrew)

brew install python

By default, Homebrew will install Python 3.x and create symlinks like python3 and pip3. You can optionally create a symlink for python and pip if you want shorter commands (but check if they already exist first):

ln -s /opt/homebrew/bin/python3 /opt/homebrew/bin/python  # might already exist
ln -s /opt/homebrew/bin/pip3 /opt/homebrew/bin/pip        # might already exist

Because of PEP 668 and Homebrew’s “externally-managed-environment” setup, you can’t do pip install ... directly into the system-wide Python.

Instead, create and activate a virtual environment:

python3 -m venv ~/my_python_env     # choose any path you like
source ~/my_python_env/bin/activate

After activating, your shell should show something like (my_python_env) as a prefix.

3.3 Install Dependencies Within the Virtual Environment

Once your virtual environment is active, you can safely use pip to install packages without system conflicts:

python -m pip install --upgrade pip
pip install PyYAML

3.4 Verify Installation

python -c "import yaml; print(yaml.__version__)"

This should print out the installed PyYAML version (e.g., 6.0.2 or similar).

If you need PyYAML as part of a standalone command-line tool, you could use pipx instead:

brew install pipx
pipx install PyYAML

However, most Teranode workflows will need PyYAML as a library for scripts, so a virtual environment is usually best.

4. Clone the Project and Install Dependencies

Clone the project:

git clone git@github.com:bsv-blockchain/teranode.git

Install all dependencies:

Execute:

cd teranode

# This will install all required dependencies (protobuf, golangci-lint, etc.)
make install

Note: If you receive an error ModuleNotFoundError: No module named 'yaml' error, refer to this issue for a potential fix. Example:

PYTHONPATH=$HOME/Library/Python/3.9/lib/python/site-packages make install  #Make sure the path is correct for your own python version

5. Configure Settings

Teranode uses two configuration files:

  • settings.conf - Contains sensible defaults for all environments. You should NOT modify this file as part of the scope of this guide.
  • settings_local.conf - Contains developer-specific and deployment-specific settings

5.1 Introducing developer-specific settings in settings_local.conf

  1. In your project directory, create a file settings_local.conf. This file is used for your personal development settings, and it's not tracked in source control.

  2. Introduce any settings override in settings_local.conf that you might require for your development. Use the settings.conf as a reference for common settings and their default values.

  3. The settings you are adding will use a prefix (settings context) that identifies your context. By default, your settings context should be dev.. You can further refine this by using a more specific prefix, such as dev.john or dev.me. However, it is recommended to use the default prefix dev., and only refine it in very specific cases.

In order for your node to read your custom lines, you set SETTINGS_CONTEXT to match the prefix you used (i.e., dev).

In zsh, open ~/.zprofile (or ~/.zshrc). In bash, open ~/.bash_profile (or ~/.bashrc).

Add:

export SETTINGS_CONTEXT=dev

(If you have used a richer prefix, such as dev.john, you would set SETTINGS_CONTEXT=dev.john)

After editing, reload your shell config:

source ~/.zprofile

(or the equivalent for your shell).

5.3 Verify

  1. Echo the environment variable to ensure it's set correctly:

    echo $SETTINGS_CONTEXT
    

    Should print dev.

  2. Run or restart your node. Check logs or console output to confirm it's picking up the lines with dev.

6. Prerequisites for Running the Node

6.1 Install OrbStack

Teranode uses Docker containers for running dependencies like Kafka and PostgreSQL. For Mac developers, we recommend using OrbStack - a fast, lightweight Docker Desktop alternative optimized for macOS.

Why OrbStack?

  • Faster: 2-3x faster than Docker Desktop for container startup and file operations
  • Lighter: Uses significantly less CPU and memory
  • Native: Built specifically for macOS with better integration
  • Compatible: Drop-in replacement for Docker Desktop - all Docker commands work the same

Installation:

  1. Download OrbStack from orbstack.dev
  2. Open the downloaded file and drag OrbStack to your Applications folder
  3. Launch OrbStack from your Applications folder
  4. Follow the brief setup wizard

Verify installation:

docker --version

6.2 Start PostgreSQL

Once OrbStack is installed and running, start PostgreSQL with:

# Start PostgreSQL in Docker
./scripts/postgres.sh

Note on Kafka: Development mode uses in-memory Kafka by default (no setup required). For production-like testing with Docker-based Kafka, see Kafka Settings Reference. If you configure your settings to use Aerospike for UTXO storage, you'll also need to run the Aerospike script:

# Start Aerospike in Docker
./scripts/aerospike.sh

7. Run the Node

You can run the entire node with the following command:

SETTINGS_CONTEXT=dev.[YOUR_CONTEXT] go run .

If no errors are seen, you have successfully installed the project and are ready to start working on the project or running the node.

Note that the node is initialized in IDLE mode by default. You'll need to transition it to RUNNING mode to start processing transactions.

7.1. Executing the Teranode-CLI as a Developer

The Teranode-CLI allows you to interact with Teranode services. You can use it to transition the node to different states, query its current state, and perform various maintenance operations. For a comprehensive guide on using the Teranode-CLI as a developer, see the Developer's Guide to Teranode-CLI.

Building the Teranode-CLI

Build the Teranode-CLI tool with:

go build -o teranode-cli ./cmd/teranodecli

Executing Commands

Once built, you can run commands directly:

# Get current FSM state
SETTINGS_CONTEXT=dev.[YOUR_CONTEXT] ./teranode-cli getfsmstate

# Set FSM state to RUNNING
SETTINGS_CONTEXT=dev.[YOUR_CONTEXT] ./teranode-cli setfsmstate --fsmstate running

Available Commands

The Teranode-CLI provides several commands:

Command Description
getfsmstate Get the current FSM State
setfsmstate Set the FSM State (with --fsmstate flag)
settings View system configuration
aerospikereader Read transaction data from Aerospike
filereader Read and process files
seeder Seed initial blockchain data
bitcointoutxoset Convert Bitcoin data to UTXO set
utxopersister Manage UTXO persistence
export-blocks Export blockchain to CSV
import-blocks Import blockchain from CSV
checkblocktemplate Check block template

Getting Help

For general help and a list of available commands:

# General help
./teranode-cli

# Command-specific help
./teranode-cli setfsmstate --help

The CLI will use your development settings as specified by your SETTINGS_CONTEXT environment variable.

Transitioning the Node to RUNNING Mode

To transition the node from IDLE to RUNNING mode, use:

# Get current FSM state
SETTINGS_CONTEXT=dev ./teranode-cli getfsmstate

# Set FSM state to RUNNING
SETTINGS_CONTEXT=dev ./teranode-cli setfsmstate --fsmstate running

After executing these commands, your log should show a successful transition:

[Blockchain Client] FSM successfully transitioned from IDLE to state:RUNNING

7.2. Debugging Teranode

Teranode supports debugging using Delve, the Go debugger. You can use any IDE that supports Delve, including VS Code, GoLand, or the Delve CLI directly.

Local Development Debugging

To debug Teranode during local development, you have several options:

This is the most reliable method and works on all platforms including M3/M4 Macs.

  1. Build with debug symbols:

    DEBUG=true make build
    

    This enables debug flags (-N -l) that disable optimizations and inlining, making debugging easier.

  2. Run with your IDE's debugger:

    • GoLand: Use "Run" → "Debug" or press Ctrl+D (Linux/Windows) / ⌃D (Mac)
    • VS Code: Use "Run and Debug" panel or press F5 after configuring launch.json
Option 2: Attach to Running Process

Note: This method does not work on Apple M3/M4 Macs due to architecture limitations.

  1. Build and start Teranode as normal
  2. Find the process ID: ps aux | grep teranode
  3. Attach your debugger to the PID:
    • GoLand: "Run" → "Attach to Process"
    • VS Code: Use "attach" configuration in launch.json
Option 3: Start via Delve and Attach Remotely

This method allows you to start the application with Delve and attach your IDE remotely:

  1. Install Delve (if not already installed):

    go install github.com/go-delve/delve/cmd/dlv@latest
    
  2. Start Teranode with Delve:

    dlv exec ./teranode.run --headless --listen=:2345 --api-version=2 --accept-multiclient
    
  3. Attach your IDE to Delve:

    • GoLand: Create a "Go Remote" run configuration pointing to localhost:2345
    • VS Code: Use a remote attach configuration in launch.json with port 2345

Remote Debugging (Kubernetes Deployments)

For debugging Teranode running in Kubernetes environments:

  • See the Remote Debug Guide for detailed instructions on:

    • Configuring the Kubernetes cluster for remote debugging
    • Port forwarding the debugger
    • Connecting with VS Code, GoLand, or Delve CLI
    • Debugging multiple services simultaneously

8. Troubleshooting

8.1. Dependency errors and conflicts

Should you have errors with dependencies, try running the following commands:

go clean -cache
go clean -modcache
rm go.sum
go mod tidy
go mod download

This will effectively reset your cache and re-download all dependencies.

Quick Setup with teranode-dev

As an alternative to the manual steps above, you can use the teranode-dev CLI tool to automate the entire local setup process. It asks a few questions and handles everything else - prerequisites, settings, Docker containers, and building.

Build the tool

make build-teranode-dev

Run the interactive wizard

./teranode-dev init

The wizard will ask for:

  1. Your developer name (for SETTINGS_CONTEXT)
  2. UTXO storage backend (SQLite, PostgreSQL, or Aerospike)
  3. Network (regtest, testnet, or mainnet)
  4. Whether to use Docker-based Kafka (default: in-memory)
  5. Whether to enable monitoring (Grafana + Prometheus)
  6. Whether to enable tracing (Jaeger)

It then automatically:

  • Checks prerequisites (Go, Docker, Python)
  • Generates settings_local.conf entries
  • Creates data directories
  • Configures /etc/hosts for Kafka (if selected)
  • Starts Docker containers and waits for health
  • Builds teranode.run with the correct build tags

Infrastructure management

./teranode-dev up       # Start infrastructure containers (postgres, kafka, etc.)
./teranode-dev down     # Stop infrastructure containers
./teranode-dev clean    # Wipe data directory (with confirmation)

If a service is already running on the expected port (e.g. a native PostgreSQL), the tool will skip starting a Docker container for it.

Running the node

./teranode-dev start    # Start teranode daemon in background with log rotation
./teranode-dev stop     # Stop teranode daemon (graceful, then force after 5s)

The node starts directly in RUNNING state (no need to manually set the FSM state).

Generating blocks (regtest)

On regtest, you can generate blocks for testing:

./teranode-dev generate      # Generate 1 block
./teranode-dev generate 10   # Generate 10 blocks

This calls the node's RPC generate command. It only works on networks where CPU mining is supported (regtest). On other networks it will return an error.

RPC passthrough

Call any Bitcoin JSON-RPC method directly without needing curl or remembering auth credentials:

./teranode-dev rpc                              # List all available RPC commands
./teranode-dev rpc getblockchaininfo            # Query chain state
./teranode-dev rpc getblockhash 0               # Get genesis block hash
./teranode-dev rpc getblock <hash> 2            # Get block with verbosity level 2
./teranode-dev rpc getpeerinfo                  # List connected peers
./teranode-dev rpc sendrawtransaction <hex>      # Broadcast a raw transaction

Parameters are automatically converted to the correct JSON types (numbers, strings, booleans).

Monitoring and diagnostics

./teranode-dev status     # Show running services, health checks, FSM state, chain tip
./teranode-dev monitor    # Live TUI dashboard for real-time node monitoring
./teranode-dev logs       # Interactive log viewer with filtering and search
./teranode-dev settings   # Print all resolved settings as JSON
./teranode-dev doctor     # Check prerequisites, configuration, and chain consistency
./teranode-dev diagnose   # Detailed health checks (gRPC, HTTP, Kafka, Postgres, Aerospike)
./teranode-dev diagnose --config  # Validate configuration for common issues
./teranode-dev diagnose --json    # Machine-readable output

The doctor command also detects chain/genesis mismatches - if you change your configured network without clearing the database, it will offer to either delete the stored data or change the network setting to match.

The logs command supports flags:

./teranode-dev logs --file ./logs/teranode.log  # Custom log file path
./teranode-dev logs --buffer 20000              # Keep more entries in memory

Non-interactive mode

For CI or scripting:

./teranode-dev init --non-interactive --name=liam --utxo=sqlite --network=regtest

Re-running init

Running init again presents your previous choices as defaults - just press enter to keep them. This is useful for changing a single setting (e.g. switching from sqlite to postgres) without re-entering everything.

Next Steps