Skip to main content

Deployment

Here we'll outline the steps to realize a full, production Treasury instance!

A Treasury instance is a collection of independent nodes, each running on a dedicated server. Usually an instance consists of two or four nodes. A strict supermajority of nodes are required to participate for the instance be available. For example, both nodes in a two node setup, and three nodes in a four node setup.

Each node is assigned a "participant" index, which is a non-zero number (usually, 1, 2, 3...).

Treasury is setup in a few steps, generally:

  • Each node generates minimal identity information.
  • Nodes exchange public-key information to establish root of trust.
  • Networking is configured/tested as necessary.
  • A CSL script is run to initialize policy rules, users, credentials, and any other resource.

Hardware requirements

For each Treasury node, we recommend using:

  • 2x CPU, AMD64 or ARM64 architecture
  • 8 GB RAM
  • 50 GB SSD Disk

Establish connectivity

Nodes need to be able to network to one another. We recommend using a simple Wireguard configuration.

You do not need to wait to have connectivity in order to do most of the steps to setup treasury.

Setup

Download binaries

Download the Treasury binaries cord, signer, and treasury.

  • cord is the CLI for use on server nodes
  • treasury is the CLI for use as client
  • signer is used to provide some cryptographic inputs when setting up an instance

The following curl | sh installs the latest versions to ~/.local/bin.

curl -Sfs https://dl.cordial.systems/init.sh | bash

The versions of cord, signer, and treasury should match (at time of writing: 24.4.4).

init.sh
#!/usr/bin/env bash

set -eo pipefail

# default to "latest"
version=${version:-latest}

# default to "~/.local/bin"
to=${to:-~/.local/bin}

# determine "build"
function _build () {
os=$(uname -s | tr '[:upper:]' '[:lower:]')
arch=$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/')
case $os-$arch in
linux-amd64) echo x86;;
linux-arm64) echo arm;;
darwin-arm64) echo mac;;
*) echo "OS ${os} with architecture ${arch} is not supported"; false;;
esac
}

# downloader
repo="https://dl.cordial.systems/${version}/$(_build)"
function _download () {
echo ":: Downloading ${1}"
curl -Lfs -H "Authorization: Bearer ${access_token}" "${repo}/${1}" | tar xz
}

# download CLI
cd /tmp
_download treasury-cli
./treasury -V

# authenticate - this may require interaction
echo ":: Authenticating"
./treasury token create
access_token=$(./treasury token get)

# download cord
_download cord
./cord version

# download signer
_download signer
./signer -V

# ensure install directory
# echo ":: Ensuring install directory"
install -d "${to}" 2>/dev/null || sudo -p ":: Enter password (to create directory \`${to}\`): " install -d "${to}"

# installer
function _install() {
# echo ":: Installing \`${1}\`"
install "${1}" "${to}" 2>/dev/null || sudo -p ":: Enter password (to install \`${1}\`): " install "${1}" "${to}"
rm "${1}"
}

# install binaries - without sudo if possible
_install cord
_install signer
_install treasury

echo ":: Successfully installed \`cord\`, \`signer\`, and \`treasury\` CLIs!"

To install a different version (e.g., preview, or 24.4.2), run

curl -Sfs https://dl.cordial.systems/init.sh | version=... bash

To install to a different directory (e.g., /usr/local/bin), run

curl -Sfs https://dl.cordial.systems/init.sh | to=... bash

Optionally, verify the signatures on the releases.

Create backup keys

Each node must be configured with a backup key, against which it encrypts and exports its key shares.

We strongly recommend generating one backup key per node, although in principle you can use the same backup key for multiple nodes.

The mnemonic of a backup key is highly sensitive, ideally it is generated on an airgapped machine, and only the public part supplied to the node admin.

cord backup bak

Write down the 12-word mnemonics and keep them safe. These values can be used to decrypt backups of key material.

Save the public parts (the age... values) to use in the next step.

Init

Create the identity for your treasury node.

You may set the location of the data directory used by setting TREASURY_HOME. Set BAK to the public part of the backup key you provisioned for the given node.

cord genesis init --participant 1 --bak ${BAK}

Configure Peers

Configure peers for each node. Here we'll use the IP's from our wireguard guide. Hostnames also works if you have them.

cord genesis config-peers --peers 10.87.77.1,10.87.77.2
info

By default each node will test each socket to see which one refers to itself, in addition to updating the configuration.

You may see or edit the configuration at $TREASURY_HOME/treasury.toml.

Gossip

Gossip the public identity information between all nodes. This also will test & update the peer information as necessary.

All nodes should run these at the same time. Nodes will wait forever until they can connect with their peers.

# run both engine + signer gossip
cord genesis gossip --peer-section engine
cord genesis gossip --peer-section signer

Complete

Now every node can complete their installation.

cord genesis complete ${TREASURY_HOME}/init-*.json

You can inspect the initial data that each node will start with at ${TREASURY_HOME}/config/genesis.json.

Generate and install triples

Triples are a trusted resource that must be generated initially and encrypted to and distributed to all of the participants. One participant must generate and encrypt them, then the others can download them to install. Without this, treasury will not be able to make ECDSA signatures.

# Generating will take some time. Feel free to lower the triple count to speed up for testing.
cord genesis triples 3000000 --home ${TREASURY_HOME}
cord genesis host-triples --home ${TREASURY_HOME}

Install triples

Once the triples are distributed, everyone can install them

# install triples for your participant
cord genesis install-triples --home ${TREASURY_HOME}

Running

While Treasury is launched in a container, you should not run it directly using docker in production. You should run Treasury using cord supervise ..., which has the following benefits.

  • Automatically execute updates that are requested by admins through Treasury.
  • Ensure updates are applied safely, without causing consensus issues or migration faults.
  • Ensure only signed updated are applied.

Use an initial image

Use the corresponding container image to start with:

cord supervise use-image us-docker.pkg.dev/cordialsys/containers/treasury:<version>

Run

# at least one node must run with --connector
cord supervise run --home ${TREASURY_HOME} --backup-dir <path/to/backup-dir> --connector

Learn more about managing backups.

Configure using CSL

Cordial Scripting Language is a minimal language that can be used to initialize all of the policies, users, and credentials on your install. Learn more in the tutorial.

Apply the recommended blueprint. This submits transactions to Treasury and thus only needs to be run once.

treasury script -f blueprint.csl

Delete the "root" user and "root" access rule that Treasury initializes with.

treasury features update delete_root true --sign-with root-key

Updating

To update the software version of Treasury, you should run the following.

treasury software-update create --artifact <IMAGE_REF> --sign-with <your-credential>

To approve:

treasury operations approve <OPERATION> --sign-with <other-credential>

Once approved, the cord supervise ... proccesses will verify and update to the next image.

This can also be done on the UI.