Creating and Running a Node⚓︎
This tutorial shows how to deploy and start a new Symbol node using the Shoestring tool.
The tutorial assumes that Shoestring and its dependencies have already been installed.
If you already have a node created with the deprecated Bootstrap tool and wish to reuse it, read the Migration guide instead.
Create a New Node⚓︎
Deploying a node with Shoestring involves the following steps.
Using the Shoestring Wizard
Alternatively, you can use the interactive setup wizard provided by Shoestring:
The wizard asks a series of questions and generates the same configuration files created in this tutorial.
The resulting node behaves exactly like one created with the command-line steps below.
After completing the wizard, continue from Start the Node if the node has not been started automatically.
1. Create a Working Directory⚓︎
Shoestring creates the node files inside the current directory.
Create a directory for the node and move into it:
All commands in this tutorial assume they are run from this directory.
2. Generate the Network Configuration⚓︎
The first step is to retrieve the default configuration files for the target network (mainnet or testnet).
Run:
This command downloads the configuration files required to operate on the mainnet network and creates the file
config.ini.
For testnet nodes, use the sai package instead.
In later commands that use the --network parameter, specify testnet instead of mainnet.
3. Configure Shoestring⚓︎
The config.ini file generated in the previous step already contains most required settings.
Only a few values usually need to be customized for your node, and they are all located in the [node] section:
-
The node roles, called features by Shoestring.
Set the desired node features from the list:
PEER,API,HARVESTER, andVOTER. You can combine multiple features by separating them with a vertical bar|, for example:Review the roles page for detailed explanations. In summary:
PEER: The node participates in consensus.API: The node exposes an API for client applications.HARVESTER: The node participates in block creation and is eligible for harvesting rewards. A minimum of 10'000 XYM are required. See Configure Harvesting below.VOTER: The node participates in finalization and is eligible for voting rewards. A minimum of 3'000'000 XYM are required. See Configure Voting below.
-
The
caCommonNameandnodeCommonNameproperties are used as Common Names (CN) in the certificates generated for the node.They do not affect node behavior, but they must not be empty or certificate generation will fail.
For example:
-
APInodes that should accept HTTPS requests must set theapiHttpsproperty totrue. Otherwise, the node will only accept HTTP requests.Enabling HTTPS support also requires setting a valid
hostas shown next.
4. Configure the Node⚓︎
An additional configuration file is required to define node-specific settings. Without it, the node will not be properly usable.
Create a new file called overrides.ini with the following content:
-
hostis the public IP address or hostname through which the rest of the network reaches your node.If you use an unreachable host (like
localhostor127.0.0.1), your node may connect to the network, but other nodes will be unable to initiate connections to it. -
friendlyNameis the human-readable name displayed in node lists such as https://symbol.fyi/nodes.
Further Customization
The overrides.ini file can be used to modify any Catapult
network or
node property.
To do so, add a section using the syntax [config-file-name.config-section],
then define the desired properties below it.
Note that setting any network property to a value different to those of the rest of the network will make your node fork, effectively disconnecting it from the rest of the network.
config.ini configures Shoestring itself, while overrides.ini customizes the generated node software.
5. Create the Node Identity⚓︎
Each node requires a cryptographic identity for secure communication with other nodes. At the heart of this identity is a private key, which corresponds to the node's main account.
This key is stored in a PEM file, and there are two ways to obtain it:
-
Create a new key with OpenSSL:
-
Import an existing private key:
This command asks you to paste your private key, but you can also provide it through a file with the
--inputparameter. Take special care not to leave private keys exposed in files or command history.
Both options create a PEM file named ca.key.pem that contains the private key.
This file must be kept secure. Leave it in this directory for now. It will be moved offline at a later stage.
Main Account Address
To view the address and public key corresponding to this private key, you can use Shoestring's pemview tool:
The output is similar to this:
The account's address is required to send funds to it. Funds are then needed to pay transaction fees, for example when enabling harvesting.
You can also use the --show-private parameter to display the private key and
import it into the wallet.
This step allows you to manage the account more conveniently, but it is not required for this guide.
Alternatively, you can use the openssl tool directly to show the account's public key:
6. Create the Node Installation⚓︎
Once the configuration and key files are ready, create the node installation with:
python3 -m shoestring setup \
--config ./config.ini \
--overrides ./overrides.ini \
--package mainnet \
--directory . \
--ca-key-path ./ca.key.pem
This command performs several tasks:
- Prepares the node directory structure.
- Generates certificates from the private key.
- Creates the Docker configuration files.
- Creates transactions that enable harvesting, if configured.
Configure Harvesting (Optional)⚓︎
If you enabled the HARVESTER role, one additional configuration step is required.
If not, this section can be skipped.
To enable harvesting, a VRF key must be linked to your account through a special transaction.
For security reasons, the main account must also be linked through a separate transaction to a remote account. This remote account is used by the node to sign newly created blocks, so it must remain on the node, where it stays online and could be exposed if the server is ever compromised.
However, the remote account does not hold any funds, as all harvesting rewards are credited to the linked main account, which can remain stored offline.
Shoestring's setup command has already created both transactions and stored them in a file named
linking_transaction.dat.
The following subsections explain how to sign the transactions in this file and announce them to the network.
7. Fund the Main Account⚓︎
First, the node's main account needs to hold some XYM to pay the fees required to announce these transactions.
Obtain the account's address as shown in step 5 above and transfer funds to it from another account. 1 XYM is typically enough.
8. Sign the Transactions⚓︎
Shoestring's signer tool reads linking_transaction.dat and signs the transactions in it with the key stored in
ca.key.pem (the node's main account):
python3 -m shoestring signer \
--config config.ini \
--ca-key-path ca.key.pem \
--save linking_transaction.dat
The signature is written back to linking_transaction.dat together with the transactions, so no new file is created.
The output looks similar to the following:
Note that the two key-link transactions are wrapped inside a single aggregate transaction, for convenience.
9. Announce the Transactions⚓︎
Use the announce-transaction tool to submit the signed transactions to the network:
python3 -m shoestring announce-transaction \
--config config.ini \
--transaction linking_transaction.dat
The tool connects to an available node on the network and submits the signed transactions. The output is similar to this:
10. Wait for Confirmation⚓︎
The announce-transaction command exits without waiting for confirmation, so the result must be verified manually.
From the output of the previous command, note the URL of the node where the transaction was submitted (line 1) and the hash of the transaction (line 2).
Then open the URL in a browser, or query it with curl:
{NODE_URL}/transactionStatus/{FULL_TRANSACTION_HASH}.
For example, from the output above, the URL is:
https://401-sai-dual.symboltest.net:3001/transactionStatus/5E59A0A0...
Check the same node where the transactions were submitted
If the node rejected the transactions without announcing them to the rest of the network, all other nodes will respond to this URL with a "transaction unknown" error, so always check the status of a transaction on the same node where you submitted it.
If the transactions are accepted, the node returns a message similar to this one:
{
"hash": "5E59A0A009A885B8DA0A6E1CE18BAE26A83441414E595799F25DB94848CCDEEB",
"code": "Success",
"deadline": "107120562182",
"group": "confirmed"
}
The most common outcomes are:
| Result | Meaning |
|---|---|
| Confirmed | The transactions are confirmed. Continue with this guide. |
| Unconfirmed | The transactions are valid but not yet included in a block. Wait up to 30 seconds. |
| Unknown | The transactions were submitted to a different node, or too long ago, or not at all. Repeat from Step 9. |
| Insufficient funds | Fund the node's main account as explained in step 7 above, then announce again. |
| Signature Not Verifiable | The transactions were probably not signed. Repeat from Step 8. |
| Deadline expired | Transactions must be announced within 6 hours of running setup. See below. |
In case of expired deadlines, repeat step 4 using the --output-transaction-only
parameter to create a fresh linking_transaction.dat and continue from step 9 to
announce it.
Once the transactions are confirmed, the node is ready to participate in block creation using the remote key
(created automatically during the setup process), and accrue any harvesting rewards on the main account
(obtained from the ca.key.pem file).
Importance Calculation Delay
A node has a higher chance of harvesting blocks, and therefore collecting rewards, when the importance of its main account is higher.
If you just funded the main account, importance takes 12 hours to update on mainnet and 3 hours on testnet.
Configure Voting (Optional)⚓︎
To create a voting node, the following requirements must be met:
- Set the
VOTERrole when configuring Shoestring. - The node's main account must hold 3'000'000 XYM.
Voting Keys Maintenance
During setup, Shoestring creates voting keys for the node. For security reasons, these keys have a maximum lifespan of 180 days, so they must be renewed periodically.
Once the node is up and running, read the Maintaining a Node guide to learn about the renewal process.
Start the Node⚓︎
The node is now configured and ready to be started, but there is one final security step remains:
Backup the Private Key
The ca.key.pem file contains the main account's private key, and it is NOT needed for normal node operation.
This file should be moved offline after the node is properly configured.
Copy ca.key.pem to secure storage, ideally offline, and remove it from the machine that will run the node.
Start the node containers with Docker:
The -d option runs the containers in detached mode, allowing the node to continue running after the terminal is closed.
Docker permissions
If you receive an error similar to:
your user does not have permission to run Docker commands.
On Linux, you can add your user to the docker group with:
Then log out and log back in, and run the command again.
To stop the node, run from the same folder:
The node data remains on disk and the node can be started again with docker compose up -d.
Keep in mind that the node might take up to 5 minutes to shut down cleanly. If interrupted, data might be left in an inconsistent state and require recovery.
Verify the Node⚓︎
Check that the node is running correctly:
If the node started successfully, the command reports that the peer endpoint, REST API, and WebSocket services are reachable (assuming these are the features you enabled):
... | running health agent for peer certificate
i | ca certificate not near expiry (7299 day(s))
i | node certificate not near expiry (374 day(s))
keys/cert/ca.crt.pem: OK
keys/cert/node.crt.pem: OK
... | running health agent for peer API
i | peer API accessible, height = 226081
... | running health agent for REST API
i | REST API accessible, height = 226081
... | running health agent for REST websockets
i | websocket connected to ws://127.0.0.1:3000/ws,
subscribing and waiting for block
i | websocket received a block with height 226082
Synchronization
Upon first launch, the node synchronizes with the network by downloading the full blockchain.
This process can take from 24 to 48 hours. During this time, REST requests to the node, if it is running the API role, may be delayed and report an incorrect chain height.
Node Recovery⚓︎
In the event of an unclean shutdown, for example, due to power loss, lock files may remain in the data
folder that prevent the node from starting.
The following command attempts to recover the node and restore a valid state:
After the recovery command completes, check whether any .lock files still exist in the data directory.
If they have been removed, start the node again with docker compose up -d.
Last Resort
If the recovery command does not solve the issue, reset-data can be used.
This command removes all downloaded blockchain data, so the node must synchronize again from the beginning. However, it preserves the node's configuration and keys.
Next Steps⚓︎
Once the node is running, only occasional maintenance tasks remain.