Printing: Difference between revisions

imported>Onny
Further cleanup
Improve formatting, add more syntax highlighting, add more links (to packages/options)
 
(32 intermediate revisions by 19 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.
Printing in NixOS is done via the {{nixos:option|services.printing}} 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 {{nixos:option|hardware.printers}} option.


== Installation ==
== Installation ==
Line 9: Line 9:
</syntaxhighlight>
</syntaxhighlight>


== Usage ==
== Configuration ==
 
=== Enable auto-discovery 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 AirPrint-compatible ([https://support.apple.com/en-ca/HT201311 list]).


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.
To detect these printers, add the following to your system configuration:
<syntaxhighlight lang="nix">
services.avahi = {
  enable = true;
  nssmdns4 = true;
  openFirewall = true;
};


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>.
services.printing = {
  enable = true;
  drivers = with pkgs; [
    cups-filters
    cups-browsed
  ];
};
</syntaxhighlight>


== Configuration ==
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 ===
=== Adding printers ===


Beside manually adding printers with client tools, it is possible to permanently add printers to your system configuration:
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><nowiki>http://192.168.178.2:631/printers/Dell_1250c</nowiki></code>


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
services.printing.enable = true;
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>
 
A similar network based, driverless approach using the very widely supported [https://www.pwg.org/ipp/everywhere.html IPP Everywhere] protocol (thanks to [https://discourse.nixos.org/t/brother-dcp-572dw-wrapper/8113/3 this] Discourse post), would look something like:
 
<syntaxhighlight lang="nix">
hardware.printers = {
  ensureDefaultPrinter = "Brother_HL-L2340D";
  ensurePrinters = [
    {
      deviceUri = "ipp://192.168.1.20/ipp";
      location = "home";
      name = "Brother_HL-L2340D";
      model = "everywhere";
    }
  ];
};
</syntaxhighlight>
 
You can run <code>lpinfo -m</code> to ensure you have the <code>everywhere</code> driver currently available.
 
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>
 
To add a printer over the smb protocol, [[Samba]] needs to be enabled:
<syntaxhighlight lang="nix">
hardware.printers.ensurePrinters = [
  {
    # (other stuff...)
    deviceUri = "smb://print-server.com/printername";
  }
];
 
services.samba.enable = true;
</syntaxhighlight>
</syntaxhighlight>


Some local or network printers might need additional drivers. You can add them using the <code>drivers</code> option
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">
Line 36: Line 112:
* <tt>pkgs.gutenprintBin</tt> &mdash; Additional, binary-only drivers for some printers.
* <tt>pkgs.gutenprintBin</tt> &mdash; Additional, binary-only drivers for some printers.
* <tt>pkgs.hplip</tt> &mdash; Drivers for HP printers.
* <tt>pkgs.hplip</tt> &mdash; Drivers for HP printers.
* <tt>pkgs.hplipWithPlugin</tt> &mdash; 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.hplipWithPlugin</tt> &mdash; Drivers for HP printers, with the proprietary plugin, see also [[Printing#Setting up HP printers with proprietary drivers|Setting up HP printers with proprietary drivers]].
* <tt>pkgs.postscript-lexmark</tt> &mdash; Postscript drivers for Lexmark
* <tt>pkgs.postscript-lexmark</tt> &mdash; Postscript drivers for Lexmark
* <tt>pkgs.samsung-unified-linux-driver</tt> &mdash; Proprietary Samsung Drivers
* <tt>pkgs.samsung-unified-linux-driver</tt> &mdash; Proprietary Samsung Drivers
* <tt>pkgs.splix</tt> &mdash; Drivers for printers supporting SPL (Samsung Printer Language).
* <tt>pkgs.splix</tt> &mdash; Drivers for printers supporting SPL (Samsung Printer Language).
* <tt>pkgs.brlaser</tt> &mdash; Drivers for some Brother printers
* <tt>pkgs.brlaser</tt> &mdash; Drivers for some Brother printers
* <tt>pkgs.brgenml1lpr</tt> and <tt>pkgs.brgenml1cupswrapper</tt> &mdash; 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> &mdash; Generic drivers for more Brother printers (Proprietary drivers) [https://support.brother.com/g/s/id/linux/en/instruction_prn1a.html]
* <tt>pkgs.cnijfilter2</tt> &mdash; Drivers for some Canon Pixma devices (Proprietary driver)
* <tt>pkgs.cnijfilter2</tt> &mdash; Drivers for some Canon Pixma devices (Proprietary driver)
* <tt>pkgs.epson-escpr2</tt> &mdash; Drivers for newer Epson devices.
* <tt>pkgs.epson-escpr</tt> &mdash; Drivers for some other Epson devices.


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}}.
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}}.


=== 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 get the specific string for <code>model</code>, run <code>lpinfo -m</code> which will produce output similar to
 
<pre>
...
samsung/SCX-3200.ppd Samsung SCX-3200 Series
samsung/SCX-3400.ppd Samsung SCX-3400 Series
samsung/SCX-4100.ppd Samsung SCX-4100 Series
samsung/SCX-4200.ppd Samsung SCX-4200 Series
samsung/SCX-4300.ppd Samsung SCX-4300 Series
samsung/SCX-4500.ppd Samsung SCX-4500 Series
samsung/SCX-4500W.ppd Samsung SCX-4500W Series
samsung/SCX-4600.ppd Samsung SCX-4600 Series
samsung/SCX-4623.ppd Samsung SCX-4623 Series
...
</pre>
 
The <code>model</code> string is the first column. For example, for the Samsung SCX-4300 series, set <syntaxhighlight inline lang="nix">model = "samsung/SCX-4300.ppd";</syntaxhighlight>.
 
=== Printer sharing ===
 
Enable network sharing of the default local printer, also known as "AirPrinting". Note that <syntaxhighlight inline lang="nix">listenAddresses = [ "*:631" ];</syntaxhighlight>, <syntaxhighlight inline lang="nix">allowFrom = [ "all" ];</syntaxhighlight> and <syntaxhighlight inline lang="nix">openFirewall = true;</syntaxhighlight> will enable anonymous access to your printer on all interfaces, you might want to restrict this.


To detect these printers, add the following to your system configuration:
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
services.avahi = {
services.avahi = {
Line 56: Line 152:
   nssmdns = true;
   nssmdns = true;
   openFirewall = 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, see [[Samba#Printer_sharing]].
 
== 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 {{nixos:package|system-config-printer}}.
 
=== 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>
</syntaxhighlight>


Discovery is done via the opened UDP port <code>5353</code>. Printers should get automatically detected and visible in your printer configuration client.
== Tips and tricks ==
 
==== Manually supplying printer driver  ====


==== With a raw PPD ====
===== Provide the PPD imperatively =====
====== Provide the PPD imperatively ======
If no driver is found for your printer, even when {{nixos:option|services.printing.drivers}} is correctly populated (see above), you can try to give cups a PPD file.  
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.  
* 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. 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.
* 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 ======
===== 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.
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.
Line 120: Line 261:
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).
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).


==Setting up shared printers==
== Troubleshooting ==


===Server===
=== Upgrade required ===
 
Described in: [https://github.com/NixOS/nixpkgs/issues/23993 Github issue 23993]
<ol>
<li>If you want to share a local printer on the network, follow the steps in [[#basic-configuration|Basic Configuration]], but check &#8220;Share This Printer&#8221; when adding it to CUPS. If you have already added the printer to CUPS, reconfigure it to make it a shared printer.</li>
<li>You should probably check that printing works locally at this point.</li>
<li>Amend <tt>/etc/nixos/configuration.nix</tt>:
<syntaxhighlight lang="nix">
{
  ...
 
  # Enable automatic discovery of the printer from other Linux systems with avahi running.
  services.avahi.enable = true;
  services.avahi.publish.enable = true;
  services.avahi.publish.userServices = true;
  services.printing.browsing = true;
  services.printing.listenAddresses = [ "*:631" ]; # Not 100% sure this is needed and you might want to restrict to the local network
  services.printing.allowFrom = [ "all" ]; # this gives access to anyone on the interface you might want to limit it see the official documentation
  services.printing.defaultShared = true; # If you want
 
  networking.firewall.allowedUDPPorts = [ 631 ];
  networking.firewall.allowedTCPPorts = [ 631 ];
 
  ...
}
</syntaxhighlight></li>
<li>Rebuild: <syntaxhighlight lang="console">$ sudo nixos-rebuild switch</syntaxhighlight></li></ol>
 
Note: I ''think'' I had to check "Share printers connected to this system" and "Allow printing from the internet" at http://192.168.11.9:631/admin but I'm not sure.
 
{{outdated|Needs checking to rectify uncertainty in instructions}}
 
Once printer sharing is enabled, it could be additionally advertised in the home network via the Samba protocol, [[Samba#Printer_sharing|see]].
 
===See also===
 
* [https://github.com/NixOS/nixpkgs/issues/13901 How to properly setup a shared (home) printer? #13901]
* [https://wiki.archlinux.org/index.php/CUPS/Printer_sharing Printer sharing (Arch Linux wiki)]
* [https://github.com/NixOS/nixpkgs/issues/23993 Little Printing/CUPS Documentation for Configuration as a Print Server #23993]
* [https://web.archive.org/web/20160829175522/https://nixos.org/wiki/Printers Old wiki page]
 
[[Category:Configuration]][[Category:Hardware]]
 
==Troubleshooting==
 
=== Adding network printer "Name or service not known" ===


If CUPS complains about "''Impossible to connect to XXX.local: Name or service not known''" even if {{nixos:option|services.avahi.nssmdns}} is enabled as shown above, the reason could be that mdns does not work properly with IPv6 in your network. In such a case, switching to mdns4-only setup can help:
<syntaxhighlight lang="nix">
{
  ...
  services.avahi.nssmdns = false; # Use the settings from below
  # settings from avahi-daemon.nix where mdns is replaced with mdns4
  system.nssModules = pkgs.lib.optional (!config.services.avahi.nssmdns) pkgs.nssmdns;
  system.nssDatabases.hosts = with pkgs.lib; optionals (!config.services.avahi.nssmdns) (mkMerge [
    (mkBefore [ "mdns4_minimal [NOTFOUND=return]" ]) # before resolve
    (mkAfter [ "mdns4" ]) # after dns
  ]);
}
</syntaxhighlight>
See [https://github.com/NixOS/nixpkgs/issues/118628 this bug report] for details.
=== Upgrade required ===
Described in: [https://github.com/NixOS/nixpkgs/issues/23993 Github issue 23993]<br />
'''Problem'''<br />
'''Problem'''<br />
Using the cups web interface, the page tells you "Upgrade Required" and then redirects you to a page that fails to load.<br />
Using the cups web interface, the page tells you "Upgrade Required" and then redirects you to a page that fails to load.<br />
Line 193: Line 274:


'''Solution'''<br />
'''Solution'''<br />
Either we can help cups to get ssl keys, or we can tell it to not use https at all.<br />
Either we can help cups to get ssl keys, or we can tell it to not use https at all.
 
''Generating ssl keys:''<br />
''Generating ssl keys:''<br />
First make sure the directory /etc/cups/ssl exists:<br />
First make sure the directory <code>/etc/cups/ssl</code> exists:
<code>sudo mkdir -p /etc/cups/ssl</code><br />
 
Try restarting cups and using the web interface again. This might be enough to get it working.<br />
<syntaxhighlight lang="bash">
If this didn't help, then check if cups has generated ssl keys in /etc/cups/ssl<br />
sudo mkdir -p /etc/cups/ssl
</syntaxhighlight>
 
Try restarting cups and using the web interface again. This might be enough to get it working.
If this didn't help, then check if cups has generated ssl keys in <code>/etc/cups/ssl</code>.
 
''Disabling ssl:''<br />
''Disabling ssl:''<br />
Edit your <code>/etc/nixos/configuration.nix</code> and add the following lines:<br />
Edit your <code>/etc/nixos/configuration.nix</code> and add the following lines:<br />
<code><pre>services.printing.extraConf = ''
 
    DefaultEncryption Never
<syntaxhighlight lang="nix">
  '';</pre></code>
services.printing.extraConf = ''
  DefaultEncryption Never
'';
</syntaxhighlight>


===Unable to launch Ghostscript: gs: No such file or directory===
===Unable to launch Ghostscript: gs: No such file or directory===
Described in: [https://github.com/NixOS/nixpkgs/issues/20806 Github issue 20806]
Described in: [https://github.com/NixOS/nixpkgs/issues/20806 Github issue 20806]
and [https://github.com/NixOS/nixpkgs/issues/22062 issues 22062]<br />
and [https://github.com/NixOS/nixpkgs/issues/22062 issues 22062]<br />
'''Problem'''<br />
'''Problem'''<br />
When printing, cups will report an error: Unable to launch Ghostscript: gs: No such file or directory<br />
When printing, cups will report an error: <code>Unable to launch Ghostscript: gs: No such file or directory</code><br />


'''Cause'''<br />
'''Cause'''<br />
Some drivers use the ghostscript binary.<br />
Some drivers use the ghostscript binary.<br />
Cups will look for the binary path in it's config file: cupsd.conf<br />
Cups will look for the binary path in it's config file: <code>cupsd.conf</code><br />
This file is normally a link. But it can be overwritten, and consequentially become outdated.<br />
This file is normally a link. But it can be overwritten, and consequentially become outdated.<br />


'''Solution'''<br />
'''Solution'''<br />
You could try to manually fix the path variable in /var/lib/cups/cupsd.conf<br />
You could try to manually fix the path variable in <code>/var/lib/cups/cupsd.conf</code><br />
Alternatively you could try to delete the file and run <code>sudo nixos-rebuild switch</code>
Alternatively you could try to delete the file and run <code>sudo nixos-rebuild switch</code>


Line 225: Line 316:


'''Problem'''<br />
'''Problem'''<br />
But, later you may experience an error like '''"/nix/store/.../lib/cups/filter/pstospl not available: No such file or directory"'''.  
But, later you may experience an error like <code>/nix/store/.../lib/cups/filter/pstospl not available: No such file or directory</code>.  


'''Cause'''<br />
'''Cause'''<br />
Line 235: Line 326:
=== Debugging a broken printer driver ===
=== Debugging a broken printer driver ===


Add to <code>/etc/nixos/configuration.nix</code>
Add to <code>/etc/nixos/configuration.nix</code>:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
Line 243: Line 334:
Rebuild
Rebuild


<pre>
<syntaxhighlight lang="bash">
sudo nixos-rebuild switch
sudo nixos-rebuild switch
</pre>
</syntaxhighlight>


Watch the cups logs
Watch the cups logs


<syntaxhighlight lang=console>
<syntaxhighlight lang="bash">
$ journalctl --follow --unit=cups
journalctl --follow --unit=cups
</syntaxhighlight>
</syntaxhighlight>
or
or
<syntaxhighlight lang=console>
<syntaxhighlight lang="bash">
$ journalctl --follow --unit=cups | grep -C10 --color=always -i -e 'No such file or directory' -e 'error:'
journalctl --follow --unit=cups | grep -C10 --color=always -i -e 'No such file or directory' -e 'error:'
</syntaxhighlight>
</syntaxhighlight>


Line 260: Line 351:


Now watch the cups logs for errors like <code>No such file or directory</code>
Now watch the cups logs for errors like <code>No such file or directory</code>
=== Setting up Panasonic printers ===
See [https://prince213.top/blog/2025/01/16/nixos-mccgdi/ this blog post].
=== Setting up HP printers with proprietary drivers ===
'''Problem'''<br />
Regular CUPS UI may not be able to add HP printers with proprietary drivers.
'''Solution'''<br />
Use <syntaxhighlight inline lang="bash">NIXPKGS_ALLOW_UNFREE=1 nix-shell -p hplipWithPlugin --run 'sudo -E hp-setup'</syntaxhighlight> to add the printer.
[[Category:Hardware]]