2025-03-25 09:06:23 +00:00
|
|
|
#!/bin/bash
|
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
# 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
|
|
|
|
#
|
2025-03-25 11:31:24 +00:00
|
|
|
# Options:
|
2025-10-18 13:20:23 +00:00
|
|
|
# -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)
|
2025-03-25 11:31:24 +00:00
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
set -e
|
|
|
|
|
|
|
|
# Default values
|
2025-03-25 11:31:24 +00:00
|
|
|
AUTO_YES=0
|
|
|
|
SHOW_HELP=0
|
2025-10-18 13:20:23 +00:00
|
|
|
SPECIFIED_VERSION=""
|
|
|
|
INSTALL_DIR="/opt/nupst"
|
|
|
|
GITEA_BASE_URL="https://code.foss.global"
|
|
|
|
GITEA_REPO="serve.zone/nupst"
|
2025-03-25 11:31:24 +00:00
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
# Parse command line arguments
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
|
|
case $1 in
|
2025-03-25 11:31:24 +00:00
|
|
|
-y|--yes)
|
|
|
|
AUTO_YES=1
|
|
|
|
shift
|
|
|
|
;;
|
|
|
|
-h|--help)
|
|
|
|
SHOW_HELP=1
|
|
|
|
shift
|
|
|
|
;;
|
2025-10-18 13:20:23 +00:00
|
|
|
--version)
|
|
|
|
SPECIFIED_VERSION="$2"
|
|
|
|
shift 2
|
|
|
|
;;
|
|
|
|
--install-dir)
|
|
|
|
INSTALL_DIR="$2"
|
|
|
|
shift 2
|
|
|
|
;;
|
2025-03-25 11:31:24 +00:00
|
|
|
*)
|
2025-10-18 13:20:23 +00:00
|
|
|
echo "Unknown option: $1"
|
|
|
|
echo "Use -h or --help for usage information"
|
|
|
|
exit 1
|
2025-03-25 11:31:24 +00:00
|
|
|
;;
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
|
|
|
|
if [ $SHOW_HELP -eq 1 ]; then
|
2025-10-18 13:20:23 +00:00
|
|
|
echo "NUPST Installer Script (v4.0+)"
|
|
|
|
echo "Downloads and installs pre-compiled NUPST binary"
|
|
|
|
echo ""
|
2025-03-25 11:31:24 +00:00
|
|
|
echo "Usage: $0 [options]"
|
|
|
|
echo ""
|
|
|
|
echo "Options:"
|
2025-10-18 13:20:23 +00:00
|
|
|
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"
|
2025-03-25 11:31:24 +00:00
|
|
|
exit 0
|
|
|
|
fi
|
2025-03-25 09:06:23 +00:00
|
|
|
|
|
|
|
# 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
|
2025-03-25 13:08:28 +00:00
|
|
|
INTERACTIVE=1
|
|
|
|
if [ ! -t 0 ] || [ ! -t 1 ]; then
|
2025-10-18 13:20:23 +00:00
|
|
|
# Either stdin or stdout is not a terminal
|
2025-03-25 13:08:28 +00:00
|
|
|
if [ $AUTO_YES -ne 1 ]; then
|
2025-03-25 13:12:38 +00:00
|
|
|
echo "Script detected it's running in a non-interactive environment without -y flag."
|
|
|
|
echo "Attempting to find a controlling terminal for interactive prompts..."
|
2025-03-25 13:08:28 +00:00
|
|
|
# Try to use a controlling terminal for user input
|
2025-10-18 13:20:23 +00:00
|
|
|
exec < /dev/tty 2>/dev/null || INTERACTIVE=0
|
|
|
|
|
2025-03-25 13:08:28 +00:00
|
|
|
if [ $INTERACTIVE -eq 0 ]; then
|
2025-03-25 13:12:38 +00:00
|
|
|
echo "ERROR: No controlling terminal available for interactive prompts."
|
2025-10-18 13:20:23 +00:00
|
|
|
echo ""
|
2025-03-25 13:12:38 +00:00
|
|
|
echo "For interactive installation (RECOMMENDED):"
|
2025-03-25 13:15:48 +00:00
|
|
|
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 ""
|
2025-10-18 13:20:23 +00:00
|
|
|
echo "For non-interactive installation with auto-confirm:"
|
2025-03-25 13:15:48 +00:00
|
|
|
echo " curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- -y"
|
2025-03-25 13:08:28 +00:00
|
|
|
exit 1
|
2025-03-25 13:12:38 +00:00
|
|
|
else
|
|
|
|
echo "Interactive terminal found, continuing with prompts..."
|
2025-03-25 13:08:28 +00:00
|
|
|
fi
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
# Helper function to detect OS and architecture
|
|
|
|
detect_platform() {
|
|
|
|
local os=$(uname -s)
|
|
|
|
local arch=$(uname -m)
|
2025-03-25 11:25:03 +00:00
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
# Map OS
|
|
|
|
case "$os" in
|
|
|
|
Linux)
|
|
|
|
os_name="linux"
|
|
|
|
;;
|
|
|
|
Darwin)
|
|
|
|
os_name="macos"
|
2025-03-25 11:25:03 +00:00
|
|
|
;;
|
2025-10-18 13:20:23 +00:00
|
|
|
MINGW*|MSYS*|CYGWIN*)
|
|
|
|
os_name="windows"
|
2025-03-25 11:25:03 +00:00
|
|
|
;;
|
2025-10-18 13:20:23 +00:00
|
|
|
*)
|
|
|
|
echo "Error: Unsupported operating system: $os"
|
|
|
|
echo "Supported: Linux, macOS, Windows"
|
|
|
|
exit 1
|
2025-03-25 11:25:03 +00:00
|
|
|
;;
|
2025-10-18 13:20:23 +00:00
|
|
|
esac
|
|
|
|
|
|
|
|
# Map architecture
|
|
|
|
case "$arch" in
|
|
|
|
x86_64|amd64)
|
|
|
|
arch_name="x64"
|
2025-03-25 11:25:03 +00:00
|
|
|
;;
|
2025-10-18 13:20:23 +00:00
|
|
|
aarch64|arm64)
|
|
|
|
arch_name="arm64"
|
2025-03-25 11:25:03 +00:00
|
|
|
;;
|
|
|
|
*)
|
2025-10-18 13:20:23 +00:00
|
|
|
echo "Error: Unsupported architecture: $arch"
|
|
|
|
echo "Supported: x86_64/amd64 (x64), aarch64/arm64 (arm64)"
|
2025-03-25 11:25:03 +00:00
|
|
|
exit 1
|
|
|
|
;;
|
|
|
|
esac
|
2025-10-18 13:20:23 +00:00
|
|
|
|
|
|
|
# Construct binary name
|
|
|
|
if [ "$os_name" = "windows" ]; then
|
|
|
|
echo "nupst-${os_name}-${arch_name}.exe"
|
|
|
|
else
|
|
|
|
echo "nupst-${os_name}-${arch_name}"
|
2025-03-25 11:25:03 +00:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
# 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
|
2025-03-25 13:20:36 +00:00
|
|
|
exit 1
|
2025-03-25 09:06:23 +00:00
|
|
|
fi
|
2025-03-25 13:20:36 +00:00
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
# 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
|
2025-03-25 09:06:23 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
2025-10-18 13:20:23 +00:00
|
|
|
|
|
|
|
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"
|
2025-03-25 09:06:23 +00:00
|
|
|
else
|
2025-10-18 13:20:23 +00:00
|
|
|
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
|
2025-10-19 10:23:14 +00:00
|
|
|
SERVICE_WAS_RUNNING=0
|
|
|
|
OLD_NODE_INSTALL=0
|
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
if [ -d "$INSTALL_DIR" ]; then
|
2025-10-19 10:23:14 +00:00
|
|
|
# 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
|
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
if [ $AUTO_YES -eq 0 ] && [ $INTERACTIVE -eq 1 ]; then
|
2025-10-19 10:23:14 +00:00
|
|
|
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
|
2025-10-18 13:20:23 +00:00
|
|
|
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
|
2025-03-25 13:20:36 +00:00
|
|
|
fi
|
2025-10-18 13:20:23 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
echo "Updating existing installation at $INSTALL_DIR..."
|
2025-10-19 10:23:14 +00:00
|
|
|
|
|
|
|
# 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
|
2025-10-18 13:20:23 +00:00
|
|
|
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
|
2025-03-25 13:20:36 +00:00
|
|
|
fi
|
|
|
|
fi
|
2025-10-18 13:20:23 +00:00
|
|
|
|
|
|
|
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
|
2025-03-25 09:06:23 +00:00
|
|
|
fi
|
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
# 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"
|
2025-03-25 13:20:36 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
# Move to final location
|
|
|
|
BINARY_PATH="$INSTALL_DIR/nupst"
|
|
|
|
mv "$TEMP_FILE" "$BINARY_PATH"
|
2025-03-25 09:06:23 +00:00
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
# Make executable
|
|
|
|
chmod +x "$BINARY_PATH"
|
|
|
|
|
|
|
|
echo "Binary installed successfully to: $BINARY_PATH"
|
|
|
|
echo ""
|
2025-03-25 09:06:23 +00:00
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
# Check if /usr/local/bin is in PATH
|
|
|
|
if [[ ":$PATH:" == *":/usr/local/bin:"* ]]; then
|
|
|
|
BIN_DIR="/usr/local/bin"
|
2025-03-25 09:06:23 +00:00
|
|
|
else
|
2025-10-18 13:20:23 +00:00
|
|
|
BIN_DIR="/usr/bin"
|
2025-03-25 09:06:23 +00:00
|
|
|
fi
|
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
# 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 ""
|
2025-10-19 10:23:14 +00:00
|
|
|
|
|
|
|
# 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
|
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
echo "================================================"
|
|
|
|
echo " NUPST Installation Complete!"
|
|
|
|
echo "================================================"
|
2025-03-25 09:06:23 +00:00
|
|
|
echo ""
|
2025-10-19 10:23:14 +00:00
|
|
|
|
|
|
|
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 ""
|
2025-10-19 13:05:51 +00:00
|
|
|
echo "See readme for migration details: https://code.foss.global/serve.zone/nupst#migration-from-v3x"
|
2025-10-19 10:23:14 +00:00
|
|
|
echo ""
|
|
|
|
fi
|
|
|
|
|
2025-10-18 13:20:23 +00:00
|
|
|
echo "Installation details:"
|
|
|
|
echo " Binary location: $BINARY_PATH"
|
|
|
|
echo " Symlink location: $BIN_DIR/nupst"
|
|
|
|
echo " Version: $VERSION"
|
|
|
|
echo ""
|
2025-10-19 10:23:14 +00:00
|
|
|
|
|
|
|
# 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
|
2025-10-18 13:20:23 +00:00
|
|
|
echo ""
|