Using Systemd to run Openwrt on Raspberry Pi 4...welcome to join

Can I install openwrt in some way to Rasbian for RPi 4 ?
I took a look at using LXC containers but seems the info is a little slim on instruction from openwrt site.

OpenWrt is a Linux distro... You need to wipe your current OS, or install it inside a container or virtual machine.

It seems like putting OpenWrt ext4 inside a directory and booting it with systemd-nspawn should be very easy, but I haven't tried it. but nspawn is basically like chroot but more powerful. give it a try and let us know!

This is a RPi, and all the operating system resides in a SD card, it's probably easier to swap cards than try to boot one OS from the other.

sure, but there are reasons to want more than one OS running on a single machine. Like you might want OpenWrt as a router, and some other distro as a file server, and a third as a real-time media server...

This was exactly my thoughts, I am just concerned with performance and heat. I will have to look up nspawn as im not familiar with it.
I have read some poor reviews about running VM on RPi. maybe they were referring to the older models as RPi4 is much improved.
In my scenario i wouldnt be able to swap SD cards as I need the routing implementation to stay up for internet service.
I read about Alpine linux running from RAM so that would be a good one but I am working from a Windows machine setting all this up and I havent been successful in writing it to a bootable image to storage to put on RPi. Any suggestions on this?
their community is on RCI and had no luck in previously joining this kind of chat.

It's a sort of chroot on steroids, designed specifically to make it easy to run a program or an entire OS image from a directory. Basically copy all the OpenWrt files into say /var/lib/machines/openwrt

Then suppose you have eth0 and eth1 that you want to give to openwrt to do routing with:

systemd-nspawn --boot --machine=openwrt --network-interface=eth0 --network-interface=eth1 --network-veth

that will move eth0 and eth1 into the openwrt namespace, and then create a veth pair so that the original host can communicate with openwrt (within openwrt you can bridge host0 into your lan bridge for example)

reading the man page you should be able to learn more about more advanced uses, but to test, you can try that at the command line...

If you connect to the host console, how can you get a shell in the container? I think:

machinectl login openwrt

should do it.

Please try it and report back how it works!

Also see this for more info:


EDIT, some info:

I had an image sitting around, so I losetup the image, mounted the / partition on /mnt/openwrtroot and tried this:

systemd-nspawn --directory=/mnt/openwrtroot --boot --network-veth --machine=openwrt /sbin/init

which gave me:

/etc/preinit: line 6: can't create /sys/devices/system/cpu/microcode/reload: Read-only file system
Press the [f] key and hit [enter] to enter failsafe mode
Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level
- failsafe -
Generating 1024 bit rsa key, this may take a while...
Public key portion is:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCS6iZhLnlHL1w5MP5NXgf//HG3wMCvlcyPEBVFr+7VB4ZJcvoe/fVHtxp+kItysqDX0qEOAw33IUFEER8/aVZMvp4ayP5IZEhdr2uwgWWTWk0ywmJgKyBLJ+B6KEgY5Q+bGj22pAtt27H9BBwiCRITQeFKCwgjKH33aD0y45YjDw== root@openwrt
Fingerprint: sha1!! c9:43:2c:35:13:3a:fb:af:79:ce:16:32:f9:81:97:d4:25:e0:16:b2

BusyBox v1.30.1 () built-in shell (ash)

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 OpenWrt 19.07.1, r10911-c155900f66
================= FAILSAFE MODE active ================
special commands:
* firstboot	     reset settings to factory defaults
* mount_root	 mount root-partition with config files

after mount_root:
* passwd			 change root's password
* /etc/config		    directory with config files

for more help see:
- failsafe_and_factory_reset
- root_password_reset

root@openwrt:/# exit

So, it looks like you want to do some modifications to the /etc/preinit script or something so it doesn't try to adjust filesystems that are read-only in the container... or some such thing.

anyway, after doing mount_root I was able to

root@openwrt:/# mount_root
root@openwrt:/# ls
bin         etc         lost+found  proc        run         tmp         www
boot        lib         mnt         rom         sbin        usr
dev         lib64       overlay     root        sys         var
root@openwrt:/# pwd
root@openwrt:/# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: host0@if9: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 2a:8e:a8:04:6a:22 brd ff:ff:ff:ff:ff:ff

So it looks basically feasible !

1 Like

Could I use a different architecture for this setup? Was hoping I could use a firmware from ROOter GoldenOrb as it is setup for modem configurations. They dont have one for RPi4 yet.

Thanks a million for the help. i am about to start working on this. may take me a little longer than you to tinker but i will update as i go.

working with Raspbian buster lite:

Each time I try to run systemd-nspawn I get the same results, no matter how i run command or put files in directory /var/lib/machines/Rooter

Directory /var/lib/machines/Rooter doesn't look like an OS root directory (os-release file is missing). Refusing.

Can you share with me what you do from start to where you launch container?
How do you have files in the directory?
Also tell me what img file you are using, if you can please provide download link to confirm.
I have the 1 folder contents uploaded(the usual root directories) to the /var/lib/machines/Rooter directory.

Made some changes and put rooter root files in /home/admin/root (users directory)

root@raspberrypi:/home/pi# systemd-nspawn --directory=/home/admin/root --boot --network-veth --machine=rooter /sbin/init

Spawning container rooter on /home/admin/root. Press ^] three times within 1s to kill container. execv(/usr/lib/systemd/systemd, /lib/systemd/systemd, /sbin/init) failed: Permission denied Container rooter failed with error code 1.

Tried some more: I was not mounting the img previously, going to try and stay with your example

root@raspberrypi:/home/admin# mount -o loop ./openwrt-19.07.2-x86-64-rootfs-ext4.img /mnt/openwrt
root@raspberrypi:/home/admin# systemd-nspawn --directory=/mnt/openwrt --boot --network-veth --machine=openwrt /sbin/init

Spawning container openwrt on /mnt/openwrt. Press ^] three times within 1s to kill container. execv(/usr/lib/systemd/systemd, /lib/systemd/systemd, /sbin/init) failed: Exec format error Container openwrt failed with error code 1.

run systemd-nspawn with sudo it needs root privileges to set up the container

getting the same result with adding sudo at beginning.

you can't loop mount the .img file because it's got multiple partitions on it. you need

losetup ./openwrt-19....
mount /dev/loop1p2 /mnt/openwrt

partition 1 is the boot partition which has essentially nothing on it. partition 2 is the / partition where the OS actually lives

Unsure what I am getting wrong

root@peppermint:/home/user/Documents# losetup ./openwrt-19.07.2-x86-64-rootfs-ext4.img
losetup: ./openwrt-19.07.2-x86-64-rootfs-ext4.img: failed to use device: No such device

if I attempt this in peppermint OS I get this seemed to site there for a minute so i aborted.

root@peppermint:/home/user/Documents# systemd-nspawn --directory=/mnt/openwrtroot --boot --network-veth --machine=openwrt /sbin/init
Spawning container openwrt on /mnt/openwrtroot.
Press ^] three times within 1s to kill container.
host's /etc/localtime is not a symlink, not updating container timezone.
Press the [f] key and hit [enter] to enter failsafe mode
Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level
Container openwrt is being rebooted.
Failed to correct access mode for TTY: Read-only file system

Getting closer. I had the same situation you had in the second paste until I forced it to run /sbin/init, can you post the command line you used?

Hmm... yeah, I think you're at least at the point where you are getting the container set up, and init started... This is about as far as I got, I was able to get one step farther to a shell... but not sure how actually, pretty sure it was by specifying /sbin/init on the command line, but you're doing that already. I was using x86 to test.

This is where some experimentation and some knowledge of the boot process might help:

you might need to actually do /etc/preinit instead of /sbin/init

you might also need to edit preinit to skip certain things that don't apply in the container. I don't know what those would be though.

maybe remove the --boot option and just start /sbin/init directly, thereby skipping some of the set-up stuff that isn't relevant to the container?

I have been trying some things from this site as well:

just posted some outcomes to to person who as been using it in Raspbian.
maybe you can light of some of it.

some research updates.
found this project and seems to show the ability to run a 32bit OS on 64 bit RPi4 .
Here is github and RPi forum thread.

you can look up this sakaki guy who has done lots of nspawn projects.
Gonna try the github image to see if I can start up a openwrt machine in 32 bit

Got a reply from github account that supports systemd-nspawn

$ ls -al /etc/localtime
lrwxrwxrwx. 1 root root 23 Dec  1  2017 /etc/localtime -> /usr/share/zoneinfo/UTC

If you see this...

$ ls -al /etc/localtime
lrwxrwxrwx. 1 root root 23 Dec  1  2017 /etc/localtime

try this...

$ cp /etc/localtime ~/localtime.backup
$ rm /etc/localtime
$ ln -s /usr/share/zoneinfo/UTC /etc/localtime

new error return, I commented back to see if he could help further.

Timezone UTC does not exist in container, not updating container timezone.


This is being run off the raspbian-nspawn-64.img from the thread above.
I believe the underlying issue was that I was running on 64 bit but the images were 32bit.

*******This maybe premature, but I am about to shit my pants!!!

root@raspberrypi:/home/pi# ls
root@raspberrypi:/home/pi# ls /mnt/
root@raspberrypi:/home/pi# mkdri /mnt/openwrtroot
bash: mkdri: command not found
root@raspberrypi:/home/pi# mkdir /mnt/openwrtroot
root@raspberrypi:/home/pi# ls /var/lib/machines/
root@raspberrypi:/home/pi# mkdir /var/lib/machines/openwrt
root@raspberrypi:/home/pi# mount openwrt-19.07.2-brcm2708-bcm2710-rpi-3-ext4-factory.img /mnt/openwrtroot/
mount: /mnt/openwrtroot: wrong fs type, bad option, bad superblock on /dev/loop0, missing codepage or helper program, or other error.
root@raspberrypi:/home/pi# losetup --show -P -f openwrt-19.07.2-brcm2708-bcm2710-rpi-3-ext4-factory.img
root@raspberrypi:/home/pi# ls /dev/loop0*
/dev/loop0  /dev/loop0p1  /dev/loop0p2
root@raspberrypi:/home/pi# mount -v /dev/loop0p2 /mnt/openwrtroot/
mount: /dev/loop0p2 mounted on /mnt/openwrtroot.
root@raspberrypi:/home/pi# mount -v /dev/loop0p1 /mnt/openwrtroot/boot
mount: /mnt/openwrtroot/boot: mount point does not exist.
root@raspberrypi:/home/pi# mkdir /mnt/openwrtroot/boot
root@raspberrypi:/home/pi# mount -v /dev/loop0p1 /mnt/openwrtroot/boot
mount: /dev/loop0p1 mounted on /mnt/openwrtroot/boot.
root@raspberrypi:/home/pi# sudo systemd-nspawn --directory=/mnt/openwrtroot/
Spawning container openwrtroot on /mnt/openwrtroot.
Press ^] three times within 1s to kill container.

BusyBox v1.30.1 () built-in shell (ash)

-sh: can't access tty; job control turned off
  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 OpenWrt 19.07.2, r10947-65030d81f3
=== WARNING! =====================================
There is no root password defined on this device!
Use the "passwd" command to set up a new password
in order to prevent unauthorized SSH logins.
1 Like

That looks exceedingly excellent. You now probably need to learn some stuff about the various options to supply networking devices to the container. My suggestion would be to move the "real" devices into the container, and provide a veth to the host so the host can be on the LAN, behind the firewall.

Assuming you have a USB external ethernet, so that there's eth0 and eth1, I think that would be via something like

systemd-nspawn --directory=/mnt/openwrtroot --network-interface=eth0 --network-interface=eth1 --network-veth

so i restarted the terminal bc it got locked in an empty place.
I have 3 active machines

I ran your command and got kicked out of terminal. lol
maybe should of configured dhcp on the openwrt machine.

Will have to make a run to the store and grab a hdmi micro cable. was trying to avoid . ~blah

Ah, yes of course if you've sshed into the machine, then when you move the ethernet device over to the container.... wham you have no internet.

The best way is probably to set up the host so that when it boots, it has a bridge br-host with a static IP for example, and having eth0 in the bridge. When you do the nspawn, have it bridge the veth into that bridge

systemd-nspawn --directory=/mnt/openwrtroot --network-interface=eth0 --network-interface=eth1 --network-bridge=br-host

You'll have a second or so of interruption but be back to normal after openwrt boots.

Does that make sense? to set up the bridge on raspbian you need to edit files in /etc/systemd/network to create the bridge with a .netdev file and set up the ip address and routing etc with a .network file.