Ubuntu Package Management
Once your server is installed, it only contains the few packages it requires to boot and run properly. To get it to do some actual serving, we'll have to install specific server software. In the comfort of the GNOME graphical environment on an Ubuntu desktop, we could launch Synaptic and point and click our way through application discovery and installation. But on a server, we must be shell samurai.
The Ubuntu Archive
Before we delve into the nitty-gritty of package management, let's briefly outline the structure of the master Ubuntu package archive, which we mentioned in the introduction to this chapter. Each new release has five repositories in the archive, called main, restricted, backports, universe, and multiverse. A newly installed system comes with only the first two enabled (and the security update repository, but we'll talk about that later). Here's the repository breakdown
- Main: This includes all packages installed by default; these packages have official support.
- Restricted: These are packages with restricted copyright, often hardware drivers.
- Backports: These are newer versions of packages in the archive, provided by the community.
- Universe: The universe includes packages maintained by the Ubuntu community.
- Multiverse: The multiverse includes packages that are not free (in the sense of freedom).
The term "official support" is a bit of a misnomer, as it doesn't refer to technical support that one would purchase or obtain, but speaks instead to the availability of security updates after a version of Ubuntu is released. Standard Ubuntu releases are supported for 18 months, which means that Ubuntu's parent company, Canonical Ltd., guarantees that security updates will be provided, free of charge, for any vulnerabilities discovered in software in the main repository for 18 months after a release. No such guarantee is made for software in the other repositories.
Of particular note is that certain Ubuntu releases have longer support cycles. These releases are denoted by the acronym LTS (long-term support) in their version number. Ubuntu 6.06 LTS, Dapper, will be supported for five years on servers!
APT Sources and Repositories
You're now aware of the structure of the Ubuntu archive, but we didn't explain how to actually modify the list of repositories you want to use on your system. In Debian package management parlance, the "list of repositories" is part of the list of Advanced Package Tool (APT) sources (keep your eyes peeled: many of the package tools we'll discuss below begin with the prefix "apt"). These sources tell APT where to find available packages: in the Ubuntu archive on the Internet, on your CD-ROM, or in a third-party archive.
The APT sources are specified in the file /etc/apt/sources.list. Let's open this file up in an editor—if you're not used to vim, substitute nano for it, which is an easier-to-use, beginner-friendly editor:
$ vim /etc/apt/sources.list
The lines beginning with a hash, or #, denote comment lines and are skipped over by APT. At the top, you'll see the CD-ROM source that the installer added, and following it these two lines:
deb http://us.archive.ubuntu.com/ubuntu/ dapper main restricted deb-src http://us.archive.ubuntu.com/ubuntu/ dapper main restricted
We can infer the general format of the APT sources list by looking at these lines. The file is composed of individual sources, one per line, and each line of several space-separated fields. The first field tells us what kind of a source the line is describing, such as a source for binary packages (deb) or source code packages (deb-src). The second field is the actual URI of the package source, the third names the distribution whose packages we want (dapper), and the remaining fields tell APT which components to use from the source we're describing—by default, main, and restricted.
If you look through the rest of the file, you'll find it's nicely commented to let you easily enable two extra repositories: the very useful universe and the bleeding-edge backports. In general, now that you understand the format of each source line, you have complete control over the repositories you use, and while we strongly recommend against using the backports repository on a server, enabling universe is usually a good idea.
With that in mind, let's get you acquainted with some of the basic command-line package management tools on an Ubuntu system. Ubuntu inherits its package management from Debian, so if you're familiar with Debian, the utilities we'll discuss are old friends.
Our first stop is the Debian package manager, dpkg, which sits around the lowest levels of the package management stack. Through a utility called dpkg-deb, dpkg deals with individual Debian package files, referred to as "debs" for their .deb filename extension.
dpkg is extensively documented in the system manual pages, so you can read up about the various options it supports by entering man dpkg in the shell. We'll point out the most common dpkg operations: listing and installing packages. Of course, dpkg can also remove packages, but we'll show you how to do that with the higher-level tool called apt-get, instead.
Running dpkg -1 | less in the shell will list all the packages on your system that dpkg is tracking, in a six-column format. The first three columns are one letter wide each, signifying the desired package state, current package status, and error status, respectively. Most of the time, the error status column will be empty.
The top three lines of dpkg output serve as a legend to explain the letters you can find in the first three columns. This lets you use the grep tool to search through the package list, perhaps to look only at removed packages, or those that failed configuration.
Installing a Package Manually
There are more than 17,000 packages in the Ubuntu archive for each release. Only a small percentage of those are officially supported, but all the other packages are still held to reasonably rigorous inclusion requirements. Packages in the Ubuntu archive are thus almost universally of high quality and are known to work well on your Ubuntu system.
Because of this, the archive should be the very first place you look when you choose to install new software. In rare instances, however, the software you want to install won't be available in the archive, either because it's new or because there are redistribution restrictions which prevent it from being included. In those cases, you might have to either build the software from source code, run binaries that the vendor provides, or find third-party Ubuntu or Debian packages to install.
Impatience is a hallmark virtue of programmers and system administrators alike, so if you were too impatient to read the warning note, do it now. This is serious business. Let's continue: Say you've downloaded a package called "myspecial-server.deb." You can install it simply by typing:
$ sudo dpkg -i myspecial-server.deb
dpkg will unpack the deb, make sure its dependencies are satisfied, and proceed to install the package. Remember what we said about the root account being unusable by default? Installing a package requires administrator privileges, which we obtained by prefixing the command we wanted to execute with sudo and entering our user password at sudo's prompt.
apt-get and apt-cache
Now let's jump higher up in the stack. Whereas dpkg deals mostly with package files, apt-get knows how to download packages from the Ubuntu archive or fetch them from your Ubuntu CD. It provides a convenient, succinct interface, so it's no surprise it's the tool that most system administrators use for their package management on Ubuntu servers.
While apt-get deals with high-level package operations, it won't tell you which packages are actually in the archive and available for installation. It knows how to get this information behind the scenes from the package cache, which you can manipulate using a simple tool called apt-cache. Let's see how these two commands come together with an example. Say we're trying to find and then install software that lets us work with extended filesystem attributes.
Searching the Package Cache and Showing Package Information
We begin by telling apt-cache to search for the phrase "extended attributes":
$ apt-cache search "extended attributes" attr - Utilities for manipulating filesystem extended attributes libattr1 - Extended attribute shared library libattr1-dev - Extended attribute static libraries and headers python-pyxattr - module for manipulating filesystem extended attributes python2.4-pyxattr - module for manipulating filesystem extended attributes rdiff-backup - remote incremental backup xfsdump - Administrative utilities for the XFS filesystem xfsprogs - Utilities for managing the XFS filesystem
The parameter to apt-cache search can be either a package name or a phrase describing the package as above. The lines following our invocation are the output we received, composed of the package name on the left, and a one-line description on the right. It looks like the attr package is what we're after, so let's see some details about it.
$ apt-cache show attr Package: attr Priority: optional Section: utils Installed-Size: 192 Maintainer: Nathan Scott <firstname.lastname@example.org> Architecture: i386 Version: 2.4.25-1 Depends: libattr1, libc6 (>= 2.3.4-1) Conflicts: xfsdump (<< 2.0.0) Filename: pool/main/a/attr/attr_2.4.25-1_i386.deb Size: 34192 MD5sum: fc71e19f1fff7017998332d96459baba Description: Utilities for manipulating filesystem extended attributes A set of tools for manipulating extended attributes on filesystem objects, in particular getfattr(1) and setfattr(1). An attr(1) command is also provided which is largely compatible with the SGI IRIX tool of the same name. Bugs: mailto:email@example.com Origin: Ubuntu
Don't be daunted by the verbose output. Extracting the useful bits turns out to be pretty simple. We can already see from the description field that this is, in fact, the package we're after. We can also see the exact version of the packaged software, any dependencies and conflicting packages it has, and an e-mail address to which we can send bug reports. And looking at the filename field, the pool/main snippet tells us this is a package in the main repository.
Installing a Package
So far, so good. Let's perform the actual installation:
$ sudo apt-get install attr
apt-get will track down a source for the package, such as an Ubuntu CD or the Ubuntu archive on the Internet, fetch the deb, verify its integrity, do the same for any dependencies the package has, and, finally, install the package.
Removing a Package
For didactic purposes, we're going to keep assuming you're very indecisive and that right after you installed the attr package, you realized it wasn't going to work out between the two of you. To the bit bucket with attr!
$ sudo apt-get remove attr
One confirmation later and attr is blissfully gone from your system, except for any configuration files which it may have installed. If you want those gone, too, you'd have to instead run the following:
$ sudo apt-get––purge remove attr
Performing System Updates
Installing and removing packages is a common system administration task, but not as common as keeping the system up to date. This doesn't mean upgrading to newer and newer versions of the software (well, it does, but not in the conventional sense), because once a given Ubuntu version is released, no new software versions enter the repositories except for the backports repository. On a server, however, you're strongly discouraged from using backports, because they receive a very limited amount of quality assurance and testing, and because there's usually no reason for a server to be chasing new software features. New features bring new bugs, and as a system administrator, you should value stability and reliability miles over features. Ubuntu's brief, six-month development cycle means that you'll be able to get all the new features in half a year anyway. But by then they will be in the main repositories and will have received substantial testing. Keeping a system up to date thus means making sure it's running the latest security patches, to prevent any vulnerabilities discovered after the release from endangering your system.
Luckily, apt-get makes this process amazingly easy. You begin by obtaining an updated list of packages from the Ubuntu archive:
$ sudo apt-get update
and then you simply run the upgrade:
$ sudo apt-get upgrade
After this, apt-get will tell you either that your system is up to date or what it's planning to upgrade, and it will handle the upgrade for you automatically. How's that for cool?
Running a Distribution Upgrade
When a new Ubuntu release comes out and you want to upgrade your server to it, you'll again use apt-get. We'll discuss apt sources in a bit, but for now, here's what an upgrade from Breezy to Dapper would look like:
$ sudo sed -i "s/breezy/dapper/" /etc/apt/sources.list $ sudo apt-get update $ sudo apt-get dist-upgrade
Let's dissect what we've done. The first line uses a tool called sed, or the stream editor, to exchange every occurrence of the word "breezy" with the word "dapper" in the file called /etc/apt/sources.list, or the apt sources file. We then tell apt-get to reload the list of packages from the archive, which downloads the list of packages available in Dapper because of our change to the apt sources. dist-upgrade is the smug older brother of upgrade who knows how to deal with dependencies in the face of new package versions. So apt-get will figure out the order in which to replace packages with the versions from the new release, and then just run through it like a regular upgrade.
Except when it doesn't.
Trivial to use and rather powerful, it's no wonder that apt-get is one of Ubuntu's most beloved features. It's a time-tested tool that deals well with most package situations and makes the system administrator's life a breeze when dealing with software maintenance. But every once in a while, apt-get will paint itself into a corner, and a lot of times that'll happen when trying to upgrade to a new release.
In Dapper, a lot of work has gone into making the release upgrade a smoother process. Some improvements have been made, but apt-get is only so flexible, and it's not known whether the deeper issues with it can be fixed at all if we stay within its framework. This is why Ubuntu has its sights set on another package manager, appropriately called Smart, to maybe take over from apt-get. Smart is written in a high-level, dynamic language, has superior dependency graph resolution capabilities, and would still offer all the ease of use of apt-get while better handling the corner cases. Smart is experimental software, though, so its inclusion for such a chief role as package management is still very uncertain and has no known timeline. We're really just giving you a heads up; apt-get should still be your best friend.
Building Packages from Source
The Ubuntu archive, unlike Debian's, doesn't permit direct binary uploads. When Ubuntu developers want to add a piece of software to the archive, they prepare its source code in a certain way and put it in a build queue. From there it's compiled, built automatically, and—if those steps succeed—pushed into the archive.
Why go through all the trouble? Why not just have the developers build the software on their machines? They could upload binaries to the archive, bypassing the build queue, which can take hours to build software. Here's the catch: Ubuntu officially supports three hardware platforms (Intel x86, AMD64/EM64T, and PowerPC). Without the build queue, developers would have to build separate binaries of their software for each platform, which entails owning a computer running on each platform (expensive!) or creating complicated cross-compilation toolchains. And even then, sitting through three software builds is an enormous waste of precious developer time.
The build queue approach solves this problem, because the automatic build system takes a single source package and builds it for all the necessary platforms. And it turns out that the approach provides you, the system administrator, with a really nifty benefit: It lets you leverage the dependency-solving power and ease of use of apt-get, and apply it to building packages from source!
Now that you're excited, let's backtrack a bit. Building packages from source is primarily of interest to developers, not system administrators. In fact, as a sysadmin, you should avoid hand-built packages whenever possible, and instead benefit from the quality assurance that packages in the Ubuntu archive receive. Sometimes, though, you might just have to apply a custom patch to a piece of software before installing it. We'll use the attr package example, as before. What follows is what a session of building attr from source and installing the new package might look like—if you want to try it, make sure you install the dpkg-dev and devscripts packages.
$ mkdir attr-build $ cd attr-build $ apt-get source attr $ sudo apt-get build-dep attr $ cd attr-2.4.25 <apply a patch or edit the source code> $ dch -i $ dpkg-buildpackage -rfakeroot $ cd .. $ sudo dpkg -i *.deb
All of the commands we invoked are well-documented in the system man pages, and covering them in detail is out of the scope of this chapter. To briefly orient you as to what we did, though:
- We made a scratch directory called attr-build and changed into it.
- apt-get source attr fetched the source of the attr package and unpacked it into the current directory.
- apt-get build-dep attr installed all the packages that are required to build the attr package from source.
- We changed into the unpacked attr-2.4.25 directory, applied a patch, and edited the package changelog to describe our changes to the source.
- dpkg -buildpackage -rfakeroot built one or more installable debs from our package.
- We ascended one directory in the filesystem and installed all the debs we just built.
This is a super-compressed cheat sheet for a topic that takes a long time to master. We left a lot of things out, so if you need to be patching packages for production use, go and read the man pages of the tools we mention above first and get a better understanding of what's going on!
Around the highest levels of the package management stack hangs aptitude, a neat, colorful textual frontend that can be used interchangeably with apt-get. We won't go into detail about aptitude use here; plenty of information is available from the system manual pages and the online aptitude help system (if you launch it as aptitude from the shell). It's worth mentioning, though, that one of the chief reasons some system administrators prefer aptitude over apt-get is its better handling of so-called orphan packages. Orphan packages are packages that were installed as a dependency of another package which has since been removed, leaving the orphan installed for no good reason. apt-get provides no automatic way of dealing with orphans, instead relegating the task to the deborphan tool, which you can install from the archive. By contrast, aptitude will remove orphan packages automatically.
Tips and Tricks
Congratulations. If you've gotten this far, you're familiar with most aspects of effectively dealing with packages on your Ubuntu server. Before you move on to other topics, though, we want to present a few odds and ends that will probably come in handy to you at one point or another.
Listing Files Owned by a Package
Sometimes it's really useful to see which files on your system belong to a specific package, say, cron. Here's dpkg to the rescue:
$ dpkg -L cron
Be careful, though, as dpkg -L output might contain directories that aren't exclusively owned by this package but shared with others.
Finding Which Package Owns a File
The reverse of the previous operation is just as simple:
$ dpkg -S /etc/crontab cron: /etc/crontab
The one-line output tells us the name of the owner package on the left.
Finding Which Package Provides a File
Both dpkg -S and dpkg -L operate on the database of installed packages. Sometimes, you might need to figure out which—potentially uninstalled—package provides a certain file. We might be looking for a package that would install the bzr binary, or /usr/bin/bzr. To do this, first install the package apt-file (requires the universe repository), then execute:
$ apt-file update $ apt-file search /usr/bin/bzr
Voilà! apt-file will tell you that the package you want is bzr, with output in the same format as dpkg -S.
That's it for our package management tricks—it's time to talk about security.