Перейти к основному содержимому
  1. Posts/

Готовим ThinStation

·2746 слов·13 минут· loading · loading ·
Sysadmin Linux
Оглавление

Введение
#

Сборка тонкого клиента, ориетнированного на определенные клиенты, сводится к следующим этапам:

  • Скачиваем полный репозиторий ThinStation
  • Собираем “толстый” (полный) образ
  • Загружаем тонкий клиент на толстом образе
  • Получаем список необходимых для этого клиента модулей ядра и пакетов
  • Исправляем конфиги сборки, оставив только самое необходимое (в том числе полученное на предыдущем этапе)
  • Собираем “тонкий” (облегченный) образ

Подготовка кухни
#

Сразу скажу, что есть и другой путь сборки - скачивание подготовленного .iso образа. Но мне это кажется не таким удобным, поэтому я буду описывать “правильный” вариант.

Скачивание репозитория
#

Вообще, для работы с ThinStation рекомендуется иметь базовые знания работы с Git. Просто потому, что ваши изменения нужно будет куда-то сохранять, а заблудиться в иерархии файлов, когда кухня уже распакована (не зная Git) - очень легко. Скачивание сводится к выполнению одной команды.

1git clone --depth 1 git://github.com/Thinstation/thinstation.git -b 5.5-Stable

где 5.5-Stable - актуальная на данный момент ветка. К сожалению размер репозитория за последние годы очень сильно вырос - в 2014-ом году он занимал чуть более 2 ГБ, а сейчас скачать придется целых 8 ГБ. Поэтому во всех мануалах предлагают скачивать его с ключом --depth 1 - на вкус и цвет.

Также нужно заметить, что мейнтейнеры проекта рекомендуют даже клонировать репозиторий от имени рута - об этом мне сказали, когда я пытался предложить изменения по исправлению владельца некоторых скриптов. Насколько это правильно - я не берусь судить, но если вы наблюдаете проблемы с правами на файлы - возможно стоит последовать этому совету.

Подготовка chroot
#

В корневой директории скачанного репозитория лежит bash-скрипт setup-chroot, который сделает всю работу за вас. О нем нужно знать лишь то, что запускать его нужно от рута (т.к. он, например, монтирует в новое дерево служебные файловые системы), а во-вторых он имеет набор ключей, самым нужным из которых на первом этапе является ключ -a - не задавать вопросы, а скачивать всё что нужно автоматически.

1soar@localhost $ cd thinstation
2soar@localhost $ sudo ./setup-chroot -a

К слову, всё остальное выполняется уже внутри этого чрута. В первый раз операция подготовки может занять до часу времени (на медленном диске), но потом вход осуществляется практически мгновенно до следующей полной очистки.

Толстый образ
#

Сборка толстого образа - это предварительный этап и нужен он для того, чтобы в первый раз загрузить ваше железо и выяснить, какой набор пакетов и модулей ему понадобится. В последствии, если у вас зоопарк железа или предвидится закупка нового - просто храните этот образ под рукой. Пересобирать его придется только при серьезных изменениях, например - новая версия ядра.

Безусловно, есть вероятность, что для вашего железа это кто-то уже сделал. Вы можете зайти в директорию ts/build/machine и поискать там название вашей платформы. Если найдете - смело пропускайте этот пункт.

Настройка сборки
#

Первое, что вам понадобится, отредактировать файл ts/build/build.conf (изначально это симлинк на build.conf.example - сделайте копию) следующим образом (раскомментируйте строки):

 1...
 2# Пригодится, чтобы больше узнать о железе
 3package lshw
 4...
 5# Набор xorg-пакетов для практически любого видео
 6package xorg7-v4l
 7package xorg7-vesa
 8package xorg7-vmware
 9package xorg7-ati
10package xorg7-nouveau
11package xorg7-openchrome
12package xorg7-intel
13package xorg7-sis
14...
15# Системные утилиты, в том числе - hwlister, о нем ниже
16package extensions
17package extensions-x
18...
19# Изменение системы сжатия
20param initrdcmd "gzip"
21...
22# Включает полный набор firmware - иногда не работает, но рекомендую раскоментировать
23param allres true
24param allfirmware true
25...

Всё остальное сейчас не важно - настраивать тонко будем потом.

Отдельно остановлюсь на том, зачем нужно поменять систему сжатия со squashfs на gzip. Скрипт hwlister.sh, о котором пойдет речь ниже, использует очень интересную методику поиска загруженного firmware - он просто смотрит время доступа к файлам в /lib/firmware и на основе этого делает выводы, какие файлы были загружены. Но squashfs монтируется с параметром relatime, что приводит к тому, что время доступа к файлам не меняется и список firmware (чёрт, не знаю, как перевести это слово, не потеряв смысл) всегда пуст. Изменение режима сжатия на gzip - самый простой и быстрый способ вернуть скрипт к жизни не залезая в кишки. Я написал об этом разработчикам, но ответа пока не было.

Сборка
#

Сборка любого образа выполняется в chroot - так что не забываем в него зайти. Для сборки толстого образа существует также специальный параметр --allmodules, который включает в образ все доступные модули ядра, что также пригодится на неизвестном железе.

1soar@localhost $ sudo ./setup-chroot
2[root@TS_chroot]/# cd build
3[root@TS_chroot]/build# ./build --allmodules --license ACCEPT --autodl

После того, как процесс завершится, в директории boot-images можно будет найти варианты образа - iso, pxe и syslinux. Можно использовать любой и загружать клиент любым удобным способом.

Сбор информации
#

Когда подопытное железо успешно загрузилось, необходимо зайти в консоль любым удобным способом и написать:

1hwlister.sh

Это обычный bash-скрипт, после выполнения которого вы обнаружите несколько файлов:

  • /firmware.list - список необходимых firmware
  • /module.list - список необходимых модулей ядра
  • /package.list - список необходимых пакетов, учитывая архитектуру будет содержать только xorg7-* пакеты
  • /vbe_modes.list - если используется uvesafb, этот файл будет содержать список поддерживаемых режимов

Некоторые файлы могут отсутствовать, если ничего подходящего не найдено

Также я рекомендую куда-нибудь сохранить вывод lshw - обязательно пригодится в будущем, когда железки под рукой уже не будет, а вы будете вспоминать, какое-же там было видео-ядро (немного личного опыта).

Этот же скрипт попытается загрузить файлы на ваш tftp-сервер, указанный в конфиге, однако, надеюсь, у вас запись на tftp, как и у меня, запрещена. Поэтому забираем файлы с тестируемой системы любым способом и кладем в директорию ts/build/machine/MACHINENAME, где MACHINENAME - кодовое имя, которое вы дадите своему железу.

Тонкий образ
#

Сборка тонкого образа - это всегда балансирование на границе между функциональностью и объемом. Меньше объем - быстрее загрузка бездисковых рабочих станций по сети, быстрее старт системы, меньше оперативной памяти требуется клиентам. Лично у меня стояла задача сделать образ минимального объёма всего под одну задачу - терминальный RDP-клиент. Об этом я и буду рассказывать.

Итак, у нас есть офис, набор тонких клиентов, подключенных проводами, получающих адрес по DHCP, загружающихся по PXE и стартующих одно единственное приложение - RDP-клиент.

Конфигурация сборки - build.conf
#

Как я уже писал выше, первый этап в конфигурации сборки - это правка файла build.conf. Он определяет какие пакеты будут включены в образ и некоторые другие параметры сборщика.

  • Все строки начинающиеся с machine - комментируем. Должно остаться только то, что используется у вас. Нужно отметить, что в конфигурации можно держать активными сразу несколько профилей - тогда получится образ, запускающийся на любом из них (в теории, если нет конфликтов).
  • Скорее всего вам не понадобятся файловые системы кроме vfat и ntfs - поэтому в блоке файловых систем можно смело комментировать строки isofs, udf, ext*.
  • Так как мы создали профиль для своего железа, содержащий необходимые пакеты xorg7, то все строки содержащие package xorg7-* - можно смело комментировать.
  • Смело комментируем все пакеты локалей package locale-* кроме, конечно ru_RU, и, по желанию, en_US - нужна она или нет вопрос спорный.
  • Если вам нужен удаленный доступ к рабочим станциям - включите package sshd
  • Если вам нужны смарт-карты и USB-токены - включите package ccidreader
  • Если вы собираетесь вырезать оконный менеджер, рабочий стол и показывать пользователю только одно приложение (например FreeRDP) - включите пакет package automount для автоматического монтирования любых USB-устройств. При этом package udisks можно смело выключить.
  • Если вам не нужен интерфейс для Wi-Fi соединений и другие рюшечки - закомментируйте package networkmanager и включите package autonet. Но будьте готовы к тому, что придется покопаться в его внутренностях - это скриптовая обвязка для системных утилит и в некоторых сетях может работать не совсем так, как ожидается.
  • Чтобы максимально облегчить образ, включаем package openbox и выключаем package gtk-*, package icons-*, package fonts-*.

Что касается пакетов в разделе Applications - здесь выбор полностью за вами. Всё описанное выше применимо к тонким клиентам, где пользователь не будет видеть своего рабочего стола (RDP, VNC, etc) и для использования, например, локального браузера - многое из перечисленного выше придется оставить.

Остается не забыть вернуть param initrdcmd "squashfs" и убрать 3 строки в самом конце: package alltimezone, param allres true и param allfirmware true - в тонком образе это нам не пригодится.

Runtime-конфигурация - thinstation.conf.buildtime
#

Файл thinstation.conf.buildtime является по своей сути bash-скриптом, предоставляющим переменные окружения для всех скриптов запуска. Перед тем, как начать его редактировать, стоит заглянуть в директорию ts/build/conf (github) - здесь собраны кусочки конфигураций для каждого пакета, включающие в себя пояснения и все доступные переменные.

Давать какие-то универсальные советы - сложно. Настройка будет зависеть от вашего окружения и используемых пакетов. Приведу лишь пример для RDP-сессии.

 1# У пользователя не будет локального UI, так что локально выкручиваем громкость на максимум
 2AUDIO_LEVEL=100
 3MIC_LEVEL=100
 4
 5# Для бездисковых станций резонно собирать логи в одном месте
 6SYSLOG_SERVER=syslog.example.com
 7
 8# Локаль и таймзона
 9LOCALE=ru_RU.UTF8
10TIME_ZONE=Europe/Moscow
11
12# Кнопки "Безопасного извлечения устройства" также не будет - поэтому включаем обязательно
13USB_STORAGE_SYNC=ON
14DISK_STORAGE_SYNC=ON
15# Монтировать устройства нужно в директорию, которую мы потом пробросим в удаленную сессию
16USB_MOUNT_DIR=/mnt/usb
17# Для поддержки кириллицы на съемных накопителях, я для себя вывел вот такой набор параметров. Он точно подходит для FAT32/NTFS разделов и FreeRDP
18USB_MOUNT_OPTIONS="rw,nosuid,nodev,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,showexec,utf8,flush,errors=remount-ro"
19DISK_MOUNT_OPTIONS="rw,nosuid,nodev,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,showexec,utf8,flush,errors=remount-ro"
20
21# Если выключили NetworkManager и включили autonet - обязательно настройте сеть
22NET_USE_DHCP=ON
23
24# Нулевая сессия должна быть оконным менеджером
25# Можно попробовать обойтись без него и даже вообще без Иксов
26# но это тема для отдельной статьи
27SESSION_0_TITLE=Desktop
28SESSION_0_TYPE=openbox
29SESSION_0_AUTOSTART=ON
30
31# Главная рабочая сессия
32# Список параметров FreeRDP - пожалуй также повод для отдельной статьи
33SESSION_1_TITLE=RemoteDesktop
34SESSION_1_TYPE=freerdp
35SESSION_1_AUTOSTART=ON
36SESSION_1_FREERDP_SERVER=rdp.example.com
37SESSION_1_FREERDP_OPTIONS="+decorations +fonts +aero ..."

Сборка тонкого образа
#

Теперь, когда конфигурация готова, остается лишь собрать легковесный образ. Всё те же команды, что и для полного образа, за исключением одного параметра:

1soar@localhost $ sudo ./setup-chroot
2[root@TS_chroot]/# cd build
3[root@TS_chroot]/build# ./build --license ACCEPT --autodl

И это всё. В зависимости от того, что вы указали в build.conf, вы получите готовые образы для загрузки по PXE, с CD-ROM, жесткого диска или флешки. При описанной конфигурации можно добиться образа размером ~90 MB и времени загрузки по PXE (от включения питания до рабочего стола) около 1 минуты. С локального диска и того быстрее.

Другие возможности
#

Нужно отметить, что всё, о чем я писал выше - советы по сборке универсального образа. Я добился того, чтобы с одного образа можно было загрузить любой ПК из присутствующих в зоопарке компании. Но может получиться так, что вам понадобится сделать несколько вариантов клиентов, с разными настройками или, например, разными адресами серверов. В таком случае обратите внимание, что ThinStation умеет как скачивать дополнительные конфигурационные файлы во время загрузки, так и докачивать дополнительные модули. Это очень хорошо описано в документации, и я на этом останавливаться не буду.

Полезные заметки
#

Очистка кухни
#

Периодически, особенно если вы активно экспериментируете с версиями пакетов, сборкой, пересборкой, перекомпилированием бинарников и т.д., рано или поздно вам придется начать очищать рабочую директорию от накопившегося мусора.

  1. Не забыть выйти из chroot
  2. Убедиться, что сохранили все свои изменения в Git
  3. Отмонтировать все системные ФС внутри кухни: umount -R thinstation/*
  4. Запустить скрипт очистки: sudo ./setup-chroot -a
  5. Удалить всё, что осталось: git clean -dx - это удалит все несохраненные файлы

Добавление своих пакетов
#

Если вы собираетесь привносить в проект что-то свое, нужно знать о том, что в терминологии ThinStation, а вернее в терминологии CRUX Linux, на котором базируется TS, существует два базовых понятия:

  • package (далее “пакет”) - некая абстракция, указывающая на то, что необходимо установить в будущий образ. Пакет может содержать кусок дерева файловой системы, отдельные файлы, или даже просто один конфигурационный файл, указывающий, например на зависимости.
  • port (далее “порт”) - подобие *.deb иди *.rpm пакета, с одним важным отличием: архив со скомпилированными файлами не содержит правил установки, а представляет из себя просто кусок дерева файловой системы. Любые правила (скрипт компиляции, скрипты пост-установки, и т.д.) лежат рядом с архивом и легко редактируются.

Когда вы хотите дополнить образ чем-то своим, первое, о чем стоит задуматься, а что именно вам нужно? Если вы хотите добавить в образ пару текстовых конфигов - просто создайте свой пакет, включите его build.conf - и этого будет более чем достаточно. Если же вам нужно собирать бинарные файлы - то вам понадобится сделать свой порт.

Создание своего порта
#

Первое, что я рекомендую сделать, это создать для своих поделок отдельную директорию. Для этого нужно в файл ts/etc/prt-get.conf добавить строку:

1prtdir /ts/ports/yourproject

Хранить в отдельной директории будет гораздо проще и безопаснее. После редактирования файла нужно не забыть перезайти в chroot. Стоит отметить, что в этом файле уже присутствуют директории с портами, разложенными по коллекциям. Сборщик будет искать порт по имени во всех директориях по-порядку, поэтому, если боитесь коллизии имен - располагайте вашу директорию выше остальных.

Теперь вам понадобится создать один единственный bash-скрипт, который будет отвечать за сборку порта: /ts/ports/yourproject/portname/Pkgfile. Образец можно посмотреть здесь, а можно подсмотреть в любом другом порте. Базовый вариант выглядит так:

 1name=mdetect-TS
 2version=0.5.2.3
 3release=1
 4source=(http://ftp.de.debian.org/debian/pool/main/m/$name/$name-$version.tar.bz2)
 5
 6build() {
 7	cd $name-$version
 8
 9	./configure --prefix=/usr \
10			--exec-prefix=/ \
11			--sysconfdir=/etc \
12			--mandir=/usr/man \
13			--disable-extras
14
15	make
16	make DESTDIR=$PKG install
17}

Давайте разберемся, что он делает (на самом деле делает не он, он лишь определяет стадию сборки):

  1. Скачивает файлы, заданные в source (в данном случае - http://ftp.de.debian.org/debian/pool/main/m/mdetect-TS/mdetect-TS-0.5.2.3.tar.bz2), их может быть несколько
  2. Распаковывает все скачанные файлы в рабочую директорию
  3. Выполняет configure + make
  4. Делает make install из директории /ts/ports/yourproject/portname/work/src в /ts/ports/yourproject/portname/work/pkg
  5. Полученное содержимое директории pkg упаковывается в архив. Это и будет наш порт, готовый для установки.

Проверим наши предположения. Чтобы выполнить первую сборку, необходимо сделать следующее:

1[root@TS_chroot]/# cd ts/ports/yourproject/portname/
2[root@TS_chroot]/ts/ports/yourproject/portname# pkgmk -kw
3=======> Building '/ts/ports/yourproject/portname/portname#0.5.2.3-1.pkg.tar.xz'.
4...
5=======> WARNING: Footprint not found, creating new.
6=======> Building '/ts/ports/yourproject/portname/portname#0.5.2.3-1.pkg.tar.xz' succeeded.

Конечный файл portname#0.5.2.3-1.pkg.tar.xz (имя файла формируется с учетом переменных заданных в начале скрипта) представляет из себя готовый к установке порт и содержит в себе дерево файловой системы. Остается включить его в образ - о том, как это сделать, смотрите ниже.

Нужно также отметить, что если у вас в директории с портом присутствуют файлы .footprint или .md5sum - сборка может “провалиться” с ошибкой из-за несоответствия дерева файлов или md5-сумм. Можно эти файлы удалить перед сборкой и они сгенерируются автоматически, а можно выполнить следующую последовательность действий:

1[root@TS_chroot]/ts/ports/yourproject/portname# pkgmk -kw
2[root@TS_chroot]/ts/ports/yourproject/portname# pkgmk -uf
3[root@TS_chroot]/ts/ports/yourproject/portname# pkgmk -um

Порт собран - самое время установить его в систему. На данном этапе речь идет о системе рабочей, той, где вы собираете ThinStation.

1[root@TS_chroot] # prt-get install portname
2prt-get: installing /ts/ports/yourproject/portname
3=======> Package '/ts/ports/yourproject/portname/portname#0.5.2.3-1.pkg.tar.xz' is up to date.
4prt-get: installing portname 0.5.2.3-1
5
6-- Packages installed
7portname
8
9prt-get: installed successfully

Теперь архив распакован в систему и все файлы доступны для использования. Однако эти файлы не появятся в собранном вами образе - для этого вам кроме порта, понадобится еще и пакет.

Создание пакета
#

Минимальный пакет может выглядеть так:

1soar@localhost$ tree ts/build/packages/mypackage/
2ts/build/packages/mypackage/
3├── dependencies
4├── etc
5│   └── somefile-placed-in-etc

Где в файле dependencies достаточно указать одну строку - base. Считается хорошим тоном, чтобы все пакеты зависели хотя бы от пакета base, но вы можете добавить больше правил. Этого уже достаточно, чтобы при включении строки package mypackage в ваш build.conf - файл somefile-placed-in-etc попал в директорию /etc вашего готового образа.

Что же делать, если мы хотим, чтобы наш пакет, кроме обычных файлов, включал в сборку наш порт? Для этого нам понадобятся всего два скрипта. Скрипт установки ts/build/packages/mypackage/build/install:

 1#!/bin/sh
 2
 3# mypackage - имя нашего порта
 4export PACKAGE=mypackage
 5export PORTS=$PACKAGE
 6repackage -e
 7
 8returnval=$?
 9
10exit $returnval

И скрипт удаления ts/build/packages/mypackage/build/remove:

1#!/bin/sh
2
3# mypackage - имя нашего порта
4export PACKAGE=mypackage
5repackage -c

Теперь, при запуске магического ./build наш порт будет добавлен в дерево файлов образа и появится в сборке. Конечно, если вы не забыли добавить этот пакет в build.conf.

Обновления
#

Нужно отметить, что все манипуляции описанные выше возможны благодаря магии системы портов CRUX. Порт устанавливается и удаляется из системы на основе данных из .footprint и важно следить, чтобы этот файл всегда был актуален. Есть и другие подводные камни - прерванный процесс установки, ошибка во время установки и еще множество различных непредусмотренных действий могут легко привести к тому, что в вашей системе (и как следствие - образе) будут файлы, которые вы совсем не ожидаете увидеть. Я периодически делаю полную очистку кухни, чтобы быть уверенным в том, что система будет вести себя as-expected. Однако, иногда на это времени не хватает. Поэтому, если какой-то пакет и/или порт стал неконсистентным, я для себя вывел следующую последовательность команд, которая в 99% случаев очистит все лишние файлы и всё-таки приведет дерево в порядок:

 1# Обновляем порт, футпринт и мд5
 2prt-get update mypackage
 3prt-get update -uf mypackage
 4prt-get update -um mypackage
 5# Очищаем билд (выполняет содержимое файла remove, описанного выше)
 6./build --removeall
 7# Удаляем порт
 8prt-get remove mypackage
 9# Обновляем пакет (при наличии .dna файла)
10update mypackage
11# Устанавливаем порт
12prt-get install mypackage
13# Запускаем сборщик
14./build --license ACCEPT --autodl

Что еще почитать
#

Вот пара достаточно интересных статей, которые когда-то мне очень помогли:

Ну и на всякий случай, моя ветка ThinStation на GitHub, где можно найти некоторые дополнительные профили и изменения, может быть пригодится:

@soar
Автор
@soar
Senior SRE/DevOps engineer

Related

О - Откровенность
· loading · loading
Sysadmin Linux
ipset-persistent — sysv init скрипт для ipset
·235 слов·2 минут· loading · loading
Sysadmin Linux Firewall
Аналог iptables-persistent для ipset
Удалённая переустановка linux на примере Debian
·1616 слов·8 минут· loading · loading
Sysadmin Linux
Что если есть только удаленный доступ и полностью распределенный жесткий диск?