From 782420b4e42ad42dc3bc11ad352d9e8b92df9047 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 27 Apr 2026 06:06:16 -0400 Subject: [PATCH] PatchMon: v2.0.0 migration (#14015) Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com> --- ct/patchmon.sh | 110 ++++++++++++++++++++---------------- install/patchmon-install.sh | 108 ++++++++++++++++++++--------------- 2 files changed, 123 insertions(+), 95 deletions(-) diff --git a/ct/patchmon.sh b/ct/patchmon.sh index e49324495..99511aaa9 100644 --- a/ct/patchmon.sh +++ b/ct/patchmon.sh @@ -29,63 +29,75 @@ function update_script() { exit fi - if ! grep -q "PORT=3001" /opt/patchmon/backend/.env; then - msg_warn "⚠️ The next PatchMon update will include breaking changes (port changes)." - msg_warn "See details here: https://github.com/community-scripts/ProxmoxVE/pull/11888" - msg_warn "Press Enter to continue with the update, or Ctrl+C to abort..." - read -r - fi - - RELEASE="v1.4.2" - NODE_VERSION="24" setup_nodejs + RELEASE="v2.0.1" if check_for_gh_release "PatchMon" "PatchMon/PatchMon" "${RELEASE}"; then msg_info "Stopping Service" systemctl stop patchmon-server msg_ok "Stopped Service" - msg_info "Creating Backup" - cp /opt/patchmon/backend/.env /opt/backend.env - cp /opt/patchmon/frontend/.env /opt/frontend.env - msg_ok "Backup Created" - - CLEAN_INSTALL=1 fetch_and_deploy_gh_release "PatchMon" "PatchMon/PatchMon" "tarball" "${RELEASE}" "/opt/patchmon" - - msg_info "Updating PatchMon" - VERSION=$(get_latest_github_release "PatchMon/PatchMon") - SERVER_PORT="$(sed -n '/SERVER_PORT/s/[^=]*=//p' /opt/backend.env)" - sed -i 's/PORT=3399/PORT=3001/' /opt/backend.env - sed -i -e "s/VERSION=.*/VERSION=$VERSION/" \ - -e '/^VITE_API_URL/d' /opt/frontend.env - export NODE_ENV=production - cd /opt/patchmon - $STD npm install --no-audit --no-fund --no-save --ignore-scripts - cd /opt/patchmon/frontend - mv /opt/frontend.env /opt/patchmon/frontend/.env - $STD npm install --no-audit --no-fund --no-save --ignore-scripts --include=dev - $STD npm run build - cd /opt/patchmon/backend - mv /opt/backend.env /opt/patchmon/backend/.env - $STD npm run db:generate - $STD npx prisma migrate deploy - cp /opt/patchmon/docker/nginx.conf.template /etc/nginx/sites-available/patchmon.conf - sed -i -e 's|proxy_pass .*|proxy_pass http://127.0.0.1:3001;|' \ - -e '\|try_files |i\ root /opt/patchmon/frontend/dist;' \ - -e 's|alias.*|alias /opt/patchmon/frontend/dist/assets;|' \ - -e '\|expires 1y|i\ root /opt/patchmon/frontend/dist;' /etc/nginx/sites-available/patchmon.conf - if [[ -n "$SERVER_PORT" ]] && [[ "$SERVER_PORT" != "443" ]]; then - sed -i "s/listen [[:digit:]].*/listen ${SERVER_PORT};/" /etc/nginx/sites-available/patchmon.conf + if [[ -d /opt/patchmon/backend ]]; then + msg_info "Legacy install detected - creating full backup, please wait..." + $STD tar czf ~/patchmon_legacy.tar.gz /opt/patchmon + cp /opt/patchmon/backend/.env /opt/legacy.env + msg_ok "Full backup saved in /root" + msg_info "Starting migration to PatchMon v2.x.x" + systemctl disable -q --now nginx + $STD npm cache clean --force + $STD apt autoremove --purge -y {nginx,nodejs} + if [[ -f /etc/apt/sources.list.d/nodesource.sources ]]; then + cp /etc/apt/sources.list.d/nodesource.sources /etc/apt/sources.list.d/nodesource.sources.bak + rm -f /etc/apt/sources.list.d/nodesource.sources + elif [[ -f /etc/apt/sources.list.d/nodesource.list ]]; then + cp /etc/apt/sources.list.d/nodesource.list /etc/apt/sources.list.d/nodesource.list.bak + rm -f /etc/apt/sources.list.d/nodesource.list + fi + rm -rf /opt/patchmon + mkdir -p /opt/patchmon/agents + cp /opt/legacy.env /opt/patchmon/.env + sed -i -e 's/^PORT=.*/PORT=3000/' \ + -e 's/^NODE_/APP_/' \ + -e '/^SERVER_*/d' \ + -e '/^# API*/,+2d' /opt/patchmon/.env + { + echo "" + echo "SESSION_SECRET=$(openssl rand -hex 64)" + echo "AI_ENCRYPTION_KEY=$(openssl rand -hex 64)" + echo "AGENT_BINARIES_DIR=/opt/patchmon/agents" + } >>/opt/patchmon/.env + sed -i -e '\|Directory|s|/backend||' \ + -e 's|^ExecStart=.*|ExecStart=/opt/patchmon/patchmon-server|' \ + -e 's|^Environment=NODE_.*|EnvironmentFile=/opt/patchmon/.env|' \ + /etc/systemd/system/patchmon-server.service + systemctl daemon-reload + rm /opt/legacy.env + msg_ok "Migration complete!" fi - ln -sf /etc/nginx/sites-available/patchmon.conf /etc/nginx/sites-enabled/ - rm -f /etc/nginx/sites-enabled/default - $STD nginx -t - systemctl restart nginx - msg_ok "Updated PatchMon" + + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "PatchMon" "PatchMon/PatchMon" "singlefile" "${RELEASE}" "/opt/patchmon" "patchmon-server-linux-amd64" + mv /opt/patchmon/PatchMon /opt/patchmon/patchmon-server + + msg_info "Fetching PatchMon agent binaries" + [[ ! -d /opt/patchmon/agents ]] && mkdir -p /opt/patchmon/agents + FILE_URL="https://github.com/PatchMon/PatchMon/releases/download/${RELEASE}/patchmon-agent-" + AGENT_NAME=( + "linux-amd64" + "linux-arm64" + "linux-arm" + "linux-386" + "freebsd-amd64" + "freebsd-arm64" + "freebsd-arm" + "freebsd-386" + "windows-amd64.exe" + "windows-arm64.exe" + ) + for arch in "${AGENT_NAME[@]}"; do + curl_with_retry "${FILE_URL}${arch}" "/opt/patchmon/agents/patchmon-agent-${arch}" + [[ "${arch}" != *.exe ]] && chmod 755 "/opt/patchmon/agents/patchmon-agent-${arch}" + done + msg_ok "Fetched PatchMon agent binaries" msg_info "Starting Service" - if grep -q '/usr/bin/node' /etc/systemd/system/patchmon-server.service; then - sed -i 's|ExecStart=.*|ExecStart=/usr/bin/npm run start|' /etc/systemd/system/patchmon-server.service - systemctl daemon-reload - fi systemctl start patchmon-server msg_ok "Started Service" msg_ok "Updated successfully!" diff --git a/install/patchmon-install.sh b/install/patchmon-install.sh index eb9911591..914591719 100644 --- a/install/patchmon-install.sh +++ b/install/patchmon-install.sh @@ -14,74 +14,90 @@ network_check update_os msg_info "Installing Dependencies" -$STD apt install -y \ - build-essential \ - nginx \ - redis-server +$STD apt install -y redis-server msg_ok "Installed Dependencies" -NODE_VERSION="24" setup_nodejs PG_VERSION="17" setup_postgresql PG_DB_NAME="patchmon_db" PG_DB_USER="patchmon_usr" setup_postgresql_db -fetch_and_deploy_gh_release "PatchMon" "PatchMon/PatchMon" "tarball" "v1.4.2" "/opt/patchmon" +RELEASE="v2.0.1" +fetch_and_deploy_gh_release "PatchMon" "PatchMon/PatchMon" "singlefile" "$RELEASE" "/opt/patchmon" "patchmon-server-linux-amd64" +mv /opt/patchmon/PatchMon /opt/patchmon/patchmon-server msg_info "Configuring PatchMon" -VERSION=$(get_latest_github_release "PatchMon/PatchMon") -export NODE_ENV=production -cd /opt/patchmon -$STD npm install --no-audit --no-fund --no-save --ignore-scripts - -cd /opt/patchmon/frontend -cat <./.env -VITE_APP_NAME=PatchMon -VITE_APP_VERSION=${VERSION} -EOF -$STD npm install --no-audit --no-fund --no-save --ignore-scripts --include=dev -$STD npm run build - +cat </opt/patchmon/.env +DATABASE_URL="postgresql://$PG_DB_USER:$PG_DB_PASS@localhost:5432/$PG_DB_NAME" JWT_SECRET="$(openssl rand -hex 64)" -mv /opt/patchmon/backend/env.example /opt/patchmon/backend/.env -sed -i -e "s|DATABASE_URL=.*|DATABASE_URL=\"postgresql://$PG_DB_USER:$PG_DB_PASS@localhost:5432/$PG_DB_NAME\"|" \ - -e "/JWT_SECRET/s/[=$].*/=$JWT_SECRET/" \ - -e "\|CORS_ORIGIN|s|localhost|$LOCAL_IP|" \ - -e "/PORT=3001/aSERVER_PROTOCOL=http \\ - SERVER_HOST=$LOCAL_IP \\ - SERVER_PORT=3000" \ - -e '/_ENV=production/aTRUST_PROXY=1' \ - -e '/REDIS_USER=.*/,+1d' /opt/patchmon/backend/.env +SESSION_SECRET="$(openssl rand -hex 64)" +AI_ENCRYPTION_KEY="$(openssl rand -hex 64)" +CORS_ORIGIN=http://${LOCAL_IP}:3000 +PORT=3000 +APP_ENV=production -cd /opt/patchmon/backend -$STD npm run db:generate -$STD npx prisma migrate deploy +# Redis +REDIS_HOST=localhost +REDIS_PORT=6379 + +## OIDC / SSO (when OIDC_ENABLED=true, issuer/client/secret/redirect required) +# OIDC_ENABLED=false +# OIDC_ISSUER_URL= +# OIDC_CLIENT_ID= +# OIDC_CLIENT_SECRET= +# OIDC_REDIRECT_URI= +# OIDC_SCOPES=openid email profile groups +# OIDC_AUTO_CREATE_USERS=false +# OIDC_DEFAULT_ROLE=user +# OIDC_DISABLE_LOCAL_AUTH=false +# OIDC_BUTTON_TEXT=Login with SSO +# OIDC_SESSION_TTL=600 +# OIDC_POST_LOGOUT_URI= +# OIDC_SYNC_ROLES=false +# OIDC_ADMIN_GROUP= +# OIDC_SUPERADMIN_GROUP= +# OIDC_HOST_MANAGER_GROUP= +# OIDC_READONLY_GROUP= +# OIDC_USER_GROUP= +# OIDC_ENFORCE_HTTPS=true + +AGENT_BINARIES_DIR=/opt/patchmon/agents +EOF msg_ok "Configured PatchMon" -msg_info "Configuring Nginx" -cp /opt/patchmon/docker/nginx.conf.template /etc/nginx/sites-available/patchmon.conf -sed -i -e 's|proxy_pass .*|proxy_pass http://127.0.0.1:3001;|' \ - -e '\|try_files |i\ root /opt/patchmon/frontend/dist;' \ - -e 's|alias.*|alias /opt/patchmon/frontend/dist/assets;|' \ - -e '\|expires 1y|i\ root /opt/patchmon/frontend/dist;' /etc/nginx/sites-available/patchmon.conf -ln -sf /etc/nginx/sites-available/patchmon.conf /etc/nginx/sites-enabled/ -rm -f /etc/nginx/sites-enabled/default -$STD nginx -t -systemctl restart nginx -msg_ok "Configured Nginx" +msg_info "Fetching PatchMon agent binaries" +mkdir -p /opt/patchmon/agents +FILE_URL="https://github.com/PatchMon/PatchMon/releases/download/${RELEASE}/patchmon-agent-" +AGENT_NAME=( + "linux-amd64" + "linux-arm64" + "linux-arm" + "linux-386" + "freebsd-amd64" + "freebsd-arm64" + "freebsd-arm" + "freebsd-386" + "windows-amd64.exe" + "windows-arm64.exe" +) +for arch in "${AGENT_NAME[@]}"; do + curl_with_retry "${FILE_URL}${arch}" "/opt/patchmon/agents/patchmon-agent-${arch}" + [[ "${arch}" != *.exe ]] && chmod 755 "/opt/patchmon/agents/patchmon-agent-${arch}" +done +msg_ok "Fetched PatchMon agent binaries" msg_info "Creating service" cat </etc/systemd/system/patchmon-server.service [Unit] -Description=PatchMon Service +Description=PatchMon Server After=network.target postgresql.service [Service] Type=simple -WorkingDirectory=/opt/patchmon/backend -ExecStart=/usr/bin/npm run start +WorkingDirectory=/opt/patchmon +ExecStart=/opt/patchmon/patchmon-server Restart=always RestartSec=10 -Environment=NODE_ENV=production Environment=PATH=/usr/bin:/usr/local/bin +EnvironmentFile=/opt/patchmon/.env NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict