From b87c6b83e40f1b26f7c311ad96d493997e424e67 Mon Sep 17 00:00:00 2001 From: Sean Ellingham Date: Fri, 31 Oct 2025 10:38:27 +0000 Subject: [PATCH] Virtual PDF printer for Paperless --- files/paperless-virtual-printer/Dockerfile | 25 +++ files/paperless-virtual-printer/cups-pdf.conf | 9 + files/paperless-virtual-printer/cupsd.conf | 190 ++++++++++++++++++ files/paperless-virtual-printer/entrypoint.sh | 30 +++ files/paperless-virtual-printer/printers.conf | 22 ++ .../paperless-virtual-printer/vprint.service | 22 ++ group_vars/docker/vars.yaml | 8 + host_vars/memory_alpha/vars.yaml | 28 ++- 8 files changed, 333 insertions(+), 1 deletion(-) create mode 100644 files/paperless-virtual-printer/Dockerfile create mode 100644 files/paperless-virtual-printer/cups-pdf.conf create mode 100644 files/paperless-virtual-printer/cupsd.conf create mode 100755 files/paperless-virtual-printer/entrypoint.sh create mode 100644 files/paperless-virtual-printer/printers.conf create mode 100644 files/paperless-virtual-printer/vprint.service diff --git a/files/paperless-virtual-printer/Dockerfile b/files/paperless-virtual-printer/Dockerfile new file mode 100644 index 0000000..2bf8e98 --- /dev/null +++ b/files/paperless-virtual-printer/Dockerfile @@ -0,0 +1,25 @@ +FROM debian:bullseye-slim +ARG USERNAME=print PASSWORD=print +ENV \ + PRINTER_ID=Paperless \ + PRINTER_NAME=Paperless \ + HOSTNAME=127.0.0.1 \ + OUTPUT_SUBPATH=vprint \ + OUTPUT_USERNAME=$USERNAME + +# Dependenicies +RUN apt-get update +RUN apt-get install -y --no-install-recommends cups printer-driver-cups-pdf gettext + +# Cups config/setup +RUN useradd -G lp,lpadmin -s /bin/bash -p "$(openssl passwd -1 $PASSWORD)" $USERNAME + +# discoverability +RUN apt-get install -y avahi-daemon +RUN sed -i 's/.*enable\-dbus=.*/enable\-dbus\=no/' /etc/avahi/avahi-daemon.conf + +# Copy configs +WORKDIR /opt/vp +COPY . . + +CMD ["./entrypoint.sh"] diff --git a/files/paperless-virtual-printer/cups-pdf.conf b/files/paperless-virtual-printer/cups-pdf.conf new file mode 100644 index 0000000..3b43e69 --- /dev/null +++ b/files/paperless-virtual-printer/cups-pdf.conf @@ -0,0 +1,9 @@ +# Cups PDF printer to /mnt + +Out /mnt/output +AnonDirName /mnt/output +Label 0 +AnonUser ${OUTPUT_USERNAME} + +Grp lpadmin +DecodeHexStrings 1 diff --git a/files/paperless-virtual-printer/cupsd.conf b/files/paperless-virtual-printer/cupsd.conf new file mode 100644 index 0000000..f5f41ba --- /dev/null +++ b/files/paperless-virtual-printer/cupsd.conf @@ -0,0 +1,190 @@ +# +# Configuration file for the CUPS scheduler. See "man cupsd.conf" for a +# complete description of this file. +# + +# Log general information in error_log - change "warn" to "debug" +# for troubleshooting... +LogLevel warn +PageLogFormat + +# Deactivate CUPS' internal logrotating, as we provide a better one, especially +# LogLevel debug2 gets usable now +MaxLogSize 0 + +# Only listen for connections from the local machine. +Listen *:631 +Listen /run/cups/cups.sock +ServerAlias * + +# Show shared printers on the local network. +Browsing On +BrowseLocalProtocols dnssd + +# Default authentication type, when authentication is required... +DefaultAuthType Basic +DefaultEncryption Never + +# Web interface setting... +WebInterface Yes + +# Restrict access to the server... + + Order allow,deny + Allow all + + +# Restrict access to the admin pages... + + Order allow,deny + Allow all + + +# Restrict access to configuration files... + + AuthType Default + Require user @SYSTEM + Order allow,deny + + +# Restrict access to log files... + + AuthType Default + Require user @SYSTEM + Order allow,deny + + +# Set the default printer/job policies... + + # Job/subscription privacy... + JobPrivateAccess default + JobPrivateValues default + SubscriptionPrivateAccess default + SubscriptionPrivateValues default + + # Job-related operations must be done by the owner or an administrator... + + Order deny,allow + + + + Require user @OWNER @SYSTEM + Order deny,allow + + + # All administration operations require an administrator to authenticate... + + AuthType Default + Require user @SYSTEM + Order deny,allow + + + # All printer operations require a printer operator to authenticate... + + AuthType Default + Require user @SYSTEM + Order deny,allow + + + # Only the owner or an administrator can cancel or authenticate a job... + + Require user @OWNER @SYSTEM + Order deny,allow + + + + Order deny,allow + + + +# Set the authenticated printer/job policies... + + # Job/subscription privacy... + JobPrivateAccess default + JobPrivateValues default + SubscriptionPrivateAccess default + SubscriptionPrivateValues default + + # Job-related operations must be done by the owner or an administrator... + + AuthType Default + Order deny,allow + + + + AuthType Default + Require user @OWNER @SYSTEM + Order deny,allow + + + # All administration operations require an administrator to authenticate... + + AuthType Default + Require user @SYSTEM + Order deny,allow + + + # All printer operations require a printer operator to authenticate... + + AuthType Default + Require user @SYSTEM + Order deny,allow + + + # Only the owner or an administrator can cancel or authenticate a job... + + AuthType Default + Require user @OWNER @SYSTEM + Order deny,allow + + + + Order deny,allow + + + +# Set the kerberized printer/job policies... + + # Job/subscription privacy... + JobPrivateAccess default + JobPrivateValues default + SubscriptionPrivateAccess default + SubscriptionPrivateValues default + + # Job-related operations must be done by the owner or an administrator... + + AuthType Negotiate + Order deny,allow + + + + AuthType Negotiate + Require user @OWNER @SYSTEM + Order deny,allow + + + # All administration operations require an administrator to authenticate... + + AuthType Default + Require user @SYSTEM + Order deny,allow + + + # All printer operations require a printer operator to authenticate... + + AuthType Default + Require user @SYSTEM + Order deny,allow + + + # Only the owner or an administrator can cancel or authenticate a job... + + AuthType Negotiate + Require user @OWNER @SYSTEM + Order deny,allow + + + + Order deny,allow + + diff --git a/files/paperless-virtual-printer/entrypoint.sh b/files/paperless-virtual-printer/entrypoint.sh new file mode 100755 index 0000000..9f4e15b --- /dev/null +++ b/files/paperless-virtual-printer/entrypoint.sh @@ -0,0 +1,30 @@ +#!/bin/bash +set -e + +declare -r usermap_original_uid=$(id -u print) +declare -r usermap_original_gid=$(id -g print) +declare -r usermap_new_uid=${USERMAP_UID:-$usermap_original_uid} +declare -r usermap_new_gid=${USERMAP_GID:-${usermap_original_gid:-$usermap_new_uid}} + +if [[ ${usermap_new_uid} != "${usermap_original_uid}" ]]; then + echo "${log_prefix} Mapping UID to $usermap_new_uid" + usermod --non-unique --uid "${usermap_new_uid}" print +else + echo "${log_prefix} No UID changes" +fi + +if [[ ${usermap_new_gid} != "${usermap_original_gid}" ]]; then + echo "${log_prefix} Mapping GID to $usermap_new_gid" + groupmod --non-unique --gid "${usermap_new_gid}" print +else + echo "${log_prefix} No GID changes" +fi + +cat cups-pdf.conf | envsubst > /etc/cups/cups-pdf.conf +cat cupsd.conf | envsubst > /etc/cups/cupsd.conf +cat printers.conf | envsubst > /etc/cups/printers.conf +cat vprint.service | envsubst > /etc/avahi/services/vprint.service +cp /usr/share/ppd/cups-pdf/CUPS-PDF_noopt.ppd /etc/cups/ppd/${PRINTER_ID}.ppd + +/usr/sbin/avahi-daemon --daemonize +exec /usr/sbin/cupsd -f diff --git a/files/paperless-virtual-printer/printers.conf b/files/paperless-virtual-printer/printers.conf new file mode 100644 index 0000000..d84d1b5 --- /dev/null +++ b/files/paperless-virtual-printer/printers.conf @@ -0,0 +1,22 @@ +# Printer configuration file for CUPS v2.2.10 +# Written by cupsd +# DO NOT EDIT THIS FILE WHEN CUPSD IS RUNNING + +UUID urn:uuid:b5105127-039f-3bdc-6153-762925a06b8f +Info ${PRINTER_NAME} +Location +MakeModel Generic PostScript Printer +DeviceURI cups-pdf:/ +State Idle +StateTime 1666751881 +ConfigTime 1666751900 +Type 8400972 +Accepting Yes +Shared Yes +JobSheets none none +QuotaPeriod 0 +PageLimit 0 +KLimit 0 +OpPolicy default +ErrorPolicy retry-job + diff --git a/files/paperless-virtual-printer/vprint.service b/files/paperless-virtual-printer/vprint.service new file mode 100644 index 0000000..3d89d9b --- /dev/null +++ b/files/paperless-virtual-printer/vprint.service @@ -0,0 +1,22 @@ + + + ${PRINTER_NAME} + + _ipp._tcp + _universal._sub._ipp._tcp + 631 + adminurl=http://${HOSTNAME}/printers/${PRINTER_ID} + txtvers=1 + qtotal=1 + Transparent=T + URF=DM3 + rp=printers/${PRINTER_ID} + note=Virtual ${PRINTER_NAME} + product=(Generic PostScript Printer) + ty=Generic PostScript Printer + printer-state=3 + printer-type=0x800004 + application/postscript + pdl=application/octet-stream,application/pdf,application/postscript,application/vnd.cups-raster,image/gif,image/jpeg,image/png,image/tiff,image/urf,text/html,text/plain,application/msword,application/pclm,application/rss+xml,application/sgml + + diff --git a/group_vars/docker/vars.yaml b/group_vars/docker/vars.yaml index 0d36413..e0a9547 100644 --- a/group_vars/docker/vars.yaml +++ b/group_vars/docker/vars.yaml @@ -115,6 +115,14 @@ all_container_users: gid: 215 hosts: - memory_alpha + - username: paperless-printer + uid: 216 + gid: 216 + groups: + - archive + - scanners + hosts: + - memory_alpha container_user_opts: shell: /usr/sbin/nologin diff --git a/host_vars/memory_alpha/vars.yaml b/host_vars/memory_alpha/vars.yaml index bc4522f..ae9d744 100644 --- a/host_vars/memory_alpha/vars.yaml +++ b/host_vars/memory_alpha/vars.yaml @@ -4,6 +4,7 @@ target_os: ubuntu appdata_path: /mnt/zfs/appdata archive_path: /mnt/zfs/archive +paperless_consume_path: /mnt/transient/paperless/consume media_downloads_mountpoint: "/mnt/zfs/media-downloads" @@ -580,7 +581,7 @@ docker_compose_projects: owner: paperless group: archive mode: "u+rwx,g+rwx" - - source: /mnt/transient/paperless/consume + - source: "{{ paperless_consume_path }}" target: /usr/src/paperless/consume owner: paperless group: scanners @@ -666,8 +667,33 @@ docker_compose_projects: restart: unless-stopped labels: - "traefik.enable=false" + - service_name: virtual-printer + build: + context: virtual-printer + src: paperless-virtual-printer + restart: unless-stopped + environment: + USERMAP_UID: "{{ (container_users | selectattr('username', 'equalto', 'paperless-printer') | list | first).uid }}" + USERMAP_GID: "{{ (nas_groups | selectattr('name', 'equalto', 'scanners') | list | first).gid }}" + networks: + - virtual-printer-vlan + volumes: + - source: "{{ paperless_consume_path }}" + target: /mnt/output + create: false + ports: + - 631:631 networks: - name: paperless + - name: virtual-printer-vlan + driver: macvlan + driver_opts: + parent: "{{ ansible_default_ipv4.interface }}" + ipam: + config: + - subnet: "192.168.5.0/24" + ip_range: "192.168.5.134/32" # Static IP + gateway: "192.168.5.1" - name: proxy external: true alias: "{{ traefik_docker_network }}"