New paste
Recent
API
Trending
Blog
Guest
Sign Up or Login
Login
Sign Up
New Paste
Syntax Highlighting
# Update-n8n-Safely.ps1 # Comprehensive Windows automation for safely upgrading n8n and its Node.js runtime. # This script performs environment validation, PATH repair, Node.js requirement checks, # automated Node.js selection and installation, n8n installation, memory/heap diagnostics, # detection of conflicting tooling (such as nvm4w), and backup of existing n8n data. # Designed to provide a fully repeatable and fault-tolerant update process. $ErrorActionPreference = "Stop" # --- ELEVATE IF NOT RUNNING AS ADMIN --- $IsAdmin = ([Security.Principal.WindowsPrincipal] ` [Security.Principal.WindowsIdentity]::GetCurrent() ).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") if (-not $IsAdmin) { Write-Host "Re-launching with administrative privileges..." -ForegroundColor Yellow Start-Process powershell.exe -Verb RunAs -ArgumentList ( "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" ) exit } # --- END ELEVATION BLOCK --- Write-Host "=== Future-Proof n8n Updater for Windows ===" -ForegroundColor Cyan # --------------------------------------------------------------- # SYSTEM MEMORY CHECK + OPTIONAL NODE HEAP DETECTION # --------------------------------------------------------------- Write-Host "Checking system memory..." -ForegroundColor Yellow $ramFree = (Get-Counter '\Memory\Available MBytes').CounterSamples[0].CookedValue $commitLimit = (Get-Counter '\Memory\Commit Limit').CounterSamples[0].CookedValue / 1MB $committed = (Get-Counter '\Memory\Committed Bytes').CounterSamples[0].CookedValue / 1MB Write-Host "Free RAM: $([math]::Round($ramFree)) MB" -ForegroundColor Cyan Write-Host "Commit Used: $([math]::Round($committed)) MB / $([math]::Round($commitLimit)) MB" -ForegroundColor Cyan $currentHeap = $null try { $heapOutput = node -e "console.log(require('v8').getHeapStatistics().heap_size_limit / 1024 / 1024)" if ($heapOutput) { $currentHeap = [math]::Round([double]$heapOutput) } } catch {} if ($currentHeap) { Write-Host "Current Node heap limit: $currentHeap MB" -ForegroundColor Cyan } else { Write-Host "Current Node heap limit: (Node not installed yet)" -ForegroundColor DarkGray } $minFreeRamMB = 800 $heapSafeMB = 1536 if ($ramFree -lt $minFreeRamMB) { Write-Host "`nWARNING: You have less than $minFreeRamMB MB free RAM." -ForegroundColor Red Write-Host "n8n installation may fail due to insufficient memory." -ForegroundColor Yellow Write-Host "`nChoose an option:" Write-Host " [1] Continue anyway" Write-Host " [2] Apply safer heap limit (--max-old-space-size=$heapSafeMB)" Write-Host " [3] Abort installation" $choice = Read-Host "Enter 1, 2, or 3" switch ($choice) { "1" { Write-Host "Continuing despite low RAM..." -ForegroundColor Yellow } "2" { $env:NODE_OPTIONS = "--max-old-space-size=$heapSafeMB" Write-Host "Applied safe heap setting: $env:NODE_OPTIONS" -ForegroundColor Green } "3" { Write-Host "Aborting installation." -ForegroundColor Red exit 1 } default { Write-Host "Invalid choice. Aborting." -ForegroundColor Red exit 1 } } } # --------------------------------------------------------------- # SAFETY CHECK: BLOCK nvm4w # --------------------------------------------------------------- if (Test-Path "C:\nvm4w") { Write-Host "ERROR: Detected 'C:\nvm4w' residual folder." -ForegroundColor Red Write-Host "This folder hijacks Node MSI installs." -ForegroundColor Yellow Write-Host "Remove it: Remove-Item -Recurse -Force 'C:\nvm4w'" -ForegroundColor Cyan exit 1 } # --------------------------------------------------------------- # BACKUP n8n DATA # --------------------------------------------------------------- Write-Host "Backing up n8n data..." -ForegroundColor Yellow $date = Get-Date -Format "yyyy-MM-dd" Write-Host "Backup complete." -ForegroundColor Green # --------------------------------------------------------------- # FETCH LATEST n8n METADATA # --------------------------------------------------------------- Write-Host "Fetching latest n8n version and Node requirements..." -ForegroundColor Yellow $n8nUrl = "https://registry.npmjs.org/n8n/latest" try { $n8nData = (Invoke-WebRequest -Uri $n8nUrl -UseBasicParsing).Content | ConvertFrom-Json $latestN8nVersion = $n8nData.version $nodeEngineRange = $n8nData.engines.node } catch { Write-Host "Failed to fetch n8n metadata: $_" -ForegroundColor Red exit 1 } Write-Host "Latest n8n: $latestN8nVersion" -ForegroundColor Green Write-Host "Required Node: $nodeEngineRange" -ForegroundColor Green # --------------------------------------------------------------- # PARSE NODE ENGINE RANGE # --------------------------------------------------------------- $min = [regex]::Match($nodeEngineRange, '(>=|>)\s*(\d+(\.\d+)*)') $minOp = $min.Groups[1].Value $minNode = $min.Groups[2].Value $max = [regex]::Match($nodeEngineRange, '(<=|<)\s*(\d+(\.\d+){0,2}(?:\.x)?)(?=$|\s)') $maxOp = $max.Groups[1].Value $maxNode = $max.Groups[2].Value if ($maxNode -match '\.x$') { $maxNode = $maxNode -replace '\.x$', '.99.99' } # --------------------------------------------------------------- # FETCH NODE INDEX # --------------------------------------------------------------- Write-Host "Fetching Node.js versions list..." -ForegroundColor Yellow $nodeIndexUrl = "https://nodejs.org/dist/index.json" try { $nodeIndex = (Invoke-WebRequest -Uri $nodeIndexUrl -UseBasicParsing).Content | ConvertFrom-Json } catch { Write-Host "Failed to fetch Node versions: $_" -ForegroundColor Red exit 1 } # --------------------------------------------------------------- # FILTER VALID NODE VERSIONS # --------------------------------------------------------------- $candidates = $nodeIndex | Where-Object { $v = $_.version.TrimStart('v') if ($v -match '-') { return $false } if (-not ($_.files -contains "win-x64-msi")) { return $false } try { $ver = [version]$v $minOK = if ($minOp -eq '>=') { $ver -ge [version]$minNode } else { $ver -gt [version]$minNode } $maxOK = if ($maxOp -eq '<=') { $ver -le [version]$maxNode } else { $ver -lt [version]$maxNode } $minOK -and $maxOK } catch { $false } } if ($candidates.Count -eq 0) { Write-Host "No Node versions satisfy $nodeEngineRange" -ForegroundColor Red exit 1 } $ltsCandidates = $candidates | Where-Object { $_.lts -and $_.lts -ne $false } if ($ltsCandidates.Count -gt 0) { $chosen = $ltsCandidates | Sort-Object { [version]($_.version.TrimStart('v')) } -Descending | Select-Object -First 1 Write-Host "Selected LTS Node: $($chosen.version) (LTS: $($chosen.lts))" -ForegroundColor Green } else { $chosen = $candidates | Sort-Object { [version]($_.version.TrimStart('v')) } -Descending | Select-Object -First 1 Write-Host "Selected latest stable Node: $($chosen.version)" -ForegroundColor Yellow } $realVer = $chosen.version.TrimStart('v') if ($realVer -like "24.1[1-9].*" -or $realVer -like "24.[2-9][0-9].*") { Write-Host "WARNING: Bogus Node version detected: $realVer" -ForegroundColor Red $chosen = $candidates | Where-Object { $_.version -like "v24.1.*" } | Select-Object -First 1 } $targetNodeVersion = $chosen.version Write-Host "Best Node version for n8n ${latestN8nVersion}: $targetNodeVersion" -ForegroundColor Green # --------------------------------------------------------------- # UNINSTALL OLD NODE # --------------------------------------------------------------- Write-Host "Uninstalling any existing Node.js..." -ForegroundColor Yellow $unKeys = @( "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" ) $products = Get-ItemProperty -Path $unKeys -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like "*Node.js*" } foreach ($p in $products) { if ($p.UninstallString -match '{[0-9A-Fa-f\-]+}') { $guid = $matches[0] Start-Process -Wait msiexec.exe -ArgumentList "/x $guid /quiet /norestart" } elseif ($p.UninstallString) { Start-Process -Wait cmd.exe -ArgumentList "/c `"$($p.UninstallString)`"" } } Start-Sleep -Seconds 2 # --------------------------------------------------------------- # DOWNLOAD + INSTALL NODE MSI # --------------------------------------------------------------- Write-Host "Downloading and installing Node $targetNodeVersion..." -ForegroundColor Yellow $base = $targetNodeVersion.TrimStart('v') $msiUrl = "https://nodejs.org/dist/v$base/node-v$base-x64.msi" $msiPath = "$env:TEMP\node-v$base-x64.msi" Write-Host "MSI URL: $msiUrl" -ForegroundColor Yellow Invoke-WebRequest -Uri $msiUrl -OutFile $msiPath -UseBasicParsing Write-Host "Downloaded: $msiPath" -ForegroundColor Yellow $size = (Get-Item $msiPath).Length Write-Host "Size: $size bytes" -ForegroundColor Yellow $bytes = Get-Content $msiPath -Encoding Byte -TotalCount 8 $hex = ($bytes | ForEach-Object { $_.ToString("X2") }) -join " " Write-Host "Header: $hex" -ForegroundColor Yellow Start-Process -Wait msiexec.exe -ArgumentList "/i `"$msiPath`" /quiet /norestart" Remove-Item $msiPath -Force # --------------------------------------------------------------- # DETECT NODE INSTALL LOCATION # --------------------------------------------------------------- $locations = @( "C:\Program Files\nodejs", "$env:LOCALAPPDATA\Programs\nodejs" ) $found = $null foreach ($loc in $locations) { if (Test-Path (Join-Path $loc "node.exe")) { $found = $loc break } } if (-not $found) { Write-Host "ERROR: Node did not install into expected directories." -ForegroundColor Red exit 1 } Write-Host "Found Node at: $found" -ForegroundColor Green $env:PATH = "$found;$env:PATH" # --------------------------------------------------------------- # PATH REPAIR (NEW SECTION) # --------------------------------------------------------------- $npmGlobalRoot = npm root -g 2>$null $npmBinDir = Split-Path $npmGlobalRoot -Parent $pathUser = [Environment]::GetEnvironmentVariable("Path","User") if (-not ($pathUser -split ";" | Where-Object { $_ -eq $npmBinDir })) { $newUserPath = $pathUser + ";" + $npmBinDir [Environment]::SetEnvironmentVariable("Path",$newUserPath,"User") Write-Host "Added npm global bin to PATH (User): $npmBinDir" -ForegroundColor Yellow } $pathMachine = [Environment]::GetEnvironmentVariable("Path","Machine") if (-not ($pathMachine -split ";" | Where-Object { $_ -eq $found })) { $newMachinePath = $pathMachine + ";" + $found [Environment]::SetEnvironmentVariable("Path",$newMachinePath,"Machine") Write-Host "Added Node install dir to PATH (Machine): $found" -ForegroundColor Yellow } $env:PATH = [Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [Environment]::GetEnvironmentVariable("Path","User") # --------------------------------------------------------------- # VERIFY NODE + REPORT HEAP LIMIT # --------------------------------------------------------------- Write-Host "Verifying installation..." -ForegroundColor Yellow $installedNode = (node -v 2>$null).Trim().Replace("v","") $installedNpm = (npm -v 2>$null).Trim() if (-not $installedNode) { Write-Host "ERROR: Node not detected even after installation." -ForegroundColor Red exit 1 } Write-Host "Node $installedNode and npm $installedNpm installed successfully." -ForegroundColor Green $heapAfter = $null try { $heapAfter = node -e "console.log(require('v8').getHeapStatistics().heap_size_limit / 1024 / 1024)" } catch {} if ($heapAfter) { Write-Host "Node heap limit now: $([math]::Round([double]$heapAfter)) MB" -ForegroundColor Cyan } # --------------------------------------------------------------- # INSTALL n8n # --------------------------------------------------------------- Write-Host "Installing n8n@$latestN8nVersion..." -ForegroundColor Yellow npm install -g n8n@$latestN8nVersion $n8nVersion = (n8n --version 2>$null).Trim() if ($n8nVersion -ne $latestN8nVersion) { Write-Host "ERROR: n8n installation mismatch (expected $latestN8nVersion, got $n8nVersion)." -ForegroundColor Red exit 1 } Write-Host "`nSUCCESS: n8n $n8nVersion installed on Node $installedNode" -ForegroundColor Cyan Write-Host "Run launch-n8n.ps1 to start n8n." -ForegroundColor Green
Optional Gist Settings
Gist Name/Title:
Category:
None
Cryptocurrency
Cybersecurity
Fixit
Food
Gaming
Haiku
Help
History
Housing
Jokes
Legal
Money
Movies
Music
Pets
Photo
Science
Software
Source Code
Spirit
Sports
Travel
TV
Writing
Syntax Highlighting:
None
Bash
C
C++
C#
CSS
HTML
Java
JavaScript
Lua
Objective C
Perl
PHP
Python
Ruby
JSON
Swift
Markdown
ActionScript
Ada
Apache Log
AppleScript
ASM (NASM)
ASP
Bash
C
C for Macs
CAD DCL
CAD Lisp
C++
C#
ColdFusion
CSS
D
Delphi
Diff
Batch
Eiffel
Fortran
FreeBasic
Game Maker
HTML
INI file
Java
JavaScript
Lisp
Lua
MPASM
MySQL
NullSoft Installer
Objective C
OCaml
Openoffice BASIC
Oracle 8
Pascal
Perl
PHP
Python
QBasic
Robots
Ruby
Scheme
Smarty
SQL
VisualBasic
VB.NET
VisualFoxPro
XML
AutoIt
Blitz Basic
BNF
Erlang
Genero
Groovy
Haskell
Inno Script
Latex
Linden Scripting
MatLab
M68000 Assembler
mIRC
Rails
PL/SQL
Smalltalk
TCL
Z80 Assembler
ABAP
ActionScript 3
APT Sources
Avisynth
Basic4GL
BibTeX
BrainFuck
BOO
CFDG
C Intermediate Language
CMake
COBOL
DCS
DIV
DOT
Email
FO Language
GetText
OpenGL Shading
Ruby Gnuplot
HQ9 Plus
IDL
INTERCAL
IO
Java 5
KiXtart
Clone C
Clone C++
Loco Basic
LOL Code
Lotus Formulas
Lotus Script
LScript
Make
Modula 3
MXML
Oberon 2
OCaml Brief
Oracle 11
Per
PHP Brief
Pic 16
Pixel Bender
POV-Ray
PowerShell
Progress
Prolog
Properties
ProvideX
REBOL
REG
SAS
Scala
Scilab
SdlBasic
Tera Term
thinBasic
T-SQL
TypoScript
VeriLog
VHDL
VIM
Visual Pro Log
WhiteSpace
WHOIS
Winbatch
Xorg Config
XPP
Pawn
4CS
6502 ACME Cross Assembler
6502 Kick Assembler
6502 TASM/64TASS
Motorola 68000 HiSoft Dev
ALGOL 68
autoconf
Autohotkey
Awk
Cuesheet
ChaiScript
Clojure
C++ (with Qt extensions)
E
ECMAScript
Formula One
F#
GAMBAS
GDB
Genie
Go
GwBasic
HicEst
Icon
J
jQuery
Liberty BASIC
Logtalk
MagikSF
MapBasic
MIX Assembler
Modula 2
newLISP
Objeck Programming Language
Oz
Delphi Prism (Oxygene)
Oz
PCRE
Perl 6
OpenBSD PACKET FILTER
Pike
PostgreSQL
PowerBuilder
PureBasic
q/kdb+
RPM Spec
R
SystemVerilog
Vala
Unicon
Vala
XBasic
ZXBasic
UnrealScript
HTML 5
ProFTPd
BASCOM AVR
C: Loadrunner
CoffeeScript
EPC
Falcon
LLVM
PyCon
YAML
FreeSWITCH
ARM
Asymptote
DCL
DCPU-16
Haxe
LDIF
Nagios
Octave
ParaSail
PARI/GP
Python for S60
Rexx
SPARK
SPARQL
StoneScript
UPC
Urbi
Vedit
AIMMS
Chapel
Dart
Easytrieve
ISPF Panel Definition
JCL
Nginx
Nim
PostScript
QML
Racket
RBScript
Rust
SCL
StandardML
VBScript
C (WinAPI)
C++ (WinAPI)
NetRexx
JSON
Swift
SuperCollider
Julia
Blitz3D
BlitzMax
SQF
Puppet
Filemaker
Euphoria
PL/I
Open Object Rexx
Markdown
Kotlin
Ceylon
Arduino
YARA
TypeScript
Mercury
MetaPost
MK-61/52
Phix
Roff Manpage
SSH Config
TeXgraph
Xojo
KSP (Kontakt Script)
GDScript
Godot GLSL
None
Tags:
Gist Exposure:
Public
Unlisted
Private
Gist Expiration:
Never
Burn after read
10 Minutes
1 Hour
1 Day
1 Week
2 Weeks
1 Month
6 Months
1 Year
Password
Enabled
Disabled
Folder:
(members only)
Burn after read
Create New Gist
You are currently not logged in, this means you can not edit or delete anything you paste.
Sign Up
or
Login
Public Gists
Untitled
None | 1 day ago | 9 Views
Shell Scripting: Generating Diff of GitLab Merge Request
Bash | 1 day ago | 15 Views
ESP32 Sample
Python | 1 day ago | 21 Views
Windows automation script for safely upgrading n8n and Node.js runtime
None | 5 days ago | 32 Views
Pub Sub
None | 5 days ago | 40 Views
Assignment 3
HTML | 5 days ago | 40 Views
React2Shell Scanner - Python Script for Exploiting CVE-2025-55182 & CVE-2025-66478
Python | 1 week ago | 59 Views
Not a member of GistPad yet?
Sign Up
, it unlocks many cool features!
We use cookies for various purposes including analytics. By continuing to use GistPad, you agree to our use of cookies as described in the
Privacy Policy
.
OK, I Understand