Constant Thinking | Technology Thoughts for the Quality Geek | by Constantin Gonzalez
Obsolete Post

This post is probably obsolete

This blog post is older than 5 years and a lot has changed since then: Meanwhile, I have changed employer, blogging platform, software stack, infrastructure, and other technologies I work with and interests I follow.
The stuff I wrote about in this article likely has changed, too, so you may find more recent information about things like Solaris, Oracle/Sun systems, Drupal, etc. somewhere else.
Still, this content is provided for your convenience, in case it is still useful for you. Just don’t expect it to be current or authoritative at this point.
Thanks for stopping by!

OpenSolaris Home Server Scripting 3: Managing Package Repositories

Package Scripting

OpenSolaris OS comes with the Image Packaging System (IPS) for managing installation and additional software. By default, it is configured to pull packages from the

repository, but of course there are many other interesting repositories with software to install from.

Chris Gerhard recommends adding at least the

repository (free, registration required) so you can easily install VirtualBox, Adobe Flash, TrueType Fonts etc.

If you have a support contract or are an Oracle/Sun employee, you may want to switch your preferred repository to the supported one. The more adventurous may want to switch to the development repository.

Then, the Software Porting Community on has a hierarchical system for making open source software available on OpenSolaris through two repositories:


And then there are a couple of more repositories from user groups, private people, companies offering commercial packages and so on.

One way to register package repositories with the IPS on your home server is by using the package management GUI, or by using the pkg(1) command (See also: "How to Add or Update a Publisher").

But of course we want to stick to our "Script Everything" philosophy and write ourselves a small script that takes care of all of our package configuration needs.

Scripting Package Configuration

We'll use a simple configuration file that contains all the parameters necessary for configuring our favorite package repositories, one line per repository.

For each repository, we'll need:

  • Its URL for

    to pull packages from.

  • A name for the repository.

  • An optional certificate file and a key file for repositories that want them (We'll just store the base name and assume they'll end with


  • An optional flag that indicates whether we want this repository to be our preferred one.

To keep things nice and simple, we'll separate the fields with spaces and add a few comments for documentation. Here's an example, taken from my current home server configuration:

admin@krengi:/krongi/config/pkg$ more pkg.config 
# Package configuration
# Fields are separated by a space.
# Fields: URL publishername preferred keyfile
# "preferred" is either empty or not.
# Keyfile is the basename of the key/certificate name standardsupport OpenSolaris_standard_support preferred contrib extras OpenSolaris_extras hacluster Open_HA_Cluster_2009.06

Certificate and key files are stored together with our configuration file in the same directory:

admin@krengi:/krongi/config/pkg$ ls -al
total 14
drwxr-xr-x 2 admin staff   9 2010-03-20 14:48 .
drwxr-xr-x 6 admin staff   6 2010-03-05 13:49 ..
-rw-r--r-- 1 admin staff 758 2010-03-20 14:40 Open_HA_Cluster_2009.06.certificate.pem
-rw-r--r-- 1 admin staff 888 2010-03-20 14:41 Open_HA_Cluster_2009.06.key.pem
-rw-r--r-- 1 admin staff 750 2010-03-20 14:41 OpenSolaris_extras.certificate.pem
-rw-r--r-- 1 admin staff 888 2010-03-20 14:41 OpenSolaris_extras.key.pem
-rw-r--r-- 1 admin staff 758 2010-03-20 14:41 OpenSolaris_standard_support.certificate.pem
-rw-r--r-- 1 admin staff 888 2010-03-20 14:41 OpenSolaris_standard_support.key.pem
-rw-r--r-- 1 admin staff 535 2010-03-20 14:48 pkg.config

Resetting to Default State

As always, we'll start with a function that resets everything to a default state: Only the

repository, configured as the preferred one:

# Hard coded constants

# Pfexec versions of commands
PFPKG="pfexec pkg"

# Clear repositories from pkg and revert to default
function clear_publishers {
        # Set default publisher.
        echo "Setting default publisher $DEFAULT_PUB at $DEFAULT_PUB_URL."
        $PFPKG set-publisher -P -O $DEFAULT_PUB_URL $DEFAULT_PUB

        # List all publishers we know except the default one.
        PUBLISHERS=$( pkg publisher -Ha | sed -e 's/\s\s*/ /g' | \
                cut '-d ' -f1 | grep -v $DEFAULT_PUB )

        # Clear all publishers.
        if [ "$PUBLISHERS" ] ; then
                echo "Clearing all other publishers."
                $PFPKG unset-publisher $PUBLISHERS

        echo "Done."

Going Through the List of Repositories

Now the more interesting part follows: We'll feed the configuration file line by line into a while loop that puts together the parameters for the right


We'll also copy key and certificate files into

which is the same location that the package manager GUI uses.

Here's the piece of code for parsing the configuration file and configuring package repositories:

PFMKDIR="pfexec mkdir"
PFCHOWN="pfexec chown"
PFCP="pfexec cp"

# Print an error message and exit.
function emit_error {
	echo "Error: $1"
	exit 1

# Set up repositories for pkg
# The argument is a file containing information about publishers and their URLs
# with possible keyfiles and "preferred" option.
function add_publishers {
	CONFIG_DIR=$(dirname $1)

	# Make sure the directory for storing keys is set up correctly.
	if [ ! -d $KEY_DIR ] ; then
		echo "Creating directory $KEY_DIR."
		$PFMKDIR -m 0755 -p $KEY_DIR
		$PFCHOWN root:root $KEY_DIR

	# File format:
	# One line per package repository.
	# Lines containing "#" are ignored.
	# Fields in a line are separated by space.
        # Fields: "URL publisher keyfile preferred".
	# "preferred" can be any string. If present, this publisher will be
	# marked as preferred.
	# Keyfile will be expanded to "keyfile.key.pem" and
	# "keyfile.certificate.pem".
	# We assume that keyfiles are in the same directory as the config file.
	# "keyfile" and "preferred" can be left out.
	cat $CONFIG_FILE | grep -v '#' | while read url pub key pref; do
		# Handle the keyfile field.
		if [ $key ] ; then
			echo "Storing key and certificate for $key in $KEY_DIR."
			$PFCP $CONFIG_DIR/$key.key.pem $KEY_DIR
			[ $? -eq 0 ] || \
				emit_error \
				"Can't copy $CONFIG_DIR/$key.key.pem."
			key_opt="-k $KEY_DIR/$key.key.pem"
			$PFCP $CONFIG_DIR/$key.certificate.pem $KEY_DIR
			[ $? -eq 0 ] || \
				emit_error \
				"Can't copy $CONFIG_DIR/$key.certificate.pem."

			key_opt="$key_opt -c $KEY_DIR/$key.certificate.pem"
			key_string=" with key $key"

		# Handle the preferred field.
		if [ $pref ] ; then
			pref_string=" preferred"

		# Put everything together into a pkg command.
		echo "Adding$pref_string publisher $pub at $url$key_string."
		$PFPKG set-publisher $pref_opt $key_opt -O $url $pub
		[ $? -eq 0 ] || \
			emit_error "Couldn't add publisher $publisher."

This script is slightly more chatty than previous scripts. You may want to modify it to be more silent or use a log file.


Download the full

script including a help function and argument parsing and feel free to modify it to your needs. Over time, you'll accumulate quite a few repositories, some with key/certificate files and some not. Then this is a handy tool to configure them all at once whenever needed.

Your Take

What are your favourite repositories? Do you use alternative package management systems, if so which ones? What packages do you install on a regular basis after a fresh install of OpenSolaris?

Related Articles

By Constantin Gonzalez , 2010-03-29, updated: 2017-10-03 in Home Server.



This is the blog of Constantin Gonzalez, a Solutions Architect at Amazon Web Services, with more than 25 years of IT experience.

The views expressed in this blog are my own and do not necessarily reflect the views of my current or previous employers.

Copyright © 2018 – Constantin Gonzalez – Some rights reserved.
This site uses Google Analytics, Alexa, Feedburner, Amazon Affiliate, Disqus and possibly other web tracking code. See Imprint for details and our information policy. By using this site you agree to not hold the author responsible for anything related to this site.

This page was built using Python, Jinja2, Bootstrap, Font Awesome, AWS Step Functions, and AWS Lambda. It is hosted on Amazon S3 and distributed through Amazon CloudFront.