297 lines
9.0 KiB
Bash
Executable File
297 lines
9.0 KiB
Bash
Executable File
#!/bin/bash
|
|
# Info: Prepare script for Polkadot Validator
|
|
# Author: Provisioning System
|
|
# Release: 1.0
|
|
# Date: 2025-07-24
|
|
|
|
USAGE="prepare-polkadot-validator.sh"
|
|
[ "$1" == "-h" ] && echo "$USAGE" && exit 1
|
|
|
|
[ -r "env-polkadot-validator" ] && . ./env-polkadot-validator
|
|
|
|
echo "Preparing Polkadot Validator environment..."
|
|
|
|
# Check if running as root for system preparation
|
|
if [ "$EUID" -ne 0 ]; then
|
|
echo "This preparation script must be run as root"
|
|
exit 1
|
|
fi
|
|
|
|
# Validate system requirements
|
|
echo "Validating system requirements..."
|
|
|
|
# Check CPU cores
|
|
CPU_CORES=$(nproc)
|
|
if [ "$CPU_CORES" -lt 8 ]; then
|
|
echo "❌ CRITICAL: Polkadot validators require at least 8 CPU cores. Found: $CPU_CORES"
|
|
exit 1
|
|
else
|
|
echo "✅ CPU cores: $CPU_CORES (minimum 8 required)"
|
|
fi
|
|
|
|
# Check memory
|
|
TOTAL_MEM=$(free -g | awk '/^Mem:/{print $2}')
|
|
if [ "$TOTAL_MEM" -lt 32 ]; then
|
|
echo "❌ CRITICAL: Polkadot validators require at least 32GB RAM. Found: ${TOTAL_MEM}GB"
|
|
exit 1
|
|
else
|
|
echo "✅ Memory: ${TOTAL_MEM}GB (minimum 32GB required)"
|
|
fi
|
|
|
|
# Check storage
|
|
STORAGE_PATH=${POLKADOT_BASE_PATH:-/var/lib/polkadot/data}
|
|
PARENT_DIR=$(dirname "$STORAGE_PATH")
|
|
[ ! -d "$PARENT_DIR" ] && PARENT_DIR="/"
|
|
|
|
AVAILABLE_SPACE_KB=$(df "$PARENT_DIR" | awk 'NR==2 {print $4}')
|
|
AVAILABLE_SPACE_GB=$((AVAILABLE_SPACE_KB / 1024 / 1024))
|
|
|
|
if [ "$AVAILABLE_SPACE_GB" -lt 2000 ]; then
|
|
echo "❌ CRITICAL: Polkadot validators require at least 2TB NVMe SSD storage"
|
|
echo "Available: ${AVAILABLE_SPACE_GB}GB"
|
|
exit 1
|
|
else
|
|
echo "✅ Storage: ${AVAILABLE_SPACE_GB}GB available (minimum 2TB required)"
|
|
fi
|
|
|
|
# Check if storage is SSD (best effort)
|
|
STORAGE_DEVICE=$(df "$PARENT_DIR" | awk 'NR==2 {print $1}' | sed 's/[0-9]*$//')
|
|
if [ -f "/sys/block/$(basename "$STORAGE_DEVICE")/queue/rotational" ]; then
|
|
IS_ROTATIONAL=$(cat "/sys/block/$(basename "$STORAGE_DEVICE")/queue/rotational" 2>/dev/null || echo "1")
|
|
if [ "$IS_ROTATIONAL" = "0" ]; then
|
|
echo "✅ Storage type: SSD/NVMe detected"
|
|
else
|
|
echo "⚠️ WARNING: Rotational storage detected. NVMe SSD strongly recommended for validators"
|
|
fi
|
|
fi
|
|
|
|
# Check network connectivity
|
|
echo "Checking network connectivity..."
|
|
|
|
# Test internet connectivity
|
|
if ping -c 1 -W 5 8.8.8.8 >/dev/null 2>&1; then
|
|
echo "✅ Internet connectivity: Available"
|
|
else
|
|
echo "❌ CRITICAL: No internet connectivity detected"
|
|
exit 1
|
|
fi
|
|
|
|
# Check DNS resolution
|
|
if nslookup github.com >/dev/null 2>&1; then
|
|
echo "✅ DNS resolution: Working"
|
|
else
|
|
echo "❌ CRITICAL: DNS resolution not working"
|
|
exit 1
|
|
fi
|
|
|
|
# Test GitHub access (for binary downloads)
|
|
if curl -s --connect-timeout 10 https://api.github.com/repos/paritytech/polkadot/releases/latest >/dev/null; then
|
|
echo "✅ GitHub API access: Available"
|
|
else
|
|
echo "❌ CRITICAL: Cannot access GitHub API for Polkadot releases"
|
|
exit 1
|
|
fi
|
|
|
|
# Validate required ports
|
|
echo "Checking port availability..."
|
|
|
|
REQUIRED_PORTS="30333 9933 9944 9615"
|
|
for port in $REQUIRED_PORTS; do
|
|
if ss -tulnp | grep -q ":${port} "; then
|
|
echo "⚠️ WARNING: Port $port is already in use"
|
|
ss -tulnp | grep ":${port} "
|
|
else
|
|
echo "✅ Port $port: Available"
|
|
fi
|
|
done
|
|
|
|
# Check system limits
|
|
echo "Checking system limits..."
|
|
|
|
# File descriptor limits
|
|
CURRENT_ULIMIT=$(ulimit -n)
|
|
if [ "$CURRENT_ULIMIT" -lt 65536 ]; then
|
|
echo "⚠️ WARNING: File descriptor limit is $CURRENT_ULIMIT, should be at least 65536"
|
|
echo "Consider adding to /etc/security/limits.conf:"
|
|
echo "* soft nofile 65536"
|
|
echo "* hard nofile 65536"
|
|
else
|
|
echo "✅ File descriptor limit: $CURRENT_ULIMIT"
|
|
fi
|
|
|
|
# Check systemd
|
|
if ! systemctl --version >/dev/null 2>&1; then
|
|
echo "❌ CRITICAL: systemd not available"
|
|
exit 1
|
|
else
|
|
echo "✅ Systemd: Available"
|
|
fi
|
|
|
|
# Validate environment variables
|
|
echo "Validating environment configuration..."
|
|
|
|
REQUIRED_VARS="POLKADOT_VERSION POLKADOT_CHAIN POLKADOT_VALIDATOR_NAME"
|
|
for var in $REQUIRED_VARS; do
|
|
if [ -z "${!var}" ]; then
|
|
echo "❌ CRITICAL: Required environment variable $var is not set"
|
|
exit 1
|
|
else
|
|
echo "✅ $var: ${!var}"
|
|
fi
|
|
done
|
|
|
|
# Validate chain name
|
|
VALID_CHAINS="polkadot kusama westend"
|
|
CHAIN_VALID=false
|
|
for chain in $VALID_CHAINS; do
|
|
if [ "${POLKADOT_CHAIN}" = "$chain" ]; then
|
|
CHAIN_VALID=true
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ "$CHAIN_VALID" = "false" ]; then
|
|
echo "❌ CRITICAL: Invalid chain '${POLKADOT_CHAIN}'. Valid chains: $VALID_CHAINS"
|
|
exit 1
|
|
fi
|
|
|
|
# Check for existing installation
|
|
echo "Checking for existing Polkadot installation..."
|
|
|
|
POLKADOT_BIN=${POLKADOT_BIN_PATH:-/usr/local/bin/polkadot}
|
|
if [ -f "$POLKADOT_BIN" ]; then
|
|
VERSION_OUTPUT=$("$POLKADOT_BIN" --version 2>/dev/null || echo "unknown")
|
|
echo "⚠️ WARNING: Existing Polkadot installation found: $VERSION_OUTPUT"
|
|
echo "Installation will overwrite existing binary"
|
|
fi
|
|
|
|
# Check systemd service
|
|
if systemctl list-unit-files | grep -q "polkadot-validator.service"; then
|
|
echo "⚠️ WARNING: polkadot-validator.service already exists"
|
|
SERVICE_STATUS=$(systemctl is-active polkadot-validator.service 2>/dev/null || echo "inactive")
|
|
echo "Current status: $SERVICE_STATUS"
|
|
fi
|
|
|
|
# Validate user configuration
|
|
POLKADOT_USER=${POLKADOT_RUN_USER:-polkadot}
|
|
if id "$POLKADOT_USER" >/dev/null 2>&1; then
|
|
echo "⚠️ WARNING: User $POLKADOT_USER already exists"
|
|
USER_HOME=$(getent passwd "$POLKADOT_USER" | cut -d: -f6)
|
|
echo "User home: $USER_HOME"
|
|
else
|
|
echo "✅ User $POLKADOT_USER: Will be created"
|
|
fi
|
|
|
|
# Check directory permissions
|
|
echo "Checking directory structure..."
|
|
|
|
DIRECTORIES="/etc/polkadot /var/lib/polkadot /var/log/polkadot /var/backups/polkadot"
|
|
for dir in $DIRECTORIES; do
|
|
if [ -d "$dir" ]; then
|
|
OWNER=$(stat -c '%U:%G' "$dir" 2>/dev/null || echo "unknown")
|
|
PERMS=$(stat -c '%a' "$dir" 2>/dev/null || echo "unknown")
|
|
echo "⚠️ WARNING: Directory $dir already exists (owner: $OWNER, perms: $PERMS)"
|
|
else
|
|
echo "✅ Directory $dir: Will be created"
|
|
fi
|
|
done
|
|
|
|
# Security checks
|
|
echo "Performing security checks..."
|
|
|
|
# Check if fail2ban is available
|
|
if command -v fail2ban-client >/dev/null 2>&1; then
|
|
echo "✅ fail2ban: Available"
|
|
else
|
|
echo "⚠️ WARNING: fail2ban not installed (will be installed during setup)"
|
|
fi
|
|
|
|
# Check firewall
|
|
if command -v ufw >/dev/null 2>&1; then
|
|
UFW_STATUS=$(ufw status | head -1)
|
|
echo "✅ UFW firewall: $UFW_STATUS"
|
|
elif command -v firewall-cmd >/dev/null 2>&1; then
|
|
FIREWALLD_STATUS=$(systemctl is-active firewalld 2>/dev/null || echo "inactive")
|
|
echo "✅ firewalld: $FIREWALLD_STATUS"
|
|
else
|
|
echo "⚠️ WARNING: No firewall detected (will be configured during setup)"
|
|
fi
|
|
|
|
# Check for automatic updates
|
|
if command -v unattended-upgrades >/dev/null 2>&1; then
|
|
echo "✅ Automatic updates: unattended-upgrades available"
|
|
elif command -v dnf >/dev/null 2>&1; then
|
|
echo "✅ Automatic updates: dnf-automatic available"
|
|
else
|
|
echo "⚠️ WARNING: Automatic update system not detected"
|
|
fi
|
|
|
|
# Time synchronization check
|
|
if systemctl is-active --quiet systemd-timesyncd || systemctl is-active --quiet ntp || systemctl is-active --quiet chrony; then
|
|
echo "✅ Time synchronization: Active"
|
|
else
|
|
echo "⚠️ WARNING: Time synchronization service not active"
|
|
echo "Accurate time is critical for validators"
|
|
fi
|
|
|
|
# Check entropy
|
|
ENTROPY=$(cat /proc/sys/kernel/random/entropy_avail 2>/dev/null || echo "unknown")
|
|
if [ "$ENTROPY" != "unknown" ] && [ "$ENTROPY" -lt 1000 ]; then
|
|
echo "⚠️ WARNING: Low entropy ($ENTROPY). Consider installing haveged or rng-tools"
|
|
else
|
|
echo "✅ System entropy: $ENTROPY"
|
|
fi
|
|
|
|
# Final validation summary
|
|
echo ""
|
|
echo "========================================="
|
|
echo "Polkadot Validator Preparation Summary"
|
|
echo "========================================="
|
|
echo "Chain: ${POLKADOT_CHAIN}"
|
|
echo "Validator name: ${POLKADOT_VALIDATOR_NAME}"
|
|
echo "Version: ${POLKADOT_VERSION}"
|
|
echo "User: ${POLKADOT_USER}"
|
|
echo ""
|
|
|
|
# Check for critical issues
|
|
CRITICAL_ISSUES=0
|
|
|
|
# Re-check critical requirements
|
|
if [ "$CPU_CORES" -lt 8 ]; then
|
|
echo "❌ CRITICAL: Insufficient CPU cores"
|
|
CRITICAL_ISSUES=$((CRITICAL_ISSUES + 1))
|
|
fi
|
|
|
|
if [ "$TOTAL_MEM" -lt 32 ]; then
|
|
echo "❌ CRITICAL: Insufficient memory"
|
|
CRITICAL_ISSUES=$((CRITICAL_ISSUES + 1))
|
|
fi
|
|
|
|
if [ "$AVAILABLE_SPACE_GB" -lt 2000 ]; then
|
|
echo "❌ CRITICAL: Insufficient storage"
|
|
CRITICAL_ISSUES=$((CRITICAL_ISSUES + 1))
|
|
fi
|
|
|
|
if [ "$CRITICAL_ISSUES" -gt 0 ]; then
|
|
echo ""
|
|
echo "❌ PREPARATION FAILED: $CRITICAL_ISSUES critical issue(s) found"
|
|
echo "Please resolve the above issues before proceeding with installation"
|
|
exit 1
|
|
fi
|
|
|
|
echo "✅ All critical requirements met"
|
|
echo ""
|
|
echo "NEXT STEPS:"
|
|
echo "1. Review any warnings above"
|
|
echo "2. Run the installation script: ./install-polkadot-validator.sh"
|
|
echo "3. Configure session keys after node sync"
|
|
echo "4. Set up staking and validation"
|
|
echo ""
|
|
echo "SECURITY REMINDERS:"
|
|
echo "- Ensure this server has proper backup procedures"
|
|
echo "- Monitor the validator continuously"
|
|
echo "- Keep the system updated"
|
|
echo "- Never run duplicate validators with the same keys"
|
|
echo ""
|
|
|
|
exit 0 |