Topics: Connected Cache

Connected Cache

Microsoft Connected Cache (MCC) can be deployed alongside FluxDeploy relay sites to cache Windows Update, Microsoft Defender, Microsoft 365, and Intune Win32 app content locally. This reduces WAN bandwidth by serving cached Microsoft content to client devices at each site.

Overview

MCC runs as a container on each relay server - inside a WSL2 VM on Windows, as a Docker/Moby container on Linux. FluxDeploy Core manages the Azure-side provisioning and pushes deployment parameters to relays via the heartbeat mechanism.

Prerequisites

  • Azure subscription with pay-as-you-go billing (MCC resource itself is free)
  • Azure App Registration dedicated to Connected Cache (not the Autopilot one), holding the Contributor role assigned at the scope of the resource group that holds the Connected Cache resource. That is an Azure RBAC role assignment, not a Microsoft Graph API permission, so there is no admin consent step. Contributor is what lets FluxDeploy create the cache resource, register a cache node per relay site, and read each node's provisioning keys. The tenant ID, the app's client ID and a client secret go into Settings > Cloud Integrations > Connected Cache
  • Azure CLI on the Core host - the Core server shells out to az mcc ent ... to provision Azure resources, so the Azure CLI must be installed on the machine running FluxDeploy Core, on its PATH before the Core service starts (a Windows service captures PATH at boot; install az then reboot / reinstall Core). The mcc CLI extension is auto-installed on first use.
  • Windows relays: Windows 11 22631.3296+ or Server 2022, with virtualization available (WSL2 is installed automatically if missing - see below)
  • Linux relays: Ubuntu 24.04 or RHEL 8.x/9.x. The Moby/Docker container engine is installed automatically if missing. The relay must have been installed with the tarball's install.sh, which also installs the FluxDeploy MCC root helper (fluxdeploy-mcc-run.path + service) - the hardened relay service itself cannot run Docker, so all container operations go through this helper. If a relay was upgraded by just unpacking the tarball, the deploy aborts with an explicit error telling you to re-run install.sh
  • Ports 80 and 443 available on relay servers (FluxDeploy configures the relay side automatically). HTTPS is mandatory: Intune Win32 app and Teams content is served over HTTPS only, so an HTTP-only cache node caches nothing useful. Every cache node therefore needs a certificate the clients trust - see Certificates (HTTPS is required).

Pre-check (minimum requirements)

Connected Cache has host requirements that Microsoft's own installers enforce, and a host that misses one fails the deployment - historically fifteen minutes in, with a vendor return code and little else. FluxDeploy checks the whole list up front instead, and reports every unmet requirement at once, so you fix the lot and retry once.

Run it on demand. Open the relay site, go to its Connected Cache tab, and use Run pre-check in the Pre-check panel. The checks execute on the relay itself - only the relay can see its own disk, memory, distribution and ports - so the request travels out on the relay's next check-in and the result comes back on the one after. The relay's heartbeat accelerates to about 15 seconds while a pre-check is outstanding, so this normally takes seconds rather than minutes. If the relay does not answer within five minutes the panel says so rather than spinning.

Each result line tells you three things: what was required, what was found on the host, and what to do about it. Items marked Microsoft requirement are enforced by Microsoft's installer, so working around one is not possible - the deployment would be refused anyway, just later and less clearly.

Two severities, and they mean different things.

  • Must be fixed (red) - the deployment cannot succeed. Enabling Connected Cache is blocked while any of these stand.
  • Worth noting (amber) - advice, not a refusal. Nothing blocks on these, because no Microsoft installer check enforces them. Free RAM below 4 GB is the common one: it is Microsoft's documented minimum but nothing in their scripts tests it, and cache nodes have been verified running on less.

Enabling is gated on the pre-check. If the most recent pre-check found anything that must be fixed, the Enable button is disabled and names the reason. Warnings never block. A pre-check older than 30 minutes is marked Out of date and no longer counts either way - a host's disk and ports change, so re-run it before relying on it. Whatever happens here, the relay runs the identical checks again immediately before it installs anything, so a deployment can never proceed on a host that does not meet the requirements.

What is checked

Linux relays

Requirement Severity Source
Ubuntu 20.04 / 22.04 / 24.04, or RHEL 8.x / 9.x Must be fixed Microsoft
x86_64 architecture Must be fixed Microsoft
lsb_release installed (Ubuntu - Microsoft's script reads the version with it) Must be fixed Microsoft
systemd is the init system Must be fixed Microsoft
podman not installed (RHEL only - see below) Must be fixed Microsoft
openssl, wget, sudo present Must be fixed Microsoft
curl, python3 present (FluxDeploy fetches and extracts the deployment package) Must be fixed FluxDeploy
The cache filesystem is at least as large as the configured cache size Must be fixed Microsoft
Outbound HTTPS to geomcc.prod.do.dsp.mp.microsoft.com, with Microsoft's pinned intermediate certificate intact Must be fixed Microsoft
Ports 80 and 443 free (an existing cache container's docker-proxy is fine) Must be fixed FluxDeploy
Free space on the cache path Worth noting FluxDeploy
4 GB RAM Worth noting FluxDeploy
crontab present (Microsoft installs a host-update job and only warns if it cannot) Worth noting Microsoft

The cache-size check reproduces Microsoft's exactly, and it is easy to misread: their script measures the total size of the filesystem holding the cache directory, not its free space, and compares that against the cache size you configured. There is no fixed floor. That is why free space is only a warning here - a full disk is not something Microsoft's installer refuses, though the cache obviously cannot grow past it.

If outbound HTTPS to Microsoft is being intercepted by a proxy, this check catches it. Microsoft pins the intermediate certificate of their Geo endpoint and exits rather than continue when it does not match, so a TLS-inspecting proxy must be configured to exempt those hosts.

Windows relays

Requirement Severity Source
Not Server Core (Desktop Experience required) Must be fixed Microsoft
Windows 11 build 22631+ / Windows Server 2022 build 20348+ Must be fixed Microsoft
x64 architecture Must be fixed Microsoft
Cache size greater than 100 GB (the WSL2 installer refuses 100 or less, ReturnCode D00057) Must be fixed Microsoft
At least 150 GB free on the install drive (ReturnCode D00039) Must be fixed Microsoft
The install location is a local drive (the cache VHDX cannot live on a network path) Must be fixed FluxDeploy
The install drive is a fixed local NTFS or ReFS volume Must be fixed FluxDeploy
Free space covers the configured cache size (the cache image is created at full size) Must be fixed FluxDeploy
The VirtualMachinePlatform, WSL and Hyper-V Windows features exist on this edition Must be fixed FluxDeploy
Hyper-V's hypervisor is actually running (checked once Hyper-V is enabled) Must be fixed FluxDeploy
The relay is not a domain controller (Connected Cache needs two local accounts) Must be fixed FluxDeploy
The Appx provisioning cmdlets are available (the Connected Cache app is provisioned with them) Must be fixed FluxDeploy
The Task Scheduler and AppX Deployment services are not disabled Must be fixed FluxDeploy
No leftover FluxDeployMccCache profile directory without the account Must be fixed FluxDeploy
No MCC_* scheduled tasks with nothing installed behind them Must be fixed FluxDeploy
No previous installation left behind with none of its MCC_* tasks Must be fixed FluxDeploy
Ports 80 and 443 free (an existing WSL port forward is fine) Must be fixed FluxDeploy
The policy Network access: Do not allow storage of passwords and credentials is disabled Must be fixed FluxDeploy
Free space for the WSL distribution and container image on top of the cache Worth noting FluxDeploy
4 GB RAM Worth noting FluxDeploy

The free-disk figure and the cache size are different quantities with different floors. 150 GB free on the install drive is what Microsoft's WSL installer measures before it creates the cache VHDX; the cache size is how large that VHDX will be. Both are checked, because neither covers the other: Microsoft's floor is stricter for a small cache, and the configured size is stricter for a large one - a 500 GB cache on a drive with 160 GB free clears the vendor floor and then cannot be created at all.

Size the data drive for the cache PLUS 150 GB, not for the cache alone. This is the one that catches people, because a drive sized to just fit the cache works perfectly - once. Microsoft's 150 GB floor is measured every time the installer runs, including on a REDEPLOY, and by then the cache file is already on the drive occupying its own space. A 220 GB drive with a 150 GB cache leaves about 44 GB free, so the first deployment succeeds and every later repair or redeploy of that node is refused for want of 150 GB that the node itself is holding. No smaller cache escapes it either: the cache must be over 100 GB on Windows (D00057), and 44 GB of headroom cannot reach the floor whatever size you pick.

So the rule is:

data drive  >=  cache size  +  150 GB  +  room for the OS, the WSL distribution and the container images

For a 150 GB cache that is roughly a 350 GB drive. The cache VHDX is a fixed file but the underlying virtual disk is usually dynamic, so the extra capacity costs nothing until it is used. A node that has already reached this state is not broken - it is serving - but it cannot be repaired automatically, and FluxDeploy will tell you so rather than retrying a deployment that cannot succeed.

Core checks the whole drive before you commit, not just the cache's own requirement. Both checks above are about the cache in isolation, and a relay's data drive also holds the deployment image cache, its boot images and its drivers. Because the cache is a fixed file, enabling a 150 GB cache on a drive with 160 GB free takes that space in one step, and the next image replication to the site fails with nothing connecting the two events. So Core projects the total when you choose the size and refuses a cache that would leave the relay unable to hold deployment images, naming the drive, what is free, what is taking it, and the largest cache that does fit. A relay that has not reported its disk (any relay older than 1.4.4) is never refused on that basis - Core says it could not confirm the fit instead. The same figures are on the site's Connected Cache tab and, fleet-wide, under Reports > Storage.

Virtualization on a virtual relay. Most relays are VMs, and Connected Cache runs in a WSL2 distribution whose cache image is created through Hyper-V - so the relay's own host has to expose virtualization extensions to it. FluxDeploy enables the Windows features and reboots once by itself; what it cannot do is turn on nested virtualization from inside the guest. Once Hyper-V is enabled, the pre-check asks whether its hypervisor actually started, and if it did not it names the command to run on the VM's host (Set-VMProcessor -VMName <relay> -ExposeVirtualizationExtensions $true, with the VM shut down). Microsoft reports this only as a failed image creation, deep inside its own installer.

Leftover state from a previous attempt. A deployment that failed half way leaves the host in a state that says what happened, and deploying again on top of it repeats the failure. Three shapes are reported precisely, with the directories, task names and distribution names found: scheduled tasks registered with nothing installed behind them (Microsoft's script can report success without ever importing the WSL distribution); an installation left on disk with none of the tasks that run it, so nothing will ever start it; and a FluxDeployMccCache profile directory whose account no longer exists, which matters because a re-created account gets a new SID and a second profile directory, stranding the per-user WSL registration in the old one. Disable and then Enable for the site performs the full uninstall and clears all three; the messages also name what to delete by hand.

"Could not determine" is its own answer. A check that could not inspect something reports amber saying so, never green: a pass means the host was inspected and met the requirement. Those lines never block a deployment - refusing on a check FluxDeploy could not run would be the same mistake in the other direction - but they do tell you the requirement is unverified rather than met.

podman on RHEL

Microsoft's Linux installer removes podman and anything depending on it when it installs the Moby container engine, and it asks for permission first. Run without a console, that prompt reads end-of-input and Microsoft's script treats the empty answer as yes - podman gets uninstalled because nobody was there to say otherwise.

FluxDeploy does not let that happen by accident. If podman is installed, the pre-check reports it as a must be fixed item naming what would be removed, so the decision is yours and it is made before anything is installed. Remove podman yourself (dnf remove podman) if nothing else on the host needs it, then run the pre-check again. Only once that check is clear does the deployment proceed, and it then answers Microsoft's prompt explicitly rather than leaving it to end-of-input.

Setup wizard

Navigate to Settings > Cloud Integrations > Connected Cache (the tile appears when the feature set is licensed or a trial is active). Until Connected Cache is configured the page offers Start setup; afterwards the same wizard is available as Reconfigure. It has four steps:

  1. Azure connection - Tenant ID, Client ID, Client Secret, plus the MCC resource name, resource group and region. Test connection signs in to Azure with those values and reads the resource group, and only saves them if that works - credentials that fail are never stored. The same applies to Save on the Connected Cache settings page. The wizard will not advance, and Connected Cache cannot be enabled, until that test passes: credentials that only look right produce a feature that appears enabled while every per-site enable fails in Azure. Any later credential change invalidates the result and requires a fresh test.
  2. Certificate signer - whether cache nodes use the organization certificate authority. See Certificates below.
  3. Cache defaults - default cache size (minimum 50 GB; Azure rejects a smaller cache drive) and the auto-update ring (Stable or Beta), which controls how quickly Microsoft rolls cache-software updates to your nodes. Stable is the default and the conservative choice; Beta takes cache-software updates earlier. Microsoft withdrew the older Fast, Preview and Slow rings - Azure now rejects them, so an install that had one of them saved is moved to Stable automatically.
  4. Enable relays - per-site toggles. Enabling a site provisions an Azure cache node and deploys the cache software on that relay; it takes several minutes and the status updates live. You can close the wizard while it runs.

Per-site enablement is also available outside the wizard: open the site and use Enable on its Connected Cache tab.

Enable is asynchronous. The request is checked (cache size, relay pre-check, disk space) and, if it is acceptable, answered straight away as accepted (HTTP 202) with the site in Provisioning. Core then creates the Azure cache node in the background - this can take minutes, and can wait behind another site's Azure operation - so the page never hangs on it. The API answer carries no node id; read GET /api/sites/{id}/mcc/status until cacheNodeId is set (the site is then Deploying) or status is Failed. A second Enable for the same site while one is running is refused with a message saying so.

When a site is enabled, FluxDeploy Core (in the background):

  1. Creates an Azure cache node for the site, first removing any leftover node an earlier attempt for this site left in Azure, so a retry never double-creates
  2. Retrieves deployment credentials (customerid, cachenodeid, customerkey, registrationkey)
  3. Pushes the credentials to the relay via the next heartbeat

When the create fails, the site says why. Every way out of the background step ends in a terminal state: the site goes to Failed, the reason and the next step are written to the site's status message (shown on the Relay Sites page beside the Failed badge and on the Connected Cache tab, and returned as statusMessage by mcc/status), and an MCC_ENABLE_FAILED entry is written to the audit log. Typical messages name a busy Azure operation (try again in a minute), an Azure refusal of the node create (with the cause), or a pipeline that did not finish in time. Use Enable or Redeploy on the Connected Cache tab to try again; both re-drive the create for a site that has no node.

A setup that is left half-done is cleaned up for you. If Core loses the background step before Azure created the cache node (Core was restarted or crashed mid-setup), the site would otherwise sit at Provisioning or Deploying forever. A check that runs every couple of minutes on Core finds such a site: it is enabled, is at Provisioning or Deploying, has no cache node id, and Core has no setup task still working on it. A site that has been in that state for about 15 minutes is moved to Failed with a message that says how long it was stuck and what happens next. A Core restart resets such a site straight away, because a setup cannot survive a restart. Every reset is written to Core's log and to the audit log as an MCC_ENABLE_FAILED entry that names the relay, what state it was in, why it was reset and for how long it had been stuck.

It then retries by itself, a bounded number of times. A stranded site has no cache node, so nothing was deployed and starting again is safe (the create first removes any leftover, unused node from an earlier attempt, so a retry never makes a second Azure node). Up to 5 automatic retries are made, waiting 2, 4, 8, 16 and 30 minutes between them, and the status message says which retry is next (for example FluxDeploy will retry automatically (retry 2 of 5, around 14:30 UTC)). When the retries are used up the message changes to An administrator is needed: fix the cause, then use Redeploy on the relay's Cache tab to start again, and nothing more is tried until someone acts.

The configure step is covered the same way. Once Azure has created the node, Core sets its cache drive (az mcc ent node update), which can wait several minutes for the node to finish registering. That step is bounded (15 minutes) and every way out of it is recorded: a refusal, a timeout or an unexpected error moves the site to Failed with the reason, an MCC_ENABLE_FAILED audit entry and the same bounded automatic retry - the periodic check re-runs the configure when the retry is due, and the site goes to Deploying the moment it succeeds. If Core restarts while a configure is in flight, the site keeps its node and stays Deploying (the relay's next heartbeat resumes the configure by itself); the restart is still written to the site's status message and to the audit log so the pause is explained rather than silent.

What the check never touches. A site whose cache node is configured is left to the relay's own status reports. A disabled site, a site at Running, Degraded or Stopped, a Failed site whose retries are used up, and a site whose setup task is still running are all left alone, however long the task has taken. The relay being offline, restarting or reporting an error is never taken as a sign that setup is stranded: only Core's own record of the setup counts.

Relay deployment

The relay's MccDeployService receives the deployment parameters and automatically:

  • Installs prerequisites (WSL2 + VirtualMachinePlatform on Windows, Moby/Docker on Linux)
  • Downloads the official Microsoft deployment package for the platform
  • Executes the MCC container deployment
  • Reports status back to Core via heartbeat

Platform specifics:

  • Windows - Follows Microsoft's official process: the Connected Cache Windows app is installed and its deploymcconwsl.ps1 script runs the deployment. A dedicated local runtime account named FluxDeployMccCache is created for the cache, and the IP Helper service (iphlpsvc) is enabled - MCC uses it to forward port 443 on the host into the container.
  • Linux - The deployment runs as root through the fluxdeploy-mcc-run.path helper installed by the relay's install.sh (see Prerequisites); the container runs under Moby/Docker.

The WSL runtime on a Windows relay is the one Windows and Microsoft provide. FluxDeploy does not pin or choose a WSL version. A relay that already has a WSL runtime keeps it, and Microsoft's own deployment script updates it the way Microsoft intends (it runs wsl --update before it installs the cache distribution). The only thing FluxDeploy installs is a runtime that is missing entirely: the first time Connected Cache is enabled on a relay with no WSL, the relay installs the current Microsoft release, because a Windows service cannot run wsl --install itself. It never reinstalls or downgrades an existing runtime. The WSL version in use is written to the install log at the start and the end of every deployment attempt, so an administrator can always see which version a cache node was built on. Earlier FluxDeploy versions pinned WSL to one release and set HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\GitHubUrlOverride to hold Microsoft's update at it; that pin did not prevent the installation stalls it was meant to avoid and kept relays off Microsoft's supported path, so it was removed. A relay upgraded from such a version has the leftover value deleted on its next deployment (and when Connected Cache is disabled). Only a value that points at a GitHub release-tag URL of the WSL project is removed; an override an administrator set for their own reasons is left alone and noted in the log.

First-time Windows relays reboot automatically. Installing WSL2 / VirtualMachinePlatform requires a reboot to activate. When MCC is enabled on a Windows relay that doesn't yet have WSL2, the relay installs it, reboots itself, and then resumes the deployment on startup - no manual step. Status shows Deploying:RebootRequired during the reboot, then continues to Running. Expect a few minutes and one reboot the first time cache is enabled on a Windows relay.

Certificates (HTTPS is required)

Intune Win32 app and Teams content is served over HTTPS only. A cache node that can only answer on port 80 will happily run and cache nothing your clients actually ask for, so every cache node needs an HTTPS certificate that the client devices trust. Delivery Optimization validates that chain like any browser would: if it doesn't trust the issuer, the client silently ignores the cache and downloads from Microsoft instead.

Each cache node generates its own certificate signing request (CSR) inside the container - the private key never leaves the node - and uploads the CSR to Core.

Who signs it is not a Connected Cache setting. FluxDeploy has one organization certificate authority, configured at Settings > Security > Certificates > How they are issued - see Certificate Authority for the modes (FluxDeploy's own root, or a CA subordinate to your enterprise PKI) and their setup steps.

All Connected Cache decides is whether to use it:

Use the organization certificate authority

Turn on Use the organization certificate authority on Settings > Cloud Integrations > Connected Cache > Certificates (or in step 2 of the setup wizard). Every node's CSR is then signed as soon as it arrives - there is no per-site signing step. The status line on that tab names the configured CA and says whether it is ready.

If you chose FluxDeploy's own root, remember the one manual step that mode carries: clients bypass the cache until they trust that root. Download and distribute it from Settings > Security > Certificates > How they are issued.

Sign each request yourself

Leave the toggle off (or leave the organization CA unconfigured) and each node's request waits for you:

  1. Enable Connected Cache on the site and wait until its cache node reports a certificate request. The Certificates tab shows Generated with a timestamp.
  2. Click Download CSR for the site and sign it with your CA using a server-authentication template.
  3. Click Upload certificate, then either pick the issued .crt/.pem file or paste the PEM. FluxDeploy rejects anything that isn't a PEM certificate, that has expired, or whose public key doesn't match that site's request (the usual sign of signing the wrong node's CSR). Include the issuing chain if your CA is not a root.
  4. The relay picks the certificate up on its next check-in and configures the node for HTTPS. The tab then shows Certificate imported.

Either way the relay imports the certificate on its next check-in, so you can switch at any time - nodes pick up the new certificate without a redeploy.

Client Configuration

Once a cache node is running, Windows clients have to be told it exists. DHCP Option 235 is the only mechanism FluxDeploy supports, and FluxDeploy does not configure it - it belongs to your DHCP server, one scope option per site. Two settings are needed and they are set in different places, once each:

What Where Value
The node's address, per network Your DHCP server, on each site's scope Option 235, type text (not "IP address"), holding that site's cache node address. Multiple nodes: comma-separate them inside the one value.
Permission to read it, fleet-wide Intune (Delivery Optimization profile) or Group Policy (Computer Configuration > Delivery Optimization > Cache Server Hostname Source) DOCacheHostSource = 1. Windows does not look at Option 235 until this is set. Use 2 ("Force") if you also have a static DOCacheHost policy that Option 235 should override.

Set the type to text. This is the commonest mistake: a DHCP server that encodes Option 235 as an IP address sends four raw bytes, the client reads nothing usable, and there is no error anywhere.

Why FluxDeploy does not write the cache host onto the devices it deploys

Up to 1.4.4 there was a "Auto-inject DOCacheHost" switch that put the cache host of the deploying relay's node into unattend.xml as a registry policy. It was removed in 1.4.5, deliberately, and it is not coming back.

A registry value is per-device and permanent. A cache node serves one network. Those two facts cannot be reconciled:

  • A laptop imaged at the Manchester branch carried Manchester's node address to head office, to the Leeds site, and to the user's home network - for the life of the machine.
  • At every one of those places the node is either unreachable or on the far side of the WAN, which is the opposite of what a cache is for.
  • And a Delivery Optimization client that cannot reach its configured cache host does not report anything. It silently bypasses the cache and downloads from Microsoft. No error on the client, no event, nothing on the node.

So the failure was invisible: the setting read "on", every site had a healthy node, and roaming devices had no caching at all. That is worse than never enabling it, because it hides the problem instead of having one.

DHCP Option 235 has the property the registry value could never have: it is answered by whatever network the device is on right now. At a site with a node, the device learns that node. At a site without one, or on a home network, the device is told nothing and goes to the internet - which is the correct answer there. The one thing you do set per device (DOCacheHostSource) names a mechanism, not an address, so it is safe to apply to the whole fleet and stays correct wherever the device travels.

If you had the old switch turned on, deployed machines keep the registry value they were given - it is a policy on their disk, and FluxDeploy never revisits a machine after first boot. Clear it with an Intune or Group Policy setting if you want those devices on Option 235 too.

Two things that stop Option 235 reaching a client

Both are Microsoft's, not FluxDeploy's, and both are silent:

  • A security baseline that disables local policy merge can stop the DHCP client retrieving Option 235 at all. Microsoft calls this out specifically for Autopilot scenarios. If nothing is reaching clients on a network whose scope option is definitely right, check that first.
  • Over a VPN, Option 235 is usually not available - the tunnel does not forward the client's DHCP. Those devices fall back to the internet, which is correct: a branch cache node is rarely the right answer for a remote worker. There is a separate policy (DODisallowCacheServerDownloadsOnVPN) if you want to forbid cache use on VPN outright.

Checking it worked

On a deployed machine:

  • Get-DeliveryOptimizationStatus reports BytesFromCacheServer above zero once Windows has actually pulled content through the node. Zero is not proof of a problem - Delivery Optimization declines a cache for small payloads and on links it judges metered - but a sustained zero across real downloads is worth investigating.
  • The node's own side is on the site dashboard (/sites/{id} > Cache) and on Reports > Relay Sites, which shows what each node has served.
  • If the device is on a network with no Option 235, that is the expected state and nothing is wrong.

Network Requirements

MCC requires outbound access to Microsoft CDN domains on ports 80 and 443:

Purpose Domains Port
Content caching *.dl.delivery.mp.microsoft.com 80
Intune Win32 *.manage.microsoft.com 80, 443
DO Service *.do.dsp.mp.microsoft.com 443
MCC updates packages.microsoft.com 80, 443

Critically, *.prod.do.dsp.mp.microsoft.com must bypass TLS-inspecting proxies - certificate pinning will break otherwise.

Monitoring

The Relay Sites page shows per-site MCC status (Running, Degraded, Deploying, Failed, Disabled) in a dedicated MCC column, and each site's dashboard (/sites/{id}) has a Connected Cache card with the provisioning state, relay-reported container status, cache size, cache node, and last-deployed time. While a relay deploys the cache container, the status advances through granular sub-steps (e.g. Deploying:Prerequisites, Deploying:Package, Deploying:Verifying) so the enable action shows real progress rather than sitting idle. Relay heartbeats report the actual container status and version, and MCC counts as a component of the relay health score. Deployment subprocess output from the relay is forwarded to Core logs for troubleshooting.

When the relay's deployment fails, the site says why, and it is written down. The site goes to Failed with the relay's reason in its status message (shown on the Relay Sites page and on the Connected Cache tab), and an MCC_DEPLOY_FAILED entry is written to the audit log naming the relay, the reason and whether FluxDeploy will retry by itself. On a Windows relay the most common cause is the Ubuntu WSL image download: the cache software installs Ubuntu through WSL, which downloads it from releases.ubuntu.com over HTTPS, and a relay that cannot reach that host (a proxy, firewall or TLS-inspecting device in the path, or a broken IPv6 route) fails with a WSL error code such as Wsl/InstallDistro/0x80072f78. FluxDeploy names the code and what it means in the status message and ends the attempt there, rather than waiting for a cache container that cannot start; give the relay outbound HTTPS access to releases.ubuntu.com, then use Redeploy.

Degraded: serving, but not everything it should be

A cache node can be genuinely useful and still be incomplete, and Degraded (amber) is that state. The commonest case is a node with no TLS certificate: the bulk Windows Update and Microsoft Store content is served over port 80 and needs no certificate at all, so such a node is doing most of its job - but Intune Win32 app content and Teams are HTTPS-only, and those clients silently bypass it. Other causes are a self-signed certificate on 443, a missing vendor scheduled task (the node works now but will not come back after a reboot), or a certificate bridge that was never established.

Degraded is not a failure: FluxDeploy does not re-run the cache deployment for it (that would not produce a certificate, and it would burn the single-use Azure registration key), and it does not drag a relay's health to critical. The site's Connected Cache tab always names the specific reason in an amber banner. Certificate problems keep retrying on their own, so a Degraded node often clears itself; if it does not, use Redeploy on that tab.

Verification and automatic repair

The cache installer exiting successfully is not the same claim as "there is a working cache node here" - a vendor deployment has been seen to report success having created no WSL distribution and none of its scheduled tasks. So after every deployment, and then on every relay check-in, FluxDeploy verifies the node itself: the WSL distribution is registered, all four vendor scheduled tasks exist, the cache runtime account still exists, the container is running, the certificate bridge is writable, and ports 80 and 443 actually answer. Each check reports its own specific reason.

If a node that the relay believes it deployed turns out not to be working, the relay repairs it without waiting for an administrator. It first tries the cheap fix - asking the cache software's own scheduled tasks to restart the node - and only clears leftovers and asks Core for a fresh deployment if that is not enough. Repairs are bounded: at most three per cache node, at least 15 minutes apart, and the count survives a relay restart, so a node that cannot be fixed is never reinstalled in a loop. A node is given 20 minutes after its deployment before any of this applies, because the cache software is still downloading and starting in that window. When the attempts are exhausted the site goes to Failed with a message naming what was tried and what is still missing, and Connected Cache appears on the dashboard's attention list.

What each node is actually serving (live check)

Everything above is FluxDeploy's own bookkeeping: what Core issued, and what the relay reported back. That is not the same as what the cache node hands to a client. Nodes have served a stale certificate, or a self-signed placeholder, while the issuance record looked perfect - and Delivery Optimization never reports it. A client that cannot validate the node simply bypasses the cache and downloads from Microsoft, so the only symptom is a cache that never caches.

So Core also checks the node directly. Every 10 minutes it opens a connection to each MCC-enabled relay and records what came back:

  • HTTP - anything answering on port 80, whatever the status code (a cache node returns 400 for a bare /, which still means it is serving).
  • HTTPS - whether a TLS handshake on port 443 completes, and the leaf certificate actually presented: subject, issuer, expiry, thumbprint, and subject alternative names.

Where it shows up:

  • Relay Sites - the MCC column carries an HTTP and an HTTPS badge per site, with the issuing CA underneath. Red means nothing answered on that port; hover for the reason.
  • Site dashboard > Connected Cache - a Served certificate (live) card with the full detail and a Refresh button that re-checks on the spot.
  • Reports > Connected Cache - "Serving HTTP" and "Serving HTTPS" counts across the fleet, plus a per-site Served By (live) column.

A self-signed or expired certificate is called out in red. No client trusts either, so a node serving one is caching nothing that a Delivery Optimization client will use.

Are all nodes on the same certificate authority?

A fleet where one node was signed by a different CA (or never got past its self-signed placeholder) is the failure that hides longest: every other node works, so nobody looks. Both the Relay Sites page and the Connected Cache report compare the issuers actually served across all MCC-enabled sites and warn when they do not match, naming each site that diverges and what signed it. When every node presenting a certificate shares one issuer, the page says so in a single line instead.

Sites that have not presented a certificate yet are not counted as divergent - they are simply not evidence either way.

Traffic statistics

How much a cache actually served is not something FluxDeploy can measure from the outside, and the cache node itself keeps no history. Azure does: Connected Cache emits platform metrics on the customer resource FluxDeploy creates during setup, split per cache node. Core reads them once an hour and stores them, so the numbers below are FluxDeploy's own copy and stay available long after Azure has aged the originals out (Azure keeps 93 days).

Where it shows up:

  • Site dashboard > Connected Cache - a Traffic panel with Served (24h), Served (7d) and Hit ratio (7d), plus a 14-day bar chart of bytes served per day. Today's bar is muted because the day is still accumulating.
  • Reports > Connected Cache - a Served (7d) fleet total in the summary strip and a per-site Served (7d) column. Hover a cell for that site's 24-hour figure and hit ratio.

Things worth knowing about the numbers:

  • They lag by up to an hour, plus Azure's own ingestion delay. Every figure carries an "as of" time. The most recent hour is deliberately never counted, because it is always incomplete and would make the newest reading look like a drop.
  • Days are UTC days, matching the Azure portal. A site in a distant timezone will not see its numbers roll over at local midnight.
  • A newly enabled node shows nothing at first. Azure can take a few hours to start reporting for a fresh cache node. The panel says so rather than showing zeros.
  • Nothing appears at all if Azure was never reachable. No Connected Cache means no traffic figures, and the panel stays hidden rather than showing an empty frame.

Azure permissions. Reading metrics needs Microsoft.Insights/metrics/read on the Connected Cache resource. If the service principal you configured holds Contributor on the resource group (what the setup wizard's own instructions produce), it already has this and there is nothing to do. If you granted a custom, minimal role instead, add the built-in Monitoring Reader role to the service principal, scoped to the Connected Cache resource or its resource group. Until you do, the Connected Cache report shows a warning saying exactly that, and no traffic figures.

Content-type breakdown is not available. The Azure portal's "Volume by Content Type" chart is fed by an internal Delivery Optimization backend that has no public API, so FluxDeploy cannot reproduce it. Bytes, hits, misses and hit ratio are everything Azure exposes.

Managing cache nodes

All MCC actions live on the site's Connected Cache tab (/sites/{id}/cache), beside the state they act on: Enable, Redeploy, and Disable. The Connected Cache cell in the Relay Sites table links there.

  • Redeploy. For a failed or stuck deployment, Redeploy re-fetches the deployment details from Azure and triggers a fresh deployment on the relay - no need to disable and re-enable. On a site that never got a cache node (the create failed), Redeploy re-runs the node create instead, in the background like Enable.
  • Re-enabling a site that has no node is safe. A site whose node create failed (or was lost) records no node id, so Enable or Redeploy simply runs the create again - after first removing any unused node an earlier attempt for that site left in Azure, so a retry never doubles the Azure bill. Node names carry a short random suffix (the fixed part is derived from the site name), and the sweep only ever touches nodes named for that site that no enabled site references.
  • Disabling performs a FULL host uninstall. Per Microsoft's documented uninstall procedure, Disable doesn't just stop the container - the relay runs the vendor uninstall script (uninstallmcconwsl.ps1 on Windows, uninstallmcc.sh on Linux) and removes every Connected Cache component from the host: the cache container and its WSL distro / IoT Edge runtime, the Connected Cache Windows app, the MCC scheduled tasks, firewall rules and port forwards, the dedicated local accounts FluxDeploy created, and the cache data. The site reports NotInstalled when the cleanup completes (a large cache can take several minutes to remove). Microsoft requires previous installations to be uninstalled before a new deployment, so this keeps every disabled host clean for a future re-enable.
  • Where it lands on a Windows relay. Connected Cache uses two folders on the relay's data drive, side by side. mccwsl01 is Microsoft's installation folder - the WSL distro's cache VHDX lives here, which is why it is as large as the configured cache, and the FluxDeployMccCache runtime account can write it (the vendor's installer imports the distro as that account). mccwsl01-control is FluxDeploy's own: the deployment scripts, their step logs and the certificate handshake files. It is administrators-only, deliberately, so that nothing the cache account can write is ever executed with elevation. If an uninstall reports that the folder could not be fully removed (usually the ~100 GB VHDX, still held by WSL), delete both folders manually before re-enabling. Step logs are also copied to C:\Windows\Temp\FluxDeployMcc, which survives an uninstall.
  • Orphaned nodes are cleaned up. Disabling MCC on a site deletes its Azure cache node. A prune operation also removes any Azure cache nodes no longer referenced by an MCC-enabled site, so cache nodes don't accumulate (and bill) after sites are disabled or re-provisioned.