1. Introduction

The Common UNIX Printing System (CUPS) is a way to manage printers and printing jobs in a universal way on UNIX and Linux systems. Importantly, perhaps the first thing that we need to know after setting up CUPS is whether our printer is recognized and available within the framework.

In this tutorial, we go through the installation and configuration of CUPS as well as some basic usage. First, we install CUPS and check how to deal with printer drivers. Next, we explore the status of the CUPS printing system. After that, we set up some printers for use. Then, we list the available printers and printing destinations. Finally, we test and delete printers.

We tested the code in this tutorial on Debian 12 (Bookworm) with GNU Bash 5.2.15. It should work in most POSIX-compliant environments unless otherwise specified.

2. Install CUPS

To begin with, we install CUPS via the apt tool:

$ apt-get install cups

The installation has a fairly small footprint and is relatively straightforward. Further, we should also end up with the cups-browsed setup and cups-client client utility packages.

3. Printer Drivers

Most modern printers can work without additional drivers. Moreover, the cups-browsed post-installation scripts should automatically set up any modern printer connected to the system.

On the other hand, legacy or non-modern printers most often need specific drivers to function. While some manufacturers provide packages that include the necessary driver, others aren’t easy to find or may not even be available. When that’s the case, we can also install the optional printer-driver-all package:

$ apt-get install printer-driver-all

The printer-driver-all package includes many drivers for older printers.

4. Check Status

After installing and setting up CUPS, we can check the current status via the lpstat command with the -t flag:

$ lpstat -t
scheduler is running
no system default destination
lpstat: No destinations added.
lpstat: No destinations added.
lpstat: No destinations added.
lpstat: No destinations added.

In particular, we check whether the cupsd scheduler is running, as well as the current destinations.

Notably, there are No destinations, which means we have no available printers that CUPS has detected. To remedy the situation, we can add some manually.

5. Printer and Printing Queue Setup

Printing queues are ordered lists of the printing jobs for given destinations, i.e., printers. If our local printer isn’t automatically detected, we can configure it on our own.

5.1. Manual Printer and Printing Queue Setup

In some cases, setting up a printing queue happens automatically within the cups-browsed daemon.

When this doesn’t happen, manual printer setup can be fairly simple:

$ lpadmin -p <PRINTER_NAME> -E -v <DESTINATION> -m everywhere

Let’s see an example:

$ lpadmin -p baeldungprn -E -v ipp://baeldungprn/ipp/print -m everywhere

Here, we use lpadmin to attempt an automatic setup of an Internet Printing Protocol (IPP) printer at the given target address:

  • -p creates printer (queue) with the given name
  • -E ensures we use an encrypted TLS connection
  • -v specifies a destination for the named printer
  • -m sets how the printer, specifically its driver, should be configured

With regard to -m, everywhere queries the printer and is the only non-deprecated value for that option. Depending on the printer and its destination, we might need specific drivers locally.

5.2. NULL Printer

If we want to test out CUPS, we can specify the destination as file://**/dev/null:

$ lpadmin -p nullprn -E -v file:///dev/null

At this point, we should be able to just print to the newly-created nullprn [-p]rinter at the destination after -v.

To ensure we can print to that printer, we may need to add a line to /etc/cups/cupsd.conf:

$ cat /etc/cups/cupsd.conf
FileDevice yes

Finally, we restart the CUPS daemon via systemctl:

$ systemctl restart cups

Now, the nullprn destination should be available for use.

5.3. PDF Printer

In addition, we can decide to install a so-called file printer:

$ apt-get install cups-pdf

In this case, we install the cups-pdf package, which provides the CUPSPDF printer.

The default output directory is /var/spool/cups-pdf/${USER}. To configure this and other parameters, we can edit the /etc/cups/cups-pdf.conf file:

$ cat /etc/cups/cups-pdf.conf
[...]
###########################################################################
#                                                                         #
# This is the configuration file for CUPS-PDF. Values that are not set in #
# here will use the defaults. Changes take effect immediately without the #
# need for restarting any services.                                       #
#                                                                         #
# Take care not to add whitespaces at the end of a line!                  #
#                                                                         #
# Options are marked where they can be set (setting via PPD requires the  #
# PPD file that comes with CUPS-PDF to be used!).                         #
# Options passed via lpoptions that are not named for lpoptions here are  #
# ignored.                                                                #
# Options precedence is as follows:                                       #
# 1st: lpoptions                                                          #
# 2nd: PPD settings                                                       #
# 3rd: config file (this file)                                            #
# 4th: default values                                                     #
###########################################################################
[...]

Naturally, we can’t just send raw data to this printer, as it expects a formatted PDF.

6. List Printers

After setting up printers, we can again see which ones are available via lpstat:

$ lpstat -t
scheduler is running
system default destination: PDF
device for nullprn: ///dev/null
device for PDF: cups-pdf:/
nullprn accepting requests since Thu 01 Nov 2023 11:00:01 AM EST
PDF accepting requests since Thu 01 Nov 2023 11:00:10 AM EST
printer nullprn is idle.  enabled since Thu 01 Nov 2023 11:00:01 AM EST
printer PDF is idle.  enabled since Thu 01 Nov 2023 11:00:10 AM EST

This time, we see a default destination of PDF at cups-pdf:/ (CUPSPDF), as well as an alternative nullprn at ///dev/null.

Another way to get the same information in a more concise form is the -l and -e flags:

$ lpstat -l -e
nullprn permanent ipp://localhost/printers/nullprn file:///dev/null
PDF permanent ipp://localhost/printers/PDF cups-pdf:/

In this case, we [-l]ong list all printers, classes, and jobs and show all d[-e]stinations on the local network.

Alternatively, we can use the Web interface at http://localhost:631/printers, where a static HTML view of the current printing queues is available.

7. Test Printer

Finally, to test some printers, we can just send data via the lp command:

$ printf 'Test data.' | lp -d nullprn

However, the CUPSPDF printer, for instance, doesn’t accept raw data directly. So, we might need to use it with an application that can send data in the correct way and format.

8. Delete Printer or Printing Queue

If we want to remove a printing queue or printer, we can use the -x option of lpadmin with the respective name:

$ lpadmin -x nullprn

Now, we should have disposed of the nullprn NULL printer we created earlier:

$ lpstat -l -e
PDF permanent ipp://localhost/printers/PDF cups-pdf:/

As expected, only one printer is left.

9. Summary

In this article, we set up and explored the practical basics of the CUPS system.

In conclusion, knowing how to configure CUPS and print data from the command line can be invaluable when using headless installations.