Restic — Emergency Interim Backup: Deployment & Restore (T3 Only)
T3 / CODE COMMANDERS ONLY — DO NOT ATTEMPT BELOW T3
This procedure deploys a non-standard backup tool into a production client environment, handles client-encryption keys that have no recovery path, and touches domain controllers and PHI-bearing volumes. A mistake here produces a backup that appears to work and cannot be restored from.
If you are T1 or T2 and a client has no working backup: escalate to T3 immediately. Do not attempt this page.
Audience: T3 / Code Commanders
Use when: NinjaOne Backup has stopped capturing both the local and cloud legs on a host, the root cause is not resolvable within the current maintenance window, and the host is left with no backup coverage.
Origin: Halo 1170038 — Lockhart clone-mode deactivation left a domain controller with 47 days of no backup and no onsite BDR.
1. Purpose & Scope
Restic is a break-glass bridge, not a backup platform. It exists to stop the bleeding on a host that currently has nothing, while the underlying NinjaOne fault is worked with the vendor. DTC's standard remains NinjaOne Hybrid Cloud Backup per page 1421.
Deploy restic only when all of the following are true:
- NinjaOne Backup is producing no usable local and no usable cloud copy on the host
- No Veeam BDR or other secondary backup covers the host
- The fault cannot be resolved today — vendor case open, or remediation gated on a maintenance window
- The host holds data whose loss would be materially damaging to the client
Do not deploy restic when:
- NinjaOne is failing only the cloud leg and the local NAS copy is current — that is a degraded state, not an outage
- A Veeam BDR at the site is protecting the host
- The NinjaOne fault has a known same-day fix (see the NinjaOne error pages in this book)
- You have not yet opened a NinjaOne support case
Every restic deployment carries an obligation to pressure the vendor. A NinjaOne case must be open before deployment and must be actively pursued afterwards. Restic is not a resting place. Review the deployment against its exit criteria at least weekly (Section 12).
2. What This Is Not — Read Before Deploying
These limitations are not caveats. They change what recovery is possible, and the client's risk position must be understood in these terms.
Limitation | Consequence |
|---|---|
File-level, not image-level | No bare-metal recovery. Total loss of the host requires a full OS rebuild, role reinstall, and LOB application reinstall before any data can be restored. Recovery time is measured in days, not hours. |
Not a supported AD restore path | VSS produces consistent NTDS files, but Microsoft's supported domain controller recovery is System State or BMR restored into DSRM. On a multi-DC domain, restoring AD files over a live DC risks USN rollback and silent replication corruption. |
Unmonitored | No RMM visibility, no alerting, no integration with backup health checks. Silent failure surfaces nowhere. Verification is manual and is your responsibility. |
Encryption key has no recovery | Losing the repository password renders every snapshot permanently unrecoverable. There is no reset, no escrow, and no vendor recovery. |
Unverified until restore-tested | A completed backup is not confirmed recovery capability. Section 9 is mandatory, not optional. |
3. Architecture
Two repositories, same encryption password, one client:
[ <SERVER01> ]
|
| restic backup --use-fs-snapshot (VSS, nightly)
v
[ \\<NAS>\backups\restic ] <-- primary, fast restore, on-site
|
| restic copy (deduplicated block transfer, nightly)
v
[ s3:s3.<REGION>.backblazeb2.com/<BUCKET> ] <-- offsite, survives site loss
Why copy rather than back up twice: the NAS repository is already deduplicated and compressed. restic copy transfers only blocks the destination lacks, avoiding a second VSS snapshot and a second full read of the source volumes. On a production server that difference is hours of avoided I/O.
Why both: the emergency this page addresses is NinjaOne failing to capture local and cloud. A NAS-only interim repeats that single point of failure — a site-level event would take the interim backup with it.
Backblaze B2 via the S3-compatible API, not the native B2 backend. Restic's own documentation recommends the S3 path because of error-handling deficiencies in the B2 library restic uses. Repository strings are therefore s3:, never b2:.
4. Prerequisites
- Elevated PowerShell on the target host (VSS snapshot creation fails without it)
- 64-bit restic binary on a 64-bit OS — restic checks that its architecture matches the OS before using VSS
- Site NAS reachable on TCP 445 with writable share
- NAS service account credentials from IT Glue under the site's NAS asset
- Backblaze B2 console access
- Free space on the NAS destination — check before committing (Section 5.3)
- Open NinjaOne support case
NinjaOne will not give you the NAS password. The credentialId in a Lockhart policy is an internal reference, not a retrievable secret. Do not waste time in the NinjaOne console — go to IT Glue.
5. Deployment
5.1 — Install restic
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$dir = "C:\Program Files\restic"
New-Item -ItemType Directory -Path $dir -Force | Out-Null
$rel = Invoke-RestMethod "https://api.github.com/repos/restic/restic/releases/latest"
$asset = $rel.assets | Where-Object { $_.name -like "*windows_amd64.zip" } | Select-Object -First 1
"Release: $($rel.tag_name) Asset: $($asset.name)"
Invoke-WebRequest -Uri $asset.browser_download_url -OutFile "$env:TEMP\restic.zip"
Expand-Archive "$env:TEMP\restic.zip" -DestinationPath "$env:TEMP\resticx" -Force
Get-ChildItem "$env:TEMP\resticx" -Filter *.exe | Move-Item -Destination "$dir\restic.exe" -Force
Remove-Item "$env:TEMP\restic.zip","$env:TEMP\resticx" -Recurse -Force
& "$dir\restic.exe" version
Confirm the output reads windows/amd64. Record the version — it goes in the tracking sheet and the ticket.
5.2 — Generate and protect the repository password
$cfg = "C:\ProgramData\restic"
New-Item -ItemType Directory -Path $cfg -Force | Out-Null
New-Item -ItemType Directory -Path "$cfg\logs" -Force | Out-Null
$bytes = New-Object byte[] 32
[Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
$pw = [Convert]::ToBase64String($bytes)
[IO.File]::WriteAllText("$cfg\repo.pw", $pw, (New-Object Text.UTF8Encoding($false)))
icacls "$cfg\repo.pw" /inheritance:r /grant:r "SYSTEM:(F)" "BUILTIN\Administrators:(F)" | Out-Null
icacls "$cfg\repo.pw"
Write-Output ""
Write-Output "REPO PASSWORD - store in IT Glue now:"
Write-Output $pw
STOP. Put this password in IT Glue before running anything else. Once data is written, losing it means losing every snapshot in both repositories. There is no recovery path. Store under the client's asset, labelled with the hostname.
The same password is used for both repositories — one secret per client, one thing to get right during an incident. The trade-off is accepted: anyone who can read the ACL-protected file on the host can also read the B2 key stored alongside it.
5.3 — Initialise the NAS repository
$env:RESTIC_REPOSITORY = "\\<NAS>\backups\restic"
$env:RESTIC_PASSWORD_FILE = "C:\ProgramData\restic\repo.pw"
Test-Path "\\<NAS>\backups"
Get-PSDrive C,D | Select-Object Name,
@{N='UsedGB';E={[math]::Round($_.Used/1GB,1)}},
@{N='FreeGB';E={[math]::Round($_.Free/1GB,1)}}
$fso = New-Object -ComObject Scripting.FileSystemObject
$d = $fso.GetDrive("\\<NAS>\backups")
[PSCustomObject]@{
FreeGB = [math]::Round($d.FreeSpace/1GB,1)
TotalGB = [math]::Round($d.TotalSize/1GB,1)
}
& "C:\Program Files\restic\restic.exe" init
Space gate: restic deduplicates and compresses, so consumption lands well below raw source size — but do not proceed on a destination with less free space than roughly 60% of source used capacity without a deliberate decision. Record the pre-deployment free space; it goes in the tracking sheet.
Record the repository ID from the init output.
Note: Get-PSDrive against a UNC root does not populate Used/Free. The FileSystemObject COM method above is required for network destinations.
5.4 — Exclude file
$cfg = "C:\ProgramData\restic"
@'
# --- Volatile system files (cannot be restored, change constantly) ---
C:\pagefile.sys
C:\hiberfil.sys
C:\swapfile.sys
D:\pagefile.sys
D:\hiberfil.sys
D:\swapfile.sys
# --- Windows internals ---
C:\System Volume Information
D:\System Volume Information
C:\$RECYCLE.BIN
D:\$RECYCLE.BIN
C:\Recovery
C:\$WinREAgent
C:\Windows\CSC
C:\Windows\Prefetch
# --- Temp and caches ---
C:\Windows\Temp
C:\Windows\SoftwareDistribution\Download
C:\Users\*\AppData\Local\Temp
C:\Users\*\AppData\Local\CrashDumps
C:\Users\*\AppData\Local\Microsoft\Windows\INetCache
C:\Users\*\AppData\Local\Microsoft\Windows\WebCache
# --- Crash dumps ---
C:\Windows\MEMORY.DMP
C:\Windows\Minidump
# --- Restic's own password file (lives in IT Glue) ---
C:\ProgramData\restic\repo.pw
'@ | Set-Content "$cfg\excludes.txt" -Encoding UTF8
Get-Content "$cfg\excludes.txt" | Measure-Object -Line
Deliberately NOT excluded, and do not add them:
C:\Windows\NTDSandC:\Windows\SYSVOL— the AD database and policy store. Excluding these makes the backup worthless on a domain controller.C:\Windows\WinSxS— bulky, but restic deduplicates it and removing it breaks any OS repair path.Program FilesandProgram Files (x86)— LOB applications frequently store working data and configuration inside their install directories.
Adjust volume letters to the host. Enumerate fixed disks first — the drive admin shares (C$, D$, …) from Get-SmbShare are a reliable cross-check that no root volume has been missed.
5.5 — First full backup
$env:RESTIC_REPOSITORY = "\\<NAS>\backups\restic"
$env:RESTIC_PASSWORD_FILE = "C:\ProgramData\restic\repo.pw"
& "C:\Program Files\restic\restic.exe" backup C:\ D:\ `
--use-fs-snapshot `
--exclude-file "C:\ProgramData\restic\excludes.txt" `
--tag interim-<TICKET>
Flag / behaviour | Why |
|---|---|
| Creates a VSS snapshot per volume and reads from it, allowing capture of files exclusively locked by another process — databases, NTDS, LOB data stores. Without this the backup is worthless. |
omitted | Deliberate. Verbose streams every filename processed, which on a clinical file server means PHI-bearing paths in console output and logs. Omit it. |
VSS timeout | Default is 120 seconds. If snapshot creation fails on a busy server, add
. Do not add it pre-emptively. |
Session persistence | Restic runs in the foreground and dies with its parent shell. If the RDP session drops, the run dies. It is resumable — rerun the identical command and it continues from existing packs. |
Mid-run state | Restic writes the snapshot object last. During a run,
legitimately returns zero. An empty repository mid-run is not evidence of failure. |
Expect hours on a first full over SMB. Record the summary output — files processed, data added, duration, snapshot ID.
5.6 — Backblaze B2 bucket and key
Performed in the Backblaze B2 web console, not S3 Browser — application keys cannot be created in S3 Browser, and a key is required before any S3 client can connect.
Bucket — B2 console → Buckets → Create a Bucket:
- Private. Never place a restic repository in a public bucket; repository structure, snapshot counts, sizes and timing would be world-readable even though contents are encrypted.
- One bucket per client. A key scoped to a single bucket cannot reach another client's data — this isolation is the point.
- Object Lock disabled unless there is a specific requirement
- SSE-B2 default encryption is optional — restic already encrypts client-side, so this is a second layer, not the primary one
- B2 bucket names are globally unique across all of Backblaze. A bare client name will collide; prefix it.
- Record the Endpoint shown on the bucket page (e.g.
s3.us-west-002.backblazeb2.com). The digits vary by account. A wrong endpoint is the most common cause of "bucket not found".
Application key — B2 console → Application Keys → Add a New Application Key:
Field | Value |
|---|---|
Name of Key |
— letters, numbers and hyphens only |
Allow access to Bucket(s) | The client's bucket. Not "All". |
Type of Access | Read and Write. Restic reads the repository index before every write — Read Only cannot back up. |
Allow List All Bucket Names | Ticked. Required for the S3 List Buckets operation, which restic's S3 backend performs. |
File name prefix | Blank — dedicated bucket, no prefix needed |
Duration (seconds) | Blank. A duration sets the key to expire, and when it does the backup stops silently. Never set one. |
The application key is displayed exactly once. Copy it to IT Glue before leaving the page. The keyID is retrievable later; the secret is not. If lost, delete the key and create a replacement.
The Master Application Key does not work with the S3-compatible API. It must be a purpose-created key.
5.7 — Initialise the B2 repository and seed it
$R = "C:\Program Files\restic\restic.exe"
$env:RESTIC_PASSWORD_FILE = "C:\ProgramData\restic\repo.pw"
# Confirm the NAS repo holds a completed snapshot before proceeding
$env:RESTIC_REPOSITORY = "\\<NAS>\backups\restic"
& $R snapshots
& $R stats --mode raw-data
# Initialise B2, matching chunker parameters to the NAS repository
$env:AWS_ACCESS_KEY_ID = "<keyID>"
$env:AWS_SECRET_ACCESS_KEY = "<applicationKey>"
$env:RESTIC_REPOSITORY = "s3:s3.<REGION>.backblazeb2.com/<BUCKET>"
& $R init --from-repo "\\<NAS>\backups\restic" --copy-chunker-params
# Seed the offsite copy
& $R copy --from-repo "\\<NAS>\backups\restic"
--copy-chunker-params is mandatory. Without it the two repositories chunk data differently and every subsequent restic copy re-uploads the entire dataset from scratch instead of transferring deduplicated blocks.
restic stats --mode raw-data against the NAS repository gives the actual upload volume for B2. Check it against the site's upstream bandwidth before committing to the seed — this is the decision point on whether the site can carry an offsite copy at all.
Repository URLs are path-style only (endpoint/bucket). Virtual-host style (bucket.endpoint) is not supported. If init fails with bucket-not-found, try the bucket name in lowercase — the B2 console displays mixed case but the S3 API path may not accept it.
6. Automation
6.1 — Environment file
$cfg = "C:\ProgramData\restic"
@'
$env:RESTIC_PASSWORD_FILE = "C:\ProgramData\restic\repo.pw"
$env:RESTIC_REPO_NAS = "\\<NAS>\backups\restic"
$env:RESTIC_REPO_B2 = "s3:s3.<REGION>.backblazeb2.com/<BUCKET>"
$env:AWS_ACCESS_KEY_ID = "<keyID>"
$env:AWS_SECRET_ACCESS_KEY = "<applicationKey>"
$env:RESTIC_BIN = "C:\Program Files\restic\restic.exe"
$env:RESTIC_EXCLUDES = "C:\ProgramData\restic\excludes.txt"
$env:RESTIC_TAG = "interim-<TICKET>"
'@ | Set-Content "$cfg\restic-env.ps1" -Encoding UTF8
icacls "$cfg\restic-env.ps1" /inheritance:r /grant:r "SYSTEM:(F)" "BUILTIN\Administrators:(F)" "<DOMAIN>\<NAS_SVC_ACCOUNT>:(R)" | Out-Null
icacls "$cfg\restic-env.ps1"
This file holds the B2 credentials in plaintext and must carry the same ACL discipline as the password file. The NAS service account needs read access so the scheduled task can source it.
6.2 — Nightly backup script
@'
$ErrorActionPreference = "Stop"
$log = "C:\ProgramData\restic\logs\nightly_{0}.log" -f (Get-Date -Format "yyyyMMdd_HHmmss")
Start-Transcript -Path $log -Force | Out-Null
# Rotate: keep 30 most recent
Get-ChildItem "C:\ProgramData\restic\logs" -Filter "nightly_*.log" |
Sort-Object LastWriteTime -Descending | Select-Object -Skip 30 | Remove-Item -Force -EA SilentlyContinue
$rc = 0
try {
. "C:\ProgramData\restic\restic-env.ps1"
$env:RESTIC_REPOSITORY = $env:RESTIC_REPO_NAS
& $env:RESTIC_BIN backup C:\ D:\ --use-fs-snapshot --exclude-file $env:RESTIC_EXCLUDES --tag $env:RESTIC_TAG
$backupExit = $LASTEXITCODE
Write-Output "BACKUP EXIT: $backupExit"
if ($backupExit -ne 0) { $rc = 2 }
$env:RESTIC_REPOSITORY = $env:RESTIC_REPO_B2
& $env:RESTIC_BIN copy --from-repo $env:RESTIC_REPO_NAS
$copyExit = $LASTEXITCODE
Write-Output "COPY EXIT: $copyExit"
if ($copyExit -ne 0) { $rc = 2 }
}
catch {
Write-Output "FATAL: $($_.Exception.Message)"
$rc = 1
}
finally {
Stop-Transcript | Out-Null
}
exit $rc
'@ | Set-Content "C:\ProgramData\restic\backup-nightly.ps1" -Encoding UTF8
Restic exit codes that matter: 0 success, 1 command failed, 3 backup completed but some source files could not be read. Exit 3 is not success — it means data is missing from the snapshot and must be investigated. Run restic --help on the deployed version for the full list.
6.3 — Weekly maintenance script
@'
$ErrorActionPreference = "Stop"
$log = "C:\ProgramData\restic\logs\maint_{0}.log" -f (Get-Date -Format "yyyyMMdd_HHmmss")
Start-Transcript -Path $log -Force | Out-Null
Get-ChildItem "C:\ProgramData\restic\logs" -Filter "maint_*.log" |
Sort-Object LastWriteTime -Descending | Select-Object -Skip 12 | Remove-Item -Force -EA SilentlyContinue
$rc = 0
try {
. "C:\ProgramData\restic\restic-env.ps1"
foreach ($repo in @($env:RESTIC_REPO_NAS, $env:RESTIC_REPO_B2)) {
Write-Output "=== $repo ==="
$env:RESTIC_REPOSITORY = $repo
& $env:RESTIC_BIN forget --keep-daily 14 --keep-within 1m --prune
if ($LASTEXITCODE -ne 0) { $rc = 2 }
& $env:RESTIC_BIN check
if ($LASTEXITCODE -ne 0) { $rc = 2 }
& $env:RESTIC_BIN snapshots
}
}
catch {
Write-Output "FATAL: $($_.Exception.Message)"
$rc = 1
}
finally {
Stop-Transcript | Out-Null
}
exit $rc
'@ | Set-Content "C:\ProgramData\restic\maintain.ps1" -Encoding UTF8
Retention is --keep-daily 14 --keep-within 1m, matching the DTC NinjaOne standard on page 1421 (14 daily revisions, one month total). The interim backup deliberately mirrors the standard so the client's recovery window does not change.
Prune runs weekly, not nightly. Prune over SMB against a large repository is slow and I/O-heavy; bolting it onto the nightly job risks the backup window.
6.4 — Register the scheduled tasks
Tasks run as the site NAS service account from IT Glue — the same identity NinjaOne uses for the local backup destination. This avoids minting a new credential and the account already has proven write access to the share.
# Interactive prompt avoids the password appearing in command history.
# (Read-Host / Get-Credential is prohibited in RMM scripts — this is a manual T3 procedure, not RMM.)
$cred = Get-Credential -Message "Site NAS service account (from IT Glue)"
$common = @{
User = $cred.UserName
Password = $cred.GetNetworkCredential().Password
RunLevel = "Highest"
}
Register-ScheduledTask -TaskName "Restic - Nightly Backup" @common `
-Action (New-ScheduledTaskAction -Execute "powershell.exe" `
-Argument "-NoProfile -ExecutionPolicy Bypass -File C:\ProgramData\restic\backup-nightly.ps1") `
-Trigger (New-ScheduledTaskTrigger -Daily -At 11pm) `
-Description "Interim restic backup - NAS then B2 copy. See KB: Restic Emergency Interim Backup. Ticket <TICKET>."
Register-ScheduledTask -TaskName "Restic - Weekly Maintenance" @common `
-Action (New-ScheduledTaskAction -Execute "powershell.exe" `
-Argument "-NoProfile -ExecutionPolicy Bypass -File C:\ProgramData\restic\maintain.ps1") `
-Trigger (New-ScheduledTaskTrigger -Weekly -DaysOfWeek Sunday -At 3am) `
-Description "Interim restic retention and integrity check. See KB: Restic Emergency Interim Backup. Ticket <TICKET>."
Get-ScheduledTask -TaskName "Restic*" | Select-Object TaskName, State
The account requires the Log on as a batch job right. If task registration succeeds but the task fails immediately with a logon error, that right is missing — grant it via secpol.msc → Local Policies → User Rights Assignment, or the equivalent GPO.
Schedule the backup at the same hour the NinjaOne plan used (DTC standard is 23:00 local) so the client's backup window does not shift.
7. Verification
Run the morning after the first scheduled execution. Do not report the deployment complete until this passes.
. "C:\ProgramData\restic\restic-env.ps1"
foreach ($repo in @($env:RESTIC_REPO_NAS, $env:RESTIC_REPO_B2)) {
Write-Output "=== $repo ==="
$env:RESTIC_REPOSITORY = $repo
& $env:RESTIC_BIN snapshots --compact
& $env:RESTIC_BIN stats --mode raw-data
}
Get-ScheduledTask -TaskName "Restic*" | Get-ScheduledTaskInfo |
Select-Object TaskName, LastRunTime, LastTaskResult, NextRunTime | Format-Table -AutoSize
Get-ChildItem "C:\ProgramData\restic\logs" | Sort-Object LastWriteTime -Descending | Select-Object -First 3
Both repositories must show a snapshot from the scheduled run. LastTaskResult 0 on both tasks. A green task result with no new snapshot means the script exited before restic ran — read the transcript.
8. Restore
Three paths. Option A is the guaranteed one and is what you should reach for under pressure.
8.1 — Option A: restic restore (primary)
. "C:\ProgramData\restic\restic-env.ps1"
$env:RESTIC_REPOSITORY = $env:RESTIC_REPO_NAS # or $env:RESTIC_REPO_B2 if the site is gone
# 1 - find the snapshot
& $env:RESTIC_BIN snapshots --compact
# 2 - locate the file if the path is unknown
& $env:RESTIC_BIN find "PatientLedger*"
# 3a - restore specific files to a staging folder (SAFE DEFAULT)
& $env:RESTIC_BIN restore <snapshotID> `
--target "D:\restore-staging" `
--include "/D/Storage/SomeFolder"
# 3b - restore an entire snapshot to a staging folder
& $env:RESTIC_BIN restore latest --target "D:\restore-staging"
Always restore to a staging folder, never over live data. Restore to D:\restore-staging, verify the content, then move it into place deliberately. Restoring directly over a production path with the application running is how a recoverable incident becomes an unrecoverable one.
Paths inside a snapshot use forward slashes with the drive letter as the first element — C:\Windows appears as /C/Windows. Use restic ls to confirm the exact form before building an --include.
8.2 — Option B: restic mount (browsing, requires WinFsp)
UNVERIFIED ON WINDOWS — verify before relying on this in a live recovery. Mount support on Windows is provided through WinFsp. DTC has not confirmed it functional on the currently deployed restic version, and Backblaze's own integration guide notes that some restic features are unavailable on Windows. Test it during the deployment, not during the disaster. If it does not work, use Option A or C.
# Install WinFsp first - https://winfsp.dev (requires a reboot on some builds)
. "C:\ProgramData\restic\restic-env.ps1"
$env:RESTIC_REPOSITORY = $env:RESTIC_REPO_NAS
& $env:RESTIC_BIN mount X:
# Browse X:\snapshots\ in Explorer. Ctrl+C in the console to unmount.
The mount is read-only. Useful for locating a file when the client cannot describe where it lived, and for comparing revisions before choosing one.
8.3 — Option C: ls and dump (no mount required)
# List a snapshot's contents
& $env:RESTIC_BIN ls latest /D/Storage
# Stream a single file straight out of the repository
& $env:RESTIC_BIN dump latest "/D/Storage/Reports/file.pdf" > "D:\restore-staging\file.pdf"
# Dump an entire folder as a zip
& $env:RESTIC_BIN dump --archive zip latest "/D/Storage/Reports" > "D:\restore-staging\reports.zip"
This is the fallback when mount is unavailable and a single file is needed quickly. It requires no additional software.
9. Restore Test — Mandatory
A backup that has not been restored from is not a backup. Perform this within 24 hours of deployment and record the result on the ticket.
- Pick a file from the client's LOB data — real data, not a text file you created
- Restore it to
D:\restore-stagingusing Option A - Open it in its native application and confirm it is intact and current
- Repeat the restore from the B2 repository, not just the NAS — an untested offsite copy is not an offsite copy
- Test Option B (mount) once, to establish whether it works on this host
- Delete the staging folder
- Record on the ticket: file restored, source repository, snapshot ID, verification method, outcome
10. Disaster Recovery — Host Is Gone
Restic holds files, not an image. Recovery of a destroyed host is a rebuild, and the sequence matters.
- Build the replacement OS to the current DTC standard and patch it
- Restore roles before data. Domain controller: promote a new DC into the existing domain and let AD replicate — do not restore NTDS files from restic onto a live domain. If this was the only DC, escalate before proceeding; restoring a lone DC from file-level backup is a Microsoft-unsupported path and needs a deliberate decision.
- Reinstall LOB applications to the same versions and paths
- Restore data from restic to a staging folder, then move into place with services stopped
- Restore from B2 if the site NAS was lost with the host — the repository string is the only thing that changes
- Verify with the client before returning the system to service
Recovering from a different machine requires only the restic binary, the repository password from IT Glue, and the B2 key. Nothing is tied to the original host.
11. Rollback
If deployment goes wrong or must be reversed before completion:
Unregister-ScheduledTask -TaskName "Restic - Nightly Backup" -Confirm:$false -EA SilentlyContinue
Unregister-ScheduledTask -TaskName "Restic - Weekly Maintenance" -Confirm:$false -EA SilentlyContinue
# Leaves the repositories intact - data is not destroyed by removing automation.
Get-ScheduledTask -TaskName "Restic*" -EA SilentlyContinue
Removing the tasks stops all activity without touching either repository. Nothing in this procedure modifies the host's existing NinjaOne configuration, so rollback cannot affect NinjaOne remediation.
12. Exit Criteria & Decommission
Review weekly. Restic comes out as soon as NinjaOne Hybrid Cloud Backup is confirmed working — not when it is believed working.
Decommission only when all hold:
- NinjaOne has produced at least three consecutive successful backups with both local and cloud legs completing
- A restore has been tested from the NinjaOne backup, per the integrity verification procedure in this book
- The NinjaOne vendor case is closed or the root cause is confirmed resolved
# 1 - stop automation
Unregister-ScheduledTask -TaskName "Restic - Nightly Backup" -Confirm:$false
Unregister-ScheduledTask -TaskName "Restic - Weekly Maintenance" -Confirm:$false
# 2 - RETAIN both repositories for 30 days past NinjaOne's first verified restore.
# Do not delete on the same day you re-enable NinjaOne.
# 3 - after the retention window:
# - delete the NAS repository folder
# - delete the B2 bucket
# - delete the B2 application key
# - remove C:\Program Files\restic and C:\ProgramData\restic
# - archive the repo password and B2 key in IT Glue as retired (do not delete
# the IT Glue entry until both repositories are gone)
# 4 - update the tracking sheet and close the ticket
13. Tracking
Every restic deployment is recorded in the Restic Interim Deployment Tracker. An untracked deployment is one nobody will remember to remove.
Record: client, hostname, deployment date, ticket, NinjaOne fault and vendor case, NAS repository path, B2 bucket and endpoint, restic version, repository ID, retention, restore-test date and result, weekly review date, decommission date.
14. Related Pages
- 1421 — NinjaOne Image Backup Plan Configuration Standard (the standard this bridges to)
- 2966 — NinjaOne Backup: Architecture Deep Dive — Lockhart, Cloud Storage & Hybrid Model
- 2967 — NinjaOne Backup: Support Escalation — When to Call & What to Bring
- 2968 — NinjaOne Backup: Log File Locations & How to Read Them
- 2969 — NinjaOne Backup: Error Code Master Reference
- 3008 — NinjaOne Backup: Backup Integrity — Manual Verification & Spot-Check Procedure
- 3715 — NinjaOne Backup: Backup Won't Start / Stuck on "Backup Started"
- 3818 — NinjaOne Backup: SMB Credentials Rejected (System Error 86) — LmCompatibilityLevel / NTLMv2
- 1034 — Disaster Recovery Runbook
- 4116 — Open Backup Failure Tracker
Change Record
Date | Author | Change |
|---|---|---|
2026-08-31 | Z. Boogher | Page created. Derived from the interim deployment performed under Halo 1170038 following Lockhart clone-mode deactivation on a domain controller with no onsite BDR. |