This will be a projectbluefin/fsdk-container designed to bring this to all Linuxes. It will be deployed by a quadlet.
- Bluefin will ship this first
- Many of the things in these containers are old school, modernize and bring it to fsdk specs, distroless. Slim and mean.
This repository contains a Printer Application for printers supported by Ghostscript's built-in printer drivers and some extra filters.
It uses PAPPL to support IPP printing from multiple operating systems. In addition, it uses the resources of cups-filters 2.x (filter functions in libcupsfilters, libppd) and pappl-retrofit (encapsulating classic CUPS drivers in Printer Applications). This work (or now the code of pappl-retrofit) is derived from the hp-printer-app.
For printer capability and driver usage information the Foomatic database of OpenPrinting (Online access by printer, by driver, Downlod) is used.
For the Bluefin OCI appliance, report issues and propose changes to the testing branch of the Bluefin fork. For upstream application and Snap changes, use OpenPrinting.
-
Ghostscript built-in:
ap3250, appledmp, bj10e, bj10vh, bj10v, bj10, bj200, bj8XXYYZ.upp, bjc250gs, bjc600, bjc800, bjc880j, cdj500, cdj550, cdnj500, chp2200, cljet5, cp50, declj250, deskjet, dj505j, djet500, dnj650c, eplaser-jp, eplaser, eps9high, eps9mid, epsonc, epson, escpage, fmlbp, fmpr, gdi, hl1250, hl7x0, ibmpro, imagen, iwhi, jetp3852, jj100, la50, la70, la75plus, la75, laserjet, lbp310, lbp320, lbp8, lex5700, lex7000, lips2p, lips3, lips4v, lips4, lj250, lj4dithp, lj4dith, lj5gray, ljet2p, ljet3d, ljet3, ljet4d, ljet4, ljetplus, ln03, lp2000, lp2563, lp8000, lq850, lxm3200-tweaked, lxm5700m, m8510, md1xMono, md2k, md50Eco, md50Mono, md5k, mj700v2c, ml600, necp2xX.upp, necp6, npdl, oce9050, oki182, oki4w, okiibm, paintjet, pcl3, picty180, pjetxl, pjxl300, pjxl, pj, ps2write, pr150, pr201, pxlcolor, pxldpl, pxlmono, r4081, rpdl, sharp.upp, sipixa6.upp, sj48, stcolor, t4693dX, tek4696, xesThis gives support for many old and ancient printers, but also for PCL lasers (especially PCL 6/XL) and dot-matrix printers.
The included Ghostscript can have more drivers but these are the ones for which we have PPD support from Foomatic and which are not considered deprecated by another driver.
-
hpijsof HPLIP: For non-HP PCL printers (use the HPLIP Printer Application for HP printers). Better print quality than with Ghostscript's built-in drivers. -
pnm2ppa: Driver for some older HP printers with proprietary protocol, probably the only HP printers NOT supported by HPLIP. even not with HP's proprietary plugin. Its configuration file is user-editable in persistent application state, see below. -
pxljr: For HP Color LaserJet 3500/3550/3600, should give better output quality than HPLIP. -
foo2zjs: Driver for laser printers with proprietary languages, from Dell, Epson, Fuji, HP, Kyocera, Lexmark, (Konica) Minolta, Oki, Olivetti, Ricoh, Samsung, Xerox. Note that the firmware loading facility for HP is not included in this Printer Application, use the HPLIP Printer Application (download proprietary plugin in-app, via web interface) for these printers, the firmware is proprietary anyway. Users can add color profiles in persistent application state, see below. -
SpliX: Driver for laser printers with proprietary languages, from Dell, Lexmark, Samsung, Toshiba, Xerox -
brlaser: Driver for Brother HL, DCP, and MFC laser printers which do not understand PostScript nor PCL. -
fxlinuxprint: Driver from Fuji Xerox for their PDF printers before the times of driverless IPP. -
c2esp: Driver for Kodak EasyShare printers. -
rastertosag-gdi: For the few Ricoh models which do not do PostScript or PCL: Ricoh Aficio SP 1000S/1100S -
dymo: Driver for Dymo's label printers -
ptouch: Driver for Brother's P-Touch label printers -
c2050,cjet,min12xxw,m2300w: Drivers for older Lexmark, Canon, and Minolta printers. Users can addm2300wcolor profiles in persistent application state, see below. -
CUPS,cups-filters: Included drivers for PCL, dot-matrix (Oki, Epson), label printers (Dymo, Intellitech, Zebra), and some older HP DesignJet large-format printers. -
Manufacturer-supplied PPD files: For PCL and PDF printers from Ricoh and OEM (Gestetner, InfoPrint, Infotec, Lanier, NRG, Ricoh, Savin) and from Samsung.
-
PostScript: For manufacturer-supplied PostScript support, use the PostScript Printer Application.
-
HPLIP: For practically all HP printers use the HPLIP Printer Application. It also supports HP's proprietary plugin for printers which need to load their firmware on startup or need a proprietary driver extension.
-
Gutenprint: High-quality output with inkjets from Epson, Canon, and others, also PCL laser printers. A lot of adjustable parameters. Use the Gutenprint Printer Application.
-
epson-inkjet-printer-escpr: Epson's free-software printer driver for ESC/P-R-based inkjet printers. It supports only 360 dpi resolution and a very awkward user interface which cannot get easily mapped to IPP. Therefore it is not included in this Printer Application. Use the Gutenprint Printer Application. -
Braille embosser drivers: We plan a separate Printer Application for that.
-
Scanners in multi-function devices: We plan a SANE retro-fit Scanner Application.
-
A Printer Application providing Ghostscript-based printer drivers. Input data is converted to PDF or PostScript (if not already supplied in one of these formats) as these are the input data formats of Ghostscript, fed into Ghostscript and by Ghostscript converted into the printer's native language. In some cases Ghostscript produces generic raster output which is converted to the printer's language by an additional filter.
-
PWG Raster, Apple Raster or image input data is converted to PostScript and not to PDF as PostScript is streamable, and this way large jobs need less resources or one can theoretically even print infinite jobs.
-
This Printer Application also includes some separate, old and now unmaintained printer drivers which are too small projects for their own Printer Application. These can also consist of a CUPS Raster filter, not needing Ghostscript if the input is PWG Raster, Apple Raster, or an image.
-
Note that most of the drivers (both inside Ghostscript and separate filters) are old, unmaintained code, for old printers which we do not have access to for testing. The packaging in the Snap (and also in Debian where the Snap uses a Debian source) is minimum-invasive to assure formerly working code stays working, but it is not assured due to changes in GCC and the libraries or due to the Snap environment.
-
This Printer Application supports thousands of (usually older) printer models. The needed printer capability information and driver usage information is mainly taken from OpenPrinting's Foomatic database, but also from information which comes with individual drivers.
-
From the Foomatic data CUPS PPD files are pre-built, compressed and packaged with the Snap. Also the foomatic-rip filter of cups-filters, Ghostscript, and the extra printer driver filters are included. With this a CUPS driver retro-fit using the pappl-retrofit library is done. This way we do not need to modify or adapt the now mostly unmaintained printer driver code, nor the Foomatic data or the PPD files. This is important as we do not have the printers for testing.
-
We use the printer's IEEE-1284 device ID to identify manufacturer and model of the printer and look for explicit driver support for this model. If we do not find it, we check the CMD: field of the ID to see whetrher the printer supports any common data format, currently PostScript, PCL-6/XL, PCL 5c, and PCL 5e to select a generic driver.
-
Available printer devices are discovered (and used) with CUPS' backends and not with PAPPL's own backends. This way quirk workarounds for USB printers with compatibility problems are used (and are editable) and any driver's output can get sent to the printer via IPP, IPPS (encrypted!), and LPD in addition to socket (usually port 9100). The SNMP backend can get configured (community, address scope).
-
If you have an unusual system configuration or a personal firewall your printer will perhaps not get discovered. In this situation the fully manual "Network Printer" entry in combination with the hostname/IP field can be helpful.
-
Standard job IPP attributes are mapped to the driver's option settings best fitting to them so that users can print from any type of client (like for example a phone or IoT device) which only supports standard IPP attributes and cannot retrive the PPD options. Trays, media sizes, media types, and duplex can get mapped easily, but when it comes to color and quality it gets more complex, as relevant options differ a lot in the PPD files. Here we use an algorithm which automatically (who wants hand-edit ~10000 PPD files for the assignments) finds the right set of option settings for each combination of
print-color-mode(color/monochrome),print-quality(draft/normal/high), andprint-content-optimize(auto/photo/graphics/text/text-and-graphics) in the PPD of the current printer. So you have easy access to the full quality or speed of your printer without needing to deal with printer-specific option settings (the original options are still accessible via web admin interface).
-
Human-readable strings for vendor options (Needs support by PAPPL: Issue #58: Localization support)
-
Internationalization/Localization (Needs support by PAPPL: Issue #58: Localization support)
-
SNMP Ink level check via ps_status() function (Needs support by PAPPL: Issue #83: CUPS does IPP and SNMP ink level polls via backends, PAPPL should have functions for this)
-
Build options for cups-filters, to build without libqpdf and/or without libppd, the former will allow to create the Snap of this Printer Application without downloading and building QPDF
To just run and use this Printer Application, simply install it from the Snap Store:
sudo snap install --edge ghostscript-printer-app
Then follow the instructions below for setting it up.
To build the Snap by yourself, in the main directory of this repository run
snapcraft snap
This will download all needed packages and build the Ghostscript Printer Application. Note that PAPPL (upcoming 1.0) and cups-filters (upcoming 2.0) are pulled directly from their GIT repositories, as there are no appropriate releases yet. This can also lead to the fact that this Printer Application will suddenly not build any more.
To install the resulting Snap run
sudo snap install --dangerous ghostscript-printer-app_1.0_amd64.snap
The Printer Application will automatically be started as a server daemon.
Enter the web interface
http://localhost:8000/
Use the web interface to add a printer. Supply a name, select the discovered printer, then select make and model. Also set the installed accessories, loaded media and the option defaults. Accessory configuration and option defaults can also offen get polled from the printer.
Then print PDF, PostScript, JPEG, Apple Raster, or PWG Raster files with
ghostscript-printer-app FILE
or print with CUPS, CUPS (and also cups-browsed) discover and treat the printers set up with this Printer Application as driverless IPP printers (IPP Everywhere and AirPrint).
See
ghostscript-printer-app --help
for more options.
Use the "-o log-level=debug" argument for verbose logging in your terminal window.
You can add files to /var/snap/ghostscript-printer-app/common/usb/
for additional USB quirk rules. Edit the existing files only for quick
tests, as they get replaced at every update of the Snap (to introduce
new rules).
You can edit the
/var/snap/ghostscript-printer-app/common/cups/snmp.conf file for
configuring SNMP network printer discovery.
For the pnm2ppa driver you can edit the configuration file:
/var/snap/ghostscript-printer-app/common/pnm2ppa/pnm2ppa.conf
For the foo2zjs and m2300w drivers you can add color profiles in
the appropriate subdirectories of
/var/snap/ghostscript-printer-app/common/foo2zjs/
/var/snap/ghostscript-printer-app/common/m2300w/
Automatic firmware loading by foo2zjs is not supported. If you have one of these HP printers which need it, use the HPLIP Printer Application and download HP's plugin (use the web interface of the HPLIP Printer Application for that).
All the changes mentioned her take effect with the next print job.
If you mess up any configuration file under
/var/snap/ghostscript-printer-app/common/, simply delete it (or move
it away) and restart the Snap to get it restored.
The OCI appliance is published only to the GitHub Container Registry. Each
published commit on testing gets an immutable sha-<commit> tag and moves
stable and the application-version tag <VERSION> (plus <VERSION>-x86_64
and <VERSION>-aarch64) to its signed index; there is no
latest or edge OCI tag.
Install Podman with a working rootless user namespace, then run stable, or
pin a sha-<commit> tag or digest instead:
image="ghcr.io/projectbluefin/ghostscript-printer-app:stable"
podman pull "$image"
podman volume create ghostscript-printer-app
podman run -d \
--name ghostscript-printer-app \
--network host \
-e PORT=8000 \
-v ghostscript-printer-app:/var/lib/ghostscript-printer-app:Z,U \
"$image"Open http://localhost:8000/ and use the web interface to add a printer.
PORT is optional; without it, the application selects port 8000 or the next
available port. Host networking is required for local-network printer discovery.
The named volume preserves Printer Application state and user-edited driver
configuration across upgrades. Startup uses umask 077 and restricts the CUPS,
TLS-key, and spool directories to the runtime user (0700). Existing TLS and
spool contents lose group/other access on every startup; a volume whose private
state cannot be secured by UID/GID 65532:65532 fails startup. Keep bind-mounted
state owned by that runtime user (the :U option above sets volume ownership),
and restrict access to its host parent directory.
PAPPL serves IPP and the web interface on the same port, and the appliance runs
on host networking, so by default the web administration pages are reachable by
every client that can reach the printer, without a credential. The entrypoint
prints a NOTICE about this at startup. Close that surface with one of these
environment variables; every value is validated, and a value the appliance
cannot honour stops the container instead of starting it unauthenticated
(exit 64 for a malformed value, 78 for a value this image cannot enforce):
| Variable | Forwarded as | Accepted values |
|---|---|---|
PRINTER_APP_SERVER_OPTIONS |
-o server-options=… |
Comma-separated PAPPL server options from the allow-list: no-web-interface. |
PRINTER_APP_AUTH_SERVICE |
-o auth-service=… |
A PAM service name ([A-Za-z0-9_.-]). Refused with exit 78 while the image's PAPPL is built without PAM (see below). |
PRINTER_APP_ADMIN_GROUP |
-o admin-group=… |
A group from the image's /etc/group; requires PRINTER_APP_AUTH_SERVICE. |
PRINTER_APP_SERVER_OPTIONS=no-web-interface is the supported way to run the
appliance on a LAN-facing surface today: every web page, including the
per-printer configuration and pappl-retrofit's "Device Settings" pages, answers
404, while IPP printing, IPP administration from the container itself, and
DNS-SD advertisement keep working. Manage printers with the command-line client
from inside the container (podman exec ghostscript-printer-app ghostscript-printer-app -u ipp://127.0.0.1:8000/ipp/system … add):
podman run -d \
--name ghostscript-printer-app \
--network host \
-e PORT=8000 \
-e PRINTER_APP_SERVER_OPTIONS=no-web-interface \
-v ghostscript-printer-app:/var/lib/ghostscript-printer-app:Z,U \
"$image"PRINTER_APP_AUTH_SERVICE and PRINTER_APP_ADMIN_GROUP are parsed so the
configuration surface is stable for supervisors such as ChairLift, but the
shared printing base builds PAPPL with --disable-libpam, so every service
name is refused and the container exits 78 with a diagnostic naming
no-web-interface as the alternative. The refusal does not depend on whether
/etc/pam.d/<name> exists in the image (/etc/pam.d/cups ships with CUPS):
forwarding auth-service to a PAM-less PAPPL would not authenticate anyone,
it would answer every administration request, including from localhost, with
401. Authenticated web administration becomes available once the base builds
PAPPL with PAM and ships a service configuration for this appliance.
Setting an unlisted server option such as no-tls or none, a name with
characters outside [A-Za-z0-9_.-], a group PAPPL cannot resolve (it would
otherwise skip the group check and admit every authenticated user), or a group
without an auth service is rejected. tests/entrypoint-validation.sh covers
those rejections on the host; tests/core-appliance.sh verifies the
no-web-interface behaviour against the built image.
For USB printers, add these options to podman run:
--device /dev/bus/usb --group-add keep-groupsThe host user must already have permission to access the printer device. Do not
work around host permissions by running the appliance as root. Before starting,
run python3 scripts/check-rootless-usb.py "$image" /dev/bus/usb/BBB/DDD with the
printer's current node. See the rootless permissions and Quadlet setup
for udev/group configuration, crun requirements, and a service that gates startup
on this check.
The OCI image is built with BuildStream inside the pinned builder container.
Install Podman and just, then run:
just build
just verifyjust build exports and tags the local image as
ghcr.io/projectbluefin/ghostscript-printer-app:build. just verify is the
authoritative appliance gate: it checks the BuildStream graph and patch chain,
starts the real image, exercises every driver slice, verifies lifecycle and
persistence behavior, audits the advertised payload and complete ELF closure,
and enforces the uncompressed size ceiling.
CUPS, cups-filters, libcupsfilters, libppd, Ghostscript, mutool, Avahi, PAPPL
and pappl-retrofit come from the shared printing base of
fsdk-containers
(fsdk-containers.bst:printing/base.bst), junctioned at a pinned commit in
elements/fsdk-containers.bst; FSDK itself comes through that junction. CI
seeds the base from its cosign-verified printing-base-devel bundle, and
Renovate (renovate.json) proposes and automerges junction
bumps to fsdk-containers main once the merge queue's full gate passes.
For real hardware, follow the separate USB and network printer validation procedure. Synthetic CI results are not physical-printer evidence.
For driver and version differences against the current OpenPrinting Snap, see the Snap parity matrix.
Merge-queue CI and the publish workflow restore BuildStream's local cache (cas, artifacts,
source_protos) from the Actions cache. The BuildStream cache refill workflow
rebuilds and saves it per architecture on testing pushes and nightly (saved only when an arch fits in 9000 MB uncompressed; a larger cache skips the save with a warning and the run stays green); reset it with gh cache delete --all.
Open OCI development PRs against testing; Renovate's fsdk-containers bumps land
there too. Pull requests run just validate, and the merge queue runs the full
native amd64 and arm64 build and just verify before a change lands on
testing. Retain main only while existing feature branches or workflows still
reference it.
Every push to testing publishes: registry-actions.yml rebuilds and verifies
native amd64 and arm64 images, then pushes, signs (index and both architecture
manifests), attests and verifies everything by digest, including its SPDX SBOM,
keyless signatures, GitHub provenance, and OCI metadata. The application
version is derived at build time: the junction's Ghostscript release plus the
packaging revision in VERSION (e.g. 10.07.1-4). IJS builds from
that same Ghostscript source, and the FSDK version and ref labels come from the
fsdk-containers junction, so a junction bump needs no other change. Only after
every check passes does it create the immutable sha-<commit> tag and move
<VERSION>, <VERSION>-x86_64, <VERSION>-aarch64 and stable, so a failed
publication leaves no tagged, unsigned image. Publications run one at a time;
pushes that queue behind a running one collapse to the newest, so an
intermediate commit may have no sha-<commit> tag. Roll back by reverting the
offending PR.
You can also do a "quick-and-dirty" build without snapping and without
needing to install PAPPL,
cups-filters 2.x, and
pappl-retrofit into
your system. You need a directory with the latest GIT snapshot of
PAPPL, the latest GIT snapshot of cups-filters, and the latest GIT
snapshot of pappl-retrofit (master branches of each). They all need to
be compiled (./autogen.sh; ./configure; make), installing not
needed. Also install the header files of all needed libraries
(installing "libcups2-dev" should do it).
In the directory with ghostscript-printer-app.c run the command line
gcc -o ghostscript-printer-app ghostscript-printer-app.c $PAPPL_SRC/pappl/libpappl.a $CUPS_FILTERS_SRC/.libs/libppd.a $CUPS_FILTERS_SRC/.libs/libcupsfilters.a $PAPPL_RETROFIT_SRC/.libs/libpappl-retrofit.a -ldl -lpthread -lppd -lcups -lavahi-common -lavahi-client -lgnutls -ljpeg -lpng16 -ltiff -lz -lm -lusb-1.0 -lpam -lqpdf -lstdc++ -I. -I$PAPPL_SRC/pappl -I$CUPS_FILTERS_SRC/ppd -I$CUPS_FILTERS_SRC/cupsfilters -I$PAPPL_RETROFIT_SRC/pappl/retrofit -L$CUPS_FILTERS_SRC/.libs/ -L$PAPPL_RETROFIT_SRC/.libs/
There is also a Makefile, but this needs PAPPL, cups-filters 2.x, and pappl-retrofit to be installed into your system.
Run
./ghostscript-printer-app --help
When running the non-snapped version, by default, PPD files are searched for in
/usr/share/ppd/
/usr/lib/cups/driver/
/var/lib/ghostscript-printer-app/ppd/
You can set the PPD_PATHS environment variable to search other
places instead:
PPD_PATHS=/path/to/my/ppds:/my/second/place ./ghostscript-printer-app server
Simply put a colon-separated list of any amount of paths into the variable. Creating a wrapper script is recommended.
This Printer Application uses CUPS' backends and not PAPPL's, meaning that for USB printers CUPS' USB quirk workarounds for compatibility problems are used, network printers can also be used with IPP, IPPS, and LPD protocols, and SNMP printer discovery is configurable.
USB Quirk rules in /usr/share/cups/usb and the /etc/cups/snmp.conf
file can get edited if needed.
Make sure you have Ghostscript, CUPS (at least its backends), and the desired printer drivers (if not built into Ghostscript) installed.
For access to the test page testpage.ps use the TESTPAGE_DIR
environment variable:
TESTPAGE_DIR=`pwd` PPD_PATHS=/path/to/my/ppds:/my/second/place ./ghostscript-printer-app server
or for your own creation of a test page (PostScript, PDF, PNG, JPEG, Apple Raster, PWG Raster):
TESTPAGE=/path/to/my/testpage/my_testpage.ps PPD_PATHS=/path/to/my/ppds:/my/second/place ./ghostscript-printer-app server
The Ghostcript Printer Application is Copyright © 2020 by Till Kamppeter.
It is derived from the HP PCL Printer Application, a first working model of a raster Printer Application using PAPPL. It is available here:
https://github.com/michaelrsweet/hp-printer-app
The HP PCL Printer Application is Copyright © 2019-2020 by Michael R Sweet.
This software is licensed under the Apache License Version 2.0 with an exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS). See the files "LICENSE" and "NOTICE" for more information.
Source freshness, updater ownership and cache evidence are documented in the FSDK source update guide.