Budowanie pakietów .deb i prosty sposób na własne repo.
W pracy admina po jakimś czasie chyba każdy zbiera sobie kolekcję skryptów i programów które używa do debugowania błędów, czy do automatyzacji czynności. Od tooli typu nmap, socat czy tcpdump które są niesamowicie użyteczne ale nie są instalowane w domyślnej instalacji, po własne skrypty automatyzujące niektóre czynności, czy służące np. do wyciągania statów z monitoringu.
I o ile gdy się ma jeden serwer panowanie na tym nie stanowi wielkiego problemu (zainstalować to co potrzeba, a skrypty wrzucić do /usr/local/bin) to już przy dwóch zaczyna się “aaa mam nową wersję tego skryptu na innym serwerze” a przy większej ilości zwykle kończy się na instalowaniu tooli “kiedy są potrzebne” czyli za każdym razem tracimy czas, a w przypadku własnych skryptów kończy się to tym że na serwerach jest 6 różnych wersji tego samego skryptu.
Rozwiązanie jest proste, albo trzymać wszystkie skrypty na NFSie ( ale to raczej obejście problemu ), albo zapaczkować je i dodać repo z paczkami do /etc/apt/sources.list. Na szczęście samo tworzenie prostych paczek (bez rzeczy wymaganych żeby paczka była zaakceptowana do “oficjalnego” repo Debiana/Ubuntu) jest dosyć proste. Ale po kolei.
Paczka debianowa “w środku” wygląda mniej-więcej tak:
xani@hydra:~/src/my/pkg-repo/packages/xani-tools (master)ᛯ find . . ./DEBIAN ./DEBIAN/control ./DEBIAN/conffiles ./DEBIAN/postinst ./DEBIAN/prerm ./usr ./usr/bin ./usr/bin/haproxy_stat.pl
Mamy tu katalog DEBIAN gdzie mamy pliki informacyjne paczki oraz skrypty uruchamiane przed/po instalacji/deinstalacji paczki, a pozostałe katalogi to są rzeczy która nasza paczka zainstaluje na dysku (i usunie przy instalacji). Z ważniejszych:
- control – opis/nazwa/wersja paczki oraz zależności (czego wymaga, z czym konfliktuje)
- conffiles – które pliki paczki są plikami konfiguracyjnymi. Plik oznaczony jako “config” w tej paczce, gdy zostanie zmieniony przez usera spowoduje przy nasŧępnej instalacji zapytanie czy zostawić modyfikacje usera czy zainstalować nową wersję configa, a przy usunięciu bez opcji purge config zostanie w systemie
- post/pre inst/rm – wykonywane przed (pre) i po (post) instalacji/usunięciu paczki. Można użyć np. do sprzątania po aplikacji (pliki cache itp.) przy deinstalacji, lub do np. startu aplikacji od razu po instalacji, czy dodawaniu skryptów startowych
Wymagany jest tylko plik control, reszta jest opcjonalna. A wygląda on tak:
Package: xani-tools Version: 0.0.1 Section: base Priority: optional Architecture: all Maintainer: XANi <some@email> Depends: etckeeper (>= 0.40), syslog-ng, emacs23-nox, emacs-goodies-el, git-core, iotop, iftop, links, mc, multitail, mtr-tiny, nmap, psmisc, screen, tcpdump, curl, socat Recommends: swaks, atop, ntpdate Suggests: hping3 Conflicts: rsyslog Description: Some random tools tools i use for everyday work
Po kolei:
- Package/version/section/priority/architecture/maintainer – wiadomo o co chodzi
- Depends: rzeczy bez których paczka się nie zainstaluje
- Recommends: te pakiety zostaną zaznaczone jeżeli nie będą konfliktować z niczym, ale można je odznaczyć i paczka się zainstaluje (nie są wymagane)
- Suggests – oznacza że domyśnie nie zainstaluje danej paczki ale będzie ona na liście sugestii w menadżerze paczek
- Conflicts – nie zainstaluje się gdy ta paczka jest w systemie. W powyższym przykładzie syslog-ng jest w depends a rsyslog w conflicts, więc spowoduje to zmianę rsysloga na syslog-ng. Można robić to samo gdy chce się np. domyślnie instalować postfixa zamiast exima
- Description – wiadomo o co chodzi. Można dodać więcej linijek poniżej ale muszą się zaczynać od spacji (jako kontynuacja poprzedniej linijki)
To teraz tworzenie paczki. Instalujemy dpkg-dev fakeroot
(NIE FAKEROOT-NG robi zbugowane paczki z ownerem plików jako user a nie root) i:
$ fakeroot dpkg-deb -b xani-tools dpkg-deb: budowanie pakietu "xani-tools" w "xani-tools.deb".
albo gdy chcemy mieć numer wersji w paczce:
$ fakeroot dpkg-deb -b xani-tools ../repo dpkg-deb: budowanie pakietu "xani-tools" w "../repo/xani-tools_0.0.1_all.deb".
I jeżeli chodzi o budowanie najprostrzej paczki to tyle ;]. Ale to nam nie wystarcza, chcemy przecież repo dla naszych serwerów, idealnie z paczkami w gicie, podzielone na część “stabilną” i “dev”. Zacznijmy więc od repo gitowego:
xani@hydra:~/src/my/pkg-repoᛯ find . . ./packages ./packages/xani-tools ./packages/xani-tools/DEBIAN ./packages/xani-tools/DEBIAN/postinst ./packages/xani-tools/DEBIAN/prerm ./packages/xani-tools/DEBIAN/conffiles ./packages/xani-tools/DEBIAN/control ./packages/xani-tools/usr ./packages/xani-tools/usr/bin ./packages/xani-tools/usr/bin/haproxy_stat.pl xani@hydra:~/src/my/pkg-repoᛯ git init Initialized empty Git repository in /home/xani/src/my/pkg-repo/.git/ xani@hydra:~/src/my/pkg-repo (master)ᛯ git add . ; git commit -a -m 'Initial commit' [master (root-commit) 7a0bd78] Initial commit 3 files changed, 48 insertions(+), 0 deletions(-) create mode 100644 packages/xani-tools.deb create mode 100644 packages/xani-tools/DEBIAN/conffiles create mode 100644 packages/xani-tools/DEBIAN/control create mode 100755 packages/xani-tools/DEBIAN/postinst create mode 100755 packages/xani-tools/DEBIAN/prerm create mode 100755 packages/xani-tools/usr/bin/haproxy_stat.pl
I teraz część najważniejsza, mianowicie budowanie paczek. Chcemy mieć możliwość cofnięcia się do starszej wersji paczki, oraz żeby paczki w branchu gitowym dev (i każdym innym) były w oddzielnym repo:
#!/bin/sh PKGDIR="packages" TMPDIR="/tmp/repo" REPODIR="/home/xani/src/my/repo" STARTPWD=$(pwd) git clone . $TMPDIR if [ $1 ] ; then BRANCH=$1 else BRANCH="master" fi #make sure repodir exists mkdir -p $REPODIR/$BRANCH/binary cd $TMPDIR git checkout $BRANCH cd $PKGDIR for a in $(find . -mindepth 1 -maxdepth 1 -type d) ;do fakeroot dpkg-deb -b $a $REPODIR/$BRANCH/binary done # cleaning rm -rf $TMPDIR #making Packages.gz cd $REPODIR/$BRANCH dpkg-scanpackages -m binary /dev/null | gzip -9c > Packages.gz
czyli gdy odpalimy ten skrypt w katalogu głównym repa stworzy on nam repo w podanym katalogu z brancha master, chyba że podamy mu nazwę innego brancha. Teraz wystarczy dodać do repo docelowego serwera coś w stylu:
deb ssh://repo@reposerwer/repo/packages/master ./
i dodać klucze publiczne. Można także po prostu udostępnić przez http jak “normalne” repo, wszystko zależy czy w naszych paczkach jest coś poufnego.
Dalszy rozwoj to budowanie paczek w posthookach repo albo używając hooków githuba (aktualnie mam tak w pracy, minutę-dwie po commicie przychodzi mi email z wynikami budowania paczek i ew. błędami).
Na początku to trochę roboty ale szybko się zwraca, zwłaszcza gdy już zrobi się parę paczek typu “zainstaluj mi wszystko co jest wymagane do postawienia LAMP” albo “zainstaluj mi toole które używam” :)