├── .gitignore ├── LICENSE ├── README.md ├── build.sh ├── default.nix ├── image-extras ├── TLMR3020 │ └── etc │ │ └── config │ │ └── placeholder └── common │ ├── etc │ ├── config │ │ └── fstab │ ├── dropbear │ │ └── .gitignore │ ├── logrotate.d │ │ └── syslog.conf │ └── rc.local │ └── root │ ├── autoprovision-functions.sh │ ├── autoprovision-stage1.sh │ └── autoprovision-stage2.sh └── manifest.scm /.gitignore: -------------------------------------------------------------------------------- 1 | notes.txt 2 | build/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Attila Lendvai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # What 2 | 3 | It's a script to build a customized 4 | [OpenWrt](https://openwrt.org/docs/guide-user/start) 5 | firmware image using 6 | [ImageBuilder](https://openwrt.org/docs/guide-user/additional-software/imagebuilder). 7 | 8 | If the generated image is flashed on a router, then during its boot 9 | process it will try to set up 10 | [extroot](https://openwrt.org/docs/guide-user/additional-software/extroot_configuration) 11 | on **any (!)** storage device plugged into the USB port. Put another 12 | way, it unconditionally reformats `/dev/sda` if it fails to mount an 13 | extroot early in the boot process. 14 | 15 | # Why 16 | 17 | So that e.g. customers can buy a router on their own, download and flash our custom 18 | firmware, plug in a pendrive, and manage their SIP (telephony) node 19 | from our webapp. 20 | 21 | I've extracted the generic parts from the above mentioned auto-provision 22 | project because I thought it's useful enough for making it public. 23 | 24 | It also serves me well on my own routers ever since then. 25 | 26 | # How 27 | 28 | You can read more about the underlying technology on the OpenWrt wiki: see e.g. the 29 | [ImageBuilder](https://openwrt.org/docs/guide-user/additional-software/imagebuilder) 30 | page, or the page that lists some other 31 | [ImageBuilder frontends](https://openwrt.org/docs/guide-developer/imagebuilder_frontends). 32 | 33 | As for the actual mechanism: custom scripts are baked into the boot 34 | process of the flashed firmware. If the extroot overlay is properly 35 | set up, then these scripts get hidden by it; i.e. they will only be run 36 | when the extroot has failed to mount early in the boot process. 37 | 38 | Keep in mind that **this will automatically erase/format any inserted 39 | storage device while the router is in the initial setup phase**! 40 | Unfortunately there's little that can be done at that point to ask the 41 | user for confirmation. 42 | 43 | ### Building 44 | 45 | OpenWrt's ImageBuilder only works on Linux x86_64. To build a firmware, issue the following command: 46 | `./build.sh architecture variant device-profile`, e.g.: 47 | 48 | * `./build.sh ath79 generic tplink_tl-wr1043nd-v1` 49 | * `./build.sh ath79 generic tplink_archer-c6-v2` 50 | * `./build.sh ath79 generic tplink_tl-wdr4300-v1` 51 | * `./build.sh bcm53xx generic dlink_dir-885l` 52 | 53 | Results will be under `build/openwrt-imagebuilder-${release}-${architecture}-${variant}.Linux-x86_64/bin/`. 54 | 55 | To see a list of available targets, run `make info` in the ImageBuilder dir. 56 | 57 | If you want to change which OpenWrt version is used, then try editing 58 | the relevant variable(s) in `build.sh`. It's not guaranteed to work 59 | across OpenWrt releases, therefore we keep git branches for the past 60 | releases. 61 | 62 | ### Setup stages 63 | 64 | Blinking leds show which phase the extroot setup scripts are in. Consult the 65 | sources for details: [autoprovision-functions.sh](image-extras/common/root/autoprovision-functions.sh#L49). 66 | 67 | #### Stage 1: setup extroot 68 | 69 | When the custom firmware first boots, the autoprovision script will 70 | wait for anything (!) in `/dev/sda` to show up (that is >= 512M), then erase 71 | it and set up a `swap`, an `extroot`, and a `data`filesystem (for the remaining 72 | space), and then reboot. 73 | 74 | #### Stage 2: download and install some packages from the internet 75 | 76 | Once it rebooted into the new extroot, it will continuously keep trying to install 77 | some OpenWrt packages until an internet connection is set up on the router. You 78 | need to do that manually either by using ssh or the web UI (LuCI). 79 | 80 | #### Stage 3, optional 81 | 82 | We also have a 3rd stage, written in Python, but it's commented out here. 83 | Search for `autoprovision-stage3.py` to see how it's done. 84 | 85 | ### Login 86 | 87 | After flashing the firmware the router will have the standard 88 | `192.168.1.1` IP address. 89 | 90 | By default the root passwd is not set, so the router will start telnet with 91 | no password. If you want to set up a password, then edit the stage 2 script: 92 | [autoprovision-stage2.sh](image-extras/common/root/autoprovision-stage2.sh#L53). 93 | 94 | If a password is set, then telnet is disabled by OpenWrt and SSH will listen 95 | using the keys specified in [authorized_keys](image-extras/common/etc/dropbear/authorized_keys). 96 | 97 | Once connected, you can read the log with `logread -f`. 98 | 99 | ### Upgrading 100 | 101 | I have kinda succeeded to upgrade an installation from `24.10.0-rc4` 102 | to `24.10.1` using the following steps: 103 | 104 |
105 | 106 | - build a new image.bin using openwrt-auto-extroot: `./build.sh ath79 generic tplink_tl-wdr4300-v1` 107 | 108 | - `scp image.bin root@router.lan:/tmp/` 109 | 110 | - `sysupgrage -c -o /tmp/image.bin` 111 | 112 | - the new version came back online (into a non-trivial network setup 113 | with vlans!) 114 | 115 | - Edit the version of the `kernel` package in the opkg database: `nano 116 | /usr/lib/opkg/status` and edit the entry for `Package: kernel`: 117 | update the version to the new one, 118 | `6.6.86~64576e1418bd4546fdb49285deb3b11c-r1` in this case. I looked 119 | up the new version by `find . | grep kernel` in the ImageBuilder 120 | directory. Without this step the `kmod-*` packages fail to upgrade 121 | due to the missing kernel dependency. The kernel package itself is 122 | not listed in the opkg package database, because you need to use 123 | sysupgrade to update the kernel. 124 | 125 | - `opkg update` 126 | 127 | - `opkg list-upgradable | cut -f 1 -d ' ' | xargs -r opkg upgrade` 128 | 129 | - ?! somehow once the extroot disappeared (got unmounted?), but then 130 | it came back after a reboot. 131 | 132 | - most things worked fine, but e.g. usteer failed to start (`Command 133 | failed: Request timed out`), and opkg was printing strange errors 134 | (`* pkg_get_installed_files: Failed to open 135 | //usr/lib/opkg/info/libuci20130104.list: No such file or 136 | directory.`). 137 | 138 | - At this point I have decided to reinstall the router using my uci 139 | based script. Patches are welcome for the upgrade instructions. 140 |
141 | 142 | # Status 143 | 144 | This is more of a template than something standalone, but I use it for 145 | my home routers as is for years now. For more specific applications 146 | you most probably want to customize this script here and there; search 147 | for `CUSTOMIZE` for places of interest. 148 | 149 | Most importantly, **set up a password and maybe add your ssh key** by 150 | adding it to `image-extras/common/etc/dropbear/authorized_keys`. 151 | 152 | None of this script is hardware specific except `setLedAttribute`, 153 | which is used to provide feedback about the progress of the initial 154 | setup phase. At the time of writing it only works on a few routers 155 | (mostly `ath79` ones), but without this everything should work fine, 156 | if only a bit less convenient. 157 | 158 | # Troubleshooting 159 | 160 | ## Which file should I flash? 161 | 162 | You should consult the [OpenWrt documentation](https://openwrt.org/docs/guide-user/start). 163 | The produced firmware files should be somewhere around 164 | ```./build/openwrt-imagebuilder-21.02.0-ath79-generic.Linux-x86_64/bin/targets/ath79/generic/```. 165 | 166 | In short: 167 | 168 | * You need a file with the name ```-factory.bin``` or ```-sysupgrade.bin```. The former is to 169 | be used when you first install OpenWrt, the latter is when you upgrade an already installed 170 | OpenWrt. 171 | 172 | * You must carefully pick the proper firmware file for your **hardware version**! I advise you 173 | to look up the wiki page for your hardware on the [OpenWrt wiki](https://openwrt.org), 174 | because most of them have a table of the released hardware versions with comments on their 175 | status (sometimes new hardware revisions are only supported by the latest OpenWrt, which is 176 | not released yet). 177 | 178 | ## Help! The build has finished but there's no firmware file! 179 | 180 | If the build doesn't yield a firmware file (```*-factory.bin``` and/or ```*-sysupgrade.bin```): 181 | when there's not enough space in the flash memory of the target device to install everything 182 | then the OpenWrt ImageBuilder prints a hardly visible error into its flow of output and 183 | silently continues. Look into [build.sh](build.sh#L31) and try to remove some packages 184 | that you can live without. 185 | 186 | ## Extroot is not mounted after a `sysupgrade` 187 | 188 | In short, this is an OpenWrt issue, and the solution is to mount the extroot 189 | somewhere, and delete `/etc/.extroot-uuid`. More details are available in 190 | [this issue](https://github.com/attila-lendvai/openwrt-auto-extroot/issues/12), 191 | and a way to deal with it can be found in 192 | [this blog post](https://blog.mbirth.de/archives/2014/05/26/openwrt-sysupgrade-with-extroot.html). 193 | You may also want to check out the 194 | [official OpenWrt wiki](https://openwrt.org/docs/guide-user/additional-software/extroot_configuration#system_upgrade) 195 | on this topic. 196 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Note: this runs as-is, pretty much without external 4 | # dependencies. The OpenWrt ImageBuilder contains the toolchain and 5 | # everything that is needed to build the firmware images. 6 | 7 | set -e 8 | 9 | TARGET_ARCHITECTURE=$1 10 | TARGET_VARIANT=$2 11 | TARGET_DEVICE=$3 12 | 13 | BUILD="$(dirname "${0}")/build/" 14 | BUILD="$(readlink -f "${BUILD}")" 15 | 16 | ### 17 | ### chose a release 18 | ### 19 | RELEASE="24.10.1" 20 | 21 | IMGBUILDER_NAME="openwrt-imagebuilder-${RELEASE}-${TARGET_ARCHITECTURE}-${TARGET_VARIANT}.Linux-x86_64" 22 | IMGBUILDER_DIR="${BUILD}/${IMGBUILDER_NAME}" 23 | IMGBUILDER_ARCHIVE="${IMGBUILDER_NAME}.tar.zst" 24 | 25 | IMGTEMPDIR="${BUILD}/image-extras" 26 | # see this feature request: 27 | # FS#1670 - consistent naming convention for the imagebuilder.tar.xz URL 28 | # https://bugs.openwrt.org/index.php?do=details&task_id=1670 29 | IMGBUILDERURL="https://downloads.openwrt.org/releases/${RELEASE}/targets/${TARGET_ARCHITECTURE}/${TARGET_VARIANT}/${IMGBUILDER_ARCHIVE}" 30 | 31 | if [ -z ${TARGET_DEVICE} ]; then 32 | echo "Usage: $0 architecture variant device-profile" 33 | echo " e.g.: $0 ath79 generic tplink_tl-wr1043nd-v1" 34 | echo " $0 ath79 generic tplink_archer-c6-v2" 35 | echo " $0 ath79 generic tplink_tl-wdr4300-v1" 36 | echo " $0 bcm53xx generic dlink_dir-885l" 37 | echo " to get a list of supported devices issue a 'make info' in the OpenWRT image builder directory:" 38 | echo " '${IMGBUILDER_DIR}'" 39 | echo " the build results will be under '${IMGBUILDER_DIR}/bin/targets/'" 40 | kill -INT $$ 41 | fi 42 | 43 | # the absolute minimum for extroot to work at all (i.e. when the disk is already set up, for example by hand). 44 | # this list may be smaller and/or different for your router, but it works with my ath79. 45 | # blockdev is needed to re-read the partition table using `blockdev --rereadpt /dev/sdX` 46 | PREINSTALLED_PACKAGES="block-mount kmod-fs-ext4 kmod-usb-storage blockdev" 47 | 48 | # some kernel modules may also be needed for your hardware 49 | #PREINSTALLED_PACKAGES+=" kmod-usb-uhci kmod-usb-ohci" 50 | 51 | # these are needed for the proper functioning of the auto extroot scripts 52 | PREINSTALLED_PACKAGES+=" blkid mount-utils swap-utils e2fsprogs fdisk" 53 | 54 | # the following packages are optional, feel free to (un)comment them 55 | PREINSTALLED_PACKAGES+=" firewall4" 56 | #PREINSTALLED_PACKAGES+=" wireless-tools" 57 | #PREINSTALLED_PACKAGES+=" kmod-usb-storage-extras kmod-mmc" 58 | #PREINSTALLED_PACKAGES+=" ppp ppp-mod-pppoe ppp-mod-pppol2tp ppp-mod-pptp kmod-ppp kmod-pppoe" 59 | PREINSTALLED_PACKAGES+=" luci" 60 | 61 | # you exclude packages with this to shrink the image for 62 | # routers with smaller flash storage. 63 | # SAVE_SPACE_PACKAGES=" -ppp -ppp-mod-pppoe -ip6tables -odhcp6c -kmod-ipv6 -kmod-ip6tables -ath10k" 64 | SAVE_SPACE_PACKAGES="" 65 | 66 | PREINSTALLED_PACKAGES+=${SAVE_SPACE_PACKAGES} 67 | 68 | mkdir -pv "${BUILD}" 69 | 70 | rm -rf "${IMGTEMPDIR}" 71 | cp -r image-extras/common/ "${IMGTEMPDIR}" 72 | PER_PLATFORM_IMAGE_EXTRAS="image-extras/${TARGET_DEVICE}/" 73 | if [ -e "${PER_PLATFORM_IMAGE_EXTRAS}" ]; then 74 | rsync -pr "${PER_PLATFORM_IMAGE_EXTRAS}" "${IMGTEMPDIR}/" 75 | fi 76 | 77 | if [ ! -e "${IMGBUILDER_DIR}" ]; then 78 | pushd "${BUILD}" 79 | # --no-check-certificate if needed 80 | wget --continue "${IMGBUILDERURL}" 81 | zstd --decompress <"${IMGBUILDER_ARCHIVE}" | tar vx 82 | popd 83 | fi 84 | 85 | pushd "${IMGBUILDER_DIR}" 86 | 87 | make image PROFILE=${TARGET_DEVICE} PACKAGES="${PREINSTALLED_PACKAGES}" FILES=${IMGTEMPDIR} 88 | 89 | pushd "bin/targets/${TARGET_ARCHITECTURE}/" 90 | ln -sf ../../../packages . 91 | popd 92 | 93 | popd 94 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | { pkgs ? import {} }: 2 | 3 | pkgs.mkShell { 4 | buildInputs = with pkgs; [ 5 | coreutils posix_man_pages bash-completion less 6 | gitFull diffutils 7 | gnumake which 8 | ncurses perl python2 python3 9 | 10 | # keep this line if you use bash 11 | bashInteractive 12 | ]; 13 | 14 | shellHook = 15 | '' 16 | alias ..='cd ..' 17 | alias ...='cd ../..' 18 | ''; 19 | } 20 | -------------------------------------------------------------------------------- /image-extras/TLMR3020/etc/config/placeholder: -------------------------------------------------------------------------------- 1 | # this is just a file to show how platform specific image extras can be specified 2 | -------------------------------------------------------------------------------- /image-extras/common/etc/config/fstab: -------------------------------------------------------------------------------- 1 | config global 2 | option anon_swap '0' 3 | option anon_mount '0' 4 | option auto_swap '0' 5 | option auto_mount '0' 6 | option delay_root '3' 7 | option check_fs '0' 8 | 9 | config swap 10 | option uuid '05d615b3-bef8-460c-9a23-52db8d09e002' 11 | option enabled '1' 12 | 13 | config mount 'extroot' 14 | option target '/overlay' 15 | option uuid '05d615b3-bef8-460c-9a23-52db8d09e000' 16 | option fstype 'ext4' 17 | option options 'rw,noatime' 18 | option enabled '1' 19 | option enabled_fsck '0' 20 | 21 | config mount 'data' 22 | option target '/mnt/data' 23 | option uuid '05d615b3-bef8-460c-9a23-52db8d09e001' 24 | option fstype 'ext4' 25 | option options 'rw,noatime' 26 | option enabled '1' 27 | option enabled_fsck '0' 28 | -------------------------------------------------------------------------------- /image-extras/common/etc/dropbear/.gitignore: -------------------------------------------------------------------------------- 1 | # you can put your ssh public key into authorized_keys, 2 | # but we don't ever want it to be committed to the repo 3 | authorized_keys 4 | -------------------------------------------------------------------------------- /image-extras/common/etc/logrotate.d/syslog.conf: -------------------------------------------------------------------------------- 1 | /var/log/syslog 2 | { 3 | olddir archive 4 | rotate 30 5 | daily 6 | dateext 7 | notifempty 8 | missingok 9 | copytruncate 10 | } 11 | -------------------------------------------------------------------------------- /image-extras/common/etc/rc.local: -------------------------------------------------------------------------------- 1 | # Put your custom commands here that should be executed once 2 | # the system init finished. By default this file does nothing. 3 | 4 | /root/autoprovision-stage1.sh 5 | 6 | exit 0 7 | -------------------------------------------------------------------------------- /image-extras/common/root/autoprovision-functions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # utility functions for the various stages of autoprovisioning 4 | 5 | # make sure that installed packages take precedence over busybox. see https://dev.openwrt.org/ticket/18523 6 | PATH="/usr/bin:/usr/sbin:/bin:/sbin" 7 | 8 | # these are also copy-pasted into other scripts and config files! 9 | rootUUID=05d615b3-bef8-460c-9a23-52db8d09e000 10 | dataUUID=05d615b3-bef8-460c-9a23-52db8d09e001 11 | swapUUID=05d615b3-bef8-460c-9a23-52db8d09e002 12 | 13 | . /lib/functions.sh 14 | 15 | # let's attempt to define some defaults... 16 | autoprovisionUSBLed="green:usb" 17 | autoprovisionStatusLed="green:qss" 18 | 19 | echo Board name is [$(board_name)] 20 | 21 | # CUSTOMIZE 22 | case $(board_name) in 23 | *tl-wr1043nd*) 24 | autoprovisionUSBLed="green:usb" 25 | autoprovisionStatusLed="green:qss" 26 | ;; 27 | *tl-mr3020*) 28 | autoprovisionUSBLed="green:wps" 29 | autoprovisionStatusLed="green:wlan" 30 | ;; 31 | *tl-wr2543n*) 32 | autoprovisionUSBLed="green:wps" 33 | autoprovisionStatusLed="green:wlan5g" 34 | ;; 35 | *tl-wdr3600* | *tl-wdr4300*) 36 | autoprovisionUSBLed="green:wlan2g" 37 | autoprovisionStatusLed="green:wlan5g" 38 | ;; 39 | *mynet-n750*) 40 | autoprovisionUSBLed="blue:wps" 41 | autoprovisionStatusLed="blue:wireless" 42 | ;; 43 | *archer-c7-v1*) 44 | autoprovisionUSBLed="green:wlan2g" 45 | autoprovisionStatusLed="green:wlan5g" 46 | ;; 47 | esac 48 | 49 | 50 | log() 51 | { 52 | /usr/bin/logger -t autoprov -s $* 53 | } 54 | 55 | setLedAttribute() 56 | { 57 | [ -f "/sys/class/leds/$1/$2" ] && echo "$3" > "/sys/class/leds/$1/$2" 58 | } 59 | 60 | signalAutoprovisionWorking() 61 | { 62 | setLedAttribute ${autoprovisionStatusLed} trigger none 63 | setLedAttribute ${autoprovisionStatusLed} trigger timer 64 | setLedAttribute ${autoprovisionStatusLed} delay_on 2000 65 | setLedAttribute ${autoprovisionStatusLed} delay_off 2000 66 | } 67 | 68 | signalAutoprovisionWaitingForUser() 69 | { 70 | setLedAttribute ${autoprovisionStatusLed} trigger none 71 | setLedAttribute ${autoprovisionStatusLed} trigger timer 72 | setLedAttribute ${autoprovisionStatusLed} delay_on 200 73 | setLedAttribute ${autoprovisionStatusLed} delay_off 300 74 | } 75 | 76 | signalWaitingForPendrive() 77 | { 78 | setLedAttribute ${autoprovisionUSBLed} trigger none 79 | setLedAttribute ${autoprovisionUSBLed} trigger timer 80 | setLedAttribute ${autoprovisionUSBLed} delay_on 200 81 | setLedAttribute ${autoprovisionUSBLed} delay_off 300 82 | } 83 | 84 | signalFormatting() 85 | { 86 | setLedAttribute ${autoprovisionUSBLed} trigger none 87 | setLedAttribute ${autoprovisionUSBLed} trigger timer 88 | setLedAttribute ${autoprovisionUSBLed} delay_on 1000 89 | setLedAttribute ${autoprovisionUSBLed} delay_off 1000 90 | } 91 | 92 | stopSignallingAnything() 93 | { 94 | # TODO this is wrong, they should be restored to their original state. 95 | # but then leds are only touched in the setup stage, which is ephemeral when things work as expected... 96 | setLedAttribute ${autoprovisionStatusLed} trigger none 97 | setLedAttribute ${autoprovisionUSBLed} trigger usbdev 98 | } 99 | 100 | setRootPassword() 101 | { 102 | local password=$1 103 | if [ "$password" == "" ]; then 104 | # set and forget a random password merely to disable telnet. login will go through ssh keys. 105 | password=$(/dev/null 14 | fi 15 | 16 | if (grep -q sda /proc/partitions) then 17 | cat /sys/block/sda/size 18 | else 19 | echo 0 20 | fi 21 | } 22 | 23 | hasBigEnoughPendrive() 24 | { 25 | local size=$(getPendriveSize) 26 | if [ $size -ge 100000 ]; then 27 | log "Found a pendrive of size: $(($size / 2 / 1024)) MB" 28 | return 0 29 | else 30 | return 1 31 | fi 32 | } 33 | 34 | rereadPartitionTable() 35 | { 36 | log "Rereading partition table" 37 | blockdev --rereadpt /dev/sda 38 | } 39 | 40 | setupPendrivePartitions() 41 | { 42 | log "Erasing partition table" 43 | # TODO find a way to keep the data partition/fs when already present. 44 | # erase partition table 45 | dd if=/dev/zero of=/dev/sda bs=1k count=256 46 | 47 | rereadPartitionTable 48 | 49 | log "Creating partitions" 50 | # sda1 is 'swap' 51 | # sda2 is 'root' 52 | # sda3 is 'data', if there's any space left 53 | fdisk /dev/sda <${overlay_root}/etc/rc.local < /tmp symlink in the new extroot, so that /var becomes persistent across reboots. 113 | # mkdir -p ${overlay_root}/var 114 | # KLUDGE: /var/state is assumed to be transient, so link it to tmp, see https://dev.openwrt.org/ticket/12228 115 | # cd ${overlay_root}/var 116 | # ln -s /tmp state 117 | # cd - 118 | 119 | disableStage1 120 | 121 | log "Finished setting up extroot" 122 | } 123 | 124 | disableStage1() 125 | { 126 | # FIXME it would be more future-proof to transform the rc.local file 127 | # instead of overwriting it. 128 | cat >/etc/rc.local <manifest 10 | '("coreutils" 11 | "bash" 12 | "make" 13 | "perl" 14 | "gcc-toolchain" 15 | "git" 16 | "git:gui" 17 | ;; "man-pages" 18 | "less" 19 | "time")) 20 | --------------------------------------------------------------------------------