ScanservJs : make your own scan server

David Claeys
10 min readNov 17, 2022

--

Printers and scanners…, I have a love/hate relationship with them. They are very handy when they work, but sometimes they cause a lot of struggle.

I recently set myself up for a challenge. Since a couple of months I own an HP Envy Pro 6442, a printer/scanner combo. While not horrible, the experience using this device as a scanner leaves a lot to be desired. By default, you are limited to use the Windows scanner utility or to installing HP’s app on your phone. I thought the experience could be much better if somehow you could scan images through a webpage.

Admittedly, this device in particular provides a web interface that allows scanning from the web browser. But this interface is not really user friendly and requires authentication (which is rather burdensome for home use). So I looked up the web for a solution and through sheer luck I stumbled upon ScanservJs. The purpose of this article is to guide you through the setup for this particular device but it can be done on other devices.

Edit :
Since I wrote the article I’ve also set everything up with an HP Envy Inspire 7200. I’ve expanded the examples to adapt a bit more to this model.

ScanserveJs has been recently updated to version 3.
The new version has some breaking changes, the article has been updated to accomodate for these changes. If you already have it installed pull the latest image and take a look at the directory mappings.

Disclaimer

This is not by any means an entry-level tutorial. I omit some details that will not be easy to figure out if you have no prior experience.

These are the details I skipped (as far as I’m aware) :

  • Setting up the scanner over the network (docs for HP Envy Pro 6442)
  • Accessing the scanner web UI
  • Setting up the server OS
  • Assigning your server a static IP to your server so that users can access it (and specifying a domain name for your server)
  • Testing this setup with other other devices than mine (other models from HP or any other manufacturer)

Setting up the scanner

Based on my experience I recommend assigning a static IP address. You can achieve this from your router making a static DHCP assignment. If you aren’t able to do this you can do this from the scanner web interface.

Under Network > Wireless > Network Address (IPv4) you can choose Manual IP and choose the IP address you wish.

Setting up the server

Since the scanner is setup over the network, it doesn’t need to be physically connected to the server. You can setup the server on bare metal or a hypervisor such as Proxmox VE, XCP-ng or even Hyper-V. I personally used Virtual Machine Manager on my Synology NAS to make a VM. If you have a QNAP NAS you could also use Virtualization Station. Since this detail is not really relevant for our purposes I won’t go into details. Use whatever suits your needs.

For my OS I used Ubuntu 22.04 Server. You might be able to use other flavors of LINUX but no success is guaranteed. First of all we want to make sure our OS has the latest updates.

Note
I did some testing on Ubuntu 22.10 and the install failed due to an unavailable dependency (python3-pyqt4).

sudo apt-get update
sudo apt-get upgrade

Installing HP drivers

This part of the guide depends mainly on the device manufacturer of your scanner. The following steps are only applicable if you own a HP scanner/printer. If you have another one you’ll need to figure this out on your own.

Edit :
The current version of the hplip software is 3.23.12.

On my server package updates broke my existing installation.
I had to install the latest driver version in order to get everything working again. Needless to say you need to be very careful when applying updates with your package manager, since it won’t automatically update your hplip installation.

Drivers for other manufacturers
Epson
Canon
Brother
Samsung

Luckily HP provides a LINUX driver for their devices. Although they just worked fine the documentation and installation process is a bit flaky.

First of all go to https://developers.hp.com/hp-linux-imaging-and-printing/gethplip and select your server’s distro. If you followed along the distro we’re using is ubuntu.

Hp driver downloader page

Then just click the download button and the download should start through SourceForge.

Driver download starting

Once the download is completed you should get a file called hplip-3.22.10.run. Please note that the version might change over time as well the download source.

Before we attempt to install the driver we need to install some required packages on the server. You can find the required packages on https://developers.hp.com/hp-linux-imaging-and-printing/install/manual/distros/ubuntu.

HP requirements documentation
sudo apt-get install --assume-yes libcups2 cups libcups2-dev cups-bsd cups-client avahi-utils libavahi-client-dev libavahi-core-dev libavahi-common-dev libcupsimage2-dev libdbus-1-dev build-essential gtk2-engines-pixbuf ghostscript openssl libjpeg-dev libatk-adaptor libgail-common libsnmp-dev snmp-mibs-downloader libtool libtool-bin libusb-1.0-0-dev libusb-0.1-4 wget policykit-1 policykit-1-gnome automake1.11 python3-dbus.mainloop.pyqt5 python3-reportlab python3-notify2 python3-pyqt5 python3-dbus python3-gi python3-lxml python3-dev python3-pil python-is-python3 libsane libsane-dev sane-utils xsane -yq

This command should do the trick but please be aware that this could change over time. Check the documentation to make sure you have all the requirements.

Now it’s time to install the driver on the server. At this stage I stumbled upon a hurdle. I was trying to get the installer file into my server but since I had a headless server I couldn’t figure out how to get the installer file into my server. Finally I settled with downloading it on my Windows machine and transferring the file to my server through sftp. I used a program called FileZilla to do this.

I made a new directory called HP where I put this file.

mkdir hp

Then I went into this directory.

cd hp

Once you are in the directory you can proceed with this command
(Please be aware of the version number).

sh hplip-3.22.10.run
Screenshot of the driver installation process

This is the point where you need a lot of patience because depending on your system this step might take a while.

Once the installation is completed you can proceed setting up the scanner. You can do this with the following command. Please be aware that you will need to adapt the IP address depending on whatever you set up previously.

sudo hp-setup -i 192.168.0.70

Once this is completed you can check if everything is working with this command

scanimage -L

This command should give the following output. If you don’t see anything at this point your driver is not working.

Example of output

Installing docker

The most easy way to get the ScanservJs software working is through docker. I performed the install with the following command. Please be aware that this might change over time and read the documentation on https://docs.docker.com/engine/install/ubuntu/.

sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
Screenshot of the official Docker documentation

Setup the server environment for the docker container

Before spinning up the container there are a couple of things we want to do.
First make a folder containing all our docker configurations. Be aware that you should change your user and user groups to yours in my example. It’s also possible to use other folders to store the configuration, if you do so you also will need to adapt the container setup later on.

sudo mkdir /docker
sudo chown sane:sane /docker

Now make a folder containing the container we are about to spin up.

mkdir -p /docker/sane/config
mkdir -p /docker/sane/images

Now make a file containing the configuration.

nano /docker/sane/config/config.local.js

Paste the following contents into the file. This example is based on the documentation on github.

The device id is derived from the AIRSCAN_DEVICES environment variable of the docker container. The device name can be whatever you want.

If you look carefully you can see I specified the resolutions for my scanner. In case you have another scanner than mine, read the documentation in order to figure how to change the them for yours.

/* eslint-disable no-unused-vars */

module.exports = {
afterDevices(devices) {
const deviceNames = {
/*
'device id':'device name'
*/
'airscan:e0:Hp Envy Pro 6442': 'Hp Envy Pro 6442'
};

/*
replace the id in the filter
*/
devices
.filter(d => d.id == 'airscan:e0:Hp Envy Pro 6442')
.forEach(device => {
device.features['--resolution'].default = 400;
device.features['--resolution'].options = [100, 150, 200, 300, 400, 600];
/*
Disable batch modes if they are not available on your printer
*/
device.settings.batchMode.options = ['none', 'manual'];
/*
Specify the default pipeline
*/
device.settings.pipeline.default = ['PNG'];
});

devices
.filter(d => d.id in deviceNames)
.forEach(d => d.name = deviceNames[d.id]);
}
};

Scantopl pipeline for uploading to Paperles-ng

With this additional configuration you can automatically upload scanned documents to Paperless

const options = { paths: ['/usr/lib/scanservjs'] };
const Process = require(require.resolve('./server/classes/process', options));

afterConfig(config) {
const pipelines = [
{
extension: 'pdf',
description: 'Paperless',
commands: [
'convert @- -quality 100 tmp-%04d.png && ls tmp-*.png',
'convert @- scan-0000.pdf',
'ls scan-*.*'
],
afterAction: 'Rename for paperless'
}
];

config.pipelines.splice(0, 0, ...pipelines);
},
actions: [
{
name: 'Rename for paperless',
async execute(fileInfo) {
return await Process.spawn(`mv '${fileInfo.fullname}' '${fileInfo.path}/pl_${fileInfo.name}'`);
}
}
]

Spin up the docker container

Now it’s finally time to setup our awesome scan server through docker.

You should read the documentation on github about this topic if you have any issues.

In the example command you should change the SANED_NET_HOSTS and AIRSCAN_DEVICES to fit the settings of your scanner. If you change the device id in the AIRSCAN_DEVICES variable you’ll need to adjust the provided configuration file.

I also deviated a bit from the suggested configuration changing the web port mapping. In my opinion it’s better to use the default web port, so that users can type the address of the server without specifying any port.

Docker command

docker run -d \
-e SANED_NET_HOSTS="192.168.0.70" \
-e AIRSCAN_DEVICES='"Hp Envy Pro 6442" = "http://192.168.0.70/eSCL"' \
-p 80:8080 \
-v /var/run/dbus:/var/run/dbus \
-v /docker/sane/config:/etc/scanservjs \
-v /docker/sane/images:/var/lib/scanservjs/output \
--restart unless-stopped \
--name scanservjs-container \
--privileged sbs20/scanservjs:latest

Docker compose

version: "3"
services:
scanservjs:
image: sbs20/scanservjs:latest
privileged: true
environment:
- UID=${UID}
- GID=${GID}
- SANED_NET_HOSTS=${SANED_NET_HOSTS}
- AIRSCAN_DEVICES=${AIRSCAN_DEVICES}
volumes:
- /docker/sane/images:/var/lib/scanservjs/output
- /docker/sane/config:/etc/scanservjs
- /var/run/dbus:/var/run/dbus
ports:
- ${WEB_PORT}:8080
restart: unless-stopped
scantopl:
image: ghcr.io/celedhrim/scantopl:master
environment:
- PLURL=http://paperless.instance
- PLTOKEN=paperless_token
volumes:
- /docker/sane/images:/output

Once you execute this command you’ve setup your own scan server !
This web interface is just awesome.

Screenshot of the scan server

Remarks

You could set up the scan server with multiple devices. If you have scanners from different manufacturers (or maybe different models) you will need to figure out the driver situation for each of them.

I also noted some issues with my particular scanner. When trying to scan with some resolutions my scanner would crash (that’s why I specified them in the configuration file). If you have a different device than mine you should make sure you test this.

Another issue that I found out is with the combination of scanner source and batch selection. By example if you choose the flatbed and the automatic batch selection the scanner would crash.
Choosing the ADF source with a manual batch selection will have the same effect. This is the only hurdle that I wasn’t able to figure out. This is not so user friendly since every time this happens the scanner needs to be restarted. If you figure this one out please let me know how figured this one out.

Further suggestions

Network scanner

Do you want to make your scans available over the network ?
Then you should need to map /docker/sane/images to a network share.
I won’t provide the detailed instructions since this write-up is already long enough. But I’ll give you some hints. (extra documentation)

sudo apt install smbclient -yq
sudo apt install cifs-utils
sudo nano /etc/fstab

#add this line to the fstab file
//fileserver/Scans /docker/sane/images/ cifs username=guest,iocharset=utf8,file_mode=0777,dir_mode=0777

sudo reboot

Setup print server

This is another write-up on its own and it might not be related to this topic.
But since you went to the trouble of setting up a scan server, you could also setup CUPS to have your own print server, which by the way is much easier than what we just did.

Setting up Portainer

Since we setup Docker we could also install Portainer to have a nice management interface for docker. You can find the official setup guide on this page.

If you have any remarks or suggestions please let me know …

--

--