вторник, 25 ноября 2014 г.

Создание своей репы с poudriere(8)

Небольшая шпаргалка по созданию своей репы с помощью ports-mgmt/poudriere.

Для полного понимания происходящего нужно уметь элементарно работать с портами: знать как выставлять опции, ставить/удалять порт, знать про /etc/make.conf и понимать в каком формате туда можно дописывать опции.

При написаниии использовал эти ссылки:
http://blather.michaelwlucas.com/archives/1941
http://www.bsdnow.tv/tutorials/poudriere
http://forums.freebsd.org/viewtopic.php?t=38859

Введение

Как известно, штатным источником софта во FreeBSD является дерево портов. Когда вы ставите софт из портов, система собирает на самом деле из порта пакет, и пакет уже устанавливается в систему. Для работы с пакетами используется утилита pkg(8).
Соответственно, вместо компилирования пакетов из портов на каждой подконтрольной машине, удобней иметь некий общий для всех машин репозиторий, с уже собранными пакетами.
pkg(8) как пакетный менеджер умеет работать с удаленными репозиториями, т. е. ставить софт из них, разрешать зависимости и т. д. Стандартной утилитой для создания своего репозитория сейчас считается poudriere(8), которая используется в том числе для сборки официальной фряшной репы.
В этой статье я создам свой репозиторий с помощью poudriere(8) с нуля, настрою http-сервер для отдачи пакетов, а затем настрою pkg(8) для того, чтобы он брал софт из этой репы.
При этом я в своей работе обычно использую только свою репу и добавляю туда софт или изменяю опции по надобности. Официальную репу FreeBSD я обычно использую только на самом раннем старте создания репы, а потом дизаблю.

Чуть подробнее

Poudriere(8) после сборки просто кладёт в указанную вами папку все пакеты и файлы метаданных. Т. е. он только собирает, готовит репу и ничего больше. Какой протокол вы будете использовать для работы с репозиторием это уже ваше дело. pkg(8) умеет работать с HTTP и FTP, например. Полный список протоколов в ман-странице. Вы берете любой http или ftp сервер и настраиваете его указывая, что вот тут лежат файлы, которые ты должен отдавать.
Я же в качестве транспорта буду использовать HTTP. Еще poudriere (8) умеет подписывать собранные пакеты , но я не буду использовать подпись, так проще.

Настройка poudriere(8)

У меня все данные, занимающие много места хранятся в каталоге /storage. В нём я создаю отдельный каталог poudriere, который будет являться рабочим каталогом для утилиты poudriere(8), т. е. там будет проходить сборка, храниться мир и дерево портов для сборки, логи сборки, сами пакеты с метаданными и т. д.
Создаю каталоги, сразу для всего
# mkdir -p /storage/poudriere/distfiles
По названию папки distfiles понятно зачем она нужна.

Затем устанавливаю минимальный набор софта, нужный для разворачивания и конфигурирования репы. Пока из официальной репы, т. к. других источником нет, да и разницы нет никакой.
Бутстрапим пакетный менеджер:
# pkg
Ставим poudriere(8):
# pkg install ports-mgmt/poudriere
Ставим утилиту для работы с фреймворком опций портов, т. е. чтобы можно было выбирать опции при сборке порта:
# pkg install ports-mgmt/dialog4ports

Далее редактирую конфиг для poudriere(8), скопировав sample. Тут сам конфиг хорошо откомментирован. В общем, всё можно найти в документации. У меня на сервере сборки используется только UFS.
# egrep -v '^\s*(#|$)' /usr/local/etc/poudriere.conf
NO_ZFS=yes
FREEBSD_HOST=ftp://ftp.freebsd.org
RESOLV_CONF=/etc/resolv.conf
BASEFS=/storage/poudriere
USE_PORTLINT=no
USE_TMPFS=yes
DISTFILES_CACHE=/storage/poudriere/distfiles
CHECK_CHANGED_OPTIONS=verbose #
CHECK_CHANGED_DEPS=yes #Ask when options on changing
NOLINUX=yes

Далее создаю каталог, где будут храниться вспомогательные конфиги, если он еще не создан:
# mkdir /usr/local/etc/poudriere.d

Вообще с помощью poudriere можно создавать любое число веток портов для любого количества релизов FreeBSD. Устроено это следующим образом.
С poudriere(8) вы создаёте окружение для сборки, иммитирующее нужный вам релиз. Такое окружение это "мир" нужного релиза, распакованный в определенную директорию. Вся эта штука в терминологии poudriere(8) называется jail. Тут есть некоторая путаница из-за такого названия. Это _не_ тот самый типичными фряшными джэйл, нет. Это что-то вроде контейнера. Хотя в процессе сборки poudriere(8) будет автоматом без вашего участия динамически создавать, а затем уничтожать пачку именно фряшных джэлов. Всё, чем нужно рулить вам, как пользователю - это poudriere jail'ы. Poudriere jail имеет такие параметры как имя, архитектура и релиз, для которого будет скачан и распакован "мир".
Таким образом достигается подход, когда на одной машине вы можете собирать пакеты для разных релизов и архитектур, просто создавая пачку таких poudriere jail'ов.

Создание окружения

Например, чтобы создать poudriere jail для 10.2-RELEASE архитектуры amd64 и с именем FreeBSD:10:amd64 нужно выполнить:
# poudriere jail -c -j FreeBSD:10:amd64 -v 10.2-RELEASE -a amd64
После этого poudriere(8) сам всё скачает и распакует в /storage/poudriere/jails.
В данном случае я выбрал имя "FreeBSD:10:amd64" для poudriere jail'а для удобства дальнейшего использования, т. к. такое имя полностью соответствует переменной ${ABI}, определяющей архитектуру релиза в некоторых утилитах. Так мне проще будет настраивать потом pkg(8).
Таком же образом можно создать остальные poudriere jail'ы, соответствующий другим релизам.
Я использую только последний релиз и собираю пакеты только для него. Стоит также помнить, что между релизами одной мажорной ветки обеспечена бинарная совместимость. Вывести список poudriere jail можно командой:
# poudriere jail -l
Поскольку poudriere jail это обычный "мир", то для него справедливы все те выходящие патчи от FreeBSD, закрывающие разные дыры. Подтянуть все фиксы, т. е. обновить poudriere jail, как бы это делалось для обычного сервера командой freebsd-update fetch/install, можно так:
# poudriere jail -u -j FreeBSD:10:amd64
Рекомендую это делать с такой же периодичностью, как для настроящего сервера с таким же релизом.

Дерево портов

Далее нам нужно дерево портов, из которого собственно будут собираться наши пакеты. Можно использовать уже существующее дерево портов, если оно у вас уже есть. Однако, я предпочитаю использовать отдельное дерево портов для нужд poudriere. Во-первых, я ставлю серверы без дерева портов, т. е. у меня нет его в привычном /usr/ports, т. к. это просто не нужно. Я ведь пакетами буду пользоваться. Во-вторых, мне кажется, что так больше порядка.
В poudriere(8) есть возможность создавать сколько угодно разных веток портов с привязкой к своему poudriere jail'у. Я с такими вещами не заморачиваюсь. Я использую только 1 ветку портов для всего. Мне это не нужно, да и так намного проще. Я делаю так:
# poudriere ports -c
Если было бы нужно с привязкой к конкретному джэйлу, то:
# poudriere ports -c -p JailName
После этого всё само скачается и распакуется в /storage/poudriere/ports/(default|JailName).
Если бы нужно было использовать уже существующее дерево портов в привычном /usr/ports, то я бы ввел:
# poudriere ports -c -F -f none -M /usr/ports -p default 
# poudriere ports -c -f none -m null -M /usr/ports -p default
Обновлять бы такое дерево можно было бы с помощью штатной утилиты portsnap(8) (или svn, что привычнее), как и раньше.
В ином, т. е. моем случае нужно просить об этом poudriere(8):
# poudriere ports -u
Если у нас не одно дерево портов, то посмотреть список можно так:
# poudriere ports -l
Теперь нужно определить список портов для сборки. Я задал свой список портов для сборки таким образом:
# cat /usr/local/etc/poudriere.d/pkglist.txt
...
www/apache24
lang/php56
net/freeradius2
net/openldap24-server
...

Опции портов

Обычно при работе с деревом портов можно использовать файл /etc/make.conf для задания предопределенных опций по умолчанию. Например, сразу отключить такие опции как иксы или дебаг. С poudriere(8) тоже можно использовать подход с опциями в make.conf, только это файл будет располагаться в другом месте. Поскольку у меня только одно дерево портов, мой make.conf будет располагаться тут:
# cat /usr/local/etc/poudriere.d/make.conf
OPTIONS_UNSET=X11 HAL DEBUG EGL
WANT_OPENLDAP_SASL="YES"
#SQUID_CONFIGURE_ARGS="--enable-useragent-log"
В файле у меня уже определено некоторое количество опций. Синтаксис меняется со временем, нужно сверяться с текущим фреймворком для задания опций.
Если бы у меня было несколько деревьев портов для каждого poudriere jail, то имя файла было бы иным:
# cat /usr/local/etc/poudriere.d/JailName-make.conf
Полностью опции для портов задаются опять же с помощью вызова poudriere(8). Т. е. никакие `make config` и т. д. тут не работают. Мало того, все определенные poudriere(8) опции хранятся в другом месте, отличном от /var/db/ports. А точнее в папке /usr/local/etc/poudriere.d/options. Поскольку я использую одно дерево портов для всего, я не могу сказать как будет в случае нескольких веток для разных poudriere jail.
Итак, задать опции для всех портов, перечисленных в /usr/local/etc/poudriere.d/pkglist.txt можно командой:
# poudriere options -f /usr/local/etc/poudriere.d/pkglist.txt
Т. е. тут poudriere(8) берет список портов из файла и последовательно выводит диалог с опциями. Чтобы задать опции для какого-то конкретного порта, вместо указания опции '-f' и имени файла нужно просто ввести неполный путь к порту, например:
# poudriere options shells/bash
Замечу, что в предыдущих двух случаях опции будут запрашиваться только если они никогда раньше не были заданы или с последнего момента задания опций появились новые. Чтобы всегда выводить диалог с опциями нужно использовать ключ '-c'. Например:
# poudriere options -cf /usr/local/etc/poudriere.d/pkglist.txt
# poudriere options -c shells/bash

Сборка портов

Всё готово. У нас есть окружение, дерево портов, для которых заданы опции. Можно собирать.
Запускаем сборку портов из списка pkglist.txt:
# poudriere bulk -j FreeBSD:10:amd64 -f /usr/local/etc/poudriere.d/pkglist.txt
Чтобы собрать вообще всё дерево портов нужно ввести ключ '-a', но я обычно так не делаю:
# poudriere bulk -j JailName -a
Далее будет долгий процесс сборки, в процессе которого на экран будет выводить куча информации. В процессе сборки можно нажать ctrl+t я посмотреть текущий отчет о том, сколько портов собрано, сколько времени затрачено на сбоку, сколько осталось собрать и т. д.
По окончанию сборки на экране появится отчет.
Мы получили готовый репозитарий. Осталось настроить транспорт и сам pkg(8).

Транспорт и настройка pkg(8)

Я буду раздавать пакеты по HTTP с помощью apache. Можно взять абсолютно любой другой веб-сервер или FTP сервер. Мой конфиг выглядит так:
# cat /usr/local/etc/apache24/Includes/pkg.example.org.conf
<VirtualHost *:80>
    ServerAdmin admin@example.org
    DocumentRoot /storage/poudriere/data/packages
    ServerName pkg.example.org
    <Directory />
        Options Indexes FollowSymLinks
        AllowOverride AuthConfig
        Require all granted
    </Directory>
</VirtualHost>
Мой репозиторий доступен по DNS имени pkg.example.org. Apache можно поставить из офф. репы или из своей же:
# pkg install /storage/poudriere/data/packages/FreeBSD:10:amd64-default/All/apache24-2.4.17.txz
Для pkg(8) всё просто. На всех клиентских машинах я дизаблю официальный репозиторий FreeBSD и использую свой. Т. е. в файле /etc/pkg/FreeBSD.conf меняю опцию 'enabled' с 'yes' на 'no', а затем создаю конфиг:
# mkdir -p /usr/local/etc/pkg/repos
# cat /usr/local/etc/pkg/repos/myrepo.conf
myrepo: {
 url: "http://pkg.example.org/${ABI}-default",
 mirror_type: "none",
 enabled: yes
}
Тут мне пригодилось имя моего poudriere jail, потому что оно соответствует переменной ${ABI}. Так по-моему удобней.
Далее все просто:
# pkg update
# pkg search squid
# pkg install www/squid
# pkg upgrade
и т. д.

Дальнейшее обслуживание

В дальнейшем я просто обновляю дерево портов и запускаю сборку. Будет собраны только те порты, новые версии которых появились в дереве и зависимые от них порты.
# poudriere ports -u
# poudriere bulk -j FreeBSD:10:amd64 -f /usr/local/etc/poudriere.d/pkglist.txt
Если у порта появились новые опции, то poudriere(8) в процессе сборки никаких диалогов не будет выводить. Так что я считаю полезным изредка запускать:
# poudriere options -f /usr/local/etc/poudriere.d/pkglist.txt
Если мы поменяли какие-то опции, то poudrire(8) в процессе сборки выведет список старых и новых опций и пересоберет порт, даже если он остался на той же версии.
Чтобы пересобрать какой-то порт принудительно, например, www/squid, нужно использовать ключ '-c':
# poudriere bulk -c -j FreeBSD:10:amd64 www/squid
Или '-f /usr/local/etc/poudriere.d/pkglist.txt' вместо имени порта, если нужно пересобрать вообще все из списка.
Для удобства я создал такие однобуквенные alias'ы для командного интерпретатора:
# alias | grep poudriere
B       (poudriere bulk -j FreeBSD:10:amd64 -f /usr/local/etc/poudriere.d/pkglist.txt)
P       (poudriere ports -u)
T       (poudriere testport -j FreeBSD:10:amd64 -n -o)
U       (poudriere jail -j FreeBSD:10:amd64 -u)
Вот так и живём.

понедельник, 17 ноября 2014 г.

Немного growfs

Маааленькая шпаргалка.
Понадобилось тут на виртуальной машине увеличить диск.
Увеличил диск на гипервизоре, при загрузке выскочило такое:
GEOM: da1: the secondary GPT header is not in the last LBA.

После этого сделал
# gpart recover da1
# gpart resize -i 1 da1
# growfs /dev/da1p1
Всё.