|
| 1 | +# FSLogix Integration |
| 2 | + |
| 3 | +This guide defines how to run FSLogix profile containers for AVD session hosts on Azure Local with operationally safe defaults. |
| 4 | + |
| 5 | +## 1) Profile container model selection |
| 6 | + |
| 7 | +### VHDX on SMB (SOFS) |
| 8 | +- Best for: Azure Local with low-latency SMB and AD DS/Kerberos. |
| 9 | +- Pros: simple operations, predictable performance, no cloud dependency in steady state. |
| 10 | +- Cons: recovery depends on storage replication/backup maturity. |
| 11 | + |
| 12 | +### Cloud Cache (CCD) |
| 13 | +- Best for: multi-site resiliency, Entra-only patterns, or mixed storage backends. |
| 14 | +- Pros: supports multiple providers and tolerates backend outages. |
| 15 | +- Cons: higher write amplification, more tuning/monitoring complexity. |
| 16 | + |
| 17 | +Recommended default: use VHDX on SOFS for primary Azure Local designs and introduce CCD only where explicit DR/availability requirements justify complexity. |
| 18 | + |
| 19 | +## 2) Sizing and capacity planning |
| 20 | + |
| 21 | +Baseline sizing: |
| 22 | +- Profile target per user: 25-40 GB (start with 30 GB). |
| 23 | +- Free space buffer: 30% on the profile volume. |
| 24 | +- Metadata growth allowance: 10% additional capacity. |
| 25 | + |
| 26 | +Planning formula: |
| 27 | + |
| 28 | +$$ |
| 29 | +Required\ Capacity = (Users \times Profile\ Size) \times 1.4 |
| 30 | +$$ |
| 31 | + |
| 32 | +Example: |
| 33 | +- 400 users, 30 GB each: $400 \times 30 \times 1.4 = 16.8$ TB usable. |
| 34 | + |
| 35 | +## 3) SOFS and SMB configuration guidance |
| 36 | + |
| 37 | +Storage layout: |
| 38 | +- Use dedicated CSV volumes for profile containers (separate from golden image/app content volumes). |
| 39 | +- Use continuous availability SMB shares for profile paths. |
| 40 | +- Keep storage traffic on dedicated east-west networks. |
| 41 | + |
| 42 | +SMB recommendations: |
| 43 | +- SMB Multichannel enabled. |
| 44 | +- SMB encryption only where required by policy (measure impact first). |
| 45 | +- Access-based enumeration enabled for profile shares. |
| 46 | + |
| 47 | +Permissions baseline: |
| 48 | +- Share permissions: `Authenticated Users` change, `Administrators` full control. |
| 49 | +- NTFS: Creator Owner full on subfolders/files, users only to their own folders, admins/system full control. |
| 50 | + |
| 51 | +## 4) FSLogix registry baseline |
| 52 | + |
| 53 | +Primary keys under `HKLM:\SOFTWARE\FSLogix\Profiles`: |
| 54 | +- `Enabled` (DWORD) = `1` |
| 55 | +- `DeleteLocalProfileWhenVHDShouldApply` (DWORD) = `1` |
| 56 | +- `FlipFlopProfileDirectoryName` (DWORD) = `1` |
| 57 | +- `IsDynamic` (DWORD) = `1` |
| 58 | +- `SizeInMBs` (DWORD) = `30720` (30 GB default) |
| 59 | +- `VolumeType` (String) = `vhdx` |
| 60 | +- `VHDLocations` (Multi-String) = `\\sofs\fslogixprofiles` |
| 61 | + |
| 62 | +PowerShell example: |
| 63 | + |
| 64 | +```powershell |
| 65 | +$base = 'HKLM:\SOFTWARE\FSLogix\Profiles' |
| 66 | +New-Item -Path $base -Force | Out-Null |
| 67 | +New-ItemProperty -Path $base -Name Enabled -PropertyType DWord -Value 1 -Force | Out-Null |
| 68 | +New-ItemProperty -Path $base -Name DeleteLocalProfileWhenVHDShouldApply -PropertyType DWord -Value 1 -Force | Out-Null |
| 69 | +New-ItemProperty -Path $base -Name FlipFlopProfileDirectoryName -PropertyType DWord -Value 1 -Force | Out-Null |
| 70 | +New-ItemProperty -Path $base -Name IsDynamic -PropertyType DWord -Value 1 -Force | Out-Null |
| 71 | +New-ItemProperty -Path $base -Name SizeInMBs -PropertyType DWord -Value 30720 -Force | Out-Null |
| 72 | +New-ItemProperty -Path $base -Name VolumeType -PropertyType String -Value 'vhdx' -Force | Out-Null |
| 73 | +New-ItemProperty -Path $base -Name VHDLocations -PropertyType MultiString -Value '\\sofs\fslogixprofiles' -Force | Out-Null |
| 74 | +``` |
| 75 | + |
| 76 | +Ansible example: |
| 77 | + |
| 78 | +```yaml |
| 79 | +- name: Configure FSLogix registry baseline |
| 80 | + ansible.windows.win_regedit: |
| 81 | + path: HKLM:\SOFTWARE\FSLogix\Profiles |
| 82 | + name: "{{ item.name }}" |
| 83 | + data: "{{ item.data }}" |
| 84 | + type: "{{ item.type }}" |
| 85 | + state: present |
| 86 | + loop: |
| 87 | + - { name: Enabled, type: dword, data: 1 } |
| 88 | + - { name: DeleteLocalProfileWhenVHDShouldApply, type: dword, data: 1 } |
| 89 | + - { name: FlipFlopProfileDirectoryName, type: dword, data: 1 } |
| 90 | + - { name: IsDynamic, type: dword, data: 1 } |
| 91 | + - { name: SizeInMBs, type: dword, data: 30720 } |
| 92 | + - { name: VolumeType, type: string, data: vhdx } |
| 93 | + - { name: VHDLocations, type: multistring, data: '\\sofs\fslogixprofiles' } |
| 94 | +``` |
| 95 | + |
| 96 | +## 5) Antivirus and performance exclusions |
| 97 | + |
| 98 | +Validate against security policy before applying exclusions. Common exclusions include: |
| 99 | +- FSLogix process paths (`frxsvc.exe`, `frxrobocopy.exe`). |
| 100 | +- Profile container share path. |
| 101 | +- VHD(X) attach points. |
| 102 | + |
| 103 | +Always verify exclusions with security operations and Defender policy owners. |
| 104 | + |
| 105 | +## 6) DR and backup strategy |
| 106 | + |
| 107 | +Minimum controls: |
| 108 | +- Daily backup of FSLogix container volumes. |
| 109 | +- Replication across fault domains or secondary site for critical workloads. |
| 110 | +- Quarterly restore test using representative profile containers. |
| 111 | + |
| 112 | +Recovery objective guidance: |
| 113 | +- Define profile RPO/RTO explicitly in operations runbooks. |
| 114 | +- Validate sign-in performance after restore and check profile lock cleanup. |
| 115 | + |
| 116 | +## 7) Validation tests |
| 117 | + |
| 118 | +Post-deployment checks: |
| 119 | +- User sign-in creates and mounts profile VHDX. |
| 120 | +- Re-sign-in lands on same profile state across hosts. |
| 121 | +- Event logs show no recurring `frxsvc` attach errors. |
| 122 | +- SMB latency and IO remain within baseline thresholds. |
| 123 | + |
| 124 | +PowerShell validation example: |
| 125 | + |
| 126 | +```powershell |
| 127 | +Get-WinEvent -LogName 'Microsoft-FSLogix-Apps/Operational' -MaxEvents 100 | |
| 128 | + Where-Object { $_.LevelDisplayName -in 'Error','Warning' } | |
| 129 | + Select-Object TimeCreated, Id, Message |
| 130 | +``` |
| 131 | + |
| 132 | +## Related references |
| 133 | +- Companion SOFS repo: https://github.com/AzureLocal/azurelocal-sofs-fslogix |
| 134 | +- FSLogix docs: https://learn.microsoft.com/fslogix/ |
| 135 | +- Deep architecture design: ../deep-design.md |
0 commit comments