Aatish Neupane

Turn a USB printer into a network printer with Proxmox

I consider printers to be an “essential luxury.” You don’t need it most of the time, but when you need it, you wish you had one at home. Going through a bout of this many times, I decided to splurge on a printer purchase and scoured the marketplace for a nice, basically un-used USB only printer for $20 (Brother HL-L2300D). It was such a nice deal and it was fun to be able to print anything right from your laptop. However, needing a laptop meant the inconvenience of transferring things to your laptop and then being finally able to print. Very high “transaction cost”.

I have a small mini PC running Proxmox which is basically my homelab for various services. I decided to figure out a way to have this printer connected to this server and be able to print from my network. And, thankfully, it wasn’t that bad. Basically, pass-through the device to a small VM, run CUPS, and use CUPS to share the printer over network. When this all worked, it was like magic. I could print from any computer and even phones without configuring really anything. In the midst of AI craze, I even created a “Send me a letter” service that would let my friends type in messages and it would print messages directly to this printer. Nothing is as fun as being able to interact with the physical world. Anyway, if you want to do the same with one of your dumb printers, you can follow along the steps below:

Find the printer on the host

Turn the printer on first, then run lsusb on the Proxmox host.

root@proxmox:~# lsusb
[...]
Bus 001 Device 004: ID 04f9:0061 Brother Industries, Ltd HL-L2300D series
[...]

We need this 04f9:0061, the vendor:product ID, for the passthrough.

Create a Linux VM

Any Linux will do, I went with Ubuntu 24.04 because the community script does all the bootstrapping work necessary: https://community-scripts.org/scripts/ubuntu2404-vm

Use cloud-init to set the password and the network, DHCP should be fine.

Pass the USB device through to the VM

VM → Hardware → Add → USB Device → Use USB Vendor/Device ID → pick the Brother 04f9:0061.

Proxmox Add USB Device dialog, with Use USB Vendor/Device ID selected and the Brother HL-L2300D listed at 04f9:0061

Install CUPS in the VM

 1sudo apt update
 2sudo apt install \
 3  cups \
 4  cups-client \
 5  cups-filters \
 6  cups-ipp-utils \
 7  printer-driver-brlaser \
 8  avahi-daemon \
 9  avahi-utils \
10  ghostscript \
11  poppler-utils

One thing to note here is that printer-driver-brlaser is the driver for the Brother laser. You might need to search around to find the right driver for your printer. Apart from CUPS, we are installing avahi-daemon which is what makes the printer discoverable on the network.

User Configuration

After CUPS is installed above, add yourself to the lpadmin group so you can administer CUPS:

1sudo usermod -aG lpadmin $USER

Group change needs a re-login to take effect.

Confirm the printer is visible in the VM

Inside the VM shell, run the following:

root@ubuntu:~# lpinfo -v
network beh
network ipps
serial serial:/dev/ttyS0?baud=115200
network http
network lpd
network socket
network ipp
network https
direct usb://Brother/HL-L2300D%20series?serial=U63878C2N839617

The direct usb://... line is the printer, so this confirms that the passthrough worked. That URI is what CUPS uses to address it.

Open CUPS up to the network

By default CUPS only listens on localhost, which is no good if the whole point is printing from other machines. Edit /etc/cups/cupsd.conf:

 1LogLevel warn
 2PageLogFormat
 3MaxLogSize 0
 4ErrorPolicy retry-job
 5# Allow remote access
 6Port 631
 7Listen /run/cups/cups.sock
 8# Share local printers on the local network.
 9Browsing On
10BrowseLocalProtocols dnssd
11DefaultAuthType Basic
12WebInterface Yes
13IdleExitTimeout 60
14<Location />
15  # Allow shared printing...
16  Order allow,deny
17  Allow 192.168.8.0/24
18</Location>
19<Location /admin>
20  AuthType Default
21  Require user @SYSTEM
22  Order allow,deny
23  Allow 192.168.8.0/24
24</Location>
25<Location /admin/conf>
26  AuthType Default
27  Require user @SYSTEM
28  Order allow,deny
29  Allow 192.168.8.0/24
30</Location>
31<Location /admin/log>
32  AuthType Default
33  Require user @SYSTEM
34  Order allow,deny
35  Allow @LOCAL
36</Location>

This changes the following:

Check the config parses before restarting anything:

root@ubuntu:~# sudo cupsd -t
"/etc/cups/cups-files.conf" is OK.
"/etc/cups/cupsd.conf" is OK.

Then turn on sharing and restart:

1sudo cupsctl --share-printers
2sudo systemctl restart cups

Add the printer in CUPS

The web interface is on port 631 of the VM:

https://192.168.8.106:631/admin

Log in as your regular user - the one you added to lpadmin earlier. Root works too, but avoid it if you can.

Administration → Add Printer.

CUPS Printers page with Add Printer, Find New Printers and Manage Printers buttons

The Brother shows up under Local Printers, because as far as the VM is concerned it’s a locally attached USB printer.

CUPS Add Printer page with Brother HL-L2300D series selected under Local Printers

Name it, and check Share This Printer. The connection URI is the same usb:// one from lpinfo -v.

CUPS Add Printer form showing name, description, connection URI and Share This Printer checked

Then pick the make and model. Mine is Brother HL-L2300D series, using brlaser v6 (en), which comes from the printer-driver-brlaser package we installed earlier.

CUPS Add Printer model selection with Brother HL-L2300D series using brlaser v6 highlighted

After this is complete, the printer queue now lives at:

https://192.168.8.106:631/printers/Brother_HL-L2300D_series

Check the printer is being advertised

On the VM, to confirm mDNS is working, run the following:

root@ubuntu:~# avahi-browse -rt _ipp._tcp
+   eth0 IPv6 Brother HL-L2300D series @ ubuntu             Internet Printer     local
+   eth0 IPv4 Brother HL-L2300D series @ ubuntu             Internet Printer     local
+     lo IPv4 Brother HL-L2300D series @ ubuntu             Internet Printer     local
=   eth0 IPv4 Brother HL-L2300D series @ ubuntu             Internet Printer     local
   hostname = [ubuntu.local]
   address = [192.168.8.106]
   port = [631]
   txt = ["printer-type=0x1056" [...] "rp=printers/Brother_HL-L2300D_series" "qtotal=1" "txtvers=1"]

That’s the printer advertising itself over Bonjour, which is what lets clients on the same subnet find it without being told an address. rp=printers/Brother_HL-L2300D_series is the queue path we need if we ever add it manually.

Test the queue directly

Avahi and mDNS don’t cross subnets, so from a different subnet you point at the IP and check IPP answers:

1ipptool -tv ipp://192.168.8.106:631/printers/Brother_HL-L2300D_series get-printer-attributes.test

This lets you verify the connection and is useful for debugging cross-subnet issues.

Add it on a Mac

Now that this is complete, the printer should be automatically visible in the “Default” tab of the Mac printer dialog. If you are crossing subnets, you can add it by hand:

Printers → Add → IP tab:

macOS Add Printer dialog on the IP tab with address, IPP protocol and printers/Brother_HL-L2300D_series as the queue

The printers/ prefix on the queue matters — it’s the resource path, the same rp= value that shows up in the mDNS record above.

We just made a dumb printer “smart”.

#Proxmox #Homelab