#!/bin/bash # Info: Script to install Polkadot Solochain # Author: Provisioning System # Release: 1.0 # Date: 2025-07-24 USAGE="install-polkadot-solochain.sh" [ "$1" == "-h" ] && echo "$USAGE" && exit 1 [ -r "env-polkadot-solochain" ] && . ./env-polkadot-solochain POLKADOT_VERSION=${POLKADOT_VERSION:-stable2024} POLKADOT_TEMPLATE_REPO="https://github.com/paritytech/polkadot-sdk-solochain-template.git" POLKADOT_RUN_USER=${POLKADOT_RUN_USER:-polkadot} POLKADOT_RUN_GROUP=${POLKADOT_RUN_GROUP:-polkadot} POLKADOT_RUN_USER_HOME=${POLKADOT_RUN_USER_HOME:-/home/polkadot} POLKADOT_WORK_PATH=${POLKADOT_WORK_PATH:-/var/lib/polkadot} POLKADOT_CONFIG_PATH=${POLKADOT_CONFIG_PATH:-/etc/polkadot} POLKADOT_BIN_PATH=${POLKADOT_BIN_PATH:-/usr/local/bin} POLKADOT_NODE_BINARY=${POLKADOT_NODE_BINARY:-solochain-template-node} POLKADOT_BUILD_PATH="/opt/polkadot-solochain-build" POLKADOT_BASE_PATH=${POLKADOT_BASE_PATH:-/var/lib/polkadot/data} POLKADOT_KEYSTORE_PATH=${POLKADOT_KEYSTORE_PATH:-/var/lib/polkadot/keystore} POLKADOT_SYSTEMCTL_MODE=${POLKADOT_SYSTEMCTL_MODE:-enabled} echo "Installing Polkadot Solochain ${POLKADOT_VERSION}..." # Install system dependencies echo "Installing system dependencies..." if command -v apt-get >/dev/null 2>&1; then apt-get update apt-get install -y curl git build-essential pkg-config libssl-dev protobuf-compiler clang cmake elif command -v yum >/dev/null 2>&1; then yum groupinstall -y "Development Tools" yum install -y curl git openssl-devel protobuf-compiler clang cmake pkg-config elif command -v dnf >/dev/null 2>&1; then dnf groupinstall -y "Development Tools" dnf install -y curl git openssl-devel protobuf-compiler clang cmake pkg-config else echo "Package manager not found. Please install dependencies manually." exit 1 fi # Install Rust if not present if ! command -v rustc >/dev/null 2>&1; then echo "Installing Rust..." curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y source "$HOME/.cargo/env" rustup default stable rustup target add wasm32-unknown-unknown fi # Create user and group if ! id "$POLKADOT_RUN_USER" &>/dev/null; then groupadd -r "$POLKADOT_RUN_GROUP" useradd -r -g "$POLKADOT_RUN_GROUP" -d "$POLKADOT_RUN_USER_HOME" -s /bin/bash -c "Polkadot service user" "$POLKADOT_RUN_USER" fi # Create directories mkdir -p "$POLKADOT_CONFIG_PATH" mkdir -p "$POLKADOT_WORK_PATH" mkdir -p "$POLKADOT_BASE_PATH" mkdir -p "$POLKADOT_KEYSTORE_PATH" mkdir -p "$POLKADOT_RUN_USER_HOME" mkdir -p "$POLKADOT_BUILD_PATH" # Clone and build Polkadot solochain template echo "Cloning Polkadot solochain template..." cd "$POLKADOT_BUILD_PATH" if [ ! -d "polkadot-sdk-solochain-template" ]; then git clone "$POLKADOT_TEMPLATE_REPO" polkadot-sdk-solochain-template fi cd polkadot-sdk-solochain-template # Checkout specific version if needed if [ "$POLKADOT_VERSION" != "stable2024" ] && [ "$POLKADOT_VERSION" != "latest" ]; then git checkout "$POLKADOT_VERSION" || echo "Version $POLKADOT_VERSION not found, using default branch" fi echo "Building Polkadot solochain node (this may take 20-30 minutes)..." export RUST_LOG=info # Build the node cargo build --release if [ ! -f "target/release/$POLKADOT_NODE_BINARY" ]; then echo "Failed to build Polkadot solochain node" exit 1 fi # Install binary echo "Installing binary..." cp "target/release/$POLKADOT_NODE_BINARY" "$POLKADOT_BIN_PATH/" chmod +x "$POLKADOT_BIN_PATH/$POLKADOT_NODE_BINARY" # Create chain specification if not exists echo "Generating chain specification..." if [ ! -f "$POLKADOT_CONFIG_PATH/local-testnet.json" ]; then cd "$POLKADOT_BUILD_PATH/polkadot-sdk-solochain-template" # Generate raw chain spec "$POLKADOT_BIN_PATH/$POLKADOT_NODE_BINARY" build-spec --disable-default-bootnode --chain local > "$POLKADOT_CONFIG_PATH/local-testnet-plain.json" "$POLKADOT_BIN_PATH/$POLKADOT_NODE_BINARY" build-spec --chain "$POLKADOT_CONFIG_PATH/local-testnet-plain.json" --raw --disable-default-bootnode > "$POLKADOT_CONFIG_PATH/local-testnet.json" fi # Create node key if not exists if [ ! -f "$POLKADOT_CONFIG_PATH/node-key" ] && [ -z "$POLKADOT_NODE_KEY" ]; then echo "Generating node key..." openssl rand -hex 32 > "$POLKADOT_CONFIG_PATH/node-key" fi # Create runtime configuration cat > "$POLKADOT_CONFIG_PATH/runtime-config.json" << EOF { "name": "${POLKADOT_RUNTIME_NAME:-solochain-template}", "version": "${POLKADOT_RUNTIME_VERSION:-1.0.0}", "pvm_enabled": ${POLKADOT_PVM_ENABLED:-true}, "wasm_execution": "${POLKADOT_WASM_EXECUTION:-compiled}", "heap_pages": ${POLKADOT_HEAP_PAGES:-64} } EOF # Set ownership chown -R "$POLKADOT_RUN_USER:$POLKADOT_RUN_GROUP" "$POLKADOT_WORK_PATH" chown -R "$POLKADOT_RUN_USER:$POLKADOT_RUN_GROUP" "$POLKADOT_BASE_PATH" chown -R "$POLKADOT_RUN_USER:$POLKADOT_RUN_GROUP" "$POLKADOT_KEYSTORE_PATH" chown -R "$POLKADOT_RUN_USER:$POLKADOT_RUN_GROUP" "$POLKADOT_RUN_USER_HOME" chown -R "$POLKADOT_RUN_USER:$POLKADOT_RUN_GROUP" "$POLKADOT_CONFIG_PATH" # Create systemd service file cat > /etc/systemd/system/polkadot-solochain.service << EOF [Unit] Description=Polkadot Solochain Node Documentation=https://docs.polkadot.com/ After=network-online.target Wants=network-online.target [Service] Type=simple User=$POLKADOT_RUN_USER Group=$POLKADOT_RUN_GROUP EnvironmentFile=$POLKADOT_CONFIG_PATH/node.env WorkingDirectory=$POLKADOT_WORK_PATH ExecStart=$POLKADOT_BIN_PATH/$POLKADOT_NODE_BINARY \\ --base-path $POLKADOT_BASE_PATH \\ --chain $POLKADOT_CONFIG_PATH/local-testnet.json \\ --port 30333 \\ --rpc-port ${POLKADOT_RPC_PORT:-9944} \\ --rpc-bind-addr ${POLKADOT_RPC_BIND_ADDR:-127.0.0.1} \\ --validator \\ --name \${POLKADOT_NODE_NAME:-SolochainNode} \\ --execution ${POLKADOT_EXECUTION_STRATEGY:-wasm} \\ --state-cache-size ${POLKADOT_STATE_CACHE_SIZE:-67108864} \\ --log ${POLKADOT_LOG_LEVEL:-info} Restart=always RestartSec=10 # Security settings NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=true ReadWritePaths=$POLKADOT_WORK_PATH $POLKADOT_BASE_PATH $POLKADOT_KEYSTORE_PATH $POLKADOT_CONFIG_PATH CapabilityBoundingSet=CAP_NET_BIND_SERVICE # Resource limits LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF # Create environment file for systemd service cat > "$POLKADOT_CONFIG_PATH/node.env" << EOF POLKADOT_NODE_NAME=${POLKADOT_NETWORK_NAME:-SolochainNode} RUST_LOG=${POLKADOT_LOG_LEVEL:-info} EOF # Load additional environment variables from template if available if [ -f "env-polkadot-solochain" ]; then cat env-polkadot-solochain >> "$POLKADOT_CONFIG_PATH/node.env" fi # Initialize keys for development if in dev mode if [ "${POLKADOT_DEV_MODE:-false}" = "true" ] || [ "${POLKADOT_ALICE_VALIDATOR:-false}" = "true" ]; then echo "Setting up development keys..." sudo -u "$POLKADOT_RUN_USER" "$POLKADOT_BIN_PATH/$POLKADOT_NODE_BINARY" key insert \ --base-path "$POLKADOT_BASE_PATH" \ --chain "$POLKADOT_CONFIG_PATH/local-testnet.json" \ --scheme Sr25519 \ --suri "//Alice" \ --key-type aura \ --password-interactive < /dev/null || true sudo -u "$POLKADOT_RUN_USER" "$POLKADOT_BIN_PATH/$POLKADOT_NODE_BINARY" key insert \ --base-path "$POLKADOT_BASE_PATH" \ --chain "$POLKADOT_CONFIG_PATH/local-testnet.json" \ --scheme Ed25519 \ --suri "//Alice" \ --key-type gran \ --password-interactive < /dev/null || true fi # Enable and start service systemctl daemon-reload systemctl "$POLKADOT_SYSTEMCTL_MODE" polkadot-solochain.service if [ "$POLKADOT_SYSTEMCTL_MODE" = "enabled" ]; then systemctl start polkadot-solochain.service # Wait a moment for service to start sleep 5 fi echo "Polkadot Solochain installation completed!" echo "Service: polkadot-solochain.service" echo "RPC endpoint: ws://${POLKADOT_RPC_BIND_ADDR:-127.0.0.1}:${POLKADOT_RPC_PORT:-9944}" echo "HTTP RPC endpoint: http://${POLKADOT_RPC_BIND_ADDR:-127.0.0.1}:${POLKADOT_HTTP_PORT:-9933}" echo "Configuration: $POLKADOT_CONFIG_PATH/" echo "Data directory: $POLKADOT_BASE_PATH" echo "Keystore: $POLKADOT_KEYSTORE_PATH" echo "" echo "Connect with Polkadot-JS Apps:" echo "https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F${POLKADOT_RPC_BIND_ADDR:-127.0.0.1}%3A${POLKADOT_RPC_PORT:-9944}" # Display service status if systemctl is-active --quiet polkadot-solochain.service; then echo "✅ Polkadot solochain service is running" else echo "⚠️ Polkadot solochain service status:" systemctl status polkadot-solochain.service --no-pager -l fi # Cleanup build directory if requested if [ "${POLKADOT_CLEANUP_BUILD:-false}" = "true" ]; then echo "Cleaning up build directory..." rm -rf "$POLKADOT_BUILD_PATH" fi