OpenWRT is an open source firmware that can be loaded on many commercially available routers. The firmware offers an upgrade path for older or obsolete hardware and customization/advanced features for newer equipment.
With OpenWRT’s small footprint (176MB vs. 1.7GB Raspbian image), it’s ideal for older Raspberry hardware where speed and memory usage is an issue.
For small home and office projects OpenWRT will offer some interesting networking solutions, such as making the Pi into an access point or using it as a wireless LAN bridge. However it’s important to note that the Raspberry Pi WiFi hardware will not offer the same performance as you’ll find on dedicated routers.
In this blog I documented my notes on getting an old Raspberry Pi Model B up and running with OpenWRT. I also tried to explain how to install many of the common Pi functions (loading software, GPIO, I2C…)
Pro’s and Con’s
Before jumping into a Pi OpenWRT project it’s useful to know where it stands versus the default Raspberry Pi OS.
Some of the OpenWRT advantages (over Raspbian/Raspberry PI OS) include:
- It’s fast. It was designed to run on lower end CPU’s with limited memory
- Network focused
- Fast bootup
- Smaller OS footprint so even older 4 GB SD card be used (2GB is possible but may not be able to load many software packages).
Some OpenWRT limitations:
- No X-window desktop.
- System setup isn’t streamlined like the default Raspberry PI OS (there’s no raspi-config)
- Default installation is quite bare, so you need to manually load packages (even Bash and Nano)
- Some packages could be a challenge to install (for example Node-Red)
Getting Started
Despite the fact that OpenWRT is designed to run on routers, in many ways its easier to play with on a Raspberry Pi. Some of the benefits of using a PI are:
- you can’t ‘brick’ the Raspi. (I’ve come close many times playing with home routers)
- SD/microSD card have considerably more space than most home routers. (This was in issue for me with older routers).
- Pi has an HDMI connection so you can work directly on the PI (good for getting started)
For the OpenWRT Raspberry Pi Images see: https://openwrt.org/toh/raspberry_pi_foundation/raspberry_pi
You can use the standard Raspi imager to install OpenWRT on an SD card. For Linux systems the imager can be installed by:
sudo apt update && sudo apt install rpi-imager
After an SD card has been loaded up there are several way to get an OpenWRT system up and running. Below are the steps that I used.
1. Connect a monitor and keyboard to the Pi
Let it boot up and then go to the command prompt, and setup an static LAN address:
# Enter your own static IP. Note: change the gateway/DNS for your setup
uci set network.lan.proto="static"
uci set network.lan.ipaddr="192.168.0.140"
uci set network.lan.netmask="255.255.255.0"
uci set network.lan.gateway="192.168.0.1"
uci set network.lan.dns="192.168.0.1"
uci commit network
If you able to see IP addresses on your LAN you can simple do:
# Set Pi for DHCP and then check its address
uci set network.lan.proto="dhcp"
uci commit network
2. Hardwire Pi to Your LAN
Connect the 100BaseT port of the Pi to your LAN and then reboot the module.
From a laptop you now can use OpenWRT’s Web Interface or you can use the secure shell (ssh) command line interface.
I like the ssh option to get started because I can paste in groups of commands. To get started with ssh (with my static IP) :
$ ssh root@192.168.0.140
BusyBox v1.35.0 (2023-01-03 00:24:21 UTC) built-in shell (ash)
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
-----------------------------------------------------
OpenWrt 22.03.3, r20028-43d71ad93e
-----------------------------------------------------
=== 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.
--------------------------------------------------
root@OpenWrt:~#
3. Install Your Required Software
The default OpenWRT installation is extremely bare, so will probably need a number of basic packages.
OpenWRT uses opkg to install software. (Note: apt and apt-get are not supported in OpenWRT).
As a bare minimum I like to load:
# Install some software, but update list first
opkg update
# Install Bash, nano editor
opkg install bash nano
# For Python projects install the base Python3 and pip
opkg install python3 python3-pip
# For Pi GPIO projects
opkg install gpioctl-sysfs gpiod-tools
If you are planned to do some projects on your Raspberry Pi adding Bash, Python, and GPIO hardware support will be useful.
LuCI – OpenWRT Web Interface
After the system was up and running, the LuCI web interface can be used to setup other features such as networking interfaces and custom software. Many of the software packages also include additions to a LuCI web add-on.
From the LuCI interface you are easily see how much memory and disk space is available. It is important to check this screen if you’re planning on loading a large number of software packages.

Setup a USB WiFi Adapter
For Raspberry Pi models 3 and 4 OpenWRT will identify their built-in WiFi hardware, however for earlier models or projects where you want to use a USB WiFi adapter you’ll need to do this step.
On OpenWRT the configuring of USB devices has to be added manually. The first step is to install the USB utilities package:
# Update the package list
opkg update
# Add USB Utils (has lsusb)
opkg install usbutils
Once usbutils in added, the lsusb command will show information about the connected USB devices (Note: drivers still need to be loaded). For my Raspberry Pi B setup with an old Realtek WiFi adapter my output was:
root@OpenWrt_Pi1:~# lsusb
Bus 001 Device 004: ID 0bda:8189 Manufacturer_Realtek RTL8187B_WLAN_Adapter
Bus 001 Device 003: ID 0424:ec00
Bus 001 Device 002: ID 0424:9512
Bus 001 Device 001: ID 1d6b:0002 Linux 5.10.176 dwc_otg_hcd DWC OTG Controller
From this listing I can see that I need to search for a RTL8187B_WLAN_Adapter. The Luci Web Interface can be used to find and install the required network driver.

Once the USB WiFi adaptor is enabled, there are several different wireless arrangements that can be used, some of the more common setups would be:
- Wireless application node, (like a typically Raspberry Pi setup)
- Access point node, to setup your own custom network
- Wireless bridge, to extend an existing wireless network
For a simple wireless application node, go into the LuCI web interface Network->Wireless menu option, and then select your radio and scan for a wireless network. After a SSID (a wireless connection) is configured, select Edit to add the network information.

Ensure that you select both lan and wwan, by doing this you will be able to remotely access the Pi node via both wireless and wired connections.
Using SFTP and FileZilla
Remotely working a OpenWRT can be a little challenging if you are only using the SSH and Luci web interface. A Secure File Transfer Protocol (SFTP) server package can be used to greatly improve editing and saving of configuration and coding files.
The OpenSSH-FTP server package is installed by:
# For remote work add an SFTP server
opkg update
opkg install openssh-sftp-server
After this software has been loaded a graphical SFTP client package like FileZilla can be used on a laptop.
FileZilla allows for an easy visual interface for remote coding and maintenance. Below is an example of FileZilla connecting into an OpenWRT Raspberry Pi node. A file association on FileZilla has been setup to link py files to the basic Python Idle editor.

A Raspi 3 Example
I wanted to do a more complete Pi functions test. For this project I used Pi 3 because I wanted to test controlling the USB power. (Note: USB power control is only available on Pi 3 and 4).
My goal was to play with GPIO, I2C and USB power. In the final project I used OpenWRT’s built-in uhttpd web server to show the results.
Below are some of the individual steps that I did to get things running.
GPIO Setup
The base GPIO packages need to loaded:
# update list of available packages
opkg update
opkg install gpioctl-sysfs gpiod-tools
After the basic GPIO software is installed Raspberry Pi pin can be read to and written to in Bash (or ash which is the default OpenWRT shell).
Before a GPIO pin can be used it needs to defined. The tee command can be used to create a gpio definition with all the required files, for example:
# Create a gpio4 definition
echo 4 | tee /sys/class/gpio/export
# Show the file structure
ls /sys/class/gpio/gpio4
active_low direction power uevent
device edge subsystem value
A example to create a GPIO definition, then to write to the pin and read the value back is:
# Define the pin as an output
echo "out" > /sys/class/gpio/gpio4/direction
# Set the pin on (1)
echo 1 > /sys/class/gpio/gpio4/value
# Read the pin value
cat /sys/class/gpio/gpio4/value
1
If you are doing some playing around and you want to remove a gpio definition then write to the unexport file:
# Remove GPIO4
echo 4 | tee /sys/class/gpio/unexport
I2C Setup
To get the I2C setup working the Raspberry Pi I2C chipset driver and the I2C tools need to be loaded:
# Update the opk list. This needs to be done once after a power up
opkg update
opkg install kmod-i2c-bcm2835 i2c-tools
The next step is to edit the file: /boot/config.txt
nano /boot/config.txt
At the bottom on the file add three dtparam lines:
################################################################################
# Bootloader configuration - config.txt
################################################################################
################################################################################
# For overclocking and various other settings, see:
# https://www.raspberrypi.org/documentation/configuration/config-txt/README.md
################################################################################
# OpenWrt config
include distroconfig.txt
[all]
# Place your custom settings here.
dtparam=i2c1=on
dtparam=spi=on
dtparam=i2s=on
Once the file is edited the system needs to be rebooted. After this I2C devices can be connected up. To check that the I2C addresses for wired devices use the i2cdetect command:
i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- 28 -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- 77
(Note: for this i2cdetect example, addresses 28 and 48 were on from the Pimoroni Explorer HAT, and address 77 was a BME280 sensor).
Typically the next step is to install Python with pip and then any required I2C device library. For this project I was using a BME280 temperature/humidity sensor.
BME280 Sensor Setup
Each sensor will have its own particular library, however you’ll probably need the python3-smbus support.
For my sensor I needed to:
opkg update
opkg install python3 python3-pip
opkg install python3-smbus
# Install Python BME280 temperature/humidity sensor library
pip install bme280
The Python bme280 library also has a Bash interface, so to get the data from I2C address 77:
# Get the BME280 sensor data from address 0x77
read_bme280 --i2c-address 0x77
1005.19 hPa
38.38 %
19.25 C
Control USB Power
Controlling the USB power is not something that is done very often. Some use cases might be: USB fans and lights or resetting an Arduino controller that a Pi is powering/connected to.
For this feature you’ll need to run:
opkg install usbutils uhubctl
The lsusb command will show which smart USB devices are connected, it will not show simple hardware like USB fans and lights.
lsusb --tree
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=dwc_otg/1p, 480M
|__ Port 1: Dev 2, If 0, Class=, Driver=hub/5p, 480M
|__ Port 1: Dev 3, If 0, Class=, Driver=smsc95xx, 480M
For the Raspberry Pi 3 and 4 the power on all USB ports is ganged together through port 2, so unfortunately it is not possible to power up/down an individual USB port. As mentioned earlier, the chip set on the Pi 1 and 2 do not support USB power control.
The Pi 4 has two internal USB hubs. Hub 1-1 connects to all the USB port on the USB 2.10 standard. Hub 2 controls to all the ports on the USB 3.00 standard and the Ethernet jack.
The commands to turn on/off/toggle the USB ports and keep the Ethernet jack powered are:
uhubctl -l 1-1 -p 2 -a on
uhubctl -l 1-1 -p 2 -a off
uhubctl -l 1-1 -p 2 -a toggle
OpenWRT uhttpd Web Server
OpenWRT has the lightweight uhttp web server pre-installed. This server is used for the LuCI Web Interface but it can also be used for custom applications.
For custom web projects add your files to: /www/cgi-bin
This directory allows any CGI program (Bash, Python, Lua, etc.) to run. Remember to set execute permissions on your CGI script files:
chmod +x mycgifile
A Pi3 CGI Web Example
The hardware setup on this project used a Pimoroni Explorer HAT Pro. This Pi Top had four built-in coloured LEDs (on pins 4, 17,27 and 5). Before toggling a GPIO pin, the device needs to be defined and a direction needs to be set:
#!/bin/bash
#
# setgpio - setup GPIO
#
for pin in 4 17 27 5
do
gpiodev=/sys/class/gpio/
gpiodev+=$pin
echo $pin | tee /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio$pin/direction
done
ls /sys/class/gpio
For my Web Page, some buttons were used to pass a query string variable that is read at the top of the script before outputting the HTML. The BME280 sensor data is shown as a simple Bash variable.
#!/bin/bash
#
# toggle - Bash CGI to show some standard functions
# - toggle GPIO LEDs and USB power
# - show some I2C sensor results
# Note: GPIO pins need to be setup as outputs
set -e
# Toggle a pin if it's passed in the queue string
if [[ "$QUERY_STRING" =~ "gpio" ]]; then
pin=$QUERY_STRING
# Read the GPIO pin value and then toggle it
if [ "$(cat /sys/class/gpio/$pin/value)" == 1 ]; then
echo 0 > /sys/class/gpio/$pin/value
else
echo 1 > /sys/class/gpio/$pin/value
fi
fi
# Toggle USB power, ensure to add '&' for CGI use
if [[ "$QUERY_STRING" =~ "usb" ]]; then
uhubctl -l 1-1 -p 2 -a toggle &> /dev/null
fi
# Get BME280 sensor data
data=$(read_bme280 --i2c-address 0x77)
echo "Content-type: text/html"
echo ""
echo "
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<title>OpenWRT PI Toogle</title>
</head>
<body>
<h1>OpenWRT PI CGI </h1>
<h3>Toggle Hardware</h3>
<hr>
<button style='background-color:skyblue;'
onclick='location.href=\"?gpio4\"'>Toggle GPIO4 LED1
</button><br>
<button style='background-color:yellow;'
onclick='location.href=\"?gpio17\"'>Toggle GPIO17 LED2
</button><br>
<button style='background-color:red;'
onclick='location.href=\"?gpio27\"'>Toggle GPIO27 LED3
</button><br>
<button style='background-color:green;'
onclick='location.href=\"?gpio5\"'>Toggle GPIO5 LED4
</button><br><br>
<button style='background-color:white;'
onclick='location.href=\"?usb\"'>Toggle USB Power
</button><br>
<hr><h3>BME280 Sensor Data</h3>
<b>$data</b>
</body>
</html>"
exit 0
The web pages is called by: http://pi_OpenWRT_ip/cgi-bin/toggle
Below is a picture of the web page and the Pi setup.

Summary
OpenWRT can breath a lot of life into old Raspberry Pi hardware. I’ve noticed a nice performance improvement on the old Pi hardware that makes the system quite usable.
Long term Raspberry Pi users may find OpenWRT’s lack of a pre-installed applications, drivers and no desktop a little frustrating at first.
It’s important to note that certain packages like Node-Red will take some work to get installed.
This blog only really looked at Raspberry Pi functionality under OpenWRT. I never documented some of the OS’s real strengths on the networking side.