Centralized Printing Using CUPS
Love or hate it, printing is something every user needs to do. In today's heterogeneous computing environment, providing a centralized printing solution can prove to be a pain. The days of having a large, dedicated printer for only UNIX systems are pretty much gone. I still remember the days of de-batching prints and sending them to users. Increasingly, system administrators find themselves having to make their UNIX systems print to printers sitting next to desks that are scattered throughout the company. Add to that the need for increased security, and you could find that firewalls also need to be navigated.
Such a situation exists where I work. A number of printers are scattered throughout the company, with UNIX systems sitting on different LANs and firewalls in between. None of the systems can talk directly to the LAN to which the printers are connected.
The CUPS server sits on a Linux system in a DMZ. This DMZ exists between the LAN where the printers reside and the LAN where the production systems lie. Installing CUPS on Linux was, as we all have come to expect, pretty painless. Add the RPMs, and the software is there and ready for use.
The configuration of the CUPS server also was quite straightforward. All of the configuration files reside in /etc/cups. Therefore, it was a simple case of modifying the cupsd.conf file to accommodate the environment. The only hiccup I experienced came when it was time to specify the listen IP address. Adding listen 127.0.0.1:631 to the cupsd.conf allowed the local host to be able to access the printers, but not the remote hosts. Changing this to the IP of the CUPS server itself allowed remote hosts to access the printers, but not the CUPS server. I needed both to appear for everything to work normally:
listen 127.0.0.1:631 listen 10.42.13.51:631
Remote management is extremely important. As the management has to be done from the same LAN as the printers, port 631 (the default port) had to be enabled through the firewall. This allows HTTP access to the administration facilities, which makes life a lot easier when it comes to defining and administering printers.
The other port to look out for is 515, the printer port. This must be allowed from the CUPS server to the Windows print server, if you have one, or to the network your printers reside on if you are defining network printers directly.
Printers can be added in a couple of ways. Both rely on knowing or being able to find out which printers are available to be used. In this scenario, the printers are networked printers being served by Windows servers. This is actually quite useful, as it does away with the need to find printer drivers for Linux. Like it or not, printer drivers usually are available under Windows before Linux, and in this instance the printer infrastructure already is present. The other bonus is we don't need to punch holes in the DMZ to allow the print server to talk to all of the printers in the network; fewer holes to the print server on the corporate LAN are required.
Printers can be added by using a Web interface or by manually editing the printers.conf file and creating the relevant .ppd file. This is great if you have an example to copy; otherwise, it is easier to add the printer using the Web interface.
An example printer entry in the printers.conf file, served from a Windows server (pserver) follows:
<DefaultPrinter p1_hp8150_01> Info 1st Floor Printer (BW) Location IRELAND DeviceURI lpd://pserver/p1_hp8150_01 State Idle Accepting Yes JobSheets none none QuotaPeriod 0 PageLimit 0 KLimit 0 </Printer>
The corresponding .ppd file can be found in the /etc/cups/ppd directory. The content of this file depends entirely on the type of printer. Michael R. Sweet's book on CUPS (ISBN 0-672-32196-3) covers writing .ppd files from scratch if required.
One of the major headaches I had was getting CUPS to compile under HP-UX11i. This is the nightmare situation that all system administrators hate the most--something doesn't work and you don't quite know who to turn to for help. HP was unable to help, and searches on the Internet at the time came up empty.
It's difficult to know quite what approach to take in this scenario. Problems like this one could be due to missing patches, broken patches, broken code or any other number of things. Therefore, the only option is to try to fix one thing at a time and see what happens.
The first thing I did was ensure I had the latest patches for HP-UX. There was no change, and the HP ANSI-C compiler still gave me problems. The next thing I tried was to use a GCC compiler. I had a slightly out-of-date version already installed, along with a slightly older version of binutils. A different error appeared this time, and it still failed to compile. Only by downloading the latest version of GCC and binutils, available from the HP-UX Porting Centre, could I finally get CUPS to compile. Even then it was not all good news. Although compilation worked, it now failed on the make install. This problem was as a result of using a bad option to the copy command, cp. I t turned out that the cp command included in HP-UX did not support the -d option. That option is available only to the GNU version of cp, which is part of fileutils. Even so, after having installed this, a problem still occurred when it came to completing the installation. Not being an expert in makefiles, I was beginning to run out of ideas.
While trawling back through the CUPS Web site looking for inspiration, I came across EPM. I decided that it would be worth a try, as it appeared to be able to create a software depot. Being an HP-UX administrator, I knew a bit about how this software worked. I knew that a depot consisted of files being taken from a source location and then being deployed to the final location, which was exactly what make install was failing to do. Thankfully, EPM built without any problems at all, and I was able to generate a depot. The final step in this phase involved installing the depot, and I finally found myself with CUPS installed in the right place.
I have to note that I did raise a bug report on www.cups.org but managed to resolve my problem in other ways. I was surprised to see that the bug report had been closed, with (as far as I can tell) no resolution to the original problem--the code refused to compile or complete the make install. Anyone trying to go though the same process likely will hit the same issues. At least there is a work-around, and it is included in the bug report.
The installation of CUPS on the desired HP server made no difference to the existing printing setup, partly because the application was calling custom code to print files as opposed to generating standard lp requests. This allowed CUPS to be installed and tested with no effect on the existing live service. This is something to bear in mind when looking to deploy CUPS in an environment where a live service may be affected.
As usual, the Linux clients were a dream. All that had to be done was to change the ServerName directive to the name of the CUPS server. In this case, only one server was effected. If you are considering multiple servers to be allocated on a per-user basis, it probably would be better to set the CUPS_SERVER environment variable to the name of the desired CUPS server.
Now, we can try to see if everything works by using lpstat. This command shows all printers available for use. The following example, issued from a system in the clean network to a CUPS server in a DMZ, shows a locally attached printer:
sys1:/opt # lpstat -t scheduler is running system default destination: lp0 device for lp0: parallel:/dev/lp0 lp0 accepting requests since Jan 01 00:00 printer lp0 is idle. enabled since Jan 01 00:00
This next example shows a number of remote printers. These printers are out on the network and are served by a Windows server:
monkey:~# lpstat -t scheduler is running system default destination: p1_hp8150_01 device for p1_hp8150_01: lpd://pserver:515/p1_hp8150_01 device for p1_hp8550_01: lpd://pserver:515/p1_hp8550_01 device for p2_hp4100_01: lpd://pserver:515/p2_hp4100_01 p1_hp8150_01 accepting requests since Jan 01 00:00 p1_hp8550_01 accepting requests since Jan 01 00:00 p2_hp4100_01 accepting requests since Jan 01 00:00 printer p1_hp8150_01 is idle. enabled since Jan 01 00:00 printer p1_hp8550_01 is idle. enabled since Jan 01 00:00 printer p2_hp4100_01 is idle. enabled since Jan 01 00:00
The printers now are defined, so it's time to try a test print:
sysl:/ # lp -d p1_hp8550_01 /etc/hosts
Your print job now should appear on the printer. Job done.