My Journey
- Used Raspberry Pi to install OpenWrt as the main system, but also wanted to build a Minecraft server. The Pi’s performance wasn’t sufficient, so I needed to upgrade.
- Purchased a Mini PC for the Minecraft server. Debian could also run a software OpenWrt router, but only as a bypass router. I thought it best to have a dedicated device for network management.
- Tried various web managers that could run on Debian like Cockpit, but they weren’t satisfying. Webmin was even worse - like a system from 20 years ago.
- Ran OpenWrt as a Docker container on Debian. First tried Docker’s host mode, but it defeated the purpose of Docker’s isolation and added unnecessary complexity. Then struggled with macvlan - the container couldn’t communicate with the host. Eventually gave up.
- Used PVE virtual machines to install OpenWrt, then installed Debian on another VM with its gateway pointing to OpenWrt.
- Had a power outage at home and worried about PVE stability. Returned to the previous setup: Raspberry Pi as OpenWrt gateway, Mini PC as Debian server, each doing their own thing.
Planned to sell the Raspberry Pi(didn’t end up selling it because Docker version Home Assistant is crippled, so I’ll use the Pi to run HA). The Raspberry Pi I bought for $70 could suddenly sell for $100. That profit difference could buy another Nanopi R2S as a gateway (didn’t sell the Pi but bought the R2S anyway).
Required Hardware and Software
Hardware
- A computer with ethernet port
- Raspberry Pi 4B+ with 2GB+ RAM
- 8GB+ microSD card for the Pi
- SD card reader
- Ethernet cable
- Monitor (optional), Micro USB to HDMI cable (optional)
Software
- Balena Etcher. MacBook users can download this or use command line instead.
- Virtual Box and Ubuntu VM (optional) for compiling OpenWrt firmware. You can also download pre-compiled firmware. Note: the first compilation needs 60GB, but compiling a full firmware library with all features needs more, so 128GB is recommended.
- SecureCRT or PuTTy (optional). I use my system’s built-in terminal.
Getting the Image
Official Download
You can download the image from OpenWrt’s official website.
Local Compilation
The official firmware is lightweight and includes nothing extra. We can install what we need later. But if you don’t want to reinstall applications after each firmware flash, you need to compile your own. This repository lets you choose applications and compile them into the kernel. The README has detailed compilation steps. You can compile once locally to familiarize yourself, then use GitHub Actions for future compilations.
First Compilation
-
First, clone the repo on Ubuntu:
git clone https://github.com/coolsnowwolf/lede.git -
Install dependencies:
sudo apt update -y sudo apt full-upgrade -y sudo apt install -y ack antlr3 asciidoc autoconf automake autopoint binutils bison build-essential \ bzip2 ccache cmake cpio curl device-tree-compiler fastjar flex gawk gettext gcc-multilib g++-multilib \ git gperf haveged help2man intltool libc6-dev-i386 libelf-dev libfuse-dev libglib2.0-dev libgmp3-dev \ libltdl-dev libmpc-dev libmpfr-dev libncurses5-dev libncursesw5-dev libpython3-dev libreadline-dev \ libssl-dev libtool lrzsz mkisofs msmtp ninja-build p7zip p7zip-full patch pkgconf python3 \ python3-pyelftools python3-setuptools qemu-utils rsync scons squashfs-tools subversion swig texinfo \ uglifyjs upx-ucl unzip vim wget xmlto xxd zlib1g-dev -
Update feeds and select configuration:
cd lede ./scripts/feeds update -a ./scripts/feeds install -a make menuconfig -
This command opens the configuration page. I use Raspberry Pi 4B. Below is a breakdown of these configurations. Choose as needed:
# Target system for compilation TargetSystem: - Broadcom BCM27xx Subtarget: - BCM2711 boards (64 bit) TargetProfile: - Raspberry Pi 4B/400/4CM (64bit) # Image parameters TargetImages: - squashfs - KernelPartitionSize: 64 - RootFilesystemPartitionSize: 2048 # LuCI settings LuCI: Collections: - luci # Enable luci Modules: Translations: - Chinese(zh-cn) # Chinese support Themes: - luci-theme-agron # Add theme # LuCI applications Applications: - luci-app-adguardhome # Ad-blocking - luci-app-advanced-reboot - luci-app-alist # File sharing (compilation is time-consuming, better as separate software) - luci-app-aria2 # Download tool - luci-app-cloudflared - luci-app-ddns - luci-app-diskman - luci-app-dockerman # Docker - luci-app-filebrowser # File management - luci-app-filetransfer - luci-app-firewall # Firewall - luci-app-frps - luci-app-frpc # Intranet penetration - luci-app-hd-idle # Hard drive sleep - luci-app-lucky - luci-app-opkg # Package manager - luci-app-openvpn - luci-app-openvpn-server - luci-app-passwall # VPN - luci-app-qos # Quality of service - luci-app-samba # Network sharing - luci-app-smartdns # Optimize VPN - luci-app-upnp # UPnP service - luci-app-usb-printer - luci-app-wol # Wake on LAN Protocols: - luci-protocol-wireguard # Optional tools BaseSystem: - block-mount # Add <Mount Points> menu to LuCI - blockd # Auto-mount devices - wireless-tools # Wireless extension tools Administration: - htop # better top # File system KernelModules: Filesystems: - kmod-fs-ext4 - kmod-fs-f2fs - kmod-fs-ntfs - kmod-fs-squashfs - kmod-fs-vfat - kmod-fuse # Network card support NetworkDevices: - kmod-xxx # Wired NIC, select as needed NetworkSupport: - kmod-wireguard WirelessDrivers: - kmod-rt2800-usb # Ralink RT5370 chipset USB wireless NIC driver USBSupport: - kmod-usb-net: - kmod-usb-net-asix # Asix wired NIC - kmod-usb-net-asix-ax88179 # USB 3.0 NIC chip AX88179 - kmod-usb-net-rtl8152 # USB 2/3 NIC RTL8152/3 chip - kmod-usb-net-sr9700 # USB 2.0 NIC SR9700 chip - kmod-usb-core # Enable USB support - kmod-usb-hid # USB keyboard/mouse - kmod-usb-ohci # OHCI support for old USB - kmod-usb-storage # Enable USB storage - kmod-usb-storage-extras - kmod-usb-uhci # UHCI support for old USB - kmod-usb2 # Enable USB2 support - kmod-usb3 # Enable USB3 support # Network tools Network: DownloadManager: - ariang # Aria2 management page FileTransfer: - curl # Add curl command - wget-ssl # Add wget command IP Addresses and Names: - ddns-scripts-cloudflare # For DDNS - drill # DDNS VPN: - wireguard-tools # Utilities Utilities: Compression: - bsdtar # tar packing tool - gzip # GZ compression suite Disc: - fdisk # Disk partitioning tool - lsblk # Disk viewing tool Filesystem: - f2fs-tools - ntfs-3g # NTFS read/write support - resize2fs # Partition resize Terminal: - screen # Add screen - losetup - pciutils # Add lspci command - qrencode # wireguard qrcode - usbutils # Add lsusb command -
My current configuration:
TargetSystem: - Broadcom BCM27xx Subtarget: - BCM2711 boards (64 bit) TargetProfile: - Raspberry Pi 4B/400/4CM (64bit) TargetImages: - squashfs - KernelPartitionSize: 64 - RootFilesystemPartitionSize: 6144 LuCI: Themes: - luci-theme-agron Applications: - luci-app-adguardhome - luci-app-autoreboot - luci-app-ddns - luci-app-filetransfer - luci-app-firewall - luci-app-nlbwmon - luci-app-opkg - luci-app-passwall - luci-app-ramfree - luci-app-sqm - luci-app-wol Protocols: - luci-protocol-wireguard Network: IP Addresses and Names: - ddns-scripts-cloudflare - drill - tcpdump Utilities: - qrencode -
A summary of Target Images:
- If you want to run directly on physical hardware like Raspberry Pi with firmware on SD card, use
squashfs. - If you want to package OpenWrt as a Docker image, select
tar.gz. - If you want to run as a PVE virtual machine on a Mini PC, see Installing PVE on x86 Mini PC | Kunyang’s Blog.
- If you haven’t decided on deployment yet, select all.
- Different architectures have different options.
RootFilesystemPartitionSizeis the system size after installation. I chose 6144M for my Pi’s 8GB SD card. If using PVE, you don’t need to worry about this as you assign disk size in PVE.
- If you want to run directly on physical hardware like Raspberry Pi with firmware on SD card, use
-
After configuration, select Save. This saves a
.configfile. Before the final installation step, install screen for persistent sessions (without it, closing SSH loses compilation progress):sudo apt install screen screen -S buildlede -
Finally, download dl library with 8 threads, compile with 1 thread for first build. (I had trouble downloading on AWS Ubuntu, so switched to local Ubuntu and it worked):
make download -j8 make V=s -j1
Single Module Compilation
Sometimes you discover you need a plugin while using it. You can compile just that module:
-
Edit
.configfile:make menuconfig -
Find the plugin you want to compile separately, like
luci-app-diskman(for managing router disks/partitions). If you selected[*]the first time (built-in module), select[M]this time (module that can be unloaded):
Use this command to compile:
make package/luci-app-diskman/compile V=s -
Open OpenWrt, go to System â File Transfer to upload the file. Click Install in the bottom-right.
-
The newly installed plugin might not appear immediately - it took some time for me.
To compile kernel modules separately, like kmod-wireguard, select it as [M], then run:
make package/kernel/linux/compile V=s
Compilation finishes quickly. The compiled package is at bin/packages/<target>/<package-repo>/kmod-wireguard_xxx.ipk
Second Compilation
-
Pull the latest feeds:
sudo sh -c "apt update && apt upgrade -y" git pull ./scripts/feeds update -a && ./scripts/feeds install -a -
Clean old build artifacts (optional):
make clean # Execute after major updates or kernel changes to ensure build quality # Deletes files in /bin and /build_dir make dirclean # For architecture changes from x86_64 to MediaTek Ralink MIPS, recommended to do deep clean # Deletes /bin, /build_dir, /staging_dir, /toolchain, /tmp, and /logs -
Compile:
make defconfig make download -j8 find dl -size -1024c -exec ls -l {} \; make -j$(nproc) || make -j1 || make -j1 V=s
GitHub Actions Compilation
After familiarizing yourself with local compilation, use GitHub Actions to offload the work to the cloud. I found this repository and decided not to reinvent the wheel.
Note: if you want to auto-publish Artifacts to Release, grant PAT permissions in Settings â Developer Settings â Personal access tokens â Tokens (classic) â Your Token. Check workflow and write:packages:
Flashing
For direct flashing, select the image
openwrt-bcm27xx-bcm2711-rpi-4-squashfs-factory.img.gz
Windows
Use Balena Etcher or other disk imager software to flash the image to your SD card. It’s very straightforward:
MacOS
MacOS can also use Balena Etcher, or use command line if you prefer:
-
Find the SD card’s disk number. Mine is
/dev/disk4:diskutil list /dev/disk4 (external, physical): #: TYPE NAME SIZE IDENTIFIER 0: FDisk_partition_scheme *7.9 GB disk4 1: Windows_FAT_32 BOOT 67.1 MB disk4s1 2: Linux 109.1 MB disk4s2 (free space) 7.7 GB -I had a previous OpenWrt without GUI, so the SD card had extra partitions. I’m reinstalling with GUI support.
-
First restore the partition (this also formats the SD card):
diskutil eraseDisk FAT32 SDCARD MBRFormat /dev/disk4After restoring:
diskutil list /dev/disk4 (external, physical): #: TYPE NAME SIZE IDENTIFIER 0: FDisk_partition_scheme *7.9 GB disk4 1: DOS_FAT_32 SDCARD 7.9 GB disk4s1 -
Unmount (but don’t eject) the SD card to avoid “busy” errors:
diskutil unmountDisk /dev/disk4 -
Decompress the downloaded image:
gunzip ./openwrt-bcm27xx-bcm2711-rpi-4-squashfs-factory.img.gz -
Use
ddto write the decompressed.imgfile. Be very careful with the disk number - mistakes are irreversible:sudo dd if=/Users/xxx/Desktop/openwrt-bcm27xx-bcm2711-rpi-4-squashfs-factory.img of=/dev/disk4 bs=1M status=progressNo errors usually means success.
-
Eject the SD card from your computer and insert it into the Raspberry Pi. Start the Pi and connect its ethernet port to your computer’s ethernet port. OpenWrt defaults to bridges the Pi’s
eth0tobr-lanwith IP192.168.1.1. Configure your computer’s Ethernet interface to also be on the192.168.1.xsubnet (x can be 2-255):
Once they’re on the same subnet, enter
192.168.1.1in your browser to access OpenWrt’s GUI (LuCI). Default username and password arerootandpassword. -
Done!
Packaging OpenWrt as a Docker Image
See: Creating OpenWrt as a Docker Image | Kunyang’s Blog
Connecting to Main Router
- My home main router uses subnet
192.168.2.x. I need to change the Pi to this subnet.
Single Network Port
-
Since the Pi has only one
eth0port, I recommend setting it as the LAN port:vi /etc/config/networkconfig interface 'lan' option device 'br-lan' option proto 'static' option netmask '255.255.255.0' option ip6assign '60' option ipaddr '192.168.2.66' option gateway '192.168.2.1' option dns '192.168.2.1' -
Disable DHCP to avoid conflicts with the main router:
vi /etc/config/dhcpconfig dhcp 'lan' option interface 'lan' option ignore '1' -
Check firewall configuration:
vi /etc/config/firewallconfig zone option name 'lan' list network 'lan' option input 'ACCEPT' option output 'ACCEPT' option forward 'ACCEPT' -
Apply settings:
/etc/init.d/network restart -
Now your computer is on
192.168.1.xbut the Pi is on192.168.2.x, so connection is lost. Change your computer’s Ethernet to192.168.2.xto reconnect. -
Disconnect the Pi from your computer and connect it to the router’s LAN port. It should have normal network access, and your computer can access the Pi.
Setting up Bypass Router
The above steps just add the Pi as a network device. Your devices still route through the main router. To make it a bypass router:
-
Simply change your WiFi gateway from the main router’s default to the Pi’s IP. If my main router is
192.168.2.1, my computer is192.168.2.54, and my Pi is192.168.2.66:
-
Same for MacBook:
-
iPhone configuration is similar.
-
I use this non-invasive approach to avoid breaking the entire network. Only affects devices with gateway set to the bypass router.
Tutorial video:
Installing Plugins
Uninstalling Plugins
- Go to System â Software â Installed to uninstall plugins
- Plugins compiled into the firmware cannot be uninstalled
Installing Plugins
Direct Installation
Foreign source ARM:
src/gz openwrt_core https://downloads.openwrt.org/releases/23.05.0/targets/bcm27xx/bcm2711/packages
src/gz openwrt_base https://downloads.openwrt.org/releases/23.05.0/packages/aarch64_cortex-a72/base
src/gz openwrt_luci https://downloads.openwrt.org/releases/23.05.0/packages/aarch64_cortex-a72/luci
src/gz openwrt_packages https://downloads.openwrt.org/releases/23.05.0/packages/aarch64_cortex-a72/packages
src/gz openwrt_routing https://downloads.openwrt.org/releases/23.05.0/packages/aarch64_cortex-a72/routing
src/gz openwrt_telephony https://downloads.openwrt.org/releases/23.05.0/packages/aarch64_cortex-a72/telephony
Foreign source x86:
src/gz openwrt_core https://downloads.openwrt.org/releases/23.05.0/targets/x86/64/packages
src/gz openwrt_base https://downloads.openwrt.org/releases/23.05.0/packages/x86_64/base
src/gz openwrt_luci https://downloads.openwrt.org/releases/23.05.0/packages/x86_64/luci
src/gz openwrt_packages https://downloads.openwrt.org/releases/23.05.0/packages/x86_64/packages
src/gz openwrt_routing https://downloads.openwrt.org/releases/23.05.0/packages/x86_64/routing
src/gz openwrt_telephony https://downloads.openwrt.org/releases/23.05.0/packages/x86_64/telephony
Domestic source ARM:
src/gz openwrt_core https://mirrors.tencent.com/lede/snapshots/targets/bcm27xx/bcm2711/packages
src/gz openwrt_base https://mirrors.tencent.com/lede/snapshots/packages/aarch64_cortex-a72/base
src/gz openwrt_luci https://mirrors.tencent.com/lede/releases/18.06.9/packages/aarch64_cortex-a72/luci
src/gz openwrt_packages https://mirrors.tencent.com/lede/snapshots/packages/aarch64_cortex-a72/packages
src/gz openwrt_routing https://mirrors.tencent.com/lede/snapshots/packages/aarch64_cortex-a72/routing
src/gz openwrt_telephony https://mirrors.tencent.com/lede/snapshots/packages/aarch64_cortex-a72/telephony
Domestic source x86:
src/gz openwrt_core https://mirrors.tencent.com/lede/releases/24.10.0-rc1/targets/x86/64/packages
src/gz openwrt_base https://mirrors.tencent.com/lede/releases/24.10.0-rc1/packages/x86_64/base
src/gz openwrt_helloworld https://mirrors.tencent.com/lede/releases/24.10.0-rc1/packages/x86_64/helloworld
src/gz openwrt_luci https://mirrors.tencent.com/lede/releases/24.10.0-rc1/packages/x86_64/luci
src/gz openwrt_packages https://mirrors.tencent.com/lede/releases/24.10.0-rc1/packages/x86_64/packages
src/gz openwrt_routing https://mirrors.tencent.com/lede/releases/24.10.0-rc1/packages/x86_64/routing
src/gz openwrt_telephony https://mirrors.tencent.com/lede/releases/24.10.0-rc1/packages/x86_64/telephony
Self Compilation
-
First compile the plugin on Ubuntu:
make menuconfigIn LuCI â Applications, select all plugins (building a firmware library). Modularize by pressing space to add
Min brackets. Save and start compiling:make -j1 V=s -
After compilation, find all compiled plugins in
bin\packagesin.ipkformat.
Common Use Cases
DDNS
Ad Blocking
Accessing My Windows Desktop from Outside
Wireguard
ZeroTier
- Required plugin:
- luci-app-zerotier
OpenVPN
- Required plugins:
- luci-app-openvpn
- luci-app-openvpn-server
- luci-i18n-openvpn-server-zh-cn
- luci-i18n-openvpn-zh-cn
- open-vpn-easy-rsa
- openvpn-openssl