The Handbook

    Theme
    • Guides
        • Check a system before installing FreeBSD
        • Orient a Linux administrator on FreeBSD
        • Supported FreeBSD releases
        • Choose a FreeBSD documentation and support channel
        • Move files safely without GNU mv -t
        • Update, upgrade, or update packages?
        • Upgrade 14.4 or 15.0 to FreeBSD 15.1
        • Choose packages, ports, or poudriere
        • Choose the quarterly or latest package branch
        • Choose a FreeBSD download or package mirror
        • Make a system setting persistent
        • Configure locale, keyboard, and time zone
        • Configure a serial console for recovery
        • Choose a custom kernel, module, or loader setting
        • Run a Linux binary with the compatibility layer
        • Check desktop and laptop hardware before installation
        • Choose and check a graphics driver
        • Choose Xorg or Wayland
        • Build a maintainable desktop baseline
        • Install and check a desktop browser
        • Check laptop Wi-Fi, power, and suspend
        • Check multimedia readiness
        • Choose and configure a printing stack
        • Run Windows applications with Wine
        • Snapshot and replicate a ZFS dataset
        • Choose a filesystem and storage layout
        • Operate ZFS without losing the recovery path
        • Restore files from a ZFS snapshot
        • Read ZFS pool health and run a scrub
        • Replace a failed device in a ZFS mirror
        • Replicate a ZFS dataset over SSH
        • Change PF safely on a remote host
        • Configure a narrow WireGuard tunnel
        • Plan a FreeBSD home server
        • Choose a mail server or an outgoing relay
        • Publish a network service safely
        • Choose a jail network model
        • Choose native jails or a jail manager
        • Choose a jail or a bhyve virtual machine
        • Establish a FreeBSD security baseline
        • Choose a MAC policy
        • Audit security-relevant activity
        • Start a DTrace performance investigation
    • Integrations
        • Create a first jail with Bastille
        • Compare jail managers and OCI tooling
        • Publish a Bastille service through PF
        • Mount a ZFS dataset in a Bastille jail
        • Update and upgrade Bastille jails
        • Back up and restore a Bastille jail
        • Prepare bhyve and vm-bhyve
        • Choose NFS or Samba for file sharing
        • Choose ZFS backup automation
        • Operate a signed poudriere repository
        • Manage FreeBSD configuration with Ansible or Salt
        • Run Motion with webcamd on FreeBSD
        • Design a reverse proxy, certificates, and monitoring
    • FAQ
    • Troubleshooting
        • Recover an interrupted freebsd-update run
        • Resolve a package repository or ABI mismatch
        • Diagnose the FreeBSD boot path
        • Recover with a ZFS boot environment
        • Diagnose DNS, routing, and firewall paths
        • Diagnose network mbuf exhaustion
        • Bind a service to a low port without running it as root
        • Diagnose audio output or input
        • Diagnose webcamd, cuse, and a webcam
        • Fix USB device permissions without opening every device
    • About this handbook
    • Synopsis
    • Inventory the printing path
    • Choose between lpd and CUPS
    • Establish a narrow lpd queue
    • Establish a local CUPS server
    • Control discovery and network exposure
    • Diagnose by layer
    • Roll back cleanly
    • Primary references

    Choose and configure a printing stack

    Last reviewed
    13 August 2026
    Applies to
    15.1-RELEASE, 15.0-RELEASE, 14.4-RELEASE

    Synopsis #

    FreeBSD includes the traditional lpd spooler. CUPS is available as a package and centers its design on the Internet Printing Protocol (IPP). Either can submit reliable jobs when the printer’s connection and page-description language are understood. They differ in discovery, driver integration, administration, and client expectations.

    Choose one queue owner before enabling services. Running two spoolers against the same device or publishing duplicate queues produces ambiguous failures and duplicate printer entries.

    The current base lpd, lpc, and chkprintcap manual pages carry deprecation notices scheduling that facility for removal before FreeBSD 16.0. It remains available on the releases covered here, but a new installation expected to cross that release boundary should normally select CUPS or include an explicit migration plan.

    Inventory the printing path #

    Record four separate facts:

    1. Connection: USB, parallel, direct IPP, AppSocket/JetDirect, LPD, SMB, or a queue on another server.
    2. Printer language: driverless IPP capability, PostScript, PDF, PCL, or a model-specific raster format.
    3. Clients: one local FreeBSD host, several Unix-like clients, mobile devices, or a mixed network.
    4. Policy: local-only printing, LAN sharing, discovery, authenticated administration, and untrusted network boundaries.

    Use the printer’s current technical documentation or self-test/configuration page to establish protocol and language support. A detected USB device proves transport only. It does not prove that the printer accepts the submitted document format.

    For USB attachment evidence:

    $ usbconfig list
    # dmesg | tail
    

    For a network printer, establish address, route, DNS, and port reachability before changing a spooler. The network-path diagnostic separates those layers.

    Choose between lpd and CUPS #

    Requirement Prefer base lpd Prefer packaged CUPS
    One known local or network queue Suitable Suitable
    Existing printcap(5) workflow and filters Native model Requires migration into CUPS queues
    IPP and driverless printing Limited traditional workflow Primary protocol and stronger fit
    Desktop printer dialogs and mixed clients Manual client configuration is common Better integration and queue discovery
    Model-specific packaged drivers Custom filter must be designed CUPS driver packages may integrate them
    Minimal base-system service set No package required Adds packages and /usr/local configuration
    Web administration None Local CUPS interface available

    Do not select a driver package solely by vendor name. Confirm that the exact model, architecture, protocol, and intended features are supported. Many modern printers work best through driverless IPP; older or host-based models may require a CUPS filter or may not be practical on FreeBSD.

    Establish a narrow lpd queue #

    Use lpd when the printer language and transport are already known and a small traditional spooler is sufficient. Before editing /etc/printcap, inspect the base examples and manual:

    $ less /usr/share/examples/printing/README
    $ man 5 printcap
    

    Create one queue with an explicit spool directory, device or remote queue, log path, and only the filter required for the documented printer language. Printer-specific device paths, remote queue names, and filters cannot be copied safely from a generic example.

    Check the file syntax before enabling the daemon by asking chkprintcap(8) to inspect all entries:

    # chkprintcap
    

    Then enable and start the base service:

    # sysrc lpd_enable=YES
    # service lpd start
    

    Submit a small known-good file in a language the printer accepts, then inspect the queue:

    $ lpr -P queue-name known-good-file
    $ lpq -P queue-name
    

    Replace queue-name with the exact queue name from /etc/printcap rather than relying on an unverified default queue.

    When a job queues but does not print, inspect the queue’s configured error log, device permissions, connection, and filter exit status. Do not repeatedly resubmit the same job while the cause is unknown.

    Establish a local CUPS server #

    Use CUPS when IPP, desktop integration, discovery, or packaged driver filters justify it. Install the package and keep administration local during initial qualification:

    # pkg install cups
    # sysrc cupsd_enable=YES
    # service cupsd start
    

    Open http://localhost:631/ from the same host. Add one printer using its documented IPP URI or the detected local device. Prefer a driverless queue when both printer and CUPS report compatible IPP capabilities; otherwise install only the package that explicitly supports the model.

    USB printers may require a narrow devfs.rules(5) entry and a persistent devfs_system_ruleset. Derive the rule from the device that appears in dmesg and /dev, and grant it to the service’s documented group. A wildcard that changes every USB device to a permissive mode is not an acceptable printing fix. The USB-permissions guide provides the evidence-first boundary.

    Verify service and queue state from the command line:

    # service cupsd status
    $ lpstat -t
    

    Use the CUPS error log under /var/log/cups/ to distinguish backend, filter, authorization, and device failures. Temporarily increasing the documented CUPS log level can collect evidence, but restore the normal level after diagnosis because job metadata and detailed requests can be sensitive.

    Control discovery and network exposure #

    Discovery and printing are separate. DNS-SD/mDNS can advertise or find a queue, while IPP carries administration and jobs. A manually configured IPP URI can work when discovery is intentionally disabled.

    Keep CUPS bound to its package default local interfaces until sharing is required. For LAN sharing:

    • define the exact client networks and interface boundary;
    • expose printing separately from remote administration;
    • require authentication and encryption where the client and server design supports them;
    • allow the required traffic through the host firewall only after a local print succeeds;
    • confirm that multicast discovery does not cross unintended networks.

    Do not publish TCP port 631, traditional LPD, AppSocket, or a printer’s management interface to the public Internet as a shortcut. The safe PF change procedure preserves a rollback path when network exposure changes.

    Diagnose by layer #

    Symptom Evidence to collect
    Printer absent locally usbconfig, dmesg, device nodes, cable, and power
    Network printer unreachable address, route, DNS, ARP/NDP, and listening protocol
    Queue accepts but never sends spooler status, queue state, backend/device error, and permissions
    Bytes arrive but output is blank or garbled submitted format, selected driver/filter, and printer language
    Local print works but clients cannot find it explicit IPP URI, discovery service, firewall, and publish policy
    Clients find duplicate queues multiple publishers, both spoolers enabled, or printer self-advertisement
    Some applications print and others do not application-selected queue, toolkit backend, document format, and environment

    Retain the smallest known-good test: one host, one queue, one document, and one transport. Add discovery, additional clients, or sharing only after that path is repeatable. A maintainable desktop baseline applies the same staged approach to the rest of a graphical workstation.

    Roll back cleanly #

    Before changing stacks, drain or cancel understood jobs, save the existing queue configuration, and stop the old daemon. Disable only the service that is being replaced:

    # sysrc lpd_enable=NO
    # service lpd stop
    

    or:

    # sysrc cupsd_enable=NO
    # service cupsd stop
    

    Remove a device-permission or firewall rule only after confirming that no other service depends on it. Keep a record of the working printer URI, driver or language, package versions, and a known-good test document so a later package or firmware change can be compared.

    Primary references #

    • FreeBSD Handbook: Printing
    • FreeBSD article: CUPS on FreeBSD
    • lpd(8)
    • printcap(5)
    • chkprintcap(8)
    • lpr(1)
    • lpq(1)
    • devfs.rules(5)

    Independent documentation. Not affiliated with or endorsed by the FreeBSD Project or the FreeBSD Foundation.

    Report a bug
    • Synopsis
    • Inventory the printing path
    • Choose between lpd and CUPS
    • Establish a narrow lpd queue
    • Establish a local CUPS server
    • Control discovery and network exposure
    • Diagnose by layer
    • Roll back cleanly
    • Primary references