How to change the root password during compilation

First post here. I have been trying to compile my own openwrt for x86-64 from the official source. I had experience of successfully compiled from lede/immortalwrt source, but now facing some tricky problems.
To change the default settings, I copied code from immortalwrt
and made my own modifications, so like configuring bridging, lan settings, tbemes, and root password. These were made into a feed of my own
The strange thing is that the bridging, lan settings, themes, all worked, expect for the root password change.
Can anyone help me to find out my mistakes?

here are the source code for reference,


# Copyright (C) 2021 Lean <>
# Copyright (C) 2021 ImmortalWrt
# <>
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.

include $(TOPDIR)/



include $(INCLUDE_DIR)/

define Package/default-settings
  TITLE:=LuCI support for Default Settings

define Package/default-settings-chn
  TITLE+= (Optimize for CHN users)
  DEPENDS:=+default-settings +@LUCI_LANG_zh_Hans +luci-i18n-base-zh-cn

define Build/Compile

define Package/default-settings/install
	$(INSTALL_DIR) $(1)/etc/uci-defaults
	$(INSTALL_BIN) ./files/99-default-settings $(1)/etc/uci-defaults/

define Package/default-settings-chn/install
	$(INSTALL_DIR) $(1)/etc/uci-defaults
	$(INSTALL_BIN) ./files/99-default-settings-chinese $(1)/etc/uci-defaults/

$(eval $(call BuildPackage,default-settings))
$(eval $(call BuildPackage,default-settings-chn))



uci -q get system.@imm_init[0] > "/dev/null" || uci -q add system imm_init > "/dev/null"

if ! uci -q get system.@imm_init[0].lang > "/dev/null"; then
	uci -q batch <<-EOF
		set luci.main.lang="auto"
		commit luci

		set system.@imm_init[0].lang="1"
		commit system

ln -sf "/sbin/ip" "/usr/bin/ip"

sed -i "/log-facility/d" "/etc/dnsmasq.conf"
echo "log-facility=/dev/null" >> "/etc/dnsmasq.conf"

rm -f "/www/luci-static/resources/view/status/include/29_ethinfo.js"
rm -f "/tmp/luci-indexcache"
rm -rf "/tmp/luci-modulecache"

uci set luci.main.mediaurlbase=/luci-static/argon

sed -i 's|root:::0:99999:7:::|root:$6$gyMxdm3KrPiL87$Lgn9dsvhiozWbH/HYoXeQmx4VdGU8fSv91NTvNGGDRHkVBIMOLCrl.2m42CD.2OBP4Ee26ho.3YqXCVXZKdJ1.::0:99999:7:::|g' /etc/shadow
sed -i 's|root::0:0:99999:7:::|root:$6$gyMxdm3KrPiL87$Lgn9dsvhiozWbH/HYoXeQmx4VdGU8fSv91NTvNGGDRHkVBIMOLCrl.2m42CD.2OBP4Ee26ho.3YqXCVXZKdJ1.:0:0:99999:7:::|g' /etc/shadow

uci set network.lan.proto='dhcp'
uci delete network.lan.ipaddr
uci delete network.lan.netmask
uci delete network.lan.gateway
uci delete network.lan.dns
uci set network.lan.ip6assign='64'
#my custom settings
uci delete network.@device[0].ports
uci add_list network.@device[0].ports='eth0'
uci add_list network.@device[0].ports='eth1'
uci add_list network.@device[0].ports='eth2'
uci add_list network.@device[0].ports='eth3'
uci delete network.wan
uci delete network.wan6
uci commit network

uci delete uhttpd.main.listen_http
uci delete uhttpd.main.listen_https
uci add_list uhttpd.main.listen_http=''
uci add_list uhttpd.main.listen_http='[::]:8888'
uci commit uhttpd

exit 0

Thanks for the tip. Actually I wish to put my openwrt scripts on github (public access), but I do not wish to expose my password like this, so I used

sed -i 's|root:::0:99999:7:::|root:$6$gyMxdm3KrPiL87$Lgn9dsvhiozWbH/HYoXeQmx4VdGU8fSv91NTvNGGDRHkVBIMOLCrl.2m42CD.2OBP4Ee26ho.3YqXCVXZKdJ1.::0:99999:7:::|g' /etc/shadow
sed -i 's|root::0:0:99999:7:::|root:$6$gyMxdm3KrPiL87$Lgn9dsvhiozWbH/HYoXeQmx4VdGU8fSv91NTvNGGDRHkVBIMOLCrl.2m42CD.2OBP4Ee26ho.3YqXCVXZKdJ1.:0:0:99999:7:::|g' /etc/shadow

where only hashed password is shown.

I wouldn't publicly post even the hash of a super-complex/secure password as it makes it just that much easier of an attack.

Are you sure SHA512 ($6) is a supported hash option for OpenWrt? Have you tried anything simpler, like md5 ($1)?

sha512 is supported by all libc-s for like a decade.

1 Like

Assuming the hash is correct, I'd check if the /etc/shadow is updated by the sed command then. If it's the matching part which is failing, I'd try:

sed -i 's|^root:[^:]*:|root:$6$gyMxdm3KrPiL87$Lgn9dsvhiozWbH/HYoXeQmx4VdGU8fSv91NTvNGGDRHkVBIMOLCrl.2m42CD.2OBP4Ee26ho.3YqXCVXZKdJ1.:|' /etc/shadow

Hi, thanks for the point. Actually, I have checked that if i use the sed command in terminal, it actually worked.
So the problem is like:

  • everything in the 99-default-settings worked, except for the password part
  • manually applying the password part worked

i am wondering, if the openwrt build process has changed, that when 99-default-settings are applied, the /etc/shadow file did not exist?

It does exit: I set password this way all the time. My guess is that your sed is failing: add below line to the beginning of your file and then look at the log file after a boot up.

exec >> /root/_log.setup 2>&1

I tried your suggestion, but it confused me more...

  1. I added this line to =99-default-settings=, but not log was generated.

  2. I also extracted the built img file, and there is even no =etc/uci-defualts/99-default-settings= file

❯ sudo mount -o loop,offset=262144 openwrt-x86-64-generic-squashfs-combined.img ./img
❯ sudo umount ./img
❯ sudo mount -o loop,offset=67633152 openwrt-x86-64-generic-squashfs-combined.img ./img
❯ ls -lah ./img/etc/uci-defaults/
Permissions Size User Date Modified Name
.rw-r--r--   251 root 24 Apr 15:41  00_uhttpd_ubus
.rw-r--r--   395 root 24 Apr 15:41  10_migrate-shadow
.rw-r--r--   369 root 24 Apr 15:41  12_network-generate-ula
.rw-r--r--   179 root 24 Apr 15:41  13_fix-group-user
.rw-r--r--   425 root 24 Apr 15:41  14_migrate-dhcp-release
.rwxr-xr-x  1.1k root 24 Apr 15:41  15_odhcpd
.rwxr-xr-x   299 root 24 Apr 15:41  20_migrate-feeds
.rwxr-xr-x   509 root 24 Apr 15:41
.rwxr-xr-x   189 root 24 Apr 15:41
.rwxr-xr-x   162 root 24 Apr 15:41

Appreciate it if anyone could help me figure out what happened at all.

I'm using a 55 uci defaults file with the 23.05.3 IB and it works.

I'm also on 23.05, let me try to change the number prefix to test if it works or not...

Could it be that different distributions using different hash algorithym's by default. So like OpenWrt/busybox/ash (sha-256/hash I don't know) vs. ArchLinux/bash (by default yescrypt since a while)? So if you generate/copy the hash on/from host system it will differ from what you get on OpenWrt I would guess and therefor it will fail.

EDIT: O.K. made a short test. I does not make a difference. So my assumption is wrong.

Damn, I was an idiot.

Everything's fine, actually I have been compiling the openwrt from a remote machine with more cores, and rsync to fetch back to my local machine, and use qemu-img to convert it into vmdk for Virtual Machine. Actually, the compiled image was in gz format, but I forgot to extract it, thus every time I was converting a same img file, that's why I saw no difference.

Anyway, the two lines to set root password did the trick, and maybe I can change that to some regex like `^root:', but for this stage I feel quite satisfied with the result.

Thanks guys.

1 Like