Setup Brother scanner ADS-1800W

I thought it is enough to check for the scanner having linux support by the manufacturer and NixOS having the drivers available. But after following wiki and the options I only get it running on eSCL, but not as as brother5: device.

Disabling eSCL with hardware.sane.disabledDefaultBackends = [ "escl" ]; results in no scanners detected.

What I included:

  hardware.sane = {
    enable = true;
    brscan5 = { 
      enable = true; 
      netDevices = {
        ADS-1800W = {
          name = "Brother";
          model = "ADS-1800W";
          ip = "192.168.188.50";
        };
      };
    };
  };
  users.users."${username}".extraGroups = [ "networkmanager" "wheel" "plugdev" "scanner" "lp" ];

This causes the config file being created where brsaneconfig5 does not allow to create a config file manually due to the systemic read only limitation:

$ cat /etc/opt/brother/scanner/brscan5/brsanenetdevice.cfg
DEVICE=Brother , "ADS-1800W" , 0x4f9:0x708 , IP-ADDRESS=192.168.188.50 , FLAG=

So I get it running via network, but not via USB yet. The device is recognised on USB:

$ lsusb|grep -i brother
Bus 001 Device 043: ID 04f9:0708 Brother Industries, Ltd ADS-1800W

But scanimage -L only lists it when connected via network, and also not with prefix brother5, but escl only.

I just would like to have the option to scan to the device directly with Duplex and maybe more options. Currently I can scan a single page only and have to set measurements to not end up with a rather long empty picture of air; meaning it’d defeat the purpose of the scanner to handle each sheet of paper twice to scan both sides.

For people considering the device: My current fallback is scanning to USB storage on the printer directly and using the USB (also delivering power for the device that came without a PSU) from my device to handle the files.. also it is possible to scan to E-Mail, Filehosters (e.g. Dropbox) or FTP/SFTP/SharePoint.

Has anyone any ideas how to get this working properly, what am I missing or doing wrong?

Thanks for sharing your config. I have the same scanner configured to send everything to my paperless server through SFTP. It is not pretty as I have to force RSA ssh host keys for that, but it works (flake module below for reference)

{ lib, ... }:
{
  flake.nixosModules.paperless =
    # Ref.: https://github.com/Mic92/dotfiles/blob/0956f80d1752b2c82d44c4ce22f70140e50e8fbb/machines/eve/modules/paperless.nix
    {
      config,
      pkgs,
      ...
    }:
    let
      cfg = config.rcouto.services.paperless;
    in
    {
      imports = [ ];

      options = {
        rcouto.services.paperless.enable = lib.mkEnableOption "enables paperless";
        rcouto.services.paperless.domain = lib.mkOption { type = lib.types.str; };
        rcouto.services.paperless.listenIface = lib.mkOption { type = lib.types.str; };
      };

      config = lib.mkIf cfg.enable (
        let
          domain = cfg.domain;
          listenIface = cfg.listenIface;
        in
        {
          services.paperless = {
            enable = true;
            address = "127.0.0.1";
            port = 28981;
            dataDir = "/var/lib/paperless";
            mediaDir = "/var/lib/paperless/media";
            consumptionDir = "/var/lib/paperless/consume";
            consumptionDirIsPublic = true;
            configureTika = true;
            passwordFile = config.clan.core.vars.generators.paperless.files.paperless-admin-password.path;
            settings = {
              PAPERLESS_DBHOST = "/run/postgresql";
              PAPERLESS_DBNAME = "paperless";
              PAPERLESS_DBUSER = "paperless";
              PAPERLESS_SECRET_KEY = config.clan.core.vars.generators.paperless.files.paperless-secret-key.path;
              PAPERLESS_ADMIN_USER = "admin";
              PAPERLESS_ADMIN_MAIL = "xxxxx@xxxxx.com";
              PAPERLESS_OCR_LANGUAGE = "eng+fra+ltz+por+deu";
              PAPERLESS_TIME_ZONE = "Europe/Luxembourg";
              PAPERLESS_TASK_WORKERS = 2;
              PAPERLESS_THREADS_PER_WORKER = 1;
              PAPERLESS_WEBSERVER_WORKERS = 2;
              PAPERLESS_CONSUMER_RECURSIVE = true;
              PAPERLESS_CONSUMER_IGNORE_PATTERN = [
                ".DS_STORE/*"
                "desktop.ini"
                "Thumbs.db"
              ];
              PAPERLESS_FILENAME_FORMAT = "{{ created_year }}/{{ correspondent }}/{{ title }}";
              PAPERLESS_FILENAME_FORMAT_REMOVE_NONE = true;
              PAPERLESS_ALLOWED_HOSTS = "127.0.0.1,${domain}";
              PAPERLESS_CORS_ALLOWED_HOSTS = "https://${domain}";
              PAPERLESS_CSRF_TRUSTED_ORIGINS = "https://${domain}";
              PAPERLESS_TIKA_GOTENBERG_ENDPOINT = "https://127.0.0.1:${builtins.toString config.services.gotenberg.port}";
            };
          };
          services.gotenberg.port = 28982;
          clan.core.vars.generators.paperless = {
            prompts.paperless-scanner-prompt = {
              description = "paperless scanner password";
              display.helperText = ''
                Run xkcdpass -n 3 -d - and save to 1Password
              '';
              type = "hidden";
              persist = false;
            };
            files.paperless-admin-password = {
              secret = true;
            };
            files.paperless-secret-key = {
              secret = true;
            };
            files.paperless-scanner-password = {
              secret = true;
            };
            runtimeInputs = [
              pkgs.openssl
              pkgs.xkcdpass
              pkgs.mkpasswd
            ];
            script = ''
              xkcdpass -n 3 -d - | tr -d '\n' > $out/paperless-admin-password
              cat $prompts/paperless-scanner-prompt | mkpasswd --method=SHA-512 --stdin | tr -d '\n' > $out/paperless-scanner-password
              openssl rand -hex 32 | tr -d '\n' > $out/paperless-secret-key
            '';
          };
          # Scanner user
          users.users.scanner = {
            description = "scanner sftp client user";
            group = "paperless";
            home = "/var/lib/sftp/scanner";
            createHome = true;
            isSystemUser = true;
            isNormalUser = false;
            shell = "${pkgs.shadow}/bin/nologin";
            hashedPasswordFile =
              config.clan.core.vars.generators.paperless.files.paperless-scanner-password.path;
          };
          # Enabling postgresql
          rcouto.services.postgresl = {
            enable = true;
            databasesForBackup = [ "paperless" ];
          };
          services.postgresql.ensureDatabases = [ "paperless" ];
          services.postgresql.ensureUsers = [
            {
              name = "paperless";
              ensureDBOwnership = true;
            }
          ];
          environment.persistence."/persist/system".directories =
            lib.mkIf config.rcouto.hosts.impermanence.enable
              [
                {
                  directory = "/var/lib/paperless";
                  user = "paperless";
                  group = "paperless";
                }
              ];
          clan.core.state.paperless = {
            folders = [ "/var/lib/paperless" ];
          };
          services.nginx = {
            enable = true;
            virtualHosts."${domain}" = {
              useACMEHost = "rcouto.org";
              forceSSL = true;
              locations."/" = {
                proxyPass = "http://127.0.0.1:${builtins.toString config.services.paperless.port}/";
                proxyWebsockets = true;
              };
            };
          };
          networking.firewall.interfaces."${listenIface}".allowedTCPPorts = [
            80
            443
          ];
        }
      );
    };
}

I will test the usb/network setup on my workstation in the weekend when I have more time and report my findings.

1 Like

If the scanner works with the escl backend and the network you may have luck enabling services.ipp-usb.enable which exposes an ipp scanner connected by usb as a local network scanner. If escl works but not fully satisfactorily, you can use the sane-airscan backed (to be added as extraBackends) instead.

1 Like

Indeed, with

  hardware.sane = {
    enable = true;
    extraBackends = [ pkgs.brscan5 pkgs.sane-airscan ];
  …
  services.ipp-usb.enable = true;
  #services.udev.packages = [ pkgs.sane-airscan ]; # this seems to have no effect at all

I get

$ scanimage -L
device `escl:http://localhost:60000' is a Brother ADS-1800W (USB) adf scanner

and a different set of options for scanimage:

$ scanimage -d "escl:http://localhost:60000" --help
Usage: scanimage [OPTION]...

Start image acquisition on a scanner device and write image data to
standard output.

Parameters are separated by a blank from single-character options (e.g.
-d epson) and by a "=" from multi-character options (e.g. --device-name=epson).
-d, --device-name=DEVICE   use a given scanner device (e.g. hp:/dev/scanner)
    --format=pnm|tiff|png|jpeg|pdf  file format of output file
-i, --icc-profile=PROFILE  include this ICC profile into TIFF file
-L, --list-devices         show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
                           can be specified: %d (device name), %v (vendor),
                           %m (model), %t (type), %i (index number), and
                           %n (newline)
-b, --batch[=FORMAT]       working in batch mode, FORMAT is `out%d.pnm' `out%d.tif'
                           `out%d.png' or `out%d.jpg' by default depending on --format
                           This option is incompatible with --output-file.
    --batch-start=#        page number to start naming files with
    --batch-count=#        how many pages to scan in batch mode
    --batch-increment=#    increase page number in filename by #
    --batch-double         increment page number by two, same as
                           --batch-increment=2
    --batch-print          print image filenames to stdout
    --batch-prompt         ask for pressing a key before scanning a page
    --accept-md5-only      only accept authorization requests using md5
-p, --progress             print progress messages
-o, --output-file=PATH     save output to the given file instead of stdout.
                           This option is incompatible with --batch.
-n, --dont-scan            only set options, don't actually scan
-T, --test                 test backend thoroughly
-A, --all-options          list all available backend options
-h, --help                 display this help message and exit
-v, --verbose              give even more status messages
-B, --buffer-size=#        change input buffer size (in kB, default 32)
-V, --version              print version information
Output format is not set, using pnm as a default.

Again, this works for single page sheets with e.g. scanimage -v -d "escl:http://localhost:60000" --mode Gray --resolution 300 -x 210 -y 297 --format=tiff --batch=letter%d.tiff, the 2nd side per sheet is not handed over (same with simple-scan) and resulting in segmentation fault when I try to force it with --source ADF (I also tried other formats and mode to test if it maybe works):

$ scanimage -v -d "escl:http://localhost:60000" --source ADF --mode Color --resolution 300 -x 210 -y 297 --format=pdf --batch=letter%d.pdf 
Segmentation fault         (core dumped) scanimage -v -d "escl:http://localhost:60000" --source ADF --mode Color --resolution 300 -x 210 -y 297 --format=pdf --batch=letter%d.pdf

Don’t mind me.. but have you tried a gui ?

Sane Backends

Actual Homepage

I do mind and am happy to try an application you have good experience with, IIRC you just linked one package that AFAIK is used with the options above. After all NixOS has the nice advantage that one can easily try yet another program without screwing up a whole system …
Also, do you manage packages with a GUI as well? I still am trying them with nix-shell -p packagename before adding any to my configuration.

You’re right, I did. I mentioned simple-scan before for a few reasons. First thing I tried was xscanimage from sane-frontends, it just scrashes with segmentation fault not showing the GUI at all. When I tried paperwork it does seem to assume flatbed scanners only (as in calibrartion doesnt do for the document scanner here) and fails to provide settings for papersize. I also tried e.g. gscan2pdf, which unfortunately crashes when configured to scan duplex with lots of selections in a tabbed setting dialogue that would need quite some screenshots to display the same options I can just paste in a command line.

So my reasoning to use CLI is mainly: That is what makes enables others to follow the steps and maybe point out things, it enables to show the actual error that occurs and behind the GUI those CLI tools are what make them run. Glad to learn how to do it with a GUI instead.

Got it..

Let other’s chime in then..

Hope it gets fixed.. Watching it closely

airsane is supposed to support all the devices that escl supports, so scanimage -L returning only an escl device is weird. Have you rebooted after you changed you config? At some point in the past hot-swapping sane configuration would not work, I am not sure it is it still the case.

It is also not normal that scanimage segfaults while scanning. Ideally you would open an issue upstream with a stacktrace, which can be obtained as follows:

  • rebuild with the following options
  { 
hardware.sane.backends-package = pkgs.sane-backends.overrideAttrs { separateDebugInfo = true; }; 
systemd.coredump.enable = true;
services.nixseparatedebuginfod2.enable = true;
}
  • reproduce the segfault
  • run coredumpctl gdb
  • in the gdb prompt thread apply all bt

The output of thread apply all bt would likely help in an issue upstream.