Start with securing your vps with a public key and disabling password access. Of course first create a key on another system and copy this to your new server to be able to access it after disabling the password authentication.
vi /etc/ssh/sshd_config PasswordAuthentication no systemctl restart sshd.service
Enable firewall security to protect it from attacks from the outside. Depending on your p2p ports and prometheus monitoring you need to open soms ports.
ufw allow openssh ufw enable
The polkadot binary needs some ports to be reachable, especially the p2p port
- 30333: p2p port
- 9933: HTTP RPC
- 9944: WS RPC
- 9615: prometheus port
I open a range of p2p ports so I can choose to setup multiple validators
ufw allow from any port 30300:30399 proto tcp
apt update; apt upgrade
I prefer to lock the kernel updates so I have to manually upgrade them (which requires a restart)
apt-mark hold linux-generic linux-headers-generic linux-image-generic
Install polkadot apt repository
# Import the firstname.lastname@example.org GPG key gpg --recv-keys --keyserver hkps://keys.mailvelope.com 9D4B2B6EB8F97156D19669A9FF0812D491B96798 gpg --export 9D4B2B6EB8F97156D19669A9FF0812D491B96798 > /usr/share/keyrings/parity.gpg # Add the Parity repository and update the package index echo 'deb [signed-by=/usr/share/keyrings/parity.gpg] https://releases.parity.io/deb release main' > /etc/apt/sources.list.d/parity.list apt update # Install the `parity-keyring` package - This will ensure the GPG key # used by APT remains up-to-date apt install parity-keyring # Install polkadot apt install polkadot
Create the systemctl scripts
By default the is a “/usr/lib/systemd/system/polkadot.service” systemctl script which reads its defaults from “/etc/default/polkadot”. I find it handier to copy the scripts and put the appropriate command line config inside.
root@stakeworld:~# cp /usr/lib/systemd/system/polkadot.service /etc/systemd/system/kusama-stakeworld.service
Theoretically it is possible to create multiple systemctl scripts and run multiple instances of the polkadot binary on the same system although this is not benificial for the polkadot ecosystem stability a demand higher resources on your server.
root@stakeworld:~# cp /etc/systemd/system/kusama-stakeworld.service /etc/systemd/system/kusama-stakeworld-01.service
Following my adapted systemctl script (/etc/systemd/system/kusama.service). As you can see i choose different ports to be able to use it alongside my polkadot validator. If you run more instances you need to adapt the ports and base directories alpongside the “Description” in the .service file.
- –chain: kusam or polkadot (or westend)
- –name: the name of the validator
- –unsafe-pruning –pruning 1000: a pruned database is enough for a validator and saves precious ssd space
- –validator: declare ourself a validator
- –port 30334 –rpc-port 9934 –ws-port 9945: select alternative ports when using multiple instances
- –prometheus-port 9621 needed for monitoring
- –database rocksdb or paritydb to choose the database format
- –base-path /home/polkadot/kusama-stakeworld-01: The base path allows for a different database location.
- –telemetry-url ‘wss://telemetry.polkadot.io/submit/ 1’ , this is the default.
[Unit] Description=Kusama Stakeworld After=network.target Documentation=https://github.com/paritytech/polkadot [Service] ExecStart=/usr/bin/polkadot --chain polkadot --name STAKEWORLD/01 --unsafe-pruning --pruning 1000 --validator --port 30321 --rpc-port 9921 --ws-port 9821 --prometheus-port 9621 --base-path /home/polkadot/polkadot-stakeworld-01 --database paritydb --telemetry-url 'wss://telemetry.polkadot.io/submit/ 1' User=polkadot Group=polkadot Restart=always RestartSec=120 CapabilityBoundingSet= LockPersonality=true NoNewPrivileges=true PrivateDevices=true PrivateMounts=true PrivateTmp=true PrivateUsers=true ProtectClock=true ProtectControlGroups=true ProtectHostname=true ProtectKernelModules=true ProtectKernelTunables=true ProtectSystem=strict RemoveIPC=true RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK AF_UNIX RestrictNamespaces=true RestrictSUIDSGID=true SystemCallArchitectures=native SystemCallFilter=@system-service SystemCallFilter=~@clock @module @mount @reboot @swap @privileged UMask=0027 [Install] WantedBy=multi-user.target
sudo -u polkadot mkdir /home/polkadot/polkadot-stakeworld-01 systemctl daemon-reload systemctl start polkadot-stakeworld-01.service journalctl -u polkadot-stakeworld-01.service -f
If all went wel you can now see synchronisation starting in the logs and your node shows up in https://telemetry.polkadot.io/
If you fire up a fresh polkadot it starts to sync from scratch, which will take a while.
Using an up to date database you can speed up the process. Best is to shortly start the relevant polkadot binary, so the file structure gets created, then stop it and execute the code below. After this you can start the binary and it will only need a short period to sync and start validating.
Tip: there are different size databases, a “pruned” database is sufficient for a validator node.
curl -o - -L https://dot-rocksdb.polkashots.io/snapshot | lz4 -c -d - | tar -x -C /home/polkadot/.local/share/polkadot/chains/polkadot
The perfect but complicated setup
I have a ledger hardware wallet with polkadot and kusama accounts and I also have made a native account via https://polkadot.js.org/. Both are connected via the browser extension https://polkadot.js.org/extension/
If you are serious about validating and maybe want to fire up more instances in the future the perfect setup seems to be a stash account on a cold (hardware/ledger) wallet which you don’t have to use often, combined with a controller account on a hot wallet with easy (password) access. The idea is you use the hot wallet more often with more risk for exposure of the keys, while your stash account with the most value on it is relatively safe.
Problem with the setup using a ledger is that a lot of functions are more complicated, because the ledger app cannot execute all functions, most importantly:
- A ledger account cannot have an “on chain identity” by itself. The workaround is giving a native account an identity (STAKEWORLD) and specifying the ledger accounts as sub-identities. In the validator lists they show as STAKEWORLD/01 , where the /01 is a sub-identity of stakeworld. The next one is STAKEWORLD/02 and so on. Every identity and sub identity locks up dot/ksm (polkadot: 20 dots, which you get back after clearing the identity).
- A ledger account misses the democracy and council voting possibilities. Since this is a factor in the validator selection protocol and you want your validators to get elected it is wise to participate in democracy votes. The workaround here is to use a proxy. You can via ledger proxy your stash account to a native account, and with that native account can cast votes in democracy on behalf of the ledger stash account. Every proxy also locks up a certain amount of dot/ksm.
The easy setup
The more easy approach is to use a native account for as well stash as controller account. You can easily take on a chain identity, vote in democracy, etc. The downside being the lesser security and probably a lower score in the selection mechanism.