Sync Docker Teranode¶
Last modified: 28-April-2026
Docker deployments sync through the teranode-quickstart workflow. You can either let Teranode sync from the network or seed it from a compatible UTXO snapshot before startup.
Choose a Sync Method¶
| Method | Best for | Command path |
|---|---|---|
| Network sync | Fresh installs without a seed source | ./start.sh |
| Snapshot seeding | Faster initial sync when a compatible snapshot is available | ./seed.sh ... && ./start.sh |
| Existing Teranode data | Recovery from your own backup | Restore volumes, then ./start.sh |
Snapshots are usually pruned. They speed up UTXO initialization, but they do
not provide full historical transaction data unless the source explicitly
contains it. Enable blockpersister before syncing if you need raw historical
block data for an explorer, indexer, or archive.
Why Seeding Instead of Full IBD¶
Network sync performs a full Initial Block Download (IBD): it downloads and validates every block and transaction back to Genesis, the same way legacy node implementations bootstrap. Teranode still supports this path — see Network Sync below — but it is not the recommended way to bring up a fresh node at Teranode's scale.
The chain of block headers alone is enough to prove a node is following the correct Proof-of-Work chain; it does not require replaying the full transaction history to do so. Because Teranode targets substantially higher block sizes and throughput than legacy nodes, a full IBD from Genesis can take days and scales with bandwidth, CPU, and storage as the chain grows.
Seeding instead loads a UTXO snapshot before startup, reconstructing current state in a fraction of the time of a full download. That is why seeding is the recommended path when a compatible snapshot is available, with Network Sync reserved for fresh installs that have no seed source.
Note the trust boundary. The export tooling checks its own output against the
source node's chainstate tip and writes a .sha256 sidecar next to each
artifact, but the seeder imports whatever it is given: it checks that each
header links to a previously stored block, but performs no proof-of-work check
on the imported headers, never reads the .sha256 sidecars, and does not
re-derive the UTXO set from the chain. A self-consistent forged chain still
passes the linkage check, and nothing in the import path can detect a snapshot
whose UTXO set does not match the chain, because a block header commits to the
block's transactions, not to the resulting UTXO state. Seed only from
artifacts you exported yourself or from an
operator you trust, and check them against the .sha256 files before
importing. Network Sync is the option that requires no such trust.
The block hash selects the seed files by name; it is not compared against the tip recorded inside them, and the headers file and the UTXO set are not compared against each other. Confirm both artifacts come from the same export before seeding. A mismatched or partially transferred pair may import without an error, or may fail at the final step after the whole UTXO set has already been written — in which case reseeding needs a forced re-run.
Network Sync¶
Network sync needs no seed data:
A fresh docker.m deployment starts in IDLE. For network sync without a seed
inspection window, start catchup explicitly:
Monitor progress:
Mainnet network sync can take days and depends on hardware, bandwidth, peer quality, and current chain activity.
Seed from a Snapshot¶
Seeding writes UTXO state before the full stack starts. Start from a clean data volume:
Teratestnet¶
Teratestnet has a canonical snapshot. Quickstart derives the URL from the block hash:
Mainnet and Testnet¶
Mainnet and standard testnet do not have a canonical public snapshot URL. Bring your own compatible seed directory or URL:
or:
The block hash must match the snapshot. The snapshot network must match the
configured .env network.
Legacy SV Node Export¶
If your seed source is an existing SV Node data directory, export it to
quickstart-compatible seed files with the Teranode image. Stop SV Node
gracefully before reading its blocks and chainstate directories:
From the quickstart repository root, load the pinned Teranode version and write the export to a local seed directory:
set -a
. ./.env
set +a
mkdir -p /path/to/teranode-seed
docker run --rm \
--entrypoint /app/teranode-cli \
-v /path/to/svnode-data:/svnode:ro \
-v /path/to/teranode-seed:/seed \
ghcr.io/bsv-blockchain/teranode:"$TERANODE_VERSION" \
bitcointoutxoset --bitcoinDir=/svnode --outputDir=/seed
Use the block hash from the generated seed filenames when loading quickstart:
Seed from .env¶
You can also configure seed values in .env:
Then run:
Use SEED_URL instead of SEED_DIR when the seed is a downloadable ZIP file.
Restore Existing Data¶
If you maintain backups of the quickstart Docker volumes, restore them while the
stack is stopped, keep .env aligned with the restored network and version,
then start normally:
Do not restore data from one network into a configuration for another network.
Verify a Seed Before Catch-up¶
The quickstart stack uses the docker.m settings context. A fresh blockchain
store therefore starts in IDLE, including the first start after ./seed.sh:
the seeder writes chain data and the Block Assembler checkpoint, but no FSM
state. While the node is parked, confirm that the seeded tip and network match
the snapshot you intended to load and that every service can reach its store.
During this IDLE inspection window, subtreevalidation and pruner have not
bound their gRPC listeners yet. With the port-listen healthchecks in the bundled
Docker definitions, their health status may remain starting or become
unhealthy while parked: those gRPC ports are not listening. That status
alone does not indicate a bad seed. Inspect the blockchain FSM, seeded tip and
logs; the blockchain listener remains available for the CLI command below.
Other enabled services with the same startup wait and port probes can behave
similarly.
After verification, start synchronization explicitly:
After allowing the services time to initialize, run ./status.sh again. If
subtreevalidation or pruner remains unhealthy after leaving IDLE, inspect its
logs and store connectivity; do not dismiss a continuing failure as expected.
Catch-up promotes the node to RUNNING after it reaches the active network's
highest checkpoint. There is no transition from CATCHINGBLOCKS back to
IDLE, so verify the seed first. To skip this window on an unattended node,
set blockchain_initializeNodeInState.docker.m = CATCHINGBLOCKS in
settings_local.conf before the first start.
Troubleshooting Sync¶
An unrecognized persisted FSM state aborts blockchain startup with an error
naming the stored value. The node preserves that value rather than guessing
whether catchup or mining was intended. LEGACYSYNCING is the one supported
legacy migration and resumes as CATCHINGBLOCKS.
For an unknown value, stop the stack and verify that the data and Teranode version are compatible. Restore a compatible backup or repair the FSM record through your datastore maintenance procedure before restarting. The CLI cannot repair this while blockchain startup is failing. Preserve a backup before any store repair; a reset and resync is a separate recovery choice.
- Check container health with
./status.sh. - Check service logs with
./logs.sh blockchain,./logs.sh legacy, or./logs.sh p2p. - Confirm the configured network in
.env. - Confirm that seed data matches the configured network and block hash.
- For full mode, confirm that public asset and P2P endpoints pass the
reachability check from
./start.sh. - If local state is inconsistent, reset with
./clean.sh --data-onlyand seed or sync again.