Scripting The OS X Caching Server To Cache Updates

The Caching Server in OS X is a little bit of a black box. But, it’s not all that complicated, compared to some things in the IT world. I’d previously written about command line management of the service itself here. When you enable the caching service, the server registers itself as a valid Caching Server. Nearby devices then lookup the closest update server with Apple and register with that update server using a GUID: /Applications/ settings caching:ServerGUID Then, each time the device looks for an update, it does so against using the device model. Noticed this with this line in my proxy logs: "GET HTTP/1.1" 200 - "-" "MobileAsset/1.0" Let’s say that the device is an iPad 2,7, then the following information is used for the update, with a URL of, which is created using the _BaseURL string followed by the _RelativePath string:
<dict> <key>ActualMinimumSystemPartition</key> <integer>1965</integer> <key>Build</key> <string>13E6238</string> <key>InstallationSize</key> <string>0</string> <key>MinimumSystemPartition</key> <integer>2017</integer> <key>OSVersion</key> <string>9.3.1</string> <key>ReleaseType</key> <string>Beta</string> <key>SUDocumentationID</key> <string>iOS931GM</string> <key>SUInstallTonightEnabled</key> <true/> <key>SUMultiPassEnabled</key> <true/> <key>SUProductSystemName</key> <string>iOS</string> <key>SUPublisher</key> <string>Apple Inc.</string> <key>SupportedDeviceModels</key> <array> <string>P107AP</string> </array> <key>SupportedDevices</key> <array> <string>iPad2,7</string> </array> <key>SystemPartitionPadding</key> <dict> <key>1024</key> <integer>1280</integer> <key>128</key> <integer>1280</integer> <key>16</key> <integer>160</integer> <key>256</key> <integer>1280</integer> <key>32</key> <integer>320</integer> <key>512</key> <integer>1280</integer> <key>64</key> <integer>640</integer> <key>768</key> <integer>1280</integer> <key>8</key> <integer>80</integer> </dict> <key>_CompressionAlgorithm</key> <string>zip</string> <key>_DownloadSize</key> <integer>1164239508</integer> <key>_EventRecordingServiceURL</key> <string></string> <key>_IsZipStreamable</key> <true/> <key>_Measurement</key> <data>Rfrw7jNYWH8xNS67pXoq7NEhpUI=</data> <key>_MeasurementAlgorithm</key> <string>SHA-1</string> <key>_UnarchivedSize</key> <integer>1235575808</integer> <key>__AssetDefaultGarbageCollectionBehavior</key> <string>NeverCollected</string> <key>__BaseURL</key> <string> </string> <key>__CanUseLocalCacheServer</key> <true/> <key>__QueuingServiceURL</key> <string></string> <key>__RelativePath</key> <string> com_apple_MobileAsset_SoftwareUpdate/ </string> </dict>
You can then use these dictionaries to assemble this path for all items in the dictionary with “iPad 2,7” in the SupportedDevices key. You can also choose to assemble this path for all items with the OSVersion of a given string, such as 9.3.1 in this case. You could curl these updates down to a client, or request them through the caching service, which would cache them to the Caching Server, using the IP of the server (e.g. Found the above URL using a reverse proxy. This URL is generated based on an http request to the IP address of the caching service, followed by the port. The port is derived using the serveradmin command and query the settings for caching:Port as follows: /Applications/ settings caching:Port In this example, the URL is then But the URL then splits the _BaseURL into two parts, taking from the URL and appending ? So without the update, the URL would be the following: OK, so now we’ll pop the other part of that _BaseURL in there: And then there’s one more step, which is throw the zip in there: Viola. Curl that and the caching server will download that update and make it ready for clients to access. Everything is hashed and secure in the directory listed using this command: /Applications/ settings caching:DataPath