Конфігурація Extroot

Цей посібник описує, як налаштувати OpenWrt для використання зовнішнього носія (USB, SATA, SD-картки або іншого) для розширення кореневої файлової системи, щоб мати змогу встановлювати всі необхідні пакети.

У більшості підтримуваних пристроїв OpenWrt розділяє внутрішню пам’ять на розділи rootfs та rootfs_data або ubifs, які об'єднуються в єдину придатну для запису файлову систему типу overlay.

Розділ Точка монтування Стиснення Запис
rootfs /rom Так Ні
rootfs_data
ubifs
/overlay
/rom/overlay
Ні Так
overlay / Незмінені файли Так

Таким чином, OpenWrt може працювати навіть на пристроях із дуже обмеженим обсягом внутрішньої пам’яті (від 4 МіБ), залишаючи можливість зберігати налаштування та встановлювати деякі пакети.

Extroot працює шляхом монтування нової розділу overlay з зовнішнього носія поверх внутрішнього під час завантаження. Це дозволяє легко повернутись до внутрішньої overlay у разі відключення зовнішнього накопичувача — пристрій завантажиться з власної overlay та працюватиме так само, як до налаштування extroot.

Відомо, що OpenWrt ігнорує конфігурацію fstab на пристроях, у яких відсутній розділ overlay у ``/proc/mtd``. Обхідним шляхом є використання ``/`` як точки монтування.

Наступні інструкції передбачають, що ви вже маєте доступ до shell на вашому пристрої OpenWrt. Більшість команд можна виконати через веб-інтерфейс, але це не рекомендується.

Доступ до shell зазвичай отримують через SSH або послідовний порт.

Пристрої з флеш-пам’яттю 8 МіБ або більше зазвичай мають достатньо місця для встановлення необхідних пакетів. В іншому разі створіть кастомний образ.

Видаліть усі пакети, встановлені для вторинного функціоналу — вони просто займають місце. Якщо ви не пам’ятаєте, що саме встановлювали — спробуйте видалити 'ntfs', це може звільнити простір.

Залиште лише ті пакети, які потрібні для доступу до Інтернету та extroot.

У деяких випадках достатньо буде використати офіційний OEM-образ (наприклад, OpenWRT GL.inet для GL.inet Mango).

Extroot може бути будь-яким пристроєм, який може монтувати утиліта ``block``. Підтримувані файлові системи: ext2/3/4, f2fs, btrfs, ntfs або ubifs (зверніть увагу, що FAT16/32 не підтримуються).

Найчастіше це USB-накопичувач, але також це може бути SD-картка, SATA-диск, мережевий пристрій тощо.

Якщо ви використовуєте USB-пристрій, налаштуйте його згідно з інструкцією зі встановлення за допомогою USB.

Нижче передбачено, що extroot створюється на USB-накопичувачі з файловою системою EXT4.

Установка необхідних пакетів вимагає значного обсягу вільного місця. Якщо система переповниться — доведеться прошивати все заново.

Встановіть необхідні пакети:

opkg update
opkg install block-mount kmod-fs-ext4 e2fsprogs parted kmod-usb-storage

Якщо ви використовуєте SSD в USB-кейсі, можливо, також потрібно встановити `kmod-usb-storage-uas`.

Перевірте назву USB-диска:

ls -l /sys/block

Розмітьте диск та створіть файлову систему:

DISK="/dev/sda"
parted -s ${DISK} -- mklabel gpt mkpart extroot 2048s -2048s
DEVICE="${DISK}1"
mkfs.ext4 -L extroot ${DEVICE}

Увага: ці команди зітруть усі дані на диску.

Налаштуйте монтування extroot:

eval $(block info ${DEVICE} | grep -o -e 'UUID="\S*"')
eval $(block info | grep -o -e 'MOUNT="\S*/overlay"')
uci -q delete fstab.extroot
uci set fstab.extroot="mount"
uci set fstab.extroot.uuid="${UUID}"
uci set fstab.extroot.target="${MOUNT}"
uci commit fstab

Додайте запис для монтування оригінальної внутрішньої overlay:

ORIG="$(block info | sed -n -e '/MOUNT="\S*\/overlay"/s/:\s.*$//p')"
uci -q delete fstab.rwm
uci set fstab.rwm="mount"
uci set fstab.rwm.device="${ORIG}"
uci set fstab.rwm.target="/rwm"
uci commit fstab

Це дозволить вам мати доступ до внутрішньої overlay (rootfs_data / ubifs) за шляхом `/rwm`.

Скопіюйте поточну overlay на extroot:

mount ${DEVICE} /mnt
tar -C ${MOUNT} -cvf - . | tar -C /mnt -xf -

Перезавантажте пристрій:

reboot
  1. LuCI → System → Mount Points має показати, що USB-розділ змонтовано як overlay.
  2. LuCI → System → Software має показати вільний простір у розділі overlay.

Розділ USB повинен бути змонтований у /overlay. Вільне місце на / повинно відповідати /overlay.

# grep -e /overlay /etc/mtab
/dev/sda1 /overlay ext4 rw,relatime,data=ordered
overlayfs:/overlay / overlay rw,noatime,lowerdir=/,upperdir=/overlay/upper,workdir=/overlay/work
 
# df /overlay /
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda1              7759872    477328   7221104   6% /overlay
overlayfs:/overlay     7759872    477328   7221104   6% /
  • Проаналізуйте етап preinit у журналі завантаження:
block info; uci show fstab; logread | sed -n -e "/- preinit -/,/- init -/p"
  • Якщо після оновлення ви бачите повідомлення «block: extroot: UUID mismatch», видаліть файли .extroot-uuid з диску:
mount /dev/sda1 /mnt
rm -f /mnt/.extroot-uuid /mnt/etc/.extroot-uuid
umount /mnt
  • Не використовуйте файлову систему vfat (FAT/FAT32) — вона не підтримується. Якщо ваш USB-накопичувач відформатований у FAT, переформатуйте його в ext4 (встановіть пакет `e2fsprogs`, а потім запустіть `mkfs.ext4 /dev/sda1`).
  • Якщо extroot не монтується під час завантаження, але його можна змонтувати вручну, спробуйте збільшити затримку параметра ``delay_root``. Наприклад, до 15 секунд:
uci set fstab.@global[0].delay_root="15"
uci commit fstab
  • ⚠️ Можливо застаріло: додайте опцію force_space у ``/etc/opkg.conf``, щоб дозволити встановлення пакетів, які більші за вільне місце у ``/rom``:
echo option force_space >> /etc/opkg.conf
  • Ще один варіант — змінити файл ``/etc/rc.local``, як описано у тікеті #14946. Це допомогло, наприклад, на Chaos Calmer r44266 (Comtrend AR-5387un):
export PREINIT=1
mount_root
  • Якщо ви використовуєте не USB-пристрій для extroot, а наприклад MMC-картку, переконайтеся, що необхідні модулі ядра додані у файл ``/etc/modules-boot.d``. Наприклад, для sdhci на пристроях mt7688/mt7628 додайте до ``/etc/modules-boot.d/mmc`` такі рядки:
mmc_core
mmc_block
sdhci
mtk_sd

Зберігайте списки `opkg` у директорії /usr/lib/opkg/lists на extroot-носії, замість оперативної памʼяті. Це дозволить зберегти списки після перезавантаження і зменшить використання RAM.

Інструкції через веб-інтерфейс

  1. Перейдіть до LuCI → System → Software → Configuration і змініть значення з /var/opkg-lists на /usr/lib/opkg/lists.
  2. Потім перейдіть до LuCI → System → Software → Actions → Update lists, щоб вперше згенерувати список пакетів на extroot.

Інструкції через командний рядок

sed -i -e "/^lists_dir\s/s:/var/opkg-lists$:/usr/lib/opkg/lists:" /etc/opkg.conf
opkg update

Якщо ваш пристрій має мало оперативної памʼяті (наприклад 32MB) і не вдається зчитати списки, увімкніть підкачку:

# Створення swap-файлу
DIR="$(uci -q get fstab.extroot.target)"
dd if=/dev/zero of=${DIR}/swap bs=1M count=100
mkswap ${DIR}/swap
 
# Увімкнення swap-файлу
uci -q delete fstab.swap
uci set fstab.swap="swap"
uci set fstab.swap.device="${DIR}/swap"
uci commit fstab
service fstab boot
 
# Перевірка статусу
cat /proc/swaps

Рекомендується включити утиліту usb-modeswitch у прошивку.

Однак існує важливе застереження: якщо /overlay монтується з картки пам’яті, що вставлена в кардрідер USB-донгла — то конфігурація pivot overlay, яка інакше працює, зламається на пізніших етапах завантаження системи.

Це відбувається тому, що usb-modeswitch (вимикаючи CDROM і вмикаючи модем) тимчасово впливає на кардрідер, порушуючи файлову систему.

Щоб уникнути цієї проблеми, використовуйте донгл, який можна попередньо сконфігурувати так, щоб модем або мережевий адаптер (та кардрідер) активувалися автоматично при подачі живлення — без використання usb-modeswitch на маршрутизаторі.

Попереднє налаштування донгла

1. Вставте донгл у настільний ПК. 2. Відкрийте термінал і надішліть AT-команди.

Перевірте початкову конфігурацію донгла:

at^setport?
^SETPORT:A1,A2;1,3,2,A1,A2
OK

Пояснення кодів доступних функцій:

at^setport=?
^SETPORT:A1: CDROM
^SETPORT:A2: SD
^SETPORT:A:  BLUETOOTH
^SETPORT:B:  FINGER PRINT
^SETPORT:D:  MMS
^SETPORT:E:  PC VOICE
^SETPORT:1:  MODEM
^SETPORT:2:  PCUI
^SETPORT:3:  DIAG
^SETPORT:4:  PCSC
^SETPORT:5:  GPS
^SETPORT:6:  GPS CONTROL
^SETPORT:16: NCM
OK

У прикладі вище:

  • Перша конфігурація (до символу ;) містить CDROM (A1) і кардрідер (A2).
  • Друга (після ;) — модем (1), діагностику (3), інтерфейс керування (2) та знову CDROM (A1) і кардрідер (A2).

Саме між цими двома конфігураціями usb-modeswitch перемикає пристрій.

Мета налаштування

Вимкнути CDROM (A1), увімкнути модем (1) або мережевий адаптер (16), та залишити активним кардрідер (A2).

ВАЖЛИВО: Ніколи не вимикайте PCUI (2) — ви втратите доступ до модему!

Застосування команди ''disable all''

Деякі модеми підтримують спеціальну команду 'disable all' (код FF), яка очищає наявні конфігурації.

Нижче наведено приклад для повного вимкнення та задання бажаних інтерфейсів:

at^setport="ff;1,2,3,a2"
OK
 
at^reset
OK
 
at^setport?
^SETPORT:;1,2,3,A2
OK

У результаті:

  • CDROM вимкнено;
  • активні: модем (1), PCUI (2), діагностика (3), кардрідер (A2);
  • лише одна конфігурація — немає нічого ліворуч від символу ;.

Підтримка попереднього налаштування

Модем Huawei E3131s-2 з прошивкою v21.158.47.00.1094 підтримує попереднє конфігурування.

Ви можете захотіти розмістити файлову систему extroot у зашифрованому контейнері LUKS. Починаючи з OpenWrt 22.03.2, це не підтримується належним чином. OpenWrt не має офіційного способу для розшифрування LUKS-розділів до того, як відбудеться перевірка extroot під час стандартного процесу завантаження. Отже, під час цієї перевірки зашифрований extroot буде невидимий, і процес завантаження продовжиться, як ніби extroot не налаштований.

Нижче описано два методи, які дозволяють запустити систему на зашифрованому extroot. Перший метод є кращим, оскільки має менше побічних ефектів і є більш елегантним рішенням.

Перш ніж продовжити, необхідно створити LUKS-контейнер, в якому буде розміщено файлову систему extroot. Скористайтеся документацією шифрування диска, щоб налаштувати LUKS-контейнер на вашому пристрої. Вам потрібно мати достатньо вільного місця у розділі rootfs_data для встановлення пакету cryptsetup та його залежностей.

Коли LUKS-контейнер буде готовий, дотримуйтесь інструкцій зі створення файлової системи extroot на розблокованому пристрої, включаючи копіювання файлів з /overlay до новоствореного extroot.

PREINIT

У фазі PREINIT процесу завантаження виконується команда mount_root, яка спочатку перевіряє наявність конфігурації extroot на ROM-пристрої, а потім на пристрої ''rootfs_data'' (див. Схема флеш-пам'яті OpenWrt для деталей).

У стандартній прошивці OpenWrt конфігурація extroot у ROM відсутня. Для перевірки файлової системи rootfs_data mount_root монтує її у тимчасовий каталог (/tmp/overlay), потім перевіряє файл /tmp/overlay/etc/config/fstab — той самий, що був налаштований раніше, — на наявність extroot.

Якщо конфігурація знайдена, послідовно шукаються виконувані файли /tmp/overlay/upper/sbin/block, /tmp/overlay/sbin/block та /sbin/block. Знайдений файл виконується з аргументом extrootце відбувається тут. Тому для роботи extroot потрібно встановити пакет block-mount.

Оскільки mount_root під час PREINIT запускається з ROM, але намагається виконати block з overlay-файлової системи, цим можна скористатися, щоб вставити власні команди у фазу PREINIT до перевірки extroot.

Це реалізується створенням скрипта, який замінює оригінальний бінарник block. Цей скрипт:

  • розшифровує LUKS-пристрій;
  • робить доступною файлову систему extroot;
  • викликає справжній block.

Скрипт використовує decrypt.sh з посібника зі шифрування дисків. Спершу виконайте install-decrypt.sh.

Щоб встановити скрипт:

  • перемістіть /sbin/block у /sbin/block.bin;
  • збережіть новий block-скрипт у /sbin/block і зробіть його виконуваним.

Скрипт перевіряє наявність файлу /.use_crypt_extroot у змонтованому overlayfs (або /upper/.use_crypt_extroot у /overlay) — якщо файл відсутній, extroot не буде налаштований. Це дозволяє легко відключити зашифрований extroot у разі потреби, наприклад, у failsafe-режимі.

Коли:

  • block скрипт встановлено;
  • decrypt.sh присутній;
  • налаштований /etc/crypttab;
  • extroot змонтовано;
  • файл /.use_crypt_extroot існує —

можна перезавантажити пристрій для входу в зашифрований extroot.

block
#!/bin/sh
 
# Залежності:
#  * пакети:
#    * block-mount
#    * cryptsetup
#  * перемістіть /sbin/block → /sbin/block.bin
#  * встановіть decrypt.sh у /sbin/decrypt.sh з правами на виконання
 
# Цей скрипт повинен бути у /upper/sbin/block (UBIFS overlay)
# або у /sbin/block, якщо overlay вже активний.
 
export DEBUG=
 
SDIR=${0%/*}
BLOCK="${SDIR}/block.bin"
LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-.}
LD_LIBRARY_PATH="${SDIR}/../usr/lib:${LD_LIBRARY_PATH}"
PATH=$PATH:${SDIR}:${SDIR}/../usr/sbin:${SDIR}/../usr/bin
 
block() {
  ( exec -a ${0} ${BLOCK} "$@" )
}
 
if [ "$PREINIT" != "1" ]; then
  exec block "$@"
fi
 
get_jiffies() {
  head -n3 /proc/timer_list | tail -n1 | cut -d' ' -f 3
}
 
if [ -z "$BLOCK_LOG" ] && [ -n "$DEBUG" ]; then
  TIME=$(get_jiffies)
  export BLOCK_LOG="/tmp/block.$(printf '%016d' ${TIME:-9999999999}).log"
  exec 2>"$BLOCK_LOG"
  set -x
fi
 
if [ ! -x "$BLOCK" ]; then
  echo "Error: ${BLOCK} is not an executable" >&2
  return 1
fi
 
if [ "$1" = "extroot" ] && [ -e ${SDIR}/../.use_crypt_extroot ]; then
  for SYSDEVPATH in /sys/class/block/sd*; do
    [ ! -f "$SYSDEVPATH"/dev ] && continue
    [ -e "/dev/${SYSDEVPATH##*/}" ] && continue
    MAJMIN=$(cat "$SYSDEVPATH"/dev | tr ':' ' ')
    mknod /dev/${SYSDEVPATH##*/} b $MAJMIN
  done
 
  KVER=$(uname -r)
  insmod ${SDIR}/../lib/modules/${KVER}/af_alg.ko
  insmod ${SDIR}/../lib/modules/${KVER}/algif_rng.ko
  insmod ${SDIR}/../lib/modules/${KVER}/algif_hash.ko
  insmod ${SDIR}/../lib/modules/${KVER}/algif_skcipher.ko
 
  find /dev -type b | grep -E "/(sd|mmcblk).*" |
  while read DEVPATH; do
    cryptsetup --disable-locks isLuks $DEVPATH || continue
    export ACTION=add DEVNAME="${DEVPATH##*/}"
    ALTROOT="${SDIR}/.." "$SDIR"/decrypt.sh || "$SDIR"/decrypt.sh
  done
fi
 
block "$@"

/etc/rc.local

Існує ще один спосіб обійти існуючі обмеження. Однак його слід використовувати лише тоді, коли попередній метод не працює, оскільки цей підхід менш стабільний і може мати побічні ефекти.

Суть у тому, що extroot буде налаштований, як описано у інструкціях вище, але не буде змонтований під час стандартного завантаження, оскільки зашифрована extroot-файлова система не буде доступна. Це очікувано.

Зміни у файлі /etc/rc.local дозволять розблокувати LUKS розділ наприкінці процесу завантаження, коли ми маємо більше контролю над системою. Після цього буде повторно викликано mount_root, і extroot буде виявлено та змонтовано.

Ваш файл конфігурації fstab має містити секцію монтування з таргетом /overlay. Краще використовувати параметр uuid замість device, щоб не синхронізувати вручну /etc/rc.local з /etc/config/fstab.

Нижче наведено приклад скрипта для вставлення в /etc/rc.local. Цей скрипт не підтримує розблокування LUKS за паролем (stdin працює неправильно у цьому контексті). Необхідно використовувати файл-ключ, наприклад: /root/extroot.key. Оцініть загрози, щоб визначити безпечність такого підходу.

# Виконується лише якщо існує /.use_crypt_extroot у rootfs_data.
mkdir -p /mnt/tmp
if [ -e /.use_crypt_extroot ]; then 
  cryptsetup open -d /root/extroot.key /dev/sda1 cextroot
  umount /overlay
 
  mount --bind /tmp /mnt/tmp
  sleep 5
  PREINIT=1 mount_root
 
  umount -l /tmp
  mount --bind /rom/mnt/tmp /tmp
 
  block mount
  service rpcd reload
fi

Цей метод фактично повторює частину процесу завантаження, тому він трохи повільніший. На моєму пристрої веб-інтерфейс доступний на 20–30 секунд пізніше. SSH-з'єднання не затримується.

Цей розділ стосується лише snapshot-збірок OpenWrt, не релізів. У релізах kernel-пакети й пов'язані з ними отримують лише патчі безпеки.

НЕ використовуйте команду opkg upgrade для оновлень — це призведе до неконсистентного стану системи або soft-brick'у:

  • ABI бібліотеки uClibc нестабільний, змінюється між версіями — двійкові файли можуть бути несумісними.
  • UUID для розділів /rom або /rwm може змінитися після оновлення, що призведе до помилок монтування extroot.
  • Якщо оновити kernel-пакети, а потім перепрошити й перезавантажити пристрій, і щось піде не так — може виникнути невідповідність між ядром і модулями.
  • Якщо оновити всі пакети, крім ядра, — пакети на зразок iptables можуть зламатися.

Також, якщо UUID ROM-партіції зміниться, можливо доведеться знову виконати кроки 3 та 4 з інструкцій.

Рекомендовано: після оновлення системи перевстановлювати всі пакети, особливо kernel-модулі.

Цей метод корисний для пристроїв з 4 МіБ флеш-пам'яті або менше. У типовому образі OpenWrt немає інструментів для extroot, оскільки система збірки створює лише мінімальні образи.

Єдиний варіант — зібрати прошивку самостійно за допомогою Image Builder.

Image Builder працює лише в 64-бітних Linux-системах. Якщо у вас немає такої — скористайтесь VirtualBox і встановіть Ubuntu 64-bit.

На сторінці завантаження прошивки для вашого пристрою знайдіть файл, що починається з “OpenWrt-imagebuilder”. Завантажте та розпакуйте його у папку в Linux-системі.

Відкрийте термінал у цій папці й виконайте:

make info

Це виведе список доступних профілів для збірки.

Приклад:

tl-wr1043nd-v1:
    TP-LINK TL-WR1043N/ND v1
    Packages: kmod-usb-core kmod-usb2 kmod-ledtrig-usbdev

Перший рядок — це назва профілю. Другий — опис пристрою. Третій — список пакетів за замовчуванням.

У моєму випадку назва профілю — tl-wr1043nd-v1. Для створення прошивки введіть:

make image PROFILE=tl-wr1043nd-v1 PACKAGES="block-mount kmod-fs-ext4 kmod-usb-storage kmod-usb-ohci kmod-usb-uhci"

Це створить прошивку з підтримкою ext4.

⚠️ Пакет e2fsprogs занадто великий для 4 МіБ flash, тому форматування USB-диска потрібно виконати заздалегідь на іншій системі.

Після збірки прошивки:

  • Відкрийте папку bin, потім target, потім специфічну для пристрою, і знайдіть папку generic.
  • Там будуть прошивки для встановлення (factory або sysupgrade).

Щоб відформатувати USB у ext4, скористайтесь LiveCD або GParted Live.

Ви можете скористатися frontend-інструментом openwrt-auto-extroot для ImageBuilder, щоб зібрати кастомну прошивку, яка автоматично відформатує та налаштує extroot на будь-якому підключеному, але ще не налаштованому пристрої зберігання.

Налаштуйте Hotplug extras та Opkg extras. Пакети, необхідні для роботи Extroot, мають бути збережені у профілі Opkg init і автоматично відновлені після оновлення за допомогою скрипта для повторного налаштування Extroot.

cat << "EOF" > /etc/uci-defaults/90-extroot-restore
if uci -q get fstab.extroot > /dev/null \
&& [ ! -e /etc/extroot-restore ] \
&& [ -e /etc/opkg-restore-init ] \
&& lock -n /var/lock/extroot-restore
then
UUID="$(uci -q get fstab.extroot.uuid)"
DIR="$(uci -q get fstab.extroot.target)"
DEV="$(block info | sed -n -e "/${UUID}/s/:.*$//p")"
if touch /etc/extroot-restore \
&& grep -q -e "\s${DIR}\s" /etc/mtab \
&& mount "${DEV}" /mnt
then
BAK="$(mktemp -d -p /mnt -t bak.XXXXXX)"
mv -f /mnt/etc /mnt/upper "${BAK}"
cp -f -a "${DIR}"/. /mnt
umount "${DEV}"
fi
lock -u /var/lock/extroot-restore
reboot
fi
exit 1
EOF
 
cat << "EOF" >> /etc/sysupgrade.conf
/etc/uci-defaults
EOF
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
  • Last modified: 2025/05/27 08:26
  • by vazaz