Only this pageAll pages
Powered by GitBook
1 of 44

Kotal Open Source

Loading...

Loading...

Loading...

Loading...

Tutorials

Aptos

Deploy Aptos Devnet Node

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Reference

Aptos

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Deploy Bitcoin RPC Node

Generate JSON-RPC password secret

Bitcoin nodes that enable JSON-RPC server are required to use basic authentication while calling JSON-RPC methods.

rpc-user-password.yaml
# WARNING: DON'T use the following secret in production
apiVersion: v1
kind: Secret
metadata:
  name: kotal-rpc-user-password
stringData:
  password: s3cr3t

Apply rpc-user-password.yaml to create the password secret:

kubectl apply -f rpc-user-password.yaml

Deploy Bitcoin RPC Node

bitcoin.yaml
apiVersion: bitcoin.kotal.io/v1alpha1
kind: Node
metadata:
  name: bitcoin-node
spec:
  network: mainnet
  rpc: true
  rpcUsers:
    - username: kotal
      passwordSecretName: kotal-rpc-user-password

Apply bitcoin.yaml manifest:

kubectl apply -f bitcoin.yaml

Kotal operator will notice your bitcoin-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.

You can fetch the deployed Bitcoin Node using:

kubectl get nodes.bitcoin

It will return an output similar to the following:

NAME            NETWORK    CLIENT
bitcoin-node    mainnet    bitcoincore

Fetch Node Logs

Get the pods that has been created by Kotal for the node:

kubectl get pods

It will return an output similar to the following:

NAME              READY   STATUS    RESTARTS   AGE
bitcoin-node-0    1/1     Running   0          1m

Get the logs of the running node:

kubectl logs -f bitcoin-node-0

It will return node logs similar to the following:

2022-04-09T18:26:45Z Bitcoin Core version v22.0.0 (release build)
2022-04-09T18:26:45Z InitParameterInteraction: parameter interaction: -bind set -> setting -listen=1
2022-04-09T18:26:45Z Assuming ancestors of block 00000000000000000008a89e854d57e5667df88f1cdef6fde2fbca1de5b639ad have valid signatures.
2022-04-09T18:26:45Z Setting nMinimumChainWork=00000000000000000000000000000000000000001fa4663bbbe19f82de910280
2022-04-09T18:26:45Z Using the 'sse4(1way),sse41(4way),avx2(8way)' SHA256 implementation
2022-04-09T18:26:45Z Using RdRand as an additional entropy source
2022-04-09T18:26:45Z Wallet disabled!
...
2022-04-09T18:27:02Z Synchronizing blockheaders, height: 9999 (~1.44%)
2022-04-09T18:27:02Z Synchronizing blockheaders, height: 11999 (~1.73%)
2022-04-09T18:27:02Z Synchronizing blockheaders, height: 13999 (~2.02%)
2022-04-09T18:27:02Z Synchronizing blockheaders, height: 15999 (~2.31%)
2022-04-09T18:27:02Z Synchronizing blockheaders, height: 17999 (~2.61%)
2022-04-09T18:27:03Z Synchronizing blockheaders, height: 19999 (~2.90%)
2022-04-09T18:27:03Z Synchronizing blockheaders, height: 21999 (~3.21%)
2022-04-09T18:27:03Z Synchronizing blockheaders, height: 23999 (~3.51%)
2022-04-09T18:27:04Z Synchronizing blockheaders, height: 25999 (~3.82%)
2022-04-09T18:27:04Z Synchronizing blockheaders, height: 27999 (~4.13%)
2022-04-09T18:27:04Z Synchronizing blockheaders, height: 29999 (~4.43%)
...

Call JSON-RPC Method

By default, Bitcoin node JSON-RPC server port is 8332, which can be changed using rpcPort.

Forward localhost:8332 calls to the node pod:

kubectl port-forward bitcoin-node-0 8332

In another terminal window call getblockhash JSON-RPC method to get the genesis block hash:

curl --user "kotal:s3cr3t" --data-binary '{"jsonrpc": "1.0", "id": 1, "method": "getblockhash", "params": [0]}' -H 'content-type: text/plain;' http://0.0.0.0:8332

You will get JSON result similar to the following:

{
  "result":"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
  "error":null,
  "id":1
}

Finally you can delete the node by:

kubectl delete -f bitcoin.yaml

Kubernetes garbage collector will delete all the resources that has been created by Bitcoin Node controller.

The following manifest describes a Bitcoin node that syncs Bitcoin mainnet network: mainnet, enables HTTP JSON-RPC server rpc: true, defines JSON-RPC user credentials rpcUsers: ... and uses client:

Bitcoin Core

Quick Start

Create rinkeby.yaml manifest that describes an Ethereum node which uses go-ethereum client, connecting to rinkeby network, and enabling JSON-RPC server:

rinkeby.yaml
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
  name: rinkeby-geth-node
spec:
  network: rinkeby
  client: geth
  rpc: true

Deploy the node using kubectl:

kubectl apply -f rinkeby.yaml

Within a couple of seconds, the node will be up and running. You can get the node using:

kubectl get nodes.ethereum

It will return an output similar to the following:

NAME                 CLIENT   Network   Consensus
rinkeby-geth-node    geth     rinkeby   poa

Kotal will create all the necessary pods, volumes, services for the node. Get the pods by:

kubectl get pods

It will return an output similar to the following:

NAME                     READY   STATUS    RESTARTS   AGE
rinkeby-geth-node-0      1/1     Running   0          1m

Finally delete the node by:

kubectl delete -f rinkeby.yaml

Congratulations!

Welcome

Kotal is multi-client, protocol-agnostic, and cloud-agnostic Blockchain Kubernetes Operator that makes it easy to deploy highly-available self-managing self-healing blockchain infrastructure on any cloud.

Kotal has been tested on Amazon Web Service, Google Cloud Platform, Microsoft Azure, DigitalOcean, Alibab Cloud, Tencent cloud 🤯.

What can I do with Kotal ?

  • Deploy nodes across 10 Blockchain protocols (Aptos, Bitcoin, Chainkstack, Ethereum, Filecoin, IPFS, NEAR, Polkadot, Stacks)

  • Upgrade and Downgrade node client software

  • Load validator keys and start producing blocks

  • Manage storage and resources (CPU & Memory) allocated to the node

  • Manage Secrets (private keys, passwords, tokens, certificates)

  • Monitor resources utilization

  • Fetch real time logs

  • Create TLS-secure API endpoints

  • View API endpoints usage

  • Create workspaces of nodes and resources

  • Invite members to workspaces and assign roles

Bitcoin

We've extended Kubernetes with Node custom resource which can be used to deploy Bitcoin nodes from the given spec.

Node

apiVersion: bitcoin.kotal.io/v1alpha1
kind: Node
metadata:
  Name: bitcoin-node
spec:
  network: mainnet
  rpc: true
  ...

For all the fields associated with the Node API resource:

kubectl explain nodes --api-version bitcoin.kotal.io/v1alpha1
kubectl explain nodes.spec --api-version bitcoin.kotal.io/v1alpha1

Kotal is an alternative to centralized API gateway, Node as a service, and Staking service providers. Like Infura in Ethereum ecosystem, Onfinality in Polkadot ecosystem, and Hiro in Stacks ecosystem.

Node is Bitcoin node using client, connecting to and syncing a specific chain.

Full Bitcoin node reference is documented .

open source
Bitcoin Core
here

Support

You can support us by donating Eth or any token to our ENS address farghaly.eth or directly to the following Ethereum address:

0x5dfA5dB515748f3E2BCc8677A9332f4aFFad5A5E

Thank you!

Ethereum

We've extended Kubernetes with Node custom resource which can be used to deploy Ethereum nodes from the given spec.

apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
  name: my-node
spec:
  # your node spec goes here

Using Ethereum Node custom resource, you can describe any public or private network node you want, and Kotal will create all the necessary Kubernetes resources like pods, persistent volumes, services, configmaps, and secrets for you.

If you want to get all the deployted ethereum Node(s):

$ kubectl get nodes.ethereum

Which will report node name, client, network, and consensus.

If you want to get all the fields associated with ethereum Node:

$ kubectl explain nodes --api-version ethereum.kotal.io/v1alpha1

Multi-client Support

Kotal supports the following Ethereum 1 clients:

For a comprehensive reference on Ethereum Node, check our

Support for OpenEthereum (parity) client has been deprecated. OpenEthereum team is working with Erigon on a smooth transition path for users. More information can be found

ethereum reference
here
Hyperledger Besu
Go-Ethereum (Geth)
Nethermind

Installation

Requirements

  • Kubernetes cluster

  • Cert Manager

Kubernetes cluster

Cert Manager

Kotal webhook component uses cert-manager for issuing certificates to default and validate your Blockchain resources such as nodes, beacon nodes, ipfs peers ... etc.

Install kotal

The latest version of Kotal operator v0.3.0 can be installed into your Kubernetes cluster simply by:

kubectl apply -f https://github.com/kotalco/kotal/releases/download/v0.3.0/kotal.yaml

For development and testing purposes we recommend using (Kubernetes in Docker), it's an easy way to create and tear down kubernetes clusters in seconds. For staging and production purposes you can use any public cloud kubernetes as a service like , or .

kind installation guide can be found .

Cert Manager is a native Kubernetes certificate management controller. It can help with issuing certificates from a variety of sources, such as , , a simple signing key pair, or self-signed. It will ensure certificates are valid and up to date, and attempt to renew certificates at a configured time before expiry.

cert-manager installation guide can be found .

kind
Amazon EKS
Azure AKS
Google GKE
here
Let’s Encrypt
HashiCorp Vault
here

Deploy Private Clique Network

Deploy Private Network Node

In this tutorial we will use the following private keys and their corresponding addresses.

DON'T use these keys in production.

Address
Private Key

0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa

fb5411342ae51291447515c89bcf6a057e3dbd0b51e060c45cb73406c38f851d

0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d

153b174f5e9948ae4678baed54f88244cc9c39d56b9f17ecef93d7ede633f56b

0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a

89b03c4de62d61be16d22e09c8a48929a9bccd11fa6b37809cfef290292bcba3

Let's describe an Ethereum Node that uses a custom genesis block to join a private Proof of Authority network using Clique consensus configuration in the genesis block.

besu-clique-node.yaml
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
  name: besu-clique-node
spec:
  client: besu
  nodePrivateKeySecretName: besu-clique-nodekey
  rpc: true
  genesis:
    chainId: 4444
    networkId: 4444
    clique:
      signers:
        - "0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa"
        - "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
        - "0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a"

In this node, we're using Hyperledger besu client client: besu, enabling JSON-RPC server rpc: true so we can query number of peers later in this tutorial, and we're loading the node private key from Kubernetes secretd called besu-clique-nodekey.

The node private key will give the node a unique identity and node URL, and will allow the node to generate blocks, because the address 0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa that's corresponding to the node private key is in the initial block signers.

We're defining a genesis block that uses the value 4444 as network and chain identifier, and we start the chain with 3 signers as defined by spec.genesis.clique.signers.

This node private key secret can be created by:

kubectl create secret generic besu-clique-nodekey --from-literal=key=fb5411342ae51291447515c89bcf6a057e3dbd0b51e060c45cb73406c38f851d

Private key must not start with 0x, and must be stored in secret data field called key.

Let's deploy the node:

kubectl apply -f besu-clique-node.yaml

Kotal operator will notice your besu-clique-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.

You can fetch the deployed Ethereum Node using:

kubectl get nodes.ethereum

It will return an output similar to the following:

NAME                 CLIENT   Consensus   Network
besu-clique-node     besu     poa         private

Fetch Node Logs

Get the pods that has been created by Kotal for the node:

kubectl get pods

It will return an output similar to the following:

NAME                  READY   STATUS    RESTARTS   AGE
besu-clique-node-0    1/1     Running   0          1m

Get the logs of the running node:

kubectl logs -f besu-clique-node-0

Deploy a Second Node

Let's deploy another go-ethereum node, and connect it to the previous node in our private proof of authority network.

Genesis block must be the same in both nodes, or they will fork at genesis block, and won't reach consensus.

geth-clique-node.yaml
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
  name: geth-clique-node
spec:
  client: geth
  miner: true
  coinbase: "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
  import:
    privateKeySecretName: geth-clique-account-key
    passwordSecretName: geth-clique-account-password
  staticNodes:
    - besu-clique-node
  genesis:
    chainId: 4444
    networkId: 4444
    clique:
      signers:
        - "0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa"
        - "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
        - "0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a"

In this node, we're using go-ethereum client client: geth, starting the PoA consensus engine miner: true, setting the second address in the genesis signers list spec.genesis.clique.signers as the coinbase coinbase: "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d", and loading the signer account private key and password from kubernetes secrets privateKeySecretName: ... and passwordSecretName: .... We're connecting to the first node using staticNodes option which accepts Node name or enode url.

staticNodes accept Node name or enode URL. Node name has the format of name.namespace, namespace is optional if Node is in the same namespace. If the node doesn't exist, or is not up and running yet, Kotal will not raise an error.

You can create the private key and password secrets using:

kubectl create secret generic geth-clique-account-key --from-literal=key=153b174f5e9948ae4678baed54f88244cc9c39d56b9f17ecef93d7ede633f56b
kubectl create secret generic geth-clique-account-password --from-literal=password=s3cr3t

Deploy the second node using:

kubectl apply -f geth-clique-node.yaml

Kotal operator will notice your second geth-clique-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.

You can fetch the deployed Ethereum Nodes using:

kubectl get nodes.ethereum

It will return an output similar to the following:

NAME                 CLIENT   Consensus   Network
besu-clique-node     besu     poa         private
geth-clique-node     geth     poa         private

Call JSON-RPC Method net_peerCount

Get the pods that has been created by Kotal for the node:

kubectl get pods

It will return an output similar to the following:

NAME                  READY   STATUS    RESTARTS   AGE
besu-clique-node-0    1/1     Running   0          1m
geth-clique-node-0    1/1     Running   0          1m

Forward localhost:8545 calls to the node pod:

kubectl port-forward besu-clique-node-0 8545

In another terminal window call net_peerCount JSON-RPC method

curl -X POST -H 'content-type: application/json' --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":32}' http://127.0.0.1:8545

You will get JSON result similar to the following:

{
  "jsonrpc" : "2.0",
  "id" : 32,
  "result" : "0x1"
}

Homework

Deploy a third node that uses Nethermind client, and signing blocks using the third key in the signers list spec.genesis.clique.signers. Nethermind client is similar to geth, you will import signer account private key and password from kubernetes secrets, and use the same genesis as the other nodes.

Finally you can delete all the nodes by:

kubectl delete nodes.ethereum --all

Kubernetes garbage collector will delete all the resources that has been created by Kotal Ethereum Node controller.

Deploy Public Rinkeby Node

Deploy Rinkeby Node

Rinkeby is a Proof of Authority public Ethereum test network, used by developers to test their dApps.

The following manifest describes an Ethereum node that joins rinkeby network network: rinkeby, and uses Hyperledger Besu client client: besu:

rinkeby.yaml
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
  name: rinkeby-besu-node
spec:
  network: rinkeby
  client: besu

Joining any Ethereum network is as easy as setting node's spec.network value, which accepts values like mainnet, rinkeby, goerli, xdai ... etc. After the node is created, you can't change spec.network.

Apply rinkeby.yaml manifest:

kubectl apply -f rinkeby.yaml

Kotal operator will notice your rinkeby-besu-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.

You can fetch the deployed Ethereum Node using:

kubectl get nodes.ethereum

It will return an output similar to the following:

NAME                 CLIENT   Consensus   Network
rinkeby-besu-node    besu     poa         rinkeby

Fetch Node Logs

Get the pods that has been created by Kotal for the node:

kubectl get pods

It will return an output similar to the following:

NAME                  READY   STATUS    RESTARTS   AGE
rinkeby-besu-node-0   1/1     Running   0          1m

If pod STATUS is Pending, most probably it's due to not enough cpu and memory, because Kotal allocates lots of cpu cores and memory for public nodes. The required node resources can be changed using spec.resources.cpu, spec.resources.memory, and spec.resources.storage.

Get the logs of the running node:

kubectl logs -f rinkeby-besu-node-0

Call JSON-RPC Method

Let's update our node by enabling JSON-RPC HTTP server:

rinkeby.yaml
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
  name: rinkeby-besu-node
spec:
  network: rinkeby
  client: besu
  rpc: true

Kotal defaults node missing spec parameters like:

  • JSON-RPC HTTP server port is defaulted to 8545.

  • JSON-RPC HTTP server enabled modules are defaulted to: eth, net, and web3.

  • Blocks Synchronization mode is defauled to fast in public networks.

Apply the new version of rinkeby.yaml:

kubectl apply -f rinkeby.yaml

Forward localhost:8545 calls to the node pod:

kubectl port-forward rinkeby-besu-node-0 8545

In another terminal window call eth_syncing JSON-RPC method

curl -X POST -H 'content-type: application/json' --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":32}' http://127.0.0.1:8545

You will get JSON result similar to the following:

{
  "jsonrpc" : "2.0",
  "id" : 32,
  "result" : {
    "startingBlock" : "0x0",
    "currentBlock" : "0x1518",
    "highestBlock" : "0x9567a3",
    "pulledStates" : "0x203ca",
    "knownStates" : "0x200636"
  }
}

Finally you can delete the node by:

kubectl delete -f rinkeby.yaml

node.ethereum.kotal.io "rinkeby-besu-node" deleted

Kubernetes garbage collector will delete all the resources that has been created by Kotal Ethereum Node controller.

Deploy Validator Client

Deploy Validator Client

In this validator client, we're using ConsenSys Teku Ethereum 2.0 client client: teku, validating pyrmont network blockchain network: pyrmont, connecting to beacon node endpoint using beaconEndpoints: ..., setting the graffiti text to include in the propsed blocks graffiti: validated by Kotal, and loading a validator keystore using keystores: ... from a kubernetes secret called my-validator.

The keystores loaded using spec.keystores[].secretName from kubernetes secret, must contain two data keys:

  • keystore key hodling the BLS12-381 keystore JSON file

  • password key holding the encryption key of the keystore.

Let's deploy the validator client:

Kotal operator will notice your teku-validator and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.

You can fetch the deployed Ethereum 2.0 Validator using:

It will return an output similar to the following:

Fetch Validator Logs

Get the pods created for the validator client:

It will return an output similar to the following:

Get the logs of the running validator pod:

You'll get an output similar to the following:

Finally delete the validator client:

Kubernetes garbage collector will delete all the resources that has been created by Kotal Ethereum 2.0 Validator controller.

For a comprehensive reference on Ethereum Node and default spec parameter values, check our

Staking is the act of depositing 32 ETH to activate validator software. As a validator you’ll be responsible for storing data, processing transactions, and adding new blocks to the blockchain. This will keep Ethereum secure for everyone and earn you new ETH in the process. This process, known as proof-of-stake, is being introduced by the Beacon Chain.

ethereum reference
validator.yaml
apiVersion: ethereum2.kotal.io/v1alpha1
kind: Validator
metadata:
  name: teku-validator
spec:
  client: teku
  network: pyrmont
  beaconEndpoints:
    - http://teku-beacon-node:9999
  graffiti: Validated by Kotal
  keystores:
    - secretName: my-validator
kubectl apply -f validator.yaml
kubectl get validators
NAME             CLIENT   NETWORK   AGE
teku-validator   teku     pyrmont   1m
kubectl get pods
NAME                 READY   STATUS    RESTARTS   AGE
teku-validator-0     1/1     Running   0          1m
kubectl logs -f teku-validator-0
...
21:21:30.668 INFO  - Storing validator data in: /opt/teku/kotal-data/validator
21:21:30.751 INFO  - Loading 1 validator keys...
21:21:31.759 INFO  - Loaded 1 Validators: 83dbb18
...
kubectl delete validator teku-validator

Deploy Private Ethash Network

Deploy Private Network Node

In this tutorial we will use the following private keys and their corresponding addresses.

DON'T use these keys in production.

Address
Private Key

0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa

fb5411342ae51291447515c89bcf6a057e3dbd0b51e060c45cb73406c38f851d

0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d

153b174f5e9948ae4678baed54f88244cc9c39d56b9f17ecef93d7ede633f56b

0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a

89b03c4de62d61be16d22e09c8a48929a9bccd11fa6b37809cfef290292bcba3

Let's describe an Ethereum Node that uses a custom genesis block to join a private Proof of Work network using Ethash consensus configuration in the genesis block.

besu-ethash-node.yaml
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
  name: besu-ethash-node
spec:
  client: besu
  nodePrivateKeySecretName: besu-ethash-nodekey
  rpc: true
  miner: true
  coinbase: "0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa"
  genesis:
    chainId: 4444
    networkId: 4444
    ethash: {}

In this node, we're using Hyperledger besu client client: besu, enabling JSON-RPC server rpc: true so we can query number of peers later in this tutorial, turning on Proof of Work mining miner: true, setting the address that will collect block reward using coinbase, and we're loading the node private key from Kubernetes secretd called besu-ethash-nodekey, this is the private from which the coinbase address is derived.

We're defining a genesis block that uses the value 4444 as network and chain identifier, and used ethash proof of work consensus engine.

ethash is required in proof of work networks, even if it's empty like in our example: ethash: {}.

This node private key secret can be created by:

kubectl create secret generic besu-ethash-nodekey --from-literal=key=fb5411342ae51291447515c89bcf6a057e3dbd0b51e060c45cb73406c38f851d

Private key must not start with 0x, and must be stored in secret data field called key.

Let's deploy the node:

kubectl apply -f besu-ethash-node.yaml

Kotal operator will notice your besu-ethash-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.

You can fetch the deployed Ethereum Node using:

kubectl get nodes.ethereum

It will return an output similar to the following:

NAME                 CLIENT   Consensus   Network
besu-ethash-node     besu     pow         private

Fetch Node Logs

Get the pods that has been created by Kotal for the node:

kubectl get pods

It will return an output similar to the following:

NAME                  READY   STATUS    RESTARTS   AGE
besu-ethash-node-0    1/1     Running   0          1m

Get the logs of the running node:

kubectl logs -f besu-ethash-node-0

Deploy a Second Node

Let's deploy another go-ethereum node, and connect it to the previous node in our private proof of work network.

Genesis block must be the same in both nodes, or they will fork at genesis block, and won't reach consensus.

geth-ethash-node.yaml
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
  name: geth-ethash-node
spec:
  client: geth
  rpc: true
  miner: true
  coinbase: "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
  import:
    privateKeySecretName: geth-ethash-account-key
    passwordSecretName: geth-ethash-account-password
  staticNodes:
    - besu-ethash-node
  genesis:
    chainId: 4444
    networkId: 4444
    ethash: {}

In this node, we're using go-ethereum client client: geth, turning on Proof of Work mining miner: true, setting the address that will collect block reward using coinbase, and loading the miner account private key and password from kubernetes secrets privateKeySecretName: ... and passwordSecretName: .... We're connecting to the first node using staticNodes option which accepts Node name or enode url.

staticNodes accept Node name or enode URL. Node name has the format of name.namespace, namespace is optional if Node is in the same namespace. If the node doesn't exist, or is not up and running yet, Kotal will not raise an error.

You can create the private key and password secrets using:

kubectl create secret generic geth-ethash-account-key --from-literal=key=153b174f5e9948ae4678baed54f88244cc9c39d56b9f17ecef93d7ede633f56b
kubectl create secret generic geth-ethash-account-password --from-literal=password=s3cr3t

Deploy the second node using:

kubectl apply -f geth-ethash-node.yaml

Kotal operator will notice your second geth-ethash-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.

You can fetch the deployed Ethereum Nodes using:

kubectl get nodes.ethereum

It will return an output similar to the following:

NAME                 CLIENT   Consensus   Network
besu-ethash-node     besu     pow         private
geth-ethash-node     geth     pow         private

Call JSON-RPC Method net_peerCount

Get the pods that has been created by Kotal for the node:

kubectl get pods

It will return an output similar to the following:

NAME                  READY   STATUS    RESTARTS   AGE
besu-ethash-node-0    1/1     Running   0          1m
geth-ethash-node-0    1/1     Running   0          1m

Forward localhost:8545 calls to the node pod:

kubectl port-forward besu-ethash-node-0 8545

In another terminal window call net_peerCount JSON-RPC method

curl -X POST -H 'content-type: application/json' --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":32}' http://127.0.0.1:8545

You will get JSON result similar to the following:

{
  "jsonrpc" : "2.0",
  "id" : 32,
  "result" : "0x1"
}

Homework

Deploy a third node that uses Nethermind client, and use the third private key and address from the table above. Nethermind client is similar to geth, you will import signer account private key and password from kubernetes secrets, and use the same genesis as the other nodes.

Finally you can delete all the nodes by:

kubectl delete nodes.ethereum --all

Kubernetes garbage collector will delete all the resources that has been created by Kotal Ethereum Node controller.

Deploy Private IBFT 2.0 Network

Deploy Private Network Node

In this tutorial we will use the following private keys and their corresponding addresses.

DON'T use these keys in production.

Address
Private Key

0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa

fb5411342ae51291447515c89bcf6a057e3dbd0b51e060c45cb73406c38f851d

0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d

153b174f5e9948ae4678baed54f88244cc9c39d56b9f17ecef93d7ede633f56b

0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a

89b03c4de62d61be16d22e09c8a48929a9bccd11fa6b37809cfef290292bcba3

Let's describe an Ethereum Node that uses a custom genesis block to join a private Proof of Authority network using ibft2 consensus configuration in the genesis block.

besu-ibft2-node.yaml
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
  name: besu-ibft2-node
spec:
  client: besu
  nodePrivateKeySecretName: besu-ibft2-nodekey
  rpc: true
  genesis:
    chainId: 4444
    networkId: 4444
    ibft2:
      validators:
        - "0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa"
        - "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
        - "0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a"

In this node, we're using Hyperledger besu client client: besu, enabling JSON-RPC server rpc: true so we can query number of peers later in this tutorial, and we're loading the node private key from Kubernetes secretd called besu-ibft2-nodekey.

The node private key will give the node a unique identity and node URL, and will allow the node to generate blocks, because the address 0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa that's corresponding to the node private key is in the initial block validators.

We're defining a genesis block that uses the value 4444 as network and chain identifier, and we start the chain with 3 validators as defined by spec.genesis.ibft2.validators.

This node private key secret can be created by:

kubectl create secret generic besu-ibft2-nodekey --from-literal=key=fb5411342ae51291447515c89bcf6a057e3dbd0b51e060c45cb73406c38f851d

Private key must not start with 0x, and must be stored in secret data field called key.

Let's deploy the node:

kubectl apply -f besu-ibft2-node.yaml

Kotal operator will notice your besu-ibft2-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.

You can fetch the deployed Ethereum Node using:

kubectl get nodes.ethereum

It will return an output similar to the following:

NAME                 CLIENT   Consensus   Network
besu-ibft2-node      besu     ibft2       private

Fetch Node Logs

Get the pods that has been created by Kotal for the node:

kubectl get pods

It will return an output similar to the following:

NAME                  READY   STATUS    RESTARTS   AGE
besu-ibft2-node-0     1/1     Running   0          1m

Get the logs of the running node:

kubectl logs -f besu-ibft2-node-0

Deploy a Second Node

Let's deploy another go-ethereum node, and connect it to the previous node in our private proof of authority network.

Genesis block must be the same in both nodes, or they will fork at genesis block, and won't reach consensus.

geth-ibft2-node.yaml
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
  name: geth-ibft2-node
spec:
  client: geth
  miner: true
  coinbase: "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
  import:
    privateKeySecretName: geth-ibft2-account-key
    passwordSecretName: geth-ibft2-account-password
  staticNodes:
    - besu-ibft2-node
  genesis:
    chainId: 4444
    networkId: 4444
    ibft2:
      validators:
        - "0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa"
        - "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
        - "0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a"

In this node, we're using go-ethereum client client: geth, starting the PoA consensus engine miner: true, setting the second address in the genesis validators list spec.genesis.ibft2.validators as the coinbase coinbase: "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d", and loading the validator account private key and password from kubernetes secrets privateKeySecretName: ... and passwordSecretName: .... We're connecting to the first node using staticNodes option which accepts Node name or enode url.

staticNodes accept Node name or enode URL. Node name has the format of name.namespace, namespace is optional if Node is in the same namespace. If the node doesn't exist, or is not up and running yet, Kotal will not raise an error.

You can create the private key and password secrets using:

kubectl create secret generic geth-ibft2-account-key --from-literal=key=153b174f5e9948ae4678baed54f88244cc9c39d56b9f17ecef93d7ede633f56b
kubectl create secret generic geth-ibft2-account-password --from-literal=password=s3cr3t

Deploy the second node using:

kubectl apply -f geth-ibft2-node.yaml

Kotal operator will notice your second geth-ibft2-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.

You can fetch the deployed Ethereum Nodes using:

kubectl get nodes.ethereum

It will return an output similar to the following:

NAME                 CLIENT   Consensus   Network
besu-ibft2-node      besu     poa         private
geth-ibft2-node      geth     poa         private

Call JSON-RPC Method net_peerCount

Get the pods that has been created by Kotal for the node:

kubectl get pods

It will return an output similar to the following:

NAME                  READY   STATUS    RESTARTS   AGE
besu-ibft2-node-0     1/1     Running   0          1m
geth-ibft2-node-0     1/1     Running   0          1m

Forward localhost:8545 calls to the node pod:

kubectl port-forward besu-ibft2-node-0 8545

In another terminal window call net_peerCount JSON-RPC method

curl -X POST -H 'content-type: application/json' --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":32}' http://127.0.0.1:8545

You will get JSON result similar to the following:

{
  "jsonrpc" : "2.0",
  "id" : 32,
  "result" : "0x1"
}

Homework

Deploy a third node that uses Nethermind client, and signing blocks using the third key in the validators list spec.genesis.ibft2.validators. Nethermind client is similar to geth, you will import validator account private key and password from kubernetes secrets, and use the same genesis as the other nodes.

Finally you can delete all the nodes by:

kubectl delete nodes.ethereum --all

Kubernetes garbage collector will delete all the resources that has been created by Kotal Ethereum Node controller.

source

Deploy Beacon Node

Deploy Beacon Node

beacon.yaml
apiVersion: ethereum2.kotal.io/v1alpha1
kind: BeaconNode
metadata:
  name: teku-beacon-node
spec:
  network: pyrmont
  client: teku
  rest: true
  restPort: 8888
  eth1Endpoints:
    - http://goerli-besu-node:8545

Let's deploy the beacon node:

kubectl apply -f beacon.yaml

Kotal operator will notice your teku-beacon-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.

You can fetch the deployed Ethereum 2.0 BeaconNode using:

kubectl get beaconnodes

It will return an output similar to the following:

NAME               CLIENT   Network   AGE
teku-beacon-node   teku     pyrmont   1m

Fetch Beacon Node Logs

Get the pods created for the beacon node:

kubectl get pods

It will return an output similar to the following:

NAME                 READY   STATUS    RESTARTS   AGE
teku-beacon-node-0   1/1     Running   0          1m

Get the logs of the running beacon node:

kubectl logs -f teku-beacon-node-0

Call /eth/v1/beacon/genesis REST API

Get the service created for the beacon node:

kubectl get services

It will return an output similar to the following:

NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
teku-beacon-node   ClusterIP   10.96.197.218   <none>        9000/UDP,9000/TCP,8888/TCP   7s

Forward the localhost:8888 calls to the beacon node

kubectl port-forward teku-beacon-node-0 8888

In another terminal window, send REST API call to get chain genesis details:

curl localhost:8888/eth/v1/beacon/genesis

You'll get a result similar to the following:

{
  "data": {
    "genesis_time": "1606824023",
    "genesis_validators_root": "0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95",
    "genesis_fork_version": "0x00000000"
  }
}

Finally delete the beacon node:

kubectl delete beaconnode teku-beacon-node

Kubernetes garbage collector will delete all the resources that has been created by Kotal Ethereum 2.0 BeaconNode controller.

NEAR

We've extended Kubernetes with Node custom resource which can be used to deploy NEAR nodes from the given spec.

Node

apiVersion: near.kotal.io/v1alpha1
kind: Node
metadata:
  Name: near-node
spec:
  network: mainnet
  rpc: true

For all the fields associated with the Node API resource:

kubectl explain nodes --api-version near.kotal.io/v1alpha1
kubectl explain nodes.spec --api-version near.kotal.io/v1alpha1

Ethereum 2.0

We've extended Kubernetes with BeaconNode and Validator custom resources which can be used to deploy Ethereum 2.0 beacon nodes and validator clients from the given spec.

Kotal seperates between beacon node and validator client by using different API resources BeaconNode and Validator. So you can't run a beacon node and validator client in the same process/container.

Beacon Node

BeaconNode is Ethereum 2.0 beacon node -optionally- connecting to Ethereum 1 endpoint and syncing the beacon chain.

Here's an example of ConsenSys Teku beacon node BeaconNode syncing mainnet beacon chain, connecting to Ethereum 1 JSON RPC endpoint, enabling REST API server which is listening at port 8888:

apiVersion: ethereum2.kotal.io/v1alpha1
kind: BeaconNode
metadata:
  name: teku-beacon-node
spec:
  network: mainnet
  client: teku
  rest: true
  restPort: 8888
  eth1Endpoints:
    - http://besu-mainnet-node:8545

For all the fields associated with the BeaconNode API resource:

kubectl explain beaconnode --api-version ethereum2.kotal.io/v1alpha1
kubectl explain beaconnode.spec --api-version ethereum2.kotal.io/v1alpha1

Validator Client

Validator is Ethereum 2.0 validator client connecting to beacon node endpoint and validating blocks using the loaded keystores.

Here's an example of ConsenSys Teku validator client connecting to beacon node endpoint, validating pyrmont blocks using 1 loaded validator keystore from its secret:

apiVersion: ethereum2.kotal.io/v1alpha1
kind: Validator
metadata:
  name: teku-validator
spec:
  network: pyrmont
  client: teku
  beaconEndpoints:
    - http://teku-beacon-node:8888
  graffiti: Validated by Kotal
  keystores:
    - secretName: my-validator

For all the fields associated with the Validator API resource:

kubectl explain validator --api-version ethereum2.kotal.io/v1alpha1
kubectl explain validator.spec --api-version ethereum2.kotal.io/v1alpha1
kubectl explain validator.spec.keystores --api-version ethereum2.kotal.io/v1alpha1

Multi-client Support

Kotal supports the following Ethereum 2.0 beacon node and validator clients:

Setting validator or beacon node client is as simple as changing the spec.client to the desired client.

Chainlink

We've extended Kubernetes with Node custom resource which can be used to deploy Chainlink nodes from the given spec.

apiVersion: chainlink.kotal.io/v1alpha1
kind: Node
metadata:
  name: my-node
spec:
  # your node spec goes here

Using Chainlink Node custom resource, you can describe any chainlink node, connect to EVM chain node, add jobs and satisfy requests, and Kotal will create all the necessary Kubernetes resources like pods, persistent volumes, services, configmaps, and secrets for you.

If you want to get all the deployted chainlink Node(s):

kubectl get nodes.chainlink

Which will report node name, client, Ethereum chain ID, and Link contract address.

If you want to get all the fields associated with chainlink Node:

kubectl explain nodes --api-version chainlink.kotal.io/v1alpha1

The Beacon Chain is the coordination mechanism of the new network, responsible for creating new blocks, making sure those new blocks are valid, and rewarding validators with ETH for keeping the network secure.

In this beacon node, we're using ConsenSys Teku Ethereum 2.0 client client: teku, and syncing the pyrmont network beacon chain network: pyrmont. We also enable REST API server rest: true at port 8888 restPort: 8888. We're connecting to Ethereum 1 endpoint eth1Endpoints: .... Check Ethereum on how to deploy an Ethereum node.

Node is NEAR node using client, connecting to and syncing a specific chain, and optionally validating blocks.

Full NEAR node reference is documented .

Full beacon node reference is documented .

Full validator client reference is documented .

by ConsenSys.

by Sigma Prime.

by Prysmatic Labs.

by Status.im.

For a comprehensive reference on Chainlink Node, check our

Source
tutorial
NEAR Core
here
here
here
Teku
Lighthouse
Prysm
Nimbus
chainlink reference

Polkadot

Polkadot is a sharded protocol that enables blockchain networks to operate together seamlessly. Polkadot is a 100% open-source project created to enable a decentralized web and better society.

We've extended Kubernetes with Node custom resource which can be used to Polkadot, Kusama, Rococo, and substrate-based chains from the given spec.

Node

apiVersion: polkadot.kotal.io/v1alpha1
kind: Node
metadata:
  Name: kusama-node
spec:
  network: kusama
  rpc: true

For all the fields associated with the Node API resource:

kubectl explain nodes --api-version polkadot.kotal.io/v1alpha1
kubectl explain nodes.spec --api-version polkadot.kotal.io/v1alpha1

Node is Polkadot node using client, connecting to and syncing a specific chain, and optionally validating blocks.

Full polkadot node reference is documented .

parity polkadot
here

Deploy Chainlink Node

Prerequisites

Ethereum Node

Chainlink node requires access to an EVM chain node with WebSocket server enabled. Here's how to deploy a simple Ethereum Rinkeby node with WebSocket server enabled:

apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
  name: besu-rinkeby-node
spec:
  network: rinkeby
  client: besu
  ws: true

PostgreSQL Database

You can use a hosted database a service to obtain PostgreSQL database:

Keystore and API Password

Chainlink node requires a strong password for securing access to keystore (wallet) and API. We will store this password in Kubernetes secret my-password:

apiVersion: v1
kind: Secret
metadata:
  name: my-password
stringData:
  password: fE2xXKDnR3ns489X

TLS Certificate

# create self-signed certificate issuer
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: self-signed-issuer
spec:
  selfSigned: {}
---
# create certificate for chainlink node
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: chainlink-node-cert
spec:
  dnsNames:
    - "chainlink-node.svc"
    - "chainlink-node.svc.cluster.local"
  # store tls.crt and tls.key in this kubernetes secret
  secretName: chainlink-node-cert
  issuerRef:
    name: self-signed-issuer

Deploying Chainlink Node

With access to Ethereum Rinkeby node, PostgreSQL database, tls certificate and a strong password. We're ready to deploy our Chainlink node to create jobs and satisfy requests:

chainlink.yaml
apiVersion: chainlink.kotal.io/v1alpha1
kind: Node
metadata:
  name: chainlink-node
spec:
  ethereumChainId: 4
  ethereumWsEndpoint: "ws://besu-rinkeby-node:8546"
  linkContractAddress: "0x01BE23585060835E02B77ef475b0Cc51aA1e0709"
  databaseURL: "postgresql://username:password@server:port/name"
  keystorePasswordSecretName: "my-password"
  certSecretName: "chainlink-node-cert"
  apiCredentials:
    email: "mostafa@kotal.co"
    passwordSecretName: "my-password"

In this manifest, we're describing Chainlink node that connects to Ethereum Rinkeby node using ethereumWsEndpoint, setting ethereum chain ID using ethereumChainId, setting link contract address using linkContractAddress, connecting to postgress database instance using databaseURL, setting wallet password using keystorePasswordSecretName which accepts a name of k8s secret, setting tls configuration using certSecretName which accepts k8s secret name that holds tls.key and tls.crt, and finally setting API credentials using apiCredentials.

Apply chainlink.yaml manifest:

kubectl apply -f chainlink.yaml

Kotal operator will notice your chainlink-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.

You can fetch the deployed Chainlink Node using:

kubectl get nodes.chainlink

It will return an output similar to the following:

NAME             CLIENT      EthereumChainId
chainlink-node   chainlink   4

If you added -o wide it will return more info like link contract address

NAME             CLIENT      EthereumChainId   LinkContractAddress
chainlink-node   chainlink   4                 0x01BE23585060835E02B77ef475b0Cc51aA1e0709

Fetch Node Logs

Get the pods that has been created by Kotal for the node:

kubectl get pods

It will return an output similar to the following:

NAME                  READY   STATUS    RESTARTS   AGE
chainlink-node-0      1/1     Running   0          1m

Get the logs of the running node:

kubectl logs -f chainlink-node-0

Open Chainlink User Interface

Chainlink node comes with a user interface for managing the node, and it's being served by default on port 6688.

Forward localhost:6688 calls to the node pod:

kubectl port-forward chainlink-node-0 6688

Open https://localhost:6688 and it will take you to Chainlink node UI. It will ask you for API credentials. Enter the email address in your node's .spec.apiCredentials.email, and in the password field, enter fE2xXKDnR3ns489X.

🔥🔥🔥

Finally you can delete the node by:

kubectl delete -f chainlink.yaml

node.chainlink.kotal.io "chainlink-node" deleted

Kubernetes garbage collector will delete all the resources that has been created by Kotal Chainlink Node controller.

Deploy NEAR Validator Node

In this tutorial, we will learn how to deploy a NEAR validator node, and load a validator key into it.

Generate Validator Key

Validator account must have the name validator.

An ed25519 private key will be generated and saved in current user home directory under .near-credentials/testnet

It will return an output similar to the following

Change private_key field to secret_key.

Generate Secret for Validator Private Key

Create a Kubernetes secret from the generated private key in the previous step:

Deploy NEAR Validator Node

Apply near.yaml manifest:

Kotal operator will notice your near-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.

You can fetch the deployed NEAR Node using:

It will return an output similar to the following:

Note that validator is true in the prevous output 😇

Fetch Node Logs

Get the pods that has been created by Kotal for the node:

It will return an output similar to the following:

Get the logs of the running node:

It will return node logs similar to the following:

Finally you can delete the node by:

Kubernetes garbage collector will delete all the resources that has been created by Kotal NEAR Node controller.

Further Reading

After deploying this node, it can be accessed in-cluster using ws://besu-rinkeby-node:8546 🔥. Read for more details on how to deploy public and private network nodes.

Chainlink requires access to database instance.

You can also deploy your own PostgreSQL database instance from official PostgreSQL .

Chainlink optionally requires TLS certificate to secure access to the node API. Using we can issue a simple self-signed certificate and store it in a Kubernetes secret:

Generate validator account using tool. Which can be installed using:

The following manifest describes a NEAR node that syncs NEAR testnet network: testnet, enables HTTP JSON-RPC server rpc: true, loads validator key from the Kubernetes secret that we've created in the previous step, and uses client:

Ethereum guide
PostgreSQL
Amazon AWS
Azure
Google Cloud
docker image
cert-manager
npm install -g near-cli
near generate-key validator
cat ~/.near-credentials/testnet/validator.json
{
  "account_id": "validator",
  "public_key": "ed25519:CdTBLXMmu9gzoCbNKdUnej1tJNMz5tzRjJF2a9DwAgUr",
  "private_key": "ed25519:4k83DwbSpD3zzai4ZPdeRJcfXttU3Uq68mWWhni6ra2RKnG3jyVKEZyP14gDJZ9W1oqFujpAkidoNrYY4TLqijsG"
}
kubectl create secret generic validator-key  --from-file=key=$HOME/.near-credentials/testnet/validator.json
near.yaml
apiVersion: near.kotal.io/v1alpha1
kind: Node
metadata:
  name: near-node
spec:
  network: testnet
  validatorSecretName: validator-key
  rpc: true
kubectl apply -f near.yaml
kubectl get nodes.near
NAME         NETWORK    CLIENT      VALIDATOR
near-node    testnet    nearcore    true
kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
near-node-0       1/1     Running   0          1m
kubectl logs -f near-node-0
Apr 08 12:24:09.930  INFO neard: Version: 1.23.1, Build: 1.23.0-9-gc0551c84b-modified, Latest Protocol: 50
Apr 08 12:24:09.937  INFO near: Did not find "/home/near/kotal-data/data" path, will be creating new store database
Apr 08 12:24:10.438  INFO stats: Server listening at ed25519:GK2bMCbzgjFrdAQPFu2qSc6rViwX4MUb8WZb97CAfUMr@0.0.0.0:24567
Apr 08 12:24:20.444  INFO stats: # 9820210 Downloading headers 0.00% (53273496)   5/3/40 peers ⬇ 0.7kiB/s ⬆ 0.2kiB/s 0.00 bps 0 gas/s CPU: 0%, Mem: 0 B
Apr 08 12:24:30.447  INFO stats: # 9820210 Downloading headers 0.00% (53273498)   5/3/40 peers ⬇ 0.7kiB/s ⬆ 0.2kiB/s 0.00 bps 0 gas/s CPU: 4%, Mem: 78.4 MiB
Apr 08 12:24:40.417  INFO stats: # 9820210 Downloading headers 0.00% (53273497)   5/3/40 peers ⬇ 0.7kiB/s ⬆ 0.2kiB/s 0.00 bps 0 gas/s CPU: 10%, Mem: 99.6 MiB
...
kubectl delete -f near.yaml
NEAR CLI
NEAR Core
Deploy NEAR stacking pool
Staking on NEAR
Upgradable staking pool
NEAR validator bootcamp

Deploy Polkadot Node

Deploy Polkadot Node

polkadot.yaml
apiVersion: polkadot.kotal.io/v1alpha1
kind: Node
metadata:
  name: polkadot-node
spec:
  network: polkadot
  rpc: true
  rpcPort: 8888

Apply polkadot.yaml manifest:

kubectl apply -f polkadot.yaml

Kotal operator will notice your polkadot-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.

You can fetch the deployed Polkadot Node using:

kubectl get nodes.polkadot

It will return an output similar to the following:

NAME             NETWORK     VALIDATOR
polkadot-node    polkadot    fasle

Fetch Node Logs

Get the pods that has been created by Kotal for the node:

kubectl get pods

It will return an output similar to the following:

NAME                  READY   STATUS    RESTARTS   AGE
polkadot-node-0       1/1     Running   0          1m

Get the logs of the running node:

kubectl logs -f polkadot-node-0

It will return node logs similar to the following:

2021-10-17 22:15:12 Parity Polkadot
2021-10-17 22:15:12 ✌️  version 0.9.11-bfd38ed62-x86_64-linux-gnu
2021-10-17 22:15:12 ❤️  by Parity Technologies <admin@parity.io>, 2017-2021
2021-10-17 22:15:12 📋 Chain specification: Polkadot
2021-10-17 22:15:12 🏷 Node name: polkadot-node
2021-10-17 22:15:12 👤 Role: FULL
2021-10-17 22:15:12 💾 Database: RocksDb at /polkadot/kotal-data/chains/polkadot/db/full
2021-10-17 22:15:12 ⛓  Native runtime: polkadot-9110 (parity-polkadot-0.tx8.au0)
2021-10-17 22:15:12 🔨 Initializing Genesis block/state (state: 0x29d0…4e17, header-hash: 0x91b1…90c3)
2021-10-17 22:15:12 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.
2021-10-17 22:15:13 ⏱  Loaded block-time = 6s from block 0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3
2021-10-17 22:15:13 👶 Creating empty BABE epoch changes on what appears to be first startup.
2021-10-17 22:15:13 🏷 Local node identity is: 12D3KooWRo3vvfgPdsJ44tXu1Y2GeFNmC9ror2HsdJjvSjEcfZdw
2021-10-17 22:15:13 📦 Highest known block at #0
2021-10-17 22:15:13 Listening for new connections on 127.0.0.1:9944.
2021-10-17 22:15:13 🔍 Discovered new external address for our node: /ip4/102.189.29.174/tcp/30333/ws/p2p/12D3KooWRo3vvfgPdsJ44tXu1Y2GeFNmC9ror2HsdJjvSjEcfZdw
2021-10-17 22:15:18 ⚙️  Syncing, target=#7304424 (1 peers), best: #64 (0x4983…1114), finalized #0 (0x91b1…90c3), ⬇ 37.0kiB/s ⬆ 17.6kiB/s

Call JSON-RPC Method

Forward localhost:8888 calls to the node pod because rpcPort: 8888:

kubectl port-forward polkadot-node-0 8888

In another terminal window call eth_getBlock JSON-RPC method to get the latest synced block:

curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "chain_getBlock", "params": []}' 0.0.0.0:8888

You will get JSON result similar to the following:

{
  "jsonrpc": "2.0",
  "result": {
    "block": {
      "extrinsics": [
        "0x280403000be06ab2527201",
        "0x14040a00912e",
        "0x1004140000"
      ],
      "header": {
        "digest": {
          "logs": [
            "0x0642414245b501030000000042eacc0f00000000f414617b1dbce8671e029af90ae45c4b51d2f8d77d7876ae5f19dd42b7cb213775f40642dc2d86dd0a16169008e2d8735c849d7113da468be33b1c85819310024daffbee165156a2c17919fdc592754960a5587b6affc81f3e9c260364da2200",
            "0x054241424501019243678a110c1271c784ba9abaf03e08ae635ea766ce953853bfb1e3c0f70b5c95907240de74e57aa379c8428cd9933f097e32f9ef82caf261277ba4dc573b8b"
          ]
        },
        "extrinsicsRoot": "0xd9c14a96f36005ef6487ff56cb4722ff64afa3535cb1464c988767084094566c",
        "number": "0xba7",
        "parentHash": "0xcfb74aa6750036482897f63806191b3b14447186e45f69c43fcb72e02b57871f",
        "stateRoot": "0x5116aa11f10b1b1ce7c05ea85de08238b7db4c2c485bc88a9167e3b0a153368b"
      }
    },
    "justifications": null
  },
  "id": 1
}

Finally you can delete the node by:

kubectl delete -f polkadot.yaml

node.polkadot.kotal.io "polkadot-node" deleted

Kubernetes garbage collector will delete all the resources that has been created by Kotal Polkadot Node controller.

Deploy NEAR RPC Node

Deploy RPC Node

Apply near.yaml manifest:

Kotal operator will notice your near-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.

You can fetch the deployed NEAR Node using:

It will return an output similar to the following:

Fetch Node Logs

Get the pods that has been created by Kotal for the node:

It will return an output similar to the following:

Get the logs of the running node:

It will return node logs similar to the following:

Call JSON-RPC Method

By default, NEAR node JSON-RPC server port is 3030, which can be changed using rpcPort.

Forward localhost:3030 calls to the node pod:

In another terminal window call status JSON-RPC method to get the general status of our node (sync status, nearcore node version, protocol version) and the current set of validators:

You will get JSON result similar to the following:

Finally you can delete the node by:

Kubernetes garbage collector will delete all the resources that has been created by Kotal NEAR Node controller.

Deploy Kusama Validator

Deploy Kusama Node

By default, Validator nodes are in archive mode, but Kotal requires that node explicitly mark the node as archive node by setting pruning: false.

Apply kusama.yaml manifest:

Kotal operator will notice your kusama-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.

You can fetch the deployed Polkadot Node using:

It will return an output similar to the following:

Fetch Node Logs

Get the pods that has been created by Kotal for the node:

It will return an output similar to the following:

Get the logs of the running node:

It will return node logs similar to the following:

Enable Validator

Once the node is fully synced, enable validator by updating the node with validator: true:

Apply the updated kusama.yaml Node manifest:

Fetch the deployed Polkadot Node using:

It will return an output similar to the following:

Note that validator has changed from false to true.

Remaining Steps

The remainig steps in setting up a validator are:

  • Bonding KSM

  • Generating Session Keys

  • Setting Session Keys by signing and submitting an extrinsic

  • Relax 🏝️

We will cover next how to generate a session key.

Generating Session Key

Validator nodes can't enable external HTTP or WS JSON-RPC servers.

Session key can be generated by calling author_rotateKeys JSON-RPC method.

Forward localhost:9933 calls to the node pod because rpcPort: 9933:

9933 is the default HTTP JSON-RPC server listening port, can be changed by setting node .spec.rpcPort

In another terminal window call author_rotateKeys JSON-RPC method to get a new session key:

You will get JSON result similar to the following:

Finally you can delete the node by:

Kubernetes garbage collector will delete all the resources that has been created by Kotal Polkadot Node controller.

The following manifest describes a Polkadot node that syncs Polkadot relay chain network: polkadot, enables HTTP JSON-RPC server rpc: true on custom port rpcPort: 8888, and uses client:

The following manifest describes a NEAR node that syncs NEAR mainnet network: mainnet, enables HTTP JSON-RPC server rpc: true and uses client:

The following manifest describes Kusama node that syncs Kusama relay chain network: kusama, in archive mode pruning: false, and uses client:

These steps are documented in .

You can set the sesison key as documented in .

Parity Polkadot
near.yaml
apiVersion: near.kotal.io/v1alpha1
kind: Node
metadata:
  name: near-node
spec:
  network: mainnet
  rpc: true
kubectl apply -f near.yaml
kubectl get nodes.near
NAME         NETWORK    CLIENT      VALIDATOR
near-node    mainnet    nearcore    fasle
kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
near-node-0       1/1     Running   0          1m
kubectl logs -f near-node-0
Apr 07 12:18:33.280  INFO neard: Version: 1.23.1, Build: 1.23.0-9-gc0551c84b-modified, Latest Protocol: 50
Apr 07 12:18:33.287  INFO near: Did not find "/home/near/kotal-data/data" path, will be creating new store database
Apr 07 12:18:33.806  INFO stats: Server listening at ed25519:4WdX3qM4qqWG4DmD1eNp5LfMGu3N2HtoQHZArVjdQpGf@0.0.0.0:24567
Apr 07 12:18:43.816  INFO stats: # 9820210 Downloading headers 0.00% (53203932)   5/3/40 peers ⬇ 7.2kiB/s ⬆ 0.4kiB/s 0.00 bps 0 gas/s CPU: 0%, Mem: 0 B
Apr 07 12:18:53.819  INFO stats: # 9820210 Downloading headers 0.00% (53203933)   5/3/40 peers ⬇ 7.2kiB/s ⬆ 0.5kiB/s 0.00 bps 0 gas/s CPU: 10%, Mem: 134.4 MiB
Apr 07 12:19:03.787  INFO stats: # 9820210 Downloading headers 0.00% (53203933)   5/3/40 peers ⬇ 7.2kiB/s ⬆ 0.5kiB/s 0.00 bps 0 gas/s CPU: 24%, Mem: 165.9 MiB
Apr 07 12:19:13.790  INFO stats: # 9820210 Downloading headers 0.00% (53203933)   5/3/40 peers ⬇ 7.2kiB/s ⬆ 0.5kiB/s 0.00 bps 0 gas/s CPU: 9%, Mem: 175.0 MiB
...
kubectl port-forward near-node-0 3030
curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "status"}' 0.0.0.0:3030
{
  "jsonrpc": "2.0",
  "result": {
    "version": {
      "version": "1.23.1",
      "build": "1.23.0-9-gc0551c84b-modified"
    },
    "chain_id": "mainnet",
    "protocol_version": 29,
    "latest_protocol_version": 50,
    "rpc_addr": "0.0.0.0:3030",
    "validators": [
      {
        "account_id": "nfvalidator2.near",
        "is_slashed": false
      },
      {
        "account_id": "nfvalidator1.near",
        "is_slashed": false
      },
      {
        "account_id": "nfvalidator4.near",
        "is_slashed": false
      },
      {
        "account_id": "nfvalidator3.near",
        "is_slashed": false
      }
    ],
    "sync_info": {
      "latest_block_hash": "EPnLgE7iEq9s7yTkos96M3cWymH5avBAPm3qx3NXqR8H",
      "latest_block_height": 9820210,
      "latest_state_root": "5o1trt9N9YgDL4xeY33z9adS5Ub3jMmuyQpWM7UHowrq",
      "latest_block_time": "2020-07-21T16:55:51.591948Z",
      "syncing": true,
      "earliest_block_hash": "EPnLgE7iEq9s7yTkos96M3cWymH5avBAPm3qx3NXqR8H",
      "earliest_block_height": 9820210,
      "earliest_block_time": "2020-07-21T16:55:51.591948Z"
    },
    "validator_account_id": "validator"
  },
  "id": 53
}
kubectl delete -f near.yaml
kusama.yaml
apiVersion: polkadot.kotal.io/v1alpha1
kind: Node
metadata:
  name: kusama-node
spec:
  network: kusama
  pruning: false
kubectl apply -f kusama.yaml
kubectl get nodes.polkadot
NAME             NETWORK     VALIDATOR
kusama-node      kusama      fasle
kubectl get pods
NAME                  READY   STATUS    RESTARTS   AGE
kusama-node-0         1/1     Running   0          1m
kubectl logs -f kusama-node-0
2021-10-18 15:32:38 ----------------------------
2021-10-18 15:32:38 This chain is not in any way
2021-10-18 15:32:38       endorsed by the
2021-10-18 15:32:38      KUSAMA FOUNDATION
2021-10-18 15:32:38 ----------------------------
2021-10-18 15:32:38 Parity Polkadot
2021-10-18 15:32:38 ✌️  version 0.9.11-bfd38ed62-x86_64-linux-gnu
2021-10-18 15:32:38 ❤️  by Parity Technologies <admin@parity.io>, 2017-2021
2021-10-18 15:32:38 📋 Chain specification: Kusama
2021-10-18 15:32:38 🏷 Node name: validator-node-sample
2021-10-18 15:32:38 👤 Role: AUTHORITY
2021-10-18 15:32:38 💾 Database: RocksDb at /polkadot/kotal-data/chains/ksmcc3/db/full
2021-10-18 15:32:38 ⛓  Native runtime: kusama-9110 (parity-kusama-0.tx7.au2)
2021-10-18 15:32:38 🔨 Initializing Genesis block/state (state: 0xb000…ef6b, header-hash: 0xb0a8…dafe)
2021-10-18 15:32:38 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.
2021-10-18 15:32:39 ⏱  Loaded block-time = 6s from block 0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe
2021-10-18 15:32:39 👶 Creating empty BABE epoch changes on what appears to be first startup.
2021-10-18 15:32:39 🏷 Local node identity is: 12D3KooWFEHU9FXqGCL6ify4rqcon31WYViCnUfA6aVYTjRXqJ5F
2021-10-18 15:32:39 📦 Highest known block at #0
2021-10-18 15:32:39 〽️ Prometheus exporter started at 0.0.0.0:9615
2021-10-18 15:32:39 Listening for new connections on 127.0.0.1:9944.
2021-10-18 15:32:39 👶 Starting BABE Authorship worker
...
kusama.yaml
apiVersion: polkadot.kotal.io/v1alpha1
kind: Node
metadata:
  name: kusama-node
spec:
  network: kusama
  pruning: false
  validator: true
kubectl apply -f kusama.yaml
kubectl get nodes.polkadot
NAME             NETWORK     VALIDATOR
kusama-node      kusama      true
kubectl port-forward polkadot-node-0 9933
curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "author_rotateKeys", "params":[]}' http://127.0.0.1:9933
{
  "jsonrpc": "2.0",
  "result": "0x159256d69a61b523a211d7845a92d5a238f6a97b53627c4aa92665eb6bc2959dc88c9c279ad01b8acf90573ca005f6565c4a0d88d19951740b8f8ec38c63b344b2c186e703ce88f0f4b628263265ffefa1cdc148c79a5608ccc7734e6a0bfb077076c5f370491331819d17884b9aa4e41d4e2bec774b5c31251203266c446a2ec02d89f5ecefcc75777d4de74766a57fbafe65b1850500875e8cf2fed3325f65",
  "id": 1
}
kubectl delete -f kusama.yaml

node.polkadot.kotal.io "kusama-node" deleted
NEAR Core
Parity Polkadot
Polkadot Wiki
Polkadot Wiki

Filecoin

We've extended Kubernetes with Node custom resource which can be used to create Filecoin nodes across different filecoin networks like Mainnet or calibration using lotus client from a given spec.

Here's an example of a Filecoin node that syncs calibration chain:

apiVersion: filecoin.kotal.io/v1alpha1
kind: Node
metadata:
  name: calibration-node
spec:
  network: calibration

For all the fields associated with the Node API resource:

kubectl explain node --api-version filecoin.kotal.io/v1alpha1
kubectl explain node.spec --api-version filecoin.kotal.io/v1alpha1

Full filecoin node reference is documented .

here

IPFS

IPFS is a distributed system for storing and accessing files, websites, applications, and data.

We've extended Kubernetes with Peer and ClusterPeer custom resources which can be used to deploy IPFS peers, swarms, and clusters from the given spec.

Peer

Peer is an ipfs peer running go-ipfs client and connecting to the public ipfs swarm or a private swarm secured by swarm key. Here's an example of a very basic ipfs peer connecting to the public ipfs swarm.

apiVersion: ipfs.kotal.io/v1alpha1
kind: Peer
metadata:
  Name: simple-peer
spec: {}

For all the fields associated with the Peer API resource:

kubectl explain peers --api-version ipfs.kotal.io/v1alpha1
kubectl explain peers.spec --api-version ipfs.kotal.io/v1alpha1

ClusterPeer

ClusterPeer is an ipfs cluster peer running ipfs-cluster-service client, connecting to ipfs peer and optional bootstrap cluster peer(s). ClusterPeers provide data orchestration across a swarm of IPFS daemons by allocating, replicating and tracking a global pinset distributed among multiple peers. Here's an example of cluster peer connecting to ipfs peer.

apiVersion: ipfs.kotal.io/v1alpha1
kind: ClusterPeer
metadata:
  Name: simple-cluster-peer
spec:
  peerEndpoint: /dns4/simple-peer/tcp/5001

For all the fields associated with the ClusterPeer API resource:

kubectl explain clusterpeers --api-version ipfs.kotal.io/v1alpha1
kubectl explain clusterpeers.spec --api-version ipfs.kotal.io/v1alpha1

Full ipfs peer reference is documented .

Full ipfs cluster peer reference is documented .

here
here

Deploy Filecoin Node

Deploy Node

calibration.yaml
apiVersion: filecoin.kotal.io/v1alpha1
kind: Node
metadata:
  name: calibration-node
spec:
  network: calibration

This is a simple filecoin Node that joins calibration test network.

Let's deploy the node:

kubectl apply -f calibration.yaml

Kotal operator will notice your calibration-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.

kubectl get peers

It will return an output similar to the following:

NAME                NETWORK        CLIENT
calibration-node    calibration    lotus

Fetch Node Logs

Get the pods created for the node:

kubectl get pods

It will return an output similar to the following:

NAME                  READY   STATUS    RESTARTS   AGE
calibration-node-0    1/1     Running   0          5m

If pod STATUS is Pending, most probably it's due to not enough cpu and memory, because Kotal allocates lots of cpu cores and memory for public nodes. The required node resources can be changed using spec.resources.cpu, spec.resources.memory, and spec.resources.storage.

Check the logs of the running node:

kubectl logs -f calibration-node-0

Finally you can delete the filecoin node and all its resources by

kubectl delete -f calibration.yaml

and kubernetes garbage collector will delete all resources created by the node controller.

Deploy IPFS peer

Deploy Peer

peer.yaml
apiVersion: ipfs.kotal.io/v1alpha1
kind: Peer
metadata:
  name: simple-peer
spec: {}

This is a simple ipfs peer that joins the public ipfs swarm, and will starts with the all default settings that's similar to running ipfs init then ipfs daemon on your machine.

Let's deploy the peer:

kubectl apply -f peer.yaml

Kotal operator will notice your simple-peer and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.

kubectl get peers

It will return an output similar to the following:

NAME          CLIENT
simple-peer   go-ipfs

Fetch Peer Logs

Get the pods created for the peer:

kubectl get pods

It will return an output similar to the following:

NAME            READY   STATUS    RESTARTS   AGE
simple-peer-0   1/1     Running   0          5m

Check the logs of the running peer:

kubectl logs -f simple-peer-0

You'll get output similar to the following:

Initializing daemon...
go-ipfs version: 0.8.0-ce693d7
Repo version: 11
System version: amd64/linux
Golang version: go1.14.4
Swarm listening on /ip4/10.244.0.6/tcp/4001
Swarm listening on /ip4/10.244.0.6/udp/4001/quic
Swarm listening on /ip4/127.0.0.1/tcp/4001
Swarm listening on /ip4/127.0.0.1/udp/4001/quic
Swarm listening on /ip6/::1/tcp/4001
Swarm listening on /ip6/::1/udp/4001/quic
Swarm listening on /p2p-circuit
Swarm announcing /ip4/10.244.0.6/tcp/4001
Swarm announcing /ip4/10.244.0.6/udp/4001/quic
Swarm announcing /ip4/127.0.0.1/tcp/4001
Swarm announcing /ip4/127.0.0.1/udp/4001/quic
Swarm announcing /ip6/::1/tcp/4001
Swarm announcing /ip6/::1/udp/4001/quic
API server listening on /ip4/0.0.0.0/tcp/5001
WebUI: http://0.0.0.0:5001/webui
Gateway (readonly) server listening on /ip4/0.0.0.0/tcp/8080
Daemon is ready

Your peer is up and running and ready to receive api calls.

Read file Using IPFS HTTP API

Let's forward localhost:5001 calls to simple-peer:5001

kubectl port-forward simple-peer-0 5001

In another terminal window, send http api call using cURL:

curl -X POST "http://127.0.0.1:5001/api/v0/cat?arg=QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme"

You'll get the following output:

Hello and Welcome to IPFS!

██╗██████╗ ███████╗███████╗
██║██╔══██╗██╔════╝██╔════╝
██║██████╔╝█████╗  ███████╗
██║██╔═══╝ ██╔══╝  ╚════██║
██║██║     ██║     ███████║
╚═╝╚═╝     ╚═╝     ╚══════╝

If you're seeing this, you have successfully installed
IPFS and are now interfacing with the ipfs merkledag!

 -------------------------------------------------------
| Warning:                                              |
|   This is alpha software. Use at your own discretion! |
|   Much is missing or lacking polish. There are bugs.  |
|   Not yet secure. Read the security notes for more.   |
 -------------------------------------------------------

Check out some of the other files in this directory:

  ./about
  ./help
  ./quick-start     <-- usage examples
  ./readme          <-- this file
  ./security-notes

You can also view ipfs webui by visiting http://0.0.0.0:5001/webui

Finally, delete the ipfs peer:

kubectl delete -f peer.yaml

Kubernetes garbage collector will delete all the resources that has been created by Kotal IPFS Peer controller.

Deploy IPFS cluster peer

Prerequisites

Before we start, you need to:

Step 1 - Deploy IPFS Peer

Step 2 - Generate Cluster Secret

Create a cluster secret which secures access to the cluster:

CLUSTER_SECRET=$(openssl rand -hex 32)
kubectl create secret generic cluster-secret --from-literal=secret=$CLUSTER_SECRET

Cluster secret must be 32-byte hex-encoded (64 characters) without the leading 0x. It must be hold in data field called secret in the Kubernetes secret.

Step 3 - Generate ID and Private Key

ipfs-key -type ed25519 | base64

It will return an output similar to the following:

Generating a 2048 bit ed25519 key...
Success!
ID for generated key: 12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq
CAESQOH/DvUJmeJ9z6m3wAStpkrlBwJQxIyNSK0YGf0EI5ZRGpwsWxl4wmgReqmHl8LQjTC2iPM0QbYAjeY3Z63AFnI=

Step 4 - Deploy Private Key Secret

create Kubernetes secret from the generated private key in step(3) above.

CLUSTER_PEER_PRIVATEKEY=CAESQOH/DvUJmeJ9z6m3wAStpkrlBwJQxIyNSK0YGf0EI5ZRGpwsWxl4wmgReqmHl8LQjTC2iPM0QbYAjeY3Z63AFnI=
kubectl create secret generic cluster-peer-privatekey --from-literal=key=$CLUSTER_PEER_PRIVATEKEY

Deploying First Cluster Peer

Now we're ready to deploy the cluster peer and connect it to the peer we've deployed in step(1)

cluster-peer.yaml
apiVersion: ipfs.kotal.io/v1alpha1
kind: ClusterPeer
metadata:
  Name: cluster-peer
spec:
  consensus: crdt
  # from step(3)
  id: "12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq"
  # from step(4)
  privateKeySecretName: cluster-peer-privatekey
  # from step(1)
  peerEndpoint: /dns4/peer-sample/tcp/5001
  # from step(2)
  clusterSecretName: cluster-secret

Note that id and privateKeySecretName are optional, they're useful to get predictable cluster peer id to be used in future steps as bootstrap peer.

Let's deploy cluster peer manifest file:

kubectl apply -f cluster-peer.yaml

Kotal operator will notice your cluster-peer and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.

You can fetch the deployed IPFS ClusterPeer using:

kubectl get clusterpeers

It will return an output similar to the following:

NAME           CLIENT                 CONSENSUS
cluster-peer   ipfs-cluster-service   crdt

Fetch Cluster Peer Logs

Get the pods created for our cluster peer:

kubectl get pods

It will return an output similar to the following:

NAME             READY   STATUS    RESTARTS   AGE
cluster-peer-0   1/1     Running   0          2m

Check the logs of the running cluster peer:

kubectl logs -f cluster-peer-0

It will return an output similar to the following:

2021-04-30T00:31:24.109Z	INFO	service	ipfs-cluster-service/daemon.go:46	Initializing. For verbose output run with "-l debug". Please wait...
2021-04-30T00:31:24.133Z	INFO	cluster	ipfs-cluster/cluster.go:136	IPFS Cluster v0.13.2+git812c8e3631d4d6771a6e04112e12cd7726e23f7a listening on:

        /ip4/10.244.0.8/tcp/9096/p2p/12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq
        /ip4/127.0.0.1/tcp/9096/p2p/12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq

2021-04-30T00:31:24.134Z	INFO	ipfsproxy	ipfsproxy/ipfsproxy.go:320	IPFS Proxy: /ip4/127.0.0.1/tcp/9095 -> /ip4/127.0.0.1/tcp/5001
2021-04-30T00:31:24.134Z	INFO	restapi	rest/restapi.go:521	REST API (HTTP): /ip4/127.0.0.1/tcp/9094
2021-04-30T00:31:24.134Z	INFO	crdt	go-ds-crdt@v0.1.20/crdt.go:278	crdt Datastore created. Number of heads: 0. Current max-height: 0
2021-04-30T00:31:24.136Z	INFO	cluster	ipfs-cluster/cluster.go:651	Cluster Peers (without including ourselves):
2021-04-30T00:31:24.136Z	INFO	cluster	ipfs-cluster/cluster.go:653	    - No other peers
2021-04-30T00:31:24.136Z	INFO	cluster	ipfs-cluster/cluster.go:666	** IPFS Cluster is READY **

As you can see from the logs that our cluster peer is up and running as indicated by the healthy logs IPFS Cluster is READY.

Update Cluster Pinset

Let's add some content to the pinset by executing commands inside cluster peer container:

$ kubectl exec -it cluster-peer-0 -- sh
# now we're inside cluster-peer container

$ echo "kotal simplifies Blockchain DevOps" > kotal.txt

# add kotal.txt to the pinset
$ ipfs-cluster-ctl add kotal.txt
added QmUiwYtz1VxeryVCpTLWqrbeUi9HyGH4AnpSG6BrmdMhzL kotal.txt

# leave cluster-peer container
$ exit

Let's fetch the pinset of the ipfs peer by executing commands inside peer -created in step(1)- container:

$ kubectl exec -it peer-sample-0 -- sh
# now we're inside peer-sample container

# List objects pinned to local storage
$ ipfs pin ls
QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn recursive
QmUiwYtz1VxeryVCpTLWqrbeUi9HyGH4AnpSG6BrmdMhzL recursive

$ ipfs cat QmUiwYtz1VxeryVCpTLWqrbeUi9HyGH4AnpSG6BrmdMhzL
kotal simplifies Blockchain DevOps

# leave ipfs peer container
$ exit

As you can see, content pinned by the cluster peer, has been added to the pinset of the ipfs peer and available in its local storage.

Deploying Second Cluster Peer

The only prerequisite to the second cluster peer is to:

Step 1 - Deploy IPFS Peer

We will reuse cluster secret that was generated in step(2) during deploying first cluster peer above.

cluster-peer-two.yaml
apiVersion: ipfs.kotal.io/v1alpha1
kind: ClusterPeer
metadata:
  Name: cluster-peer-two
spec:
  # from step(1)
  peerEndpoint: /dns4/peer-sample-twp/tcp/5001
  # generated during deploying first cluster peer in step(2)
  clusterSecretName: cluster-secret
  # first cluster peer listening address
  bootstrapPeers:
    - /ip4/cluster-peer/tcp/9096/p2p/12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq

The first cluster peer multiaddress is predictable because we've used a pre-generated id and private key in step(3). /ip4/{cluster peer k8s service name}/tcp/9096/p2p/{cluster peer ID}

Deploying this cluster manifest will deploy a cluster peer that connects to the first cluster peer and will connect to its own ipfs peer peer-sample-two instance.

kubectl apply -f cluster-peer-two.yaml

You can fetch the deployed cluster peers by:

kubectl get clusterpeers

It will return an output similar to the following:

NAME               CLIENT                 CONSENSUS
cluster-peer       ipfs-cluster-service   crdt
cluster-peer-two   ipfs-cluster-service   crdt

Fetch Second Cluster Peer Logs

Get the pods created by our cluster peer:

kubectl get pods

It will return an output similar to the following:

NAME                 READY   STATUS    RESTARTS   AGE
cluster-peer-0       1/1     Running   0          10m
cluster-peer-two-0   1/1     Running   0          2m

Check the logs of cluster peer two:

kubectl logs -f cluster-peer-two-0

It will return an output similar to the following:

2021-05-01T19:17:12.043Z	INFO	service	ipfs-cluster-service/daemon.go:46	Initializing. For verbose output run with "-l debug". Please wait...
2021-05-01T19:17:12.352Z	INFO	cluster	ipfs-cluster/cluster.go:136	IPFS Cluster v0.13.2+git812c8e3631d4d6771a6e04112e12cd7726e23f7a listening on:

        /ip4/10.244.0.35/tcp/9096/p2p/12D3KooWGVZek7gdarvj7gePvnV9x8ekSeSdruYojgj5dmU466Wv
        /ip4/127.0.0.1/tcp/9096/p2p/12D3KooWGVZek7gdarvj7gePvnV9x8ekSeSdruYojgj5dmU466Wv


2021-05-01T19:17:12.441Z	INFO	restapi	rest/restapi.go:521	REST API (HTTP): /ip4/127.0.0.1/tcp/9094
2021-05-01T19:17:12.441Z	INFO	ipfsproxy	ipfsproxy/ipfsproxy.go:320	IPFS Proxy: /ip4/127.0.0.1/tcp/9095 -> /ip4/127.0.0.1/tcp/5001
2021-05-01T19:17:12.441Z	INFO	service	ipfs-cluster-service/daemon.go:218	Bootstrapping to /dns4/cluster-peer/tcp/9096/p2p/12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq
2021-05-01T19:17:12.442Z	INFO	crdt	go-ds-crdt@v0.1.20/crdt.go:278	crdt Datastore created. Number of heads: 0. Current max-height: 0
2021-05-01T19:17:12.442Z	INFO	crdt	crdt/consensus.go:277	'trust all' mode enabled. Any peer in the cluster can modify the pinset.
2021-05-01T19:17:12.447Z	INFO	cluster	ipfs-cluster/cluster.go:651	Cluster Peers (without including ourselves):
2021-05-01T19:17:12.447Z	INFO	cluster	ipfs-cluster/cluster.go:653	    - No other peers
2021-05-01T19:17:12.448Z	INFO	cluster	ipfs-cluster/cluster.go:666	** IPFS Cluster is READY **
2021-05-01T19:17:12.551Z	INFO	cluster	ipfs-cluster/cluster.go:1020	12D3KooWGVZek7gdarvj7gePvnV9x8ekSeSdruYojgj5dmU466Wv: joined 12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq's cluster

As you can see cluster peer two is up and running as indicated by the healthy logs and IPFS Cluster is READY.

Cluster peer two has joined the first cluster peer as indicated by the highlighted log line joined 12D...uiq's cluster

Finally, delete all peers and cluster peers:

kubectl delete peers --all
kubectl delete clusterpeers --all

Kubernetes garbage collector will delete all the resources that has been created by Kotal IPFS Peer and ClusterPeer controllers.

IPFS Cluster provides data orchestration across a swarm of IPFS daemons by allocating, replicating and tracking a global pinset distributed among multiple peers.

Deploy an ipfs peer Peer because it's required by ClusterPeer. Check our tutorial.

Create cluster peer ID and private key using

Deploy an ipfs peer Peer, and name it peer-sample-two. Check our tutorial.

Source
Deploy IPFS Peer
ipfs-key
Deploy IPFS Peer

Stacks

We've extended Kubernetes with Node custom resource which can be used to deploy Stacks rpc and miner nodes from the given spec.

Node

apiVersion: stacks.kotal.io/v1alpha1
kind: Node
metadata:
  Name: stacks-node
spec:
  network: mainnet
  ...

For all the fields associated with the Node API resource:

kubectl explain nodes --api-version stacks.kotal.io/v1alpha1
kubectl explain nodes.spec --api-version stacks.kotal.io/v1alpha1

Deploy Stacks Miner Node

Make sure Bitcoin node is fully synced before deploying your Stacks node.

Generating Miner Private Key

Don't use the following Miner private key in production!

npm install -g @stacks/cli

Generate key chain using:

stx make_keychain

It will return an output similar to the following

{
  "mnemonic": "blue news bid also tell vault blame tonight crumble history tribe anxiety arch stove usage eight stick firm weapon wet chapter gravity seat idle",
  "keyInfo": {
    "privateKey": "7a3ef70a4a3ff3c389818ac11abec24b20ffbe3fb2cf6f71e947367a4ddbec6601",
    "address": "SPQG93WFTVV6GA4AEDMS18ZCSTKMKFHWEHEXQAJJ",
    "btcAddress": "15HcDuW1W2TqEe9mVER9ceJYtqMAED26jp",
    "wif": "L1KLjY5xMGUSSV9cfE9VoKRdVt3D1zJxoJwPVLHfgRNS1ETGUSvr",
    "index": 0
  }
}

Store privateKey from the output above into a Kubernetes secret in data field called key:

kubectl create secret generic seed-private-key --from-literal=key=7a3ef70a4a3ff3c389818ac11abec24b20ffbe3fb2cf6f71e947367a4ddbec6601

Bitcoin node JSON-RPC user password

Let's store Stacks Foundation Bitcoin node JSON-RPC password in a Kubernetes secret to be used by our node:

bitcoin-node-rpc-password.yaml
apiVersion: v1
kind: Secret
metadata:
  name: bitcoin-node-rpc-password
stringData:
  password: blockstacksystem

Apply bitcoin-node-rpc-password.yaml to create the password secret:

kubectl apply -f bitcoin-node-rpc-password.yaml

Deploy Stacks Miner Node

The following manifest describes a Stacks node that syncs Stacks mainnet network: mainnet, and connects to the bitcoin node using configurations in bitcoinNode: ... for Proof of Transfer, and loading miner private key using seedPrivateKeySecretName:

stacks.yaml
apiVersion: stacks.kotal.io/v1alpha1
kind: Node
metadata:
  name: stacks-node
spec:
  network: mainnet
  seedPrivateKeySecretName: seed-private-key
  bitcoinNode:
    endpoint: bitcoin.blockstack.com
    rpcPort: 8332
    p2pPort: 8333
    rpcUsername: blockstack
    rpcPasswordSecretName: bitcoin-node-rpc-password

Apply stacks.yaml manifest:

kubectl apply -f stacks.yaml

Kotal operator will notice your stacks-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.

You can fetch the deployed Stacks Node using:

kubectl get nodes.stacks

It will return an output similar to the following:

NAME            NETWORK    CLIENT    MINER
stacks-node     mainnet    stacks    true

Note Miner is true in the previous output 🔥

Fetch Node Logs

Get the pods that has been created by Kotal for the node:

kubectl get pods

It will return an output similar to the following:

NAME             READY   STATUS    RESTARTS   AGE
stacks-node-0    1/1     Running   0          1m

Get the logs of the running node:

kubectl logs -f stacks-node-0

It will return node logs similar to the following:

INFO [1649610683.233993] [testnet/stacks-node/src/main.rs:113] [main] Loading config at path /home/stacks/kotal-config/config.toml
INFO [1649610683.795606] [testnet/stacks-node/src/run_loop/neon.rs:341] [main] Start syncing Bitcoin headers, feel free to grab a cup of coffee, this can take a while
INFO [1649610686.606279] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 0.3% (2000 out of 731294)
INFO [1649610687.625014] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 0.5% (4000 out of 731294)
INFO [1649610688.634560] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 0.8% (6000 out of 731294)
INFO [1649610689.677533] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.1% (8000 out of 731294)
INFO [1649610690.737928] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.4% (10000 out of 731294)
INFO [1649610691.745002] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.6% (12000 out of 731294)
INFO [1649610692.789689] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.9% (14000 out of 731294)
...

Finally you can delete the node by:

kubectl delete -f stacks.yaml

Kubernetes garbage collector will delete all the resources that has been created by Stacks Node controller.

Deploy Stacks RPC Node

Make sure Bitcoin node is fully synced before deploying your Stacks node.

Bitcoin node JSON-RPC user password

Let's store Stacks Foundation Bitcoin node JSON-RPC password in a Kubernetes secret to be used by our node:

Apply bitcoin-node-rpc-password.yaml to create the password secret:

Deploy Stacks RPC Node

The following manifest describes a Stacks node that syncs Stacks mainnet network: mainnet, and connects to the bitcoin node using configurations in bitcoinNode: ... for Proof of Transfer:

Apply stacks.yaml manifest:

Kotal operator will notice your stacks-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.

You can fetch the deployed Stacks Node using:

It will return an output similar to the following:

Fetch Node Logs

Get the pods that has been created by Kotal for the node:

It will return an output similar to the following:

Get the logs of the running node:

It will return node logs similar to the following:

Call JSON-RPC Method

By default, Stacks node JSON-RPC server port is 20443, which can be changed using rpcPort.

Forward localhost:20443 calls to the node pod:

HTTP server will start after Bitcoin headers sync, till then you will get the following error if you tried to send JSON-RPC calls:

In another terminal window call info JSON-RPC method to retrieve information about the Core API including the server version:

You will get JSON result similar to the following:

Finally you can delete the node by:

Kubernetes garbage collector will delete all the resources that has been created by Stacks Node controller.

Node is Stacks node using client, connecting to and syncing a specific chain, optionally mining or exposing JSON-RPC server to be used by clients.

Full Stacks node reference is documented .

Stacks node requires a Bitcoin node to connect to on the back-end for . You can deploy a Bitcoin node using Kotal operator like we did in this . In this tutorial, we will be using Bitcoin node hosted by Stacks Foundation.

Generate Key chain using tool. Stacks CLI can be installed using:

Stacks node requires a Bitcoin node to connect to on the back-end for . You can deploy a Bitcoin node using Kotal operator like we did in this . In this tutorial, we will be using Bitcoin node hosted by Stacks Foundation.

Stacks Blockchain Node
here
Proof of Transfer
guide
Stacks CLI
bitcoin-node-rpc-password.yaml
apiVersion: v1
kind: Secret
metadata:
  name: bitcoin-node-rpc-password
stringData:
  password: blockstacksystem
kubectl apply -f bitcoin-node-rpc-password.yaml
stacks.yaml
apiVersion: stacks.kotal.io/v1alpha1
kind: Node
metadata:
  name: stacks-node
spec:
  network: mainnet
  bitcoinNode:
    endpoint: bitcoin.blockstack.com
    rpcPort: 8332
    p2pPort: 8333
    rpcUsername: blockstack
    rpcPasswordSecretName: bitcoin-node-rpc-password
kubectl apply -f stacks.yaml
kubectl get nodes.stacks
NAME            NETWORK    CLIENT    MINER
stacks-node     mainnet    stacks    false
kubectl get pods
NAME             READY   STATUS    RESTARTS   AGE
stacks-node-0    1/1     Running   0          1m
kubectl logs -f stacks-node-0
INFO [1649597250.010714] [testnet/stacks-node/src/main.rs:113] [main] Loading config at path /home/stacks/kotal-config/config.toml
INFO [1649597250.599067] [testnet/stacks-node/src/run_loop/neon.rs:341] [main] Start syncing Bitcoin headers, feel free to grab a cup of coffee, this can take a while
INFO [1649597251.949664] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 0.3% (2000 out of 731268)
INFO [1649597253.010039] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 0.5% (4000 out of 731268)
INFO [1649597254.019798] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 0.8% (6000 out of 731268)
INFO [1649597254.992070] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.1% (8000 out of 731268)
INFO [1649597256.214756] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.4% (10000 out of 731268)
INFO [1649597257.276950] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.6% (12000 out of 731268)
INFO [1649597258.383248] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.9% (14000 out of 731268)
...
kubectl port-forward bitcoin-node-0 20443
curl: (52) Empty reply from server
curl localhost:20443/v2/info
{
  "peer_version": 402653189,
  "pox_consensus": "9bed78c9f02d2ba5a5950fe88c4746436b47c730",
  "burn_block_height": 666051,
  "stable_pox_consensus": "0000000000000000000000000000000000000000",
  "stable_burn_block_height": 666050,
  "server_version": "stacks-node No Version Info (No Branch Info:No Commit Info, release build, linux [x86_64])",
  "network_id": 1,
  "parent_network_id": 3652501241,
  "stacks_tip_height": 0,
  "stacks_tip": "0000000000000000000000000000000000000000000000000000000000000000",
  "stacks_tip_consensus_hash": "0000000000000000000000000000000000000000",
  "genesis_chainstate_hash": "74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b",
  "unanchored_tip": null,
  "unanchored_seq": null,
  "exit_at_block_height": null
}
kubectl delete -f stacks.yaml
Proof of Transfer
guide

Bitcoin

Syntax
Type
Description
Default

string

Bitcoin network to join and sync

number

p2p communications port

8333 for mainnet, 18333 for testnet

string

p2p communication host

0.0.0.0

boolean

Enables JSON-RPC server

false

number

JSON-RPC server port

8332 for mainnet, 18332 for testnet

string

JSON-RPC server host

0.0.0.0

array

JSON-RPC users credentials

boolean

Load local wallet and enables wallet RPC calls

false

boolean

Maintains a full transaction index

false

object

node compute and storage resources to alloacte

network

network is Bitcoin network to join and sync. Possible values are mainnet and testnet.

network is immutable, can't be changed after node is created.

p2pPort

p2pPort is p2p communications port.

p2pHost

p2pHost is p2p communications host.

rpc

rpc enables JSON-RPC server.

rpcPort

rpcPort is JSON-RPC server port.

rpcHost

rpcHost is JSON-RPC server host.

rpcUsers

rpcUsers is a list of JSON-RPC users credentials:

Syntax
Type
Description

username

string

JSON-RPC user name

passwordSecretName

string

Kubernetes secret name holding JSON-RPC user password

wallet

wallet loads local wallet and enables wallet RPC calls.

txIndex

txIndex maintains a full transaction index.

resources

resources allocates compute and storage resources to the node.

Syntax
Type
Description
Default

cpu

string

number of cpu cores this node requires

2

cpuLimit

string

number of cpu cores this node is limited to

4

memory

string

memory this node requires

4Gi

memoryLimit

string

memory this node is limited to

8Gi

storage

string

disk space this node requires

100Gi

storageClass

string

Node volume storage class

Cluster's default storage class will be used as defined by cluster admin or cloud provider

memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.

cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1), 1500m, 2, and 4.

cpuLimit can't be less than cpu.

memoryLimit can't be less than or equal to memory.

storageClass field is immutable, it cannot be changed after creation.

required

network
p2pPort
p2pHost
rpc
rpcPort
rpcHost
rpcUsers
wallet
txIndex
resources

NEAR

Syntax
Type
Description
Default

string

NEAR network to join and sync

string

Kubernetes secret name holding node Ed25519 private key

string

Kubernetes secret name holding node Ed25519 validator key

number

Minimum number of peers to start syncing/producing blocks

5

boolean

Keeps old blocks in the storage

false

number

p2p protocol tcp port

24567

string

p2p host

0.0.0.0

boolean

Enables JSON-RPC server

false

number

JSON-RPC server listening port

3030

string

JSON-RPC server listening host

0.0.0.0

number

Prometheus exporter port

9615

string

Prometheus exporter host

0.0.0.0

string

Telemetry service URL

array

Boot nodes to bootstrap network from

object

node compute and storage resources to alloacte

network

network is NEAR network to join and sync. Possible values are mainnet, testnet, and betanet.

network is immutable, it can't be changed after node is created.

nodePrivateKeySecretName

nodePrivateKeySecretName is Kubernetes secret name holding node Ed25519 private key in data field key, from which node public key is generated, and p2p messages are signed.

validatorSecretName

validatorSecretName is Kubernetes secret name holding node Ed25519 validator key in data field key.

minPeers

minPeers is the minimum number of peers to start syncing/producing blocks.

archive

archive keeps old blocks in the storage.

p2pPort

p2pPort is p2p protocol tcp port.

p2pHost

p2pHost is p2p host address.

rpc

rpc enables JSON-RPC server.

rpcPort

rpcPort is JSON-RPC server listening port.

rpcHost

rpcHost is JSON-RPC server listening host address.

prometheusPort

prometheusPort is Prometheus exporter port.

prometheusHost

prometheusHost is Prometheus exporter host address.

telemetryURL

telemetryURL is Telemetry service URL.

bootnodes

bootnodes is a list of boot nodes to bootstrap network from

resources

resources allocates compute and storage resources to the node.

Syntax
Type
Description
Default

cpu

string

number of cpu cores this node requires

4

cpuLimit

string

number of cpu cores this node is limited to

8

memory

string

memory this node requires

4Gi

memoryLimit

string

memory this node is limited to

8Gi

storage

string

disk space this node requires

250Gi for non archival node, 4Ti for archive node

storageClass

string

Node volume storage class

Cluster's default storage class will be used as defined by cluster admin or cloud provider

memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.

cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1), 1500m, 2, and 4.

cpuLimit can't be less than cpu.

memoryLimit can't be less than or equal to memory.

storageClass field is immutable, it cannot be changed after creation.

required

network
nodePrivateKeySecretName
validatorSecretName
minPeers
archive
p2pPort
p2pHost
rpc
rpcPort
rpcHost
prometheusPort
prometheusHost
telemetryURL
bootnodes
resources

Polkadot

Syntax
Type
Description
Default

string

Polkadot node client image

last stable and tested client

array

Extra arguments to pass down to the node client

number

number of replicas

1

string

polkadot network/chain to join and sync

string

p2p protocol tcp port

30333

string

Kubernetes secret name holding node Ed25519 private key

boolean

enables validator

false

string

blockchain synchronization mode

full

boolean

whether to keep only recent or all blocks

false

number

number of blocks to keep state for

256

string

database backend

auto

string

logging verboisty level

info

boolean

enables connecting to telemetry server

false

string

telemetry service URL

wss://telemetry.polkadot.io/submit/ 0

string

exposes prometheus exporter endpoint

false

number

prometheus exporter port

9615

boolean

enables JSON-RPC server

false

number

JSON-RPC server port

9933

boolean

enables Websocket server

false

number

Websocket server port

9944

array

browser origins allowed to access the JSON-RPC HTTP and WS servers

all

object

node compute and storage resources to alloacte

image

extraArgs

extraArgs are extra arguments to pass down to the node client. This can be useful if kotal doesn't support something you're inttersted in.

# these extra arguments will be passed as follow to the client
# --arg1 val1 --toggle --arg2 val2
extraArgs:
  "--arg1": val1
  "--toggle": ""
  "--arg2": val2

Note that extraArgs adds arguments only, and doesn't remove arguments. Future release will support removing arguments. Use this feature with care.

replicas

replicas is number of replicas. Accepted values are 0 and 1 only.

replicas is used to start and shutdown node gracefully.

network

p2pPort

p2pPort is p2p protocol tcp port.

nodePrivateKeySecretName

nodePrivateKeySecretName is Kubernetes secret name holding node Ed25519 private key in data field called key.

# generate binary node key and save it in node.key file
subkey generate-node-key node.key
# convert node.key binary file into hexadecimal node.key.hex file
xxd -p -c 32 node.key > node.key.hex

Create node private key secret:

kubectl create secret generic polkadot-node-key  --from-file=key=node.key.hex

polkadot-node-key secret can be used in your polkadot Node by updating .spec with nodePrivateKeySecretName: polkadot-node-key.

validator

validator enables validator.

Node must sync blocks in archive mode pruning: false if validator is enabled.

syncMode

syncMode is blockchain synchronization mode. Available values are fast and full.

pruning

pruning controls whether to keep only recent or all blocks. Setting pruning to false runs the node in archive mode.

retainedBlocks

retainedBlocks is the number of blocks to keep state for. It's only considered if .spec.pruning is set to true.

database

database is database backend. Possible values are auto, paritydb or rocksdb.

logging

logging is logging verboisty level. Available logging levels are error, warn, info, debug, and trace.

telemetry

telemetry enables connecting to telemetry server.

telemetryURL

telemetryURL is telemetry service URL. It's only considered if .spec.telemetry is set to true.

promethems

prometheus exposes prometheus exporter endpoint.

prometheusPort

prometheusPort is prometheus exporter port

rpc

rpc enables JSON-RPC server.

rpcPort

rpcPort is JSON-RPC server port.

ws

ws enables Websocket server.

wsPort

wsPort is Websocket server port.

corsDomains

corsDomains is browser origins allowed to access the JSON-RPC HTTP and WS servers.

resources

resources allocates compute and storage resources to the node.

Syntax
Type
Description
Default

cpu

string

number of cpu cores this node requires

4

cpuLimit

string

number of cpu cores this node is limited to

8

memory

string

memory this node requires

4Gi

memoryLimit

string

memory this node is limited to

8Gi

storage

string

disk space this node requires

80Gi

storageClass

string

Node volume storage class

Cluster's default storage class will be used as defined by cluster admin or cloud provider

memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.

cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1), 1500m, 2, and 4.

cpuLimit can't be less than cpu.

memoryLimit can't be less than or equal to memory.

storageClass field is immutable, it cannot be changed after creation.

Ethereum 2.0

BeaconNode

Syntax
Type
Description
Default

string

Network to join

string

Ethereum 2.0 client to use

array

Ethereum 1 JSON RPC endpoints

array

hostnames to whitelist for RPC access

*

array

domains from which to accept cross origin requests

*

bool

Enable REST API server

false

string

REST API server host

0.0.0.0

number

REST API server port

5051

bool

Enables JSON RPC server

false

string

JSON RPC server host

0.0.0.0

number

JSON RPC server port

4000

bool

GRPC gateway server

false

string

GRPC gateway server host

0.0.0.0

number

GRPC gateway server port

3500

number

p2p and discovery port

9000

string

k8s secret name that holds tls.key and tls.crt

string

logging verbosity level

info

object

Node compute and storage resources

network

network is Ethereum 2.0 network to join and sync its beacon chain.

client

client is the Ethereum 2.0 client to use.

client possible values are teku,prysm,lighthouse, and nimbus.

eth1Endpoints

eth1Endpoints is array of Ethereum 1 JSON RPC endpoints.

prysm, teku, and lighthouse clients support multiple endpoints in eth1Endpoints.

nimbus client supports only 1 endpoint in eth1Endpoints.

hosts

hosts is a list of host names to whitelist for RPC access (server enforced).

corsDomains

corsDomains is a list of domains from which to accept cross-origin requests (browser enforced).

rest

rest enables REST API server.

REST API server is only supported by teku and lighthouse.

restHost

restHost is the REST API server host.

restPort

restPort is the REST API server port.

rpc

rpc enables JSON RPC server.

JSON RPC server is only supported by nimbus and prysm.

rpcHost

rpcHost is the JSON RPC server host.

rpcPort

rpcPort is the JSON RPC server port.

grpc

grpc enables GRPC gateway server.

GRPC gateway is only supported by prysm client.

grpcHost

grpcHost is the GRPC gateway server host.

grpcPort

grpcPort is the GRPC gateway server port.

p2pPort

p2pPort is the p2p and discovery port.

certSecretName

certSecretName is k8s secret name that holds TLS private key in data field called tls.key and TLS certificate in data field called tls.crt.

certSecretName is supported only by prysm client.

logging

logging is logging verbosity level.

Different levels are supported by different Ethereum 2.0 beacon node clients.

Logging/Client
Teku
Lighthouse
Prysm
Nimbus

off

✔️

❌

❌

❌

fatal

✔️

❌

✔️

✔️

none

❌

❌

❌

✔️

notice

❌

❌

❌

✔️

error

✔️

✔️

✔️

✔️

warn

✔️

✔️

✔️

✔️

info

✔️

✔️

✔️

✔️

debug

✔️

✔️

✔️

✔️

trace

✔️

❌

✔️

✔️

all

✔️

❌

❌

❌

critical

❌

✔️

❌

❌

panic

❌

❌

✔️

❌

resources

resources allocates compute and storage resources to the node.

resources object has the following fields:

Syntax
Type
Description
Defalt

cpu

string

number of cpu cores this node requires

4

cpuLimit

string

number of cpu cores this node is limited to

8

memory

string

memory this node requires

8Gi

memoryLimit

string

memory this node is limited to

16Gi

storage

string

disk space this node requires

200Gi

storageClass

string

Node volume storage class

Cluster's default storage class will be used as defined by cluster admin or cloud provider

memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.

cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1 core), 1500m which is 1.5 core, 2 cores, and 4 cores.

cpuLimit can't be less than cpu.

memoryLimit can't be less than or equal to memory.

storageClass field is immutable, it cannot be changed after creation.

Validator

Syntax
Type
Description
Default

string

Network to validate blocks for

string

Ethereum 2.0 client to use

array

List of beacon node endpoints

string

k8s secret name that holds tls.crt

string

Text to include in proposed blocks

Powered by Kotal

string

Wallet password kubernetes secret

array

Validator keystores

string

logging verbosity level

info

object

Validator compute and storage resources

network

network is the Network to validate blocks for.

client

client is the Ethereum 2.0 client to use.

beaconEndpoints

beaconEndpoints is a list of beacon node endpoints.

lighthouse is the only client that supports multiple endpoints. All other clients supports only a single endpoint.

certSecretName

certSecretName is k8s secret name that holds TLS certificate in data field called tls.crt.

certSecretName is supported only by prysm client.

graffiti

graffiti is the text to include in proposed blocks.

walletPasswordSecretName

walletPasswordSecretName is prysm wallet password kubernetes secret.

walletPasswordSecretName is supported only by prysm client.

Wallet password secret must be deployed before deploying the validator.

Wallet password secret must contain the password in key named password.

# create k8s secret from password value
kubectl create secret wallet-password --from-literal=password=<actual-password>
# create k8s secret from password file
kubectl create secret wallet-password --from-file=password=<password-file-path>

keystores

keystores is array of keystore objects.

Syntax
Type
Description

secretName

string

kubernetes secret name holding keystore and password

publicKey

string

Validator public key in hexadecimal

Validator keystore public key is required in case of client: lighthouse

Keystore secret must be deployed before deploying the validator.

Keystore secret must contain the BLS12-381 keystore JSON file in data field key called keystore key, and password in password key.

# create k8s secret from keystore and password file
kubectl create secret my-validator --from-file=keystore=/path/to/keystore.json --from-file=password=/path/to/password.txt

logging

logging is logging verbosity level.

Different levels are supported by different Ethereum 2.0 beacon node clients.

Teku validator client doesn't support logging. Verbosity level will be ignored 🙈

Logging/Client
Lighthouse
Prysm
Nimbus

off

❌

❌

❌

fatal

❌

✔️

✔️

none

❌

❌

✔️

notice

❌

❌

✔️

error

✔️

✔️

✔️

warn

✔️

✔️

✔️

info

✔️

✔️

✔️

debug

✔️

✔️

✔️

trace

❌

✔️

✔️

all

❌

❌

❌

critical

✔️

❌

❌

panic

❌

✔️

❌

resources

resources allocates compute and storage resources to the node.

resources object has the following fields:

Syntax
Type
Description
Defalt

cpu

string

number of cpu cores this node requires

4

cpuLimit

string

number of cpu cores this node is limited to

8

memory

string

memory this node requires

8Gi

memoryLimit

string

memory this node is limited to

16Gi

storage

string

disk space this node requires

200Gi

memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.

cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1 core), 1500m which is 1.5 core, 2 cores, and 4 cores.

cpuLimit can't be less than cpu.

memoryLimit can't be less than or equal to memory.

IPFS

Peer

Kotal uses only go-ipfs client for IPFS peers, that's why there's no .spec.client option.

Syntax
Type
Description
Default

Array

List of initial configuration profiles

default-datastore

Array

List of configuration profiles to apply after peer initialization

string

API server host

0.0.0.0

number

API server port

5001

string

Local ipfs gateway host

0.0.0.0

number

Local ipfs gateway port

8080

string

Content routing mechanism

dht

string

Name of the k8s secret holding swarm secret key

object

Compute and storage resources

initProfiles

initProfiles is al list of initial ipfs configuration profile.

initialProfiles available values are server, randomports, default-datastore, local-discovery, test, default-networking, flatfs, badgerds, and lowpower.

initProfiles can't be updated (immutable).

profiles

profiles is the list of configuration profiles to apply after peer initialization.

profiles available values are server, randomports, default-datastore, local-discovery, test, default-networking, flatfs, badgerds, and lowpower.

apiHost

apiHost is API server host.

If you set apiHost to host other than 0.0.0.0, api calls forwarded to the container won't hit the API server. This is useful if you want to disallow calls to API server.

apiPort

apiPort is API server port.

gatewayHost

gatewayHost is local ipfs gateway host.

If you set gatewayHost to host other than 0.0.0.0, gateway won't work. This is useful if you want to disable to access gateway from outside.

gatewayPort

gatewayPort is API server port.

routing

routing is the content routing mechanism.

routing available values are none, dht, dhtclient, dhtserver.

swarmKeySecretName

swarmKeySecretName is the kubernetes secret name that's holding the swarm key in a key called secret.

kubectl create secret generic swarm-key --from-literal=secret=$w@rmk3y

resources

resources allocates compute and storage resources to the peer.

resources object has the following fields:

Syntax
Type
Description
Defalt

cpu

string

number of cpu cores this peer requires

1

cpuLimit

string

number of cpu cores this peer is limited to

2

memory

string

memory this peer requires

2Gi

memoryLimit

string

memory this peer is limited to

4Gi

storage

string

disk space this peer requires

10Gi

storageClass

string

Node volume storage class

Cluster's default storage class will be used as defined by cluster admin or cloud provider

Memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.

cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1 core), 1500m which is 1.5 core, 2 cores, and 4 cores.

cpuLimit can't be less than cpu.

memoryLimit can't be less than or equal to memory.

storageClass field is immutable, it cannot be changed after creation.

ClusterPeer

Kotal uses only ipfs-cluster-service for IPFS cluster peers that runs along with go-ipfs, that's why there's no .spec.client option.

Syntax
Type
Description
Default

string

Cluster peer ID

string

Name of the k8s secret holding cluster peer privatekey

* if consensus is crdt

array

Peer IDs that can manage the pinset in crdt consensus

array

Peers to connect to on startup

string

Cluster consensus algorithm

crdt

string

ipfs peer http API endpoint

string

Name of the k8s secret holding cluster secret

object

Compute and storage resources

id

id is cluster peer id derived from private key.

id is required if privateKeySecretName is provided.

ipfs-key -type ed25519 | base64

It will return an output similar to the following:

Generating a 2048 bit ed25519 key...
Success!
ID for generated key: 12D3KooWT2bqgwZPxHthAGBV9Ut8ZLraz1LARtB7vG3mF26Mtof1
CAESQLepaunFGa/PI0oNS3plrbVSInqab/X/U1laEDe2V2cL/7kbF9H6x3xBiwpbVnYT/jDA8EhAznXALlbwzEsuKaw=

privateKeySecretName

privateKeySecretName is the name of the k8s secret holding base64 cluster peer privatekey in a key called key.

privateKeySecretName is required if id is provided.

ipfs-key -type ed25519 | base64

It will return an output similar to the following:

Generating a 2048 bit ed25519 key...
Success!
ID for generated key: 12D3KooWT2bqgwZPxHthAGBV9Ut8ZLraz1LARtB7vG3mF26Mtof1
CAESQLepaunFGa/PI0oNS3plrbVSInqab/X/U1laEDe2V2cL/7kbF9H6x3xBiwpbVnYT/jDA8EhAznXALlbwzEsuKaw=

trustedPeers

trustedPeers is a list of peer IDs that can manage the cluster pinset in crdt consensus clusters.

trustedPeers is ignored in raft consensus clusters.

trustedPeers default value is * which is trust all peers.

bootstrapPeers

bootstrapPeers is a list of peers to connect to on startup.

bootstrapPeers will be trusted peers in crdt clusters.

consensus

consensus is the cluster consensus algorithm.

peerEndpoint

peerEndpoint id ipfs peer http API endpoint.

peerEndpoint is required for the cluster peer to function correctly.

clusterSecretName

clusterSecretName is the k8s secret name holding 32-bit hex-encoded (without 0x) cluster secret in a key called secret.

clusterSecretName can be generated using openssl tool:

CLUSTER_SECRET=$(openssl rand -hex 32)
kubectl create secret generic cluster-secret --from-literal=secret=$CLUSTER_SECRET

resources

resources allocates compute and storage resources to the peer.

resources object has the following fields:

Syntax
Type
Description
Defalt

cpu

string

number of cpu cores this peer requires

1

cpuLimit

string

number of cpu cores this peer is limited to

2

memory

string

memory this peer requires

2Gi

memoryLimit

string

memory this peer is limited to

4Gi

storage

string

disk space this peer requires

10Gi

Memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.

cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1 core), 1500m which is 1.5 core, 2 cores, and 4 cores.

cpuLimit can't be less than cpu.

memoryLimit can't be less than or equal to memory.

Ethereum

Node

Syntax
Type
Description
Default

string

Public network name to join, like mainnet, rinkeby, and goerli

boolean

Ethereum nodes will be scheduled on different kubernetes nodes

false

string

kubernetes node label key used to distribute ethereum nodes

topology.kubernetes.io/zone

object

Genesis block configuration

array

ethereum node URLs for p2p discovery bootstrap

string

ethereum client powering the node

string

ethereum account to which mining rewards are paid

array

domains from which to accept cross origin requests (browser enforced)

*

boolean

enable GraphQL server

false

number

GraphQL server listening port

8547

array

hostnames to whitelist for RPC access (server enforced)

*

object

ethereum account to import for geth node

string

node logging verbosity level

info

boolean

node is mining or signing blocks ?

false

string

name of kubernetes secret holding node private key

string

node p2p port

30303

object

node compute and storage resources to alloacte

boolean

enable HTTP RPC server

false

number

HTTP RPC server listening port

8545

array

services to enable

web3, eth, and net

array

set of trusted ethereum nodes to maintain connection to

string

blockchain synchronization mode

fast in public, full in private

boolean

enable web socket server

false

number

web socket server listening port

8546

array

services to enable

web3, eth, and net

network

network is the public network name to join, like rinkeby.

network can't be provided in private networks, where .spec.genesis is not null.

network can't be updated (immutable).

highly available

highlyAvailable controls if Ethereum nodes will be scheduled on different Kubernetes nodes.

topology key

topologyKey is Kubernetes node label key used to distribute ethereum nodes pods on different kubernetes nodes.

bootnodes

bootnodes is ethereum node URLs for p2p network discovery and bootstraping.

bootnodes accepts ethereum node URL enodeURL or a reference to kotal Node in the form of name.namespace where namespace is optional if referenced node is in the same namespace.

Ethereum clients have hardcoded bootnodes for public main and test networks. bootnodes will override these bootnodes.

client

client is the Ethereum client name powering the node.

client possible values are besu, geth, nethermind.

Only besu client can be used if network consensus is ibft2.

Only besu can be used in fixed difficulty proof of work networks, where spec.genesis.ethash.fixedDifficulty is not null.

coinbase

coinbase is ethereum account to which mining rewards are paid.

coinbase is required if the node is mining miner: true.

corsDomains

corsDomains is a list of domains from which to accept cross-origin requests (browser enforced).

Default value * will be used if HTTP RPC server is enabled rpc: true or web socket server is enabled ws: true or graphQL server is enabled graphql: true.

graphql

graphql enables the GraphQL server.

  • Nethermind client doesn't support GraphQL.

graphqlPort

graphqlPort GraphQL server listening port.

The default value 8547 will be used if the graphQL server is enabled graphql: true.

hosts

hosts is a list of host names to whitelist for RPC access (server enforced).

import

import is the ethereum account to import. Only for nodes running with geth or nethermind.

During account creation, it will be encrypted with the password, and during import it will be unlocked using the same password.

Nodes that import accounts can't enable HTTP RPC server, web socket server, or GraphQL server to prevent funds drainage if exposed to the internet.

Account must be imported if the node is running with geth or nethermind clients wants to be a signer or miner.

Syntax
Type
Description

privateKeySecretName

string

name of the k8s secret holding account private key in hexadecimal (without 0x) in data field called key

passwordSecretName

string

name of the k8s secret holding encryption secret in data field called password

logging

logging is Ethereum node logging verbosity level.

logging possible values are off, fatal, error, warn, debug, info, trace and all.

Different clients support different logging vrbosity levels as shown in the following table:

Logging/Client
Hyperledger Besu
Go Ethereum
Nethermind

off

✔️

✔️

❌

fatal

✔️

❌

❌

error

✔️

✔️

✔️

warn

✔️

✔️

✔️

debug

✔️

✔️

✔️

info

✔️

✔️

✔️

trace

✔️

❌

✔️

all

✔️

✔️

❌

miner

miner enables node mining or signing blocks.

nodePrivateKeySecretName

nodePrivateKeySecretName is the node private key.

nodePrivateKeySecretName is required if the node is a boot node bootnode: true, or if besu node with client: besu is a signer in proof of authority clique network or validator in ibft2 network.

p2pPort

p2pPort is node p2p port for communication (TCP) and discovery (UDP).

resources

resources allocates compute and storage resources to the node.

Syntax
Type
Description
Default

cpu

string

number of cpu cores this node requires

2 in private, 4 in public

cpuLimit

string

number of cpu cores this node is limited to

3 in private, 6 in public

memory

string

memory this node requires

4Gi in private, 8Gi in public

memoryLimit

string

memory this node is limited to

8Gi in private, 16Gi in public

storage

string

disk space this node requires

100Gi in private, 6Ti in mainnet with full sync, 750Gi in mainnet wit fast sync, 25Gi in public test networks

storageClass

string

Node volume storage class

Cluster's default storage class will be used as defined by cluster admin or cloud provider

memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.

cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1), 1500m, 2, and 4.

cpuLimit can't be less than cpu.

memoryLimit can't be less than or equal to memory.

storageClass field is immutable, it cannot be changed after creation.

rpc

rpc enables the HTTP RPC server.

rpcPort

rpcPort is the HTTP RPC server listening port.

Default value 8545 will be used if the HTTP RPC server is enabled with rpc: true.

rpcAPI

rpcAPI is a list of RPC services to enable.

Default value ["web3", "eth", "net] will be used if HTTP RPC server is enabeld with rpc: true.

staticNodes

staticNodes is a set of trusted ethereum nodes to maintain connection to.

Static nodes are exempt from maximum peer and remote connection limits. Ethereum clients periodically initiating a connection to any unconnected static node.

staticNodes accepts ethereum node URL enodeURL or a reference to kotal Node in the form of name.namespace where namespace is optional if referenced node is in the same namespace.

syncMode

syncMode is Blockchain synchronization mode.

syncMode possible values are light, full, snap or fast.

light and snap sync modes are only supported by go-ethereum client.

ws

ws enables the web socket server.

wsPort

wsPort is the web socket server listening port.

The default value 8546 is used if the web socket server is enabled with ws: true.

wsAPI

wsAPI is a list of rpc services to enable.

the default value ["web3", "eth", "net] will be used if the web socket server is enabeld with ws: true.

genesis

genesis is the genesis block configuration.

Genesis block configuration genesis is required in private networks.

Syntax
Type
Description
Default

number

number

used in network p2p communications

string

benefeciary (ethereum address) of mining reward

address(0)

string

difficulty (hexadecimal number) of the genesis block

0x1

string

hash (hexadecimal) combined with nonce to prove effort spent to create block

0x00..00

string

total gas limit (hexadecimal number) for all transactions in a block

0x47b760

string

random hexadecimal number used in block computation

0x0

string

genesis block creation date (hexadecimal)

0x0

Array

array of accounts to prefund and store code

object

supported forks and corresponding block number

object

Proof of Work consensus configuration

object

Proof of Authority consensus configuration

object

IBFT2 consensus configuration

chainId

chainId is required.

chainId can't reuse existing public network chain id to avoid transaction replay.

Network
Chain id

mainnet

1

ropsten

3

rinkeby

4

goerli

5

kotti

6

ethereum classic

61

Mordor

63

development

2018

networkId

id is the network id used for p2p communications between network nodes in private networks.

id is required in private networks.

id can't be provided while joining a public network.

id can't be updated (immutable).

coinbase

coinbase is the beneficiary (ethereum address) of mining reward.

coinbase is optional.

difficulty

difficulty is the difficulty of the genesis block.

difficulty is optional.

mixHash

mixHash is combined with the nonce to prove the effort spent to create a block.

mixHash is optional.

gasLimit

gasLimit is the total gas limit for all transactions in a block.

gasLimit is optional.

nonce

nonce is a random number used in block computation.

nonce is optional.

timestamp

timestamp is block creation date.

timestamp is optional.

forks

forks is an object, where the key is fork name and the value is the block number at which to activate this fork.

forks is optional.

if forks is missing, all forks will be activated at block 0 (genesis block) except DAO.

Later forks like muirglacier can't be activated before earlier forks like homestead. They must be ordered as in the following table:

Syntax
Type
Description

homestead

number

dao

number

eip150

number

eip155

number

eip158

number

byzantium

number

constantinople

number

petersburg

number

istanbul

number

muirglacier

number

berlin

number

london

number

arrowGlacier

number

accounts

accounts is an array of accounts to fund or store code.

accounts is optional.

accounts is recommended for networks where signers or validators are not rewarded with eth.

a single account has no defaults.

Syntax
Type
Description

address

string

ethereum address

balance

string

account balance in hexadecimal

code

string

bytecode in hexadecimal

storage

map

key is the storage location in hexadecimal, and value in hexadecimal is the storage value

ethash

ethash is Proof of Work consensus engine configuration.

ethash is optional.

ethash can be set only in proof of work private networks.

ethash.fixedDifficulty has no default value.

ethash.fixedDifficulty is only supported by Hyperledger Besu Client client: besu

Syntax
Type
Description
Default

fixedDifficulty

number

fixed difficulty used in block computation

clique

clique is Proof of Authority clique consensus engine configuration.

clique is optional.

clique can be set only in proof of authority clique private networks.

At least one signer in clique.signers is required.

Syntax
Type
Description
Default

blockPeriod

number

block time in seconds

15

epochLength

number

number of blocks after which to reset all votes

1000

signers

Array

array of ethereum addresses

ibft2

ibft2 is IBFT2 engine configuration.

ibft2 is optional.

ibft2 can be set only in IBFT2 private networks.

At least one validator in ibft2.validators is required.

Syntax
Type
Description
Default

blockPeriod

number

block time in seconds

15

epochLength

number

number of blocks after which to reset all votes

1000

validators

array

array of ethereum addresses

requestTimeout

number

timeout for each consensus round in seconds

10

messageQueueLimit

number

message queue limit

1000

duplicateMessageLimit

number

duplicate messages limit

100

futureMessagesLimit

number

future messages buffer limit

1000

futureMessagesMaxDistance

number

maximum height from current chain height for buffering future messages

10

Chainlink

ethereumChainId

ethereumChainId is ethereum chain id.

linkContractAddress

linkContractAddress is Link contract address.

ethereumWsEndpoint

ethereumWsEndpoint is Ethereum node's WebSocket server endpoint.

ethereumHttpEndpoints

ethereumHttpEndpoints is array of Ethereum HTTP endpoints used for heavy requests and as fallback in case of Ethereum node bug or failure.

databaseURL

databaseURL is Postgres database connection URL.

keystorePasswordSecretName

keystorePasswordSecretName is k8s secret name that holds keystore (wallet) password in data field called password.

apiCredentials

apiCredentials is the credetials used to access Chainlink node UI:

corsDomains

corsDomains is a list of domains from which to accept cross origin requests.

certSecretName

certSecretName is k8s secret name that holds TLS private key in tls.key data field and TLS certificate in tls.crt data field.

apiPort

apiPort is the port used for node API and GUI.

tlsPort

tlsPort is the port used for HTTPS connections.

p2pPort

p2pPort is the port used for p2p communcations.

secureCookies

secureCookies enables secure cookies for authentication.

logging

logging is logging verbosity level. Possible values are debug, info, warn, error, and panic.

resources

resources allocates compute and storage resources to the node.

memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.

cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1), 1500m, 2, and 4.

cpuLimit can't be less than cpu.

memoryLimit can't be less than or equal to memory.

storageClass field is immutable, it cannot be changed after creation.

Stacks

network

network is Stacks network to join and sync. Possible values are mainnet and testnet.

network is immutable, can't be changed after node is created.

rpcPort

rpcPort is JSON-RPC server port.

rpcHost

rpcHost is JSON-RPC server host.

p2pPort

p2pPort is p2p bind port.

p2pHost

p2pHost is p2p bind host.

bitcoinNode

bitcoinNode is Bitcoin node details for Stacks node to connect and query:

miner

miner enables mining.

seedPrivateKeySecretName

seedPrivateKeySecretName is Kubernetes secret name holding seed private key used for mining.

mineMicroblocks

mineMicroblocks enables mining Stacks micro blocks.

nodePrivateKeySecretName

nodePrivateKeySecretName is Kubernetes secret name holding node private key.

resources

resources allocates compute and storage resources to the node.

memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.

cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1), 1500m, 2, and 4.

cpuLimit can't be less than cpu.

memoryLimit can't be less than or equal to memory.

storageClass field is immutable, it cannot be changed after creation.

Filecoin

Kotal uses only lotus client for Filecoin nodes, that's why there's no .spec.client option.

network

network is the network this node should join and sync its blockchain data.

network possible values are mainnet, and calibration.

butterfly and nerpa networks have been deprecated 🥺

api

api enables API server.

apiPort

apiPort is API server listening port.

apiHost

apiHost is API server host.

apiRequestTimeout

apiRequestTimeout is API request timeout in seconds.

disableMetadataLog

disableMetadataLog disables metadata logging.

p2pPort

p2pPort is p2p port.

p2pHost

p2pHost is p2p host.

ipfsPeerEndpoint

ipfsPeerEndpoint ipfs peer endpoint.

ipfsOnlineMode

ipfsOnlineMode sets sets ipfs online mode.

ipfsForRetrieval

ipfsForRetrieval uses ipfs for retrieval.

resources

resources allocates compute and storage resources to the node.

memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.

cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1), 1500m, 2, and 4.

cpuLimit can't be less than cpu.

memoryLimit can't be less than or equal to memory.

storageClass field is immutable, it cannot be changed after creation.

required

image is polkadot node client image. Kotal dashboard uses image information published .

network is the polkadot network/chain to join and sync. Possible values are polkadot, kusama, rococo, westend and other chains supported by client.

Node private can be generated using tool from Parity Substrate.

required

required

id can be generated using tool.

privateKeySecretName can be generated using tool.

Support for OpenEthereum (parity) client has been deprecated. OpenEthereum team is working with Erigon on a smooth transition path for users. More information can be found

Geth (Go-Ethereum) GraphQL server can be used only if RPC is enabled as of geth

Nethermind client which was activated by syncMode: light.

used in transaction signature to prevent transactions reply

chainId is the chain id value used in transaction signature to prevent transactions reply

fork activation block number

fork activation block number

fork activation block number

fork activation block number

fork activation block number

fork activation block number

fork activation block number

fork activation block number

fork activation block number

fork activation block number

fork activation block number

fork activation block number

fork activation block number

Syntax
Type
Description
Default
Syntax
Type
Description
Syntax
Type
Description
Default
Syntax
Type
Description
Default
Syntax
Type
Description
Syntax
Type
Description
Default
Syntax
Type
Description
Default
Syntax
Type
Description
Default
here
Parity Polkadot
subkey
ipfs-key
ipfs-key
here
v1.9.19 release notes
removed support for beam sync
eip155

email

string

User email

passwordSecretName

string

k8s secret name that holds password in data field called password

cpu

string

number of cpu cores this node requires

2

cpuLimit

string

number of cpu cores this node is limited to

4

memory

string

memory this node requires

2Gi

memoryLimit

string

memory this node is limited to

4Gi

storage

string

disk space this node requires

20Gi

storageClass

string

Node volume storage class

Cluster's default storage class will be used as defined by cluster admin or cloud provider

endpoint

string

Stacks network to join and sync

p2pPort

number

p2p bind port

rpcPort

number

JSON-RPC server host

rpcUsername

string

Bitcoin node JSON-RPC username

rpcPasswordSecretName

string

Kubernetes secret name holding bitcoin node JSON-RPC password

cpu

string

number of cpu cores this node requires

2

cpuLimit

string

number of cpu cores this node is limited to

4

memory

string

memory this node requires

4Gi

memoryLimit

string

memory this node is limited to

8Gi

storage

string

disk space this node requires

100Gi

storageClass

string

Node volume storage class

Cluster's default storage class will be used as defined by cluster admin or cloud provider

cpu

string

number of cpu cores this node requires

4 in nerpa, 8 in other networks

cpuLimit

string

number of cpu cores this node is limited to

8 in nerpa, 16 in other networks

memory

string

memory this node requires

8Gi in nerpa, 16Gi in other networks

memoryLimit

string

memory this node is limited to

16Gi in nerpa, 32Gi in other networks

storage

string

disk space this node requires

100Gi in nerpa, 200Gi in other networks

storageClass

string

Node volume storage class

Cluster's default storage class will be used as defined by cluster admin or cloud provider

eip155
Homestead
DAO
eip150
eip155
eip158
Byzantium
Constantipole
Petersburg
Istanbul
Muir Glacier
Berlin
London
Arrow Glacier
network
client
eth1Endpoints
hosts
corsDomains
rest
restHost
restPort
rpc
rpcHost
rpcPort
grpc
grpcHost
grpcPort
p2pPort
certSecretName
logging
resources
network
client
beaconEndpoints
certSecretName
graffiti
walletPasswordSecretName
keystores
logging
resources
initProfiles
profiles
apiHost
apiPort
gatewayHost
gatewayPort
routing
swarmKeySecretName
resources
id
privateKeySecretName
trustedPeers
bootstrapPeers
consensus
peerEndpoint
clusterSecretName
resources
network
highlyAvailable
topologyKey
genesis
bootnodes
client
coinbase
corsDomains
graphql
graphqlPort
hosts
import
logging
miner
nodePrivateKeySecretName
p2pPort
resources
rpc
rpcPort
rpcAPI
staticNodes
syncMode
ws
wsPort
wsAPI
chainId
networkId
coinbase
difficulty
mixHash
gasLimit
nonce
timestamp
accounts
forks
ethash
clique
ibft2
image
extraArgs
replicas
network
p2pPort
nodePrivateKeySecretName
validator
syncMode
pruning
retainedBlocks
database
logging
telemetry
telemetryURL
prometheus
prometheusPort
rpc
rpcPort
ws
wsPort
corsDomains
resources

number

Ethereum chain id

string

Link contract address

string

Ethereum node WebSocket server endpoint

array

Ethereum HTTP endpoints

string

Postgres database connection URL

string

k8s secret name that holds keystore password

object

API credentials

array

Domains from which to accept cross origin requests

*

string

k8s secret name that holds tls.key and tls.crt

number

Port used for node API and GUI

6688

number

Port used for HTTPS connections

6689

number

Port used for p2p communcations

30303

boolean

Enable secure cookies for authentication

false

string

Logging verbosity level

info

object

node compute and storage resources to alloacte

string

Stacks network to join and sync

number

JSON-RPC server port

20443

string

JSON-RPC server host

0.0.0.0

number

p2p bind port

20444

string

p2p bind host

0.0.0.0

object

Bitcoin node details

boolean

Enables mining

false

string

Kubernetes secret name holding seed private key used for mining

boolean

Mines Stacks micro blocks

false

string

Kubernetes secret name holding node private key

object

node compute and storage resources to alloacte

string

network to join and sync

boolean

enables API server

false

number

API server listening port

1234

string

API server host

0.0.0.0

number

API request timeout in seconds

30

boolean

disables metadata logging

false

string

p2p port

4444

string

p2p host

0.0.0.0

string

ipfs peer endpoint

boolean

ipfs online mode

false

boolean

use ipfs for retrieval

false

object

node compute and storage resources to alloacte

required

ethereumChainId
linkContractAddress
ethereumWsEndpoint
ethereumHttpEndpoints
databaseURL
keystorePasswordSecretName
apiCredentials
corsDomains
certSecretName
apiPort
tlsPort
p2pPort
secureCookies
logging
resources
network
rpcPort
rpcHost
p2pPort
p2pHost
bitcoinNode
miner
seedPrivateKeySecretName
mineMicroblocks
nodePrivateKeySecretName
resources
network
api
apiPort
apiHost
apiRequestTimeout
disableMetadataLog
p2pPort
p2pHost
ipfsPeerEndpoint
ipfsOnlineMode
ipfsForRetrieval
resources