Configuring macOS Clients to Point to a Custom Software Update Server: A Developer’s Guide


2 views

When managing multiple macOS devices in a development environment, pointing clients to a local Software Update Server (SUS) provides control over update timing and bandwidth usage. The SUS system uses a combination of configuration profiles and command-line tools to manage update sources.

The most direct approach for developers is using Terminal commands:

sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate CatalogURL http://your-server-address:8088
sudo softwareupdate --set-catalog http://your-server-address:8088

Verify the configuration with:

defaults read /Library/Preferences/com.apple.SoftwareUpdate CatalogURL

For enterprise deployment, create a mobileconfig file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PayloadContent</key>
    <array>
        <dict>
            <key>PayloadIdentifier</key>
            <string>com.apple.SoftwareUpdate</string>
            <key>PayloadType</key>
            <string>com.apple.SoftwareUpdate</string>
            <key>PayloadUUID</key>
            <string>YOUR-UUID-HERE</string>
            <key>PayloadVersion</key>
            <integer>1</integer>
            <key>CatalogURL</key>
            <string>http://your-server-address:8088</string>
        </dict>
    </array>
    <key>PayloadDisplayName</key>
    <string>Software Update Server Settings</string>
    <key>PayloadIdentifier</key>
    <string>com.yourcompany.softwareupdate</string>
    <key>PayloadType</key>
    <string>Configuration</string>
    <key>PayloadUUID</key>
    <string>ANOTHER-UUID-HERE</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
</dict>
</plist>

For large-scale deployments, consider this Bash script:

#!/bin/bash

SERVER_URL="http://your-server-address:8088"
TEMP_PROFILE="/tmp/sus_profile.mobileconfig"

cat << EOF > $TEMP_PROFILE
[Previous XML content from Method 2]
EOF

# Install the profile
/usr/bin/profiles -I -F $TEMP_PROFILE

# Verify installation
/usr/bin/profiles -C -v

# Clean up
rm $TEMP_PROFILE

If updates aren't appearing:

  • Check firewall settings: sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add /usr/sbin/softwareupdated
  • Verify server accessibility: curl -I http://your-server-address:8088
  • Reset local caches: sudo softwareupdate --clear-catalog

Use this command to check pending updates:

softwareupdate -l --no-scan

For detailed logging during update attempts:

sudo softwareupdate -ia --verbose

By default, macOS clients connect to Apple's public Software Update servers (swscan.apple.com) to check for available updates. When you've set up your own Software Update service on a macOS Server, you'll need to modify client configurations to redirect these requests.

The most straightforward approach is using Terminal to modify the System Preferences plist:

sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate CatalogURL http://your.server.address:8088/content/catalogs/others/index-leopard-snowleopard.merged-1.sucatalog

Replace "your.server.address" with your server's IP or hostname. The port 8088 is the default for macOS Server's Software Update service.

For enterprise environments, creating a configuration profile is more scalable:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PayloadContent</key>
    <array>
        <dict>
            <key>PayloadDisplayName</key>
            <string>Software Update Settings</string>
            <key>PayloadIdentifier</key>
            <string>com.apple.SoftwareUpdate.management</string>
            <key>PayloadType</key>
            <string>com.apple.SoftwareUpdate</string>
            <key>PayloadUUID</key>
            <string>C8FB3D8F-EA8B-4A5A-A76C-123456789ABC</string>
            <key>PayloadVersion</key>
            <integer>1</integer>
            <key>CatalogURL</key>
            <string>http://your.server.address:8088/content/catalogs/others/index-leopard-snowleopard.merged-1.sucatalog</string>
        </dict>
    </array>
    <key>PayloadDescription</key>
    <string>Configures Software Update to use internal server</string>
    <key>PayloadDisplayName</key>
    <string>Software Update Server Settings</string>
    <key>PayloadIdentifier</key>
    <string>com.yourorg.softwareupdate</string>
    <key>PayloadOrganization</key>
    <string>YourOrg</string>
    <key>PayloadRemovalDisallowed</key>
    <false/>
    <key>PayloadScope</key>
    <string>System</string>
    <key>PayloadType</key>
    <string>Configuration</string>
    <key>PayloadUUID</key>
    <string>E5A96B84-3DDE-4C89-A456-123456789ABC</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
</dict>
</plist>

After applying changes, verify the settings took effect:

defaults read /Library/Preferences/com.apple.SoftwareUpdate CatalogURL

You can also check the active configuration with:

softwareupdate --list

For larger deployments, consider using Mobile Device Management (MDM) solutions to push these settings:

# Jamf Pro example
sudo jamf policy -event swu_server_change

Or with Munki:

<dict>
    <key>SoftwareUpdateServerURL</key>
    <string>http://your.server.address:8088</string>
</dict>

If clients aren't connecting properly:

  1. Verify port 8088 is open on the server
  2. Check DNS resolution for your server
  3. Confirm the catalog URL is accessible from client machines
  4. Review server logs at /Library/Logs/SoftwareUpdate.log