The Raspberry Pi Zero 2 W can act as a USB Ethernet device when connected to a host computer. This allows you to create a fully isolated, point‑to‑point network link over USB — perfect for headless access, provisioning, or embedded projects.
Raspberry Pi OS Bookworm introduced changes to the boot partition layout and USB subsystem, so older tutorials no longer work. This guide shows the correct, modern procedure for Bookworm (2023+), including how to:
- Power and boot the Pi from the USB data port
- Enable USB gadget mode
- Expose a USB Ethernet interface to the host
- Assign the Pi a static IP
- Run a DHCP server so the host receives an IP automatically
- Use a clean CGNAT /30 network for isolation
Everything below has been tested on Raspberry Pi OS Bookworm with kernel 6.12.
1. Hardware Setup
The Pi Zero 2 W has two micro‑USB ports:
- USB (inner port): data + OTG
- PWR IN (outer port): power only
For gadget mode, always connect the host to the USB port.
A data‑capable micro‑USB cable is required. Many cables are charge‑only and will not work.
2. Enable USB Gadget Mode (Bookworm Paths)
Bookworm moved all boot configuration files to:
Code
/boot/firmware/
Edit /boot/firmware/config.txt
Add the following inside the [all] section:
Code
dtoverlay=dwc2,dr_mode=peripheral
The dr_mode=peripheral parameter is mandatory on Bookworm for the Pi Zero family. Without it, the Pi stays in host mode and the USB gadget will never enumerate.
Edit /boot/firmware/cmdline.txt
This file must remain a single line.
Insert the module load directive after rootwait:
Code
modules-load=dwc2,g_ether
Example:
Code
console=serial0,115200 console=tty1 root=PARTUUID=XXXX rootfstype=ext4 fsck.repair=yes rootwait modules-load=dwc2,g_ether quiet splash
This loads:
dwc2— USB OTG controllerg_ether— USB Ethernet gadget
3. Configure the USB Network Interface on the Pi
Bookworm defaults to NetworkManager, but systemd‑networkd is the cleanest way to manage gadget interfaces.
Enable systemd‑networkd
Code
sudo systemctl enable systemd-networkd
sudo systemctl start systemd-networkd
Tell NetworkManager to ignore usb0
Create:
Code
/etc/NetworkManager/conf.d/10-ignore-usb0.conf
Contents:
Code
[keyfile]
unmanaged-devices=interface-name:usb0
Restart NM:
Code
sudo systemctl restart NetworkManager
4. Assign a Static IP and Enable DHCP Server
Use a small CGNAT /30 block for a clean point‑to‑point link. Example network: 100.64.64.64/30
- Pi:
100.64.64.65 - Host:
100.64.64.66
Create /etc/systemd/network/usb0.network
Code
[Match]
Name=usb0
[Network]
Address=100.64.64.65/30
DHCPServer=yes
Create /etc/systemd/network/usb0.dhcpserver
Code
[DHCPServer]
PoolOffset=1
PoolSize=1
DefaultLeaseTimeSec=600
MaxLeaseTimeSec=3600
EmitDNS=no
Restart networkd:
Code
sudo systemctl restart systemd-networkd
After reboot, the Pi will bring up usb0 with the static IP and run a DHCP server for the host.
5. Connect the Pi to the Host
Plug the Pi’s USB port into the host using a data‑capable cable.
On Linux/macOS/Windows, a new USB Ethernet interface will appear:
- Linux:
enx… - macOS:
enX - Windows: “RNDIS/Ethernet Gadget”
The host will receive:
Code
100.64.64.66
The Pi remains reachable at:
Code
100.64.64.65
You can now SSH over USB:
Code
ssh pi@100.64.64.65
6. Routing Behavior on the Host
The Pi’s DHCP server assigns a high metric (e.g., 20100) to the USB default route. This ensures the host prefers its normal network (Wi‑Fi/Ethernet) and only uses the Pi as a fallback.
Example routing table:
Code
default via 172.19.19.1 dev wlp3s0 metric 600
default via 100.64.64.65 dev enx... metric 20100
100.64.64.64/30 dev enx... scope link
This is expected and correct.
7. Result
You now have a fully functional, deterministic USB Ethernet gadget setup on Raspberry Pi OS Bookworm:
- Pi boots from the USB data port
- Pi exposes a USB Ethernet interface
- Pi has a static IP
- Host receives an IP via DHCP
- Clean CGNAT /30 network
- No interference from NetworkManager
- Works on Linux, macOS, and Windows
This setup is ideal for embedded deployments, provisioning, or secure out‑of‑band access.