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 nodestreasury
is the CLI for use as clientsigner
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.
- Participant 1
- Participant 2
cord backup bak
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.
- Participant 1
- Participant 2
cord genesis init --participant 1 --bak ${BAK}
cord genesis init --participant 2 --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.
- Participant 1
- Participant 2
cord genesis config-peers --peers 10.87.77.1,10.87.77.2
cord genesis config-peers --peers 10.87.77.1,10.87.77.2
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.
- Participant 1
- Participant 2
# 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}
# will keep trying to download until success
cord genesis download-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
- CSL
treasury features update delete_root true --sign-with root-key
update feature delete_root { enabled = true }
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.