#!/bin/bash # Decred Node Installation Script # Installs and configures a Decred node as a systemd service. # # Usage: # curl -fsSL https://node.dcr.pw | sudo bash # Exit immediately if a command exits with a non-zero status. set -euo pipefail # --- Configuration --- # Dedicated system user for running the Decred daemon. DCR_USER="decred" # Data directory for blockchain and configuration files. DCR_HOME="/var/lib/decred" # Installation log file location. LOG_FILE="/var/log/decred_setup.log" # Temporary directory for downloads (set during execution). TMP_DIR="" # --- Functions --- # Log messages to both stdout and log file with timestamp. log_message() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" } # Clean up temporary directory on script exit. cleanup() { if [ -n "$TMP_DIR" ] && [ -d "$TMP_DIR" ]; then log_message "Cleaning up temporary directory..." rm -rf "$TMP_DIR" fi } # Register cleanup function to run on exit. trap cleanup EXIT # --- Script Start --- # 1. Check for Root Permissions if [ "$(id -u)" -ne "0" ]; then echo "This script must be run as root. Please use sudo." exit 1 fi # Initialize log file with proper permissions. touch "$LOG_FILE" chmod 644 "$LOG_FILE" log_message "Starting Decred node setup..." # 2. Verify and Install Required Dependencies log_message "Checking required dependencies..." missing_deps=() for cmd in curl jq; do if ! command -v "$cmd" &> /dev/null; then log_message "'$cmd' is not installed." missing_deps+=("$cmd") else log_message "'$cmd' is already installed." fi done if [ ${#missing_deps[@]} -gt 0 ]; then log_message "Installing missing dependencies: ${missing_deps[*]}" # Detect package manager and install if command -v apt-get &> /dev/null; then log_message "Using apt-get package manager..." apt-get update -qq apt-get install -y "${missing_deps[@]}" elif command -v yum &> /dev/null; then log_message "Using yum package manager..." yum install -y "${missing_deps[@]}" elif command -v dnf &> /dev/null; then log_message "Using dnf package manager..." dnf install -y "${missing_deps[@]}" elif command -v pacman &> /dev/null; then log_message "Using pacman package manager..." pacman -Sy --noconfirm "${missing_deps[@]}" elif command -v apk &> /dev/null; then log_message "Using apk package manager..." apk add --no-cache "${missing_deps[@]}" else log_message "Error: Could not detect package manager. Please install manually: ${missing_deps[*]}" exit 1 fi # Verify installation succeeded for cmd in "${missing_deps[@]}"; do if ! command -v "$cmd" &> /dev/null; then log_message "Error: Failed to install '$cmd'." exit 1 fi done log_message "All dependencies installed successfully." else log_message "All required dependencies are already installed." fi # 3. Detect System Architecture arch=$(uname -m) case "$arch" in 'x86_64') a='amd64' ;; 'aarch64') a='arm64' ;; *) log_message "Error: Unsupported architecture: $arch"; exit 1 ;; esac log_message "Detected architecture: $arch ($a)" # 4. Fetch Latest Decred Version log_message "Fetching the latest Decred version..." v=$(curl -sSf "https://api.github.com/repos/decred/decred-binaries/releases/latest" | jq -r .tag_name) if [ -z "$v" ] || [ "$v" = "null" ]; then log_message "Error: Could not fetch the latest version tag from GitHub." exit 1 fi log_message "Latest version is $v" # 5. Download and Verify Decred Binaries b="decred-linux-${a}-${v}.tar.gz" download_url="https://github.com/decred/decred-binaries/releases/download/${v}/${b}" manifest_url="https://github.com/decred/decred-binaries/releases/download/${v}/manifest-${v}.txt" # Create temporary directory for downloads. TMP_DIR=$(mktemp -d) log_message "Using temporary directory: $TMP_DIR" log_message "Downloading $b..." if ! curl -sSfL -o "${TMP_DIR}/${b}" "$download_url"; then log_message "Error: Failed to download binaries from $download_url" exit 1 fi log_message "Downloading manifest for checksum verification..." if curl -sSfL -o "${TMP_DIR}/manifest.txt" "$manifest_url"; then log_message "Verifying checksum..." cd "$TMP_DIR" if grep "$b" manifest.txt | sha256sum -c --status; then log_message "Checksum verification passed." else log_message "Warning: Checksum verification failed or not found in manifest." fi cd - > /dev/null else log_message "Warning: Could not download manifest file. Skipping checksum verification." fi log_message "Extracting binaries to /usr/local/bin/..." # Extract archive to temporary directory. tar -xzf "${TMP_DIR}/${b}" -C "$TMP_DIR" # Copy Decred binaries to system path. find "$TMP_DIR" -name "dcrd" -type f -executable -exec cp {} /usr/local/bin/ \; find "$TMP_DIR" -name "dcrctl" -type f -executable -exec cp {} /usr/local/bin/ \; find "$TMP_DIR" -name "dcrwallet" -type f -executable -exec cp {} /usr/local/bin/ \; # Verify dcrd binary was successfully installed. if [ ! -x "/usr/local/bin/dcrd" ]; then log_message "Error: dcrd binary not found after extraction." exit 1 fi chmod +x /usr/local/bin/dcrd /usr/local/bin/dcrctl /usr/local/bin/dcrwallet 2>/dev/null || true log_message "Binaries installed successfully." # 6. Configure System User and Data Directory if ! id -u "$DCR_USER" >/dev/null 2>&1; then log_message "Creating system user '$DCR_USER'..." useradd -r -m -d "$DCR_HOME" -s /usr/sbin/nologin "$DCR_USER" else log_message "User '$DCR_USER' already exists." fi # Create data directory structure with secure permissions. mkdir -p "$DCR_HOME" mkdir -p "$DCR_HOME/logs/mainnet" chown -R "${DCR_USER}:${DCR_USER}" "$DCR_HOME" chmod 755 "$DCR_HOME" chmod 755 "$DCR_HOME/logs" chmod 755 "$DCR_HOME/logs/mainnet" log_message "Data directory configured at $DCR_HOME" # 7. Stop Existing Service if systemctl is-active --quiet dcrd.service; then log_message "Stopping existing dcrd service..." systemctl stop dcrd.service fi # 8. Create Systemd Service File log_message "Creating dcrd systemd service..." cat > /etc/systemd/system/dcrd.service < /usr/local/bin/decred.sh < /dev/null; then echo "Monitoring dcrd service logs..." echo "" journalctl -u dcrd -f --no-pager else # Fallback to direct log file access LOG_FILE="/var/lib/decred/logs/mainnet/dcrd.log" if [ -r "$LOG_FILE" ]; then tail -f "$LOG_FILE" else echo "Error: Cannot read log file. Try running with sudo:" echo " sudo journalctl -u dcrd -f" echo " or" echo " sudo tail -f $LOG_FILE" exit 1 fi fi EOF # Make status script executable. chmod +x /usr/local/bin/decred.sh # 11. Display Installation Summary log_message "Installation complete." printf "\n✅ Installation complete! Your Decred node is running.\n" printf " - To check the status: systemctl status dcrd\n" printf " - To monitor the log in real-time: decred.sh\n" printf " - To view logs: journalctl -u dcrd -f\n" printf " - Binaries installed: dcrd, dcrctl, dcrwallet\n\n"