Configurations

elvmasterd

elvmasterd configuration .toml

[node] section

This is the main part of the config. Most parameters are set here.

  • Change this value to a name that identifies the Fabric Node to humans:

    identity = "some-name-that-is-descriptive"
    
  • The datadir needs to exist and be owned by the user that is running the elvmasterd server/daemon. The log location should also be readable/writable by the same user. Based on log retention policies and storage layout, these should be different volumes and the datadir needs to be the fast, large storage noted in the specifications.

    datadir = "/var/elvmasterd/data"
    log_file = "/var/elvmasterd/log/elvmasterd.log"
    
  • These parameters should not change, but using different ports is possible given security restraints on the deployment.

    port = 40304
    rpcaddr = "127.0.0.1"
    rpcport = 8545
    
  • elvmasterd will look in the datadir for a keystore directory. By default it will use the first available keys in this dir. To pin the right address, please use the explicit hex address for the wallet/key. Note, this is the address noted in the partition section.

    node_account = "0x1234abcd..."
    

This account will be setup later on. Just note that it will need to be set. NOTE: A value not mentioned, but does need consideration is ipcpath, which is set to /tmp/elvmasterd.socket. This socket can be used by anyone with read access to it to connect in with the unlocked wallet. Adequate measures should be used to secure this socket.

[hdwallet] section

The following wallet parameters are used to either generate (via elvmasterd wallet create) or in securing/accessing the wallet on setup/startup.

  • The mnemonic needs to be a 12 word phrase that confirms to BIP 39. This is used to generate a seed for the wallet. This can be set at the CLI, or left unset and the wallet creation (only time this is used) will generate one on the fly. If using the generated mnemonic, it is printed in the logs. This mnemonic should be saved and kept secret like a password/passphrase as it can be used to recover or regenerate a wallet.:

    mnemonic = ""
    
  • The passphrase secures the wallet on disk. Pick a strong one.

    passphrase = ""
    

Key Generation

All Fabric Nodes need to have a unique wallet. The address of the wallet is used to identify the Fabric Node and is used in the enode that is used by chain participants to locate a system.

In the config above, the [hdwallet] section is used to create this, but the parameters can also be from the CLI. For the purpose of documenting key generation, both the config set parameters, and the CLI passed version will be shown.

These examples presume the datadir exists and the config file is placed in /etc/elvmasterd as config.toml (and is readable).

Keygen - Config only

/usr/local/bin/elvmasterd wallet create --config /etc/elvmasterd/config.toml

Keygen - CLI only

With supplied mnemonic:

/usr/local/bin/elvmasterd wallet create --datadir /var/elvmasterd-data --passphrase "uber-secret" --mnemonic "word1 ... word12" -n 1

Without supplied mnemonic:

/usr/local/bin/elvmasterd wallet create --datadir /var/elvmasterd-data --passphrase "uber-secret" -n 1

Keygen output

# /usr/local/bin/elvmasterd wallet create --datadir /var/elvmasterd-data --passphrase "uber-secret" -n 1
INFO [12-21|01:12:08.207] keystore                                 dir=/var/elvmasterd-data/keystore
WARN [12-21|01:12:08.213] no user mnemonic specified. creating random value mnemonic="word1 ... word12"
INFO [12-21|01:12:08.241] derive path                              wallet_path=m/44H/60H/0H/0/0
INFO [12-21|01:12:08.244] node account                             address=0xa4f2d5Ff017336Fa416949d1C2DD7c52A772df94
WARN [12-21|01:12:08.244] encrypting keystore account with default password password=uber-secret
INFO [12-21|01:12:10.343] Available accounts
INFO [12-21|01:12:10.343] account[0]                               TargetAddr=0xa4f2d5ff017336fa416949d1c2dd7c52a772df94

NOTE: In this sample output, the 0xa4f2d5Ff017336Fa416949d1C2DD7c52A772df94 address should be used in the configuration for node_account noted above.

Full Sample elvmasterd.toml

The following example elvmasterd configuration can enable validation, provided the directories and files specified are created/exist.

enc_block = "H4sIAAAAAAAA/6yUz47jNgzG30VnH6g/lMQcix5aoNc+AEmRE6NJnCYOMNtF3r3IzjYLbC8ezOhG2v6Zn/R9+hp0Ofn8EnZfg+55Pv0+wo4QM+AU9svRrqvx+OWw6F9hB1Ow+RwRfq5/4+s+7AK8wgdX+E7En/7Qf9Ty5R8+rfPt+KOlh/nvmz0knO0yL+Ptu/Oi+7CLAHC/T+G0nNTeZgxTWOeHMj6enx17XS/8K6/8KTq0e6qSKrbBXXNqvbbMpUYwcxBwJYXRR84GRLVJslRUBWrHApGxgI6YE7Jnq8kaupeIppF0qPXC3Myl8sCUurgn7d1UyMS1kMcOEBOJZ7TSwHrJQgwSQbRiQVUamVhrx9xSKrGRtRydqBWNkdzQvGX96D58fIUpvPD1j/k4r99OJuaYxrf2mN1nvR3WL28PwhSO8+tnWlGX+SR8tXfxwhT4cFj0Ycetx/t4V/jA/1mUsTqjEEEkRu3fyfcpoKbcZQzVaLmUrFg0EmXCXDCjJ8NcHev/iKN1E0XWmp6w2iI6iUht5obUwUdPMmQQNM6xZnTOrW2CbbXodq3EDK5dPGbj3gzAYqlavWXpDQSkegTWTeNtTcb28bZm/B3EjancTjSJHaGhYMucuYCmVhChsvRILhUrGTNt2kLzREJRMqTUAY37IGQX8UIwAFKJRC3BBtjjQr4dxS7P+/eFr39ebTzrM1/stH5emu//BgAA//9rsh4v6gYAAA=="

[node]
identity = "some-validator"
datadir = "/var/elvmasterd/data"
networkid = 955305
port = 40304
nodiscover = false
ipcenable = true
ipcpath = "/tmp/elvmasterd.socket"
rpcaddr = "127.0.0.1"
rpcport = 8545
rpccorsdomain = "*"
node_account = ""

verbosity = 4
log_file = "/var/elvmasterd/log/elvmasterd.log"
log_rotate = true
log_maxbackups = 5
log_maxage = 6
log_maxsize = 100

discovery_urls = "enrtree://ANSPCRAV5TS5FGBBXB7ERZBRUCTS4BLXOF7BQIELODCLLZE2BR2U4@main955305.nodes.cfab.app"

[hdwallet]
mnemonic = ""
passphrase = ""
accounts = 1

elvmasterd systemd Unit

elvmasterd should be run with some form of process management, like systemd to ensure the daemon loads on system boot, and reloads when failures occur.

[Unit]
Description=Eluvio elvmasterd
After=network.target

[Service]
User=eluvio
Group=eluvio
Type=simple
Restart=always
RestartSec=30s

ExecStart=/usr/local/bin/elvmasterd start \
  --config=/etc/elvmasterd/config.toml \
  --log-file=/var/elvmasterd/log/elvmasterd.log

[Install]
WantedBy=default.target

The attached versions highlight other scenarios that will work, but may not be documented in detail otherwise.

qfab

Below are the main sections that need per-host configuration.

.paths section

From there the main paths used to determine where parts are stored is defined:

{
  "paths": {
    "install_path": "/var/qfab/QDATA",
    "qparts_path": "/var/qfab/QDATA/PARTS",
    "qtemp_path": "/var/qfab/QDATA/TMP",
    "qlibs_path": "/var/qfab/QDATA/LIBS",
    "node_path": "/var/qfab/QDATA/LOCAL",
    "cache_path": "/var/qfab/CACHE"
  },

The sample uses the /var/qfab storage location noted in the setup documentation.

.fabric.node_id parameter

Each nodes is identified by an ID, and this ID is placed in the configuration file. The Node ID is an encoding of the node_account that is created when the wallet is generated. Using the example address from the elvmasterd configuration above (0xa4f2d5Ff017336Fa416949d1C2DD7c52A772df94), use the qfab tools format-id CLI to format in the right encoding:

$ qfab tools format-id -t node 0xa4f2d5Ff017336Fa416949d1C2DD7c52A772df94
inod3JHWWWSUKxMFuAi27fUXroyBhxE7

This value then replaces the REPLACE_ME in the example config, like so

{
  "fabric": {
    "node_id": "inod3JHWWWSUKxMFuAi27fUXroyBhxE7",

.api.listeners[] array

Each array item is a simple object like so:

{
  "base_url": "/tmp/qfab.socket"
}

The .base_url can be a socket or an HTTP/HTTPS URI. If an HTTPS URI, then the object can also include CA and key data passed along.

In the example in the config, a socket and localhost listener on port 8008 is created.

{
  "api": {
    "listeners": [
      {
        "base_url": "/tmp/qfab.socket"
      },
      {
        "base_url": "http://127.0.0.1:8008"
      }
    ],

.log.level parameter

It may be useful to change this to info or debug if troubleshooting errors

{
  "log": {
    "level": "debug",

.qspaces[] array

Each array item defines a space the node participates in. In the exmaple config a single space is defined:

{
  "id": "ispc2RUoRe9eR2v33HARQUVSp1rYXzw1",
  "type": "Ethereum",
  "names": [
    "main"
  ],
  "ethereum": {
    "url": "/tmp/elvmasterd.socket",
    "wallet_file": "/var/elvmasterd/keystore/UTC...",
    "network_id": 955305,
    "dao": {
      "enabled": true,
      "interval": "1s"
    }
  }
}

The .ethereum.url can be a socket or an HTTP/HTTPS URI that the elvmasterd presents to get access to the Web3 APIs. It is advised to keep this as a socket.

The .ethereum.wallet_file is the wallet/key file generated above

qfab configuration .json

Full Sample qfab.json

The following example qfab configuration can enable validation, provided the directories and files specified are created/exist.

{
  "paths": {
    "install_path": "/var/qfab/QDATA",
    "qparts_path": "/var/qfab/QDATA/PARTS",
    "qtemp_path": "/var/qfab/QDATA/TMP",
    "qlibs_path": "/var/qfab/QDATA/LIBS",
    "node_path": "/var/qfab/QDATA/LOCAL",
    "cache_path": "/var/qfab/CACHE"
  },
  "fabric": {
    "skip_part_checks": true,
    "node_id": "REPLACE_ME",
    "network": {
      "id": "ispc2RUoRe9eR2v33HARQUVSp1rYXzw1",
      "names": [ "main" ],
      "seed_nodes": [ "38.142.50.106", "60.240.133.202" ]
    },
    "net": {
      "routing_protocol": {
        "partition_strategy": {
          "partition_level": 4,
          "partition_num": 1,
          "partition_replication": 2,
          "archive_nodes": [
            "inodBzkjwDzHMy8gYPJEr5tHDtPSubP",
            "inodX38Ag8Zv3dgZ8GBpt4uDLU17DR4",
            "inod3SNhxjib1zwsbaPd6qQrssYMzjGV",
            "inod4rCfYkpMHeqRz6F1h3gXPeXLCBq",
            "inodBkzb4tHyvFLJqDbuhzRYHtbZnD4",
            "inod3xqm6WzXPF9KrLoCeB6AJG7TPhGN",
            "inod2Guf82eKGYfPH5jEW7giVFkQKxxF",
            "inod39yyg65Jw1YsrNR9SegoJdGBc6EG",
            "inod4CyWjqrnPAxkxeWLpCzzafPqGB4U",
            "inod47KtntQ5uvpPS4oWB4GhTtZhYgC1"
          ]
        }
      },
      "http": {
        "max_conns_per_host": 2000,
        "max_idle_conns": 5000,
        "max_idle_conns_per_host": 1000,
        "idle_conn_timeout": "3m"
      },
      "transport_protocol": {
        "type": "http",
        "http": {
          "timeout": "120s"
        }
      }
    }
  },
  "gc": {
    "enabled": true,
    "interval": "1h"
  },
  "usage": {
    "enabled": true,
    "part_duration": "12h",
    "object_duration": "24h",
    "worker_num": 32,
    "process_interval": "30m",
    "process_wait_interval": "15m"
  },
  "api": {
    "listeners": [
      {
        "base_url": "/tmp/qfab.socket"
      },
      {
        "base_url": "http://127.0.0.1:8008"
      }
    ],
    "cors": {
      "allowed_origins": [
        "*"
      ],
      "allowed_methods": [
        "GET",
        "POST",
        "PUT",
        "DELETE",
        "OPTIONS"
      ],
      "allowed_headers": [
        "*"
      ],
      "max_age": 600,
      "debug": false
    },
    "log_body_max": "64KB"
  },
  "log": {
    "level": "warn",
    "formatter": "text",
    "file": {
      "filename": "/var/qfab/logs/qfab.log",
      "maxsize": 1000,
      "maxage": 0,
      "maxbackups": 10
    },
    "named": {
      "/eluvio/qfab/daemon": {
        "level": "info"
      }
    }
  },
  "llvm": {
    "execution_engine_cache": {
      "enabled": true,
      "size": 20
    },
    "port_range": "7000:7100"
  },
  "avpipe": {
    "persistent": "leveldb",
    "drm_required": false,
    "cache": {
      "path": "leveldb",
      "audio_page_segments": 20000,
      "video_page_segments": 20000,
      "manifests": 2000,
      "metas": 2000,
      "abr_infos": 2000,
      "captions": 2000
    }
  },
  "decryption": {
    "pool": {
      "max_workers": 8,
      "input_queue_size": 99
    },
    "buffer_size": "128MB"
  },
  "metrics": {
    "type": "expvar",
    "collectors": {
      "avpipe": {
        "period": "120s",
        "enabled": true
      }
    }
  },
  "qspaces": [
    {
      "id": "ispc2RUoRe9eR2v33HARQUVSp1rYXzw1",
      "type": "Ethereum",
      "names": [
        "main"
      ],
      "ethereum": {
        "url": "/tmp/elvmasterd.socket",
        "wallet_file": "/var/elvmasterd/keystore/UTC...",
        "network_id": 955305,
        "dao": {
          "enabled": true,
          "interval": "1s"
        }
      }
    }
  ]
}

qfab systemd Unit

qfab should be run with some form of process management, like systemd to ensure the daemon loads on system boot, and reloads when failures occur.

[Unit]
Description=Eluvio elvmasterd
After=network.target

[Service]
User=eluvio
Group=eluvio
Type=simple
LimitCORE=500000
LimitNOFILE=500000
Restart=always
RestartSec=2s
Environment=CUDA_DEVICE_ORDER=PCI_BUS_ID
ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/usr/local/bin/qfab daemon --config /etc/qfab/qfab.json

[Install]
WantedBy=default.target

The attached versions highlight other scenarios that will work, but may not be documented in detail otherwise.