Printing with CUPS

Printing via Linux has always been a bit tricky, but the situation is improving in many ways. At the forefront of this change is the shift from the old Line Printer Daemon (LPD) printing system, as implemented in the BSD LPD or LPRng servers, to the newer Common Unix Printing System (CUPS). CUPS is now the default printing system of most Linux distributions, as well as with some non-Linux systems, such as Mac OS X.

Printing via Linux has always been a bit tricky, but the situation is improving in many ways. At the forefront of this change is the shift from the old Line Printer Daemon (LPD) printing system, as implemented in the BSD LPD or LPRng servers, to the newer Common Unix Printing System (CUPS). CUPS is now the default printing system of most Linux distributions, as well as with some non-Linux systems, such as Mac OS X.

Like most changes, though, the shift from BSD-style printing systems to CUPS isn’t always painless. If you’re used to BSD-style printing, CUPS may seem bizarre. In truth, though, CUPS need not be any trickier to configure than a BSD-style printing system, and it offers several advantages as well.

What’s the Big Deal About CUPS, Anyway?

The traditional LPD printing system used on Linux works by passing a file received from an application or remote client computer through a series of filters and queues, ultimately passing the file to be printed via a printer port. However, this process operates blindly: the application can’t query the printing system about the capabilities of the printer. Thus, applications must either make assumptions about the printer or must be explicitly and individually configured to handle each printer’s unique features, such as color capabilities and duplex options.

One of the big advantages of CUPS, at least in theory, is that it provides a protocol for communicating printer-specific information to applications. A CUPS-aware application can learn about a printer’s features and adjust its output and options appropriately. CUPS handles this task by associating a PostScript Printer Description (PPD) file with each printer queue. Most PostScript printers ship with PPD files, and PPD files for various non-PostScript printers (as driven via Ghostscript) are available from various sources.

So, in theory, you can tell CUPS about your printers and all your printing applications will be automatically configured to use the printers, including their unique features.

In practice, however, applications must be rewritten to take advantage of CUPS, and many programs remain unchanged — instead, they treat CUPS much as they treat older printing systems. In time, though, this feature is likely to greatly simplify printer configuration, particularly in environments in which printers sport unusual features.

Both LPD and CUPS operate as network-enabled daemons, meaning that a Linux printing system can both send print jobs to a remote printer and accept print jobs from remote clients for a local printer. CUPS, though, abandons the venerable LPD protocols, at least natively. In their place, CUPS uses a new and more feature-rich network printing system known as the Internet Printing Protocol (IPP).

One of the most interesting features of IPP and CUPS, at least in the short term and for network-enabled printing, is their support for browsing, a feature that enables print clients to automatically locate IPP print servers. On a large network, this feature can save a great deal of effort. Rather than manually reconfigure dozens or hundreds of clients whenever you add or change a printer, you need only modify the configuration on the print server computer. Those changes then propagate to all of the CUPS print clients.

Telling CUPS About Local Printers

As with BSD-style printing systems, the general assumption when using CUPS is that printers are PostScript devices. Programs generate PostScript output, and in the simplest case, CUPS passes that PostScript output directly to the printer.

If your printer isn’t a PostScript model, though, CUPS can pass the PostScript file through Ghostscript to generate an appropriate printer-specific format. To do that, though, CUPS must know what Ghostscript driver to use, and that driver must be installed on your system. A stock CUPS installation provides drivers and information for just a handful of printers — PostScript and a few models from Dymo, Epson, Hewlett-Packard, and Okidata. To print to a wider array of printers, you must install a printer driver package, or at least a PPD file for the printer in question.

To obtain the widest array of driver options, you should first install two packages: GIMP-Print (http://gimp-print.sourceforge.net) and Foomatic (http://www.linuxprinting.org/foomatic.html). Both packages ship with most major distributions, and chances are that both are already installed on your system. Foomatic is a set of interfaces to standard Ghostscript drivers. Many PPD files rely on Foomatic. GIMP-Print is a set of extra drivers originally developed for the GIMP, but adapted for use by Ghostscript. GIMP-Print is most useful if your printer isn’t well supported by Ghostscript’s stock drivers.

The next step is to install a PPD file for your printer. Some Linux distributions ship with many PPD files, often in a package called cups-drivers or something similar. Check the /usr/share/cups/model directory. If it’s filled with files and subdirectories, chances are you’ve got such a package installed. If not, or if you can’t find a PPD named for your printer, you’ll need to locate a PPD. If you’re using a PostScript printer, check the CD-ROM that shipped with the printer or visit the manufacturer’s web site to locate a PPD. (PPD files typically have a .PPD or .ppd suffix).

You can also locate PPD files for both PostScript and non-PostScript printers on the Linux Printing web site, http://www.linuxprinting.org.

Click the “Printer Listings” link, enter the manufacturer and model of your printer, and click the “Show” button. You should see information on the Linux compatibility of the printer, including a link that reads “Download PPD.”

Click this link and save the PPD file in some convenient location. (You may need to right-click the link and select an option to save to a file.) Copy the PPD file to the /usr/share/ cups/model directory. CUPS looks here during printer configuration for PPDs, and if it can’t find a PPD for your printer in this location, you may not be able to print.

You may need to restart CUPS at this point. On most distributions, typing /etc/rc.d/init.d cups restart or something similar does the job. Before you do this, though, you should ensure that your printer is powered on and plugged into the computer. This is particularly important for USB printers, because CUPS expects to be able to find any USB printers when it starts up.

Using CUPS’s Browser Interface

The simplest way to add a local or non-CUPS network printer to CUPS is to use its web-based interface, as follows:

1. Type http://localhost:631 into a web browser running on your computer. (You can also try the computer’s hostname in place of localhost.) The result should be the main CUPS configuration screen, which consists mainly of a series of options.

2. Click “Manage Printers” to see a list of printers, as shown in Figure One. (On a system connected to a network with no other CUPS servers, the list will be empty.)

Figure One: CUPS provides a web-based graphical tool to administer printers

3. Click “Add Printer” at the bottom of the page (not shown in Figure One). The system asks for a username and password. Type root as the username and type the root password.

4. You should see a prompt for the name, location, and description of the printer. This information is for your and other users’ benefit, not for the printing system. (The name you enter will be the name you pass to lpr or select from an application’s print dialog box, though.)

5. The system asks for a printer device, which you select from a drop-down menu. Precisely how many devices appear depends on your system. Chances are you’ll pick “Parallel Printer #1,” “USB Printer #1,” or something similar. (You can pick options for LPD or Samba/Windows network printers, too.) When you’re done, click “Continue.”

6. If you picked a network printer, you’ll need to enter additional information in a subsequent page. Enter the machine and printer name in the format specified. For Samba/ Windows shares, you may need to include a username and password, as in smb://user:pass@ server/share/.

7. Select the make of the printer from the list on the next page. If you don’t see the make for the printer whose PPD file you installed, either something is wrong or the PPD file doesn’t use the printer make you expect. Load the PPD file into a text editor and look for a line that starts *Manufacturer. That entry should list the make of the printer.

8. Select the printer model from the list on the next page. If you installed a single PPD for a manufacturer that wasn’t listed originally, chances are you’ll see just one model. But if you installed a set of PPDs or if some were present for your printer before you began, you may need to pick your model from a list.

After you click “Continue” after the final step, the system should respond that the printer’s been installed correctly.

You can then click the printer name to go to a printer control page. Click the “Print Test Page” button to verify that the printer is working correctly. You should see a test page emerge from the printer, summarizing the printer’s capabilities and showing a couple of geometric shapes, including one in color for color-capable printers. You should also click the “Configure Printer” link, which shows a series of printer-specific options you can adjust. These options may include the resolution, color vs. black-and-white printing, paper size, and so on. Precisely what options you see will vary from one printer to another.

At this point, you should be able to print from typical applications, such as the GIMP, OpenOffice.org, and Mozilla. The traditional Linux/Unix printing commands, such as lpr, should work too, although a few details differ between CUPS and other printing systems.

Configuring a CUPS IPP Client and Server

Ideally, if you’re setting up a CUPS client on a network that uses CUPS servers, the CUPS client should require no additional configuration to locate and use the network’s printers. If you go into the CUPS web-based configuration tool, as just described, you should see a list of available printers from the start of the process, and these printers should be available to any application that can print.

If this doesn’t work, though, chances are something is interfering with the system’s CUPS browsing traffic. This could be a firewall running on the client, a firewall running on a router between the client and the server, a firewall running on the server, or server options that are restricting access from the client.

If you’ve set up printers on a computer and want to share them with other systems that run CUPS, you must edit your CUPS configuration file, /etc/cups/cupsd.conf. Most lines in this file are parameter names followed by their values. Toward the end of the file are several blocks of associated lines, though.

The first option you should check when sharing printers is the Browsing line, which should look like Browsing On.

This line tells the system to accept browse requests from other computers. The default value is On, so many implementations comment out this option. To be sure a system functions correctly, though, uncomment this line and be sure it’s set correctly.

A few lines down, you’ll find a series of lines that are commented out and that show examples of using the BrowseAddress option. On a small network, you should set this address to the broadcast address for your network, as in: BrowseAddress

Once set, the system accepts browsing requests from any computer on the specified network. The default value doesn’t send or accept browsing information, and enabling this option is often all that’s necessary to share your printers with others.

The BrowseAllow and BrowseDeny options accept domain names or various IP address-based specifications and serve as access control tools. They can be set globally to enable system-wide controls, or used inside a <Location> directive.

These directives set access controls for particular CUPS subsystems, such as /printers or /admin, which control access to the printers themselves or administrative functions, respectively.

To share printers, you must ensure that the printers location is accessible to others, using lines like the following:

<Location /printers>
Order Deny,Allow
Deny from All
BrowseAllow from
BrowseAllow from
Allow from
Allow from

This set of options tells CUPS to first deny access as specified and then to open holes in the denial policy (Order Deny, Allow). It then denies access to all comers, but creates exceptions for both browsing (BrowseAllow) and other (Allow) accesses. These exceptions cover (the localhost system itself) and the subnet. The effect is that the system accepts print jobs from and exports its list of available printers to all computers on the network.

Configuring a CUPS Server to Work with LPD Clients

What if your CUPS server must accept print jobs from older LPD clients, though? In this case, you can run a special CUPS helper server, known as cups-ldp, that listens on the LPD port for print jobs submitted using the LPD protocol. The cups-lpd server ships with most CUPS packages, but it may be installed in an odd location, such as /usr/lib/cups/daemon/. To run it, you must create an appropriate super server configuration. If you’re using inetd, the appropriate entry looks like this:

printer stream tcp nowait lp

If you’re using xinetd, chances are your CUPS package installed an appropriate /etc/xinetd.d/cups-ldp file on your system, but you may need to edit it. Specifically, look for a line that reads disable = yes. If it’s present, either comment it out or change it to read disable = no. This enables the server.

With either inetd or xinetd, you must restart or reload the super server. On most distributions, you can do this with the SysV startup scripts by typing /etc/rc.d/init.d/inetd restart or something similar. Once you do this, the system should begin responding to LPD printing requests. Clients can be configured as if the server were running BSD LPD or LPRng. Use the CUPS printer name as the LPD printer name.

One important caveat concerning the cups-lpd server is that it provides no access control features! Once you run this server, anybody who can send data to the LPD port (515) can print to your printers. For best security, you should use a firewall and either TCP Wrappers or xinetd‘s access controls to limit access to this port.

Roderick W. Smith can be reached at rodsmith@rodsbooks.com.

Comments are closed.