#!/bin/bash set -euo pipefail # Load IP configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true # Install NPMplus using existing template or create from existing container set -e PROXMOX_HOST="${1:-192.168.11.11}" TZ="${2:-America/New_York}" ACME_EMAIL="${3:-nsatoshi2007@hotmail.com}" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "🚀 NPMplus Installation (Using Available Resources)" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" # Find next container ID CTID=$(ssh root@"$PROXMOX_HOST" "pct list | tail -n +2 | awk '{print \$1}' | sort -n | tail -1") CTID=$((CTID + 1)) echo "📋 Using container ID: $CTID" echo "" # Check for existing templates echo "📦 Checking for available templates..." EXISTING_TEMPLATE=$(ssh root@"$PROXMOX_HOST" "pveam list local | grep -i alpine | head -1 | awk '{print \$1}' || echo ''") if [ -n "$EXISTING_TEMPLATE" ]; then echo " ✅ Found existing template: $EXISTING_TEMPLATE" # pveam list returns format like "local:vztmpl/alpine-3.22-default_20250617_amd64.tar.xz" TEMPLATE="$EXISTING_TEMPLATE" else # Check what the existing NPM container uses echo " ⚠️ No Alpine template found locally" echo " 📋 Checking existing NPM container (105) for template info..." # Try to use ubuntu or debian template if available UBUNTU_TEMPLATE=$(ssh root@"$PROXMOX_HOST" "pveam list local | grep -iE 'ubuntu|debian' | head -1 | awk '{print \$1}' || echo ''") if [ -n "$UBUNTU_TEMPLATE" ]; then echo " ✅ Found alternative template: $UBUNTU_TEMPLATE" # pveam list returns format like "local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst" TEMPLATE="$UBUNTU_TEMPLATE" else echo " ❌ No suitable template found" echo "" echo " 💡 Solution: Download template manually or use Proxmox web UI" echo " Or run on Proxmox host:" echo " pveam download local alpine-3.22-default_20250617_amd64.tar.xz" exit 1 fi fi # Create container echo "" echo "📦 Creating container with template: $TEMPLATE..." # Template from pveam is already in format "local:vztmpl/filename", use directly ssh root@"$PROXMOX_HOST" "pct create $CTID \\ $TEMPLATE \\ --hostname npmplus \\ --memory 512 \\ --cores 1 \\ --rootfs local-lvm:3 \\ --net0 name=eth0,bridge=vmbr0,ip=dhcp \\ --unprivileged 1 \\ --features nesting=1" || { echo " ❌ Failed to create container" exit 1 } echo " ✅ Container created" # Start container echo "" echo "🚀 Starting container..." ssh root@"$PROXMOX_HOST" "pct start $CTID" || { echo " ❌ Failed to start container" exit 1 } # Wait for container to be ready echo " ⏳ Waiting for container to be ready..." sleep 5 # Install NPMplus inside container echo "" echo "📦 Installing NPMplus inside container..." ssh root@"$PROXMOX_HOST" "pct exec $CTID -- bash" << INSTALL_EOF set -e # Detect OS and install accordingly if [ -f /etc/alpine-release ]; then echo " 📋 Detected Alpine Linux" apk update apk add --no-cache tzdata gawk yq docker curl bash # Start Docker rc-service docker start || true rc-update add docker default || true # Install docker compose plugin DOCKER_COMPOSE_VERSION=\$(curl -fsSL https://api.github.com/repos/docker/compose/releases/latest 2>/dev/null | grep '"tag_name":' | cut -d'"' -f4 || echo "v2.24.0") DOCKER_CONFIG=\${DOCKER_CONFIG:-\$HOME/.docker} mkdir -p \$DOCKER_CONFIG/cli-plugins curl -fsSL "https://github.com/docker/compose/releases/download/\${DOCKER_COMPOSE_VERSION#v}/docker-compose-linux-x86_64" -o \$DOCKER_CONFIG/cli-plugins/docker-compose 2>/dev/null || \\ curl -fsSL "https://github.com/docker/compose/releases/download/v2.24.0/docker-compose-linux-x86_64" -o \$DOCKER_CONFIG/cli-plugins/docker-compose chmod +x \$DOCKER_CONFIG/cli-plugins/docker-compose elif [ -f /etc/debian_version ]; then echo " 📋 Detected Debian/Ubuntu" apt-get update apt-get install -y tzdata gawk curl bash ca-certificates gnupg lsb-release # Install Docker from official repository echo " 📦 Installing Docker..." if [ ! -f /etc/apt/keyrings/docker.gpg ]; then install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg chmod a+r /etc/apt/keyrings/docker.gpg # Detect Ubuntu version for Docker repo UBUNTU_CODENAME=\$(lsb_release -cs 2>/dev/null || echo "jammy") echo "deb [arch=\$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \$UBUNTU_CODENAME stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null apt-get update fi # Install Docker packages (skip if already installed) if ! command -v docker >/dev/null 2>&1; then apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin else echo " ℹ️ Docker already installed, ensuring docker-compose-plugin..." apt-get install -y docker-compose-plugin || true fi # Install yq from GitHub releases echo " 📦 Installing yq..." if ! command -v yq >/dev/null 2>&1; then YQ_VERSION=\$(curl -fsSL https://api.github.com/repos/mikefarah/yq/releases/latest 2>/dev/null | grep '"tag_name":' | cut -d'"' -f4 || echo "v4.40.5") curl -fsSL "https://github.com/mikefarah/yq/releases/download/\${YQ_VERSION}/yq_linux_amd64" -o /usr/local/bin/yq chmod +x /usr/local/bin/yq else echo " ℹ️ yq already installed" fi # Start Docker systemctl start docker || true systemctl enable docker || true else echo " ❌ Unsupported OS" exit 1 fi # Wait for Docker sleep 5 # Fetch NPMplus compose file cd /opt echo " 📥 Downloading NPMplus compose.yaml..." curl -fsSL "https://raw.githubusercontent.com/ZoeyVid/NPMplus/refs/heads/develop/compose.yaml" -o compose.yaml || { echo " ❌ Failed to download compose.yaml" exit 1 } # Update compose file with timezone and email if command -v yq >/dev/null 2>&1; then echo " 📝 Updating compose.yaml..." yq -i " .services.npmplus.environment |= (map(select(. != \"TZ=*\" and . != \"ACME_EMAIL=*\")) + [\"TZ=$TZ\", \"ACME_EMAIL=$ACME_EMAIL\"]) " compose.yaml else echo " ⚠️ yq not available, updating manually..." sed -i "s|TZ=.*|TZ=$TZ|g" compose.yaml || true sed -i "s|ACME_EMAIL=.*|ACME_EMAIL=$ACME_EMAIL|g" compose.yaml || true fi # Start NPMplus echo " 🚀 Starting NPMplus (this may take 1-2 minutes)..." cd /opt docker compose up -d || { echo " ⚠️ docker compose failed, checking status..." docker compose ps || true exit 1 } # Wait for NPMplus to be ready echo " ⏳ Waiting for NPMplus to start..." CONTAINER_ID="" for i in {1..60}; do CONTAINER_ID=\$(docker ps --filter "name=npmplus" --format "{{.ID}}" 2>/dev/null || echo "") if [ -n "\$CONTAINER_ID" ]; then STATUS=\$(docker inspect --format '{{.State.Health.Status}}' "\$CONTAINER_ID" 2>/dev/null || echo "starting") if [ "\$STATUS" = "healthy" ] || [ "\$STATUS" = "running" ]; then echo " ✅ NPMplus is running" break fi fi sleep 2 done # Get admin password echo " 🔑 Retrieving admin password..." PASSWORD_LINE=\$(docker logs "\$CONTAINER_ID" 2>&1 | grep -i "Creating a new user" | tail -1 || echo "") if [ -n "\$PASSWORD_LINE" ]; then PASSWORD=\$(echo "\$PASSWORD_LINE" | grep -oP "password: \K[^\s]+" || echo "") if [ -n "\$PASSWORD" ]; then echo "username: admin@example.org" > /opt/.npm_pwd echo "password: \$PASSWORD" >> /opt/.npm_pwd echo " ✅ Admin password saved" fi fi echo " ✅ NPMplus installation complete!" INSTALL_EOF if [ $? -eq 0 ]; then # Get container IP CONTAINER_IP=$(ssh root@"$PROXMOX_HOST" "pct exec $CTID -- hostname -I | awk '{print \$1}'") echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "✅ NPMplus Installation Complete!" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" echo "📋 Container Information:" echo " • Container ID: $CTID" echo " • Container IP: $CONTAINER_IP" echo " • Access URL: https://$CONTAINER_IP:81" echo " • Admin Email: admin@example.org" echo "" echo "🔑 Get admin password:" echo " ssh root@$PROXMOX_HOST \"pct exec $CTID -- cat /opt/.npm_pwd\"" echo "" # Continue with migration echo "🚀 Continuing with configuration migration..." ADMIN_PASSWORD=$(ssh root@"$PROXMOX_HOST" "pct exec $CTID -- cat /opt/.npm_pwd 2>/dev/null | grep -i password | cut -d: -f2 | tr -d ' ' || echo '') if [ -z "$ADMIN_PASSWORD" ]; then echo " ⚠️ Could not retrieve password automatically" echo " 💡 Run migration manually:" echo " bash scripts/nginx-proxy-manager/post-install-migration.sh $PROXMOX_HOST $CTID $CONTAINER_IP" else echo "$ADMIN_PASSWORD" | bash scripts/nginx-proxy-manager/migrate-configs-to-npmplus.sh \ "$PROXMOX_HOST" \ "$CTID" \ "https://$CONTAINER_IP:81" || { echo " ⚠️ Migration had issues, but installation is complete" } fi else echo "" echo "❌ Installation failed. Check the output above." exit 1 fi