File server migration without breaking permissions
Copying the data is the part everyone plans for. It is also the part that rarely goes wrong. What goes wrong is Monday morning, when forty people cannot open the folder they opened every day for the last six years, and nobody can say which of the four things changed over the weekend caused it.
Most migration guides assume a file server that does not exist: documented shares, clean inheritance, no local accounts, no hard-coded paths. The server you are actually moving is ten years old, has been through two admins who left, and contains at least one folder whose permissions nobody has understood since 2019.
This is the audit to run before you copy anything.
Why permissions break, specifically
Three mechanisms cause almost all of it, and they are independent of each other.
There are two sets of permissions, and only one usually travels
A Windows share has NTFS permissions on the folder and share permissions on the share itself. Effective access is the more restrictive of the two. Copy tools move NTFS ACLs; they do not move share permissions, because share permissions are not stored with the files. Recreate a share with the default and you have just granted a different set of people access than the old server did.
Identities that do not exist on the destination
An ACL stores a SID, not a name. Any entry referring to a local account or group on the old server refers to a SID that will never resolve on the new one. So do entries for domain accounts that were deleted years ago. Both show up in the ACL editor as a raw S-1-5-21-... string, and both survive the copy perfectly while meaning nothing.
Broken inheritance and explicit deny
Somewhere in the tree, someone unticked inheritance to fix an urgent access problem. Every folder below that point stopped tracking the parent, and has been drifting ever since. Explicit deny entries are worse: deny beats allow, so a single deny ACE placed on a group in 2018 quietly overrides everything you grant afterwards. Neither is visible from the top of the tree.
The pre-migration audit
Run all of this before the maintenance window, not during it. The output is the thing you compare against after cutover, and without it you have no way to prove the migration preserved access rather than merely appearing to.
Inventory the shares separately from the folders
# shares and their share-level ACLs — these do NOT travel with the data
Get-SmbShare | Where-Object { $_.Name -notlike '*$' } |
Select-Object Name, Path, Description, FolderEnumerationMode |
Export-Csv .\shares.csv -NoTypeInformation
Get-SmbShare | Where-Object { $_.Name -notlike '*$' } |
Get-SmbShareAccess |
Export-Csv .\share-acls.csv -NoTypeInformationFind the identities that will not resolve
This is the highest-value query in the whole audit. Every unresolved SID is either an account you are about to lose track of or evidence of a cleanup nobody finished.
# ACEs whose identity is a raw SID — deleted accounts, or local accounts
# on the old server that will not exist on the new one
Get-ChildItem D:\Data -Directory -Recurse -ErrorAction SilentlyContinue |
ForEach-Object {
$path = $_.FullName
(Get-Acl $path).Access |
Where-Object { $_.IdentityReference -match '^S-1-5-21-' } |
Select-Object @{n='Path';e={$path}}, IdentityReference,
FileSystemRights, AccessControlType
} | Export-Csv .\orphaned-sids.csv -NoTypeInformationFind broken inheritance and every deny
# folders that stopped inheriting, and explicit deny entries
Get-ChildItem D:\Data -Directory -Recurse -ErrorAction SilentlyContinue |
ForEach-Object {
$acl = Get-Acl $_.FullName
$deny = $acl.Access | Where-Object { $_.AccessControlType -eq 'Deny' }
if ($acl.AreAccessRulesProtected -or $deny) {
[PSCustomObject]@{
Path = $_.FullName
InheritanceOff = $acl.AreAccessRulesProtected
DenyCount = @($deny).Count
Owner = $acl.Owner
}
}
} | Export-Csv .\inheritance-breaks.csv -NoTypeInformationDo not fix what you find yet. Migrating a permissions problem you have documented is a controlled risk. Fixing permissions during a migration means that when access breaks on Monday, you cannot tell whether the move caused it or your cleanup did. Two changes, one window, no way to bisect.
Find who is actually connected
Before you decide the cutover window, find out who has the server open at 2am. There is usually a backup job, a scanner or a line-of-business application, and none of them are on the email thread.
Get-SmbSession | Select-Object ClientComputerName, ClientUserName, NumOpens
Get-SmbOpenFile | Group-Object ClientComputerName |
Sort-Object Count -Descending | Select-Object Count, NameWhat does not come across with the files
| Item | Travels with a file copy? | What to do |
|---|---|---|
| NTFS ACLs | Yes, with the right flags | /COPYALL or /COPY:DATSOU |
| Share permissions | No | Export with Get-SmbShareAccess, recreate explicitly |
| Local users and groups | No | Re-point to domain groups before the move |
| Access-based enumeration | No | Per-share setting, recreate it |
| FSRM quotas and file screens | No | Export templates, reapply |
| Shadow copies (Previous Versions) | No | Users lose history — tell them before, not after |
| DFS namespace targets | No | Repoint folder targets at cutover |
| Auditing entries (SACLs) | Only with /COPY:U | Include U if you are audited |
| Offline files / caching mode | No | Per-share setting |
The shadow copies row causes more support calls than anything else on the list. Previous Versions is the feature users rely on without knowing its name, and it does not survive the move. Announce it in advance.
Robocopy flags that matter
Robocopy is the right tool and it is also the tool people run with the wrong flags. Four things are worth knowing before the first run.
# seed run: copy everything including ACLs, owner and auditing,
# with retries that fail fast instead of hanging for a year
robocopy D:\Data \\NEWSRV\D$\Data /E /COPYALL /DCOPY:DAT /ZB /MT:16 ^
/R:2 /W:5 /XD "System Volume Information" /LOG:seed.log /TEE
# delta run, repeated until the window: only what changed
robocopy D:\Data \\NEWSRV\D$\Data /E /COPYALL /DCOPY:DAT /ZB /MT:16 ^
/R:2 /W:5 /XO /LOG:delta.log /TEE- •The retry defaults will hang you. /R defaults to 1,000,000 retries and /W to 30 seconds. One locked file at those values is roughly 347 days of waiting. Always set /R and /W explicitly.
- •/COPYALL is /COPY:DATSOU — data, attributes, timestamps, security, owner, auditing. It needs backup-operator rights on both ends. Without the S flag you copy the files and silently leave the permissions behind.
- •/DCOPY defaults to DA, so directory timestamps are not preserved unless you ask for /DCOPY:DAT. Nobody notices until an auditor sorts a folder by date.
- •/MIR deletes. It is /E plus /PURGE, and pointed at the wrong destination it removes everything not present in the source. Microsoft also notes it can overwrite the destination root's security settings. Use it for the final sync, deliberately, never for the first one.
Two edge cases worth checking before the window rather than during it: encrypted files need /EFSRAW, and alternate data streams are copied by default but skipped if anyone has added X to the copy flags. If the estate uses EFS at all, test one file end to end first.
Cutover: the alias problem nobody warns about
The clean cutover is to keep the old server's name, so mapped drives, GPO drive maps, scripts and the hard-coded UNC path inside the accounting application all keep working. The instinct is to create a DNS CNAME pointing the old name at the new server.
This fails. SMB access through a CNAME breaks Kerberos authentication because no service principal name exists for the alias, and the error is not obvious — typically "the target account name is incorrect", or an access-denied message that sends you looking at permissions you just spent a week migrating.
# on the NEW server: register the old name as a real computer alias
netdom computername NEWSRV /add:OLDSRV.contoso.com
# verify the SPNs landed on the computer account
setspn -L NEWSRVThis is Microsoft's current guidance: use a computer name alias rather than a DNS CNAME for a file server. It registers the SPNs Kerberos needs. The older DisableStrictNameChecking registry workaround is still widely posted and is no longer the recommended fix.
Validating by people, not by file count
Comparing file counts proves the copy ran. It proves nothing about access, which is the thing that actually breaks. Validate against the audit output instead:
- •Re-run the orphaned-SID and inheritance queries on the new server and diff them against the pre-migration CSVs. Anything that changed, changed for a reason you should be able to name.
- •Check effective access for one real user per department, not for a test account that belongs to no groups. Get-Acl shows what is configured; effective access shows what happens.
- •Open the applications, not just Explorer. A line-of-business app authenticating as a service account is the classic Monday failure, and it is never in the test plan.
- •Confirm share-level ACLs against share-acls.csv — this is the set most likely to have been recreated with a default.
- •Watch the security log for access-denied events for the first two days. Users report a fraction of what breaks; the log reports all of it.
Rollback
Decide the rollback trigger before the window and write it down: which failures mean revert, who decides, and by what time. Keep the old server powered on, shares intact and read-only for a week — long enough to cover the monthly process that only runs once. A rollback plan that consists of "we still have the backup" is not a rollback plan; restoring a multi-terabyte volume takes longer than the window you were given.
When this is worth outsourcing
A small, well-documented file server is a weekend for a competent admin. What makes these projects expensive is the audit above: the tree that has been accumulating exceptions for a decade, the shares nobody can name an owner for, the deny ACE that turns out to be load-bearing. That work is unglamorous, it does not compress, and it is the difference between a quiet Monday and a week of tickets.
If you are moving a file server that predates the people currently running it, the audit is the part to take seriously — and the part worth having someone do who has unpicked one before.
Once the move is done and the audit output says what you have inherited, the next question is what to do about it — covered in restructuring file server permissions without breaking access.
The checks in this article are collected as a printable file server migration checklist, free and not gated behind an email address.
Moving a file server nobody fully documented?
We run pre-cutover permission audits, migrations and ongoing Windows and Linux server administration. €65/hour, fixed-scope quotes for projects, from €60/month per server for ongoing support.