Managing your own pkgng repository

[edit 2013-08-05: fixed a typo in the two command lines used to create the repo definition files, spotted by swills@]

Say you have your own poudriere and your own pkgng repo. You’ve set up Apache to point at your poudriere’s package directory:

<VirtualHost *>
  ServerName pkg.des.no
  ServerAdmin www@des.no
  DocumentRoot /poudriere/data/packages
  <Directory "/poudriere/data">
    Options +Indexes +SymLinksIfOwnerMatch
    IndexOptions +FancyIndexing +FoldersFirst
    Order allow,deny
    Allow from all
  </Directory>
</VirtualHost>

The 91amd64-default and 91i386-default directories are so named by poudriere because they contain the output of the 91amd64 and 91i386 jails, respectively, based on the default ports tree. These are details which you don’t necessarily want your clients to know (or need to know), so you create symlinks which match your clients’ ABIs:

# cd /poudriere/data/packages
# ln -s 91amd64-default freebsd:9:x86:64
# ln -s 91i386-default freebsd:9:x86:32

All you need to do on the client side now is:

# cat >/usr/local/etc/pkg.conf <<EOF
packagesite: http://pkgng.tsdutv.usit.no/freebsd:9:x86:64
EOF

Now, let’s think about this for a while. Every time you install a new machine, you have to copy or type in that pkg.conf, and while this is a pretty minimal example, your real pkg.conf could be much larger: you could have multiple repos, multiple servers with failover, etc. How about we fetch it from a central location?

# fetch -o/usr/local/etc/ http://pkg.des.no/pkg.conf

But what if it changes? Well, why not use the package system itself to distribute and maintain it?

We want to distribute our pkg.conf as a package, and since we want pkg to update it when it changes, we need to place it in a repo. We can’t stick it in the FreeBSD ports tree, and while it is possible to sneak it into the local copy of the ports tree that poudriere builds from, it’s not very convenient. So what we do is create an additional pkgng repo with only one package, which contains two pkg.conf files: one for our real pkgng repo, and one for the repo that contains our configuration package.

First, we create the contents of our package:

% mkdir des-repos
% cd des-repos
% mkdir -p usr/local/etc/pkg/repos
% cat >usr/local/etc/pkg/repos/des-packages.conf <<EOF
des-packages:
  url: http://pkg.des.no/${ABI}
EOF
% cat >usr/local/etc/pkg/repos/des-repos.conf <<EOF
des-repos:
  url: http://pkg.des.no/repos
EOF

Now we need a manifest:

% cat >+MANIFEST <<EOF
name: des-repos
version: 20130715
origin: local/des-repos
comment: Repository definitions for pkg.des.no.
arch: 
www: http://pkg.des.no/
maintainer: des@des.no
prefix: /usr/local
desc: Repository definitions for pkg.des.no.
categories: local, ports-mgmt
deps:
  pkg: { name: pkg, origin: ports-mgmt/pkg, version: 1.1 }
files:
  /usr/local/etc/pkg/repos/des-packages.conf: { uname: root, gname: wheel, perm: 0644 }
  /usr/local/etc/pkg/repos/des-repos.conf: { uname: root, gname: wheel, perm: 0644 }
EOF

Note that arch is intentionally left blank, as this package is architecture-neutral.

Once we have contents and a manifest, we can create the package file:

% pkg create -r $PWD -m $PWD
% tar tf des-repos-20130715.txz 
+COMPACT_MANIFEST
+MANIFEST
/usr/local/etc/pkg/repos/des-packages.conf
/usr/local/etc/pkg/repos/des-repos.conf

All that remains (on the server) is to create the repo:

# mkdir /poudriere/data/packages/repos
# cp des-repos-20130715.txz /poudriere/data/packages/repos
# pkg repo /poudriere/data/packages/repos
# cd /poudriere/data/packages
# ln -s repos/des-repos-20130715.txz des-repos.txz

Then, on each client (presumably including the server itself):

# rm /var/db/pkg/repo*sqlite
# rm /usr/local/etc/pkg.conf
# pkg add http://pkg.des.no/des-repos.txz
# pkg update

Tada!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.