Diving into NixOS: Printing
I like to dive into problems to learn new skills. Especially when it comes to technology and crafts. This led to a self-made cargo-bike, basic welding skills, but also the basis for my profession: knowledge of embedded systems, programming in C and configuring various software systems.
In this and probably two future blog posts I want to document my last deep-dive into a new-to-me technology:
Nix/NixOS or more specifically getting my printer/scanner combo device to work well with NixOS.
Nix is a functional approach to packaging software, and approaching system configuration. The OS is configured declaratively by writing config files, instead of changing the system in an iterative way. I’ve used both Debian and Arch Linux based distributions before and experienced problems regarding software dependencies and malfunctioning packages now and then with them. Probably NixOS will have some challenges for me as well, but I’m more willing to tackle them. Whatever I do to mitigate those is documented and version controlled in my system configuration and won’t come back to haunt me (ooh, I remember I spent hours debugging and solving this problem, but what the heck did I do?). I’ve had NixOS installed on my personal laptop for 3 months, with barely enough configuration for it to serve my everyday needs, but without wrapping my head around it yet. So it’s about time to develop better skills around the system I’m using.
I’ll use this post to document the chunk that worked quite flawlessly: getting the printer to work. I’ll have a similar post for the scanner as well, which was more challenging to get running well.
I’ve bought a scanner/printer combo device (Canon PIXMA TR4551) with USB and Wi-Fi connectivity about one and a half years ago. It worked OK with my previous Arch Linux setup but needed proprietary software and drivers provided by the vendor.
IPP Everywhere
Before installing those drivers again on NixOS, I tried out using the printer
with available free software drivers. The printer supports IPP
(InternetPrintingProtocol) for access via the network. CUPS
(CommonUnixPrintingService, the standard way to access printers on Linux) has a
built-in Generic IPP Everywhere Printer
driver. To get
this working on NixOS I added the line
services.printing.enable = true;
to my configuration.nix
file.
Turns out this driver works OK with my printer, but there are some pitfalls:
- The driver allows selecting the print quality in DPI from a drop-down with many many options. Selecting a value that’s not well-supported by my printer causes no error message, but weirdly scaled pages
- A similar issue arises with the color-profile selection
- The duplex printing function is inversed
Those pitfalls are more or less cosmetic, but would probably be a constant source of failed printouts in the future. I’m human and tend to forget which options I need to choose. I don’t want to be able to select unsupported modes.
It’s nice to have the printer supported kinda-out-of-the-box. I decided to try using Canon’s proprietary drivers as I remember them to work a little better.
Proprietary Driver
The drivers provided by Canon are already available as a package in NixOS! The right keyword to use in the Nix package search is cnijfilter2 which is also part of the filename of the driver archive offered for download at Canon’s website.
I went on extending my configuration.nix
file like suggested in the NixOS
wiki
services.printing.enable = true;
services.printing.drivers = [ pkgs.cnijfilter2 ];
This led to an error while rebuilding the NixOS system:
$ sudo nixos-rebuild switch
building Nix...
building the system configuration...
error: Package ‘cnijfilter2-5.30’ in /nix/store/ywjr6djpwc1cp4hp52yqwwgyb9vphkql-nixos-19.09.2426.9237a09d8ed/nixos/pkgs/misc/cups/drivers/cnijfilter2/default.nix:117 has an unfree license (‘unfree’), refusing to evaluate.
a) For `nixos-rebuild` you can set
{ nixpkgs.config.allowUnfree = true; }
in configuration.nix to override this.
b) For `nix-env`, `nix-build`, `nix-shell` or any other _Nix_ command you can add
{ allowUnfree = true; }
to ~/.config/nixpkgs/config.nix.
(use '--show-trace' to show detailed location information)
following the hint in the error message and adding
nixpkgs.config.allowUnfree = true;
to configuration.nix
solved the problem. The printer works with the new
driver and I’m glad it offers fewer options and therefore fewer possibilities
for me to screw up, but […]
A Note on Free Software
[…] I don’t like the allowUnfree = true
setting. I’m a big fan of free
software and use it whenever there’s a viable solution available. Being
pragmatic I use proprietary software on my devices as well. The decision should
remain on a per-package base though, not to give carte blanche for all unfree
packages. I found the relevant
section in the nixpkgs
manual, but the solution presented there didn’t work. Turns out there’s also a
github
issue
mentioning the documentation being incorrect and offering a working alternative
for allowing individual unfree packages.
nixpkgs.config.allowUnfreePredicate = (pkg: builtins.elem
pkg.pname [
"cnijfilter2"
]
);
Network Printing
The printer offers USB and Wi-Fi as means of communication. Using the
cnijfilter2 driver CUPS finds the printer via it’s USB connection, but not
via Wi-Fi. Printing via Wi-Fi works after configuring the printer manually
(ipp://123.ip.of.printer
). It would be nice to have CUPS auto-detect
network printers. Without going into detail (I really don’t know a lot about
auto-discovery of networked devices and just followed the clues from the
NixOS wiki) here’s what I had to add to my configuration.nix
for CUPS to
automatically find the printer via Wi-Fi:
services.avahi.enable = true;
services.avahi.nssmdns = true;
Note: the printer needs to be in the same IP-subnet as the computer for auto-discovery to work.
Declarative Printer Configuration
I’ve skipped over the part of actually configuring the printer, since I’ve not done it the Nix way yet. Configuring printers declaratively in NixOS seems to be possible and I’ll take a look into it later.
Config File
To summarize, this is the section in my configuration.nix
related to printing
{
#...
services.printing.enable = true;
services.printing.drivers = [ pkgs.cnijfilter2 ];
nixpkgs.config.allowUnfreePredicate = (pkg: builtins.elem
pkg.pname [
"cnijfilter2"
]
);
services.avahi.enable = true;
services.avahi.nssmdns = true;
#...
}
Feel free to contact me via mail or mastodon if you’ve got any notes on this post or start a public discussion via this blogs github issue tracker. Like I mentioned above, I’ve got more posts planned on Nix and my printer/scanner, so if this interests you subscribe to the RSS feed to stay tuned!