#!/bin/bash # NUPST Installer Script (v4.0+) # Downloads and installs pre-compiled NUPST binary from Gitea releases # # Usage: # Direct piped installation (recommended): # curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash # # With version specification: # curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- --version v4.0.0 # # Non-interactive mode (auto-confirm): # curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- -y # # Downloaded script: # curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh -o nupst-install.sh # sudo bash nupst-install.sh # # Options: # -y, --yes Automatically answer yes to all prompts # -h, --help Show this help message # --version VERSION Install specific version (e.g., v4.0.0) # --install-dir DIR Installation directory (default: /opt/nupst) set -e # Default values AUTO_YES=0 SHOW_HELP=0 SPECIFIED_VERSION="" INSTALL_DIR="/opt/nupst" GITEA_BASE_URL="https://code.foss.global" GITEA_REPO="serve.zone/nupst" # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in -y|--yes) AUTO_YES=1 shift ;; -h|--help) SHOW_HELP=1 shift ;; --version) SPECIFIED_VERSION="$2" shift 2 ;; --install-dir) INSTALL_DIR="$2" shift 2 ;; *) echo "Unknown option: $1" echo "Use -h or --help for usage information" exit 1 ;; esac done if [ $SHOW_HELP -eq 1 ]; then echo "NUPST Installer Script (v4.0+)" echo "Downloads and installs pre-compiled NUPST binary" echo "" echo "Usage: $0 [options]" echo "" echo "Options:" echo " -y, --yes Automatically answer yes to all prompts" echo " -h, --help Show this help message" echo " --version VERSION Install specific version (e.g., v4.0.0)" echo " --install-dir DIR Installation directory (default: /opt/nupst)" echo "" echo "Examples:" echo " # Install latest version" echo " curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash" echo "" echo " # Install specific version" echo " curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- --version v4.0.0" echo "" echo " # Non-interactive installation" echo " curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- -y" exit 0 fi # Check if running as root if [ "$EUID" -ne 0 ]; then echo "Please run as root (sudo bash install.sh or pipe to sudo bash)" exit 1 fi # Detect if script is being piped or run directly INTERACTIVE=1 if [ ! -t 0 ] || [ ! -t 1 ]; then # Either stdin or stdout is not a terminal if [ $AUTO_YES -ne 1 ]; then echo "Script detected it's running in a non-interactive environment without -y flag." echo "Attempting to find a controlling terminal for interactive prompts..." # Try to use a controlling terminal for user input exec < /dev/tty 2>/dev/null || INTERACTIVE=0 if [ $INTERACTIVE -eq 0 ]; then echo "ERROR: No controlling terminal available for interactive prompts." echo "" echo "For interactive installation (RECOMMENDED):" echo " curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh -o nupst-install.sh" echo " sudo bash nupst-install.sh" echo "" echo "For non-interactive installation with auto-confirm:" echo " curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- -y" exit 1 else echo "Interactive terminal found, continuing with prompts..." fi fi fi # Helper function to detect OS and architecture detect_platform() { local os=$(uname -s) local arch=$(uname -m) # Map OS case "$os" in Linux) os_name="linux" ;; Darwin) os_name="macos" ;; MINGW*|MSYS*|CYGWIN*) os_name="windows" ;; *) echo "Error: Unsupported operating system: $os" echo "Supported: Linux, macOS, Windows" exit 1 ;; esac # Map architecture case "$arch" in x86_64|amd64) arch_name="x64" ;; aarch64|arm64) arch_name="arm64" ;; *) echo "Error: Unsupported architecture: $arch" echo "Supported: x86_64/amd64 (x64), aarch64/arm64 (arm64)" exit 1 ;; esac # Construct binary name if [ "$os_name" = "windows" ]; then echo "nupst-${os_name}-${arch_name}.exe" else echo "nupst-${os_name}-${arch_name}" fi } # Get latest release version from Gitea API get_latest_version() { echo "Fetching latest release version from Gitea..." >&2 local api_url="${GITEA_BASE_URL}/api/v1/repos/${GITEA_REPO}/releases/latest" local response=$(curl -sSL "$api_url" 2>/dev/null) if [ $? -ne 0 ] || [ -z "$response" ]; then echo "Error: Failed to fetch latest release information from Gitea API" >&2 echo "URL: $api_url" >&2 exit 1 fi # Extract tag_name from JSON response local version=$(echo "$response" | grep -o '"tag_name":"[^"]*"' | cut -d'"' -f4) if [ -z "$version" ]; then echo "Error: Could not determine latest version from API response" >&2 exit 1 fi echo "$version" } # Main installation process echo "================================================" echo " NUPST Installation Script (v4.0+)" echo "================================================" echo "" # Detect platform BINARY_NAME=$(detect_platform) echo "Detected platform: $BINARY_NAME" echo "" # Determine version to install if [ -n "$SPECIFIED_VERSION" ]; then VERSION="$SPECIFIED_VERSION" echo "Installing specified version: $VERSION" else VERSION=$(get_latest_version) echo "Installing latest version: $VERSION" fi echo "" # Construct download URL DOWNLOAD_URL="${GITEA_BASE_URL}/${GITEA_REPO}/releases/download/${VERSION}/${BINARY_NAME}" echo "Download URL: $DOWNLOAD_URL" echo "" # Check if installation directory exists SERVICE_WAS_RUNNING=0 OLD_NODE_INSTALL=0 if [ -d "$INSTALL_DIR" ]; then # Check if this is an old Node.js-based installation if [ -f "$INSTALL_DIR/package.json" ] || [ -d "$INSTALL_DIR/node_modules" ]; then OLD_NODE_INSTALL=1 echo "Detected old Node.js-based NUPST installation (v3.x or earlier)" echo "This installer will migrate to the new Deno-based binary version (v4.0+)" echo "" fi if [ $AUTO_YES -eq 0 ] && [ $INTERACTIVE -eq 1 ]; then if [ $OLD_NODE_INSTALL -eq 1 ]; then echo "This will replace your Node.js installation with a pre-compiled binary." echo "Your configuration in /etc/nupst/config.json will be preserved." echo "" fi echo "Installation directory already exists: $INSTALL_DIR" echo "Do you want to update/reinstall? (Y/n): " read -r update_confirm if [[ "$update_confirm" =~ ^[Nn]$ ]]; then echo "Installation cancelled." exit 0 fi fi echo "Updating existing installation at $INSTALL_DIR..." # Check if service is running and stop it if systemctl is-active --quiet nupst 2>/dev/null; then echo "Stopping NUPST service..." systemctl stop nupst SERVICE_WAS_RUNNING=1 fi # Clean up old Node.js installation files if [ $OLD_NODE_INSTALL -eq 1 ]; then echo "Cleaning up old Node.js installation files..." rm -rf "$INSTALL_DIR/node_modules" 2>/dev/null || true rm -rf "$INSTALL_DIR/vendor" 2>/dev/null || true rm -rf "$INSTALL_DIR/dist_ts" 2>/dev/null || true rm -f "$INSTALL_DIR/package.json" 2>/dev/null || true rm -f "$INSTALL_DIR/package-lock.json" 2>/dev/null || true rm -f "$INSTALL_DIR/pnpm-lock.yaml" 2>/dev/null || true rm -f "$INSTALL_DIR/tsconfig.json" 2>/dev/null || true rm -f "$INSTALL_DIR/setup.sh" 2>/dev/null || true rm -rf "$INSTALL_DIR/bin" 2>/dev/null || true echo "Old installation files removed." fi else if [ $AUTO_YES -eq 0 ] && [ $INTERACTIVE -eq 1 ]; then echo "NUPST will be installed to: $INSTALL_DIR" echo "Continue? (Y/n): " read -r install_confirm if [[ "$install_confirm" =~ ^[Nn]$ ]]; then echo "Installation cancelled." exit 0 fi fi echo "Creating installation directory: $INSTALL_DIR" mkdir -p "$INSTALL_DIR" fi # Download binary echo "Downloading NUPST binary..." TEMP_FILE="$INSTALL_DIR/nupst.download" curl -sSL "$DOWNLOAD_URL" -o "$TEMP_FILE" if [ $? -ne 0 ]; then echo "Error: Failed to download binary from $DOWNLOAD_URL" echo "" echo "Please check:" echo " 1. Your internet connection" echo " 2. The specified version exists: ${GITEA_BASE_URL}/${GITEA_REPO}/releases" echo " 3. The platform binary is available for this release" rm -f "$TEMP_FILE" exit 1 fi # Check if download was successful (file exists and not empty) if [ ! -s "$TEMP_FILE" ]; then echo "Error: Downloaded file is empty or does not exist" rm -f "$TEMP_FILE" exit 1 fi # Move to final location BINARY_PATH="$INSTALL_DIR/nupst" mv "$TEMP_FILE" "$BINARY_PATH" # Make executable chmod +x "$BINARY_PATH" echo "Binary installed successfully to: $BINARY_PATH" echo "" # Check if /usr/local/bin is in PATH if [[ ":$PATH:" == *":/usr/local/bin:"* ]]; then BIN_DIR="/usr/local/bin" else BIN_DIR="/usr/bin" fi # Create symlink for global access if [ $AUTO_YES -eq 0 ] && [ $INTERACTIVE -eq 1 ]; then echo "Create symlink in $BIN_DIR for global access? (Y/n): " read -r symlink_confirm if [[ ! "$symlink_confirm" =~ ^[Nn]$ ]]; then ln -sf "$BINARY_PATH" "$BIN_DIR/nupst" echo "Symlink created: $BIN_DIR/nupst -> $BINARY_PATH" else echo "Symlink creation skipped." echo "To use NUPST, run: $BINARY_PATH" echo "Or manually create symlink: sudo ln -sf $BINARY_PATH $BIN_DIR/nupst" fi else ln -sf "$BINARY_PATH" "$BIN_DIR/nupst" echo "Symlink created: $BIN_DIR/nupst -> $BINARY_PATH" fi echo "" # Restart service if it was running before update if [ $SERVICE_WAS_RUNNING -eq 1 ]; then echo "Restarting NUPST service..." systemctl start nupst echo "Service restarted successfully." echo "" fi echo "================================================" echo " NUPST Installation Complete!" echo "================================================" echo "" if [ $OLD_NODE_INSTALL -eq 1 ]; then echo "Migration from v3.x to v4.0 successful!" echo "" echo "What changed:" echo " • Node.js runtime removed (now a self-contained binary)" echo " • Faster startup and lower memory usage" echo " • CLI commands now use subcommand structure" echo " (old commands still work with deprecation warnings)" echo "" echo "Migration guide: https://code.foss.global/serve.zone/nupst/src/branch/main/MIGRATION.md" echo "" fi echo "Installation details:" echo " Binary location: $BINARY_PATH" echo " Symlink location: $BIN_DIR/nupst" echo " Version: $VERSION" echo "" # Check if configuration exists if [ -f "/etc/nupst/config.json" ]; then echo "Configuration: /etc/nupst/config.json (preserved)" echo "" echo "Your existing configuration has been preserved." if [ $SERVICE_WAS_RUNNING -eq 1 ]; then echo "The service has been restarted with your current settings." else echo "Start the service with: sudo nupst service start" fi else echo "Get started:" echo " nupst --version" echo " nupst help" echo " nupst ups add # Add a UPS device" echo " nupst service enable # Enable systemd service" fi echo ""