sudo apt update && sudo apt upgrade -y && sudo apt autoremove -y \
  && sudo apt install -y docker.io pwgen jq joe screen \
  && sudo reboot
Now run screen and inside
curl https://getsubstrate.io -sSf | bash
Press ^A ^D to detach screen and run screen -r to resume to installation.
Subkey is Substrate's command line tool to handle Ed25519 keypairs. To generate a new keypair, use subkey generate:
$ subkey generate
Seed 0xd26c63905a3b2f455185cff37dfbe1b70ec3c16ea33138772d430f24d6c1d7d2 is account:
  Public key (hex): 0x8d240d69a6b5006da03bfb7ee59888bd310bf7727ff193ebed73a13a8067b0db
  Address (SS58): 5FFmKSNARNV4gkJLczvWMakv8ooNRufmQtEwuwoheesqAHEc
Address is in the Substrate-specific SS58 format (base58 of network identifier + pubkey + checksum)
- Create new chainspec.json
export PUBLIC_IP_ADDRESS=$(curl -sS 'https://api.ipify.org?format=json' | jq '.ip' --raw-output)
cat /dev/urandom | head -c 32 | xxd -p -c 256 > ~/.node_key
substrate --chain=staging --node-key "$(< ~/.node_key)" build-spec \
  | jq '.name = "TSP"' \
  | jq '.id = "tsp_testnet_123"' \
  | jq '.bootNodes[0] |= gsub("127\\.0\\.0\\.1"; env.PUBLIC_IP_ADDRESS)' \
  | jq '.genesis.runtime.timestamp.period = 20' \
  | jq '.genesis.runtime.balances.balances[0][1] = 1000000000000000' \
  > ~/chainspec.json
- Set your address in authoritiesof ~/chainspec.json, e.g.
"consensus": {
  "authorities": [
    "5FFmKSNARNV4gkJLczvWMakv8ooNRufmQtEwuwoheesqAHEc"
  ],
  [...]
}
- Set your public key in balances, validators,intentions,upgradeKey,sudoof ~/chainspec.json, e.g.
"balances": [
  [
    "0x8d240d69a6b5006da03bfb7ee59888bd310bf7727ff193ebed73a13a8067b0db",
    1000000000000000
  ]
]
"session": {
  "validators": [
    "0x8d240d69a6b5006da03bfb7ee59888bd310bf7727ff193ebed73a13a8067b0db"
  ],
  [...]
}
"staking": {
  "intentions": [
    "0x8d240d69a6b5006da03bfb7ee59888bd310bf7727ff193ebed73a13a8067b0db"
  ],
  [...]
}
"upgradeKey": {
  "key": "0x8d240d69a6b5006da03bfb7ee59888bd310bf7727ff193ebed73a13a8067b0db"
},
"sudo": {
  "key": "0x8d240d69a6b5006da03bfb7ee59888bd310bf7727ff193ebed73a13a8067b0db"
}
- Build raw chain definition
substrate --chain ~/chainspec.json build-spec --raw > ~/mychain.json
- Start chain as a validator
The --key is the password from above
substrate --chain ~/mychain.json --node-key "$(< ~/.node_key)" --validator --key 0xd26c63905a3b2f455185cff37dfbe1b70ec3c16ea33138772d430f24d6c1d7d2
adduser --disabled-login --gecos "" bob && usermod -a -G docker bob
cp mychain.json ~bob
Now start Substrate node as bob via docker
su bob
cd ~
mkdir --mode=777 substrate_data
export NODE_PORT=8002
docker run \
  --user "$UID" \
  -v "$HOME":/data \
  -p "$NODE_PORT:$NODE_PORT/tcp" \
  parity/substrate:latest \
  --chain /data/mychain.json --base-path /data/substrate_data --port "$NODE_PORT"
cargo install --git https://github.com/paritytech/substrate subkey --force
cargo install --git https://github.com/paritytech/substrate substrate --force