A user signs into your Azure Virtual Desktop pool, the desktop loads, and their profile is gone — fresh Start menu, no Outlook signature, no OneDrive, no browser history. Next login they get a different session host and a different empty profile. This is what FSLogix exists to solve: on pooled, non-persistent session hosts a user can land on any VM, so their profile must live on shared storage and be attached at logon, not baked into C:. FSLogix packages the entire profile into a VHDX container it mounts as a virtual disk at sign-in and detaches at sign-out — wherever the user lands, their profile follows. That container needs a home that’s fast, redundant and SMB-accessible, and Azure Files is the natural fit.
The hard part was never FSLogix itself — it is authentication and permissions. Putting containers on Azure Files used to mean standing up domain controllers (or Entra Domain Services) just so the share could authenticate SMB sessions with Kerberos. Microsoft Entra ID Kerberos removes that: your Entra-joined hosts mount an Azure Files SMB share and authenticate directly against Entra ID, no domain controller in the path. That simplification introduces a two-layer permission model that trips up almost everyone the first time: share-level RBAC (who may connect, granted as Azure roles) and NTFS/file-level permissions (what they may do once connected, set with icacls). Get one layer right and the other wrong and FSLogix silently fails to create or load the container — symptom: again, an empty profile.
This is a step-by-step implementation guide. You will configure a complete FSLogix-on-Azure-Files setup using Entra ID Kerberos from scratch — storage account, Kerberos identity, both permission layers, the FSLogix registry, and the exclusions that keep containers small — three ways: the portal, the az CLI, and a Bicep template you can commit. Every step states its expected output and how to validate it, and the article ends with the exact registry keys, the permission matrix, the exclusion list, a troubleshooting playbook, and a teardown. By the end you won’t be guessing why a profile is empty; you’ll know which permission layer, or which registry value, is wrong, and fix it in minutes.
What problem this solves
On a single, persistent desktop the profile lives on the local disk and nobody thinks about it. On pooled Azure Virtual Desktop — many users sharing a fleet of disposable session hosts — that collapses: a user is load-balanced to whichever host has capacity, so their profile cannot live on any one host’s C: drive. The classic answers (roaming profiles, mandatory profiles, UPDs) are slow, fragile, and notorious for corruption with modern apps like OneDrive, Teams and the new Outlook. FSLogix replaces all of it with one idea: the profile is a VHDX file on an SMB share, attached as a disk at logon so Windows sees a normal local profile, detached at logout.
What breaks without getting storage and permissions right: FSLogix tries to create the container and can’t — the host can’t authenticate (Kerberos misconfigured), or authenticates but lacks NTFS rights to create the file, or the quota is full. The default failure mode is to fall back to a temporary local profile — the user logs in to a working-but-empty desktop, does work, logs out, and it evaporates. No error, no crash. The most common ticket in an AVD estate is “my files disappeared”, and behind it is almost always one of: the container never attached, attached read-only, or got reset because the two permission layers disagreed.
Who hits this: anyone running pooled AVD or Windows 365 at scale, migrating off file-server UPD/roaming profiles, and especially teams adopting the cloud-only identity model — Entra-joined hosts with no domain controller. That last group is exactly who Entra ID Kerberos is for, and the configuration this guide builds. Done right, you get a profile system that survives host reimaging, scales to thousands of users on one storage account, and needs no AD at all.
Learning objectives
By the end of this article you can:
- Explain the FSLogix profile-container model, why pooled AVD needs it, and when to choose VHDLocations (profile container) versus CloudCache.
- Stand up an Azure Files SMB share sized and tiered for FSLogix, and enable Microsoft Entra ID Kerberos authentication on the storage account with no domain controller.
- Configure the two-layer permission model: the share-level RBAC roles (Reader vs Contributor vs Elevated Contributor) and the NTFS permissions FSLogix requires via
icacls. - Grant the Entra ID Kerberos app its admin consent and set the Default share-level permission so users don’t each need an explicit role assignment.
- Install the FSLogix agent and set the exact registry keys that turn it on (
Enabled,VHDLocations,VolumeType,FlipFlopProfileDirectoryName,DeleteLocalProfileWhenVHDShouldApply) — with the default, valid values and gotcha for each. - Apply a sane profile-exclusion policy (
redirections.xml) to keep containers small and avoid double-syncing cloud data. - Validate an attached container end to end (event logs + the mounted disk) and run a troubleshooting playbook against the real failures: read-only profile,
STATUS_LOGON_FAILURE, “you do not have permission”, and0x0000000eattach errors.
Prerequisites & where this fits
You should understand the AVD building blocks: a host pool is a set of session-host VMs that users connect to through the AVD control plane. If that’s new, read Azure Virtual Desktop Architecture: Control Plane and Session Hosts Explained and Deploy Your First AVD Pooled Host Pool End to End first. Know the Azure Files basics — mounting an SMB share, quotas, tiers — from Azure Files SMB Share: Mount on Windows and Linux Quickstart. Comfort with az in Cloud Shell, reading JSON, and Windows NTFS/registry basics will make the lab smooth.
This sits in the AVD / End-User Compute track — the storage and identity layer beneath a host pool. Which pool model you run — see AVD Host Pool: Personal vs Pooled — Deciding the Right Model — is upstream: FSLogix matters most for pooled pools (personal desktops keep profiles locally). It pairs with Azure Storage Redundancy: LRS, ZRS, GRS, RA-GRS Explained (the share’s redundancy is a real availability call) and with Managed Identity: System-Assigned vs User-Assigned Patterns (the identity concepts underpinning how Kerberos authenticates).
The identity options for Azure Files, and which this guide uses:
| Auth method for Azure Files SMB | Needs a domain controller? | Host join type | Best for | This guide? |
|---|---|---|---|---|
| Microsoft Entra ID Kerberos | No | Entra-joined (cloud-only) | Cloud-only AVD/W365, no AD | Yes |
| On-prem AD DS authentication | Yes (your own DCs) | AD-joined / Hybrid-joined | Estates that already run AD | No |
| Microsoft Entra Domain Services | Managed DC (Azure-hosted) | Entra DS-joined | Wanted Kerberos but no AD to extend | No |
| Storage account key (no identity) | No | Any | One-off mounts, never for FSLogix profiles | No |
The point of Entra ID Kerberos is the top row: no domain controller, cloud-only hosts, profiles authenticated straight to Entra ID.
Core concepts
Five mental models make every later step and every failure obvious.
A profile is a VHDX, attached at logon. FSLogix packages C:\Users\<user> into a single VHDX on the SMB share. At sign-in it mounts the VHDX as a disk and redirects the profile to it, so Windows and every app see an ordinary local profile; at sign-out it flushes and detaches. The file is foldered per user and created on first login. Everything here is about FSLogix being able to create, attach and write that one file.
Authentication and authorization are two layers. A host must first authenticate (prove who it is), then be authorized (be allowed to read/write). With Entra ID Kerberos, authentication is a Kerberos ticket from Entra ID — no DC. Authorization is itself two sub-layers: share-level RBAC (Azure roles for whether an identity may connect) and NTFS permissions (Windows ACLs for what they may do). Both must allow the operation — the double-gate is the number-one source of “it authenticated but the profile is empty” confusion.
Entra ID Kerberos puts the storage account in Entra ID as an app. Enabling Kerberos registers an app / service principal for the account, which needs admin consent for the Graph permissions it uses to issue tickets. When a host mounts the share it asks Entra ID for a ticket for that account, presents it to Azure Files, and is authenticated. No consent (or unreachable endpoints) → logon failure at mount, before any NTFS check.
FSLogix is driven entirely by the registry. No UI. The agent reads values under HKLM\SOFTWARE\FSLogix\Profiles to decide whether it’s enabled, where containers live, the disk format, and how to behave on failure. You set these via Group Policy, Intune, a script, or by hand in the lab. Get Enabled and VHDLocations right and you have a working system; the rest is behaviour tuning.
Exclusions keep the container small and avoid double-syncing. By default the whole profile goes into the VHDX — including caches you don’t want and cloud-synced data (OneDrive, Teams) already in the cloud. Profile exclusions (via redirections.xml) leave chosen folders out. The classic call: keep OneDrive in for a smooth experience but exclude transient caches. It’s about size and performance, not correctness — but a bloated container is slow to attach and a recurring cost.
The vocabulary in one table
Pin down every moving part before the steps (the glossary repeats these for lookup):
| Concept | One-line definition | Where it lives | Why it matters here |
|---|---|---|---|
| FSLogix agent | Windows service that attaches profile VHDXs | On each session host | The thing doing the work |
| Profile container | The user’s profile packaged as a VHDX | On the Azure Files share | The file that must be created/attached |
| VHDLocations | UNC path(s) where containers live | Registry value | Points FSLogix at the share |
| Azure Files share | SMB share hosting the VHDX files | Storage account | The redundant home for profiles |
| Entra ID Kerberos | Cloud Kerberos auth for Azure Files | Storage account + tenant | Authenticates hosts with no DC |
| Storage account app | The SP representing the account in Entra | App registration | Needs admin consent for tickets |
| Share-level RBAC | Azure roles to connect to the share | IAM on the storage account | Layer 1 of authorization |
| NTFS permissions | ACLs inside the file system | Set via icacls |
Layer 2 of authorization |
| Default share-level permission | A baseline role for all authenticated users | Storage account file setting | Avoids per-user role assignment |
| redirections.xml | The profile exclusion/inclusion list | On the share or local | Controls container size |
| CloudCache | Local cache layered over remote VHDX(s) | Registry (CCDLocations) |
Resilience / multi-region option |
Core concept: the two-layer permission model (read this twice)
If you remember one thing, remember this. Every FSLogix-on-Azure-Files permission problem is one of these two layers being wrong, and they live in different places with different tools.
Layer 1 — share-level RBAC (authorization to connect). Azure role assignments on the storage account (Access control / IAM) decide whether an Entra identity may establish an SMB session at all. Three built-in roles, and the difference between them is exactly what bites FSLogix admins.
| Built-in role (share-level) | What it grants over SMB | Who you assign it to | FSLogix relevance |
|---|---|---|---|
| Storage File Data SMB Share Reader | Read-only access to files/dirs | Auditors, read-only apps | Too little — container can’t be written |
| Storage File Data SMB Share Contributor | Read, write, delete on files/dirs | The AVD users (their profiles) | The baseline users need |
| Storage File Data SMB Share Elevated Contributor | Contributor plus modify NTFS ACLs | Admins setting up permissions | Needed to run icacls to set NTFS |
The trap: people assign users Reader (or nothing) and the container attaches read-only or not at all. Users get Contributor; the admin who sets NTFS permissions needs Elevated Contributor (changing ACLs is itself a permission). Rather than assign Contributor to every user, set a Default share-level permission so all authenticated Entra identities get a baseline role (typically Contributor) automatically — overriding per-identity only when needed.
Layer 2 — NTFS / file-level permissions (authorization to act on the file). Once connected, Windows ACLs decide what each identity may do. FSLogix’s requirement: each user can create their own profile folder and files, but not traverse into others’ folders. The canonical layout, set with icacls:
| Identity | NTFS permission on the share root | Applies to | Why |
|---|---|---|---|
| Creator Owner | Modify | Subfolders and files only | The user who creates a folder owns and controls it |
| Authenticated Users (or your AVD users group) | Modify, this folder only (no inherit) | This folder only | Lets users create their own folder, not see others’ |
| Administrators / FSLogix admins | Full control | This folder, subfolders, files | Admin management and cleanup |
The effect: a user can create \\<account>.file.core.windows.net\profiles\<their-SID> and write their VHDX, but cannot open another user’s folder — privacy and correctness. Both layers exist because RBAC is the Azure-plane gate (does this identity get an SMB session) and NTFS is the OS-plane gate (what can they do once in). Skipping either fails closed — not open — and FSLogix falls back to a temp profile.
The division of labour, side by side:
| Dimension | Share-level RBAC (Layer 1) | NTFS permissions (Layer 2) |
|---|---|---|
| Configured in | Storage account → Access control (IAM) | The file system, via icacls / Windows Explorer |
| Tool | Azure portal / az role assignment / Bicep |
icacls from an Elevated-Contributor-mounted drive |
| Controls | Whether you can connect to the share | What you can do once connected |
| Granularity | The whole share | Per folder / per file |
| Default behaviour | Set via “Default share-level permission” | Inherited from parent unless overridden |
| Symptom when wrong | Mount fails / read-only / access denied at connect | Container attaches but can’t write / can read others |
Step-by-step deep section: enabling Entra ID Kerberos correctly
Entra ID Kerberos makes the no-domain-controller story work, with three sub-steps people miss: enable the feature, grant admin consent to the app it creates, and configure the clients. Miss the consent and every mount fails with a logon error.
Sub-step A — enable the feature. On the account’s File shares → Active Directory blade, select Microsoft Entra Kerberos as the source. This registers the account as an app and sets directoryServiceOptions = AADKERB.
Sub-step B — grant admin consent. The app registration requests Microsoft Graph openid / profile / User.Read delegated permissions so it can issue tickets on behalf of signed-in users. A Global Administrator must grant admin consent in Entra ID → App registrations → (the storage account app) → API permissions → Grant admin consent. Until then, hosts can’t get tickets and you get STATUS_LOGON_FAILURE at mount.
Sub-step C — configure the clients. Entra-joined hosts must use cloud Kerberos. Current Windows 11 multi-session images support it, but you may need to set CloudKerberosTicketRetrievalEnabled = 1 via policy so the client retrieves cloud tickets. With the policy set, retrieval is automatic.
The lab below walks all of this with “done-when” checks. One thing easy to overlook in a network-locked environment is egress — the endpoints the host must reach:
| Endpoint / port | Used for | Failure if blocked |
|---|---|---|
login.microsoftonline.com (443) |
Entra auth + ticket retrieval | No Kerberos ticket → mount logon failure |
<account>.file.core.windows.net (445) |
SMB to the share | Can’t reach the share at all |
| TCP 445 outbound | SMB traffic | Mount times out (ISPs often block 445) |
| Entra/Graph endpoints (443) | App consent, identity | Consent/identity operations fail |
A note that saves hours: TCP 445 is frequently blocked by ISPs and corporate egress. Azure hosts reach Azure Files over the backbone fine, but if a mount from a laptop hangs, that’s 445, not permissions — test from a VM in Azure.
Step-by-step deep section: the FSLogix registry that actually matters
FSLogix is configured by values under HKLM\SOFTWARE\FSLogix\Profiles — two to turn it on, a few more to behave well. The canonical set, with default, valid values and gotcha:
Registry value (...\FSLogix\Profiles) |
Type | What it does | Default | Set it to | Gotcha |
|---|---|---|---|---|---|
| Enabled | DWORD | Turns profile containers on | 0 (off) | 1 | Without this, FSLogix does nothing — most common “it’s not working” |
| VHDLocations | MULTI_SZ | UNC path(s) to the profile share | (none) | \\<acct>.file.core.windows.net\<share> |
Wrong/missing path → temp profile fallback |
| VolumeType | SZ | Disk format of the container | VHDX (modern) |
VHDX | VHDX supports dynamic + larger; prefer over VHD |
| FlipFlopProfileDirectoryName | DWORD | Folder name order: %username%%sid% vs %sid%%username% |
0 | 1 | Set to 1 so folders sort by username — operational nicety |
| SizeInMBs | DWORD | Max container size (dynamic grows to this) | 30000 (~30 GB) | 30000 or per policy | Too small → container fills, profile can’t save |
| IsDynamic | DWORD | Dynamically-expanding vs fixed VHDX | 1 (dynamic) | 1 | Dynamic saves space; fixed pre-allocates |
| DeleteLocalProfileWhenVHDShouldApply | DWORD | Remove a stale local profile that blocks the container | 0 | 1 (with care) | Deletes a local profile — only when you’re sure no real data is local |
| ProfileType | DWORD | Normal vs concurrent (RW/RO) access | 0 (normal) | 0 | Non-zero only for specific RW+RO concurrent designs |
| LockedRetryCount / LockedRetryInterval | DWORD | Retries if the VHDX is locked | 12 / 5 | leave default | Tune only for known contention |
| ReAttachIntervalSeconds / ReAttachRetryCount | DWORD | Re-attach attempts after a transient drop | defaults | leave default | Raises resilience to brief share blips |
The minimum is Enabled=1 plus VHDLocations; the behaviour-tuning set is applied together in lab Step 10 below. Where these come from in production — pick one source of truth, never two (if a GPO and the golden image set the same value, last-writer-wins gives you invisible drift; for cloud-only AVD, standardize on Intune and disable the rest):
| Delivery mechanism | Best for | How it lands | Caution |
|---|---|---|---|
| Group Policy (FSLogix ADMX) | AD/Hybrid estates | GPO writes the registry | Needs AD; not the cloud-only story |
| Intune (settings catalog / config profile) | Cloud-only Entra estates | MDM writes the registry | The right fit for Entra-joined AVD |
| Image bake-in (script in the golden image) | Static config across a pool | Set once, captured in image | Re-bake to change values |
| Deployment script (CSE / DSC) | One-off or IaC-driven | Script runs at provision | Drift if hosts diverge |
| Manual (regedit/PowerShell) | Labs and testing only | You type it | Never for production fleets |
Step-by-step deep section: profile exclusions and container hygiene
By default the entire profile goes into the VHDX — including transient caches that bloat the container and cloud-synced data already in the cloud. The tool is redirections.xml (referenced via RedirXMLSourceFolder), listing folders to exclude or include. Exclusions are about size and performance, not correctness — but a 28 GB container that takes 40 seconds to attach is a recurring complaint.
The judgement calls that matter:
| Profile data | Default (in container) | Recommended | Why |
|---|---|---|---|
| OneDrive synced folder | In container | Keep in container | Smooth re-login; avoids re-sync storm each logon |
| Teams cache (classic) | In container | Often exclude transient cache | Large, regenerates; bloats the disk |
| Outlook OST / search | In container | Keep (cached mode) | Re-downloading a large OST every login is worse |
| Browser caches (temp) | In container | Exclude | Pure transient bloat |
%temp% / Windows temp |
In container | Exclude | Never needs to persist |
| Windows Defender/AV caches | In container | Exclude | Large, regenerates, can cause locks |
A minimal redirections.xml excluding transient bloat (tailor to your apps):
<?xml version="1.0" encoding="UTF-8"?>
<FrxProfileFolderRedirection ExcludeCommonFolders="0">
<Excludes>
<Exclude Copy="0">AppData\Local\Temp</Exclude>
<Exclude Copy="0">AppData\Local\Microsoft\Edge\User Data\Default\Cache</Exclude>
<Exclude Copy="0">AppData\Local\Google\Chrome\User Data\Default\Cache</Exclude>
</Excludes>
<Includes>
<!-- Explicitly keep things you care about even if a parent is excluded -->
</Includes>
</FrxProfileFolderRedirection>
Point FSLogix at the folder holding it:
Set-ItemProperty -Path "HKLM:\SOFTWARE\FSLogix\Profiles" -Name "RedirXMLSourceFolder" `
-Type String -Value "\\stfslogixlab.file.core.windows.net\profiles\redir"
Five hygiene rules keep attach times low and quotas sane: exclude transient caches (smaller VHDX → faster attach); keep cloud-synced data in the container (no re-sync storm); set a realistic SizeInMBs ceiling and use dynamic VHDX (pay for used space); schedule compaction on newer FSLogix (containers otherwise only grow); and don’t redirect everything — over-exclusion strips app state and defeats the point.
Architecture at a glance
Picture the path a profile takes at sign-in, because every later failure maps to one hop on it. A user authenticates to Entra ID and is brokered to a pooled session host — an Entra-joined Windows 11 multi-session VM with the FSLogix agent and its registry pointed (via VHDLocations) at an Azure Files SMB share. To attach the profile, the host asks Entra ID for a Kerberos ticket for the storage account (the app you consented to) and opens an SMB (port 445) session to the share. Two gates apply in order: share-level RBAC decides the session is allowed (the user has SMB Share Contributor, directly or via the default share-level permission), then NTFS ACLs decide the user may create and write their own folder (Creator Owner + users this-folder-only). FSLogix then creates or attaches Profile.vhdx, mounts it, and redirects C:\Users\<user> into it. At sign-out it flushes and detaches; the next login on any host repeats the dance and the profile follows.
Hold three things from that walk. First, the order is fixed: authenticate (Kerberos) → authorize to connect (RBAC) → authorize to act (NTFS) → attach (FSLogix). A failure at any gate falls back to a temp local profile, never forward — so an empty profile means “stopped at one of these gates” and your job is to find which. Second, the two authorization gates live in different planes (Azure IAM vs the Windows file system), set with different tools (az role assignment vs icacls) — which is why “I gave them access” is ambiguous until you say which. Third, the storage account is an Entra app; if its admin consent is missing you never reach the RBAC gate — the ticket request fails first. Keep that pipeline — ticket, connect, RBAC, NTFS, attach — as your probe order throughout.
Real-world scenario
Brightpath Legal runs a 600-seat pooled AVD estate for document-heavy legal teams across two Indian offices, entirely cloud-only: Entra-joined Windows 11 multi-session hosts, no on-prem AD, no Entra Domain Services. They were on UPD-on-a-file-server from an old RDS farm — profiles corrupted weekly and a single file VM was a scaling dead end. The brief to the two-person platform team: move to FSLogix on Azure Files with Entra ID Kerberos, no new AD, under a tight profile-storage budget (~₹14,000/month).
The build went cleanly until first user testing. They enabled Entra ID Kerberos on a Premium file share, set the default share-level permission to Contributor, set the FSLogix registry (Enabled=1, VHDLocations), and logged in a pilot user. The desktop loaded — with an empty profile. No error. The user worked, logged out, lost everything. Classic temp-profile fallback.
The diagnosis walked the pipeline in order. Kerberos? The FSLogix/SMB event logs showed the mount failing before any file operation — STATUS_LOGON_FAILURE. That ruled out NTFS and pointed at authentication. The storage account’s app registration in Entra: admin consent had not been granted — they’d enabled the feature but skipped the consent click. One Global Admin, one Grant admin consent, and the mount succeeded — straight into the second failure: the container attached read-only, FSLogix logging it couldn’t write. The default permission was correct (Contributor), but the NTFS root ACL was at the storage default, with no Modify for the users group to create their folder. The admin re-mounted with an Elevated Contributor assignment and ran the canonical icacls. Next login: created, read-write, persisted.
A week later, containers ballooned. The legal teams live in Outlook cached mode and OneDrive; with no exclusions every cache went into the VHDX — average 22 GB, attach 35–50 s, Premium quota climbing. They added a redirections.xml excluding transient browser/Teams caches (but kept OneDrive and the Outlook OST to avoid a re-sync storm), set SizeInMBs to a 30 GB ceiling with dynamic VHDX, and enabled compaction. Containers fell to ~9 GB, attach to ~8 s. Seeing the real IOPS profile, they moved Premium → transaction-optimized, landing the bill at ₹12,400/month.
Eight months on, the estate runs on a single storage account, has survived multiple golden-image re-bakes (profiles untouched — they live on the share), and scaled 50 → 600 seats with zero profile-infrastructure change. The post-mortem note: “Empty profile = stopped at a gate. Walk them in order — ticket, connect, write — never blame FSLogix until all three are clear.”
The incident as a pipeline walk — the order of checks is the method:
| Stage | Symptom | What they checked | Finding | Fix |
|---|---|---|---|---|
| 1 | Empty profile, no error | SMB/FSLogix event log | Mount failed: STATUS_LOGON_FAILURE |
(auth problem — not NTFS) |
| 2 | Logon failure | Storage account app in Entra | Admin consent not granted | Grant admin consent |
| 3 | Now mounts, still empty | FSLogix log: write denied | Container attached read-only | NTFS root ACL missing Modify |
| 4 | Read-only | NTFS ACL on the share | Default ACL, no user Modify | icacls canonical layout |
| 5 | Works, but huge & slow | Container size, attach time | 22 GB, every cache included | redirections.xml exclusions |
| 6 | Tuned | Tier vs real IOPS | Premium over-provisioned | Move to transaction-optimized |
Advantages and disadvantages
The cleanest cloud-only profile design Azure offers, trading AD’s familiarity for a two-layer permission discipline. Weigh it honestly:
| Advantages (why this model wins) | Disadvantages (why it bites) |
|---|---|
| No domain controller — cloud-only Entra-joined hosts, nothing to patch or scale | Newer than AD DS auth; some images/policies need the cloud-Kerberos toggle set |
| Azure Files gives built-in redundancy (LRS/ZRS) and scales to thousands of profiles on one account | Two authorization layers (RBAC and NTFS) — getting one right and the other wrong fails closed silently |
| Profiles survive host reimaging entirely — golden-image rebuilds never touch user data | A failed gate falls back to a temp profile with no error — data loss looks like “it worked” |
| FSLogix is the industry-standard, app-compatible profile solution (OneDrive/Teams/Outlook friendly) | All config is registry-driven — no UI; misconfiguration is a silent empty profile |
| Container size and tier are tunable for cost (dynamic VHDX, transaction-optimized tier, exclusions) | Containers only grow unless you exclude caches and schedule compaction |
| Admin consent + RBAC + NTFS map to clean, auditable least-privilege roles | Setup ordering is unforgiving — skip admin consent and nothing mounts |
| Works for Windows 365 Cloud PCs and AVD alike | TCP 445 egress and specific endpoints must be reachable — network locks break it subtly |
This model is right for any cloud-only or cloud-first AVD/W365 estate that wants rid of profile servers and AD plumbing. It is not the pick if you run heavy on-prem AD and want one Kerberos model across file servers and Azure Files — there, AD DS auth is more uniform. The disadvantages are about discipline and ordering, not capability: do the steps in sequence, set the registry from one source, apply exclusions, and the model is rock-solid.
Hands-on lab
This is the centerpiece. You’ll build a complete FSLogix-on-Azure-Files setup with Entra ID Kerberos end to end — storage account and SMB share, Kerberos enabled and consented, both permission layers, the FSLogix registry, a redirections file, validation, and teardown — three ways (portal, az CLI, Bicep). Run the CLI parts in Cloud Shell (Bash) except where a step must run on a Windows host (PowerShell), called out explicitly.
Lab prerequisites. A subscription where you are Owner, Global Administrator in the tenant (to grant admin consent), and one Entra-joined Windows 11 multi-session host you can RDP into — simplest via a one-host pool from Deploy Your First AVD Pooled Host Pool End to End. Everything else the lab creates. Region: centralindia.
The lab at a glance:
| Phase | Steps | Where | Outcome |
|---|---|---|---|
| A — Storage & share | 1–3 | Cloud Shell / portal | Account + profiles SMB share |
| B — Entra ID Kerberos | 4–5 | CLI + Entra portal | Kerberos enabled + admin consent |
| C — Permissions (both layers) | 6–8 | IAM + session host | RBAC + NTFS set |
| D — FSLogix on the host | 9–11 | Session host (PowerShell) | Agent + registry + redirections |
| E — Validate | 12–13 | Session host | Container attaches read-write |
| F — Teardown | 14 | Cloud Shell | Everything deleted |
Phase A — storage account and SMB share
Step 1 — variables and resource group.
RG=rg-fslogix-lab
LOC=centralindia
ST=stfslogixlab$RANDOM # storage account names are global + lowercase, 3–24 chars
SHARE=profiles
az group create -n $RG -l $LOC -o table
Expected: a resource-group row with provisioningState: Succeeded.
Step 2 — create the storage account (Standard, with large file shares enabled; the directory/Kerberos option follows in Step 4).
az storage account create -n $ST -g $RG -l $LOC \
--sku Standard_LRS --kind StorageV2 \
--enable-large-file-share \
--https-only true \
-o table
Expected: an account row, provisioningState: Succeeded, kind: StorageV2. (Use Standard_ZRS for zone redundancy; LRS is fine for a lab.)
Step 3 — create the file share with a quota (100 GB here; size for users × container-size in production).
az storage share-rg create --storage-account $ST -g $RG \
--name $SHARE --quota 100 --access-tier TransactionOptimized -o table
Expected: a share named profiles. Validate it exists:
az storage share-rg show --storage-account $ST -g $RG --name $SHARE \
--query "{name:name, quota:properties.shareQuota, tier:properties.accessTier}" -o table
Portal (Steps 1–3): Create a resource → Storage account (Standard, LRS/ZRS, Central India, large file shares enabled) → File shares → + File share →
profiles, set quota and tier.
Phase B — enable Entra ID Kerberos and grant consent
Step 4 — enable Microsoft Entra ID Kerberos. Sets identity-based auth to AADKERB and registers the account as an app.
az storage account update -n $ST -g $RG \
--enable-files-aadkerb true -o table
Expected: the update succeeds. Validate the directory option flipped:
az storage account show -n $ST -g $RG \
--query "azureFilesIdentityBasedAuthentication.directoryServiceOptions" -o tsv
# Expected output: AADKERB
Portal equivalent: Storage account → File shares → Active Directory: Not configured → Set up → Microsoft Entra Kerberos → Save.
Step 5 — grant admin consent to the storage account app (the step everyone forgets). Enabling Kerberos created an app registration that needs its Graph permissions consented — a portal/Entra action (no single az command for the consent click):
- In the portal go to Microsoft Entra ID → App registrations → All applications.
- Search for the app named like
[Storage Account] <your-account-name>.file.core.windows.net. - Open it → API permissions. You’ll see Microsoft Graph permissions (e.g.
openid,profile,User.Read) with status “Not granted”. - Click Grant admin consent for
<tenant>→ Yes.
Expected/validate: every permission row shows a green tick and “Granted for <tenant>”. Mandatory — until it’s green, every mount fails with a logon error and nothing downstream works.
Phase B is done when two things are true: directoryServiceOptions reads AADKERB (Step 4) and the app’s API permissions show “Granted for <tenant>” in green (Step 5).
Phase C — both permission layers
Step 6 — Layer 1: assign share-level RBAC. Give your AVD users Contributor and yourself Elevated Contributor (to set NTFS in Step 8), scoped to the account.
ST_ID=$(az storage account show -n $ST -g $RG --query id -o tsv)
# The AVD users group (replace with your group's object id)
USERS_GROUP_OID=<object-id-of-your-avd-users-group>
az role assignment create --assignee-object-id $USERS_GROUP_OID \
--assignee-principal-type Group \
--role "Storage File Data SMB Share Contributor" \
--scope $ST_ID -o table
# Yourself, elevated, to set NTFS ACLs
ME_OID=$(az ad signed-in-user show --query id -o tsv)
az role assignment create --assignee-object-id $ME_OID \
--assignee-principal-type User \
--role "Storage File Data SMB Share Elevated Contributor" \
--scope $ST_ID -o table
Expected: two role-assignment JSON/table rows. Validate:
az role assignment list --scope $ST_ID \
--query "[].{who:principalName, role:roleDefinitionName}" -o table
Step 7 — (recommended) set a default share-level permission so all authenticated Entra identities get a baseline role without per-user assignments — the scalable pattern for hundreds of users.
az storage account update -n $ST -g $RG \
--default-share-permission StorageFileDataSmbShareContributor -o table
Expected: succeeds. Validate it reads back as StorageFileDataSmbShareContributor:
az storage account show -n $ST -g $RG \
--query "azureFilesIdentityBasedAuthentication.defaultSharePermission" -o tsv
With a default share-level permission of
StorageFileDataSmbShareContributoryou can skip the per-group assignment in Step 6 for the users — keep Elevated Contributor on yourself for NTFS work. The valid values map to the same RBAC roles from the Layer-1 table:None,StorageFileDataSmbShareReader,...Contributor(the FSLogix baseline), and...ElevatedContributor(usually too broad as a default).
Step 8 — Layer 2: set NTFS permissions. Do this from a machine that has mounted the share with your Elevated-Contributor identity — typically the session host (PowerShell). Mount using your Entra identity (the OS uses your Kerberos ticket; no key):
# On the Entra-joined session host, as your (Elevated Contributor) user:
net use Z: \\stfslogixlab.file.core.windows.net\profiles
Expected: The command completed successfully. Now apply the canonical FSLogix NTFS layout to the share root (Z:\):
# Users can create their own folder (this folder only, no inherit into siblings)
icacls Z:\ /grant "YourTenant\AVD Users:(M)"
# Creator Owner gets Modify on what they create (subfolders + files)
icacls Z:\ /grant "Creator Owner:(OI)(CI)(IO)(M)"
# Admins full control
icacls Z:\ /grant "BUILTIN\Administrators:(OI)(CI)(F)"
# Remove broad inherited rights you don't want users to have on each other's folders
icacls Z:\ /remove:g "Authenticated Users"
Expected: Successfully processed 1 files for each. Validate the resulting ACL:
icacls Z:\
You should see your users group with (M) on this folder, CREATOR OWNER with (OI)(CI)(IO)(M), and Administrators (F). The flag cheat-sheet so the icacls lines aren’t magic:
icacls flag |
Meaning |
|---|---|
(M) |
Modify (read/write/delete, not change-permissions) |
(F) |
Full control |
(OI) |
Object inherit (applies to files) |
(CI) |
Container inherit (applies to subfolders) |
(IO) |
Inherit only (the entry itself doesn’t apply to this folder) |
/remove:g |
Remove a granted ACE for the principal |
Phase D — FSLogix on the session host
Step 9 — install the FSLogix agent (it ships in current Windows 11 multi-session/AVD images; install only if absent):
# On the session host (PowerShell as admin) — only if FSLogix isn't already present
# Download from aka.ms/fslogix-latest, extract, then:
.\x64\Release\FSLogixAppsSetup.exe /install /quiet /norestart
Expected: the frxsvc (FSLogix Apps Service) is installed. Validate:
Get-Service frxsvc | Select-Object Status, Name, DisplayName
# Expected: Status = Running
Step 10 — set the FSLogix registry (the heart of the config), on the host as admin:
$key = "HKLM:\SOFTWARE\FSLogix\Profiles"
New-Item -Path $key -Force | Out-Null
Set-ItemProperty -Path $key -Name "Enabled" -Type DWord -Value 1
Set-ItemProperty -Path $key -Name "VHDLocations" -Type MultiString -Value "\\stfslogixlab.file.core.windows.net\profiles"
Set-ItemProperty -Path $key -Name "VolumeType" -Type String -Value "VHDX"
Set-ItemProperty -Path $key -Name "FlipFlopProfileDirectoryName" -Type DWord -Value 1
Set-ItemProperty -Path $key -Name "SizeInMBs" -Type DWord -Value 30000
Set-ItemProperty -Path $key -Name "IsDynamic" -Type DWord -Value 1
Set-ItemProperty -Path $key -Name "DeleteLocalProfileWhenVHDShouldApply" -Type DWord -Value 1
Expected: no errors. Validate the values landed:
Get-ItemProperty -Path $key | Select-Object Enabled, VHDLocations, VolumeType, SizeInMBs
# Expected: Enabled=1, VHDLocations points at your share, VolumeType=VHDX, SizeInMBs=30000
Step 11 — (optional) add the redirections.xml exclusions. Create a redir folder on the share, drop redirections.xml there, and point FSLogix at it:
New-Item -ItemType Directory -Path "Z:\redir" -Force | Out-Null
# Save the redirections.xml from the earlier section into Z:\redir\redirections.xml
Set-ItemProperty -Path $key -Name "RedirXMLSourceFolder" -Type String `
-Value "\\stfslogixlab.file.core.windows.net\profiles\redir"
FSLogix reads it at the next logon.
Phase E — validate an attached container end to end
Step 12 — sign in as a test user and confirm the container attaches read-write. Add a test user (in the AVD Users group / covered by the default permission) to the host pool’s app group, then sign in as that user via the AVD client. After the desktop loads:
- Open Disk Management (or
Get-Disk) — you should see an extra attached VHDX disk: the container mounted. - On the share, a per-user folder now exists (
<SID>_<username>per FlipFlop) containingProfile.vhdx. Check from Cloud Shell:
az storage file list --account-name $ST --share-name $SHARE \
--auth-mode login -o table
# Expected: a folder named after the test user's SID/username, plus the 'redir' folder
Step 13 — confirm FSLogix loaded the profile (not a temp fallback). Check the FSLogix log and event log on the host:
# FSLogix logs live here:
Get-Content "C:\ProgramData\FSLogix\Logs\Profile\*.log" -Tail 40
# Look for: "Loading Profile" / "Attached VHD" / "VirtualDisk attach succeeded"
# A line like "ProfileType ... TEMP" or "falling back" means it did NOT attach — go to troubleshooting.
Also confirm in the FSLogix event log:
Get-WinEvent -LogName "Microsoft-FSLogix-Apps/Operational" -MaxEvents 20 |
Format-Table TimeCreated, Id, LevelDisplayName, Message -Wrap
Expected: events showing the container located, attached, and loaded — no temp-profile/fallback warning. A fallback maps straight to the troubleshooting table: logon failure → Kerberos/consent, write-denied → NTFS, access-denied at connect → RBAC.
The validation checklist — what “working” looks like at each layer:
| Check | Where | “Good” signal | “Bad” signal → section |
|---|---|---|---|
| Share mounts | net use on host |
“completed successfully” | logon failure → Kerberos/consent |
| Per-user folder created | az storage file list |
folder + Profile.vhdx exists |
nothing created → NTFS/RBAC |
| Disk attached | Disk Management / Get-Disk |
extra VHDX disk present | no disk → attach error |
| FSLogix log | C:\ProgramData\FSLogix\Logs |
“attach succeeded” | “TEMP”/“fallback” → troubleshooting |
| Profile persists | log out / log in | data survives | empty again → read-only/quota |
Phase F — teardown
Step 14 — delete everything so the lab costs nothing. Remove the role assignments, then the resource group:
# Remove the role assignments you created (optional; deleting the RG removes scoped ones)
az role assignment delete --scope $ST_ID \
--role "Storage File Data SMB Share Elevated Contributor" --assignee $ME_OID 2>/dev/null
# Delete the whole resource group (storage account + share) — irreversible
az group delete -n $RG --yes --no-wait
On the session host, undo the FSLogix registry if you’ll reuse the host:
Remove-Item -Path "HKLM:\SOFTWARE\FSLogix\Profiles" -Recurse -Force
net use Z: /delete
Expected: the resource group enters Deleting. Confirm it’s gone:
az group exists -n $RG # Expected: false (after a minute or two)
The storage account’s app registration in Entra can be removed manually from App registrations if you want a fully clean tenant.
The Bicep version (commit this instead of clicking)
For repeatable, reviewed infrastructure, here is storage + Kerberos + default-permission + share + RBAC as Bicep. NTFS (icacls) and the FSLogix registry stay outside IaC — they run inside the OS, delivered via Intune/CSE.
@description('Region for the FSLogix profile storage')
param location string = resourceGroup().location
@description('Globally-unique storage account name (lowercase, 3-24 chars)')
param storageAccountName string
@description('Object ID of the AVD users group that gets SMB Contributor')
param avdUsersGroupObjectId string
var shareName = 'profiles'
resource sa 'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: storageAccountName
location: location
sku: { name: 'Standard_LRS' } // or Standard_ZRS for zone redundancy
kind: 'StorageV2'
properties: {
supportsHttpsTrafficOnly: true
largeFileSharesState: 'Enabled'
minimumTlsVersion: 'TLS1_2'
azureFilesIdentityBasedAuthentication: {
directoryServiceOptions: 'AADKERB' // Entra ID Kerberos
defaultSharePermission: 'StorageFileDataSmbShareContributor' // baseline for all users
}
}
}
resource fileService 'Microsoft.Storage/storageAccounts/fileServices@2023-05-01' = {
parent: sa
name: 'default'
}
resource profileShare 'Microsoft.Storage/storageAccounts/fileServices/shares@2023-05-01' = {
parent: fileService
name: shareName
properties: {
shareQuota: 100 // GB; size for users x container size in prod
accessTier: 'TransactionOptimized'
enabledProtocols: 'SMB'
}
}
// Layer 1 RBAC: AVD users group -> SMB Share Contributor on the account
resource usersContributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(sa.id, avdUsersGroupObjectId, 'smb-contributor')
scope: sa
properties: {
// Storage File Data SMB Share Contributor
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions',
'0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')
principalId: avdUsersGroupObjectId
principalType: 'Group'
}
}
output storageAccountName string = sa.name
output profileShareUnc string = '\\\\${sa.name}.file.core.windows.net\\${shareName}'
Deploy it and read the UNC straight into your FSLogix VHDLocations:
az deployment group create -g rg-fslogix-lab \
--template-file fslogix.bicep \
--parameters storageAccountName=stfslogixlab$RANDOM \
avdUsersGroupObjectId=<your-group-object-id> \
--query "properties.outputs.profileShareUnc.value" -o tsv
What Bicep cannot do here: the admin consent (Step 5) and the NTFS icacls (Step 8) aren’t ARM operations — consent is an Entra tenant action, NTFS lives in the file system. Template the storage plane; script the OS/identity plane.
Common mistakes & troubleshooting
Most of your first-time effort goes here. Every failure below ends in the same visible symptom — an empty or non-persisting profile — so you diagnose by walking the pipeline (ticket → connect → write → attach) and matching the log line. The playbook, ordered by how often it bites:
| # | Symptom | Root cause | Confirm (exact place / command) | Fix |
|---|---|---|---|---|
| 1 | Empty profile, no error; mount fails STATUS_LOGON_FAILURE |
Admin consent not granted on the storage account app | Entra → App registrations → (account app) → API permissions shows “Not granted” | Grant admin consent (Step 5) |
| 2 | Container attaches read-only; FSLogix log “write denied” | NTFS ACL missing user Modify (Layer 2) | icacls Z:\ shows no Modify for users group |
Apply canonical icacls (Step 8) |
| 3 | “You do not have permission to access” at connect | Share-level RBAC missing (Layer 1) | az role assignment list --scope <acct> lacks Contributor; default permission None |
Assign Contributor / set default permission |
| 4 | Mount hangs / times out from a non-Azure machine | TCP 445 blocked by ISP/egress | Test-NetConnection <acct>.file.core.windows.net -Port 445 fails |
Test from an Azure VM; use Private Endpoint |
| 5 | Profile loads but is a temp profile every login | Enabled=0, wrong VHDLocations, or stale local profile blocking |
FSLogix log “TEMP”/“fallback”; check registry | Set Enabled=1, fix UNC, set DeleteLocalProfileWhenVHDShouldApply=1 |
| 6 | Profile can’t save / disk full mid-session | SizeInMBs too small or share quota exhausted |
Container at ceiling; az storage share-rg show quota near full |
Raise SizeInMBs; raise share quota; add exclusions |
| 7 | Logins take 30–60 s | Bloated container (no exclusions) / Premium-vs-tier mismatch | Container 20 GB+; attach time in FSLogix log | Add redirections.xml; enable compaction |
| 8 | 0x0000000e / attach error in event log |
VHDX locked by another session or a crashed prior session | FSLogix event log attach failure; another host holds the file | Ensure single-session profile; clear stale lock; check ProfileType |
| 9 | Kerberos works for hybrid users, fails for cloud-only users | Client not retrieving cloud Kerberos tickets | CloudKerberosTicketRetrievalEnabled not set on host |
Set the policy/registry to 1 on all hosts |
| 10 | icacls itself fails “Access is denied” |
You mounted as Contributor, not Elevated | Your role on the account is Contributor only | Re-assign Elevated Contributor, re-mount, retry |
| 11 | Works on one host, temp profile on another | Registry drift — VHDLocations only on some hosts |
Compare Get-ItemProperty ...FSLogix\Profiles across hosts |
Deliver registry from one source (Intune) |
| 12 | Container created but app settings still reset | Over-exclusion — you excluded folders apps need | redirections.xml excludes AppData\Roaming\... app state |
Narrow exclusions to transient caches only |
Three reading habits that save the most time:
| Distinction | The trap | How to tell them apart |
|---|---|---|
| Auth failure vs NTFS failure | Both end in an empty profile | A logon failure in the SMB/FSLogix log = auth (Kerberos/consent); a write-denied = NTFS |
| RBAC vs NTFS “access denied” | Both say “denied” | RBAC denial happens at connect (can’t even mount); NTFS denial happens after mount on a file op |
| Temp-profile fallback vs real load | The desktop looks fine either way | The FSLogix log explicitly says TEMP/fallback, and no VHDX disk is attached in Disk Management |
The diagnostic order to internalize: (1) does the share mount (net use)? No → Kerberos/consent/445. Yes → (2) does a per-user folder + Profile.vhdx get created? No → RBAC or NTFS. Yes → (3) is it read-write (Disk Management + FSLogix log)? No → NTFS Modify / quota. Yes → it works; any remaining “lost settings” is exclusions.
Best practices
Crisp, production-grade rules from estates that run this at scale:
- Set the registry from one source of truth — for cloud-only AVD that’s Intune. Never mix Intune + GPO + image bake-in for the same values; drift is invisible and causes “works on one host” tickets.
- Use the default share-level permission, not hundreds of per-user assignments. Set it to Contributor once; reserve explicit assignments for exceptions.
- Grant admin consent immediately after enabling Kerberos — make it a checklist gate; nothing downstream works without it and the failure is silent.
- Set NTFS with the canonical Creator-Owner + this-folder-only layout so users create their own folder and cannot see others’; admins get Full Control for cleanup.
- Keep cloud-synced data (OneDrive, Outlook OST) in the container, exclude only transient caches. Excluding OneDrive triggers a re-sync storm every login; including every cache bloats the disk.
- Use dynamic VHDX with a sane
SizeInMBsceiling and enable periodic compaction — containers otherwise only grow. - Pick the redundancy you actually need — ZRS for zone resilience; weigh GRS against cost (profiles are usually recreatable, so cross-region DR is often overkill).
- Size the share for
users × average-container × headroomand alert on share-used and per-container size before users hit “disk full”. - Alert on FSLogix temp-profile/fallback events — they mean silent data loss, not just a slow login.
- Validate mounts from an Azure VM, never a laptop — TCP 445 egress will otherwise mislead you.
- One profile = one user at a time unless you deliberately use a concurrent
ProfileTypeor CloudCache; otherwise you get lock/attach errors. - Bake the FSLogix agent into the golden image but deliver config via policy, so you change behaviour without re-imaging.
Security notes
Built on least-privilege identity, the posture is good if you keep the layers tight:
- Least privilege across both layers. Users get exactly SMB Share Contributor (not Elevated, not account Owner); only the setup admin holds Elevated Contributor, transiently, to set NTFS. Audit IAM so no human keeps standing Elevated rights.
- NTFS privacy by design. The canonical ACL (this-folder-only + Creator Owner) means one user cannot read another’s profile — a real confidentiality control. Verify with
icaclsafter setup; a too-broad inherited ACE leaks profiles. - No storage account keys for profiles. Auth is Entra ID Kerberos — no shared key in a connection string to leak. Disable shared-key access (
allowSharedKeyAccess=false) once Kerberos is proven. - Encryption. Azure Files encrypts at rest by default (Microsoft-managed keys; bring customer-managed keys if required). SMB 3.x encrypts in transit — enforce SMB encryption and secure transfer (HTTPS) on the account.
- Network isolation. For sensitive estates, put the account behind a Private Endpoint so the share is reachable only from your VNet (also sidesteps TCP-445 egress questions); pair with private DNS — see Azure Private Endpoint vs Service Endpoint.
- Admin-consent governance. The consented app has only
openid/profile/User.Readscopes — minimal — but treat the consent as auditable and restrict who can grant it. - Treat the profile as sensitive data (saved passwords, tokens, cached docs) — guard the share’s RBAC and NTFS as you would a data store, not “just profiles”.
Cost & sizing
What drives the bill is the file share: capacity (GB across all containers), the tier (Premium provisioned IOPS vs Standard pay-as-you-go), redundancy (LRS < ZRS < GRS), and egress (negligible — traffic stays on the backbone). FSLogix is free and Entra ID Kerberos adds no cost. The lever is right-tiering and keeping containers small.
| Cost driver | What it is | How to right-size | Rough figure |
|---|---|---|---|
| Share capacity (Standard) | GB stored, pay-as-you-go | Exclusions + dynamic VHDX + compaction | ~₹4–6 / GB / month (transaction-optimized) |
| Transactions (Standard) | Per-operation charges | Fewer, larger I/O; right tier | Small for typical profile I/O |
| Provisioned share (Premium) | You pay for provisioned GB/IOPS | Only if you measured high IOPS need | Higher baseline; over-provisioned easily |
| Redundancy uplift | LRS → ZRS → GRS | Pick the lowest that meets your RPO | ZRS modest uplift; GRS ~2× |
| Per-container size | Avg VHDX GB × users | Exclusions; SizeInMBs ceiling | 5–10 GB/user typical with exclusions |
The tier decision — most FSLogix estates do not need Premium:
| File tier | When it’s right for FSLogix | Watch out |
|---|---|---|
| Transaction-optimized (Standard) | Most pooled AVD profile workloads | Transaction charges if I/O is very chatty |
| Hot (Standard) | General-purpose, balanced | Slightly higher storage, lower transactions |
| Premium (provisioned) | Very large/IOPS-heavy estates that measured the need | Easy to over-provision and overpay |
A worked example: 600 users × 9 GB average after exclusions = ~5.4 TB. On a transaction-optimized Standard share at ~₹5/GB that’s roughly ₹27,000/month before transactions — most estates land lower because dynamic VHDX bills used, not max, space. The classic over-spend is putting that workload on Premium “to be safe”, provisioning IOPS it never uses. Free-tier note: there’s no free tier for Azure Files sized for profiles — the lab stays cheap only because it’s tiny; delete it.
Size the quota for users × average-container-GB × headroom (1.3–1.5×), enable large file shares, and alert on share-used. Under-sizing the quota or SizeInMBs causes mid-session “can’t save” failures — size generously; it’s cheap relative to a data-loss ticket.
Interview & exam questions
Mapped to AZ-140 (Azure Virtual Desktop Specialty) and the storage/identity portions of AZ-104.
Q1. Why does pooled AVD need FSLogix when personal desktops don’t? Pooled hosts are non-persistent and load-balanced, so a user can land on any host and must not depend on a local C: profile. FSLogix stores the profile as a VHDX on shared storage and attaches it at logon, so it follows the user to whichever host they get. Personal desktops keep the profile locally because the user always returns to the same VM.
Q2. What are the two authorization layers for FSLogix on Azure Files, and what does each control?
Share-level RBAC (Azure roles like Storage File Data SMB Share Contributor) controls whether an identity may connect to the share at all. NTFS permissions (set with icacls) control what they may do once connected. Both must allow the operation; either being wrong fails closed.
Q3. Which RBAC role do AVD users need, and which does the admin setting permissions need? Users need Storage File Data SMB Share Contributor. The admin who sets NTFS ACLs needs Storage File Data SMB Share Elevated Contributor, because modifying NTFS permissions is itself privileged and plain Contributor cannot do it.
Q4. What does Microsoft Entra ID Kerberos give you over AD DS authentication for Azure Files? It authenticates SMB sessions using Kerberos tickets issued by Entra ID with no domain controller required — ideal for cloud-only, Entra-joined hosts. AD DS authentication requires you to run domain controllers (your own or via Entra Domain Services).
Q5. After enabling Entra ID Kerberos, mounts fail with a logon error. Most likely cause? Admin consent has not been granted to the storage account’s app registration in Entra ID. Enabling the feature creates the app with Graph permissions “not granted”; a Global Admin must consent before any host can obtain a ticket.
Q6. Name the two registry values that are mandatory to turn FSLogix on.
Enabled (DWORD = 1) and VHDLocations (MULTI_SZ, the UNC path to the share), both under HKLM\SOFTWARE\FSLogix\Profiles. Without Enabled=1 FSLogix does nothing; without a correct VHDLocations it can’t find the share and falls back to a temp profile.
Q7. A user’s container attaches read-only. Which layer is wrong and how do you confirm?
The NTFS layer (Layer 2) — the user lacks Modify. Confirm with icacls on the share root (no Modify for the users group) and the FSLogix log showing write-denied. RBAC is fine because the mount succeeded; the failure is a file operation after connecting.
Q8. Why keep OneDrive inside the container but exclude transient caches? Excluding OneDrive forces a full re-sync every login (network storm, slow first use); keeping it preserves the synced state for a fast experience. Transient caches (browser/Teams temp) are excluded because they regenerate and only bloat the disk.
Q9. What’s the difference between dynamic and fixed VHDX, and which is preferred?
A dynamic VHDX grows with actual data up to SizeInMBs (you pay for used space); a fixed VHDX pre-allocates the full size. Dynamic is preferred for cost — most profiles use a fraction of their ceiling — with periodic compaction to reclaim freed space.
Q10. A mount hangs from your laptop but works on the session host. Why? TCP port 445 (SMB) is frequently blocked by ISP/corporate egress, so the laptop can’t reach Azure Files, while the in-Azure host reaches it over the backbone. Validate mounts from an Azure VM, or use a Private Endpoint.
Q11. What is the symptom when FSLogix can’t attach a container, and why is it dangerous? It falls back to a temporary local profile — a working but empty desktop with no error; the user works and loses it at logout. It’s dangerous because it looks like success, so you must alert on FSLogix fallback/temp events to catch silent data loss.
Q12. How do you grant share access to hundreds of users without hundreds of role assignments? Set the account’s default share-level permission to Contributor, granting all authenticated Entra identities that baseline automatically. Use explicit per-identity assignments only for exceptions, and keep Elevated Contributor for admins.
Quick check
- Which two registry values are the bare minimum to enable FSLogix profile containers?
- You enabled Entra ID Kerberos but every mount returns a logon failure. What did you most likely skip?
- A container attaches but is read-only. Which permission layer is wrong — RBAC or NTFS?
- Why should OneDrive stay inside the container while browser caches are excluded?
- Which RBAC role does an admin need to run
icaclsto set NTFS permissions on the share?
Answers
Enabled= 1 andVHDLocations(the UNC path to the share), both underHKLM\SOFTWARE\FSLogix\Profiles.- Granting admin consent to the storage account’s app registration in Entra ID — without it, hosts can’t get Kerberos tickets and the mount fails with
STATUS_LOGON_FAILURE. - NTFS (Layer 2). RBAC let the mount succeed; the user lacks Modify to write the file, so the failure is on a file operation after connecting.
- Keeping OneDrive in the container avoids a full re-sync storm every login; browser caches are pure transient bloat that regenerates, so excluding them keeps the VHDX small and attach fast.
- Storage File Data SMB Share Elevated Contributor — modifying NTFS ACLs is privileged and plain Contributor can’t do it.
Glossary
- FSLogix — Microsoft agent that packages a user profile into a VHDX and attaches it at logon, so profiles roam on pooled session hosts.
- Profile container — the per-user VHDX holding the entire profile; FSLogix creates, attaches and detaches it.
- VHDLocations — the FSLogix registry value (MULTI_SZ) pointing to the UNC path(s) of the share where containers live.
- Azure Files — Azure’s managed SMB file-share service; here, the redundant home for the VHDX containers.
- Microsoft Entra ID Kerberos — cloud Kerberos auth for Azure Files SMB that needs no domain controller; Entra issues the ticket.
- Storage account app registration — the Entra app for the storage account, created when Kerberos is enabled; needs admin consent.
- Admin consent — a Global Admin granting that app its Graph permissions; mandatory before any host can mount with Kerberos.
- Share-level RBAC — Azure roles (Reader/Contributor/Elevated Contributor) controlling whether an identity may connect (Layer 1).
- NTFS permissions — Windows ACLs (set with
icacls) controlling what an identity may do once connected (Layer 2). - Default share-level permission — an account setting granting all authenticated Entra identities a baseline role, avoiding per-user assignments.
- icacls — the Windows CLI tool for viewing/editing NTFS ACLs; applies the canonical FSLogix layout.
- redirections.xml — the FSLogix file listing folders to exclude/include, controlling container size and redundant sync.
- CloudCache — an FSLogix mode caching locally over one or more remote VHDX locations, for resilience or multi-region.
- Temp-profile fallback — FSLogix’s failure behaviour: it loads a temporary local profile, silently risking data loss.
- SizeInMBs — the registry value capping the container’s max size; a dynamic VHDX grows up to this ceiling.
Next steps
- Stand up the pool these profiles serve with Deploy Your First AVD Pooled Host Pool End to End, then point its hosts at this share.
- Decide whether you even need FSLogix with AVD Host Pool: Personal vs Pooled — Deciding the Right Model.
- Choose the share’s redundancy deliberately using Azure Storage Redundancy: LRS, ZRS, GRS, RA-GRS Explained.
- Lock the share behind a Private Endpoint with Azure Private Endpoint vs Service Endpoint.
- Compare the desktop platforms with Windows 365 Cloud PC vs AVD: Choosing Between Them.