by rkagerer | 2025-09-08 20:25:34+00:00
I've been following OpenWRT for years, and finally made the jump.

This was after using DD-WRT and various flavors of Tomato (especially Shibby and FreshTomato) for two decades on probably ~100 routers in various locations. Some of those locations were business production environments, with the routers providing VPN connecting sites across the continent as a backbone for VOIP telephony, remote user access, etc. (before the likes of Tailscale).

It's an important project and I have a great appreciation for all the work the developers have put into it. But I have to admit, I was underwhelmed. LuCI wasn't as robust as I expected (the "queue all your changes as a batch of commands" approach is a great idea, but its implementation has some rough edges that simply don't work - IIRC, where the UI isn't aware of conflicting config changes you've already queued). And I found in practice getting it to do things that are easy and reliable on FreshTomato, was frustratingly unintuitive, taking more steps than I'd expect, some seeming brittle/error-prone. I'm not averse to scripting, having written short novels of commands for previous OS's, and even custom-compiled binaries (e.g. to install iPerf, before it was bundled with the OS) and a whole custom FreshTomato build that added some admin pages for long-term bandwidth/latency graphing. So I'm open to learning new things, I just felt like I was doing more fighting with the OS than should be necessary.

One small example was configuring a Let's Encrypt certificate. This feels like it should be a near one-click operation. In my case it took a bit of testing and tweaking to get right - I wound up contributing my short solution back to a SuperUser answer: https://superuser.com/a/1904844/75522

Properly disabling IPv6 took more than just a checkbox. I had "No default route present, overriding ra_lifetime to 0!" messages logged, until I added "net.ipv6.conf.all.disable_ipv6=1" to /etc/sysctl.conf.

Maybe I'm just getting snagged by doing things in 'weird' ways. e.g. My inaugural router on it is a MikroTik wAP ac. Turns out you don't get a WAN interface out of the box when flashed on that device, and I had to manually create it. There wasn't really any documentation warning about that, and it took a while before I realized life would go better if I used a lowercase rather than uppercase convention (for better integration with built-in stuff that relies on its existence).

A lingering issue I haven't figured out yet is how to make a reliable "toggle switch" to turn on and off access to the internet for one device on my network (by IP or MAC address). I set up a firewall rule, but wind up having to manually run "/etc/init.d/firewall reload" and "conntrack -D ..." each time to kill any established connections. On FreshTomato it was just a checkbox you turn on/off. If anyone has advice on this I'd be grateful.

One last tip for anyone else using it on a router plugged into a Starlink endpoint that's in bypass mode (i.e. you want to be able to port forward). You'll get messages in syslog every 5 minutes due to short-lived Starlink IP:

daemon.notice netifd: wan (####): udhcpc: sending renew to server daemon.notice netifd: wan (####): udhcpc: lease of ###.###.###.# obtained from ###.###.###.#, lease time 300

You can suppress them by appending "-l 1" (without quotes) to the "procd_set_param command /sbin/netifd" line in /etc/init.d/network, then reboot the router (in my case running "/etc/init.d/network reload" didn't quite do it). On the plus side, the Dynamic DNS package is working well in my setup. (And yes, I understand the implications of using Let's Encrypt on a DDNS IP).

I'm not here to whine, just to suggest that anyone else thinking of making the switch manage your expectations and leave yourself some time to perfect things and get used to the new platform.