NinjaOne RMM Platform Setup
Deploy a complete NinjaOne Remote Monitoring and Management platform for IT operations or MSP service delivery. This project covers the full implementation from tenant configuration through advanced automation.
Project Overview
What We're Building
┌─────────────────────────────────────────────────────────────────────┐
│ NinjaOne Platform Architecture │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ NinjaOne Cloud │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Tenant │ │ Policies │ │ Scripts │ │ │
│ │ │ Config │ │ Engine │ │ Library │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────┼────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Organization│ │ Organization│ │ Organization│ │
│ │ Client A │ │ Client B │ │ Internal │ │
│ │ │ │ │ │ IT │ │
│ │ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │
│ │ │Servers │ │ │ │Servers │ │ │ │Servers │ │ │
│ │ │(15) │ │ │ │(25) │ │ │ │(50) │ │ │
│ │ ├─────────┤ │ │ ├─────────┤ │ │ ├─────────┤ │ │
│ │ │Workstns │ │ │ │Workstns │ │ │ │Workstns │ │ │
│ │ │(75) │ │ │ │(150) │ │ │ │(300) │ │ │
│ │ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘Prerequisites
- NinjaOne subscription
- Admin access to NinjaOne dashboard
- Windows/macOS/Linux endpoints to manage
- Network access from endpoints to NinjaOne cloud
- Documentation system (IT Glue, Hudu, etc. - optional)
Part 1: Organization and Structure
Step 1: Organization Hierarchy Design
Recommended Structure:
NinjaOne Tenant
├── Organizations (Clients/Departments)
│ ├── Client A Inc
│ │ ├── Location: Headquarters
│ │ └── Location: Branch Office
│ ├── Client B Corp
│ └── Internal IT
├── Policies
│ ├── Windows-Servers
│ ├── Windows-Workstations
│ ├── macOS-Workstations
│ └── Linux-Servers
└── Scripts
├── Remediation
├── Maintenance
└── InventoryStep 2: Create Organizations
- Navigate to Administration → Organizations
- Click Add Organization
- Configure:
- Organization Name
- Description
- Tags (industry, SLA tier, etc.)
- Contact information
Step 3: Configure Roles and Permissions
Create Custom Roles:
| Role Name | Permissions | Use Case |
|---|---|---|
| Help Desk L1 | View devices, Run approved scripts | Tier 1 support |
| Help Desk L2 | Above + Remote access, Install software | Tier 2 support |
| Admin | Full device control, Policy management | System admins |
| Read Only | View only, Report access | Executives, Auditors |
Configure in: Administration → Roles
Part 2: Policy Configuration
Step 4: Create Windows Server Policy
Navigate to: Administration → Policies → Add Policy
Windows Server Policy Configuration:
Policy Name: Windows-Server-Production
Applies To: Windows Servers
Agent Settings:
Check-in Interval: 1 minute
Heartbeat Timeout: 5 minutes
Proxy Mode: Disabled
Monitoring:
CPU Alert: > 90% for 15 minutes
Memory Alert: > 95% for 10 minutes
Disk Space Alert: < 10% free
Service Monitoring:
- Windows Update
- DNS Server
- DHCP Server
- Active Directory Domain Services
Event Log Monitoring:
- Security: Failed logins (4625)
- System: Service crashes (7034)
- Application: Errors
Patch Management:
Scan Schedule: Daily at 2 AM
Approval: Auto-approve security patches
Install Window: Saturday 2 AM - 6 AM
Reboot Behavior: Prompt user (servers require approval)
Backup Monitoring:
Check for: Last backup within 24 hours
Alert on: Backup failure
Antivirus:
Scan Schedule: Weekly full scan Sunday 3 AM
Real-time Protection: EnabledStep 5: Create Windows Workstation Policy
Policy Name: Windows-Workstation-Standard
Applies To: Windows Workstations
Agent Settings:
Check-in Interval: 5 minutes
Heartbeat Timeout: 15 minutes
Monitoring:
CPU Alert: > 95% for 30 minutes
Memory Alert: > 95% for 30 minutes
Disk Space Alert: < 15% free
Disk Health: SMART monitoring enabled
Patch Management:
Scan Schedule: Daily at 12 PM
Approval: Auto-approve all (workstations)
Install Window: Tuesday - Friday, 12 PM - 2 PM
Reboot Behavior: Prompt user, force after 3 days
Software Updates:
Chrome: Auto-update enabled
Firefox: Auto-update enabled
Adobe Reader: Auto-update enabled
Zoom: Auto-update enabled
Security:
BitLocker: Alert if not enabled
Windows Defender: Verify enabled
Firewall: Verify enabledStep 6: Create macOS Policy
Policy Name: macOS-Workstation
Applies To: macOS Devices
Monitoring:
CPU Alert: > 90% for 30 minutes
Memory Alert: > 90% for 30 minutes
Disk Space Alert: < 15% free
Patch Management:
macOS Updates: Notify and install
App Updates: Automatic via MDM
Security:
FileVault: Alert if not enabled
Firewall: Alert if not enabled
Gatekeeper: Verify enabledStep 7: Create Linux Policy
Policy Name: Linux-Server
Applies To: Linux Servers
Monitoring:
CPU Alert: > 95% for 10 minutes
Memory Alert: > 95% for 10 minutes
Disk Space Alert: < 10% free
Service Monitoring:
- sshd
- httpd/nginx
- mysqld/postgresql
- docker
Patch Management:
Package Manager: Detect (apt/yum/dnf)
Scan Schedule: Daily at 4 AM
Install: Manual approval requiredPart 3: Patch Management
Step 8: Configure Patch Management Settings
Navigate to: Administration → Policies → Patch Management
Approval Workflow:
Patch Released
│
▼
┌───────────────┐
│ Auto-Approve? │
└───────┬───────┘
│
┌──────────┴──────────┐
│ │
┌────▼────┐ ┌─────▼────┐
│Critical │ │ Other │
│Security │ │ Updates │
└────┬────┘ └─────┬────┘
│ │
▼ ▼
Auto-Approve Review Queue
│ │
└─────────┬───────────┘
│
▼
┌─────────────────┐
│ Install Window │
│ (Policy Based) │
└─────────────────┘Approval Rules:
| Category | Auto-Approve | Review |
|---|---|---|
| Critical Security | Yes (immediate) | No |
| Security | Yes (24hr delay) | No |
| Feature Updates | No | Yes |
| Driver Updates | No | Yes |
| Definition Updates | Yes | No |
Step 9: Create Maintenance Windows
Server Maintenance Window:
Name: Server-Weekly-Maintenance
Schedule: Saturday 2:00 AM - 6:00 AM
Applies To: Windows-Server-Production policy
Actions:
- Install approved patches
- Reboot if required
- Run maintenance scriptsWorkstation Maintenance:
Name: Workstation-Daily-Patching
Schedule: Tuesday-Friday 12:00 PM - 2:00 PM
Applies To: Windows-Workstation-Standard policy
Actions:
- Install approved patches
- Prompt for reboot (defer up to 3 days)Part 4: Scripting and Automation
Step 10: Build Script Library
Navigate to: Administration → Library → Scripting
Script Categories:
Script Library/
├── Remediation/
│ ├── Restart-PrintSpooler.ps1
│ ├── Clear-BrowserCache.ps1
│ ├── Reset-NetworkStack.ps1
│ └── Repair-WindowsUpdate.ps1
├── Inventory/
│ ├── Get-InstalledSoftware.ps1
│ ├── Get-LocalAdmins.ps1
│ ├── Get-BitLockerStatus.ps1
│ └── Get-DiskHealth.ps1
├── Maintenance/
│ ├── Clear-TempFiles.ps1
│ ├── Optimize-Disk.ps1
│ └── Update-Defender.ps1
└── Security/
├── Set-PasswordPolicy.ps1
├── Disable-LegacyProtocols.ps1
└── Enable-Firewall.ps1Step 11: Create Core Scripts
System Health Check Script:
<#
.SYNOPSIS
Comprehensive system health check for NinjaOne custom fields.
.NOTES
Run As: SYSTEM
Schedule: Daily
#>
# Initialize results
$healthStatus = "Healthy"
$issues = @()
# Check disk space
$disk = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='C:'"
$freeGB = [math]::Round($disk.FreeSpace / 1GB, 2)
$freePercent = [math]::Round(($disk.FreeSpace / $disk.Size) * 100, 1)
if ($freePercent -lt 10) {
$healthStatus = "Critical"
$issues += "Low disk space: $freePercent% free"
} elseif ($freePercent -lt 20) {
$healthStatus = "Warning"
$issues += "Disk space warning: $freePercent% free"
}
Ninja-Property-Set diskFreeGB $freeGB
Ninja-Property-Set diskFreePercent $freePercent
# Check uptime
$os = Get-CimInstance Win32_OperatingSystem
$uptime = (Get-Date) - $os.LastBootUpTime
$uptimeDays = [math]::Round($uptime.TotalDays, 1)
if ($uptimeDays -gt 30) {
if ($healthStatus -ne "Critical") { $healthStatus = "Warning" }
$issues += "High uptime: $uptimeDays days"
}
Ninja-Property-Set uptimeDays $uptimeDays
Ninja-Property-Set lastReboot $os.LastBootUpTime.ToString("yyyy-MM-dd HH:mm")
# Check Windows Defender
$defenderStatus = Get-MpComputerStatus -ErrorAction SilentlyContinue
if ($defenderStatus) {
if (-not $defenderStatus.RealTimeProtectionEnabled) {
$healthStatus = "Critical"
$issues += "Real-time protection disabled"
}
$signatureAge = ((Get-Date) - $defenderStatus.AntivirusSignatureLastUpdated).Days
if ($signatureAge -gt 3) {
if ($healthStatus -ne "Critical") { $healthStatus = "Warning" }
$issues += "AV signatures $signatureAge days old"
}
Ninja-Property-Set defenderSignatureAge $signatureAge
}
# Check BitLocker
try {
$bitlocker = Get-BitLockerVolume -MountPoint "C:" -ErrorAction Stop
$blStatus = if ($bitlocker.VolumeStatus -eq "FullyEncrypted") { "Enabled" } else { "Disabled" }
Ninja-Property-Set bitlockerStatus $blStatus
if ($blStatus -ne "Enabled") {
$issues += "BitLocker not enabled"
}
} catch {
Ninja-Property-Set bitlockerStatus "NotSupported"
}
# Check pending updates
try {
$updateSession = New-Object -ComObject Microsoft.Update.Session
$searcher = $updateSession.CreateUpdateSearcher()
$results = $searcher.Search("IsInstalled=0 AND IsHidden=0")
$pendingCount = $results.Updates.Count
Ninja-Property-Set pendingUpdates $pendingCount
if ($pendingCount -gt 10) {
if ($healthStatus -ne "Critical") { $healthStatus = "Warning" }
$issues += "$pendingCount pending updates"
}
} catch {
Ninja-Property-Set pendingUpdates -1
}
# Set overall health status
Ninja-Property-Set healthStatus $healthStatus
Ninja-Property-Set healthIssues ($issues -join "; ")
# Output summary
Write-Output "Health Status: $healthStatus"
Write-Output "Issues: $($issues.Count)"
foreach ($issue in $issues) {
Write-Output " - $issue"
}Software Inventory Script:
<#
.SYNOPSIS
Collect installed software inventory.
.NOTES
Run As: SYSTEM
Schedule: Weekly
#>
$software = @()
# Get installed software from registry
$paths = @(
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
)
foreach ($path in $paths) {
$software += Get-ItemProperty $path -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName } |
Select-Object @{N='Name'; E={$_.DisplayName}},
@{N='Version'; E={$_.DisplayVersion}},
@{N='Publisher'; E={$_.Publisher}},
@{N='InstallDate'; E={$_.InstallDate}}
}
# Remove duplicates
$software = $software | Sort-Object Name -Unique
# Format for custom field (limited size)
$topSoftware = $software | Select-Object -First 50 | ForEach-Object {
"$($_.Name) v$($_.Version)"
}
Ninja-Property-Set softwareCount $software.Count
Ninja-Property-Set softwareList ($topSoftware -join "`n")
Write-Output "Installed Software: $($software.Count) items"
$software | Format-Table Name, Version, Publisher -AutoSizeStep 12: Create Condition-Based Automation
Navigate to: Administration → Policies → Conditions
Low Disk Space Remediation:
Condition Name: Low-Disk-Space-Remediation
Trigger: Custom Field "diskFreePercent" < 15
Action: Run Script "Clear-TempFiles.ps1"
Notification: Email IT TeamService Not Running:
Condition Name: Critical-Service-Down
Trigger: Service "Spooler" not running
Action: Run Script "Restart-Service.ps1" -ServiceName Spooler
Notification: Create ticket (if integrated)Part 5: Alerting and Notifications
Step 13: Configure Alert Channels
Navigate to: Administration → Channels
Email Channel:
Channel Name: IT-Team-Email
Type: Email
Recipients:
- it-team@company.com
- oncall@company.comSlack/Teams Integration:
Channel Name: IT-Alerts-Slack
Type: Webhook
URL: https://hooks.slack.com/services/XXX/YYY/ZZZ
Format: JSONStep 14: Create Alert Rules
Critical Server Alerts:
Alert Name: Server-Critical-Alerts
Applies To: Windows-Server-Production
Conditions:
- CPU > 95% for 10 minutes
- Memory > 98% for 5 minutes
- Disk < 5% free
- Service down (critical services)
- Device offline > 10 minutes
Priority: Critical
Channels: IT-Team-Email, IT-Alerts-SlackWorkstation Alerts:
Alert Name: Workstation-Alerts
Applies To: Windows-Workstation-Standard
Conditions:
- Disk < 10% free
- Device offline > 4 hours
- Security software disabled
Priority: Warning
Channels: IT-Team-EmailPart 6: Documentation Integration
Step 15: Connect IT Glue/Hudu
IT Glue Integration:
- Navigate to Administration → Apps → IT Glue
- Enter API credentials
- Configure sync settings:
- Organizations: Auto-match by name
- Configurations: Sync device details
- Passwords: Sync credentials
- Documents: Link to procedures
Hudu Integration:
- Navigate to Administration → Apps → Hudu
- Configure API connection
- Map organizations
Step 16: Configure Documentation Sync
Sync Settings:
Organizations: Bi-directional
Devices:
- Sync to IT Glue/Hudu: Yes
- Fields: Name, OS, IP, MAC, Serial, User
- Update Frequency: Daily
Credentials:
- Sync passwords: Yes (local admin, etc.)Part 7: Reporting
Step 17: Configure Standard Reports
Navigate to: Administration → Reports
Executive Summary Report:
Report Name: Monthly-Executive-Summary
Schedule: 1st of month at 8 AM
Recipients: executives@company.com
Content:
- Device count by organization
- Alert summary
- Patch compliance percentage
- Uptime statistics
- Ticket summary (if PSA connected)Technical Operations Report:
Report Name: Weekly-Operations
Schedule: Monday 7 AM
Recipients: it-team@company.com
Content:
- Devices with issues
- Patch status by organization
- Failed scripts
- Offline devices
- Upcoming maintenanceStep 18: Create Custom Dashboards
Build Dashboard Views:
- Navigate to Dashboard
- Add widgets:
- Device count by OS
- Alert trends (7 days)
- Patch compliance gauge
- Top issues by category
- Devices needing attention
Verification Checklist
Organizations:
- All organizations created with correct structure
- Roles and permissions configured
- User accounts created with appropriate access
Policies:
- Server policy configured and tested
- Workstation policy configured and tested
- macOS policy configured (if applicable)
- Linux policy configured (if applicable)
Patch Management:
- Approval rules configured
- Maintenance windows scheduled
- Test patch deployment successful
Automation:
- Core scripts uploaded and tested
- Custom fields created
- Condition-based automation working
- Scheduled scripts running
Monitoring:
- Alerts configured for critical events
- Notification channels tested
- Escalation procedures documented
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| Agent not checking in | Network/firewall | Allow NinjaOne cloud URLs |
| Scripts failing | Execution policy | Set to RemoteSigned |
| Patches not installing | Maintenance window | Check schedule and policy |
| Custom fields empty | Script error | Check script logs |
Resources
Questions? Reach out in our community Discord!