macOS client can’t download Apple updates

This is a really odd situation. I have one client machine that cannot download a particular Apple update. This is the error message that comes up:

softwareupdate -d -a
Software Update Tool

Finding available software

Error downloading Security Update 2017-002: The Internet connection appears to be offline.
Done.

Error downloading updates.
Here are two things that make this situation weird:
  1. The machine can contact any random website, including Apple's.
  2. The machine eventually could even download and install the Safari update from the Apple servers.
I haven't found a real solution to this yet, and it affects only one client, but I did find a workaround, which was to just use Reposado with it.

Setting up Reposado on a Mac

Confused? Read Using Reposado to manage cached Mac updates yet? If not, read that first.

There's a great step-by-step guide to setting up Reposado on Ubuntu Linux, and, in fact, one of the benefits of Reposado is that it can be run on Linux... but it doesn't have to be. For whatever reasons you have, you may want to run it on a Mac instead.

First, make sure Apache is up and running on your Mac:

sudo apachectl start
and then visit localhost in a web browser on your machine or https://myserver.mycompany.com from another computer (with your actual Mac-as-web-server's fully qualified domain name in place of the dummy placeholder I gave as an example).

You may have to configure a bunch of other things on the web server for that last part to work—all that's a bit outside the scope of a Reposado tutorial.

(Keep in mind, too, that the path I'm using to the web server documents is based on a regular macOS installation. If you add OS X Server on top of that, the path then changes to /Library/Server/Web/Data/Sites/Default.)

Next, get the latest Reposado code. If you have Git installed, you can just clone the repository:

git clone https://github.com/wdas/reposado

If you don't have Git installed and don't want to install it, you can also click the Clone or download link on the Reposado GitHub repository and then double-click the downloaded .zip to unzip its contents.

Either way, you should have a folder called reposado with a subfolder called code.

Go ahead and copy that to /usr/local/reposado:

sudo mkdir -p /usr/local/reposado
sudo cp -R /PATH/TO/reposado/code/* /usr/local/reposado/

Make folders to store the Reposado-downloaded Apple updates data:

sudo mkdir -p /Library/WebServer/Documents/reposado/html
sudo mkdir -p /Library/WebServer/Documents/reposado/metadata

Configure Reposado:

sudo /usr/local/reposado/repoutil --configure
You'll be asked a few questions. Answer them appropriately. If you drag the folders to the terminal, be sure to delete any trailing spaces.
Filesystem path to store replicated catalogs and updates [None]:
/Library/WebServer/Documents/reposado/html
Filesystem path to store Reposado metadata [None]:
/Library/WebServer/Documents/reposado/metadata
Base URL for your local Software Update Service
(Example: http://su.your.org -- leave empty if you are not replicating updates) [None]:
https://myserver.mycompany.com

Create at least one branch (you'll probably have at least two later):

sudo /usr/local/reposado/repoutil --new-branch testing
Read more details on manipulating branches.

Start syncing your Reposado cache with Apple's update servers:

sudo /usr/local/reposado/repo_sync
Note: This could take a while (depending on your bandwidth) and download several hundred gigabytes of data.

Once it's finished syncing up, add all the products to the testing branch:

repoutil --add-product all testing
Now, you should be able to see the catalog if you visit

https://myserver.mycompany.com/reposado/content/catalogs/others/index-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1_testing.sucatalog

That URL will change with each new version of macOS that's released (the sample above is valid as of Sierra), so you may want to wait until Reposado's code is updated and then do another Git clone on the code to update the URL (and then fix the URL for your clients).

The last part of the URL is the branch you want the client to access (in this case, testing).

To write the change to a client, run on the client machine:

sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate CatalogURL "https://myserver.mycompany.com/reposado/content/catalogs/others/index-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1_testing.sucatalog"

That's a very basic setup. For more details on Reposado options, read the official docs.

Using Reposado to manage cached Mac updates

Usually if you get Mac updates, those updates come straight from Apple's servers. If you have the caching service enabled on OS X Server, the updates will cache there every time a new one is requested from a client, and then future clients requesting the same update will download from the caching service instead of from Apple's servers directly.

Reposado allows you to, in addition to caching updates, create "branches" for testing and production (and development, if you want to make the distinctions that fine) so you can test updates before making them available to all your Mac clients. Keep in mind, though, Reposado works for Mac clients. It does not, unlike OS X Server's caching service, cache iOS updates or purchases.

Lots of good documentation on how to install and use Reposado already exists, so I won't rehash all that.

The only thing I couldn't find in the default functionality was some kind of auto-promotion from a testing to a production branch, so I wrote one: ReposadoAutopromote. After a few days (number of your choosing), anything in the testing branch will automatically move up to the production branch (name of the branches also your choosing). This gives you some time to test updates before rolling them out to clients, but then you don't have to examine each and every individual update and move them all over—you get some time to get a troublesome update out of testing before the auto-promotion happens.