My goal with this post is to have cardano-node
s on both testnets – preview and preprod – and on mainnet running as a user, so I can later use them for minting, contract experiments etc. I’m not going to run a pool and this is not about setting up one.
To setup as fast and simple as possible, I’m going to use the pre-compiled binaries. Moreover, since we now have Mithril to get snapshots of the chains and do not have to synchronise from the beginning anymore, I’m going to use that.
Installing the software
I’m downloading the latest stable versions of cardano-node
(10.1.2 at the time of last update) from https://github.com/input-output-hk/cardano-node/releases and of mithril
(v2445.0 at the time of last update) from https://github.com/input-output-hk/mithril/releases. Then, I unpack those archives and put the binaries in there in the PATH
.
I won’t give copy and paste instructions here. There are far too many already out there. A Cardano forum is not the right place to give a thorough introduction to Linux, bash
, etc. You should learn a bit about that from the plethora of resources that are readily available out there for Linux in general and your specific Linux distribution.
After that, you can choose how you would like to organise your (Cardano) software. Personally, I chose to have the different packages in ~/.local/cardano/software/
:
$ ls -l ~/.local/cardano/software/
drwxr-xr-x 1 sean sean 16 2024-11-01 14:58 cardano-node-10.1.2/
-rw-r--r-- 1 sean sean 126310571 2024-11-01 16:42 cardano-node-10.1.2-linux.tar.gz
drwxr-xr-x 1 sean sean 414 2024-11-27 02:00 mithril-2445.0/
-rw-r--r-- 1 sean sean 63016769 2024-11-07 14:38 mithril-2445.0-linux-x64.tar.gz
Observe:
- IOG tends to pack its binary distributions such that they unpack in the current directory. So, I manually created those versioned directories, changed into them and called
tar xaf
from in there. - The binaries in the
mithril
distribution were not set to executable. I had to manuallychmod +x
them.
And I then have symbolic links in ~/.local/bin/
which for me is in the PATH
anyway:
$ ls -l ~/.local/bin/
lrwxrwxrwx 1 sean sean 50 2024-11-27 02:15 bech32 -> ../cardano/software/cardano-node-10.1.2/bin/bech32*
lrwxrwxrwx 1 sean sean 55 2024-11-27 02:16 cardano-cli -> ../cardano/software/cardano-node-10.1.2/bin/cardano-cli*
lrwxrwxrwx 1 sean sean 56 2024-11-27 02:17 cardano-node -> ../cardano/software/cardano-node-10.1.2/bin/cardano-node*
lrwxrwxrwx 1 sean sean 49 2024-11-27 02:19 mithril-client -> ../cardano/software/mithril-2445.0/mithril-client*
That way, I can easily switch to new versions by changing the symbolic links, with the possibility to easily switch back as long as I have not deleted the old version.
Using Mithril to get snapshots
Mithril can be used to bootstrap nodes on mainnet as well as both testnets as described in https://mithril.network/doc/manual/getting-started/bootstrap-cardano-node.
I decided to put the chains next to each other in ~/.local/cardano/chains/
. So, I’m doing in ~/.local/cardano/chains/mainnet/
:
$ export NETWORK=mainnet
$ export AGGREGATOR_ENDPOINT=https://aggregator.release-mainnet.api.mithril.network/aggregator
$ export GENESIS_VERIFICATION_KEY=$(curl -s https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/release-mainnet/genesis.vkey)
$ mithril-client cardano-db snapshot list
$ mithril-client cardano-db download <latest digest>
In ~/.local/cardano/chains/preprod/
:
$ export NETWORK=preprod
$ export AGGREGATOR_ENDPOINT=https://aggregator.release-preprod.api.mithril.network/aggregator
$ export GENESIS_VERIFICATION_KEY=$(curl -s https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/release-preprod/genesis.vkey)
$ mithril-client cardano-db snapshot list
$ mithril-client cardano-db download <latest digest>
And in ~/.local/cardano/chains/preview/
:
$ export NETWORK=preview
$ export AGGREGATOR_ENDPOINT=https://aggregator.pre-release-preview.api.mithril.network/aggregator
$ export GENESIS_VERIFICATION_KEY=$(curl -s https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/pre-release-preview/genesis.vkey)
$ mithril-client cardano-db snapshot list
$ mithril-client cardano-db download <latest digest>
mithril-client
downloads the databases into db/
directories in the current directory and, when the downloads are ready, verifies the signatures (after all that is what Mithril is all about).
Download and check of preprod
and preview
were ready in about eleven minutes each, of mainnet
in about 95 minutes:
Getting and adapting the configurations
The configuration and Genesis files are obtained from https://book.world.dev.cardano.org/environments.html.
In ~/.local/cardano/chains/mainnet/config/
:
$ curl -s -O https://book.world.dev.cardano.org/environments/mainnet/config.json
$ curl -s -O https://book.world.dev.cardano.org/environments/mainnet/topology.json
$ curl -s -O https://book.world.dev.cardano.org/environments/mainnet/byron-genesis.json
$ curl -s -O https://book.world.dev.cardano.org/environments/mainnet/shelley-genesis.json
$ curl -s -O https://book.world.dev.cardano.org/environments/mainnet/alonzo-genesis.json
$ curl -s -O https://book.world.dev.cardano.org/environments/mainnet/conway-genesis.json
$ curl -s -O https://book.world.dev.cardano.org/environments/mainnet/guardrails-script.plutus
In ~/.local/cardano/chains/preprod/config/
:
$ curl -s -O https://book.world.dev.cardano.org/environments/preprod/config.json
$ curl -s -O https://book.world.dev.cardano.org/environments/preprod/topology.json
$ curl -s -O https://book.world.dev.cardano.org/environments/preprod/byron-genesis.json
$ curl -s -O https://book.world.dev.cardano.org/environments/preprod/shelley-genesis.json
$ curl -s -O https://book.world.dev.cardano.org/environments/preprod/alonzo-genesis.json
$ curl -s -O https://book.world.dev.cardano.org/environments/preprod/conway-genesis.json
$ curl -s -O https://book.world.dev.cardano.org/environments/preprod/guardrails-script.plutus
In ~/.local/cardano/chains/preview/config/
:
$ curl -s -O https://book.world.dev.cardano.org/environments/preview/config.json
$ curl -s -O https://book.world.dev.cardano.org/environments/preview/topology.json
$ curl -s -O https://book.world.dev.cardano.org/environments/preview/byron-genesis.json
$ curl -s -O https://book.world.dev.cardano.org/environments/preview/shelley-genesis.json
$ curl -s -O https://book.world.dev.cardano.org/environments/preview/alonzo-genesis.json
$ curl -s -O https://book.world.dev.cardano.org/environments/preview/conway-genesis.json
$ curl -s -O https://book.world.dev.cardano.org/environments/preview/guardrails-script.plutus
I decided that I need neither EKG nor Prometheus for my use case (local node just to submit transactions and experiment around with). The logs in journalctl
are more than enough. So, I removed superfluous configuration in all three configs:
$ diff -u1 config-original.json config.json
--- config-original.json 2024-01-04 10:25:32.232620424 +0100
+++ config.json 2024-01-04 10:26:16.619097477 +0100
@@ -63,3 +63,3 @@
"TracingVerbosity": "NormalVerbosity",
- "TurnOnLogMetrics": true,
+ "TurnOnLogMetrics": false,
"TurnOnLogging": true,
@@ -74,27 +74,4 @@
],
- "hasEKG": 12788,
- "hasPrometheus": [
- "127.0.0.1",
- 12798
- ],
"minSeverity": "Info",
"options": {
- "mapBackends": {
- "cardano.node.metrics": [
- "EKGViewBK"
- ],
- "cardano.node.resources": [
- "EKGViewBK"
- ]
- },
- "mapSubtrace": {
- "cardano.node.metrics": {
- "subtrace": "Neutral"
- }
- }
- },
- "rotation": {
- "rpKeepFilesNum": 10,
- "rpLogLimitBytes": 5000000,
- "rpMaxAgeHours": 24
},
Since I want to be able to run the nodes on the different chains/networks in parallel and the port the node itself listens on will be given on the command line and is not set in config.json
, I create environment files that can be read by the systemd
unit in the next section:
$ cat ~/.local/cardano/chains/mainnet/env
CARDANO_NODE_PORT=3001
$ cat ~/.local/cardano/chains/preprod/env
CARDANO_NODE_PORT=3002
$ cat ~/.local/cardano/chains/preview/env
CARDANO_NODE_PORT=3003
Creating a systemd user unit
I want to be able to manage the nodes with systemctl
, but not as system-wide units (as in the usual setups according to CoinCashew or CNTools), but as user units.
I create the following unit file:
$ cat ~/.config/systemd/user/cnode@.service
[Unit]
Description=Cardano Node
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
WorkingDirectory=%h/.local/cardano/chains/%i/
EnvironmentFile=%h/.local/cardano/chains/%i/env
ExecStart=%h/.local/bin/cardano-node run --topology config/topology.json --database-path db --socket-path socket --config config/config.json --port ${CARDANO_NODE_PORT}
SyslogIdentifier=cnode@%i
KillSignal=SIGINT
TimeoutStopSec=300
LimitNOFILE=32768
Restart=always
RestartSec=5
[Install]
WantedBy=default.target
That the name of the unit ends in an @
means that it is started with an instance name that is available inside the unit as %i
. That way, I can use this same unit file to manage all three networks/chains with it.
Changing into the directory for the corresponding chain makes the call to cardano-node
very simple and there are no further scripts needed.
Starting all three chains:
$ systemctl --user start cnode@mainnet
$ systemctl --user start cnode@preprod
$ systemctl --user start cnode@preview
This also organises them into a slice that can be used to query the state of all of them at once:
$ systemctl --user status app-cnode.slice
● app-cnode.slice - Slice /app/cnode
Loaded: loaded
Active: active since Wed 2024-11-27 03:09:44 CET; 1h 3min ago
Invocation: 6ad7f10099474e7b85faf90f9d552c2b
Tasks: 40
Memory: 16.6G (peak: 16.6G)
CPU: 7min 36.291s
CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/app-cnode.slice
├─cnode@mainnet.service
│ └─982663 /home/sean/.local/bin/cardano-node run --topology config/topology.json --database-path db --socket-path socket --config config/config.json --port 3001
├─cnode@preprod.service
│ └─975140 /home/sean/.local/bin/cardano-node run --topology config/topology.json --database-path db --socket-path socket --config config/config.json --port 3002
└─cnode@preview.service
└─975169 /home/sean/.local/bin/cardano-node run --topology config/topology.json --database-path db --socket-path socket --config config/config.json --port 3003
Nov 27 04:12:33 nat cnode@preview[975169]: [nat:cardano.node.ConnectionManager:Info:1456] [2024-11-27 03:12:33.45 UTC] TrConnectionManagerCounters (ConnectionManagerCounters {fullDuplexConns = 0, duplexConns = 54>
Nov 27 04:12:34 nat cnode@mainnet[982663]: [nat:cardano.node.ChainDB:Notice:23] [2024-11-27 03:12:34.67 UTC] Chain extended, new tip: 4a24ab43ac538cce8135c7cc6ff0b5fa3c1bf700f15e8841d6301b3e24ccd683 at slot 14111>
Nov 27 04:12:36 nat cnode@preview[975169]: [nat:cardano.node.ChainDB:Notice:21] [2024-11-27 03:12:36.11 UTC] Chain extended, new tip: 6fb38c90fec87eb49213011b5b37074f89f8436a82668ae7a9ac267ece73b392 at slot 66021>
Nov 27 04:12:36 nat cnode@preview[975169]: [nat:cardano.node.Mempool:Info:29] [2024-11-27 03:12:36.11 UTC] fromList [("enclosingTime",Object (fromList [("tag",String "RisingEdge")])),("kind",String "TraceMempoolS>
Nov 27 04:12:36 nat cnode@preview[975169]: [nat:cardano.node.metrics:Notice:29] [2024-11-27 03:12:36.11 UTC] txsSyncDuration = 0
Nov 27 04:12:36 nat cnode@preview[975169]: [nat:cardano.node.Mempool:Info:29] [2024-11-27 03:12:36.11 UTC] fromList [("enclosingTime",Object (fromList [("contents",Number 2.77389e-4),("tag",String "FallingEdgeWit>
Nov 27 04:12:51 nat cnode@preprod[975140]: [nat:cardano.node.ChainDB:Notice:21] [2024-11-27 03:12:51.11 UTC] Chain extended, new tip: c3ae45890a32f8887a7bead3111c1d2b8c73a29ed5354be11fd177af9ec0e193 at slot 76993>
Nov 27 04:12:51 nat cnode@preprod[975140]: [nat:cardano.node.Mempool:Info:29] [2024-11-27 03:12:51.12 UTC] fromList [("enclosingTime",Object (fromList [("tag",String "RisingEdge")])),("kind",String "TraceMempoolS>
Nov 27 04:12:51 nat cnode@preprod[975140]: [nat:cardano.node.metrics:Notice:29] [2024-11-27 03:12:51.12 UTC] txsSyncDuration = 0
Nov 27 04:12:51 nat cnode@preprod[975140]: [nat:cardano.node.Mempool:Info:29] [2024-11-27 03:12:51.12 UTC] fromList [("enclosingTime",Object (fromList [("contents",Number 2.66822e-4),("tag",String "FallingEdgeWit>
$ journalctl --user -fu app-cnode.slice
Nov 27 04:12:51 nat cnode@preprod[975140]: [nat:cardano.node.Mempool:Info:29] [2024-11-27 03:12:51.12 UTC] fromList [("enclosingTime",Object (fromList [("tag",String "RisingEdge")])),("kind",String "TraceMempoolSynced")]
Nov 27 04:12:51 nat cnode@preprod[975140]: [nat:cardano.node.metrics:Notice:29] [2024-11-27 03:12:51.12 UTC] txsSyncDuration = 0
Nov 27 04:12:51 nat cnode@preprod[975140]: [nat:cardano.node.Mempool:Info:29] [2024-11-27 03:12:51.12 UTC] fromList [("enclosingTime",Object (fromList [("contents",Number 2.66822e-4),("tag",String "FallingEdgeWith")])),("kind",String "TraceMempoolSynced")]
Nov 27 04:12:58 nat cnode@mainnet[982663]: [nat:cardano.node.ChainDB:Notice:23] [2024-11-27 03:12:58.29 UTC] Chain extended, new tip: f931ed71fc0b6a940cb246d481f068b1de87e5a9b1143f45beb5f79b95545417 at slot 141110886
Nov 27 04:13:00 nat cnode@mainnet[982663]: [nat:cardano.node.ChainDB:Notice:23] [2024-11-27 03:13:00.61 UTC] Chain extended, new tip: 254c9806d0e468f1fb3ffb503a6e9e924dae03e9240023035d6707b9143be3cf at slot 141110889
Nov 27 04:13:30 nat cnode@preprod[975140]: [nat:cardano.node.ChainDB:Notice:21] [2024-11-27 03:13:30.20 UTC] Chain extended, new tip: 4bc5a79bd52308e45607fb86f76bf4e580ed55c09f7a489feeca5cec704fef33 at slot 76994010
Nov 27 04:13:30 nat cnode@preprod[975140]: [nat:cardano.node.Mempool:Info:29] [2024-11-27 03:13:30.21 UTC] fromList [("enclosingTime",Object (fromList [("tag",String "RisingEdge")])),("kind",String "TraceMempoolSynced")]
Nov 27 04:13:30 nat cnode@preprod[975140]: [nat:cardano.node.metrics:Notice:29] [2024-11-27 03:13:30.21 UTC] txsSyncDuration = 0
Nov 27 04:13:30 nat cnode@preprod[975140]: [nat:cardano.node.Mempool:Info:29] [2024-11-27 03:13:30.21 UTC] fromList [("enclosingTime",Object (fromList [("contents",Number 2.82809e-4),("tag",String "FallingEdgeWith")])),("kind",String "TraceMempoolSynced")]
Nov 27 04:13:32 nat cnode@mainnet[982663]: [nat:cardano.node.ChainDB:Notice:23] [2024-11-27 03:13:32.43 UTC] Chain extended, new tip: 88bee3572c8a6081e6e37dae5a76c7496f7c90fe9f30dac982d853dae4d504cb at slot 141110921
Nov 27 04:13:37 nat cnode@mainnet[982663]: [nat:cardano.node.ChainDB:Notice:23] [2024-11-27 03:13:37.23 UTC] Chain extended, new tip: e0e51bcd5fc083461236f47d749b5f38b0e383753cf4e76a89e3908a3cb56855 at slot 141110926
^C
Setting bash
aliases
Finally, I created some aliases for bash
and put them in one of my startup files to be able to use all three nodes with cardano-cli
:
$ alias | grep cardano-cli
alias cardano-cli-mainnet='CARDANO_NODE_SOCKET_PATH=~/.local/cardano/chains/mainnet/socket cardano-cli'
alias cardano-cli-preprod='CARDANO_NODE_SOCKET_PATH=~/.local/cardano/chains/preprod/socket cardano-cli'
alias cardano-cli-preview='CARDANO_NODE_SOCKET_PATH=~/.local/cardano/chains/preview/socket cardano-cli'
$ cardano-cli-mainnet query tip --mainnet
{
"block": 11145441,
"epoch": 524,
"era": "Conway",
"hash": "372d014e87886b69f3cf93c2318167aa0da7993538f0c1f32dacae85c7e1970c",
"slot": 141111002,
"slotInEpoch": 106202,
"slotsToEpochEnd": 325798,
"syncProgress": "100.00"
}
$ cardano-cli-preprod query tip --testnet-magic 1
{
"block": 2928764,
"epoch": 182,
"era": "Conway",
"hash": "f26414a5697ffc5f55df0632933865ccfd7bc0189a85f1410316423d54f18b6a",
"slot": 76994094,
"slotInEpoch": 11694,
"slotsToEpochEnd": 420306,
"syncProgress": "100.00"
}
$ cardano-cli-preview query tip --testnet-magic 2
{
"block": 2712398,
"epoch": 764,
"era": "Conway",
"hash": "0ca434a573915d90248a534019191b5e929db4f8d21a1f59324c93cfee1943ed",
"slot": 66021277,
"slotInEpoch": 11677,
"slotsToEpochEnd": 74723,
"syncProgress": "100.00"
}
And this concludes my journey in setting up nodes on mainnet and both testnets in parallel under a user account using pre-compiled binaries and Mithril to reduce effort and time as much as possible.
To summarise, these are the files and directories, we now have for the three chains/networks:
$ tree -L 3 ~/.local/cardano/chains/
/home/sean/.local/cardano/chains/
├── mainnet
│ ├── config
│ │ ├── alonzo-genesis.json
│ │ ├── byron-genesis.json
│ │ ├── config-original.json
│ │ ├── config.json
│ │ ├── conway-genesis.json
│ │ ├── guardrails-script.plutus
│ │ ├── shelley-genesis.json
│ │ └── topology.json
│ ├── db
│ │ ├── gsm
│ │ ├── immutable
│ │ ├── ledger
│ │ ├── lock
│ │ ├── protocolMagicId
│ │ └── volatile
│ ├── env
│ └── socket
├── preprod
│ ├── config
│ │ ├── alonzo-genesis.json
│ │ ├── byron-genesis.json
│ │ ├── config-original.json
│ │ ├── config.json
│ │ ├── conway-genesis.json
│ │ ├── guardrails-script.plutus
│ │ ├── shelley-genesis.json
│ │ └── topology.json
│ ├── db
│ │ ├── gsm
│ │ ├── immutable
│ │ ├── ledger
│ │ ├── lock
│ │ ├── protocolMagicId
│ │ └── volatile
│ ├── env
│ └── socket
└── preview
├── config
│ ├── alonzo-genesis.json
│ ├── byron-genesis.json
│ ├── config-original.json
│ ├── config.json
│ ├── conway-genesis.json
│ ├── guardrails-script.plutus
│ ├── shelley-genesis.json
│ └── topology.json
├── db
│ ├── gsm
│ ├── immutable
│ ├── ledger
│ ├── lock
│ ├── protocolMagicId
│ └── volatile
├── env
└── socket
22 directories, 36 files
$ du -h ~/.local/cardano/chains/ | sort -h
0 /home/sean/.local/cardano/chains/mainnet/db/gsm
0 /home/sean/.local/cardano/chains/preprod/db/gsm
0 /home/sean/.local/cardano/chains/preview/db/gsm
48K /home/sean/.local/cardano/chains/preview/config
52K /home/sean/.local/cardano/chains/preprod/config
1.1M /home/sean/.local/cardano/chains/mainnet/config
1.3M /home/sean/.local/cardano/chains/preview/db/volatile
7.2M /home/sean/.local/cardano/chains/preprod/db/volatile
108M /home/sean/.local/cardano/chains/mainnet/db/volatile
400M /home/sean/.local/cardano/chains/preview/db/ledger
893M /home/sean/.local/cardano/chains/preprod/db/ledger
4.6G /home/sean/.local/cardano/chains/mainnet/db/ledger
8.7G /home/sean/.local/cardano/chains/preprod/db/immutable
9.4G /home/sean/.local/cardano/chains/preview/db/immutable
9.6G /home/sean/.local/cardano/chains/preprod
9.6G /home/sean/.local/cardano/chains/preprod/db
9.8G /home/sean/.local/cardano/chains/preview
9.8G /home/sean/.local/cardano/chains/preview/db
186G /home/sean/.local/cardano/chains/mainnet/db/immutable
191G /home/sean/.local/cardano/chains/mainnet
191G /home/sean/.local/cardano/chains/mainnet/db
210G /home/sean/.local/cardano/chains/
Changelog
2024-01-15:
- Updated to Mithril v2347.0 and Cardano Node 8.7.3.
- Changed location of software and chains to
~/.local/cardano/
.
2024-11-27:
- Updated to Mithril v2445.0 and Cardano Node 10.1.2.