Disable /etc config save

Hi everyone, I'm currently using OpenWISP for my AP setup, I'm planning to completely disable the config saving function of OpenWrt (or save it to /tmp somehow) so on every reboot, it will be completely factory default thus reduce the risk of misconfiguring my device and soft-brick it, requiring someone to climb up there and poke the factory reset button.

Anyone have tried to do this before? I've looked everywhere in the Wiki but there doesn't seem to be any documented way to do it, I built my firmware from source and added uci-defaults with openwisp installed.

I think I could mount ramdisk to /etc?

There are multiple ways around this. As long as a default, working config is baked into the firmware, you could just disable mounting /overlay (or mount a ramdisk to /overlay), and that should be it. Obviously this means that ANY change - including extra packages installed, etc. - will be lost on a reboot.

You should not mount a ramdisk to /etc since the firmware itself contains the needed initial configuration files. Mounting anything on top of this without an overlay approach would result in no configurations/initd scripts/etc. being available, thus the unit wouldn't boot.

1 Like

Thanks, I'm gonna try this tomorrow and see how it goes.

Disable mounting /overlay will not work, because the default firmware configuration likely does not have the UUID and key of the specific device but only the shared secret set.

For those who don't know OpenWISP, a device to be able to communicate with OpenWISP needs to have a config file in /etc/config/openwisp, which has at least

  • URL
  • UUID
  • key

or alternatively:

  • URL
  • shared_secret

In the latter case, the device will register automatically if it's allowed to do so, depending on the configuration of OpenWISP Controller. Once it registers, it writes the UUID and key to the config file.

So, if /etc/config/openwisp is lost at each reboot, the device will not be able to download the config from OpenWISP Controller.

Some time ago, some OpenWISP users had the requirement of allowing people installing access points around cities to log in luci but just be able to set the LAN interface settings and nothing else, so we created https://github.com/openwisp/luci-openwisp/ which was based on a luci minimal version and allowed setting a password different than the root password. But the package we depended on is now unmtaintained and there's no maintainers around so this package doesn't work anymore.
But it sounds like you need something similar: avoid people to mess with the conf.

I would look for an alternative solution. Either disable luci access and disable SSH access with password, retaining only SSH access with public key, you should then give the SSH private key only to people who know what they're doing.

1 Like

Well... no one set the AP configuration manually but us pushed the config from OpenWISP controller.

It appears that even after a factory reset and the AP have the basic OpenWISP configuration baked in the firmware then it will apply its cloud configuration just fine after booted up, that's why I'm looking to completely disable the config save function of OpwnWrt so it will booted as firstboot on every reboot and reduce the chance of us wrongly configured the cloud config and brick its network access or something... once that happen all it needs is a reboot to connect back to the cloud again.

isn't this what -initramfs-kernel images do by default?

Yeah, that's exactly what I wanted... maybe I can just write that image to flash instead of the actual firmware? :stuck_out_tongue: don't know if sysupgrade would accept it though

I see no reason why it wouldn't flash. I think I ones did that when master output broken sysupgrade image for my device

Well... I just tried, it's complaining metadata not found, retry it with -F bricked it

Yes, if the firmware has the shared secret baked in the devices will register again each time.

1 Like

This is actually harder than I thought it would... I've tried to mount tmpfs to /overlay and /overlay/upper but it's still showing through for some reason... I've tried to put my script in /etc/rc.d and /lib/preinit but it doesn't seems to work also...

I just can't figure out how to unmount the already mounted overlayfs on top of /, if I managed to do this then I'll just create an overlayfs loop device in /tmp and then mount it on top of /

I don't want to run firstboot on every boot because it will shorten the flash lifespan

This is precisely why I said that if the firmware has all the needed details baked in (in this case, the OpenWISP-specific configuration), then it should be a walk in the park - just remove the overlay mounting bit and you're golden.

Another option would be to have an init.d script delete the contents of /overlay on every boot.

Might I ask, what package is not being maintained that is necessary for luci-openwisp? I've checked your Makefiles and it all seems pretty standard to me.

@minhng99 If I'm not mistaken, you could add an uci-defaults script that adds a tmpfs mount:

uci set fstab.overlay="mount"
uci set fstab.overlay.target="/overlay"
uci set fstab.overlay.device="tmpfs"
uci set fstab.overlay.fstype="tmpfs"
// You might need further settings:
// uci set fstab.overlay.options="remount,rw,nosuid,nodev,noatime,size=256M"
// uci set fstab.overlay.enabled_fsck="0"
// uci set fstab.overlay.enabled="1"

This should mount a tmpfs disk as /overlay on boot.

2 Likes

I double checked the code, seems you are right. I guess it just has to be updated and tested on the latest versions of OpenWRT.

Is there a limited luci version around still or was that stripped?

Both of those don't work, sadly...

[    9.010805] block: attempting to load /tmp/ubifs_cfg/upper/etc/config/fstab
[    9.021063] block: unable to load configuration (fstab: Entry not found)
[    9.027717] block: attempting to load /tmp/ubifs_cfg/etc/config/fstab
[    9.034786] block: unable to load configuration (fstab: Entry not found)
[    9.041021] block: attempting to load /etc/config/fstab
[    9.048927] block: unable to load configuration (fstab: Entry not found)
[    9.052746] block: no usable configuration
[    9.099407] UBIFS (ubi0:2): un-mount UBI device 0
[    9.100631] UBIFS (ubi0:2): background thread "ubifs_bgt0_2" stops
[    9.110468] UBIFS (ubi0:2): background thread "ubifs_bgt0_2" started, PID 185
[    9.216343] UBIFS (ubi0:2): UBIFS: mounted UBI device 0, volume 2, name "rootfs_data"
[    9.216386] UBIFS (ubi0:2): LEB size: 126976 bytes (124 KiB), min./max. I/O unit sizes: 2048 bytes/2048 bytes
[    9.223237] UBIFS (ubi0:2): FS size: 29585408 bytes (28 MiB, 233 LEBs), journal size 1523712 bytes (1 MiB, 12 LEBs)
[    9.233108] UBIFS (ubi0:2): reserved for root: 1397391 bytes (1364 KiB)
[    9.243316] UBIFS (ubi0:2): media format: w4/r0 (latest is w5/r0), UUID 90170F01-2AD7-4591-B81C-BA363FDA5C2F, small LPT model
[   10.113411] block: attempting to load /tmp/ubifs_cfg/upper/etc/config/fstab
[   10.113550] block: unable to load configuration (fstab: Entry not found)
[   10.119244] block: attempting to load /tmp/ubifs_cfg/etc/config/fstab
[   10.126383] block: unable to load configuration (fstab: Entry not found)
[   10.132569] block: attempting to load /etc/config/fstab
[   10.139316] block: unable to load configuration (fstab: Entry not found)
[   10.144296] block: no usable configuration
[   10.199213] mount_root: overlay filesystem has not been fully initialized yet
[   10.203572] mount_root: switching to ubifs overlay

after it booted first time with those configs integrated in uci-defaults, I tried to create a random file in /etc/ and after rebooted it's still there....

Thinking about it, you can't actually make this work because the overlayfs is already mounted before the uci-defaults get triggered...

also this happened when I preloaded the files/etc/config/fstab


[   15.933156] block: attempting to load /etc/config/fstab
[   15.940372] block: extroot: device not present, retrying in 5 seconds
[   21.824934] block: extroot: cannot find device tmpfs

I think you need to hack around in this folder https://github.com/openwrt/openwrt/tree/master/package/base-files/files/lib/preinit

especially on the 70_initramfs_test and 80_mount_root
as those should be the scripts responsible for mounting the overlay during preinit stage.

They are calling functions from this library script https://github.com/openwrt/openwrt/blob/master/package/base-files/files/lib/functions/preinit.sh

The first script is checking if the system is running as initramfs and maybe if you add a INITRAMFS=1 at the top before the code you can trick OpenWrt into thinking it is in an initramfs, and that it should mount stuff to RAM like it does when in an initramfs.
But I'm not really an expert on these parts, you might as well break stuff, so you should be ready to run a recovery from bootloader.

1 Like

@bobafetthotmail is right that likely you need to do things at the preinit phase. Doing things later via uci-defautls etc. is much more difficult as things are already mounted.

That INITRAMFS =1 settings might work.

To continue on that line, x86 has apprently functionality to detect if you are running from ISO image (=readonly), and then switch to "ramoverlay". Then you would have everything working "normally", but the overlay would be in RAM and all changes would be lost at reboot. That ramoverlay might be the cleanest (least invasive) approach.

PS. Important:
Note that as preinit is executed before the overlay is mounted, you need to edit the source files in your buildroot, and then compile and flash the image to test the changes. Trying to edit the preinit files in a live router is pointless, as the your changes are written to the overlay, which is enabled only later in the boot process. (I have stumbled upon that challenge at some times when I have tweaked the preinit files, and the reason for "non-functioning" is not easy to figure out...)

2 Likes

@minhng99 - I think I figured out how to mount a tmpfs overlay on root. The following works on my device, and Id think it would work on others, but idk for sure how portable it is. It does not, however, require modifying the source code and recompiling, which is nice.

Basically, this sets up an identical root filesystem at /newroot using bind mounts, with the only difference being that the overlay uses a tmpfs directory for upper overlay, and uses the /overlay/upper:/rom for lower overlay.

This makes it so that when when you write to the filesystem at / it goes to persistent overlay, and when you write to the filesystem at /newroot it goes to tmpfs overlay.

running pivot_root /newroot /newroot/oldroot switches the system to use the tmpfs overlay.

running pivot_root /oldroot /oldroot/newroot switches the system back to using the persistent overlay. Rebooting also would do this, but is not required to get the original configuration back.

Heres the code. Hope it is of some use to you.

# create directories and setup a dedicated tmpfs for the overlay
mkdir -p /newroot /oldroot /overlay_tmpfs
mount -t tmpfs tmpfs /overlay_tmpfs
chmod 755 /newroot /oldroot /overlay_tmpfs
mkdir -p /overlay_tmpfs/rom /overlay_tmpfs/lower /overlay_tmpfs/upper /overlay_tmpfs/work

# setup read-only bind mounts of '/rom' and '/overlay/upper' into '/overlay_tmpfs'
mount -o bind,ro /rom /overlay_tmpfs/rom
mount -o bind,ro /overlay/upper /overlay_tmpfs/lower

# setup tmpfs overlay (tmpfs <-- /overlay/upper <-- /rom) at '/newroot'
mount -t overlay -o rw,noatime,lowerdir=/overlay_tmpfs/lower:/overlay_tmpfs/rom,upperdir=/overlay_tmpfs/upper,workdir=/overlay_tmpfs/work/ overlayfs:/overlay_tmpfs /newroot

# bind-mount everything else into '/newroot'
cat /proc/mounts | awk '{print $2}' | grep -Fv '/newroot' | grep -Ev '^\/$' | while read -r nn; do mkdir -p "/newroot${nn}"; findmnt "/newroot${nn}" 1>/dev/null 2>/dev/null || mount -o bind "${nn}" "/newroot${nn}"; done

# THIS ENABLES THE TMPFS OVERLAY
# pivot root to '/newroot'
pivot_root /newroot /newroot/oldroot
wifi up
/etc/init.d/wpad restart
/etc/init.d/network restart

# THIS DISABLES THE TMPFS OVERLAY
# pivot root to '/oldroot'
pivot_root /oldroot /oldroot/newroot
wifi up
/etc/init.d/wpad restart
/etc/init.d/network restart
1 Like