How to schedule automatic reboots on Windows Server VPS
Schedule automatic reboots on Windows Server using Task Scheduler and PowerShell, with safe maintenance windows, RDP warnings, and auditable logs.
Windows servers running long-lived applications — IIS hosting APIs, .NET services, SQL Server instances, integration gateways — degrade gradually without reboots. Memory fragments, kernel handles accumulate, and pending updates remain in an intermediate state that only a reboot resolves. In production, the stable practice is to schedule periodic reboots during a low-traffic window.
This tutorial covers how to configure automatic reboots on a Windows Server VPS via Task Scheduler (graphical interface and command line) and via PowerShell. It also shows how to add warnings for active RDP sessions, abort conditions based on load, and auditable logs to confirm that each window executed. Estimated time: 25 minutes.
The audience is a Windows sysadmin who already has the server configured and wants to automate the maintenance cycle without depending on a manual connection at 4 AM on a Sunday.
Prerequisites
Windows Server 2019, 2022, or 2025 with administrative access (RDP or console). PowerShell 5.1 or higher (preinstalled). The account used to create the task needs the right to log on as a service and the privilege to shut down the system — local administrators have both by default.
Before starting, confirm the basic session data. These values are referenced in the commands below:
Windows Server 2022 Administrator PowerShell 5.1+ Sunday 04:00 Decision: Task Scheduler or PowerShell
There are two paths to schedule a reboot on Windows. Each one fits a scenario:
| Method | When to use | Limitation |
|---|---|---|
| Task Scheduler via GUI | One-off configuration, sysadmin prefers clicking | Hard to version and replicate |
| Task Scheduler via schtasks | Reproducible single script | Verbose syntax for complex conditions |
| PowerShell Register-ScheduledTask | Versioning, conditional logic, multiple servers | Steeper learning curve |
For a single server, Task Scheduler via GUI is enough. For a fleet of 5+ servers or if you use configuration as code, PowerShell is the way. We will cover all three methods — pick the one that fits.
Method 1: Task Scheduler via the graphical interface
The graphical interface is the fastest way for an isolated server. The steps below create a task that reboots the server every Sunday at 4 AM.
Open Task Scheduler. Press Win + R, type taskschd.msc, and press Enter.
In the right panel, click “Create Task” (not “Create Basic Task” — you need the advanced options).
On the “General” tab, fill in:
- Name:
Weekly Maintenance Reboot - Description:
Automatic maintenance reboot - Sunday 04:00 - Select “Run with highest privileges”
- In “Configure for”, select your Windows Server version
Check “Run whether user is logged on or not” — this guarantees execution even without an active RDP session.
“Triggers” tab → “New”. Configure:
- Begin the task: “On a schedule”
- Weekly, recur every 1 week
- Day: Sunday
- Time: 04:00:00
In advanced options, check “Enabled” and leave without expiration.
“Actions” tab → “New”. Configure:
- Action: “Start a program”
- Program/script:
shutdown.exe - Add arguments:
/r /t 600 /c "Automatic weekly maintenance" /f
The /r parameter forces a reboot (not shutdown), /t 600 gives a 10-minute warning to connected users, /c defines the visible message, and /f forces closing of unresponsive applications.
“Conditions” tab. Uncheck “Start the task only if the computer is idle” and “Start the task only if the computer is on AC power”. On a server, those conditions make no sense and can prevent execution.
“Settings” tab. Check “Allow task to be run on demand” and “If the task fails, restart every 1 minute, attempt to restart up to 3 times”.
Click OK. You will be prompted to enter the account password — provide it.
Right-click the created task and select “Run”. The reboot should fire with a visible warning. Reconnect afterward and confirm everything came back up. A task that was never tested manually tends to fail on the first scheduled execution.
Method 2: Creation via schtasks
To script the same schedule in a single line — useful in provisioning or to document configuration — use schtasks.
Open PowerShell as administrator (right-click → “Run as administrator”) and execute:
schtasks /create `
/tn "Weekly Maintenance Reboot" `
/tr "shutdown.exe /r /t 600 /c 'Automatic weekly maintenance' /f" `
/sc weekly /d SUN /st 04:00 `
/ru "SYSTEM" /rl HIGHEST /fThe /ru SYSTEM parameter avoids dependency on an account password — the task runs as system. /rl HIGHEST ensures elevated privileges, and /f overwrites the task if it already exists.
Verify that the task was created:
schtasks /query /tn "Weekly Maintenance Reboot" /v /fo LISTThe output shows the next run time, state, and last run. Confirm that “Next Run Time” falls on the next Sunday at 04:00.
Method 3: PowerShell with conditional logic
When you need more complex conditions — abort the reboot if CPU is above 80%, or if a critical service is in a transaction — wrap the logic in a script and schedule it via Register-ScheduledTask.
Create the wrapper script at C:\Scripts\weekly-reboot.ps1:
$LogPath = "C:\Scripts\weekly-reboot.log"
$Stamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
# Check average CPU load over the last 60s
$cpu = (Get-Counter '\Processor(_Total)\% Processor Time' `
-SampleInterval 5 -MaxSamples 12).CounterSamples |
Measure-Object -Property CookedValue -Average
if ($cpu.Average -gt 80) {
Add-Content $LogPath "$Stamp ABORT cpu=$([math]::Round($cpu.Average,1))%"
exit 1
}
# Check critical service (adjust the name)
$svc = Get-Service -Name "MyCriticalService" -ErrorAction SilentlyContinue
if ($svc -and $svc.Status -eq 'Running') {
# Application health-check logic here
Add-Content $LogPath "$Stamp OK service active, proceeding"
}
Add-Content $LogPath "$Stamp REBOOT starting shutdown /r /t 600"
Start-Process -FilePath "shutdown.exe" `
-ArgumentList "/r","/t","600","/c","Weekly maintenance","/f"This script writes each execution to a local log, checks the 1-minute average CPU, and only fires the reboot if the condition is safe. Adjust the service name and thresholds for your scenario.
Register the task via PowerShell:
$Action = New-ScheduledTaskAction `
-Execute "PowerShell.exe" `
-Argument "-ExecutionPolicy Bypass -File C:\Scripts\weekly-reboot.ps1"
$Trigger = New-ScheduledTaskTrigger `
-Weekly -DaysOfWeek Sunday -At 04:00
$Principal = New-ScheduledTaskPrincipal `
-UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
$Settings = New-ScheduledTaskSettingsSet `
-StartWhenAvailable -DontStopOnIdleEnd `
-RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1)
Register-ScheduledTask `
-TaskName "Weekly Maintenance Reboot" `
-Action $Action -Trigger $Trigger `
-Principal $Principal -Settings $Settings -ForceThe -StartWhenAvailable flag is important: if the server was off at the scheduled time and powers on later, the task runs at the next opportunity instead of skipping.
Commit weekly-reboot.ps1 to a configuration repository for your infra. When you need to adjust the CPU threshold or add a new condition, edit once and replicate via Group Policy or Ansible. Configuration scattered across GUIs becomes technical debt in fleets of 5+ servers.
Verification
Confirm that the task is active and the next run time is correct:
Get-ScheduledTask -TaskName "Weekly Maintenance Reboot" |
Select-Object TaskName, State, @{N='Next';E={
(Get-ScheduledTaskInfo $_).NextRunTime
}}
Expected output:
TaskName State Next
-------- ----- -------
Weekly Maintenance Reboot Ready 6/1/2026 4:00:00 AM
To confirm that the task ran after the first Sunday, query the history:
Get-ScheduledTaskInfo -TaskName "Weekly Maintenance Reboot"
The LastRunTime field shows when it ran and LastTaskResult should be 0 (success). Any different value indicates failure — investigate via Task Scheduler → History or via Get-WinEvent on the “Microsoft-Windows-TaskScheduler/Operational” log.
Troubleshooting
Task does not run, no error message
Check whether Task Scheduler history is enabled. By default, on some Windows Server installations it comes disabled, which prevents you from seeing what happened. In the right panel of Task Scheduler, click “Enable All Tasks History”.
After that, open the task and check the History tab. If the event is “Task did not start because the account is not logged on” — you forgot to check “Run whether user is logged on or not” during creation.
Reboot fires but the server does not come back up
Check whether any service with automatic startup is failing on boot. Run after reconnecting:
Get-EventLog -LogName System -EntryType Error -Newest 20 |
Where-Object {$_.Source -like "*Service*"}
A service stuck in “Starting” indefinitely is the most common cause. It is usually a network or database dependency that has not stabilized yet — add a delay to the startup of the problematic service.
If the server enters a reboot loop, connect via the console (not RDP) and disable the task before anything else: Disable-ScheduledTask -TaskName "Weekly Maintenance Reboot". On a VPS, the console is the access via the control panel — RDP will not work if the machine reboots before the network comes up.
Reboot warning does not appear to RDP users
The /c "message" parameter only works if the user has an active session at the moment shutdown /t 600 runs. If they connect after the trigger, nothing is shown. For proactive notification, add before the shutdown:
msg * /TIME:60 "Scheduled reboot in 10 minutes - save your work"
msg.exe broadcasts to all active sessions — combined with the visual warning from shutdown, it covers both cases.
Next steps
With the reboot cycle automated, it is worth evolving in complementary directions:
- Configure a post-reboot health check via PowerShell that validates critical services and sends an alert if something did not come up in 5 minutes.
- Add event log writes (
Write-EventLog) in the wrapper script to centralize via syslog or SIEM. - Document the maintenance window on an internal status page so the application team knows when to expect downtime.
- Combine with automatic pre-reboot snapshots via your provider’s API for quick rollback if something breaks.
- Consider scheduling Windows Update to run before the reboot, ensuring the cycle covers pending updates.
If you are putting this in production, a Hostini VPS running Windows Server already includes an out-of-band console in the panel — useful for recovering access if a scheduled reboot breaks the network and RDP becomes unavailable, avoiding having to rely on support to reset the machine.
Frequently asked questions
Can I schedule a reboot without disconnecting RDP users immediately?
Yes. The /t parameter of shutdown sets a delay in seconds before the actual reboot, during which connected users receive a visual warning. Use /t 600 to give a 10-minute margin. Combine with /c "message" to explain the reason in the notification.
How do I prevent the scheduled reboot from firing if the server is under heavy load?
Add a trigger condition that checks the average CPU usage over the last minute via PowerShell before Restart-Computer. If it exceeds a threshold, write to the event log and abort. Task Scheduler lets you run a wrapper script instead of shutdown directly.
Windows Update schedules reboots on its own — do I need to disable that?
On Windows Server, automatic updates usually respect active hours and do not restart on their own if you use WSUS or manual scheduling. Even so, configure the "No auto-restart with logged on users" policy to make sure only your task controls when the reboot happens.
How do I verify that the task actually ran last week?
Open Task Scheduler, select the task, and click the History tab — each execution is recorded with timestamp and exit code. For persistent auditing, enable event log writes in the script (Write-EventLog) and query via Get-WinEvent.
Can I skip the scheduled reboot if a critical service is in an active transaction?
Yes, but you need a wrapper script. Before Restart-Computer, query the service state (Get-Service, Get-Process, or an application health-check API) and return without rebooting if the condition does not hold. Log the decision so you can trace it later.
What is the real impact of not rebooting a Windows Server for months?
Memory fragments, kernel handles accumulate, non-paged pool grows, and pending updates stay in an intermediate state. Long-uptime .NET applications show noticeable degradation after 30-60 days. Weekly or biweekly reboots are the common balance in production.