My Proxmox VE (PVE) hypervisor was installed and the host networking configured on my N100 box. Now it was time to create the core component: the virtual machine that would act as my main home router. My initial plan was to use vanilla OpenWrt, the classic, highly customizable Linux distribution for routers.
Act I: The Struggles with Vanilla OpenWrt
Creating the VM in PVE (giving it VM ID 100) involved several steps:
- Download Firmware: Get the official OpenWrt x86-64 combined-ext4 image (
.img.gz). - Upload & Import: Upload the
.img.gzfile to PVE (e.g., via SCP or the web UI’s storage browser – note: uploading directly as an ISO image type fails). Import the disk image into the VM usingqm importdisk 100 openwrt.img.gz local-lvm. - VM Hardware Config: Assign CPU cores, RAM. Remove the default SCSI disk. Attach the imported OpenWrt disk as a VirtIO block device. Add two VirtIO network cards – one connected to PVE’s
vmbr0(WAN) and one tovmbr1(LAN). Set the boot order to use the OpenWrt disk. - Disk Resizing: The default image is tiny. Resize the virtual disk in PVE’s hardware tab. Boot the VM with a GParted Live ISO attached, use GParted to expand the OpenWrt partition to fill the larger virtual disk.
- Initial Network Config: Boot OpenWrt. Access the console (via PVE’s web UI or
qm terminal 100- notqm console). Use thevieditor to modify/etc/config/network, changing the LAN interface’s IP address to10.0.0.1.
So far, so good. I could access the OpenWrt LuCI web interface at 10.0.0.1. I configured PPPoE on eth1 (WAN, connected to vmbr0) and set up the LAN interface (eth0, connected to vmbr1) with DHCP and IPv6 server settings. Basic routing worked!
The Dependency Hell
The problems began when I tried to customize OpenWrt by installing packages. My goal was simple: install luci-app-adguardhome. But opkg update often failed to connect to the repositories. When it did connect, attempting to install AdGuard Home resulted in a cascade of errors about incompatible architectures or missing dependencies (luci-lua-runtime was a frequent culprit). Even manually downloading .ipk packages failed with similar architecture errors.
I spent hours trying different package versions, compiling dependencies, and scouring forums. I even managed to “force install” some packages, but this led to a broken LuCI interface – the “Services” menu simply wouldn’t appear, despite the package seemingly being installed.
[Placeholder: Add a screenshot of the terminal showing the opkg errors or the LuCI interface missing the Services menu.]
Clearing LuCI caches (rm /tmp/luci-indexcache) did nothing. Log files (logread) showed no obvious errors. File permissions seemed correct. The final nail in the coffin was a detailed error log clearly stating that key LuCI components and their dependencies were fundamentally incompatible with the base system. Trying to manually build a complex setup on vanilla OpenWrt felt like assembling a car from mismatched parts found in a junkyard.
Act II: The Turn Towards iStoreOS
Frustrated and realizing the “DIY package management” route was unsustainable, I revisited earlier advice: use a pre-integrated firmware like iStoreOS. Based on OpenWrt but comes with a user-friendly interface and, crucially, a curated app store where dependencies should just work.
The Migration Plan
The challenge: perform this migration without disrupting my family’s internet access for too long.
- Preparation: In PVE, create a new VM (e.g., VM ID 101) for iStoreOS. Download the iStoreOS x86
.img.gzfirmware. - Import & Basic Config: Upload and import the iStoreOS disk into VM 101. Configure its hardware similarly to the OpenWrt VM (CPU, RAM, 2x VirtIO NICs connected to
vmbr0andvmbr1). - Offline Config Attempt (Failed): Boot VM 101 with GParted. Try to mount the iStoreOS partition to change the default IP (
192.168.100.1) to10.0.0.1offline. Failure! GParted couldn’t identify the filesystem. Manualmountcommands failed, complaining about unknown filesystem types or missing superblocks. Offline config was impossible. - The Switch: Plan B - configure online. Physically disconnect the WAN cable from the N100. Shut down the old OpenWrt VM (100). Start the new iStoreOS VM (101). Set my Mac’s IP statically to
192.168.100.5. Connect my Mac to one of the N100’s LAN ports (connected tovmbr1). Try accessing192.168.100.1.
The WAN/LAN Inversion Twist
Failure again! 192.168.100.1 was unreachable. In a moment of desperation (or maybe just random plugging), I moved my Mac’s cable to the N100 port I had designated for WAN (connected to vmbr0). And… success! I reached the iStoreOS login page.
Diagnosis: iStoreOS had, for some reason, reversed the network interface identification compared to OpenWrt. It saw eth0 (connected to PVE’s vmbr1, my LAN bridge) as its WAN interface, and eth1 (connected to PVE’s vmbr0, my WAN bridge) as its LAN interface, assigning the 192.168.100.1 address there.
Resolution: Logged into iStoreOS via the “wrong” port. Navigated to Network -> Interfaces. Edited the LAN and WAN interfaces, swapping their assigned physical devices (eth0 <-> eth1). Saved and applied. Moved my Mac’s cable back to a correct LAN port. Set my Mac back to DHCP. Accessed 192.168.100.1 (the default iStore IP). Success! Changed the iStoreOS LAN IP to 10.0.0.1. Plugged the WAN cable back into the N100’s WAN port.
The network migration was complete in under 15 minutes. The foundation was finally stable. iStoreOS provided the pre-packaged environment I needed. Now, it was time to deploy the services that started this whole journey.