Node setup

You can use the all-in-one docker solution, or install Tendermint, MongoDB, and Planetmint step by step. For more advanced users and for development, the second option is recommended.

Deploy a Machine for Your Planetmint Node

The first step is to deploy a machine for your Planetmint node. It might be a virtual machine (VM) or a real machine, for example, an EC2 on AWS or a droplet on Digital Ocean. If you follow this simple deployment template, all your node’s software will run on that one machine.

We don’t make any assumptions about where you run the machine. It might be in Azure, AWS, your data center or a Raspberry Pi.

IP Addresses

The following instructions assume all the nodes in the network (including yours) have public IP addresses. (A Planetmint network can be run inside a private network, using private IP addresses, but we don’t cover that here.)

Operating System

Use Ubuntu 18.04 Server or above versions as the operating system.

Similar instructions will work on other versions of Ubuntu, and other recent Debian-like Linux distros, but you may have to change the names of the packages, or install more packages.

Network Security Group

If your machine is in AWS or Azure, for example, and you want users to connect to Planetmint via HTTPS, then you should configure its network security group to allow all incoming and outgoing traffic for:

  • TCP on port 22 (SSH)

  • TCP on port 80 (HTTP)

  • TCP on port 443 (HTTPS)

  • Any protocol on port 26656 (Tendermint P2P)

If you don’t care about HTTPS, then forget about port 443, and replace port 80 with port 9984 (the default Planetmint HTTP port).

Update Your System

SSH into your machine and update all its OS-level packages:

sudo apt update
sudo apt full-upgrade

DNS Setup

  • Register a domain name for your Planetmint node, such as example.com

  • Pick a subdomain of that domain for your Planetmint node, such as bnode.example.com

  • Create a DNS “A Record” pointing your chosen subdomain (such as bnode.example.com) at your machine’s IP address.

Basic AWS Setup

Before you can deploy anything on AWS, you must do a few things.

Get an AWS Account

If you don’t already have an AWS account, you can sign up for one for free at aws.amazon.com.

Install the AWS Command-Line Interface

To install the AWS Command-Line Interface (CLI), just do:

pip install awscli

Create an AWS Access Key

The next thing you’ll need is AWS access keys (access key ID and secret access key). If you don’t have those, see the AWS documentation about access keys.

You should also pick a default AWS region name (e.g. eu-central-1). The AWS documentation has a list of them.

Once you’ve got your AWS access key, and you’ve picked a default AWS region name, go to a terminal session and enter:

aws configure

and answer the four questions. For example:

AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: eu-central-1
Default output format [None]: [Press Enter]

This writes two files: ~/.aws/credentials and ~/.aws/config. AWS tools and packages look for those files.

Generate an RSA Key Pair for SSH

Eventually, you’ll have one or more instances (virtual machines) running on AWS and you’ll want to SSH to them. To do that, you need a public/private key pair. The public key will be sent to AWS, and you can tell AWS to put it in any instances you provision there. You’ll keep the private key on your local workstation.

See the appendix page about how to generate a key pair for SSH.

Send the Public Key to AWS

To send the public key to AWS, use the AWS Command-Line Interface:

aws ec2 import-key-pair \
--key-name "<key-name>" \
--public-key-material file://~/.ssh/<key-name>.pub

If you’re curious why there’s a file:// in front of the path to the public key, see issue aws/aws-cli#41 on GitHub.

If you want to verify that your key pair was imported by AWS, go to the Amazon EC2 console, select the region you gave above when you did aws configure (e.g. eu-central-1), click on Key Pairs in the left sidebar, and check that <key-name> is listed.

Run Planetmint with all-in-one Docker

For those who like using Docker and wish to experiment with Planetmint in non-production environments, we currently maintain a Planetmint all-in-one Docker image and a Dockerfile-all-in-one that can be used to build an image for planetmint.

This image contains all the services required for a Planetmint node i.e.

  • Planetmint Server

  • Tarantool

  • Tendermint

Note: NOT for Production Use: This is an single node opinionated image not well suited for a network deployment. This image is to help quick deployment for early adopters, for a more standard approach please refer to one of our deployment guides:

Prerequisite(s)

Pull and Run the Image from Docker Hub

With Docker installed, you can proceed as follows.

In a terminal shell, pull the latest version of the Planetmint all-in-one Docker image using:

$ docker pull planetmint/planetmint:all-in-one

$ docker run \
  --detach \
  --name planetmint \
  --publish 9984:9984 \
  --publish 9985:9985 \
  --publish 3303:3303 \
  --publish 26657:26657 \
  --volume $HOME/planetmint_docker/tarantool:/var/lib/tarantool \
  --volume $HOME/planetmint_docker/tendermint:/tendermint \
  planetmint/planetmint:all-in-one

Let’s analyze that command:

  • docker run tells Docker to run some image

  • --detach run the container in the background

  • publish 9984:9984 map the host port 9984 to the container port 9984 (the Planetmint API server)

    • 9985 Planetmint Websocket server

    • 26657 Tendermint RPC server

    • 3303 Configured port for Tarantool

  • $HOME/planetmint_docker/tarantool:/var/lib/tarantool this allows us to have the data persisted on the host machine, you can read more in the official Docker documentation

  • $HOME/planetmint_docker/tendermint:/tendermint to persist Tendermint data.

  • planetmint/planetmint:all-in-one the image to use. All the options after the container name are passed on to the entrypoint inside the container.

Verify

$ docker ps | grep planetmint

Send your first transaction using Planetmint drivers.

Building Your Own Image

Assuming you have Docker installed, you would proceed as follows.

In a terminal shell:

git clone git@github.com:planetmint/planetmint.git
cd planetmint/

Build the Docker image:

docker build --file Dockerfile-all-in-one --tag <tag/name:latest> .

Now you can use your own image to run Planetmint all-in-one container.

Setting up a network of nodes with the Ansible script

You can find one of the installation methods with Ansible on GitHub at:

Ansible script

It allows to install Planetmint, MongoDB, Tendermint, and python, and then connect nodes into a network. Current tested machine is Ubuntu 18.04.

Set Up Planetmint, Tarantool and Tendermint

We now install and configure software that must run in every Planetmint node: Planetmint Server, Tarantool and Tendermint.

Install Planetmint Server

Planetmint Server requires Python 3.9+, so make sure your system has it.

Install the required OS-level packages:

# For Ubuntu 18.04:
sudo apt install -y python3-pip libssl-dev
# Ubuntu 16.04, and other Linux distros, may require other packages or more packages

Planetmint Server requires gevent, and to install gevent, you must use pip 19 or later (as of 2019, because gevent now uses manylinux2010 wheels). Upgrade pip to the latest version:

sudo pip3 install -U pip

Now install the latest version of Planetmint Server. You can find the latest version by going to the Planetmint project release history page on PyPI. For example, to install version 2.2.2, you would do:

# Change 2.0.0 to the latest version as explained above:
sudo pip3 install planetmint==2.2.2

Check that you installed the correct version of Planetmint Server using planetmint --version.

Configure Planetmint Server

To configure Planetmint Server, run:

planetmint configure

The first question is API Server bind? (default `localhost:9984`).

  • If you’re using NGINX (e.g. if you want HTTPS), then accept the default value (localhost:9984).

  • If you’re not using NGINX, then enter the value 0.0.0.0:9984

You can accept the default value for all other Planetmint config settings.

If you’re using NGINX, then you should edit your Planetmint config file (in $HOME/.planetmint by default) and set the following values under "wsserver":

"advertised_scheme": "wss",
"advertised_host": "bnode.example.com",
"advertised_port": 443

where bnode.example.com should be replaced by your node’s actual subdomain.

Install (and Start) Tarantool

Install a recent version of Tarantool. Planetmint Server requires version 3.4 or newer.

curl -L https://tarantool.io/DDJLJzv/release/2.8/installer.sh | bash

sudo apt-get -y install tarantool

Sharding with Tarantool

If the load on a single node becomes to large Tarantool allows for sharding to scale horizontally. For more information on how to setup sharding with Tarantool please refer to the official Tarantool documentation.

Install Tendermint

The version of Planetmint Server described in these docs only works well with Tendermint 0.31.5 (not a higher version number). Install that:

sudo apt install -y unzip
wget https://github.com/tendermint/tendermint/releases/download/v0.31.5/tendermint_v0.31.5_linux_amd64.zip
unzip tendermint_v0.31.5_linux_amd64.zip
rm tendermint_v0.31.5_linux_amd64.zip
sudo mv tendermint /usr/local/bin

Start Configuring Tendermint

You won’t be able to finish configuring Tendermint until you have some information from the other nodes in the network, but you can start by doing:

tendermint init

Set Up NGINX

If you don’t want HTTPS (for communications between the external world and your node), then you can skip all the NGINX steps on this page.

Note: This simple deployment template uses NGINX for more than just HTTPS. For example, it also does basic rate limiting.

Install NGINX

SSH into your machine and install NGINX:

sudo apt update
sudo apt install nginx

Configure & Reload NGINX

Get an SSL certificate for your node’s subdomain (such as bnode.example.com).

  • Copy the SSL private key into /etc/nginx/ssl/cert.key

  • Create a “PEM file” (text file) by concatenating your SSL certificate with all intermediate certificates (in that order, with the intermediate certs last).

  • Copy that PEM file into /etc/nginx/ssl/cert.pem

  • In the planetmint/planetmint repository on GitHub, find the file nginx/nginx.conf and copy its contents to /etc/nginx/nginx.conf on your machine (i.e. replace the existing file there).

  • Edit that file (/etc/nginx/nginx.conf): replace the two instances of the string example.testnet2.com with your chosen subdomain (such as bnode.example.com).

  • Reload NGINX by doing:

    sudo service nginx reload
    

Configuration Settings

Every Planetmint Server configuration setting has two names: a config-file name and an environment variable name. For example, one of the settings has the config-file name database.host and the environment variable name PLANETMINT_DATABASE_HOST. Here are some more examples:

database.portPLANETMINT_DATABASE_PORT

database.keyfile_passphrasePLANETMINT_DATABASE_KEYFILE_PASSPHRASE

server.bindPLANETMINT_SERVER_BIND

The value of each setting is determined according to the following rules:

  • If it’s set by an environment variable, then use that value

  • Otherwise, if it’s set in a local config file, then use that value

  • Otherwise, use the default value

The local config file is $HOME/.planetmint by default (a file which might not even exist), but you can tell Planetmint to use a different file by using the -c command-line option, e.g. planetmint -c path/to/config_file.json start or using the PLANETMINT_CONFIG_PATH environment variable, e.g. PLANETMINT_CONFIG_PATH=.my_planetmint_config planetmint start. Note that the -c command line option will always take precedence if both the PLANETMINT_CONFIG_PATH and the -c command line option are used.

You can read the current default values in the file planetmint/__init__.py. (The link is to the latest version.)

database.*

The settings with names of the form database.* are for the backend database (currently only Tarantool). They are:

  • database.backend can only be localtarantool, currently.

  • database.host is the hostname (FQDN) of the backend database.

  • database.port is self-explanatory.

  • database.user is a user-chosen name for the database inside Tarantool, e.g. planetmint.

  • database.pass is the password of the user for connection to tarantool listener.

There are two ways for Planetmint Server to authenticate itself with Tarantool (or a specific Tarantool service): no authentication, username/password.

No Authentication

If you use all the default Planetmint configuration settings, then no authentication will be used.

Username/Password Authentication

To use username/password authentication, a Tarantool instance must already be running somewhere (maybe in another machine), it must already have a spaces for use by Planetmint, and that database must already have a “readWrite” user with associated username and password.

Default values

"database": {
    "backend": "tarantool",
    "host": "localhost",
    "port": 3301,
    "username": null,
    "password": null

}

server.*

server.bind, server.loglevel and server.workers are settings for the Gunicorn HTTP server, which is used to serve the HTTP client-server API.

server.bind is where to bind the Gunicorn HTTP server socket. It’s a string. It can be any valid value for Gunicorn’s bind setting. For example:

  • If you want to allow IPv4 connections from anyone, on port 9984, use 0.0.0.0:9984

  • If you want to allow IPv6 connections from anyone, on port 9984, use [::]:9984

In a production setting, we recommend you use Gunicorn behind a reverse proxy server such as NGINX. If Gunicorn and the reverse proxy are running on the same machine, then you can use localhost:9984 (the default value), meaning Gunicorn will talk to the reverse proxy on port 9984. The reverse proxy could then be bound to port 80 (for HTTP) or port 443 (for HTTPS), so that external clients would connect using that port. For example:

[External clients]—(port 443)—[NGINX]—(port 9984)—[Gunicorn / Planetmint Server]

If Gunicorn and the reverse proxy are running on different machines, then server.bind should be hostname:9984, where hostname is the IP address or FQDN of the reverse proxy.

There’s more information about deploying behind a reverse proxy in the Gunicorn documentation. (They call it a proxy.)

server.loglevel sets the log level of Gunicorn’s Error log outputs. See Gunicorn’s documentation for more information.

server.workers is the number of worker processes for handling requests. If set to None, the value will be (2 × cpu_count + 1). Each worker process has a single thread. The HTTP server will be able to handle server.workers requests simultaneously.

Example using environment variables

export PLANETMINT_SERVER_BIND=0.0.0.0:9984
export PLANETMINT_SERVER_LOGLEVEL=debug
export PLANETMINT_SERVER_WORKERS=5

Example config file snippet

"server": {
    "bind": "0.0.0.0:9984",
    "loglevel": "debug",
    "workers": 5,
}

Default values (from a config file)

"server": {
    "bind": "localhost:9984",
    "loglevel": "info",
    "workers": null,
}

wsserver.*

wsserver.scheme, wsserver.host and wsserver.port

These settings are for the aiohttp server, which is used to serve the WebSocket Event Stream API. wsserver.scheme should be either "ws" or "wss" (but setting it to "wss" does not enable SSL/TLS). wsserver.host is where to bind the aiohttp server socket and wsserver.port is the corresponding port. If you want to allow connections from anyone, on port 9985, set wsserver.host to 0.0.0.0 and wsserver.port to 9985.

Example using environment variables

export PLANETMINT_WSSERVER_SCHEME=ws
export PLANETMINT_WSSERVER_HOST=0.0.0.0
export PLANETMINT_WSSERVER_PORT=9985

Example config file snippet

"wsserver": {
    "scheme": "wss",
    "host": "0.0.0.0",
    "port": 65000
}

Default values (from a config file)

"wsserver": {
    "scheme": "ws",
    "host": "localhost",
    "port": 9985
}

wsserver.advertised_scheme, wsserver.advertised_host and wsserver.advertised_port

These settings are for the advertising the Websocket URL to external clients in the root API endpoint. These configurations might be useful if your deployment is hosted behind a firewall, NAT, etc. where the exposed public IP or domain is different from where Planetmint is running.

Example using environment variables

export PLANETMINT_WSSERVER_ADVERTISED_SCHEME=wss
export PLANETMINT_WSSERVER_ADVERTISED_HOST=myplanetmint.io
export PLANETMINT_WSSERVER_ADVERTISED_PORT=443

Example config file snippet

"wsserver": {
    "advertised_scheme": "wss",
    "advertised_host": "myplanetmint.io",
    "advertised_port": 443
}

Default values (from a config file)

"wsserver": {
    "advertised_scheme": "ws",
    "advertised_host": "localhost",
    "advertised_port": 9985
}

log.*

The log.* settings are to configure logging.

Example

{
    "log": {
        "file": "/var/log/planetmint.log",
        "error_file": "/var/log/planetmint-errors.log",
        "level_console": "info",
        "level_logfile": "info",
        "datefmt_console": "%Y-%m-%d %H:%M:%S",
        "datefmt_logfile": "%Y-%m-%d %H:%M:%S",
        "fmt_console": "%(asctime)s [%(levelname)s] (%(name)s) %(message)s",
        "fmt_logfile": "%(asctime)s [%(levelname)s] (%(name)s) %(message)s",
        "granular_levels": {}
}

Default values

{
    "log": {
        "file": "~/planetmint.log",
        "error_file": "~/planetmint-errors.log",
        "level_console": "info",
        "level_logfile": "info",
        "datefmt_console": "%Y-%m-%d %H:%M:%S",
        "datefmt_logfile": "%Y-%m-%d %H:%M:%S",
        "fmt_logfile": "[%(asctime)s] [%(levelname)s] (%(name)s) %(message)s (%(processName)-10s - pid: %(process)d)",
        "fmt_console": "[%(asctime)s] [%(levelname)s] (%(name)s) %(message)s (%(processName)-10s - pid: %(process)d)",
        "granular_levels": {}
}

log.file

The full path to the file where logs should be written. The user running planetmint must have write access to the specified path.

Log rotation: Log files have a size limit of about 200 MB and will be rotated up to five times. For example, if log.file is set to "~/planetmint.log", then logs would always be written to planetmint.log. Each time the file planetmint.log reaches 200 MB it will be closed and renamed planetmint.log.1. If planetmint.log.1 and planetmint.log.2 already exist they would be renamed planetmint.log.2 and planetmint.log.3. This pattern would be applied up to planetmint.log.5 after which planetmint.log.5 would be overwritten by planetmint.log.4, thus ending the rotation cycle of whatever logs were in planetmint.log.5.

log.error_file

Similar to log.file (see above), this is the full path to the file where error logs should be written.

log.level_console

The log level used to log to the console. Possible allowed values are the ones defined by Python, but case-insensitive for the sake of convenience:

"critical", "error", "warning", "info", "debug", "notset"

log.level_logfile

The log level used to log to the log file. Possible allowed values are the ones defined by Python, but case-insensitive for the sake of convenience:

"critical", "error", "warning", "info", "debug", "notset"

log.datefmt_console

The format string for the date/time portion of a message, when logged to the console.

For more information on how to construct the format string please consult the table under Python’s documentation of time.strftime(format[, t]).

log.datefmt_logfile

The format string for the date/time portion of a message, when logged to a log file.

For more information on how to construct the format string please consult the table under Python’s documentation of time.strftime(format[, t]).

log.fmt_console

A string used to format the log messages when logged to the console.

For more information on possible formatting options please consult Python’s documentation on LogRecord attributes.

log.fmt_logfile

A string used to format the log messages when logged to a log file.

For more information on possible formatting options please consult Python’s documentation on LogRecord attributes.

log.granular_levels

Log levels for Planetmint’s modules. This can be useful to control the log level of specific parts of the application. As an example, if you wanted the logging of the core.py module to be more verbose, you would set the configuration shown in the example below.

Example

{
    "log": {
        "granular_levels": {
            "bichaindb.core": "debug"
        }
}

Default value

{}

tendermint.*

The settings with names of the form tendermint.* tell Planetmint Server where it can connect to the node’s Tendermint instance.

  • tendermint.host is the hostname (FQDN)/IP address of the Tendermint instance.

  • tendermint.port is self-explanatory.

Example using environment variables

export PLANETMINT_TENDERMINT_HOST=tendermint
export PLANETMINT_TENDERMINT_PORT=26657
```Planetmint

**Default values**

```js
"tendermint": {
    "host": "localhost",
    "port": 26657
}

.. Copyright © 2020 Interplanetary Database Association e.V., Planetmint and IPDB software contributors. SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) Code is Apache-2.0 and docs are CC-BY-4.0

Production Nodes

.. include:: node-requirements.md :parser: myst_parser.sphinx_ .. include:: node-assumptions.md :parser: myst_parser.sphinx_ .. include:: node-components.md :parser: myst_parser.sphinx_ .. include:: node-security-and-privacy.md :parser: myst_parser.sphinx_ .. include:: reverse-proxy-notes.md :parser: myst_parser.sphinx_