Creating a new file under /etc

I’m trying to configure a network-connected scanner so:

environment.etc."sane-config/samsung.conf" = {
	text = ''
		tcp SEC30CDA71BCDB2.landcroft.net
	'';
	mode = "0440";
};

but with 24.05 that leads to

[root@elsinor:~]# nixos-rebuild switch 
building Nix...
building the system configuration...
these 2 derivations will be built:
  /nix/store/rvw6vbss3hkf70x65jlcnaliadwqsdrl-etc.drv
  /nix/store/zn34r0v9glvwnrnbihsf46m5aa52zffj-nixos-system-elsinor-24.05.6206.d063c1dd113c.drv
building '/nix/store/rvw6vbss3hkf70x65jlcnaliadwqsdrl-etc.drv'...
ln: failed to create symbolic link '/nix/store/q1qs6zdkdzbbg4n96iljr75ibdyqngmj-etc/etc/sane-config/samsung.conf': Permission denied
error: builder for '/nix/store/rvw6vbss3hkf70x65jlcnaliadwqsdrl-etc.drv' failed with exit code 1
error: 1 dependencies of derivation '/nix/store/zn34r0v9glvwnrnbihsf46m5aa52zffj-nixos-system-elsinor-24.05.6206.d063c1dd113c.drv' failed to build

What now?

use sudo (extra words to get past the 20 char limit)

EDIT: missed that the command was issued by root :shame:

Hi,

the error is because your file conflicts with the fact that the SANE nixos module manages the full /etc/sane.d folder. You have to go through the interface of the module to inject your configuration file. A variation of this should work:

{ config, pkgs, lib, ... }: {
    hardware.sane.extraBackends = [
      (pkgs.writeTextFile {
        name = "whatever";
        text = ''
        tcp SEC30CDA71BCDB2.landcroft.net
        '';
        destination = "/etc/sane.d/samsung.conf";
      }) ];

}
1 Like

Thanks for the reply but

hardware.sane.extraBackends = [
	(pkgs.writeTextFile {
		name = "Samsung net config.";
		text = ''
			tcp SEC30CDA71BCDB2.landcroft.net
		'';
		destination = "/etc/sane-config/samsung.conf";
	})
];

is entirely ignored by nixos-rebuild. grep -rw tcp /etc outputs only /etc/nixos/configuration.nix.

grep does not seem to follow symlinks enough:

$  cat /etc/sane-config/abaton.conf 
scsi ABATON
/dev/scanner
                                                                                                                                                                                             
~ 
$  grep -rw ABATON /etc/
grep: /etc/NetworkManager/system-connections: Permission denied
grep: /etc/fwupd/fwupd.conf: Permission denied
grep: /etc/lvm/archive: Permission denied
grep: /etc/lvm/backup: Permission denied
grep: /etc/ssh/ssh_host_rsa_key: Permission denied
grep: /etc/ssh/ssh_host_ed25519_key: Permission denied
grep: /etc/ipsec.d: Permission denied
grep: /etc/.pwd.lock: Permission denied
grep: /etc/shadow: Permission denied
grep: /etc/sudoers: Permission denied
                                        
[root@elsinor:~]# ls -ltr /etc/sane-config
lrwxrwxrwx 1 root root 23 Nov 20 07:02 /etc/sane-config -> /etc/static/sane-config

so grep -rw tcp /etc would find samsung.conf, if it had been created.

Also you changed destination = "/etc/sane.d/samsung.conf"; to destination = "/etc/sane-config/samsung.conf"; but this is not correct. Have a look at the layout of the sane package:

nix-shell -p sane-backends --run 'tree $buildInputs/etc'

Hmm. I have /etc/sane-config but /etc/sane.d does not exist on my system. Now I am puzzled.

The nixos module collects the contents of all the sane backends’ etc/sane.d/ directories and make a symlink to the result at /etc/sane-config. As you are providing a backend, the file must be at /nix/store/whatever/etc/sane.d

Yes.

grep -rw SEC30CDA71BCDB2.landcroft.net /nix/store/

lists several files (since I ran nixos-rebuild many times) but nothing under /etc so the problem is how to get nixos-rebuild to symlink to the file it has created under /nix/store.

Hi,

can you copy paste exactly the config that I gave you without editing it and confirm that it works ?

I confirned that it works with a nixos test so Im positive it will work for you.

diff --git a/nixos/tests/sane.nix b/nixos/tests/sane.nix
index cba1b4d1dc4d..234b1de06c7f 100644
--- a/nixos/tests/sane.nix
+++ b/nixos/tests/sane.nix
@@ -51,6 +51,14 @@ in
       serviceConfig.ExecStart = [ "${pkgs.ffmpeg}/bin/ffmpeg -framerate 30 -re -stream_loop -1 -i ${image} -f v4l2 -pix_fmt gray /dev/video0" ];
     };
     hardware.sane.enable = true;
+    hardware.sane.extraBackends = [
+      (pkgs.writeTextFile {
+        name = "whatever";
+        text = ''
+        tcp SEC30CDA71BCDB2.landcroft.net
+        '';
+        destination = "/etc/sane.d/samsung.conf";
+      }) ];
     system.extraDependencies = [ image ];
     environment.systemPackages = [
       pkgs.fswebcam
@@ -63,6 +71,8 @@ in
     start_all()
     machine.wait_for_unit("fake-webcam.service")
 
+    machine.succeed("grep landcroft /etc/sane-config/samsung.conf")
+
     # the device only appears when ffmpeg starts producing frames
     machine.wait_until_succeeds("scanimage -L | grep /dev/video0")
 

It’s working now thank you.

I don’t know what I was doing wrong before but I took care to copy the hardware.sane.extraBackends extract verbatim and now it works.

The problem now is that the scanner was turned off when the PC was booted and I can’t see how to make SANE realise that the scanner is now on. sane-find-scanner doesn’t do it and nor does scanimage -L.

ping SEC30CDA71BCDB2.landcroft.net works.

I don’t find any trace of a sane-samsung backend. http://www.sane-project.org/sane-backends.html
What backend are you trying to configure with this samsung.conf file?

Originally my change was in xerox_mfp.conf. I guess I have to modify / append-to that file rather than create samsung.conf. How do I do that?

Yes you need to keep the filename mentioned in man sane-xerox_mfp.
I don’t think you can append to it, but replacing the file should be doable by replacing samsung.conf by xerox_mfp.conf in the code snippet. If it complains about collision you can use lib.hiPrio to make your version of the file win over the default one.

Brilliant, thanks; I changed the name as you advised, and it replaced xerox_mfp.conf without complaint and I can scan. Thank you!