Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save michele-tn/3dd7b8c2f4c6a4e3c21fd4b5c7d40a6d to your computer and use it in GitHub Desktop.

Select an option

Save michele-tn/3dd7b8c2f4c6a4e3c21fd4b5c7d40a6d to your computer and use it in GitHub Desktop.

RustDesk Portable Auto Downloader & Configurator (Windows x64)

This repository provides a PowerShell script that automatically downloads, configures, and launches the RustDesk Windows x64 portable client, using only your self-hosted ID server and public key.

It is ideal for:

  • 🔧 Mass deployment (RMM, GPO, Intune, etc.)
  • 🧰 Technicians who need a ready-to-use portable RustDesk client
  • 💼 Environments where software installation is restricted

Note
This script configures the client only.
It does not install or manage a RustDesk server.
For server setup, refer to the official RustDesk documentation.


Script Link

Official PowerShell script (published as a Gist):

🔗 RustDeskPortable.ps1:
https://gist.github.com/michele-tn/8a824d6257147718fd8384da0fa13f7a

You can:

  • download it as a single .ps1 file,
  • include it in deployment packages,
  • or run it remotely using PowerShell (Invoke-WebRequest, Invoke-RestMethod, etc.)

Features

  • 🆕 Automatically fetches the latest RustDesk release tag from GitHub.
  • 💾 Downloads the corresponding Windows x64 portable executable.
  • ⚙️ Creates a valid RustDesk configuration file with:
    • rendezvous_server
    • key
  • 🧱 Uses the official RustDesk config path for the current user:
    %AppData%\RustDesk\config\RustDesk2.toml
    
  • 🪶 No installation required — fully portable.
  • 🧾 Logs download and update information.
  • ▶️ Launches RustDesk automatically once configured.

Requirements

  • Operating System:
    Windows 10 / 11 (64-bit)

  • PowerShell:

    • Windows PowerShell 5.1+ or
    • PowerShell 7+
  • Network:
    Outbound HTTPS access to:

    • api.github.com
    • github.com
  • Server:
    Self-hosted RustDesk hbbs (ID server) and a valid public key (id_ed25519.pub).


Script Parameters

param(
    [string]$ServerIP = "192.168.1.100",   # ID server (hbbs)
    [string]$Key      = "MY_PUBLIC_KEY"    # Full contents of id_ed25519.pub
)
  • ServerIP → Address or hostname of your RustDesk ID server (hbbs)
  • Key → The full public key string used by your RustDesk server

Generated Configuration Example

The script writes this configuration file to:

%AppData%\RustDesk\config\RustDesk2.toml

Example contents:

rendezvous_server = 'rustdesk.yourdomain.com'
nat_type = 1
serial = 0

[options]
custom-rendezvous-server = 'rustdesk.yourdomain.com'
key = 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMyExampleKey1234567890...'

Only ID server and key are configured — no relay or API server entries are set.


How It Works

  1. Detects the script execution directory.
  2. Creates a clean portable folder (RustDeskPortable) and user config directory.
  3. Fetches the latest tag from the official RustDesk GitHub repository.
  4. Locates the Windows x64 portable executable (no installer, no server build).
  5. Downloads and verifies it.
  6. Generates a RustDesk2.toml file with your provided ServerIP and Key.
  7. Updates the local update.log with tag and timestamp.
  8. Starts RustDesk automatically, ready to connect.

Usage

1. Download the Script

Invoke-WebRequest `
  -Uri "https://gist.github.com/michele-tn/8a824d6257147718fd8384da0fa13f7a/raw/RustDeskPortable.ps1" `
  -OutFile "RustDeskPortable.ps1"

2. Run the Script

powershell.exe -ExecutionPolicy Bypass -File .\RustDeskPortable.ps1 `
  -ServerIP "rustdesk.yourdomain.com" `
  -Key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMyExampleKey1234567890..."

Or as a one-liner for deployment systems (RMM / GPO / Intune):

powershell.exe -ExecutionPolicy Bypass -NoProfile `
  -File "C:\Tools\RustDesk\RustDeskPortable.ps1" `
  -ServerIP "rustdesk.yourdomain.com" `
  -Key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMyExampleKey1234567890..."

Output Overview

After successful execution:

  • RustDeskPortable\rustdesk.exe downloaded
  • RustDeskPortable\update.log updated
  • %AppData%\RustDesk\config\RustDesk2.toml created
  • 🚀 RustDesk automatically launched and ready to use

Deployment Scenarios

You can automate this for:

  • Group Policy (GPO):
    Assign as a startup/logon script

  • RMM / MDM / Intune:
    Deploy remotely with PowerShell scripting

  • USB Toolkit:
    Carry and run from a USB drive for field operations


Troubleshooting

Problem Cause Solution
Download fails GitHub not reachable Check proxy/firewall or GitHub access
No portable exe found GitHub release format changed Verify latest release manually
Config not applied Existing TOML not replaced Script removes old config automatically
Connection error Wrong ServerIP or invalid Key Double-check your RustDesk server setup

Security Recommendations

  • Keep your public/private key pairs secure.
  • Use HTTPS for your RustDesk server.
  • Verify script integrity before deploying.
  • Restrict outbound access to trusted domains only.

Disclaimer

This script is provided "as-is", with no warranty.
Always test it in a controlled environment before mass deployment.


Author: Michele TN (original Gist)

@xman0980
Copy link

can you help me figure out this error when i try to run it?

At C:\Users\me\RustDeskPortable.ps1:174 char:71
+ ...   Write-Error "� Failed to start RustDesk: $($_.Exception.Message)"
+                                                                         ~
The string is missing the terminator: ".
At C:\Users\me\RustDeskPortable.ps1:159 char:5
+ try {
+     ~
Missing closing '}' in statement block or type definition.
At C:\Users\me\RustDeskPortable.ps1:176 char:2
+ }
+  ~
The Try statement is missing its Catch or Finally block.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString```

I've tried running it with the server and the key like 

```powershell.exe -ExecutionPolicy Bypass -File .\RustDeskPortable.ps1 `
  -ServerIP "rustdesk.yourdomain.com" `
  -Key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMyExampleKey1234567890..."```
but that also fails. so i put the server info in the script to try and it gives the same error. 
please advise.

@michele-tn
Copy link
Author

can you help me figure out this error when i try to run it?

At C:\Users\me\RustDeskPortable.ps1:174 char:71
+ ...   Write-Error "� Failed to start RustDesk: $($_.Exception.Message)"
+                                                                         ~
The string is missing the terminator: ".
At C:\Users\me\RustDeskPortable.ps1:159 char:5
+ try {
+     ~
Missing closing '}' in statement block or type definition.
At C:\Users\me\RustDeskPortable.ps1:176 char:2
+ }
+  ~
The Try statement is missing its Catch or Finally block.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString```

I've tried running it with the server and the key like 

```powershell.exe -ExecutionPolicy Bypass -File .\RustDeskPortable.ps1 `
  -ServerIP "rustdesk.yourdomain.com" `
  -Key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMyExampleKey1234567890..."```
but that also fails. so i put the server info in the script to try and it gives the same error. 
please advise.

Fixed Unicode and Parsing Issues in RustDeskPortable.ps1

The script has been cleaned to remove all non-ASCII/Unicode characters that were causing PowerShell parsing errors such as:

The string is missing the terminator: ". Missing closing '}' in statement block or type definition.
<#
RustDesk Portable (x64) Auto Downloader & Configurator
-----------------------------------------------------
• Downloads the latest RustDesk Windows x64 portable client from GitHub
• No installation (single .exe)
• Automatically sets:
  - ID server
  - Key
• Creates and updates a download log
• Launches RustDesk ready to use
#>

param(
 [string]$ServerIP = "192.168.1.100", # ID server (hbbs)
 [string]$Key = "MY_PUBLIC_KEY"       # Contenuto id_ed25519.pub (stringa completa)
)

# ----------------- ENVIRONMENT & TLS -----------------
try {
 [Net.ServicePointManager]::SecurityProtocol = `
   [Net.ServicePointManager]::SecurityProtocol -bor `
   [Net.SecurityProtocolType]::Tls12
} catch { }

$ErrorActionPreference = "Stop"

# ----------------- SCRIPT ROOT -----------------
if ($PSScriptRoot -and (Test-Path $PSScriptRoot)) {
 $scriptRoot = $PSScriptRoot
} elseif ($MyInvocation.MyCommand.Path) {
 $scriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
} else {
 $scriptRoot = Get-Location
}

# ----------------- PATHS -----------------
$baseFolder = Join-Path $scriptRoot "RustDeskPortable"
$exePath = Join-Path $baseFolder "rustdesk.exe"
$logPath = Join-Path $baseFolder "update.log"

$rustdeskConfigDir = Join-Path ([Environment]::GetFolderPath("ApplicationData")) "RustDesk\config"
$configPath = Join-Path $rustdeskConfigDir "RustDesk2.toml"

# Create folders
New-Item -ItemType Directory -Path $baseFolder -Force | Out-Null
New-Item -ItemType Directory -Path $rustdeskConfigDir -Force | Out-Null

$headers = @{ "User-Agent" = "PowerShell-RustDeskPortable" }

Write-Host "===> Fetching latest RustDesk tag from GitHub..." -ForegroundColor Cyan

# ----------------- FETCH LATEST TAG -----------------
$tagsUrl = "https://api.github.com/repos/rustdesk/rustdesk/tags"

try {
 $tags = Invoke-RestMethod -Uri $tagsUrl -Headers $headers
} catch {
 Write-Error "Failed to retrieve tags from GitHub: $($_.Exception.Message)"
 exit 1
}

if (-not $tags) {
 Write-Error "No tags found on GitHub repository rustdesk/rustdesk."
 exit 1
}

$latestTag = $tags[0].name
Write-Host "Latest tag detected: $latestTag" -ForegroundColor Green

# ----------------- FETCH RELEASE BY TAG -----------------
$releaseUrl = "https://api.github.com/repos/rustdesk/rustdesk/releases/tags/$latestTag"

try {
 $release = Invoke-RestMethod -Uri $releaseUrl -Headers $headers
} catch {
 Write-Error "Failed to retrieve release for tag '$latestTag': $($_.Exception.Message)"
 exit 1
}

if (-not $release.assets) {
 Write-Error "No assets found in release '$latestTag'."
 exit 1
}

# ----------------- SELECT PORTABLE X64 CLIENT -----------------
$asset = $release.assets | Where-Object {
 $_.name -match "^rustdesk-.*x86_64.*\.exe$" -and
 $_.name -notmatch "server" -and
 $_.name -notmatch "\.msi$"
} | Select-Object -First 1

if (-not $asset) {
 Write-Error "No suitable Windows x64 portable executable found for tag '$latestTag'."
 exit 1
}

$downloadUrl = $asset.browser_download_url
Write-Host "Download URL: $downloadUrl" -ForegroundColor Cyan

# ----------------- DOWNLOAD EXECUTABLE -----------------
try {
 Invoke-WebRequest -Uri $downloadUrl -OutFile $exePath -Headers $headers
} catch {
 Write-Error "Error while downloading RustDesk executable: $($_.Exception.Message)"
 exit 1
}

if (!(Test-Path $exePath)) {
 Write-Error "Download failed: file not found at '$exePath'."
 exit 1
}

Write-Host "Downloaded RustDesk executable to: $exePath" -ForegroundColor Green

# ----------------- WRITE CONFIG -----------------
if (Test-Path $configPath) {
 Remove-Item $configPath -Force -ErrorAction SilentlyContinue
}

$configContent = @"
rendezvous_server = '$ServerIP'
nat_type = 1
serial = 0
[options]
custom-rendezvous-server = '$ServerIP'
key = '$Key'
"@

try {
 $configContent | Set-Content -Path $configPath -Encoding UTF8
 Write-Host "Configuration written to: $configPath" -ForegroundColor Green
} catch {
 Write-Error "Failed to write configuration file: $($_.Exception.Message)"
 exit 1
}

# ----------------- WRITE / APPEND LOG -----------------
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logEntry = "[$timestamp] Tag: $latestTag | File: $($asset.name)"
try {
 Add-Content -Path $logPath -Value $logEntry
 Write-Host "Log updated: $logPath" -ForegroundColor Yellow
} catch {
 Write-Host "Could not update log file: $($_.Exception.Message)" -ForegroundColor DarkYellow
}

@xman0980
Copy link

xman0980 commented Jan 22, 2026

OMG thanks so much for fixing it. Now I have to figure out how to have CrowdStrike Falcon not block it when trying to run rustdesk.exe. Thanks corporate IT! LOL

@michele-tn
Copy link
Author

OMG thanks so much for fixing it. Now I have to figure out how to have CrowdStrike Falcon not block it when trying to run rustdesk.exe. Thanks corporate IT! LOL

I get the frustration 😄
That said, remote administration tools like RustDesk are powerful software and fall into some of the most sensitive categories from a security standpoint.
It’s therefore normal for EDR solutions like CrowdStrike to block them by default in corporate environments.
It’s not about “blocking things for no reason”, but about reducing risk: if these tools are genuinely needed, they should be properly reviewed, approved, and whitelisted according to company policies.
Cyber Security in the enterprise is not optional! ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment