🔍 Шаг 1. смотрим диски

lsblk sdb

🔍 Шаг 2. вставить скрипт

builder.sh
  1. cat << 'MAIN_EOF' > builder.sh
  2. #!/bin/bash
  3. set -e
  4.  
  5. # ==============================================================================
  6. # 0. ГЛОБАЛЬНАЯ ТЕХНИЧЕСКАЯ КОНФИГУРАЦИЯ СЕРВЕРА И ССЫЛОК
  7. # ==============================================================================
  8. TARGET_FLASH="/dev/sdb" # Физический диск флешки, размечаемый в Ubuntu
  9. SERVER_NAME="arch-server" # Имя хоста (hostname) будущего ПК
  10. ADMIN_NAME="eva" # Логин администратора с доступом к sudo
  11. ADMIN_PASS="65421" # Пароль администратора
  12. ROOT_PASS="rootpassword" # Пароль суперпользователя (root)
  13. OFFLINE_MODE="YES" # Измените на "NO", если на целевом ПК есть интернет
  14.  
  15. # Базовый образ Arch Linux
  16. URL_BOOTSTRAP="https://mirror.yandex.ru/archlinux/iso/latest/archlinux-bootstrap-x86_64.tar.zst"
  17.  
  18. # Официальные репозитории и зеркала (используются для скачивания и прописываются на ПК)
  19. URL_YANDEX="https://mirror.yandex.ru/archlinux/\$repo/os/\$arch"
  20. URL_PKGS="https://archlinux.pkgs.org/archlinux/\$repo/os/\$arch"
  21. URL_RACKSPACE="http://mirror.rackspace.com/archlinux/\$repo/os/\$arch"
  22. URL_PKGBUILD="https://geo.mirror.pkgbuild.com/\$repo/os/\$arch"
  23.  
  24. # ==============================================================================
  25. # ШАГ 1: Верификация безопасности накопителей
  26. # ==============================================================================
  27. echo "=== ШАГ 1: Верификация безопасности накопителей ==="
  28. UBUNTU_ROOT_DISK=$(lsblk -no PKNAME $(findmnt -nvo SOURCE /) 2>/dev/null || true)
  29. if [ -z "$UBUNTU_ROOT_DISK" ]; then
  30. UBUNTU_ROOT_DISK=$(lsblk -dno NAME,MOUNTPOINTS | grep -E '/$' | awk '{print $1}')
  31. fi
  32.  
  33. if [ "/dev/$UBUNTU_ROOT_DISK" == "$TARGET_FLASH" ]; then
  34. echo "КРИТИЧЕСКАЯ ОШИБКА: Запрещено размечать диск запущенной Ubuntu ($TARGET_FLASH)!"
  35. exit 1
  36. fi
  37.  
  38. echo "Целевой диск определен как безопасный: $TARGET_FLASH"
  39. echo "ВНИМАНИЕ! Диск $TARGET_FLASH будет тотально очищен через 5 секунд..."
  40.  
  41. # ==============================================================================
  42. # ШАГ 2: Принудительное уничтожение метаданных и разметки
  43. # ==============================================================================
  44. echo "=== ШАГ 2: Принудительное уничтожение метаданных и разметки ==="
  45. sudo umount -f ${TARGET_FLASH}* 2>/dev/null || true
  46. sudo wipefs -a --force "$TARGET_FLASH"
  47. sudo dd if=/dev/zero of="$TARGET_FLASH" bs=1M count=20 status=none
  48. sudo partprobe "$TARGET_FLASH" || true
  49.  
  50. # ==============================================================================
  51. # ШАГ 3: Создание новой таблицы разделов GPT
  52. # ==============================================================================
  53. echo "=== ШАГ 3: Создание новой таблицы разделов GPT ==="
  54. printf "g\nn\n1\n\n+512M\nt\n1\nn\n2\n\n\nw\n" | sudo fdisk --wipe always --wipe-partitions always "$TARGET_FLASH"
  55. sudo partprobe "$TARGET_FLASH" || true
  56.  
  57. if [[ "$TARGET_FLASH" == *"nvme"* ]]; then
  58. PART1="${TARGET_FLASH}p1"
  59. PART2="${TARGET_FLASH}p2"
  60. else
  61. PART1="${TARGET_FLASH}1"
  62. PART2="${TARGET_FLASH}2"
  63. fi
  64.  
  65. echo "Ожидание инициализации разделов ядром..."
  66. sudo partprobe /dev/sdb || true
  67. sudo udevadm settle || true
  68.  
  69. # ==============================================================================
  70. # ШАГ 4: Безусловное форматирование файловых систем
  71. # ==============================================================================
  72. echo "=== ШАГ 4: Безусловное форматирование файловых систем ==="
  73. sudo mkfs.vfat -F 32 "$PART1"
  74. sudo mkfs.ext4 -F "$PART2"
  75.  
  76. # ==============================================================================
  77. # ШАГ 5: Развертывание структуры точек монтирования
  78. # ==============================================================================
  79. echo "=== ШАГ 5: Развертывание структуры точек монтирования ==="
  80. sudo mkdir -p /mnt/arch
  81. sudo mount "$PART2" /mnt/arch
  82. sudo mkdir -p /mnt/arch/boot
  83. sudo mount "$PART1" /mnt/arch/boot
  84.  
  85. # ==============================================================================
  86. # ШАГ 6: Скачивание официального образа Arch Linux
  87. # ==============================================================================
  88. echo "=== ШАГ 6: Скачивание официального образа Arch Linux ==="
  89. sudo apt update && sudo apt install -y zstd wget
  90. if [ ! -f archlinux-bootstrap-x86_64.tar.zst ]; then
  91. wget --timeout=15 --tries=3 "$URL_BOOTSTRAP"
  92. fi
  93. sudo tar -I zstd -xf archlinux-bootstrap-x86_64.tar.zst --strip-components=1 -C /mnt/arch
  94.  
  95. # ==============================================================================
  96. # ШАГ 7: Статическая генерация таблицы fstab флешки
  97. # ==============================================================================
  98. echo "=== ШАГ 7: Статическая генерация таблицы fstab флешки ==="
  99. EFI_UUID=$(sudo blkid -s UUID -o value "$PART1")
  100. ROOT_UUID=$(sudo blkid -s UUID -o value "$PART2")
  101. sudo mkdir -p /mnt/arch/etc
  102. printf "UUID=%s /boot vfat defaults 0 2\nUUID=%s / ext4 defaults 0 1\n" "$EFI_UUID" "$ROOT_UUID" | sudo tee /mnt/arch/etc/fstab
  103.  
  104. # ==============================================================================
  105. # ШАГ 8: Внедрение скрипта АВТОУСТАНОВКИ на флешку (ОФФЛАЙН МЕТОД)
  106. # ==============================================================================
  107. echo "=== ШАГ 8: Внедрение скрипта АВТОУСТАНОВКИ на флешку ==="
  108. sudo mkdir -p /mnt/arch/root
  109.  
  110. sudo cat << EOF | sudo tee /mnt/arch/root/forest-install.sh > /dev/null
  111. #!/bin/bash
  112. set -e
  113. echo "=== КОМБАЙН ЗАПУЩЁН ==="
  114.  
  115. MY_DISK=\$(lsblk -no PKNAME \$(findmnt -nvo SOURCE /) 2>/dev/null || true)
  116. if [ -z "\$MY_DISK" ]; then
  117. MY_DISK=\$(lsblk -no PKNAME /bootmnt 2>/dev/null || echo "sdb")
  118. fi
  119.  
  120. TARGET_DISK=\$(lsblk -dno NAME,TYPE | grep -v "loop" | grep -v "rom" | grep -v "\$MY_DISK" | head -n1 | awk '{print \$1}')
  121. TARGET="/dev/\$TARGET_DISK"
  122. if [ -z "\$TARGET_DISK" ]; then
  123. echo "КРИТИЧЕСКАЯ ОШИБКА: Жёсткий диск ПК не найден!"
  124. exit 1
  125. fi
  126.  
  127. echo "Целевой жёсткий диск ПК определён: \$TARGET. Уничтожаем старые данные..."
  128. umount -f \${TARGET}* 2>/dev/null || true
  129. wipefs -a --force "\$TARGET"
  130. dd if=/dev/zero of="\$TARGET" bs=1M count=20 status=none
  131. partprobe "\$TARGET" || true
  132.  
  133. echo "Разметка жёсткого диска ПК..."
  134. printf "g\nn\n1\n\n+512M\nt\n1\nn\n2\n\n\nw\n" | fdisk --wipe always --wipe-partitions always "\$TARGET"
  135. if [[ "\$TARGET" == *"nvme"* ]]; then
  136. TPART1="\${TARGET}p1"
  137. TPART2="\${TARGET}p2"
  138. else
  139. TPART1="\${TARGET}1"
  140. TPART2="\${TARGET}2"
  141. fi
  142.  
  143. echo "Форматирование жёсткого диска ПК..."
  144. mkfs.vfat -F 32 "\$TPART1"
  145. mkfs.ext4 -F "\$TPART2"
  146.  
  147. echo "Монтирование дисков ПК под установку..."
  148. mkdir -p /mnt/target && mount "\$TPART2" /mnt/target
  149. mkdir -p /mnt/target/boot && mount "\$TPART1" /mnt/target/boot
  150.  
  151. # ==============================================================================
  152. # ШАГ 8.1 ОФЛАЙН УСТАНОВКА С ОБНОВЛЕНИЕМ
  153. # ==============================================================================
  154. if [ "${OFFLINE_MODE}" == "YES" ]; then
  155. echo "=== ВЫБРАН РЕЖИМ: ТОТАЛЬНЫЙ ОФЛАЙН ==="
  156. mkdir -p /mnt/target/var/cache/pacman/pkg
  157. mkdir -p /mnt/target/var/lib/pacman
  158.  
  159. echo "Копируем автономный кэш пакетов с флешки на диск ПК..."
  160. # Пишем команду так, чтобы в ней не было круглых скобок $() и find
  161. cp -R /var/cache/pacman/pkg/. /mnt/target/var/cache/pacman/pkg/
  162.  
  163. echo "Переводим системный pacman флешки в автономный режим..."
  164. # Подменяем системный файл зеркал флешки, указывая вместо сайтов локальный путь file://
  165. mkdir -p /etc/pacman.d
  166. echo "Server = file:///var/cache/pacman/pkg" > /etc/pacman.d/mirrorlist
  167.  
  168. echo "Развертывание системы из локальных файлов без интернета..."
  169. # Теперь pacman -Syu прочитает родной конфиг, увидит тамfile:// и молча поставит пакеты из папки
  170. pacman -Syu --noconfirm --root /mnt/target --dbpath /mnt/target/var/lib/pacman base linux linux-firmware openssh networkmanager sudo nano dosfstools mtools samba grub efibootmgr nginx php php-fpm
  171. else
  172. # ==============================================================================
  173. # ШАГ 8.2 ОНЛАЙН УСТАНОВКА С ОБНОВЛЕНИЕМ
  174. # ==============================================================================
  175. echo "=== ВЫБРАН РЕЖИМ: ОНЛАЙН УСТАНОВКА С ОБНОВЛЕНИЕМ ==="
  176. echo "Создаем чистые папки под кэш на жестком диске ПК..."
  177. mkdir -p /mnt/target/var/cache/pacman/pkg
  178. mkdir -p /mnt/target/var/lib/pacman
  179. mkdir -p /mnt/target/etc/pacman.d
  180.  
  181. echo "Записываем готовый адрес зеркала Яндекса в целевой ПК..."
  182. # Переменная URL_YANDEX уже содержит идеальную ссылку, просто убираем один лишний слэш перед arch
  183. echo "Server = ${URL_YANDEX/\\\$arch/\$arch}" > /mnt/target/etc/pacman.d/mirrorlist
  184.  
  185. # Записываем полученный адрес зеркала в зеркала целевого ПК
  186. echo "Server = ${URL_YANDEX}" > /mnt/target/etc/pacman.d/mirrorlist
  187. echo "Server = ${URL_PKGS}" >> /mnt/target/etc/pacman.d/mirrorlist
  188. echo "Server = ${URL_RACKSPACE}/\$repo/os/$arch" >> /mnt/target/etc/pacman.d/mirrorlist
  189. echo "Server = ${URL_PKGBUILD}/\$repo/os/$arch" >> /mnt/target/etc/pacman.d/mirrorlist
  190.  
  191. # Прописываем DNS Google прямо в сетевой конфиг запущенной флешки
  192. echo "nameserver 8.8.8.8" > /etc/resolv.conf
  193. echo "nameserver 1.1.1.1" >> /etc/resolv.conf
  194.  
  195. cat << 'PAC_EOF' > /tmp/pacman-install.conf
  196. [options]
  197. Architecture = auto
  198. SigLevel = Required DatabaseOptional
  199. LocalFileSigLevel = Optional
  200.  
  201. [core]
  202. Include = /mnt/target/etc/pacman.d/mirrorlist
  203.  
  204. [extra]
  205. Include = /mnt/target/etc/pacman.d/mirrorlist
  206. PAC_EOF
  207.  
  208. echo "Принудительно включаем DNS-серверы на запущенной флешке..."
  209. cp /etc/resolv.conf /etc/resolv.conf.bak && echo "nameserver 8.8.8.8" > /etc/resolv.conf
  210.  
  211. echo "Скачиваем свежие базы репозиториев напрямую на жесткий диск ПК..."
  212. # ИСПРАВЛЕНИЕ: Этот шаг скачает файлы core.db и extra.db прямо на HDD компьютера
  213. pacman -Sy --noconfirm --config /tmp/pacman-install.conf --dbpath /mnt/target/var/lib/pacman
  214.  
  215. echo "Скачиваем свежие пакеты из интернета в кэш жесткого диска ПК..."
  216. pacman -Syw --noconfirm --config /tmp/pacman-install.conf --cachedir /mnt/target/var/cache/pacman/pkg --dbpath /mnt/target/var/lib/pacman \
  217. base linux linux-firmware openssh networkmanager sudo nano dosfstools mtools samba grub efibootmgr nginx php php-fpm
  218.  
  219. echo "Развертывание системы из скачанных из интернета файлов..."
  220. # Копируем созданный рабочий зеркальный лист в саму систему, чтобы она знала зеркала после перезагрузки
  221. cp /mnt/target/etc/pacman.d/mirrorlist /mnt/target/etc/pacman.d/mirrorlist.bak
  222.  
  223. pacman -U --noconfirm --root /mnt/target --dbpath /mnt/target/var/lib/pacman /mnt/target/var/cache/pacman/pkg/*.pkg.tar.zst
  224. fi
  225. # ==============================================================================
  226.  
  227. umount /mnt/target/var/cache/pacman/pkg
  228.  
  229. echo "Генерация таблицы fstab целевого ПК..."
  230. printf "UUID=\$(blkid -s UUID -o value \$TPART2) / ext4 defaults 0 1\nUUID=\$(blkid -s UUID -o value \$TPART1) /boot vfat defaults 0 2\n" > /mnt/target/etc/fstab
  231.  
  232. echo "Вход в chroot окружение ПК..."
  233. /mnt/arch/bin/arch-chroot /mnt/target /bin/bash << 'CHROOT_EOF'
  234. set -e
  235. # Отключите автоматическую синхронизацию
  236. # Автоматическая настройка времени без пользовательского ввода
  237. # Вариант 1: Использовать UTC (рекомендуется)
  238. #echo "UTC" > /etc/timezone
  239. #ln -sf /usr/share/zoneinfo/UTC /etc/localtime
  240. #timedatectl set-local-rtc 0
  241.  
  242. # Вариант 2: Использовать локальное время с материнки
  243. hwclock --systohc
  244. timedatectl set-local-rtc 1
  245. echo "Конфигурация пользователей..."
  246. useradd -m -G wheel -s /bin/bash "${ADMIN_NAME}"
  247.  
  248. # ==============================================================================
  249. # ЖЕСТКОЕ ПОДАВЛЕНИЕ СИНЕГО ЭКРАНА НА ЦЕЛЕВОМ ПК
  250. # ==============================================================================
  251. echo "en_US.UTF-8 UTF-8" > /etc/locale.gen
  252. locale-gen
  253. echo "LANG=en_US.UTF-8" > /etc/locale.conf
  254. echo "KEYMAP=us" > /etc/vconsole.conf
  255. echo "${SERVER_NAME}" > /etc/hostname
  256. systemd-machine-id-setup
  257. ln -sf /dev/null /etc/systemd/system/systemd-firstboot.service
  258. sudo ln -sf /dev/null /mnt/arch/etc/systemd/system/systemd-firstboot.service
  259. # ==============================================================================
  260.  
  261. echo "Конфигурация пользователей..."
  262. useradd -m -G wheel -s /bin/bash "${ADMIN_NAME}"
  263. echo "${ADMIN_NAME}:${ADMIN_PASS}" | chpasswd
  264. echo "root:${ROOT_PASS}" | chpasswd
  265. echo "%wheel ALL=(ALL:ALL) ALL" > /etc/sudoers.d/wheel
  266.  
  267. touch /etc/locale.conf
  268. touch /etc/vconsole.conf
  269. touch /etc/machine-id
  270.  
  271. echo "Активация служб..."
  272. sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config
  273. systemctl enable sshd NetworkManager
  274.  
  275. echo "Установка загрузчика GRUB..."
  276. grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=Arch_PC --recheck
  277. grub-mkconfig -o /boot/grub/grub.cfg
  278. CHROOT_EOF
  279.  
  280. printf "## Russia\nServer = %s\nServer = %s\n## International\nServer = %s\nServer = %s\n" \
  281. "${URL_YANDEX}" "${URL_PKGS}" "${URL_RACKSPACE}" "${URL_PKGBUILD}" > /mnt/target/etc/pacman.d/mirrorlist
  282.  
  283. umount -R /mnt/target
  284. echo "Система успешно развёрнута автономно! Перезагрузка через 3 секунды..."
  285. sleep 3
  286. reboot
  287. EOF
  288.  
  289. # Настройка прав доступа к файлу автоустановщика
  290. sudo chmod 755 /mnt/arch/root
  291. sudo chmod +x /mnt/arch/root/forest-install.sh
  292. sudo chmod 700 /mnt/arch/root
  293.  
  294. # ==============================================================================
  295. # ШАГ 9: Создание и регистрация фоновой службы systemd
  296. # ==============================================================================
  297. echo "=== ШАГ 9: Создание и регистрация фоновой службы systemd ==="
  298. sudo cat << 'SERVICE_EOF' | sudo tee /mnt/arch/etc/systemd/system/forest-autoinstall.service > /dev/null
  299. [Unit]
  300. Description=Автоустановщик Arch Linux без монитора
  301. After=multi-user.target
  302. [Service]
  303. Type=idle
  304. ExecStart=/root/forest-install.sh
  305. StandardOutput=tty
  306. StandardError=tty
  307. [Install]
  308. WantedBy=multi-user.target
  309. SERVICE_EOF
  310.  
  311. sudo mkdir -p /mnt/arch/etc/systemd/system/multi-user.target.wants
  312. sudo ln -sf /etc/systemd/system/forest-autoinstall.service /mnt/arch/etc/systemd/system/multi-user.target.wants/forest-autoinstall.service
  313.  
  314. # ==============================================================================
  315. # ШАГ 10: Формирование чистых репозиториев для флешки
  316. # ==============================================================================
  317. echo "=== ШАГ 10: Формирование чистых репозиториев для флешки ==="
  318. sudo mkdir -p /mnt/arch/etc/pacman.d
  319.  
  320. cat << MIRROR_EOF | sudo tee /mnt/arch/etc/pacman.d/mirrorlist > /dev/null
  321. ## Russia
  322. Server = ${URL_YANDEX}
  323. Server = ${URL_PKGS}
  324.  
  325. ## International
  326. Server = ${URL_RACKSPACE}
  327. Server = ${URL_PKGBUILD}
  328. MIRROR_EOF
  329.  
  330. # ==============================================================================
  331. # ШАГ 11: Подготовка локального репозитория на флешке
  332. # ==============================================================================
  333. echo "=== ШАГ 11: Подготовка локального репозитория ==="
  334. sudo mkdir -p /mnt/arch/var/cache/pacman/pkg
  335. sudo mkdir -p /mnt/arch/var/lib/pacman
  336.  
  337. sudo mkdir -p /mnt/arch/etc/pacman.d
  338. echo "Server = ${URL_YANDEX//\\\\\\$/\$}" | sudo tee /mnt/arch/etc/pacman.d/mirrorlist > /dev/null
  339.  
  340.  
  341.  
  342. cat << 'EOF' | sudo tee /mnt/arch/etc/pacman.conf > /dev/null
  343. [options]
  344. Architecture = auto
  345. SigLevel = Required DatabaseOptional
  346. LocalFileSigLevel = Optional
  347.  
  348. [core]
  349. Include = /etc/pacman.d/mirrorlist
  350.  
  351. [extra]
  352. Include = /etc/pacman.d/mirrorlist
  353. EOF
  354.  
  355. # ==============================================================================
  356. # ШАГ 12: Установка пакетов на флешку и кэширование пакетов для ПК
  357. # ==============================================================================
  358. echo "=== ШАГ 12: Накатывание пакетов и загрузчика на флешку ==="
  359.  
  360. echo "nameserver 8.8.8.8" | sudo tee /mnt/arch/etc/resolv.conf
  361.  
  362. # ДОБАВЛЕНО: Генерируем базовые конфиги флешки до chroot, чтобы заблокировать синий экран systemd-firstboot
  363. echo "en_US.UTF-8 UTF-8" | sudo tee /mnt/arch/etc/locale.gen
  364. echo "LANG=en_US.UTF-8" | sudo tee /mnt/arch/etc/locale.conf
  365. echo "KEYMAP=us" | sudo tee /mnt/arch/etc/vconsole.conf
  366. echo "arch-flash" | sudo tee /mnt/arch/etc/hostname
  367. sudo systemd-machine-id-setup --root=/mnt/arch
  368.  
  369. # ТОТ САМЫЙ КЛЮЧЕВОЙ КОСТЫЛЬ: Жестко блокируем запуск синего экрана на самой флешке
  370. sudo ln -sf /dev/null /mnt/arch/etc/systemd/system/systemd-firstboot.service
  371.  
  372. # Возвращаем пути к зеркалам в стандартный вид для работы внутри самой флешки
  373. sudo sed -i 's|/mnt/arch||g' /mnt/arch/etc/pacman.conf
  374.  
  375. sudo /mnt/arch/bin/arch-chroot /mnt/arch /bin/bash << 'EOF'
  376. set -e
  377. pacman-key --init
  378. pacman-key --populate archlinux
  379. # Обновляем базы пакетов
  380. # Объединяем обновление баз и скачивание пакетов в ОДНУ команду
  381. pacman -Syuw --noconfirm base linux linux-firmware openssh networkmanager sudo nano dosfstools mtools nginx samba grub efibootmgr
  382. # Устанавливаем систему и загрузчик на флешку
  383. pacman -S --noconfirm base linux linux-firmware openssh networkmanager sudo nano dosfstools mtools nginx grub efibootmgr
  384. # Принудительно генерируем локали
  385. locale-gen
  386. # Настраиваем GRUB на флешке как съемный диск
  387. grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=Arch_Flash --removable --recheck
  388. grub-mkconfig -o /boot/grub/grub.cfg
  389. EOF
  390.  
  391. # ==============================================================================
  392. # ШАГ 13: финальная проверка
  393. # ==============================================================================
  394. echo "=== ШАГ 13: финальная проверка ==="
  395.  
  396. # Размонтируем каталоги, если они еще примонтированы
  397. sudo umount -l /mnt/arch/dev || true
  398. sudo umount -l /mnt/arch/proc || true
  399. sudo umount -l /mnt/arch/sys || true
  400. sudo umount -l /mnt/arch || true
  401.  
  402.  
  403. MAIN_EOF

🔍 Шаг 4. Очистите его от символов Windows

sed -i 's/\r$//' builder.sh

🔍 Шаг 5. Разрешите запуск

chmod +x builder.sh && ./builder.sh

🔍 Шаг 4. запустить скрипт

./builder.sh