Solaris package repository

A Solaris package repository is similar to a yum repository: a place to get Solaris SVR4 packages in datastream format.  It is mostly a straightforward process to setup a repository, but I have found a few gotchas. All these examples are based on the server at repo.tusk.tufts.edu.  The basic file structure and package naming conventions follow www.sunfreeware.com, but with the addition of the Latest subdirectory, which is a directory of sym links to the latest version of a package.  Similar to the Latest directory on the FreeBSD ftp package servers.

Server Setup

Apache

The server is just an Apache server with mod_ssl enabled.  I decided to use only https on this server after reading a recent ;login: article, as one step to help mitigate a man-in-the-middle attack.  (I have yet to sign the SVR4 packages with a key.) The virtual host setup looks like this:

NameVirtualHost SERVERNAME:80


        Redirect permanent / https://SERVERNAME/



        ServerAdmin root@SERVERNAME
        ServerName SERVERNAME
        CustomLog /var/log/httpd/SERVERNAME-access_log combined
        ErrorLog /var/log/httpd/SERVERNAME-error_log
        SSLEngine on
        SSLCertificateFile "/etc/httpd/conf.d/SERVERNAME.crt"
        SSLCertificateKeyFile "/etc/httpd/conf.d/SERVERNAME.key"
        SSLCertificateChainFile "/etc/httpd/conf.d/IPS-IPSCABUNDLE.crt"
        DocumentRoot /var/www/html-SERVERNAME
        KeepAlive on
        
                Options FollowSymLinks Indexes
                AllowOverride None
                Order allow,deny
                Allow from all
        

The one apache configuration option to note is the KeepAlive on. Until I did that, I was getting these strange pkgadd errors:

pkgadd: ERROR: Failure occurred with http(s) negotiation:
pkgadd: ERROR: unable to download package datastream from .

I found the solution buried in this OpenSolaris bug report.

File System

Here is the script I use to create the filesystem layout and the contents of the Latest directory:

#!/bin/sh

SERVERNAME="SERVERNAME"
BASEDIR="/var/www/html-$SERVERNAME/Solaris";
SolarisOSes="8 9 10";
SolarisArches="sparc i386";

for arch in ${SolarisArches}; do
     if [ ! -d "$BASEDIR/${arch}" ]; then
          mkdir -p "$BASEDIR/${arch}"
     fi
     for ver in ${SolarisOSes}; do
          if [ ! -d "$BASEDIR/${arch}/${ver}" ]; then
               mkdir -p "$BASEDIR/${arch}/${ver}"
          fi
          if [ ! -d "$BASEDIR/${arch}/${ver}/Latest" ]; then
               mkdir -p "$BASEDIR/${arch}/${ver}/Latest"
          fi
          cd $BASEDIR/${arch}/${ver}/Latest
          for pkg in $BASEDIR/${arch}/${ver}/*-local; do
               p=`basename $pkg`
               spkg=`echo ${p} |sed -e "s/-[^-]*-sol${ver}-${arch}-local//"`

               if [ $spkg != ${oldpkg:-''} -a -n "$oldsource" ]; then
                    rm -f $oldtarget
                    ln -s ../$oldsource $oldtarget
               fi
               oldsource=$p
               oldtarget="${spkg}-sol${ver}-${arch}-local"
               oldpkg=$spkg
          done
     done
done

exit 0;

Now, all I need to do is to populate the $BASEDIR/${arch}/${ver} directory with the packages and run the script anytime I add a new package or version.

Client Setup

To allow pkgadd to fetch packages, you need to first prefetch the SSL certificate from the server you want to download from.

  1. openssl s_client -connect SERVERNAME:443 > SERVERNAME.crt
  2. pkgadm addcert -ty SERVERNAME.crt  # Do not put a password on the truststore

The pkgadm command needs to be run as root; the openssl command can be run as the normal user.

In the case of repo.tusk.tufts.edu, it is using a IPSca certificate (I have talked about IPSca before), so we need to download the chain certificate and add it to the truststore before we add the main certificate.  This is what I did for that:

  1. wget http://certs.ipsca.com/companyIPSipsCA/IPS-IPSCABUNDLE.CRT
  2. pkgadm addcert -ty IPS-IPSCABUNDLE.CRT

Now, the client will be able to download a package via the pkgadd command, like this:

pkgadd -a depends -d https://SERVERNAME/Solaris/i386/10/security-v3.4.4-sol10-i386-local -n security