Skip to content

Instantly share code, notes, and snippets.

@djhojd
Created March 18, 2026 16:58
Show Gist options
  • Select an option

  • Save djhojd/ea136053332dfa78489d5c20da15a719 to your computer and use it in GitHub Desktop.

Select an option

Save djhojd/ea136053332dfa78489d5c20da15a719 to your computer and use it in GitHub Desktop.
Proxmox LXC CUPS Setup script for Samsung USB Printer
#!/usr/bin/env bash
# Proxmox LXC CUPS Print Server Setup Script (Hotplug Resilient)
# Run this script on your Proxmox host as root.
# Gist Description: Automates the creation of an unprivileged Debian LXC container on Proxmox, passing through a USB printer, configuring CUPS + Avahi, and enabling robust hotplug support.
set -e
# ================= Configuration =================
CTID=111
TEMPLATE="local:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst"
STORAGE="local-lvm"
# Samsung SCX-4300 IDs
USB_VENDOR="04e8"
USB_PRODUCT="342e"
PRINTER_NAME="Samsung_SCX-4300"
CUPS_DRIVER="drv:///splix-samsung.drv/scx4300.ppd"
CUPS_ADMIN_PASS="printadmin"
HOTPLUG_SCRIPT="/usr/local/bin/update-printer-lxc.sh"
# =================================================
echo "==> Finding USB Printer ($USB_VENDOR:$USB_PRODUCT)..."
USB_INFO=$(lsusb | grep -i "${USB_VENDOR}:${USB_PRODUCT}") || true
if [ -z "$USB_INFO" ]; then
echo "Error: Samsung printer not found on USB bus."
exit 1
fi
BUS=$(echo "$USB_INFO" | awk '{print $2}')
DEV=$(echo "$USB_INFO" | awk '{print $4}' | tr -d ':')
USB_PATH="/dev/bus/usb/$BUS/$DEV"
echo "==> Creating LXC Container $CTID on $STORAGE..."
pct create $CTID $TEMPLATE \
--rootfs ${STORAGE}:8 \
--ostype debian \
--memory 512 \
--cores 1 \
--net0 name=eth0,bridge=vmbr0,ip=dhcp \
--hostname cups-server \
--unprivileged 1 \
--ssh-public-keys /root/.ssh/authorized_keys || echo "Container might already exist."
echo "==> Configuring Initial USB Passthrough for $USB_PATH..."
pct set $CTID -dev0 ${USB_PATH},uid=0,gid=7,mode=0660
echo "==> Starting Container $CTID..."
pct start $CTID
echo "==> Waiting for container network to initialize..."
lxc-attach -n $CTID -- bash -c 'while ! ping -c 1 -W 1 1.1.1.1 &>/dev/null; do sleep 1; done'
echo "==> Setting root password for CUPS web interface..."
echo "root:${CUPS_ADMIN_PASS}" | lxc-attach -n $CTID -- chpasswd
echo "==> Installing CUPS, Avahi (mDNS/AirPrint), and SpliX drivers..."
lxc-attach -n $CTID -- apt-get update
lxc-attach -n $CTID -- apt-get install -y cups printer-driver-splix avahi-daemon
lxc-attach -n $CTID -- systemctl enable --now cups avahi-daemon
echo "==> Configuring CUPS network access..."
lxc-attach -n $CTID -- cupsctl --remote-admin --remote-any --share-printers
echo "==> Discovering actual printer URI inside CUPS..."
PRINTER_URI=$(lxc-attach -n $CTID -- lpinfo -v | grep -i 'usb://' | awk '{print $2}' | head -n 1)
if [ -n "$PRINTER_URI" ]; then
echo "==> Adding and sharing printer in CUPS..."
lxc-attach -n $CTID -- lpadmin -p $PRINTER_NAME -E -v "$PRINTER_URI" -m "$CUPS_DRIVER" -D "Samsung SCX-4300 Shared" -o printer-is-shared=true
lxc-attach -n $CTID -- lpoptions -d $PRINTER_NAME
else
echo "Warning: Printer URI not found immediately. Hotplug script will handle it."
fi
echo "==> Setting up automated Hotplug (udev) Support..."
cat << EOF > $HOTPLUG_SCRIPT
#!/bin/bash
sleep 2
USB_INFO=\$(lsusb | grep -i "${USB_VENDOR}:${USB_PRODUCT}" | head -n 1)
if [ -n "\$USB_INFO" ]; then
BUS=\$(echo "\$USB_INFO" | awk '{print \$2}')
DEV=\$(echo "\$USB_INFO" | awk '{print \$4}' | tr -d ':')
NEW_PATH="/dev/bus/usb/\$BUS/\$DEV"
# Update LXC config dynamically and restart container to apply device nodes
pct set $CTID -dev0 \${NEW_PATH},uid=0,gid=7,mode=0660
pct reboot $CTID
fi
EOF
chmod +x $HOTPLUG_SCRIPT
echo "ACTION==\"add\", SUBSYSTEM==\"usb\", ATTR{idVendor}==\"${USB_VENDOR}\", ATTR{idProduct}==\"${USB_PRODUCT}\", RUN+=\"${HOTPLUG_SCRIPT}\"" > /etc/udev/rules.d/99-samsung-printer.rules
udevadm control --reload-rules
IP_ADDR=$(lxc-attach -n $CTID -- hostname -I | awk '{print $1}')
echo "=========================================================="
echo "SUCCESS!"
echo "CUPS Print Server is running at: https://${IP_ADDR}:631"
echo "Login credentials for Web UI: root / ${CUPS_ADMIN_PASS}"
echo "=========================================================="

Walkthrough: USB Printer Network Sharing via CUPS

We successfully bridged your Samsung SCX-4300 USB printer to your home network using a lightweight Debian LXC container on Proxmox.

What Was Accomplished

  1. Identified the Printer: Located the printer on Bus 001 Device 004 (Vendor/Product ID 04e8:342e).
  2. Created the LXC (ID 111): Provisioned a minimal Debian 13 footprint on local-lvm.
  3. USB Passthrough: Mapped the character device /dev/bus/usb/001/004 into the unprivileged container, assigning ownership (uid=0, gid=7) to allow the lp group to print.
  4. CUPS Server Configuration:
    • Installed cups, avahi-daemon, and the open-source printer-driver-splix needed for the printer.
    • Authorized remote network access so you can access it at 192.168.1.30:631.
  5. Printer Installed Automatically:
    • Created the print queue exactly matched to the USB URI (usb://Samsung/SCX...).
    • Network Sharing is ON.

How to use it on your devices:

Because we installed avahi-daemon matching your Tailscale-gateway environment, the printer advertises itself via IPP/Bonjour/mDNS.

  • macOS / iOS: The printer should automatically appear as an AirPrint / nearby printer named Samsung_SCX-4300.
  • Windows: Go to Add a printer or scanner -> It should appear automatically. If not, browse by URL: http://192.168.1.30:631/printers/Samsung_SCX-4300.

Final Notes

  • Your CUPS admin password is set to printadmin for the root user, though you probably won't need to touch it since everything is configured!
  • Pro Tip: If you ever unplug the physical USB cable from the Beelink PC and plug it into a different port, the USB bus might change. If it stops printing, just re-run the lsusb and pct set commands we used to update the path!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment