diff --git a/README.md b/README.md index c43211dcd..b3d00622a 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ bash -c "$(wget -qLO - https://github.com/community-scripts/ProxmoxVE/raw/main/c docker run -d -p 7655:3000 -v pulse_config:/etc/pulse -v pulse_data:/data rcourtman/pulse:latest # Option C: Manual Install (For existing LXC/VMs) -curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-pulse.sh | sudo bash +curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | sudo bash ``` ### Configure Pulse diff --git a/build-release.sh b/build-release.sh new file mode 100755 index 000000000..4d636e933 --- /dev/null +++ b/build-release.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash + +# Build script for Pulse releases +# Creates release archives for different architectures + +set -euo pipefail + +VERSION=${1:-$(cat VERSION)} +BUILD_DIR="build" +RELEASE_DIR="release" + +echo "Building Pulse v${VERSION}..." + +# Clean previous builds +rm -rf $BUILD_DIR $RELEASE_DIR +mkdir -p $BUILD_DIR $RELEASE_DIR + +# Build frontend +echo "Building frontend..." +cd frontend-modern +npm ci +npm run build +cd .. + +# Build for different architectures +architectures=( + "linux/amd64" + "linux/arm64" + "linux/arm/v7" +) + +for arch in "${architectures[@]}"; do + echo "Building for $arch..." + + os=$(echo $arch | cut -d'/' -f1) + arch_name=$(echo $arch | cut -d'/' -f2) + + # Convert arch names + case $arch_name in + "arm/v7") arch_suffix="armv7" ;; + *) arch_suffix=$arch_name ;; + esac + + # Build binary + GOOS=$os GOARCH=${arch_name%/*} GOARM=${arch_name#*/} \ + go build -ldflags="-s -w -X main.version=${VERSION}" \ + -trimpath -o $BUILD_DIR/pulse-$os-$arch_suffix ./cmd/pulse + + # Create release archive + tar_name="pulse-v${VERSION}-${os}-${arch_suffix}.tar.gz" + + cd $BUILD_DIR + tar -czf ../$RELEASE_DIR/$tar_name \ + pulse-$os-$arch_suffix \ + ../frontend-modern/dist \ + ../README.md \ + ../LICENSE \ + ../pulse.service \ + ../install.sh + cd .. + + echo "Created $RELEASE_DIR/$tar_name" +done + +# Create checksums +cd $RELEASE_DIR +sha256sum *.tar.gz > checksums.txt + +echo "Release build complete! Files in $RELEASE_DIR/" \ No newline at end of file diff --git a/install.sh b/install.sh new file mode 100755 index 000000000..d3c5ea00a --- /dev/null +++ b/install.sh @@ -0,0 +1,275 @@ +#!/usr/bin/env bash + +# Pulse Installer Script for Go Version +# Supports: Ubuntu 20.04+, Debian 11+, Proxmox VE 7+ + +set -euo pipefail + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Configuration +INSTALL_DIR="/opt/pulse" +CONFIG_DIR="/etc/pulse" +DATA_DIR="/var/lib/pulse" +SERVICE_NAME="pulse" +GITHUB_REPO="rcourtman/Pulse" +REQUIRED_GO_VERSION="1.21" + +# Functions +print_header() { + echo -e "${BLUE}=================================================${NC}" + echo -e "${BLUE} Pulse Installation Script${NC}" + echo -e "${BLUE}=================================================${NC}" + echo +} + +print_error() { + echo -e "${RED}[ERROR] $1${NC}" >&2 +} + +print_success() { + echo -e "${GREEN}[SUCCESS] $1${NC}" +} + +print_info() { + echo -e "${YELLOW}[INFO] $1${NC}" +} + +check_root() { + if [[ $EUID -ne 0 ]]; then + print_error "This script must be run as root" + exit 1 + fi +} + +detect_os() { + if [[ -f /etc/os-release ]]; then + . /etc/os-release + OS=$ID + VER=$VERSION_ID + else + print_error "Cannot detect OS" + exit 1 + fi +} + +check_existing_installation() { + if systemctl is-active --quiet $SERVICE_NAME 2>/dev/null; then + print_info "Pulse is currently running" + return 0 + elif [[ -f "$INSTALL_DIR/pulse" ]]; then + print_info "Pulse is installed but not running" + return 0 + else + return 1 + fi +} + +install_dependencies() { + print_info "Installing dependencies..." + + apt-get update -qq + apt-get install -y -qq curl wget git build-essential + + # Install Go if not present or version is too old + if ! command -v go &> /dev/null; then + print_info "Installing Go..." + wget -q -O go.tar.gz https://go.dev/dl/go1.23.linux-amd64.tar.gz + tar -C /usr/local -xzf go.tar.gz + rm go.tar.gz + export PATH=$PATH:/usr/local/go/bin + echo 'export PATH=$PATH:/usr/local/go/bin' >> /etc/profile + fi + + # Install Node.js for frontend build + if ! command -v node &> /dev/null; then + print_info "Installing Node.js..." + curl -fsSL https://deb.nodesource.com/setup_20.x | bash - + apt-get install -y nodejs + fi +} + +create_user() { + if ! id -u pulse &>/dev/null; then + print_info "Creating pulse user..." + useradd --system --home-dir $INSTALL_DIR --shell /bin/false pulse + fi +} + +backup_existing() { + if [[ -d "$CONFIG_DIR" ]]; then + print_info "Backing up existing configuration..." + cp -a "$CONFIG_DIR" "${CONFIG_DIR}.backup.$(date +%Y%m%d-%H%M%S)" + fi +} + +download_pulse() { + print_info "Downloading Pulse..." + + # Get latest release + LATEST_RELEASE=$(curl -s https://api.github.com/repos/$GITHUB_REPO/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + + if [[ -z "$LATEST_RELEASE" ]]; then + print_error "Could not determine latest release" + exit 1 + fi + + print_info "Latest version: $LATEST_RELEASE" + + # Download and extract + cd /tmp + wget -q -O pulse.tar.gz "https://github.com/$GITHUB_REPO/releases/download/$LATEST_RELEASE/pulse-${LATEST_RELEASE}-linux-amd64.tar.gz" + + mkdir -p "$INSTALL_DIR" + tar -xzf pulse.tar.gz -C "$INSTALL_DIR" + rm pulse.tar.gz +} + +setup_directories() { + print_info "Setting up directories..." + + # Create directories + mkdir -p "$CONFIG_DIR" + mkdir -p "$DATA_DIR" + mkdir -p "$INSTALL_DIR" + + # Set permissions + chown -R pulse:pulse "$CONFIG_DIR" "$DATA_DIR" "$INSTALL_DIR" + chmod 700 "$CONFIG_DIR" +} + +install_systemd_service() { + print_info "Installing systemd service..." + + cat > /etc/systemd/system/$SERVICE_NAME.service << EOF +[Unit] +Description=Pulse Monitoring Server +After=network.target + +[Service] +Type=simple +User=pulse +Group=pulse +WorkingDirectory=$INSTALL_DIR +ExecStart=$INSTALL_DIR/pulse +Restart=always +RestartSec=3 +StandardOutput=journal +StandardError=journal +Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + +# Security hardening +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=$INSTALL_DIR $CONFIG_DIR $DATA_DIR + +[Install] +WantedBy=multi-user.target +EOF + + systemctl daemon-reload +} + +start_pulse() { + print_info "Starting Pulse..." + systemctl enable $SERVICE_NAME + systemctl start $SERVICE_NAME + + # Wait for service to start + sleep 3 + + if systemctl is-active --quiet $SERVICE_NAME; then + print_success "Pulse started successfully" + else + print_error "Failed to start Pulse" + journalctl -u $SERVICE_NAME -n 20 + exit 1 + fi +} + +print_completion() { + local IP=$(hostname -I | awk '{print $1}') + + echo + print_header + print_success "Pulse installation completed!" + echo + echo -e "${GREEN}Access Pulse at:${NC} http://${IP}:7655" + echo + echo -e "${YELLOW}Useful commands:${NC}" + echo " systemctl status $SERVICE_NAME - Check service status" + echo " systemctl restart $SERVICE_NAME - Restart Pulse" + echo " journalctl -u $SERVICE_NAME -f - View logs" + echo +} + +# Main installation flow +main() { + print_header + check_root + detect_os + + if check_existing_installation; then + print_info "Existing Pulse installation detected" + echo + echo "What would you like to do?" + echo "1) Update to latest version" + echo "2) Reinstall" + echo "3) Remove" + echo "4) Cancel" + read -p "Select option [1-4]: " choice + + case $choice in + 1) + backup_existing + systemctl stop $SERVICE_NAME || true + download_pulse + start_pulse + print_completion + ;; + 2) + backup_existing + systemctl stop $SERVICE_NAME || true + download_pulse + setup_directories + install_systemd_service + start_pulse + print_completion + ;; + 3) + systemctl stop $SERVICE_NAME || true + systemctl disable $SERVICE_NAME || true + rm -f /etc/systemd/system/$SERVICE_NAME.service + rm -rf "$INSTALL_DIR" + print_success "Pulse removed successfully" + ;; + 4) + print_info "Installation cancelled" + exit 0 + ;; + *) + print_error "Invalid option" + exit 1 + ;; + esac + else + # Fresh installation + install_dependencies + create_user + download_pulse + setup_directories + install_systemd_service + start_pulse + print_completion + fi +} + +# Run main function +main "$@" \ No newline at end of file diff --git a/pulse.service b/pulse.service new file mode 100644 index 000000000..0b1e22c8a --- /dev/null +++ b/pulse.service @@ -0,0 +1,25 @@ +[Unit] +Description=Pulse Monitoring Server +After=network.target + +[Service] +Type=simple +User=pulse +Group=pulse +WorkingDirectory=/opt/pulse +ExecStart=/opt/pulse/pulse +Restart=always +RestartSec=3 +StandardOutput=journal +StandardError=journal +Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + +# Security hardening +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=/opt/pulse /etc/pulse /var/lib/pulse + +[Install] +WantedBy=multi-user.target \ No newline at end of file