Documenting your server environment is one of those tasks that always feels like it can wait — until a server fails at midnight and the person on call has no idea what it does, what connects to it, or where the backup is. Good documentation takes a few hours to build and saves days when something goes wrong. This guide covers what to document and how to capture it efficiently using PowerShell.
What to Document
A useful server environment document should cover enough information for someone unfamiliar with the environment to understand the setup and respond to an incident. At a minimum:
- Server inventory: name, IP address, OS version, hardware spec, role/purpose, location, and support contract
- Roles and services: what the server does and what depends on it
- Network details: IP addresses, subnet, gateway, DNS, VLAN
- Credentials and access: where admin passwords are stored (not the passwords themselves — a reference to the password manager or safe)
- Backup details: what is backed up, how often, where, and how to restore
- Licensing: licence type, key reference, expiry
- Maintenance history: when it was last patched, any hardware replaced
Gather Server Information Automatically with PowerShell
Building an inventory from scratch is tedious manually. PowerShell can pull the key details from each server in minutes:
# Collect core server information
$info = [PSCustomObject]@{
Hostname = $env:COMPUTERNAME
OS = (Get-CimInstance Win32_OperatingSystem).Caption
OSVersion = (Get-CimInstance Win32_OperatingSystem).Version
LastBoot = (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
CPU = (Get-CimInstance Win32_Processor).Name
RAM_GB = [math]::Round((Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory/1GB,1)
InstalledRoles = (Get-WindowsFeature | Where-Object {$_.InstallState -eq 'Installed' -and $_.FeatureType -eq 'Role'}).Name -join ", "
IPAddresses = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object {$_.PrefixOrigin -ne 'WellKnown'}).IPAddress -join ", "
DefaultGateway = (Get-NetRoute -DestinationPrefix "0.0.0.0/0").NextHop
DNSServers = (Get-DnsClientServerAddress -AddressFamily IPv4 | Where-Object {$_.ServerAddresses}).ServerAddresses -join ", "
}
$info | Format-List
Document Storage Across All Drives
Get-PSDrive -PSProvider FileSystem | Select-Object Name,
@{N='Total_GB';E={[math]::Round(($_.Used+$_.Free)/1GB,1)}},
@{N='Used_GB';E={[math]::Round($_.Used/1GB,1)}},
@{N='Free_GB';E={[math]::Round($_.Free/1GB,1)}},
@{N='Free_Pct';E={[math]::Round($_.Free/($_.Used+$_.Free)*100,1)}}
Document Installed Software
Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |
Select-Object DisplayName, DisplayVersion, Publisher, InstallDate |
Where-Object {$_.DisplayName} |
Sort-Object DisplayName
Document Network Shares
Get-SmbShare | Where-Object {$_.Name -notmatch '\$$'} | Select-Object Name, Path, Description
Document Scheduled Tasks
Get-ScheduledTask | Where-Object {$_.TaskPath -notlike '\Microsoft\*'} |
Select-Object TaskName, TaskPath, State,
@{N='NextRun';E={(Get-ScheduledTaskInfo $_.TaskName -ErrorAction SilentlyContinue).NextRunTime}}
Export Everything to a Single Report
$report = "C:\Temp\ServerReport-$env:COMPUTERNAME-$(Get-Date -Format 'yyyyMMdd').txt"
"=== SERVER REPORT: $env:COMPUTERNAME ===" | Out-File $report
"Generated: $(Get-Date)" | Out-File $report -Append
"" | Out-File $report -Append
"--- SYSTEM INFO ---" | Out-File $report -Append
(Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, LastBootUpTime) | Out-File $report -Append
"--- INSTALLED ROLES ---" | Out-File $report -Append
(Get-WindowsFeature | Where-Object {$_.InstallState -eq 'Installed' -and $_.FeatureType -eq 'Role'} | Select-Object DisplayName) | Out-File $report -Append
"--- DISK SPACE ---" | Out-File $report -Append
(Get-PSDrive -PSProvider FileSystem | Select-Object Name, Used, Free) | Out-File $report -Append
"--- NETWORK ADAPTERS ---" | Out-File $report -Append
(Get-NetIPConfiguration | Select-Object InterfaceAlias, IPv4Address, IPv4DefaultGateway, DNSServer) | Out-File $report -Append
Write-Host "Report saved to $report"
Where to Store Documentation
A document that only exists on the server being documented is useless when that server is down. Store server documentation in a location that is accessible independently:
- A shared document platform (SharePoint, Confluence, IT Glue, Hudu)
- A network share on a different server
- A password manager with document storage (1Password, Bitwarden)
- A printed copy in a physical IT folder for truly critical information
Schedule the PowerShell report script to run monthly via Task Scheduler and save the output to a central location — automated documentation that stays current with minimal effort.
Review and Update Frequency
Documentation decays. Build reviewing it into your regular maintenance cycle:
- Update immediately after any significant change — new role installed, IP change, hardware swap
- Full review quarterly — verify IPs are still correct, roles match reality, backup details are current
- Annual review — update hardware age, warranty status, and licence expiry dates