home about

Build Your Own Deb File and Repository Server

July 9th, 2007 cpetersen

Introduction

How do you install software on an Ubuntu machine? How do you create a deb file? How does apt-get work? These are the questions I will try to answer in this post, but first a little background.

Background

I love Virtual Computing. I can run tons of virtual servers on a very limited number of physical machines. This allows me to segregate applications exactly as I choose. I can have subversion and Trac running on one and nothing but an email gateway on another, it also gives me a way to try new applications like Splunk without jeopardizing a system and with investing in another box. The drawback to being able to create new virtual machines on a whim is administering them once they are created. I've written a couple of applications that would like to install on all my virtual machines and that is where packaging them as deb files and creating a repository server that apt-get is aware of comes in very handy.

Create a DEB file

The ultimate goal is to be able to type
sudo apt-get install myapp
from any of my VMs and have it install properly. All apt-get really does is check all its repository servers for a deb file that contains the "myapp" package, downloads the deb file and installs it. So before we build our repository server (also a VM BTW) we have to create the deb file. To create the deb file, you need to:
  1. Create the directory structure
  2. Create the control file
  3. Write the install and uninstall scripts
  4. Build the package

Create the Directory Structure

The directory structure of your package will directly mimic the directory structure of the system, with the files in place. For example, if my application requires placing the script A.sh in /usr/sbin and B in /etc/init.d, my directory structure would like:
DEB File Directory

Create the Control File

Next, we need to create the control file. The control file is placed in a special directory called DEBIAN. After you create that directory your directory structure should look like:
DEB File Directory w/DEBIAN
Inside of the DEBIAN directory, create a file named control. Mine looks like:
Package: package
Version: 1.0
Section: web
Priority: optional
Architecture: all
Essential: no
Depends: ruby, sed, xinetd
Installed-Size: 1
Maintainer: Chris Petersen [christopher dot petersen at gmail dot com]
Provides: package
Description: A short description of your package
 This should be a longer description of your package,
 it can span multiple lines, and should indented with 
 spaces
Most of the entries are self explanatory, but the one you will want to pay close attention to is the "depends" statement. When a user installs your package, if they haven't installed any of the dependencies, apt-get will allow them to automatically install them.

Install and Uninstall

The next step is to write the install and uninstall scripts. The files in your package will automatically be copied to their corresponding location on disk, but if you need more configuration that has to be performed in your script, you can add that code to a script called "postinst" in the DEBIAN directory. Conversely, you must reverse any changes made during installation in a script called "prerm" which will be called during uninstallation. For instance, my package contains an xinetd service, so I am going to add lines to "/etc/services". My "postinst" file will look like:
#!/bin/sh

echo "package          1789/tcp" >> /etc/services
echo "package          1789/udp" >> /etc/services
/etc/init.d/xinetd reload
And my "prerm" file will look like:
#!/bin/sh

sed '/package/d' /etc/services > /tmp/services
mv /tmp/services /etc/services

Side Note About postinst and prerm

I find sed to be a very useful tool when editing configuration files from a script. This page contains many useful one sed script that may help you write your install/uninstall scripts.

Build the Package

Now our package is complete, we've placed our files in the appropriate places and written our control file, install and uninstall scripts. The last step is to package the results into a deb file. To do this, navigate to one level above your package. So if your package is in ~cpetersen/projects/pacakge, navigate to ~cpetersen/projects. From there execute the following command.
dpkg-deb --build package
That will create the file ~cpetersen/projects/package.deb. You now have a fully functioning deb file. You could install it using dpkg, but we want to use apt-get, so next we'll look at creating a repository server.

Setup a Repository Server

The repository server is a simple web server (apache in our case) that happens to store the deb files and some meta-data about them. The first step in getting it up and running is installing apache and the dpkg-dev kit which will allows us to create the index.
sudo apt-get install ssh
sudo apt-get install apache2
Next, create the directory where the repository will live. I created a virtual machine to serve as the repository server. Since this is a dedicated machine, I will create my directory directly at the www-root. This would work as well in an apache virtual server. My www-root is /var/www so my deb files will go into /var/www/repository. Finally, you must index the deb files meta data. You can do this with a program called dpkg-scanpackage that comes with the dpkg-dev package. From the directory that you want to server as your repository (for me it is the root /var/www) execute the following commands:
sudo su
dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz
Your repository server is done. If you want more information, I found this page very helpful. Now make sure apache is running and we can move on to the final step, making your clients aware of the server.

Using Your Server

So now you have your deb file, and you have your repository server. How do your client machines know to you use it? apt-get configures its servers using the /etc/apt/sources.list file. So you need to add your new server to that file. I named my server repo01, and I placed my repository in the www-root directory, so I added the following line to all of my clients /etc/apt/sources.list files:
deb http://repo01 /
Don't forget the trailing " /" (there is a space there). Now update your clients:
sudo apt-get update
And finally you should be able to install your package:
sudo apt-get install package

A Note About Adding Packages

Once your server is up and running and your clients are configured to look for it, it is very easy to add or update packages.
  1. Copy the deb file to your repository directory
  2. Re-execute the dpkg-scanpackages command to update the index
  3. Update your clients with sudo apt-get update

Conclusion

Setting up your own repository server and distributing your internal applications as deb files can simplify administration of numberous machines. There are three basic steps, each of which we outlined in this post:
  1. Create the deb file
  2. Setup the repository server
  3. Configure the clients to use your repository
You should now have a working deb file that you can install using apt-get.

6 Responses to “Build Your Own Deb File and Repository Server”

  1. Uma Shankar Says:
    Hi, This article was very informative. I would like to know more about the files which are located in "/var/lib/dpkg/info" of these endings *.list, *.md5sums, *.shlibs, *.list. This folder also has files like *.postinst and *.postrem, which I think you have explained great. Thanks.
  2. Christopher L Petersen Says:
    HI Uma, Great point, I didn't really touch on the /var/lib/dpkg/info at all. My understanding is that your install and uninstall scripts <macro:code> preinst postinst prerm postrm </macro:code> all get copied there using the filename <macro:code> {package_name}.{script_name} </macro:code> It is also my understanding that the package manager keeps track of all the files that were copied onto the file system for this install in the file: <macro:code> {package_name}.list </macro:code> So for the example in the post, the list file would look like: <macro:code> /. /etc /etc/init.d /etc/init.d/B /usr /usr/sbin /usr/sbin/A.sh </macro:code> As for the md5sums, I'm guessing it has to do with signing your package, which I haven't yet tried. shlibs seems to store the dependencies. I've also seen files named <macro:code> {package_name}.conffiles </macro:code> I assume these store the configuration files for the package, but I'm unsure how to use them. If anyone has any insight into these files, please post a reply or a link that may help. Thanks! Chris
  3. Federico Says:
    Hi, nice article. I have just a question, did you tryed also to build deb packages from rails application? I'm investigate the possibility of using deb/rpm packages to deploy rails apps. What do you think?
  4. Federico Feroldi&#8217;s blog &raquo; Blog Archive &raquo; links for 2007-09-03 Says:
    [...] Build Your Own Deb File and Repository Server How do you install software on an Ubuntu machine? How do you create a deb file? How does apt-get work? These are the questions I will try to answer in this post, but first a little background. (tags: debian linux repository package deployment howto) [...]
  5. Christopher L Petersen Says:
    Hi Frederico, I haven't tried building a deb file from Rails, but it does sound like an interesting idea. What type of service do you anticipate building? Chris
  6. hardbop200.com Says:
    [...] Build Your Own Deb File and Repository Server [...]

Leave a Reply