Printing: Difference between revisions
imported>Eliasp Add `pkgs.postscript-lexmark` to list of printer driver pkgs |
Tomodachi94 (talk | contribs) m →Configuration: services.avahi.nssmdns -> services.avahi.nssmdns4 |
||
(38 intermediate revisions by 17 users not shown) | |||
Line 1: | Line 1: | ||
Printing in NixOS is done via the <code>services.printing</code> module, to configure the local printing services which is provided by the software [https://openprinting.github.io/projects/00-cups CUPS]. Setting up physical printer devices is done using <code>hardware.printers</code> option. | |||
< | == Installation == | ||
To enable the local print service on your machine, simply add following lines to your configuration | |||
<syntaxhighlight lang="nix"> | |||
services.printing.enable = true; | |||
</syntaxhighlight> | |||
== Configuration == | |||
=== Enable autodiscovery of network printers === | |||
Most printers manufactured after 2013 support the [https://www.pwg.org/ipp/everywhere.html IPP Everywhere] protocol, i.e. printing without installing drivers. This is notably the case of all WiFi printers marketed as Apple-compatible ([https://support.apple.com/en-ca/HT201311 list]). | |||
To detect these printers, add the following to your system configuration: | |||
<syntaxhighlight lang="nix"> | |||
services.avahi = { | |||
enable = true; | |||
nssmdns4 = true; | |||
openFirewall = true; | |||
}; | |||
</syntaxhighlight> | |||
Discovery is done via the opened UDP port <code>5353</code>. Printers should get automatically detected and visible in your printer configuration client. | |||
=== Adding printers === | |||
Beside manually adding printers with client tools, it is possible to permanently add printers to your system configuration (but be aware of [https://github.com/NixOS/nixpkgs/issues/78535 this bug] that sometimes expect the printer to be plugged in your system). The following example configures a network printer called <code>Dell_1250c</code> to your local system, reachable via IPP at <code>http://192.168.178.2:631/printers/Dell_1250c</code> | |||
<syntaxhighlight lang="nix"> | |||
hardware.printers = { | |||
ensurePrinters = [ | |||
{ | |||
name = "Dell_1250c"; | |||
location = "Home"; | |||
deviceUri = "http://192.168.178.2:631/printers/Dell_1250c"; | |||
model = "drv:///sample.drv/generic.ppd"; | |||
ppdOptions = { | |||
PageSize = "A4"; | |||
}; | |||
} | |||
]; | |||
ensureDefaultPrinter = "Dell_1250c"; | |||
}; | |||
</syntaxhighlight> | |||
To add a local printer, connected via USB, change the <code>deviceUri</code> to a USB address and optionally define which driver to use by adding the <code>model</code> option. | |||
<syntaxhighlight lang="nix"> | |||
hardware.printers = { | |||
ensurePrinters = [ | |||
{ | |||
name = "Dell_1250c"; | |||
location = "Home"; | |||
deviceUri = "usb://Dell/1250c%20Color%20Printer?serial=YNP023240"; | |||
model = "Dell-1250c.ppd.gz"; | |||
ppdOptions = { | |||
PageSize = "A4"; | |||
}; | |||
} | |||
]; | |||
}; | |||
</syntaxhighlight> | |||
Some local or network printers might need additional drivers. You can add them using the <code>drivers</code> option | |||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
services.printing.drivers = [ YOUR_DRIVER ]; | |||
</syntaxhighlight> | </syntaxhighlight> | ||
where <code>YOUR_DRIVER</code> is the driver package appropriate for your printer. Commonly used driver packages include: | where <code>YOUR_DRIVER</code> is the driver package appropriate for your printer. Commonly used driver packages include: | ||
Line 16: | Line 76: | ||
* <tt>pkgs.gutenprintBin</tt> — Additional, binary-only drivers for some printers. | * <tt>pkgs.gutenprintBin</tt> — Additional, binary-only drivers for some printers. | ||
* <tt>pkgs.hplip</tt> — Drivers for HP printers. | * <tt>pkgs.hplip</tt> — Drivers for HP printers. | ||
* <tt>pkgs.hplipWithPlugin</tt> — Drivers for HP printers, with the proprietary plugin. Use < | * <tt>pkgs.hplipWithPlugin</tt> — Drivers for HP printers, with the proprietary plugin. Use <code>NIXPKGS_ALLOW_UNFREE=1 nix-shell -p hplipWithPlugin --run 'sudo -E hp-setup'</code> to add the printer, regular CUPS UI doesn't seem to work. | ||
* <tt>pkgs.postscript-lexmark</tt> — Postscript drivers for Lexmark | * <tt>pkgs.postscript-lexmark</tt> — Postscript drivers for Lexmark | ||
* <tt>pkgs.samsung-unified-linux-driver</tt> — Proprietary Samsung Drivers | * <tt>pkgs.samsung-unified-linux-driver</tt> — Proprietary Samsung Drivers | ||
Line 23: | Line 83: | ||
* <tt>pkgs.brgenml1lpr</tt> and <tt>pkgs.brgenml1cupswrapper</tt> — Generic drivers for more Brother printers [https://support.brother.com/g/s/id/linux/en/instruction_prn1a.html] | * <tt>pkgs.brgenml1lpr</tt> and <tt>pkgs.brgenml1cupswrapper</tt> — Generic drivers for more Brother printers [https://support.brother.com/g/s/id/linux/en/instruction_prn1a.html] | ||
* <tt>pkgs.cnijfilter2</tt> — Drivers for some Canon Pixma devices (Proprietary driver) | * <tt>pkgs.cnijfilter2</tt> — Drivers for some Canon Pixma devices (Proprietary driver) | ||
Search for other printer drivers in the NixOS package directory: the official list of packages is [https://search.nixos.org/packages here]. Add the driver to {{nixos:option|services.printing.drivers}}, '''not''' {{nixos:option|environment.systemPackages}}. | |||
< | === Printer sharing === | ||
< | Enable network sharing of the default local printer, also known as "AirPrinting". Note that <code>listenAddresses = [ "*:631" ];</code>, <code>allowFrom = [ "all" ];</code> and <code>openFirewall = true;</code> will enable anonymous access to your printer on all interfaces, you might want to restrict this. | ||
<syntaxhighlight lang="nix"> | |||
services.avahi = { | |||
enable = true; | |||
nssmdns = true; | |||
openFirewall = true; | |||
publish = { | |||
enable = true; | |||
userServices = true; | |||
}; | |||
}; | |||
services.printing = { | |||
listenAddresses = [ "*:631" ]; | |||
allowFrom = [ "all" ]; | |||
browsing = true; | |||
defaultShared = true; | |||
openFirewall = true; | |||
}; | |||
</syntaxhighlight> | |||
Once printer sharing is enabled, it could be additionally advertised in the home network via the Samba protocol, [[Samba#Printer_sharing|see]]. | |||
== Usage == | |||
After enabling the printing service you'll be able to configure and add network printers via http://localhost:631. You may need to authenticate with your local user when you add the printer. | |||
Depending on your desktop environment, there are several graphical tools available which will connect to this backend service and allow you a more convenient printer management, for example <code>system-config-printer</code>. | |||
=== Command line === | |||
List printers | |||
<syntaxhighlight lang="bash"> | |||
# lpstat -p | |||
</syntaxhighlight> | |||
Print test page for printer called <code>HP-LaserJet-1020</code> | |||
<syntaxhighlight lang="bash"> | |||
# lp -o job-sheets=standard,none -d HP-LaserJet-1020 /dev/null | |||
</syntaxhighlight> | |||
List jobs | |||
<syntaxhighlight lang="bash"> | |||
# lpstat | |||
</syntaxhighlight> | |||
Cancel job | |||
<syntaxhighlight lang="bash"> | |||
# cancel 1 | |||
</syntaxhighlight> | |||
== Tips and tricks == | |||
==== Manually supplying printer driver ==== | |||
===== | ===== Provide the PPD imperatively ===== | ||
If no driver is found for your printer, even when <code>services.printing.drivers</code> is correctly populated (see above), | If no driver is found for your printer, even when <code>services.printing.drivers</code> is correctly populated (see above), | ||
you can try to give cups a PPD file. | you can try to give cups a PPD file. | ||
* Download the required PPD file, for example from [https://openprinting.org/printers openprinting.org] | * Download the required PPD file, for example from [https://openprinting.org/printers openprinting.org] | ||
* Open the PPD as a text file, and check that it does not mention FHS paths like <code>/usr/bin</code>. If it does, this method is unlikely to work, as the PPD file depends on executables not present on your system. | * Open the PPD as a text file, and check that it does not mention FHS paths like <code>/usr/bin</code>. If it does, this method is unlikely to work, as the PPD file depends on executables not present on your system. You can certainly install the binaries yourself and point to the new binary, but it is certainly easier to patch the executables in a derivation (see below) to avoid garbage collection of your binaries. | ||
* add the printer with <code>system-config-printer</code> (for example) and at the 'choose driver' screen choose 'provide PPD file' | * add the printer with <code>system-config-printer</code> (for example) and at the 'choose driver' screen choose 'provide PPD file' | ||
===== | ===== Provide the PPD declaratively ===== | ||
You can also declaratively add the PPD as a new driver by creating a simple derivation. You just need to create a derivation that puts the PPD file in <code>$out/share/cups/model/yourfile.ppd</code> (you can also put it in a subfolder like <code>$out/share/cups/model/HP/yourfile.ppd</code> to limit conflicts between ppd having the same name). Note that the name of the file does not change the way cups will list it as the model/manufacturer is written inside the (text) ppd. | |||
As in the imperative method, first check that your file does not contain any reference to binaries outside the store like <code>/bin/</code> or <code>/usr/</code>. If it does not contain any reference then you should be able to simply do this: | |||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
{ | { | ||
... | ... | ||
services.printing.enable = true; | |||
services.printing.drivers = [ | |||
services. | (writeTextDir "share/cups/model/yourppd.ppd" (builtins.readFile ./yourppd.ppd)) | ||
]; | |||
services.printing. | |||
... | ... | ||
} | } | ||
</syntaxhighlight | </syntaxhighlight> | ||
If your ppd contains links to external binaries, you can instead patch the file using for instance <code>substituteInPlace</code>. For that, create a file, say, <code>myPrinter.nix</code> containing something like: | |||
<syntaxhighlight lang="nix"> | |||
{ stdenv }: | |||
stdenv.mkDerivation rec { | |||
name = "myprinter-${version}"; | |||
version = "1.0"; | |||
src = ./.; | |||
= | installPhase = '' | ||
mkdir -p $out/share/cups/model/ | |||
If you | cp myprinter.ppd $out/share/cups/model/ | ||
# If you need to patch the path to files outside the nix store, you can do it this way | |||
# (if the ppd also comes with executables you may need to also patch the executables) | |||
substituteInPlace $out/share/cups/model/myprinter.ppd \ | |||
--replace "/usr/yourProgram/" "${yourProgram}/bin/yourProgram" | |||
''; | |||
} | |||
</syntaxhighlight> | |||
Of course update the name of the files and adapt the substituteInPlace command to your needs. Then add your driver as: | |||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
{ | { | ||
... | ... | ||
services.printing.enable = true; | services.printing.enable = true; | ||
services. | services.printing.drivers = [ | ||
(pkgs.callPackage ./myPrinter.nix {}) | |||
]; | |||
... | ... | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Your PPD file should now appear next to the other PPD files installed on your system when you add a new printer. | |||
For debugging purpose, it may be interesting to note that the data folder used by cups (containing the drivers and more) can be obtained by looking in the environment <code>$CUPS_DATADIR</code> (the contents of <code>$out/share/cups/</code> contained in your drivers are linked in this folder). | |||
==Troubleshooting== | == Troubleshooting == | ||
===Upgrade | === Upgrade required === | ||
Described in: [https://github.com/NixOS/nixpkgs/issues/23993 Github issue 23993]<br /> | Described in: [https://github.com/NixOS/nixpkgs/issues/23993 Github issue 23993]<br /> | ||
'''Problem'''<br /> | '''Problem'''<br /> | ||
Line 166: | Line 256: | ||
'''Solution'''<br /> | '''Solution'''<br /> | ||
Go into the <code>gnome-control-center printers</code> settings, remove the printer and recreate it. | Go into the <code>gnome-control-center printers</code> settings, remove the printer and recreate it. | ||
=== Debugging a broken printer driver === | |||
Add to <code>/etc/nixos/configuration.nix</code> | |||
<syntaxhighlight lang="nix"> | |||
services.printing.logLevel = "debug"; | |||
</syntaxhighlight> | |||
Rebuild | |||
<pre> | |||
sudo nixos-rebuild switch | |||
</pre> | |||
Watch the cups logs | |||
<syntaxhighlight lang=console> | |||
$ journalctl --follow --unit=cups | |||
</syntaxhighlight> | |||
or | |||
<syntaxhighlight lang=console> | |||
$ journalctl --follow --unit=cups | grep -C10 --color=always -i -e 'No such file or directory' -e 'error:' | |||
</syntaxhighlight> | |||
Start a print job | |||
Now watch the cups logs for errors like <code>No such file or directory</code> | |||
[[Category:Hardware]] |