Published: 20191222
Updated: 20191225 (Added DHCP server)
Updated: 20191226 (Added IPv6 settings)

Hardware: Raspberry Pi Zero or Raspberry Pi 4 Model B
Software: Raspbian Buster
And: Pop!_OS 19.04 64bit (Ubuntu)

Hardware tested
Automate things by installing a DHCPv4 server
Adding IPv6


Here's the idea...

I have way to many Raspberry Pi Zero at home, doing nothing, sitting in a box. And I mean the basic model, the cheapest one, the one completely without a network interface. I know I can use a USB WiFi stick or a USB Ethernet Adapter but they cost even more than the RPi (Raspberry Pi) I'm using. There should be a cheaper way to network these boards, without having to spend money on a PSU and USB network adapter.

So, some of the RPi models have the ability to work as USB gadgets. This means that they have a USB port that can receive power at the same time as it is receiving and transmitting data. The idea is that you make some smart software and put it on your RPi, maybe put the RPi in a neat box and just have a USB cable between your little box and the computer/device you want it to connect to.

In this write up I'm gonna show how to get Ethernet working over USB.
You need a "host" computer, a compatible RPi and a USB cable.

  1. Install Raspbian on your device.

    I trust that you can do this yourself. Also, it might be a good idea having the SSH server enabled on your RPi.

  2. Enable gadget mode on the RPi.

    Edit the file /boot/config.txt by making sure this line is in there:


    Edit the file /boot/cmdline.txt by putting this text in the right place. This file is only one single long line, so be careful.
    Right after rootwait you put in this text:


    As an example: on my RPi Zero the file looks like this:

    dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline rootwait modules-load=dwc2,g_ether quiet splash plymouth.ignore-serial-consoles

    The changes will be active next time you boot your RPi.

  3. Configure network on your RPi (and probably your PC too!)

    Right now, when you connect the cable between your RPi and your PC, it will power up the RPi. Both computers will have a new Ethernet interface between them. On the RPi it is called usb0 and probably it is called usb0 on your PC too. You can check "dmesg" on the PC to see what happens. If nothing happens, you might need to activate the funtionality with: modprobe g_ether, or you are unlucky like me and see that it registers usb0 and then renames it to something like enp0s20u2u2u2. *sigh*

    This Ethernet interface doesn't have subnet yet, you need to configure this network. There are different ways of doing this. You can do it manually, with DHCP, with RNDIS (but why?!) or probably some other method.

    This network is isolated from other networks. That means that it is it's own segment and it needs it's own subnet. So I'm just gonna manually set up the with static addresses. On the PC I will either configure the USB interface enp0s20u2u2u2 via the GUI or I do some CLI like:

    # ip ad ad dev enp0s20u2u2u2
    # ip link set dev enp0s20u2u2u2 up

    On the RPi I edit the file /etc/dhcpcd.conf and add these two lines:

    interface usb0
    static ip_address=

    Do note that the USB interface on the PC only comes up after it is connected. It will always have the same name when connected to the same device (your PC). This means that manual CLI stuff like I did above only works after the RPi has booted. If you configure your PC via Network Manager or similar it may be more stable for the next time you connect.

  4. Using your network

    So after you've connected your RPi Zero with a USB cable and made sure that you can reach it via network, what more is there? Well, SSH makes a lot of sense to have enabled.

    x2x works as well, if you want to connect the RPi to a monitor.

    As you might've figured out. This "gadget mode" kind of makes sense if you: Have your settings hardcoded into the textfiles on your RPi, configure a DHCP server on the RPi and when you connect it to a PC, the PC will catch the device and get network settings from it. You could have it as your own little Ethernet-USB-cable-NAS or make USB devices that reroute network traffic.

    Note! If you connect several RPi:s to the same PC, they will all be connected to your PC via unique USB Ethernet "interfaces". Which means they will not share subnets.

  5. Now to the fun stuff!


Hardware tested

Here's a list of all the hardware I've tested on:

Tested successfully on:
Raspberry Pi Zero (port marked "USB")
Raspberry Pi Zero W (port marked "USB")
Raspberry Pi 4 Model B (4GB model, via USB-C port)

It is highly likely that this will also work on:
Raspberry Pi Zero WH
Raspberry Pi 4 Model B (1GB model)
Raspberry Pi 4 Model B (2GB model)

Tested unsuccessfully on:
Raspberry Pi 1 Model A+
Raspberry Pi 3 Model A+

However... I did notice that these two models support "PSU hopping" with the USB micro PWR in and it's single USB Type A connector.

I don't think it will work on any other models.


Automate things by installing a DHCPv4 server

Manually setting network each time is tiresome.
It makes more sense to automize networking by having a small DHCP-server on the RPi.

On your Raspberry Pi:

  1. Add these two lines to /etc/dhcpcd.conf

    interface usb0
    static ip_address=
    static ip6_address=2001:db8::1/64
  2. Install the DHCP server

    # apt install isc-dhcp-server
  3. Configure the DHCP server

    Edit /etc/dhcp/dhcpd.conf to look like this:

    default-lease-time 1800;
    max-lease-time 7200;
    subnet netmask {

    Edit /etc/default/isc-dhcp-server and make sure this line is active:


    Edit /etc/dhcpcd.enter-hook and make sure this line is active:

    $ sudo systemctl restart isc-dhcp-server


Adding IPv6

On your Raspberry Pi:

  1. Install Router Advirtisement Daemon (RA)

    # apt install radvd
  2. Configure radvd

    Edit /etc/radvd.conf and make sure these lines are in there:

    interface usb0
      AdvSendAdvert on;
      prefix fc00::/64 {

    Enable radvd:

    # systemctl enable radvd
    # systemctl start radvd