В данном руководстве описана установка Debian-based дистрибутива Linux (Debian, Ubuntu, Kali и др.) с нуля без использования каких-либо автоматических установщиков.
Цель ручной установки — минимизировать количество пакетов в системе, установить только то, что нужно. В какой-то момент понимаешь, что проще поставить систему с нуля, чем выпиливать лишнее из готовой. Какие преимущества это даёт перед традиционным способом установки?
- Ручная установка поможет лучше узнать как работает ОС.
- Экономится дисковое пространство, система занимает меньше места.
- Обновления системы проходят быстрее, экономится трафик.
- Бэкап системы занимает меньше места и быстрее разворачивается.
- Вы знаете что есть в системе и для чего.
- Загрузка из выключенного состояния проходит быстрее, т.к. не запускаются сервисы, о назначении которых вы ничего не знаете.
- Поскольку лишних сервисов нет, ресурсы компьютера используются более рационально.
Тут мне надо написать абзац, чтобы отделить плюшки от оглавления. Пока ничего не придумал.
- Шаг 0. Подготавливаем и монтируем жёсткий диск
- Шаг 1. Debootstrap
- Шаг 2. Вход в систему (chroot)
- Шаг 3. Первичная настройка системы
- Шаг 4. Устанавливаем ядро
- Шаг 5. Устанавливаем загрузчик
- Шаг 6. Перезагружаемся!
- Шаг 7. Доведение до ума
Нам понадобятся..
- Установка производится из другой работающей linux-системы. Это может быть livecd того же дистрибутива или уже установленная система, причём не обязательно debian-based. Главное — это наличие утилиты
debootstrap
в репозиториях. В Archlinux соответствующий пакет лежит в репозитории community, а в Gentoo называетсяdev-util/debootstrap
. Устанавливать 32-битную систему можно как из 32-битной, так и из 64-битной. А вот 64-битную из 32-битной нельзя. - Подключение к интернету во время установки.
- Отсутствие страха перед консолью.
Шаг 0. Подготавливаем и монтируем жёсткий диск
Чтобы сосредоточиться на установке и не описывать различные варианты разбиения жёсткого диска, я буду рассматривать простейший случай с одним единственным разделом на одном единственно диске, который мы целиком отдадим под новую систему и загрузчик. Это оптимальный вариант разбивки диска для использования под виртуальной машиной (VirtualBox, Qemu, VMware).
В случае установки на реальное железо надо соблюдать осторожность. Жёсткий диск как правило уже содержит какие-то разделы с ценной информацией. Возможно новая система будет соседствовать с другой ОС. При необходимости спланировать схему разбиения дисков обращайтесь к другим руководствам по установке Linux.
Можно не трогать жёсткий диск, а установить систему на флэшку или внешний жёсткий диск. В этом случае мы можем без опаски отдать под систему всё устройство целиком.
При создании виртуального диска сразу помечаем его как твердотельный, чтобы при удалении файлов его реальный размер уменьшался:
Создаём таблицу разделов и первый раздел
Для разметки диска можно использовать fdisk
или графический gparted
. Я использую parted
, потому что им удобно пользоваться в неинтерактивном режиме.
Прежде чем вводить эти команды, проверьте, что на размечаемом диске нет ничего ценного! Я не несу ответственности за ваши потерянные данные!
# parted -s /dev/sdX mklabel msdos
# parted -s /dev/sdX -- mkpart primary ext2 1MiB -1s
Вместо sdX
должно быть sda
, sdb
, sdc
и т.д, смотря сколько дисков подключено и на какой вы хотите установить систему. Команда lsblk
покажет информацию обо всех дисковых устройствах, подключенных в настоящий момент.
Первая команда создаёт таблицу разделов MBR (не GPT). Вторая команда создаёт раздел, смещённый относительно начала диска ровно на 1 МБ (т.н. “выравнивание” раздела) и заканчивающийся последним сектором (-1s
). Нумерация секторов начинается с нуля. Ключ --
означает, что дальше аргументов не будет и нужен для правильного восприятия -1s
.
Информация о разделе записана в таблицу разделов MBR, но файловой системы на нём ещё нет. ext2
во второй команде — это только тип раздела — однобайтный идентификатор, записываемый в таблицу разделов MBR. У файловых систем ext2/3/4 идентификатор одинаковый и равен 0x83.
Хорошая подсказка по идентификаторам есть в утилите fdisk
:
# echo l | fdisk /dev/sdX
На всякий случай проверим выравнивание (последняя цифра — номер раздела):
# parted /dev/sdX align-check opt 1
Форматируем раздел
В качестве файловой системы будем использовать Ext4. Это хорошая, стабильная файловая система. Я вижу два существенных преимущества Ext4 по сравнению с Ext2 и Ext3:
- возможность эффективного хранения разреженных (sparse) файлов,
- поддержка ATA-команды TRIM. Она не даст виртуальному диску распухать со временем.
# mkfs.ext4 -m 1 /dev/sdX1 -L debian
или
# mkfs.ext4 -m 1 -O ^has_journal /dev/sdX1 -L debian
-m 1
— зарезервировать 1% пространства под нужды суперпользователя (по умолчанию 5%).
-L debian
— метка (label) раздела. Выбирайте на свой вкус.
-O ^has_journal
отключает журналирование на ФС. Отсутствие журнала немного увеличивает производительность, но может привести к нарушению целостности ФС при внезапном отключении питания.
Монтируем файловую систему, чтобы получить к ней доступ.
# mkdir /mnt/sdX1 && mount /dev/sdX1 /mnt/sdX1
Шаг 1. Debootstrap
Debootstrap разворачивает в указанном каталоге минимальный набор пакетов, необходимый для самостоятельной работы системы. Это самый важный шаг. Если сейчас допустить ошибку, то всё придётся переделывать сначала. Инструкцию я вынес в отдельный пост debootstrap.
Рекомендую сделать бэкап сразу после этого шага. Я устанавливаю Debian Jessie, поэтому мои бэкапы содержат jessie в названии. Команды подсмотрены в Ubuntu community help wiki.
# tar cpzf /path/to/jessie-debootstrapped.tar.gz --one-file-system -C /mnt/sdX1 .
или
# tar cpjf /path/to/jessie-debootstrapped.tar.bz2 --one-file-system -C /mnt/sdX1 .
или
# tar cpJf /path/to/jessie-debootstrapped.tar.xz --one-file-system -C /mnt/sdX1 .
Наибольшее сжатие будет у .tar.xz
архива, самое быстрое у tar.gz
. Посередине находится tar.bz2
. У меня в цифрах получилось так:
Сжатие | Размер архива, MiB | Время компрессии, с |
---|---|---|
gzip | 91 | 7.5 |
bzip2 | 83 | 16.6 |
xz | 68 | 68.2 |
Восстановление из бэкапа:
# find /mnt/sdX1 -delete
# tar xpf /path/to/backup.tar.gz -C /mnt/sdX1 --numeric-owner
или
# tar xpf /path/to/backup.tar.bz2 -C /mnt/sdX1 --numeric-owner
или
# tar xpf /path/to/backup.tar.xz -C /mnt/sdX1 --numeric-owner
Шаг 2. Вход в систему (chroot)
Чтобы процессы из chroot-окружения могли общаться с ядром, необходимо примонтировать псевдо-файловые системы /proc
, /sys
, /dev
:
# cd /mnt/sdX1
# mount proc -t proc ./proc
# mount sys -t sysfs ./sys
# mount --bind /dev ./dev
# mount --bind /dev/pts ./dev/pts
/dev/pts
— виртуальная файловая система, которая динамически создаёт файлы терминалов /dev/pts/X
для каждого нового подключения. Это необходимо для нормального функционирования многих программ, работающих с терминалом, в т.ч. скриптов debconfig.
После того, как всё необходимое смонтировано, делаем chroot “в туда”
# chroot /mnt/sdX1 /bin/bash
Стоп, так делать не надо. Такой чрут потянет за собой переменные окружения из внешней системы (проверяется командой env
). Вот правильный чрут:
# chroot /mnt/sdX1 /usr/bin/env -i HOME=/root TERM="$TERM" /bin/bash --login
Всё, мы внутри! В дальнейшем по тексту я буду отмечать чрутовый шелл приглашением (chroot)#
.
Можно ли поиметь сразу несколько терминалов в одном chroot-окружении? Да, просто делаем ещё один точно такой же чрут и получаем второй терминал. Повторно монтировать ничего не надо.
Шаг 3. Первичная настройка системы
Задаём пароль рута:
(chroot)# passwd
Устанавливаем часовой пояс:
(chroot)# ln -sf /usr/share/zoneinfo/UTC /etc/localtime
или
(chroot)# ln -sf /usr/share/zoneinfo/Europe/Moscow /etc/localtime
Задаём имя хоста, в моём случае — debian-pc
:
(chroot)# echo "debian-pc" > /etc/hostname
также прописываем имя хоста в /etc/hosts
для адреса 127.0.0.1 после localhost
:
(chroot)# echo 127.0.0.1 localhost debian-pc > /etc/hosts
(chroot)# echo ::1 localhost debian-pc >> /etc/hosts
Если этого не сделать, то имя debian-pc
не будет резолвится в IP-адрес, и вы не сможете себя попинговать :)
Сеть должна работать без дополнительных манипуляций. Проверяем:
(chroot)# apt update
Если возникли проблемы с DNS, берём /etc/resolv.conf
с основной системы:
# cp /etc/resolv.conf /mnt/sdX1/etc/resolv.conf
Устанавливаем локаль:
(chroot)# apt install locales
(chroot)# echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
(chroot)# locale-gen
(chroot)# update-locale LANG=en_US.UTF-8
- Вы можете не использовать
echo
, а раскомментировать необходимые локали в/etc/locale.gen
вручную. - Вместо
en_US.UTF-8
можно прописатьru_RU.UTF-8
, тогда всё будет по-русски. - Последние 3 команды можно заменить интерактивной
dpkg-reconfigure locales
.
Проверяем список доступных локалей и текущую локаль:
(chroot)# locale -a
(chroot)# locale
Создаём fstab
В случае с одним единственным разделом можно обойтись без fstab
, т.к. корневую ФС ядро само примонтирует, а больше ничего монтировать не требуется. Однако:
- Корневая ФС не будет видна в выводе команды
mount
и в/etc/mtab
. В/proc/mounts
по-прежнему видна. - Ядро будет монтировать корень с дефолтными параметрами, что не всегда приемлемо. Можно поменять параметры монтирования по-умолчанию и всё равно обойтись без fstab. Вот я сейчас включу discard:
# tune2fs -o discard /dev/sdX1
# tune2fs -l /dev/sdX1 | grep "^Default mount"
Однако не все параметры монтирования можно прописать как дефолтные напрямую в ФС (см. man tune2fs
). У меня не получись вписать relatime
, поэтому таки пришлось создать fstab
:
(chroot)# echo "/dev/sdX1 / ext4 defaults,relatime,discard,barrier=0 0 1" > /etc/fstab
Вместо /dev/sdX1
надёжнее вписать UUID файловой системы. Узнать его можно командой blkid /dev/sdX1
. При использовании UUID запись в fstab будет выглядеть примерно так:
Опция монтирования discard
нужна если наш носитель является твердотельным. Опции relatime
и barrier=0
немного повышают производительность ФС.
Конфигурируем менеджер пакетов
При необходимости добавляем репозитории, указываем локальное зеркало и т.д.
Спортсмены отключают установку рекомендованных пакетов:
(chroot)# echo 'APT::Get::Install-Recommends "false";' >>/etc/apt/apt.conf
(chroot)# echo 'APT::Get::Install-Suggests "false";' >>/etc/apt/apt.conf
Шаг 4. Устанавливаем ядро
Наша новая система может работать в chroot-окружении, но ещё не способна самостоятельно загружаться. Потому что ни загрузчика нет, ни ядра (да-да, тот самый Linux).
Выясним какие ядра доступны в репозиториях:
(chroot)# apt search linux-image
или
# chroot /mnt/sdX1 apt search linux-image
Посмотреть описание конкретного пакета можно командой
(chroot)# apt show linux-image-686
или
# chroot /mnt/sdX1 apt show linux-image-686
Ну и устанавливаем понравившееся:
(chroot)# apt install linux-image-686
В каталоге /boot
появился образ ядра. Запоминаем его название, скоро пригодится.
(chroot)# ls /boot/vmlinuz*
Шаг 5. Устанавливаем загрузчик
У нас есть ядро, но его кто-то должен загрузить в оперативную память компьютера и передать управление. Этим занимается загрузчик. Обычно ставят GRUB2, но мне больше нравится Syslinux. Ещё есть LILO.
Поскольку загрузчик никак не используется после загрузки Linux, и мы стремимся минимизировать количество пакетов в системе, я буду устанавливать загрузчик из внешней системы.
# mkdir /mnt/sdX1/boot/syslinux
# extlinux -i /mnt/sdX1/boot/syslinux
# dd if=/usr/lib/syslinux/bios/mbr.bin of=/dev/sdX bs=440 count=1
# cp /usr/lib/syslinux/bios/{ldlinux.c32,libcom32.c32,libutil.c32} /mnt/sdX1/boot/syslinux
В зависимости от дистрибутива Linux и версии загрузчика могут различаться пути к запчастям загрузчика (вот этот /usr/lib/syslinux/bios
). Команды в помощь:
# find / -name ldlinux.c32 2>/dev/null
# find / -name mbr.bin 2>/dev/null
Создадим минимальный конфиг загрузчика: без меню, без графики, лишь бы ядро загружалось.
После LINUX
указывается путь к ядру Linux.
После APPEND
перечисляются параметры загрузки ядра (Kernel boot parameters).
После INITRD
указывается путь к начальному рам-диску. Начальный рам-диск лежит в том же каталоге, что и ядро.
Подробнее о загрузчике см. арчвики, там хорошо написано.
Осталось включить boot-флаг в MBR:
# parted -s /dev/sdX set 1 boot on
Шаг 6. Перезагружаемся!
Осталось закрыть все чруты, размонтировать файловую систему и загрузиться с носителя.
(chroot)# exit
# cd /mnt
# umount ./proc ./sys ./dev/pts ./dev
# reboot
Если загрузка прошла успешно, то появится приглашение залогиниться. Проверяем пароль рута, перезагружаемся и делаем новый бэкап:
# mkdir /mnt/sdX1 && mount /dev/sdX1 /mnt/sdX1
# cd /mnt/sdX1
# tar cpJf jessie-configured.tar.xz --exclude='./var/cache/apt/archives/*.deb' \
--exclude='./var/lib/apt/lists/*' --exclude='./var/cache/apt/*.bin' \
--one-file-system -C jessie .
Чтобы архив занимал меньше места, мы исключаем:
/var/cache/apt/archives/*.deb
— кэш deb-пакетов apt’а
/var/lib/apt/lists/*
— сохранённые индексы репозиториев (что лежит в таком-то репозитории)
/var/cache/apt/*.bin
— какая-то база данных apt’а
Вот собственно и всё — минимальный Debian готов!
Если возникают проблемы с загрузкой, то снова загружаемся в большую систему, монтируем носитель, монтируем ФС /dev/
, /proc
, /sys
, чрутаемся внутрь и вносим исправления.
Шаг 7. Доведение до ума
Дополнительные пакеты, которые могут понадобиться:
cron
— планировщик задач
dhcpcd
позволит получать настройки сети автоматически по протоколу DHCP
file
— утилита для определения типа файла
iproute
— набор утилит для управления сетевыми подключениями
less
— утилита просмотра текста с возможностью скроллить вверх и вниз
logrotate
nano
— простенький консольный текстовый редактор
ncurses-term
для поддержки терминала rxvt-unicode-256color и других
ntp
— сервис точного времени
openssh-server
rsync
для синхронизации файлов и каталогов
sudo
vim
или vim-tiny
zsh
Напоминаю, что посмотреть описание пакета можно командой
(chroot)# apt show ПАКЕТ
Создаём пользователя vas, входящего в группу sudo
. Вы можете создать другого :)
(chroot)# useradd -m -g users -G sudo -s /usr/bin/zsh vas
(chroot)# passwd vas
Иногда бывает удобно сделать sudo без ввода пароля. На хостовой системе я себе таких шалостей не позволяю, а в контейнере можно. Не редактируйте /etc/sudoers
напрямую! Используйте команду visudo
.
Разрешаем sudo без пароля для всех пользователей, входящих в группу sudo
:
В качестве вишенки на торте возьмём zshrc, vimrc и т.п. с хостовой системы.
Можно немного облегчить систему за счёт man-страниц, документации, локалей. Это для особо целеустремлённых спортсменов.
(chroot)# rm -rf /usr/share/doc/*
(chroot)# find /usr/share/locale -maxdepth 1 -mindepth 1 ! -name en_US -exec rm -rf {} \;
(chroot)# find /usr/share/i18n/locales -maxdepth 1 -mindepth 1 ! -name en_US -exec rm -rf {} \;
(chroot)# rm -rf /usr/share/man/*
(chroot)# rm -rf /usr/share/groff/*
(chroot)# rm -rf /usr/share/info/*
(chroot)# rm -rf /usr/share/lintian/*
(chroot)# rm -rf /usr/include/*
Вот собственно и всё!