You need a PDF and the print dialog is confusing
You open a terminal log, a markdown file, or a LibreOffice document and need a clean PDF copy. You click print, but the dialog shows a dozen physical printers, a network queue, and a confusing Save as PDF option that sometimes vanishes. You need a reliable way to generate a PDF without wrestling with printer drivers or missing filters.
What is actually happening when you print to PDF
Linux does not treat Print to PDF as a single application feature. It treats it as a standard print job routed through CUPS. CUPS stands for Common Unix Printing System. It acts as a translation layer between your application and the output format. When you select a PDF destination, CUPS passes the document through a filter chain. The filter converts the application native format into PostScript, then another filter converts PostScript into PDF. The final file lands in your home directory or a specified output path.
This architecture means you can print to PDF from any application that supports standard printing. You can also automate the process from the terminal. The system already includes the necessary filters. You only need to enable the virtual printer or install a lightweight CLI tool for batch work. The cups-pdf package provides the virtual destination. It registers a printer named CUPS-PDF that accepts any document type and routes it through the standard CUPS pipeline. The package is included in the default Fedora Workstation installation. If it was removed, the graphical option disappears.
Run lpstat -p -d to verify the virtual printer is registered. The output should list printer CUPS-PDF idle. If it is missing, the package needs reinstalling.
Check the printer queue before you troubleshoot. An empty queue means the job never left the application.
The graphical route: CUPS PDF printer
Most desktop applications on Fedora use GTK or Qt print dialogs. Both dialogs query CUPS for available destinations. If the CUPS PDF printer is not visible, the virtual destination is likely disabled. Enable it through the CUPS web interface or the command line. The CUPS web interface runs locally on port 631. Open your browser and navigate to http://localhost:631/admin. Click the Administration tab. Check the box that says Share printers connected to this system if you plan to share, but more importantly, look for Add Printer. If you already see CUPS-PDF in the list, you can skip to using it. If it is missing, add it manually. Select Class or Printer, choose CUPS-PDF from the device list, and install the default driver. The driver is already packaged with Fedora. You do not need to download anything.
Once enabled, open any application. Click Print. Select CUPS-PDF as the destination. The output file will appear in ~/CUPS-PDF/ by default. You can change the output directory by editing the CUPS-PDF configuration file. The configuration lives in /etc/cups/cups-pdf.conf. Edit it with your preferred editor. Change the Out directive to point to a different path. Restart the CUPS service afterward.
Here is how to adjust the default output directory so your PDFs land in a dedicated workspace folder instead of your home directory.
# Open the CUPS-PDF configuration file for editing
sudo nano /etc/cups/cups-pdf.conf
# Change the Out directive to your preferred path
# Out /home/youruser/Documents/PDFs
# Save and exit, then restart the CUPS daemon to apply changes
sudo systemctl restart cups
Convention aside: Configuration files in /etc/ are meant for user modifications. The original package files live in /usr/lib/cups/. Always edit /etc/. Package updates will overwrite /usr/lib/ but leave /etc/ untouched.
Reboot before you debug. Half the time the symptom is gone.
The command-line route: text, spreadsheets, and headless apps
Graphical dialogs work well for single documents. They break down when you need to convert fifty text files or automate a nightly report. The terminal provides direct access to the same filter chain without opening a window. The enscript package converts plain text to PostScript, and the built-in CUPS filter converts that PostScript to PDF. Install the package first.
Here is how to install the conversion tool and generate a PDF from a plain text file.
# Install enscript and its dependencies from the default repository
sudo dnf install enscript
# Convert the text file to PostScript, then pipe it through the system PDF filter
enscript --pdf --output=report.pdf /var/log/syslog
The --pdf flag tells enscript to invoke the system PostScript to PDF converter automatically. You do not need to run ps2pdf manually. The command handles the pipeline. For spreadsheets or complex documents, LibreOffice provides a headless conversion mode. It uses the same rendering engine as the desktop application but runs without a graphical interface.
Here is how to convert a spreadsheet or document to PDF using LibreOffice in headless mode.
# Run LibreOffice without a GUI and convert the target file to PDF
libreoffice --headless --convert-to pdf --outdir /tmp/document.pdf /home/user/data.ods
# The --outdir flag specifies where the output file should be written
# The conversion uses the exact same rendering engine as the desktop app
Headless conversion respects the document internal formatting. Margins, fonts, and embedded images render identically to the desktop version. This method is reliable for batch processing. You can pass multiple files by using a wildcard. The command will process each file sequentially and place the results in the specified directory.
Verify it worked. Open the generated file with xdg-open or check the file type with file. The output should report PDF document, version 1.4 or higher. If the file is empty or shows only a single page of whitespace, the source document likely contains hidden formatting or the font cache needs rebuilding. Run fc-cache -fv to refresh the font database and try again.
Run file output.pdf first. Confirm the MIME type before opening it in a viewer.
Verify the output and check the pipeline
CUPS logs every job that passes through the system. If a conversion fails silently, the logs will show where the pipeline broke. The CUPS error log lives in /var/log/cups/error_log. You can also query the job history directly from the terminal. Use lpstat -o to list pending and completed jobs. The output shows the job ID, owner, size, and status. If a job is stuck in held or stopped state, CUPS encountered a fatal error during filtering.
Here is how to inspect the job queue and release a stuck conversion.
# List all jobs currently in the CUPS queue
lpstat -o
# Release a held job by its ID number
# lp -i <jobid> -r
# Check the CUPS error log for the exact failure reason
sudo journalctl -u cups --since "1 hour ago"
The --since flag limits the output to recent entries. CUPS logs can grow quickly on busy systems. Filtering by time keeps the output readable. If the log shows filter failed or cannot execute, the filter binary is missing or lacks execute permissions. Run sudo dnf reinstall cups-filters to restore the default filter chain. The package contains the PostScript and PDF conversion binaries. Reinstalling it fixes broken symlinks or corrupted binaries without touching your configuration.
Convention aside: journalctl -xeu cups reads better than journalctl alone. The x flag adds explanatory text and the e flag jumps to the end. Most sysadmins type journalctl -xeu <unit> muscle-memory style.
Check the queue before you restart the service. Restarting drops pending jobs.
Common pitfalls and what the error looks like
The CUPS service might be stopped. If you see Error: Unable to connect to server when accessing the web interface, the daemon is not running. Start it with sudo systemctl start cups. If the service starts but immediately fails, check the system journal. Run journalctl -xeu cups to see the exact failure reason. Most failures stem from a missing filter or a permission mismatch on the output directory.
Permission errors appear when CUPS tries to write to a directory owned by root. The CUPS daemon runs as the cups user. If you change the Out directory in the configuration file, ensure the cups user has write access. Run sudo chown cups:cups /path/to/output and sudo chmod 755 /path/to/output. The service will then write successfully.
Another common issue is the Save as PDF option disappearing from GTK applications. This happens when the cups-pdf package is removed or the virtual printer is disabled. Reinstall the package with sudo dnf install cups-pdf. The package is part of the default Fedora Workstation installation. If it was accidentally purged, restoring it brings the option back immediately.
SELinux denials can also block PDF generation. If the conversion fails silently, check the audit logs. Run journalctl -t setroubleshoot to see a one-line summary of any security policy violations. SELinux rarely blocks standard CUPS operations, but custom output directories in restricted paths like /opt or /srv will trigger a denial. Move the output directory to your home folder or apply the correct SELinux context with semanage fcontext.
Run journalctl -xeu cups first. Read the actual error before guessing.
Which method fits your workflow
Use the CUPS PDF printer when you need a one-click solution from any graphical application. Use enscript when you are converting plain text, logs, or code files from the terminal. Use LibreOffice headless mode when you need to preserve complex formatting, charts, or embedded objects. Use a2ps when you need advanced pagination control or multiple files merged into a single PDF. Stay on the default CUPS pipeline if you only deviate from the standard print dialog occasionally.