As you've found, pkg_add can't upgrade ports gracefully. The portupgrade package does this quite nicely however, and is the method I use and recommend (there are others available if you don't like this method).
Once the port is installed you can simply run
portupgrade -aPP and it will upgrade all ports installed on the system using packages. If you don't want to update ever port, you can run
portupgrade -RPP [category/port] to upgrade a particular port and the ports it depends on. Running the program without arguments will upgrade the port belonging to the current directory (ie
cd /usr/ports/security/openssl ; portupgrade will upgrade openssl, without the -PP option it will build the port from source); and if you are not in a port directory it will display help (same as the
By default portupgrade will install packages if they exist in the directory defined by the PKG_PATH environmental variable (defaults to $PACKAGES/All, $PACKAGES defaults to $PORTSDIR/packages; so the default path is
If they don't exist there, it will download the packages (by preference) from $PKG_SITES (takes a URI with subfolders Latest and All; no default value), or $PACKAGEROOT (takes a URI with the normal mirror path under it; default is "ftp://ftp.freebsd.org").
One easy way to do this, use one machine to build/cache packages that will be installed on other machine.
- You can build packages from the ports tree with
make package in the port's directory (which will also install the port).
- You can use portupgrade to upgrade one machine and cache the package files for use on other machines, the aforementioned commands will cache the package files in the default directory (see above).
- You can use portupgrade to fetch the packages only, and not install them, with
portupgrade -aPPF or
portupgrade -RPPF [category/port].
Once you have the cached package files you can share the directory via NFS, FTP, HTTP, etc; so long as the files are accessible from the other machines. Set the PACKAGES or PKG_SITE with the appropriate values to point to the caching server. Execute the typical portupgrade command, it should pull the packages from the caching server and install them.
Note: The port tree has to be up to date on all the servers for portupgrade to operate correctly (it will attempt to update to whatever version is in the local ports tree). If you're going to have the same ports/packages installed on all the computers, it might be easiest to share one servers
/usr/ports directory (say over NFS) and mount it on all the other servers.