Skip to content

Repository files navigation

Pi Node Docker Image

This is a fork of PiCoreTeam/pi-node-docker upgraded for:

  • Protocol 22 → 23 (stellar-core 23.*)
  • Ubuntu 20 → 24 (base image)
  • PostgreSQL 12 → 16
  • Multi-network support: mainnet, testnet1 (original), testnet2

Software Versions

  • PostgreSQL 16
  • stellar-core 23.*
  • horizon 2.*
  • Supervisord — process manager
  • stellar-archivist — history archive management (optional)

Usage

1. Choose a Network

FlagNetworkPassphraseHistory CDN
--mainnetPi MainnetPi Networkhttps://history.mainnet.minepi.com
--testnetPi Testnet (original)Pi Testnethttps://history.testnet.minepi.com
--testnet2Pi Testnet2Pi Testnethttps://history.temp.testnet2.minepi.com

The Go Horizon API uses these corresponding NETWORK= env var values:

Docker flagNETWORK= (for Go Horizon)
--mainnetpimainnet
--testnetpitestnet1
--testnet2pitestnet2 (or pitestnet for backward compat)

2. Choose Ports to Expose

The software listens on several ports. At minimum, expose the horizon HTTP port (8000).

3. Mount a Data Volume

You must mount a host directory to /opt/stellar:

$ docker run --rm -it -p "31401:8000" -v "/path/to/data:/opt/stellar" --name pi-node pinetwork/pi-node-docker:organization_mainnet-v1.0-p23.0 --mainnet

Configuring the Original Pi Testnet (testnet1)

The testnet/ directory contains placeholder validators marked with __TESTNET_VALIDATOR*__. You must replace these before running the image on the original Pi Testnet.

How to find the validator keys

Option A — From a running Pi Testnet node's config: If you have access to a node already connected to the original Pi Testnet, look at its stellar-core.cfg:

$ grep -A4 '\[\[VALIDATORS\]\]' /opt/stellar/core/etc/stellar-core.cfg

Copy the PUBLIC_KEY, ADDRESS, and HISTORY values into:

pi-node-docker/testnet/core/etc/stellar-core.cfg
pi-node-docker/testnet/horizon/etc/stellar-core-captive.yml

Option B — From the Pi Core Team: The validator configuration is published by the Pi Core Team. Check:

Option C — From a running stellar-core node via HTTP API: If you have a stellar-core node running on the old testnet, query its quorum set:

$ curl http://<node-ip>:11626/info | jq .info.quorum

This returns the public keys of validators in the quorum set.

Option D — From the Pi Network blockchain explorer or community: Look up the Pi Testnet validator set in the Pi blockchain explorer or community documentation. Common validator key prefixes for Pi Core Team: GDLA3KOM..., GDFDDPMCL..., GAOBNDXT....

Understanding the validator config format

Each validator entry needs three fields:

[[VALIDATORS]]
NAME="validatorN"# Any descriptive nameHOME_DOMAIN="pi-core-team"# Domain for the validatorPUBLIC_KEY="G..."# The validator's public key (starts with G)ADDRESS="<ip>:31402"# IP and peer portHISTORY="curl -sf https://history.testnet.minepi.com/{0} -o {1}"# Archive CDN URL

Note: Both testnets (original and testnet2) share the same passphrase "Pi Testnet". They are distinguished by different validator sets and history archive URLs. If the old testnet has been merged into or replaced by testnet2, you only need the testnet2 configuration.

After filling in the validators

  1. Verify the config is valid:
$ stellar-core --conf pi-node-docker/testnet/core/etc/stellar-core.cfg --ll info --checkquorum
  1. Build and run:
$ cd pi-node-docker
$ docker build --platform linux/amd64 -t pinetwork/pi-node-docker:organization_mainnet-v1.0-p23.0 .
$ docker run --rm -it -p "31401:8000" -v "/path/to/data:/opt/stellar" --name pi-node pinetwork/pi-node-docker:organization_mainnet-v1.0-p23.0 --testnet

Background vs. Interactive Containers

  1. Run an interactive session first, ensuring all services start correctly.
  2. You will be prompted to set a PostgreSQL password (or set POSTGRES_PASSWORD env var).
  3. Shut down the interactive container (using Ctrl-C).
  4. Start a new container using the same host directory in the background.

Customizing Configurations

Default configurations are copied to the data directory on first launch:

/opt/stellar
├── core
│ └── etc
│ └── stellar-core.cfg # stellar-core configuration
├── horizon
│ └── etc
│ ├── horizon.env # Horizon environment variables
│ └── stellar-core-captive.yml # Captive core configuration
├── postgresql
│ └── etc
│ ├── postgresql.conf # PostgreSQL configuration
│ ├── pg_hba.conf # PostgreSQL client authentication
│ └── pg_ident.conf # PostgreSQL user mapping
├── supervisor
│ └── etc
│ └── supervisord.conf # Supervisord configuration
├── history/
│ └── local/ # Local history archive
└── migration_status # Tracks executed migrations (auto-created)

Stop the container before editing configuration files, then restart after changes.

WARNING: Incorrect configuration edits can break services.

Command Line Options

OptionDescription
--mainnetConnect to Pi Network mainnet
--testnetConnect to Pi Testnet (original)
--testnet2Connect to Pi Testnet2
--enable-auto-migrationsRun database/config migrations on startup

Environment Variables

VariableDescription
POSTGRES_PASSWORDSet PostgreSQL password (avoids interactive prompt)
NODE_PRIVATE_KEYSet the node's private key (secret seed). Optional - auto-generated if not provided

Migrations

The container includes migration scripts that update database schemas, modify deprecated configuration parameters, and apply other necessary changes when upgrading. Migrations run automatically on startup when enabled with --enable-auto-migrations.

How It Works

  • Migration scripts are in /migrations/ inside the container
  • Scripts execute in alphanumeric order (e.g., 001_*.sh, 002_*.sh, ...)
  • Each script runs only once — completed migrations are tracked in /opt/stellar/migration_status
  • If a migration fails, the container stops immediately (fail-fast)
  • Failed migrations will re-run on next startup
  • Backups are created in /opt/stellar/migration_backups/ before changes

Enabling Migrations

$ docker run -d \
-v "/path/to/data:/opt/stellar" \
-p "31401:8000" \
--name pi-node \
pinetwork/pi-node-docker:organization_mainnet-v1.0-p23.0 --mainnet --enable-auto-migrations

Running Migrations Manually

$ docker exec -it pi-node /migrations/migration_runner.sh

Or a specific migration:

$ docker exec -it pi-node /migrations/001_update_validator3.sh

Step-by-step documentation is in migrations/docs.

Ports

PortServiceDescription
5432PostgreSQLDatabase access port
8000HorizonMain HTTP port
6060HorizonAdmin port
31402stellar-corePeer node port
11626stellar-coreHTTP port (internal)
11726captive-coreCaptive core HTTP port
1570webfsdLocal history server

Recommended Port Mappings

Host PortContainer PortService
314018000Horizon HTTP
3140231402stellar-core peer
314031570Local history server

Security Considerations

  • PostgreSQL (5432): Keep protected. Write access can corrupt your view of the network.
  • Horizon HTTP (8000): Safe to expose publicly.
  • Horizon Admin (6060): Expose only to trusted networks.
  • stellar-core HTTP (11626): Expose only to trusted networks. Allows admin commands.
  • stellar-core Peer (31402): Can be exposed publicly to improve connectivity.
  • Local history (1570): Internal only.

Accessing and Debugging

Access a running container:

$ docker exec -it pi-node bash

Managing Services

Services are managed via supervisord:

$ supervisorctl
horizon RUNNING pid 143, uptime 0:01:12
postgresql RUNNING pid 126, uptime 0:01:13
stellar-core RUNNING pid 125, uptime 0:01:13
supervisor>

Common commands:

supervisor> restart horizon
supervisor> stop stellar-core
supervisor> tail -f horizon # live horizon logs
supervisor> tail -f stellar-core

Viewing Logs

Logs are at /var/log/supervisor/. Use supervisorctl tail for live logs.

/tmp/stellar-core.log — stellar-core log file.

Accessing Databases

Two PostgreSQL databases:

  • core — stellar-core data
  • horizon — Horizon data

Connect with username:stellar, password: the one you set during init (or POSTGRES_PASSWORD).

Example Commands

Initialize mainnet (interactive):

$ docker run -it --rm \
-v "/path/to/data:/opt/stellar" \
-p "31401:8000" -p "31402:31402" -p "31403:1570" \
--name pi-node \
pinetwork/pi-node-docker:organization_mainnet-v1.0-p23.0 --mainnet

Start testnet2 in background (after init):

$ docker run -d \
-v "/path/to/data:/opt/stellar" \
-p "31401:8000" -p "31402:31402" -p "31403:1570" \
-e POSTGRES_PASSWORD=your_password \
--name pi-node \
pinetwork/pi-node-docker:organization_mainnet-v1.0-p23.0 --testnet2

Docker Compose

Recommended docker-compose.yml:

name: pi-nodeservices:
mainnet:
image: pinetwork/pi-node-docker:organization_mainnet-v1.0-p23.0container_name: mainnetenv_file:
- ./.envvolumes:
- ./data/stellar:/opt/stellar
- ./data/supervisor_logs:/var/log/supervisor
- ./data/history:/historyports:
- "31401:8000"
- "31402:31402"
- "31403:1570"command: ["--mainnet --enable-auto-migrations"]

Create .env:

POSTGRES_PASSWORD=your_secure_password
NODE_PRIVATE_KEY=your_node_private_key # Optional - auto-generated if not provided

Start:

$ docker compose up -d mainnet

Building

$ make build

Builds as pinetwork/pi-node-docker:organization_mainnet-v1.0-p23.0.

Changes from Upstream (PiCoreTeam/pi-node-docker)

AreaUpstreamThis fork
Ubuntu base20.0424.04
PostgreSQL1216
stellar-core19.9.023.*
horizon2.30.02.*
Networksmainnet onlymainnet + testnet1 + testnet2
apt key methodapt-key add (deprecated)keyrings
STELLAR_CORE_DATABASE_URLpresent in common configremoved (deprecated in horizon)
Captive core storage pathnot in common configadded as default

Troubleshooting

If you encounter issues, open an issue in the repository.

About

Home of the stellar/quickstart docker image

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages