3 entries tagged with 'Debian'

Howto debianize Java applications

Debianization

When you are working on a Java based project, it is often handy to debianize the resulting application. Using a package installer your application can be easily installed together with its dependencies, it will will be accessible automagically by the all the users of the system and can easily be uninstalled,...

Manually

You could do this debianization manually, but there are many drawbacks when doing so:

  • It would work only for your machine type (e.g. Ubuntu Karmic, or Debian Sid), not for other os types.
  • Extra documentation needs to be provided to the other developers in the team.
  • It would be a very repetitive job.
  • I'm sure errors will be made.
The pkg plugin

When the application is built using Maven the pkg plugin can be used to automate the package building process.

The package builder itself is managed at the Evolvis site. It is created by Tarent, an IT company from Bonn, and is released under GPL version 2.

Prepare

Best to start by adding this plugin prepository to your pom or your settings.xml:

:::::xml
<pluginRepositories>
     <pluginRepository>
           <id>evolvis-release-repository</id>
           <name>evolvis.org release repository</name>
           <url>http://maven-repo.evolvis.org/releases</url>
           <snapshots>
               <enabled>false</enabled>
           </snapshots>
     </pluginRepository>
</pluginRepositories>

Configure

Here is an example of a simple Java application configured for Ubuntu Hardy debianization. These tags should be placed in the <build><plugins> section of your pom. Further down the important tags are explained.

:::::xml
<plugin>
    <groupId>de.tarent.maven.plugins</groupId>
    <artifactId>maven-pkg-plugin</artifactId>
    <version>2.1.4</version>
    <configuration>
         <defaultDistro>ubuntu_hardy</defaultDistro>
         <shortDescription>PPP Monitor</shortDescription>
         <auxPackageMapURL>
               ${project.baseUri}/src/main/package/elevenbits.xml
         </auxPackageMapURL>
         <defaults>
              <distros><string>ubuntu_hardy</string></distros>
              <architecture>all</architecture>
              <section>misc</section>
              <mainClass>com.elevenbits.pppmonitor.PPPMonitor</mainClass>
              <maintainer>
                    ElevenBits <[email protected]>
              </maintainer>
              <revision>r6</revision>
              <customCodeUnix>
                    #echo "Updating classpath..."
                    POSTFIX=$${CLASSPATH_ARG#* }
                    PREFIX=/etc/pppmonitor
                    CLASSPATH_ARG="-cp $PREFIX:$POSTFIX"
                    #echo "Classpath: $CLASSPATH_ARG"
               </customCodeUnix>
               <srcSysconfFilesDir>src/main/packager/etc</srcSysconfFilesDir>
               <sysconfFiles>
                    <sysconfFile>
                         <from>log4j.xml</from>
                         <to>pppmonitor</to>
                    </sysconfFile>
                    <sysconfFile>
                         <from>pppmonitor.properties</from>
                         <to>pppmonitor</to>
                    </sysconfFile>
               </sysconfFiles>
               <datadir>
                     /usr/share/pppmonitor/
               </datadir>
               <dataFiles>
                    <dataFile>
                         <from>pppmonitor</from>
                         <to></to>
                    </dataFile>
               </dataFiles>
               <srcAuxFilesDir>src/main/packager/scripts</srcAuxFilesDir>
               <postinstScript>postinst.sh</postinstScript>
               <postrmScript>postrm.sh</postrmScript>
          </defaults>
     </configuration>
</plugin>

Now follows the explanation of the important tags. The pkg web site contains all information on the configuration settings.

:::::xml
<groupId>de.tarent.maven.plugins</groupId>
<artifactId>maven-pkg-plugin</artifactId>
<version>2.1.4</version>

Version 2.1.4 or higher is required, since it allows the installment of pre/post install/remove scripts in the resulting package.

:::::xml
<defaultDistro>ubuntu_hardy</defaultDistro>

The pkg plugin can build packages for distributions like Debian and Ubuntu as well as embedded Linux variants like Maemo and OpenMoko. Additionally it supports the creation of IzPack installers. The defaultDistro tag value can be one of these.

:::::xml
<auxPackageMapURL>
     ${project.baseUri}/src/main/package/elevenbits.xml
</auxPackageMapURL>

The auxPackageMapURL should point to the ElevenBits package map. This package map sets the defaultBinPath to /usr/sbin. That way the generated package will be runnable by root only. You can find more info on the PackageMaps is available at the pkg site. Here is the ElevenBits mapping xml:

:::::xml
<!--
     Package maps document for Ubuntu 8.04 LTS (Hardy Heron) with
     ElevenBits updates.
-->
<package-maps>
     <version>1.0</version>
     <distro>
          <id>ubuntu_hardy</id>
          <label>ElevenBits's Ubuntu Hardy mapping.</label>
          <inherit>ubuntu_gutsy</inherit>
          <defaultBinPath>/usr/sbin</defaultBinPath>
          <map>
               <!-- Add extra mappings here. -->
          </map>
     </distro>
</package-maps>

Lets continue with some other tags:

:::::xml
<architecture>all</architecture>
<section>misc</section>
<mainClass>com.elevenbits.pppmonitor.PPPMonitor</mainClass>

The package will run on all architectures (since it is a Java application), the section in the package list is misc and the main class is com.elevenbits.pppmonitor.PPPMonitor.

::::xml
<maintainer>
     ElevenBits <[email protected]>
</maintainer>

The maintainer will be used when signing the package. This is in detail explained further below.

:::::xml
<customCodeUnix>
      #echo "Updating classpath..."
      POSTFIX=$${CLASSPATH_ARG#* }
      PREFIX=/etc/pppmonitor
      CLASSPATH_ARG="-cp $PREFIX:$POSTFIX"
      #echo "Classpath: $CLASSPATH_ARG"
</customCodeUnix>

When pkg builds a package a script is created using the pom data. At the end of the script the customCodeUnix is added by the plugin. Here is the code generated for this example:

:::::bash
#!/bin/sh
# This file is autogenerated by the maven-pkg-plugin. The source responsible
# for this script can be found in class: de.tarent.maven.plugins.pkg.generator.WrapperScriptGenerator

# You can provide additional VM arguments by setting the VMARGS environment variable.
BOOTCLASSPATH_ARG=""

CLASSPATH_ARG="-cp /usr/share/java/pppmonitor/devices-1.1.0.jar:/usr/share/java/RXTXcomm.jar:/usr/share/java/commons-logging.jar:/usr/share/java/log4j-1.2.jar:/usr/share/java/pppmonitor/mail-1.4.jar:/usr/share/java/activation.jar:/usr/share/java/pppmonitor/jms-1.1.jar:/usr/share/java/pppmonitor/jmxtools-1.2.1.jar:/usr/share/java/pppmonitor/jmxri-1.2.1.jar:/usr/share/java/pppmonitor/rolling-appender-1.0.jar:/usr/share/java/pppmonitor.jar"

MAIN_CLASS=com.elevenbits.pppmonitor.PPPMonitor

# Path of the shared libraries (e.g. for SWT
LIBRARY_PATH_ARG="-Djava.library.path=/usr/lib/jni:/usr/lib"

# Path to BC-ABI compiled classes. Has no effect on runtimes other than GCJ.
DB_PATH_ARG=""

# Additional system properties which are special for this application:
SYSTEM_PROPERTIES=""

# Allows overriding the VM by setting the JAVA environment variable.
if [ x${JAVA} = x ];
then
     JAVA=java
fi

#echo "Updating classpath..."
POSTFIX=${CLASSPATH_ARG#* }
PREFIX=/etc/pppmonitor
CLASSPATH_ARG="-cp $PREFIX:$POSTFIX"
#echo "Classpath: $CLASSPATH_ARG"

exec ${JAVA}  ${VMARGS} ${BOOTCLASSPATH_ARG} ${CLASSPATH_ARG} ${LIBRARY_PATH_ARG} ${DB_PATH_ARG} ${SYSTEM_PROPERTIES} ${MAIN_CLASS} ${@}

To set up the /etc and the related data files you can use these tags:

:::::xml
<srcSysconfFilesDir>src/main/packager/etc</srcSysconfFilesDir>
<sysconfFiles>
     <sysconfFile>
          <from>log4j.xml</from>
          <to>pppmonitor</to>
      </sysconfFile>
      <sysconfFile>
           <from>pppmonitor.properties</from>
           <to>pppmonitor</to>
      </sysconfFile>
</sysconfFiles>
<datadir>
     /usr/share/pppmonitor/
</datadir>
<dataFiles>
     <dataFile>
           <from>pppmonitor</from>
           <to></to>
     </dataFile>
</dataFiles>

The default sysconfDir is /etc. The pppmonitor is a script that will be placed in the /etc/init.d by the postinst.sh. The ppppmonitor script is created with the Linux Standard Base in mind:

:::::bash
#! /bin/sh

### BEGIN INIT INFO
# Provides:             pppmonitor
# Required-Start:       $all
# Required-Stop:
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    The ppp monitor checks the 3G/UMTS state
### END INIT INFO

# Do NOT "set -e"!

PATH=/sbin:/usr/sbin:/bin:/usr/bin
NAME=pppmonitor
DESC="PPP Monitor"
DAEMON=/usr/sbin/pppmonitor
PIDFILE=/var/run/pppmonitor.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x $DAEMON ] || exit 0

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh 

# Define the LSB start_daemoin, killproc and log_* functions
. /lib/lsb/init-functions

case "$1" in
    start)
         [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
         start_daemon -p $PIDFILE $DAEMON 
         if [ $? -ne 0 ]; then
              [ "$VERBOSE" != no ] && log_end_msg 1 || \
              log_failure_msg "Oops!"
              exit 1
         fi
         [ "$VERBOSE" != no ] && log_end_msg 0
    ;;
    stop)
         [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" 
         killproc -p $PIDFILE $DAEMON
         if [ $? -ne 0 ]; then
              [ "$VERBOSE" != no ] && log_end_msg 1
              exit 1
         fi
         [ "$VERBOSE" != no ] && log_end_msg 0
   ;;
   restart)
         log_daemon_msg "Restarting $DESC" "$NAME"
         killproc -p $PIDFILE $DAEMON
         if [ $? -ne 0 ]; then
              log_end_msg 1
              log_failure_msg "Failed to stop $NAME."
              exit 1
         fi
         start_daemon -p $PIDFILE $DAEMON 
         if [ $? -ne 0 ]; then
              log_end_msg 1
              log_failure_msg "Failed to start $NAME."
              exit 1
         fi
         log_end_msg 0
    ;;
    status)
         log_failure_msg "Status is not implemented yet."
    ;;
    *)
         echo "Usage: $SCRIPTNAME {start|stop|restart|status}" >&2
         exit 3
    ;;
esac
exit 0

The last plugin tags define the install and remove scripts:

:::::xml
<srcAuxFilesDir>src/main/packager/scripts</srcAuxFilesDir>
<postinstScript>postinst.sh</postinstScript>
<postrmScript>postrm.sh</postrmScript>

They are placed in the directory set in the srcAuxFilesDir. Here uis the postinst.sh:

:::::bash
echo "Installing $name..."
/bin/cp $datadir/$name /etc/init.d
/bin/chmod +x /etc/init.d/$name
cd /etc/init.d 
/usr/sbin/update-rc.d $name start 95 2 3 4 5 . stop 95 0 1 6 .
echo "Installed $name successfully!"

The postrm.sh:

:::::bash
echo "Removing $name..."
/bin/rm -f /etc/init.d/$name
/usr/sbin/update-rc.d -f $name remove
echo "Removed $name successfully!"

When following this example, do use this code layout for your maven package:

alt code

Execute

The pkg plugin has four goals: config, pkg, sign and deploy. To create a package, use this command:

:::::console
[email protected]:~/java/workspace/pppmonitor$ mvn pkg:pkg
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building PPP Monitor
[INFO]    task-segment: [pkg:pkg]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing pkg:pkg
[INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Nothing to compile - all classes are up to date
[INFO] [resources:testResources {execution: default-testResources}]
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO] [compiler:testCompile {execution: default-testCompile}]
[INFO] Nothing to compile - all classes are up to date
[INFO] [surefire:test {execution: default-test}]
[INFO] Surefire report directory: /home/jw/java/workspace/pppmonitor/target/surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.elevenbits.pppmonitor.command.CurrentOperatorCommandTest
...
[device] [DEBUG] [2009.12.25 13:52:11] com.elevenbits.pppmonitor.command.ATCommand.handleLine(146) | Received empty line, ignore
[device] [DEBUG] [2009.12.25 13:52:11] com.elevenbits.pppmonitor.command.ATCommand.handleLine(148) | Received OK, output complete
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.018 sec

Results :

Tests run: 10, Failures: 0, Errors: 0, Skipped: 0

[INFO] [jar:jar {execution: default-jar}]
[INFO] [pkg:pkg {execution: default-cli}]
[INFO] distribution             : ubuntu_hardy
[INFO] package system           : deb
[INFO] default package map      : built-in
[INFO] auxiliary package map    : file:/home/jw/java/workspace/pppmonitor//src/main/packager/elevenbits.xml
[INFO] type of project          : application
[INFO] section                  : misc
[INFO] bundle all dependencies  : no
[INFO] ahead of time compilation: no
[INFO] custom jar libraries     : <none>
[INFO] JNI libraries            : <none>
[INFO] auxiliary file source dir: src/main/packager/scripts
[INFO] auxiliary files          : <none>
[INFO] prefix                   : / (default)
[INFO] sysconf files source dir : src/main/packager/etc
[INFO] sysconfdir               : (default)
[INFO] dataroot files source dir: src/main/auxfiles (default)
[INFO] dataroot                 : (default)
[INFO] data files source dir    : src/main/auxfiles (default)
[INFO] datadir                  : /usr/share/pppmonitor/
[INFO] bindir                   : (default)
[INFO] creating temporary directory: /home/jw/java/workspace/pppmonitor/target/deb-tmp
[INFO] cleaning the temporary directory
[INFO] creating package directory: /home/jw/java/workspace/pppmonitor/target/deb-tmp/pppmonitor-0.0.3-0ubuntu~hardy-r6
[INFO] copying artifact: /home/jw/java/workspace/pppmonitor/target/pppmonitor-0.0.3.jar
[INFO] destination: /home/jw/java/workspace/pppmonitor/target/deb-tmp/pppmonitor-0.0.3-0ubuntu~hardy-r6/usr/share/java/pppmonitor.jar
[INFO] copying sysconf file: /home/jw/java/workspace/pppmonitor/src/main/packager/etc/log4j.xml
[INFO] destination: /home/jw/java/workspace/pppmonitor/target/deb-tmp/pppmonitor-0.0.3-0ubuntu~hardy-r6/etc/pppmonitor
[INFO] copying sysconf file: /home/jw/java/workspace/pppmonitor/src/main/packager/etc/pppmonitor.properties
[INFO] destination: /home/jw/java/workspace/pppmonitor/target/deb-tmp/pppmonitor-0.0.3-0ubuntu~hardy-r6/etc/pppmonitor
[INFO] copying data file: /home/jw/java/workspace/pppmonitor/src/main/packager/scripts/pppmonitor
[INFO] destination: /home/jw/java/workspace/pppmonitor/target/deb-tmp/pppmonitor-.0.3-0ubuntu~hardy-r6/usr/share/pppmonitor
[INFO] resolving dependency artifacts
[WARNING] ubuntu_hardy has no entry for: com.elevenbits:devices:jar:1.1.0:compile
[WARNING] ubuntu_hardy has no entry for: javax.mail:mail:jar:1.4:compile
[WARNING] ubuntu_hardy has no entry for: javax.jms:jms:jar:1.1:compile
[WARNING] ubuntu_hardy has no entry for: com.sun.jdmk:jmxtools:jar:1.2.1:compile
[WARNING] ubuntu_hardy has no entry for: com.sun.jmx:jmxri:jar:1.2.1:compile
[WARNING] ubuntu_hardy has no entry for: org.apache.log4j:rolling-appender:jar:1.0:compile
[INFO] using traditional starter
[INFO] copying 6 dependency artifacts.
[INFO] destination: /home/jw/java/workspace/pppmonitor/target/deb-tmp/pppmonitor-0.0.3-0ubuntu~hardy-r6/usr/share/java/pppmonitor
[INFO] copying artifact: org.apache.log4j:rolling-appender:jar:1.0:compile
[INFO] copying artifact: com.elevenbits:devices:jar:1.1.0:compile
[INFO] copying artifact: com.sun.jmx:jmxri:jar:1.2.1:compile
[INFO] copying artifact: javax.jms:jms:jar:1.1:compile
[INFO] copying artifact: com.sun.jdmk:jmxtools:jar:1.2.1:compile
[INFO] copying artifact: javax.mail:mail:jar:1.4:compile
[WARNING] ubuntu_hardy has no entry for: com.elevenbits:devices:jar:1.1.0:compile
[WARNING] ubuntu_hardy has no entry for: javax.mail:mail:jar:1.4:compile
[WARNING] ubuntu_hardy has no entry for: javax.jms:jms:jar:1.1:compile
[WARNING] ubuntu_hardy has no entry for: com.sun.jdmk:jmxtools:jar:1.2.1:compile
[WARNING] ubuntu_hardy has no entry for: com.sun.jmx:jmxri:jar:1.2.1:compile
[WARNING] ubuntu_hardy has no entry for: org.apache.log4j:rolling-appender:jar:1.0:compile
[INFO] creating control file: /home/jw/java/workspace/pppmonitor/target/deb-tmp/pppmonitor-0.0.3-0ubuntu~hardy-r6/DEBIAN/control
[INFO] calling dpkg-deb to create binary package
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5 seconds
[INFO] Finished at: Fri Dec 25 13:52:13 CET 2009
[INFO] Final Memory: 13M/78M
[INFO] ------------------------------------------------------------------------

You can find the .deb file in the target folder.

To sign and deploy a site to your (private) package list, you can use this command:

:::::console
[email protected]:~/java/workspace/pppmonitor$ mvn pkg sign deploy -Dmaven.test.skip -Drepo=<dupload config name>

where the dupload config name is the name linking to your packaging system as specified in the /etc/dupload.conf file. The dupload tool is a utility to upload Debian packages. See here for an example and information regarding this command.

Howto merge PDF documents

It is very simple to merge serveral PDF documents together into one PDF document. Just make sure that the gs package is installed on your system.

::::console
[email protected]:~$ gs -dNOPAUSE -sDEVICE=pdfwrite \
> -sOUTPUTFILE=result.pdf \
> -dBATCH one.pdf two.pdf three.pdf

This command will merge the thee PDF documents one.pdf, two.pdf and three.pdf into the resulting result.pdf document.

Howto create your own Ubuntu repository

Ubuntu and Debian packages are all bundled in something what is called a repository. Some people, like me, create their own:

Note:

My repository links with the Jaunty distribution (that is Ubuntu 9.04). Your can connect yours to any other, like Debians experimental repository.

First create your own repository.

My repository is accessible over the web, so I installed it on my web server:

::::console
[email protected]:~$ cd /var/www/
[email protected]:/var/www$ sudo mkdir packages
[email protected]:/var/www$ cd packages/

In this /var/www/packages we will create a pool, the 'jaunty' distribution and the cache directories:

::::console
[email protected]:/var/www/packages$ sudo mkdir -p pool/main
[email protected]:/var/www/packages$ sudo mkdir -p dists/jaunty/main/binary-i386
[email protected]:/var/www/packages$ sudo mkdir .cache

Now two files need to be created. The first one is the apt-release.conf. Make sure that it looks like:

::::console
APT::FTPArchive::Release::Codename "jaunty";
APT::FTPArchive::Release::Origin "elevenbits.com";
APT::FTPArchive::Release::Components "main";
APT::FTPArchive::Release::Label "ElevenBits Ubuntu Repository";
APT::FTPArchive::Release::Architectures "i386";
APT::FTPArchive::Release::Suite "jaunty;

The second file is called apt-ftparchive.conf. This one should look like:

::::console
Dir {
     ArchiveDir ".";
     CacheDir "./.cache";
};

Default {
     Packages::Compress ". gzip bzip2";
     Contents::Compress ". gzip bzip2";
};

TreeDefault {
     BinCacheDB "packages-$(SECTION)-$(ARCH).db";
     Directory "pool/$(SECTION)";
     Packages "$(DIST)/$(SECTION)/binary-$(ARCH)/Packages";
     Contents "$(DIST)/Contents-$(ARCH)";
};

Tree "dists/jaunty" {
     Sections "main";
     Architectures "i386";
}

After you'd created these file your system should look like this:

::::console
[email protected]:/var/www/packages$ ls -al
total 28
drwxr-xr-x 5 root root 4096 Aug 14 13:32 .
drwxr-xr-x 3 root root 4096 Aug 14 13:22 ..
drwxr-xr-x 2 root root 4096 Aug 14 13:26 .cache
-rw-r--r-- 1 root root  427 Aug 14 13:32 apt-ftparchive.conf
-rw-r--r-- 1 root root  282 Aug 14 13:30 apt-release.conf
drwxr-xr-x 3 root root 4096 Aug 14 13:26 dists
drwxr-xr-x 3 root root 4096 Aug 14 13:26 pool

Add your own packages and update the repository.

Here the yourpackage package version 1.0 is copied into the new (empty) repository:

::::console
[email protected]:~$ cd /var/www/packages/pool/main
[email protected]:/var/www/packages/pool/main$ sudo cp ~/yourpackage_1.0_all.deb .

Now the repo needs to be initialized. This you can do using these commands:

::::console
[email protected]:~$ cd /var/www/packages
[email protected]:/var/www/packages$ sudo apt-ftparchive generate apt-ftparchive.conf
 pool/main: 1 files 9900B 0s
Done Packages, Starting contents.
 dists/jaunty/Contents-i386: 1 files 9900B 0s
Done. 9900B in 1 archives. Took 0s
[email protected]:/var/www/packages$ apt-ftparchive -c apt-release.conf release dists/jaunty | sudo tee dists/jaunty/Release
Architectures: i386
Codename: jaunty
Components: main
Date: Mon, 17 Aug 2009 14:16:41 UTC
Label: ElevenBits Ubuntu Repository
Origin: elevenbits.com
Suite: jaunty
MD5Sum:
 1d25efc884e5bbfc32eeba74771e322e              536 main/binary-i386/Packages
 574c2e304fb14272b8f70355e93fbe80              416 main/binary-i386/Packages.bz2
 3a0cbc2e4a38e40c8182451c85de1251              390 main/binary-i386/Packages.gz
SHA1:
 949b9e9045f7698cd64abd4c1fa2261eb5d22f82              536 main/binary-i386/Packages
 6d5d5c841a8890b4491650f4f360d53158d16cc0              416 main/binary-i386/Packages.bz2
 eda59ba70dc9e9d65cf92076e33cb589a07de564              390 main/binary-i386/Packages.gz
SHA256:
 b30b4e68d8928785d132dbdc6bb4158e75e907e07f00a3b8d206030236b8f94a              536 main/binary-i386/Packages
 38b855ab6e0ce3111f986f26347871827e5e461af9b29b8ccf12773560f63caf              416 main/binary-i386/Packages.bz2
 1d1aec4f2cff1a3b71212083aabfc3f2003c88b70f1f0a2ef32bfbb94c2aa879              390 main/binary-i386/Packages.gz

After this, the repository is ready to be used. See http://localhost/packages to make sure.

Note:

Remember to re-initialize the repo each time the /var/www/packages is altered.

Enable the repository on your client machines.

On the Ubuntu machines that need access to your repository, use

::::console
sudo vim /etc/apt/sources.list

to add in the repository address:

::::sources.list
deb http://ww.xx.yy.zz/packages jaunty main

where ww.xx.yy.zz is the address where your server lives.

From now on the system has access to our own private repository. Cool, no?