Configuring print spooling with CUPS on OpenWRT

OpenWRT software provides a way to turn certain wireless routers into general purpose Linux servers. This lets you do interesting things like install VPN software, use it as a file server, DNS server, and all the other things you can do on a basic Linux server. Of course you have to be careful as most routers have very limited memory and flash storage, so you can’t run just anything.

I use OpenWRT at my first restaurant and recently bought a printer/fax for the store so that my manager could print out necessary forms without bothering me. (I have bought an OpenWRT compatible router for my second restaurant but haven’t gotten around to installing it yet. EDIT: Installed OpenWRT with CUPS at the second restaurant and it is working fine now.) I originally followed the OpenWRT Printer Sharing HOWTO and installed the printer using the p910nd software and set up XP to be able to print to it.

p910nd provides very simple non-spooling printer sharing service. Windows XP calls these ‘Raw’ TCP/IP printers. Basically all it does is read in data from the client and then feed it out to the printer port. This has a lot of advantages in that it is simple and does not require storage space to spool the print job. (Remember what I said about limited flash storage?)

Unfortunately it doesn’t handle error conditions very well. It worked well most of the time, but all too frequently something would happen in the middle of printing a page. The printer would stop printing, the client would report an error and spoolsv.exe on XP would go nuts on the CPU usage. And then it was just about impossible to gracefully recover from the error. XP would refuse to remove the job without rebooting, and even then the next job on the printer would come out with the characters all scrambled. That sure is annoying, and wastes time and ink. (Those ink jet cartridges ain’t cheap.)

So what is the alternative? Well, the aforementioned HOWTO also mentions briefly that CUPS is an alternative, but that it isn’t necessarily a good option due to limited storage on most OpenWRT boxes. However, USB flash drives are cheap and make an excellent spooling device. And my OpenWRT box just happens to have a modest 512mb USB flash drive installed which should be plenty for print jobs.

The next frustration is that while there is a CUPS package provided for OpenWRT, I couldn’t find any comprehensive guide for installing or using it on OpenWRT. I also had no experience using this kind of print spooler either. That lead to much flailing around trying to figure out how to get it working, but I was finally able to crack that nut. This document will hopefully help others successfully implement CUPS on their OpenWRT routers.

First, let’s get the prerequisites out of the way. At the least you will need a working OpenWRT router with either a USB or parallel port, and a printer with the same. It is also highly recommended that you add a USB flash drive of 128mb or larger (512mb would be better). (EDIT: Flash drives are so cheap now you should probably get a 512mb or 1gb model.) If you use a USB flash drive and USB printer your router will either need to have two USB ports or you will also need a USB hub. (I haven’t tried it with a hub so please give me feedback if this works for you.)

Next, refer to the OpenWRT Printer Sharing HOWTO and follow step 3.1 if you have a USB printer or step 3.2 for a parallel port printer. Make sure you reboot after installing any ‘kmod’ packages. After this you should see a USB printer device in /dev/usb (e.g. /dev/usb/lp0) or a parallel port printer in /dev/printers (e.g. /dev/printers/0).

If you are using a USB flash drive as the spooling device, also see the OpenWRT USB Storage HOWTO to format and mount your USB storage. (I mount mine as /usb.)

Now you will install the CUPS package for OpenWRT: ipkg install cups

EDIT: You will either need to start cupsd by running ‘/etc/init.d/S60cupsd’ or wait until after installing the cups package to reboot to get lpinfo to work.

Next you will need to do some configuration. First, find out where your printer is by running ‘lpinfo -v’. You will get a list of possible printer ports available. For a USB printer you should see something like:

‘direct usb://HP/Officejet%204300%20series?serial=XXXXXXXXXXXX’

For a parallel printer you should see a device like:

‘direct parallel:/dev/printers/0’

Note that for USB printers you can refer to the printer by either device or by name. The listing above will show the named device if possible. In my case the device is really on /dev/usb/lp0. However, sometimes when a printer is power cycled or the cable is removed and plugged back in, it may come back as /dev/usb/lp1 or some other number. The named device should still work regardless of which USB device the system assigns it.

Now let’s go in and edit /etc/cups/printers.conf. The config that is installed by the package uses a default printer called USB on /dev/usb/lp0 and a printer called LP on /dev/printers/0. Use one of these as your template and remove the other one.

If you have a USB printer, then you’ll want to change the printer name from USB to something more descriptive. My printer is an HP OfficeJet 4355 so I set the first line of printers.conf to read ‘<DefaultPrinter HP4355>’. You can also change the ‘Info’ line to show a description of the printer and the ‘Location’ line to show where it is located. The important part is the DeviceURI. By default it is set to /dev/usb/lp0, but due to the issues described above, I changed it to the named device instead.

If you have a parallel port printer then you would make similar changes there except that your would keep the DeviceURI set to parallel:/dev/printers/0 unless your printer is on a different device.

In the end, my printers.conf looked like:

<DefaultPrinter HP4355>
Info HP OfficeJet 4355 USB Printer
Location Subway Xingtian Temple Store
DeviceURI usb://HP/Officejet%204300%20series?serial=XXXXXXXXXXXX
State Idle
Accepting Yes
JobSheets none none
QuotaPeriod 0
PageLimit 0
KLimit 0
</Printer>

CUPS is typically installed with various filter to understand various conversions of files to the printer’s native format. On OpenWRT, that’s not practical because of the memory limitations. It’s more practical to use the printers as raw printer devices and let the print client provide a formatted file. To enable this, edit /etc/cups/mime.convs and /etc/cups/mime.types. In each, find the line starting with ‘#application/octet-stream’ and uncomment it by removing the ‘#’ character and saving the files.

Now there are a couple of things to edit in /etc/cups/cupsd.conf. By default CUPS is set to require authentication of a system account to print. This essentially means setting up a user account for printing or entering the root password into clients. I didn’t find these options attractive, so instead I set it for anonymous access type and restricted access by IP address. If you do this, remember to make access to the administrative functions more restrictive, otherwise anyone will be able to modify your config. I decided to turn off remote admin functions entirely. The result is something like:

EDIT: I eventually switched back to using user account authentication which has the advantage of being able to print to the printer over the Internet reasonably securely. I added a user with a password and then opened up port 631 by editing /etc/firewall.user and copying the section for opening ssh access and changing the port number from 22 to 631. If you do this you can keep the original configuration for “Location /”. I decided to disable the admin functions even with password protection.

<Location />
AuthClass Anonymous
AuthType None
Order Deny,Allow
Deny From All
Allow From 192.168/16
</Location>

<Location /admin>
Order Deny,Allow
Deny From All
</Location>

That should work without modification when using any private network starting with 192.168.

By default, cups on OpenWRT uses /tmp/cups for storing temporary and spool files. /tmp on OpenWRT is a filesystem using free memory as storage. Many OpenWRT routers only have 16mb of memory and will have very little available for /tmp. Mine has a more robust 32m of memory but typically only has around 15m free with the software I have running.

Depending on your printer, a print job can take quite a bit more than this. For example, on my printer even just one simple page takes 8m and a multi-page document can easily grow to a 60-80m print spool. Needless to say, that’s not going to work too well if only 15m is free. That’s why I’m using a 512m USB flash drive for the print spool instead. Keep in mind that if you use the default config, you will be extremely constrained in what kind of things you can print. (EDIT: The amount of space needed will vary depending on your type of printer, the resolution, rendering engine, and the material being printed.)

That said, let’s say that you’ve mounted your USB flash drive as /usb. Make a print spool in /usb/cups: mkdir /usb/cups

This needs to have drwxrwx–T permissions which can be set with: chmod 1770 /usb/cups

Now change the RequestRoot and TempDir settings in /etc/cups/cupsd.conf to use that spool directory:

RequestRoot /usb/cups
TempDir /usb/cups

Now if you’ve set up everything correctly, you should be able to start up the cupsd server: /etc/init.d/S60cupsd

EDIT: You will need to kill the previous cupsd process before the prior command. ‘ps | grep cupsd’ then kill the process number in the first column.

For the following examples we will assume that the LAN interface of your router is IP address 192.168.1.1. If it is different or if you have set a host name for it in DNS, then change as appropriate.

Open up your browser and type in the address: http://192.168.1.1:631/

You should see the information on your CUPS server and the printers configured. Also make sure that you cannot access the admin functions, otherwise your print server is open to anyone changing your configuration.

Now let’s say that we have a Windows XP system to setup. On the above web page you should be able to browse down to your configured printer and end up with a URL which looks like this: http://192.168.1.1:631/printers/HP4355

(It will show the name you gave your printer instead of HP4355.)

Now bring up the Printers & Faxes explorer in XP and click on ‘Add a printer’. Select ‘network printer’ then ‘Connect to a printer on the Internet or on a home or office network’ and put the above URL in the box below that option. (EDIT: If you use the user account authentication method instead, it will ask for the login and password on the next screen.) Click on ‘next’ and you should be able to select the manufacturer and type of printer you have (or you may have to select ‘Have Disk’ if the printer driver is not included in XP) and the rest of the normal printer setup process.

If everything was done right then you should now be able to print to your network printer.

EDIT: In installing the printer at the second restaurant, I found that some printer drivers don’t show up in the list of available printers if installing as a network printer. The trick to get around this if you run into it is to install it as a USB printer first. Then open the printer properties and change the port to a network printer port.

I would appreciate any comments on whether this worked for you or not, or any significant changes you had to make to get your cups server working. Comments on my blog do not require any registration.

14 thoughts on “Configuring print spooling with CUPS on OpenWRT”

  1. Excellent tutorial thanks, I followed the instructions and my Canon iX4000 works fine on my Asus wl500gp printing with Win XP.

    There is a minor problem which I can ignore for now, on the printer administration page, when I click “Configure printer” I get the following error:
    client-error-not-possible
    Likewise “Print test page” gives the error:
    client-error-not-found

  2. If you follow the directions above, the configuration via the web client will be prohibited. You would have to change the security settings to be able to configure via the web. Also as I understand it, CUPS for OpenWRT does not include the test page software.

  3. James – thanks for the tutorial – it worked great. I had a Netgear PS121 printserver and it was junk…I took the openwrt plung on an old Netgear wgt634u, flashed it with kamikaze, then loaded and config’d cups. Due to the wgt634u having one USB port, I tried a hub and it works fine supporting a flash drive and my printer.

    Thanks again!

    Kent

  4. Thanks for this excellent tutorial. Works as charm.
    However there were a few things that needed to be altered if installing cups software on external media as i have mounted on /opt.

  5. Thank you James!

    I’ve been trying to get CUPS running on my NSLU2 for a week, but after following your tutorial it is now working. Thank you very much for posting this.

    Mike from Minnesota, USA

  6. Thank you for your instructions.

    It looks like you have been using kernel 2.4. Kernel 2.6 puts printer device files under /dev directory (not /dev/usb). I had to create directory /dev/usb and add symlinks for every lp device I had

    mkdir /dev/usb
    cd /dev/usb
    ln -s ../lp0 lp0
    ln -s ../lp1 lp1

    After that it was possible to get printer information with

    lpinfo -v

  7. Hi

    Great how-to article. After struggling with p910nd for a couple of hours, I followed your guide, and got printing via wifi working in no time.

    It took me a little longer to add an USB stick as print spool. Perhaps you could mention that setting the permissions for the temp-dir (chmod 1770 /usb/cups) requires the USB disk to be ext2 formatted. Your guide is a bit vague on the specific steps to partition and format the USB disk. Perhaps just add a couple of links?

    Otherwise I really found the guide helpful and well written!

    And I will just add, that my router is a Asus W500G Deluxe and my printer is a Konica Minolta PagePro 1400W.

    /Emil

  8. 博主,您好,想请问一下您的cups使用opkg安装上去的吗?我使用 opkg install cups报错如下:
    Unknown package ‘cups’.
    Collected errors:
    * opkg_install_cmd: Cannot install package cups.
    这应该如何解决呢,能够提供一些思路么?我搜索了网上cups包搜索不到.

Leave a Reply

Your email address will not be published.