Universa node: server pre-configuration


🇬🇧 / 🇷🇺

This document describes how the Linux server should be configured to launching the Universa Node software on it.

The server should already satisfy the requirements (hardware/OS) specified on Node Owner Central.

Required packages

Latest PostgreSQL repository

Configure PostgreSQL 10 APT sources as described here.

Mandatory packages

Install mandatory packages needed for Universa node launch/maintenance.

apt-get install apache2-utils build-essential check-postgres curl dirmngr git haveged libpam-systemd libpq-dev libssl-dev lsb-release netfilter-persistent nginx-light postgresql postgresql-client pgtop rsync sudo wget vim hdparm net-tools

Java

Installing Oracle JDK from webupd is discontinued because the Oracle license has changed. There are two options now:

  1. Register in Oracle, download and install Linux x64 tar.gz archive.

  2. Install openjdk-11-jdk package from Debian stretch-backports repository.

DISCONTINUED METHOD

Install webupd8.org Oracle Java packages for Debian:

su -
echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main" | tee /etc/apt/sources.list.d/webupd8team-java.list
echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main" | tee -a /etc/apt/sources.list.d/webupd8team-java.list
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886
apt-get update
apt-get install oracle-java8-installer oracle-java8-set-default binfmt-support
exit

Open the /etc/java-8-oracle/security/java.security file in a text editor. Change the line:

securerandom.source=file:/dev/random

to:

securerandom.source=file:/dev/./urandom

Save your change and exit the text editor. See details here.

For OpenJDK 11 edit the file /etc/java-11-openjdk/security/java.security.

Other packages

Recommended packages, but not mandatory:

  • cryptsetup – to protect private keys and other sensitive data in LUKS encrypted partition, or even full PostgreSQL data.
  • certbot – to get free SSL certificates for Nginx HTTP server.

Nginx

See conf-files in attached Nginx configuration tarball, where the actual domain is mentioned as DOMAIN.

Every external node should use its personal domain, we highly recommend to use CloudFlare for protect node, HTTPS and so on. To encrypt the traffic between CloudFlare and node we recommend “Let’s Encrypt” free SSL certificates – install certbot package for this purpose.

Unpack example files from archive and place them to /etc/nginx, change domain name everywhere, edit the SSL certificate paths, generate dhparam, make symlink and reload Nginx:

ln -s /etc/nginx/sites-available/universa_node /etc/nginx/sites-enabled
openssl dhparam -out /etc/nginx/dhparam.pem 4096
nginx -t && nginx -s reload

Obtaining an SSL certificate with certbot

When configuring your node to use free Let’s Encrypt SSL certificates, you should take the following precaution:

Before you’ve received the first SSL certificate for your host, you can’t actually use 8443 ssl line in your Nginx conf file (because there is no certificate yet), so just comment it out for now.

Edit the command to mention your domain, and get certificates with:

certbot certonly -d #{domain} --webroot -w /var/www/letsencrypt

After successful execution, uncomment the SSL-related section in your Nginx file and reload Nginx again (service nginx reload).

Extra configuration

PostgreSQL

After you’ve installed the packages, create the database user for Universa software to user, with some custom password and database name you prefer.

CREATE USER universa PASSWORD '<PASSWORD>';
CREATE DATABASE universa_node WITH OWNER=universa;

Add the following line to the pg_hba.conf; alter it in case if you’ve changed the user name/database name:

local    universa_node   universa       md5

Tuning postgresql.conf

Enable more simultaneous connections in /etc/postgresql/10/main/postgresql.conf:

max_connections = 500

Also, configure the memory-related settings, depending on your server RAM and disk type, so you have to change the numbers (refer to http://pgtune.leopard.in.ua/ and PostgreSQL documentation):

shared_buffers = 196MB 
work_mem = 64MB
maintenance_work_mem = 256MB
max_wal_size = 8GB

Restart server:

systemctl restart postgresql.service

Prepare dedicated user to run the service

Add user deploy for node, please use exactly this name:

useradd -m -s /bin/bash deploy

Enable systemd log view:

usermod -a -G systemd-journal deploy 

Enable systemd service for user:

loginctl enable-linger deploy 

Prepare systemd service file /home/deploy/.config/systemd/user/java.service:

[Unit]
Description=Universa Java daemon
After=network.target

[Service]
StandardOutput=journal+console
StandardError=journal+console
Type=simple
WorkingDirectory=/home/deploy/universad/current
ExecStart=/usr/bin/java -jar /home/deploy/universad/current/app/uninode.jar -c /home/deploy/universad/current                          
TimeoutStartSec=15s
ExecStop=/bin/kill -TERM $MAINPID
TimeoutStopSec=10s
Restart=always

[Install]
WantedBy=default.target

Reload systemd and enable the service:

systemctl --user daemon-reload
systemctl --user enable java

If you are setting up some private test net and multiple nodes at once, then, using uniclient tool, prepare the keys for all the network nodes; the example below is for 10 nodes (for a single node you need just a single key):

for n in $(seq 1 10); do uniclient -g node_$(printf "%04d" $n); done

Prepare the config in YAML format, the example is for first node (node_number: 1). You have to change the domain node-1-test.example.com and IP address.

---                                                                                                                                     
http_client_port: 2052                                                                                                                  
http_client_listen:                                                                                                                     
- 127.0.0.1                                                                                                                             
http_server_port: 2082                                                                                                                  
udp_server_port: 2700                                                                                                                   
database: jdbc:postgresql://localhost:5432/universa_node?user=universa&password=<PASSWORD>                                              
node_number: 1                                                                                                                          
public_host: node-1-test.example.com                                                                                                    
node_name: node-1-test.example.com                                                                                                    
ip:                                                                                                                                     
- 1.2.3.4
ipv6:
- 1111:2222:33:4::5555

Build the Universa node .jar files in multi-jar Gradle configuration:

gradle :universa_node:buildMultiJar -x test

Upload Universa node .jar files to folder ~/universad/current/app.

Upload public keys for all nodes to ~/universad/current/config/keys.

Upload node conf files to ~/universad/current/config/nodes.

Upload current node conf file to ~/universad/shared/config/config.yaml

Upload private key to folder ~/universad/current/tmp – for security reasons, it may be tmpfs or ramfs folder.

Now we ready to start node as systemd service:

systemctl --user start java

Access the configured network

To access the configured nodes or network it you’ll need some client software like uniclient. If you are configuring a private network (rather than using the Mainnet), this client will likely need a network topology file to access it. Use the attached Topology builder application to generate it for your network.

Useful operation commands

To check process status:

systemctl --user status java

To watch the log in realtime (to “follow” the log):

journalctl -f --user-unit java

Extra configuration for remotely-managed nodes only

SSH

Prepare authorized_keys file and add attached public SSH keys to it for a deploy user (your system can use file authorized_keys2 instead).

mkdir -m 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Generate SSH keypair for deploy user:

ssh-keygen

If you have multiple nodes you have to generate this key once and then copy it to other nodes.

Firewall and open ports

The following ports must be open:

tcp 22 or other non standard port used for sshd                                                                                                                       
tcp 80                                                                                                                      
tcp 8080                                                                                                                      
tcp 8443                                                                                                                      
tcp 2052                                                                                                                      
tcp 2082                                                                                                                      
udp 2700