I’m currently trying to setup a Raspberry Pi with USB ethernet to connect to it from an iPad over USB-C.
There are various articles about this but I got a bit stuck.
My config currently lives here:
And it’s mostly inspired by the config from @maxhbr
I currently have two issues:
The interface usb0 doesn’t show up
dhcpd4 doesn’t start, I get the same error message as described in this issue but I reckon the problem is that the interface doesn’t show up
In addition I’m unsure about the following script, most of the articles implement this in some form and I don’t really know how to implement it in NixOS.
Using it 1:1 didn’t work.
I have no experience with usb gadget mode, but I am curious, so I started digging into this a bit.
My first question is how do you “enable the libcomposite driver” (/etc/modules/libcomposite) as described in sausheong’s article?
I do not know how that works, but I expect it is related to the nixos dwc2 option. The option’s help text suggests how to verify gadget mode is working. Possibly the kernel module needed for an ethernet gadget is not loaded.
I’d have to dig deeper into kernel docs to figure out more details – maybe you can if you do not already know enough. I would like to learn how to make this work.
That script is mostly creating a directory containing a bunch of files with specific content. Then it tells the OS to use the dir. You could create a nix package to “build” the directory tree as a nix store entry, and tell the OS to use it in the “install” phase. It sure would be nice if someone has already done this for nix, but maybe it has to be you.
Good point I haven’t seen this yet, might be a piece of the puzzle.
As for the script, I don’t mind trying to package it, but shouldn’t it be working manually as well if a package is possible?
If not I’m not sure what is missing besides correcting the shebang.
It depends. The script is using the filesystem to tell the OS how to configure a particular feature. But NixOS typically feeds custom paths to OS tools. I’d try to understand how the script is supposed to work and then verify that is compatible with how nix configures the relevant OS bits (or adjust the script accordingly).
Ideally the tools involved in the script would report useful diagnostic info if the inputs from the script do not work. Do you see any relevant console output when running the script? Any relevant output in the journal?
In this case, the relevant tool is udev. The script creates the directory /sys/kernel/config/usb_gadget/pi4 and populates it with config parameters. Then it calls udevadm settle. Then adds another file, UDC, to pi4, and finally activates the new network interface with ifup.
I do not know linux well enough to know how /sys/kernel/config/ works without reading kernel docs. I don’t know NixOS well enough to know how it uses or supports /sys/kernel/config/. This directory is empty on my system.
Also, /sys/class/udc does not exist on my system. If udc is generally about USB or network devices, I’d expect it to be present if NixOS supports it. That’s another bit to find in the kernel docs.
I found this article on usb gadget configfs informative. It describes what your script is doing. Notice the instructions begin with modprobe libcomposite which implies boot.kernelModules = [ "libcomposite" ]; for NixOS. But maybe that module is included by default and explicitly listing it does nothing.
I am not sure how linux configfs fits with NixOS, or even how to use it, so I read a bit of the configfs kernel docs. Using findmnt I see that NixOS mounts configfs at /sys/kernel/config/. Mine is empty until I run sudo modprobe libcomposite, which creates the usb_gadgets dir. Now cd /sys/kernel/config/usb_gadget/ works. Maybe that NixOS boot.kernelModules entry actually is necessary.
You’re absolutely fantastic!
I got it working now. You’re right the module libcomposite was the missing piece and makes the usb_gadget directory appear.
If adapted the script slightly (full paths and restarting the relevant services at the end).
Wrapping everything into a systemd service should be easy now.
Here’s the config for the pi as a minimal working example:
For anyone copying this, please be aware that the { custom, hostname }: part is very much non standard.
I notice that you include networks.psk in your config. Isn’t that supposed to be secret? (I keep mine in local files outside the nix store.)
Also, your network uses top-level-domain .local. .local is reserved for use by mdns (such as with avahi). Its resolution by regular DNS depends on how the resolver is configured. I’ve encountered problems with such a configuration when mDNS is not running, particularly in recently upgraded Microsoft networks. The Wikipedia article on .local has more details.
You can pick or makeup any other TLD you want. .lan has been commonly used for local networks for decades. Just know that whatever you choose may shadow Internet access to that TLD – useful if you want to avoid resolving hosts in particular TLDs.
You’re absolutely right, however since it’s the hotspot from my phone I don’t really care too much.
Ideally I would use age to encrypt the password or file but I don’t had more time to extend it.
And right again, I just have used .local for years and so far have been to lazy to change it.
Thank you for the suggestion of .lan, I wasn’t sure what I should pick instead.
Hi @Nebucatnetzer@ericgundrum I was just looking for a similar solution and glad it worked for you, I’ll have a look into this in depth but it seems complex. I think OS images built with “nixos-hardware” on raspberry pis should have this behavior/usb gadget mode on by default.
The whole hardware stuff in general is complex.
I personally stopped using nixos-hardware because it broke my setup with 23.05 and I still continue understand the reason.
It could be working again but since I can achieve my configuration without it, I won’t readd it for the moment.