Creating custom firmware using ImageBuilder

Hey there,

I always wanted to create a custom firmware for my WDR4300 without IPv6 and PPP because I don't use those and wanted to save more space on flash.

I read through the related topic found here:

My questions are:

  • what packages shall I use in ImageBuilder if I want to create almost the same firmware and packages as the original one has except PPP and IPv6? (so with luci, iptables, and so on)
  • will TFTP recovery work even if something goes wrong with the new firmware?

Sorry if this was asked earlier, I just wanted to be sure to not brick my router :wink:

On your link, the - ones are removals -- select those related to IPv6 and PPPoE and probably leave the rest alone.

Flashing firmware using LuCI or sysupgrade, as long as force is not selected, doesn't "touch" anything but the kernel and firmware[1]. So, yes, you should still have TFTP recovery available in the unlikely situation that something was wrong with your image that necessitated it, as long as you didn't "force" the upgrade.

[1] At least for the vast majority of devices, as there are a few wonky ones that need to replace the factory boot loader, or other "unique" behavior when upgrading from OEM or from older releases.

For the largest saving on flash/RAM, build your image from source.
And de-select redundant stuff, not to be built.
Because there are even a few "agressive" options for more savings compared to usage of ImageBuilder

Thanks for the quick answers.

@jeff Yeah, I know, that the packages beginning with - are removals, what I don't know is that if I don't add or remove any packages with PACKAGES argument, then what packages will be installed by default.
I read on that link that I can use the make menuconfig or kernel_menuconfig too, but don't really know those commands have to be issued before or after the make image command.
@reinerotto I'm not sure how to do that. It sounds me like rocketscience.

Those are only available when building from source, using OpenWrt's buildroot, not using the imagebuilder which is fed by prebuilt release (or snapshot) binary packages.

Typically, at least as I understand it (as I only build from source), those would be options for the full build system and building from scratch, and not assembling images from pre-compiled kernels and packages with the image builder.

I recently checked a modest VM for building from scratch, 2 cores of a MacBook Pro, and it took about an hour for the first build (needs to build all the tools), 5-10 minutes for an incremental build, and about a half hour for a clean build of the same target. On a 12-core machine, it's half or less than that. The prereqs are the same as for the image builder, from what I've read about it.

All the commands you need to run to use make menuconfig are listed here:

If you want LuCi it has to be selected explicitly, but other than that you will probably get the same packages that are in the release image. You don't need to run make kernel_menuconfig to do the changes you want.

I (also) use a VM , VMWare Player on Windows, to install ubuntu 16.04 or 18.04 minimal , server, and then add the packages mentioned in above link. Then clone the git repo, and switch to openwrt, for example.

Thank you guys.
Sorry for answering late.
So, if I well understood, I have to do the followings:

  • download the specific branch with git clone
  • update the feeds with feeds update -a && feeds install -a
  • run make menuconfig and select luci & and stuffs I want to include or remove (PPP and IPv6)
  • run make download and make

This time I don't have to use make image PROFILE=xxxxx, am I correct?

That is correct -- that is all handled in the full build system with make menuconfig

If a first-time build on a new architecture, I'll sometimes do

make -j12 download toolchain/install

to make sure all the host executables are ready. (Select the -j to match your number of cores, or willingness to have the build take over most of your machine's CPU.)

My normal "mantra" is

make -j12 clean download world

with ccache enabled. If I wasn't using ccache, I'd probably skip the clean except for my "final" builds.

What does toolchain/install at the end of this mean? And clean download world?

I started to build then got few warnings:

home@asus:~/openwrt/openwrt$ ./scripts/feeds install -a
Collecting package info: done
Collecting target info: done
WARNING: Makefile 'package/utils/busybox/Makefile' has a dependency on 'libpam', which does not exist
WARNING: Makefile 'package/utils/busybox/Makefile' has a build dependency on 'libpam', which does not exist
WARNING: Makefile 'package/network/utils/curl/Makefile' has a dependency on 'libgnutls', which does not exist
WARNING: Makefile 'package/network/utils/curl/Makefile' has a dependency on 'libopenldap', which does not exist
WARNING: Makefile 'package/network/utils/curl/Makefile' has a dependency on 'libidn2', which does not exist
WARNING: Makefile 'package/network/utils/curl/Makefile' has a dependency on 'libssh2', which does not exist
WARNING: Makefile 'package/boot/kexec-tools/Makefile' has a dependency on 'liblzma', which does not exist
WARNING: Makefile 'package/network/services/lldpd/Makefile' has a dependency on 'libnetsnmp', which does not exist

Does this mean that I forgot to install the packages it meantions (with apt-get install)? I'm building with Linuxmint 19 :slight_smile:

Update: I was trying to remove anything related to PPP and IPv6. Most of them are removed but I cannot uncheck luci-proto-ipv6 and luci-proto-ppp.
I have replaced dnsmasq with dnsmasq-full (I hope it is not a problem) because DNSSEC needs it anyway, and when I was trying to use stubby as DNS packet validator, it did not do its job.

make accepts "targets" -- things defined in the makefile that you can do/build. "world" is the one that is run if you don't specify anything. Here, toolchain/install is one of the earlier steps that can cause problems with parallel builds that "get ahead of themselves". This lets you build all the toolchain components in parallel, before trying to build any of the firmware itself. It's a "one time" thing to get your build system going quickly.

clean -- remove the last build's intermediates (not the toolchain though)
download -- get all the files needed from other sites
world -- "everything"

This helps sequences things which often don't have their dependencies quite perfectly called out in the makefiles.

No, you're good unless you need one of those packages for your build. Those are error messages about the OpenWrt packages you might want to build. They are usually resolved through a fresh update/install of feeds, if not that day, a day or two later.

Thank you.
I created my very first own build with success! :wink: And it seems to be working.

Few things:

  • how can I set stubby to run on boot after upgrading? I chose stubby to be part of my firmware and I think it didn't started after a sysupgrade, because system's RAM consumption was very low
  • later if I want to add/remove any package on my build, do I need to do a make clean, make download toolchain/install and make clean download world again?
  • is there any way to remove luci-proto-ppp package? I turned off any ppp-related kernel modules, but still unable to remove it, however It was successful removing IPv6 completely. (including luci-proto-ipv6)

Thank you for your time in advance.

1 Like

Generally by enabling the service through LuCI or with something like

/etc/init.d/stubby enable

I always do a make -j12 clean download world, but then again, running ccache and on a dedicated machine, I can build in 5-10 minutes. If it takes too long, you can skip the clean. Also, since I stay pretty current with master, refreshing the feeds, running make menuconfig and clean is "required" after every source update.

The / key in make menuconfig will search for a package and then can show dependencies, so you can figure out what is "locking it in"


So I'm guessing it is a LuCI "metapackage" -- a package that just brings in other packages. If you remove luci-ssl-nginx then it might be the case that the other LuCI-related packages stick around. Otherwise you'd have to craft it "by hand" (same trick with / to see what luci-nginx-ssl brings in).

luci is also a meta package, which depend on luci-proto-ppp. If you want to remove luci-proto-ppp you have to deselect luci and anything that depends on it and select all the packages you need explicitly.

Yeah, I agree, thank you.

Guys, thank you for helping me, you helped me a lot! Just one more thing: I used a hosts file in files/etc prior building to have an ad/malware filtering already on the first boot. The hosts file contains stevenblack's ad+fakenews lists and it is 1.2M. Without having hosts file filtering, my custom build consumes 30M RAM, while using hosts file it is using 50M. Is this okay?

"50 M[B]" is certainly a problem with 32 MB of RAM, likely a problem with 64 MB, may be a problem with 128 MB of RAM and one or more ath10k wireless devices or a bunch of "non-essential" applications (including LuCI in that), ... , is likely not a problem with 4 GB or RAM.

For comparison, my Archer C7v2 running multiple APs and batman-adv (but very limited services) shows "used" of 24000 of 123212 "total" at this moment.

Really thank you for your effort and time helping me!

I have a well working custom FW now, but I've become curious: I saw, that dropbear has a version of v2017.75 if I use origin/openwrt-18.06 branch. The latest is v2019.78 if I check it here.
I have compiled it with

# ./configure
# make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" MULTI=1

How can I use this newly compiled binary in my builds instead of the existing one?

Within openwrt-18.06, you can't. You need to switch to a newer branch for that.

How will be possible to replace it then in a later version, let's say in v19.07? Will it have the latest version of dropbear anyway?