Ubuntu Package Management
Once your server is installed, it contains only the few packages it requires to boot and run properly plus whatever software you selected at the software select screen. 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 plus the security update repository. 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. The latest Ubuntu LTS, version 10.04 (Lucid), 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 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 (or something very similar):
deb http://us.archive.ubuntu.com/ubuntu/ natty main restricted deb-src http://us.archive.ubuntu.com/ubuntu/ natty 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 (lucid), 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 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 -l | 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. On rare instances, however, the software you want to install won't be available in the archive because it's new or because redistribution restrictions 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 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 by 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 in our example. 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: 240 Maintainer: Ubuntu Core Developers <email@example.com> Original-Maintainer: Nathan Scott <firstname.lastname@example.org> Architecture: i386 Version: 1:2.4.39-1 Depends: libattr1 (>= 2.4.4-1), libc6 (>= 2.6.1-1) Conflicts: xfsdump (<< 2.0.0) Filename: pool/main/a/attr/attr_2.4.39-1_i386.deb Size: 31098 MD5sum: 84457d6edd44983bba3dcb50495359fd SHA1: 8ae3562e0a8e8a314c4c6997ca9aced0fb3bea46 SHA256: f566a9a57135754f0a79c2efd8fcec626cde10d2533c10c1660bf7064a336c82 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. . Homepage: http://oss.sgi.com/projects/xfs/ 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 that 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 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 use a new tool, do-release-upgrade. The upgrade tool will switch over your sources.list to the new distribution and will figure out what packages are needed and whether they have any known issues. After it has done this, it will ask you to confirm the update by pressing y or to view the updated packages by pressing d. If you choose to view the updates, merely type y to continue the update, as the tool will not prompt you again.
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 received. 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, devscripts, and fakeroot packages.
$ mkdir attr-build $ cd attr-build $ apt-get source attr $ sudo apt-get build-dep attr $ cd attr-2.4.39 <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, here's a quick description.
- 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 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 patch packages for production use, first go and read the man pages of the tools we mentioned 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 front end 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 that has since been removed, leaving the orphan installed for no good reason. apt-get provides no automatic way to deal 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. 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 are 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
Voila! 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—now it's time to talk about security.