Quantcast
Channel: Debian Users Gang - teksty
Viewing all 160 articles
Browse latest View live

Instalacja Clamav z on-access

$
0
0

Sporo jest porad jak zainstalować i jakie komendy użyć do skanowania komputera (clamav), ale mało jest jak ustawić on-access i żeby w logach nie wywalało, że coś nie pasuje.

Najpierw moje testy na różnych dystrybucjach, to tak:

  • Debian testing i unstable - w testingu Clamav działa. A unstable w aktualnej wersji jest kłopot w clamav 0.98.5-rc1, dlatego zalecam do cofnięcia pakietu do testingu lub stable (używam sida)
  • Linux Mint 17 - działa wzorowo.

No to zabieram się do rozwinięcia tematu, instalujemy Clamav (wraz z nakładką Clamtk) i pozostałe pakiety.....

1.Instalujemy:

    apt-get update

    i

    apt-get install clamav clamav-base clamav-daemon clamav-freshclam
    clamav-unofficial-sigs clamdscan clamtk libclamav6

2.Teraz po wszystkim aktualizujemy baze Clamav:

    freshclam

3.Teraz konfiguracja na początku można sobie pomóc konfiguratorem , wystarczy wywołać go komendą:

    dpkg-reconfigure clamav-daemon

między innymi można tam włączyć on-access, i troche innych ustawień np. do ilu MB ma skanować plik itp. Niestety nie obejmuje wszystkich ustawień, które oferuje Clamav. Trzeba troche pogrzebać w pliku konfiguracyjnym - clamd.conf

4.Wchodzimy do

    /etc/clamav/clamd.conf

tu można sprawdzić czy wszystko jest włączone i wstawić jeszcze jeden wpis bo w logach na pewno jest błąd. Sprawdzamy czy mamy włączone :

    ScanOnAccess true

    User root - uruchamiamy clamd jako root, potrzebne gdy chcemy on-access

Jeszcze musimy wstawić instrukcje, żeby Clamav wiedział co skanować (on-access)

    OnAccessIncludePath

Uruchamiamy komputer ponownie i patrzymy czy wszystko działa i czy nie ma błędów

    /var/log/clamav/clamav.log

Pozdrawiam.

Poradnik amatora Linuksa


Wyrównywanie tekstu w powłoce za pomocą column

$
0
0

Aby szybko wyrównać tekst (np. pliki konfiguracyjne) w powłoce można skorzystać z programu column:

$ cat test.txt
AAAAAAAA BB CCCCC DDD
AA BBB C DDDDDDDDDD
AAAAA BBBBBB CCC DDDDDD

$ column -t test.txt
AAAAAAAA  BB      CCCCC  DDD
AA        BBB     C      DDDDDDDDDD
AAAAA     BBBBBB  CCC    DDDDDD

$ head -n2 test.txt | column -t
AAAAAAAA  BB   CCCCC  DDD
AA        BBB  C      DDDDDDDDDD

Można również ustawić separator pól, np. czytelniejsze wyświetlenie pliku CSV (aczkolwiek metoda ta ma swoje ograniczenia, np. pole nie może być puste):

$ sed 's/ /,/g' test.txt
AAAAAAAA,BB,CCCCC,DDD
AA,BBB,C,DDDDDDDDDD
AAAAA,BBBBBB,CCC,DDDDDD

$ sed 's/ /,/g' test.txt | column -s , -t
AAAAAAAA  BB      CCCCC  DDD
AA        BBB     C      DDDDDDDDDD
AAAAA     BBBBBB  CCC    DDDDDD

Zwiększenie bezpieczeństwa połączeń Thunderbirda z kontami pocztowymi Gmail, Yahoo, Yandex

$
0
0

Uwaga początkowa: wskazówki tutaj przedstawione należy traktować jako dodatkowe zabezpieczenie. Nie zastępuje ono jednak szyfrowania end-to-end za pomocą np GPG.

Konfiguracja, na której były testowane połączenia:

Debian 8 Jessie
Thunderbird 34 w wersji 64 bit za strony Mozilli

Aby zwiększyć bezpieczeństwo połączeń (rozumiane jako utrudnienie dostępu do treści) należy zmienić ustawienia w: Preferencje -> Preferencje -> Edytor ustawień. Klikamy "Zachowam ostrożność"

Wartości wpisów ustawiamy na 3:

security.tls.version.fallback-limit
security.tls.version.max
security.tls.version.min

Zestawy używanych szyfrów zmienia się zmieniając wpisy zaczynające się od security.ssl3. Proponuję ustawić na początku wszystkie na false, a następnie zależnie od dostawcy poczty można przestawić odpowiednie na wartość true.

Zmień na true jeśli używasz:

Gmail:

security.ssl3.ecdhe_rsa_aes_128_gcm_sha256
security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256

Yandex:

security.ssl3.rsa_aes_256_sha
security.ssl3.rsa_camellia_256_sha

Yahoo:

security.ssl3.ecdhe_rsa_aes_256_sha
security.ssl3.ecdhe_ecdsa_aes_256_sha

Minusem powyższych ustawień jest to, że są one niestandardowe i z tego powodu mogą one stanowić nasz charakterystyczny elektroniczny odcisk palca (Fingerprint). Jeśli zakładałeś i zawsze użytkowałeś anonimowo swoją skrzynkę (np poprzez sieć Tor i nigdy nie podawałeś swojego nazwiska ani innych identyfikujących informacji), miej to na uwadze. Jeśli jednak skrzynka jest na Twoje nazwisko i tak wiadomo kim jesteś, więc co najwyżej można zwiększyć bezpieczeństwo wyłączając słabsze zestawy szyfrów.

Przypominam, że wiadomości dalej nie są w formie zaszyfrowanej w części, a może nawet całej reszcie drogi do adresata. Dostawcy usług poczty elektronicznej jak najbardziej ciągle mogą na swoich serwerach odczytać wiadomość, nie wiadomo czy a jeśli tak to jak szyfrowane jest połączenie pomiędzy serwerami z pocztą, a także serwerem adresata a adresatem. Z tego względu należy stosować również szyfrowanie treści wiadomości w modelu end-to-end (nie deszyfrowane na drodze od nadawcy do adresata) za pomocą GPG, a powyższe wskazówki potraktować jako dodatkowe, niewielkie zwiększenie bezpieczeństwa.

Archiwizacja plików w Linuksie z linii poleceń z zastosowaniem kompresji, redundancji, szyfrowania i uwierzytelniania autentyczności pochodzenia

$
0
0

W poradniku użyto gpg (GnuPG) 1.4.18, par2cmdline 0.6.11, xz 5.1.0alpha uruchomione na Debianie 8 Jessie

W poniższym poradniku zostanie pokazane jak stworzyć skompresowane archiwum. Następnie zostaną stworzone dane naprawcze, dzięki którym będzie można w razie lekkiego uszkodzenia archiwum je odtworzyć, następnie archiwum zostanie zaszyfrowane z użyciem symetrycznego szyfru blokowego w trybie CFB. Następnie zostanie ono podpisane, by móc zweryfikować autentyczność pochodzenia archiwum. Następnie zostanie podzielone na mniejsze części, by móc umieścić je na mniejszych nośnikach pamięci lub przesłać poprzez email. Do części tych również zostaną wygenerowane dane naprawcze i połączone w jednym pliku tar. Te ostatnie będą główną ochroną przed uszkodzeniami, wewnętrzne dane naprawcze będą tylko dodatkowym zabezpieczeniem na wypadek zagubienia zewnętrznych.

Tryb CFB, a w zasadzie jego wariant, jest domyślnym dla OpenPGP

Dlaczego ktoś chciałby szyfrować pliki blokowym szyfrem symetrycznym? Szyfrowanie uznanym szyfrem symetrycznym jest prostsze dla użytkownika, szybsze dla sprzętu i jednocześnie bezpieczniejsze niż szyfrowanie RSA lub inne metody szyfrowania z użyciem szyfrów asymetrycznych. Wadą jednak jest to, że nie rozwiązuje problemu przesłania do jakiejś osoby danych wymaganych do odszyfrowania szyfrogramu poprzez niezaufane kanały komunikacji m.in. Internet. Jeśli jednak tworzymy sami dla siebie kopię zapasową lub możemy bezpiecznie przekazać hasło osobie, do której zamierzamy w przyszłości wysłać szyfrogram, np będąc z nią sam na sam, wtedy metoda ta jest najlepsza.

Dlaczego tworzyć dane naprawcze? Gdyż dzięki nim można w 100% odtworzyć oryginalne dane z lekko uszkodzonego archiwum. To tym bardziej ważne, gdy stosujemy kompresję xz: nawet zamiana jednego bitu w dowolnym miejscu powoduje, że program xz nie poradzi sobie z wypakowaniem dalszej części archiwum. Jeśli przesyłamy duży plik przez Internet (lub wiele małych plików składających się na duże archiwum), pomimo tego że protokół TCP posiada zdolność do wykrycia większości błędów, możliwość uszkodzenia pliku podczas przesyłania nie jest duża, ale jak najbardziej na tyle duża że można uznać ją za realną.


Archiwizowanie

Zakładam, że znajduję się w katalogu przeznaczonym do pracy, a w podkatalogu katalogDoZaszyfrowania znajdują się wszystkie pliki, które chcę zaszyfrować.

Opcjonalnie w tym momencie mogę stworzyć nowy plik z losową długością, która zmieni wielkość pliku wynikowego.

dd if=/dev/urandom of=katalogDoZaszyfrowania/plikOLosowejDlugosci bs=6 count=$RANDOM

Należy ustawić dla bs taką wartość, by plik wynikowy różnił się od oryginału wystarczająco.

Teraz możemy przystąpić do stworzenia lekko skompresowanego archiwum programem tar i xz:

tar cf - katalogDoZaszyfrowania/ | xz -zf --format=xz -2e --threads=2 - > wiadomosc.tar.xz

W tej chwili stworzone zostaną dane redundantne (nadmiarowe), które zabezpieczą przed uniemożliwieniem wypakowania archiwum w skutek jego uszkodzenia. Danych tych będzie 2%. Następnie właściwe archiwum i dane dodatkowe zostaną zapakowane do pliku wiadomoscPlusNaddatek.tar, a właściwe archiwum wraz z danymi nadmiarowymi bezpiecznie usunięte.

par2 create -r2 wiadomosc.tar.xz.par2 wiadomosc.tar.xz
tar -cf wiadomoscPlusNaddatek.tar wiadomosc.tar.xz*
shred -n1 --random-source=/dev/zero wiadomosc.*
rm wiadomosc.*

Z ciekawych szyfrów blokowych dostępnych w tej wersji oprogramowania można wymienić CAMELLIA256 i AES256. Ja użyję pierwszego. Oprócz tego wyłączona zostanie kompresja w programie gpg, gdyż dane już raz były kompresowane, więc nie zmniejszyłoby to ich wielkości, ale mogłoby utrudnić rozszyfrowanie w wypadku uszkodzenia. Aby przystąpić do części właściwej procesu szyfrowania wystarczy wykonać komendę i wpisać trudne do przewidzenia przez atakującego hasło (długie, skomplikowane, losowe):

gpg --cipher-algo=CAMELLIA256 --digest-algo=SHA512 --compress-algo="none"  \
--output szyfrogram.tar.xz.tar.gpg --symmetric wiadomoscPlusNaddatek.tar

shred -n1 --random-source=/dev/zero wiadomoscPlusNaddatek.tar
rm wiadomoscPlusNaddatek.tar

Jeśli plików byłoby więcej i nie pasowałoby wpisywanie za każdym razem hasła możesz zastanowić się nad opcją --passphrase-file, jednak należy uniemożliwić dostęp do pliku innym osobom, a po wykonaniu szyfrowania nadpisać plik. Ewentualnie opcja --passphrase-fd 0 i podanie hasła przez potok z komendy echo, jednak wtedy hasło zostanie zapisane w historii basha.

Aby podzielić plik na części, których nazwy zaczynają się od czescNr a końcą Szyfrogramu.tar.xz.tar.gpg.part, a każda z części jest mniejsza niż 10 Megabajtów, wykonaj:

split --suffix-length=4 --numeric-suffixes --additional-suffix="Szyfrogramu.tar.xz.tar.gpg.part" \
--bytes=10MB  szyfrogram.tar.xz.tar.gpg czescNr

--bytes=10MB to 10^6 bajtów czyli mniej niż 2^20 bajtow. Jeśli chcesz ustawić maksymalną wielkość na 2^20 bajtów, wtedy --bytes=10m

Tutaj również zostaną stworzone dodatkowe, nadmiarowe dane, w celu minimalizacji prawdopodobieństwa niemożliwości odczytu zaszyfrowanych plików. Danych tych będzie 4% czyli więcej, gdyż to one powinny dać sobie radę w pełni z uszkodzeniami. Dane redundantne wewnątrz są tylko dodatkowymi, które mogą pozwolić wypakować archiwum w razie zagubienia dodatkowych danych zewnętrznych. Do danych wewnętrznych powinno się udać dostać nawet w przypadku lekkiego uszkodzenia pliku OpenPGP, jeśli oczywiście mamy hasło/klucz. W wyniku operacji powstanie plik daneNadmiaroweGPG.tar, który również wysyłamy wraz z innymi częściami pliku.

par2 c -r4 czescNr0000Szyfrogramu.tar.xz.tar.gpg.part.par2 czescNr*Szyfrogramu.tar.xz.tar.gpg.part
tar -cf daneNadmiaroweGPG.tar czescNr*Szyfrogramu.tar.xz.tar.gpg.part.*par2
rm czescNr*Szyfrogramu.tar.xz.tar.gpg.part.*

Zakładam, że w systemie jest już skonfigurowane gpg, wraz z kluczami którymi można podpisać plik. Tworzymy podpis cyfrowy szyfrogramu:

gpg --output podpisSzyfrogramu.tar.xz.tar.gpg.sig --detach-sig szyfrogram.tar.xz.tar.gpg

Mamy części szyfrogramu, więc można usunąć szyfrogram:

rm szyfrogram.tar.xz.tar.gpg

Jeśli chcemy więc wysłać gdzieś pliki, to wysyłamy: czescNr*Szyfrogramu.tar.xz.tar.gpg.part, podpisSzyfrogramu.tar.xz.tar.gpg.sig, daneNadmiaroweGPG.tar


Przywracanie danych

Założenie jest takie, że w katalogu w którym jesteśmy możemy swobodnie działać, znajdują się pliki czescNr*Szyfrogramu.tar.xz.tar.gpg.part, a także plik z informacjami nadmiarowymi daneNadmiaroweGPG.tar i podpis cyforwy podpisSzyfrogramu.tar.xz.tar.gpg.sig

Sprawdzone teraz zostanie, czy pliki nie są uszkodzone.

tar -xf daneNadmiaroweGPG.tar
par2 verify czescNr0000Szyfrogramu.tar.xz.tar.gpg.part.par2

Jeśli ujrzymy napis "All files are correct, repair is not required" to znaczy, że nie trzeba naprawiać. Jeśli ujrzymy "Repair is required", naprawiamy, a następnie usuwamy niepotrzebne już rozpakowane pliki naddatkowe:

par2 repair czescNr0000Szyfrogramu.tar.xz.tar.gpg.part.par2
rm czescNr*Szyfrogramu.tar.xz.tar.gpg.part.*

Aby połączyć wystarczy wykonać:

cat czescNr*Szyfrogramu.tar.xz.tar.gpg.part > szyfrogram.tar.xz.tar.gpg

Teraz można zweryfikować czy plik nie był modyfikowany. Jeśli był, to mógł zostać podmieniony przez atakującego lub dane naprawcze nie wystarczyły do jego pełnego naprawienia. Jeśli podpis się zgadza ujrzymy linijkę "gpg: Poprawny podpis złożony przez"

gpg --verify podpisSzyfrogramu.tar.xz.tar.gpg.sig szyfrogram.tar.xz.tar.gpg

Teraz archiwum zostanie rozszyfrowane rozszyfrować plik wystarczy wykonać komendę:

gpg --output rozszyfrowanaWiadomoscPlusNaddatek.tar --decrypt szyfrogram.tar.xz.tar.gpg

Gdy ja plik lekko zmodyfikowałem hexeditem, podczas rozszyfrowania zobaczyłem:

gpg: OSTRZEŻENIE: zaszyfrowana wiadomość była manipulowana!

Teraz rozpakujemy plik tar i sprawdzimy czy nie jest uszkodzony:

tar -xf rozszyfrowanaWiadomoscPlusNaddatek.tar
par2 verify wiadomosc.tar.xz.par2

Jeśli plik jest uszkodzony wykonujemy:

par2 repair wiadomosc.tar.xz.par2

Możemy sprawdzić w tym miejscu czy dane naprawcze wystarczyły do naprawienia archiwum:

xz --test wiadomosc.tar.xz

Następnie można wyodrębnić pliki z archiwum do katalogu wyodrebnione:

mkdir wyodrebnione
tar -xf wiadomosc.tar.xz -C wyodrebnione

Końcowy test dla poradnika:

Jeśli chcemy porównać w tym miejscu oryginalne pliki jeszcze nie zaszyfrowane z powstałymi w wyniku wszystkich powyższych operacji, wystarczy wykonać:

rsync -rvnc --delete katalogDoZaszyfrowania/ wyodrebnione/katalogDoZaszyfrowania/

Jeśli jakiś plik jest inny niż oryginał to pod napisem "sending incremental file list" wyświetli się jego nazwa.


Czego nie jestem pewien? Tego czy tar, xz lub potok nie pozostawi po tych operacjach na dysku fragmentów niezaszyfrowanych jeszcze plików.

Skryptowa nakładka na kernelowski moduł ZRAM

$
0
0

Wiele miesięcy temu opisywałem ciekawy mechanizm, który może nam pomóc w odciążeniu dysku twardego. Z tym, że wiele się od tego czasu zmieniło, świat poszedł ździebko do przodu i postanowiłem napisać lekki update w stosunku do modułu ZRAM. Tego starego tekstu zdecydowałem się nie kasować -- może komuś się przyda, jakby nie patrzeć, są jeszcze ludzie na świecie co używają stabilnych wydań debiana.

Dla przypomnienia, ZRAM to taki moduł kernela, który tworzy wirtualne urządzenia w pamięci operacyjnej komputera, a te z kolei można wykorzystać pod system plików lub też i pod przestrzeń wymiany SWAP. Dane w takim urządzeni są kompresowane, dzięki czemu mamy do dyspozycji więcej miejsca w pamięci. Jeśli mamy niepierwszej jakości dysk twardy, lub też wykorzystujemy szyfrowanie i nie mamy przy tym procka ze wsparciem dla AES, to operacje zapisu/odczytu mogą zająć wieki. Możemy w dość znacznym stopniu odciążyć dysk przenosząc pliki do RAMu, który jest o wiele szybszy no i dane w nim nie podlegają szyfrowaniu. Tu jest przykład zastosowania takiego mechanizmu -- pokazane w oparciu o przeprowadzenie kompilacji na w pełni zaszyfrowanym systemie nie posiadającym wsparcia dla AES.

Jeśli mamy dużo pamięci operacyjnej, to raczej ZRAM będzie zbędny i tylko podniesie nam rachunek za prąd. Natomiast jeśli nasz komputer nie szasta zbytnio pamięcią, możemy rozszerzyć ją 2-3 krotnie. Trzeba jednak pamiętać, że kompresja dodaje lekki overhead procesorowi.

By móc skorzystać z modułu ZRAM, musimy mieć go wkompilowanego w kernel:

cat /boot/config-3.16.0-4-amd64 | grep -i zram

CONFIG_ZRAM=m

CONFIG_ZRAM_LZ4_COMPRESS is not set

CONFIG_ZRAM_DEBUG is not set

Na githubie znalazłem projekt co się zwie zram-init . Jest to skrypt, zajmujący się tworzeniem odpowiednich urządzeń i całość działa prawie OOTB. Prawie, a to z tego względu, że jak się przyjrzymy wyżej, w debianie nie mamy standardowo wkompilowanego LZ4_COMPRESS i trzeba to będzie zmienić ale o tym później.

W paczce też znajdziemy kilka innych plików, w tym też konfigurację dla modułu ZRAM. Chodzi o to ile urządzeń system będzie tworzył na starcie -- domyślnie są 3. Jeden dla SWAP, jeden dla /tmp/ i jeden dla /var/tmp/ . Oczywiście możemy to sobie dowolnie dobrać przez edycję pliku /etc/modprobe.d/zram.conf :

options zram num_devices=3

Skrypt zram-init wgrywamy do /usr/sbin/ .

Ja używam systemd, zatem potrzebne mi są również pliki .service , które są także dostarczone z paczką. Z tym, że trzeba zmienić w nich algorytm kompresji -- trzeba pozmieniać linijki, przykładowo:

ExecStart=/usr/sbin/zram-init -s2 -alz4 2048

na

ExecStart=/usr/sbin/zram-init -s2 -alzo 2048

Jeśli nie odpowiada nam rozmiar urządzenia (w powyższym przykładzie to 2G), możemy również zmienić tę wartość. Sam skrypt ma więcej opcji, patrz --help .

Po edycji pliki wrzucamy do do /etc/systemd/system/ i aktywujemy:

systemctl enable zram_swap.service systemctl enable zram_tmp.service systemctl enable zram_var_tmp.service

Takich plików .service możemy tworzyć ile dusza zapragnie. Trzeba jednak pamiętać, by odpowiednio dobrać parametr -b oraz stworzyć odpowiednią ilość urządzeń.

Jeśli mamy zamiar korzystać z kompresji plików w katalogu /tmp/ , musimy także zamaskować systemową usługę tmp.mount :

systemctl mask tmp.mount

Jeśli mamy jakieś wpisy w pliku /etc/fstab dotyczące /tmp/ , trzeba je wykomentować.

Po zresetowaniu maszyny, urządzenia ZRAM powinny zostać utworzone, odpowiednio sformatowane i zamontowane w systemie.

Github z obsługą kluczy SSH

$
0
0

W końcu przyszedł czas na eksperymenty z githubem. Jakby nie patrzeć, do tej pory jedyne co potrafiłem zrobić w przypadku samego gita, to wydać jedno polecenie -- "git clone". Wszelkie inne rzeczy, choć nie było ich wcale tak dużo, robiłem via panel www, co trochę było upierdliwe. Postanowiłem nauczyć obsługi gita i nieco uprościć sobie życie. Jeśli chodzi o samą naukę, to tutaj jest dostępny dość obszerny pdf (prawie 500 stron): http://git-scm.com/book/en/v2 . Nie będę tutaj przerabiał wyżej podlinkowanej książki, bo w sumie jeszcze jej nie przeczytałem, tylko zajmę się ciekawym tematem, czyli implementacją kluczy SSH, tak by operować na gicie bez zbędnych haseł.

Przede wszystkim potrzebne będą nam klucze SSH ale cały proces ich tworzenia również nie zostanie uwzględniony w tym artykule -- to zostało zrobione już tutaj, ewentualnie można jeszcze skorzystać ze ściągawki dostępnej w helpie githuba. Dalsza część artykułu zakłada, że mamy już do dyspozycji jakiś klucz SSH. Jeśli nie mamy konta na githabie, to przydałoby się je również utworzyć.

Mając klucz SSH i konto, możemy przejść do powiązania tych dwóch rzeczy ze sobą. W tym celu włazimy w opcje konta i po lewej stronie klikamy w SSH keys:

Teraz klikamy na ADD SSH key (prawy róg) i uzupełniamy pola od nazwy i klucza. Powinno to wyglądać mniej więcej tak:

Po pomyślnym dodaniu klucza powinniśmy zobaczyć go na liście kluczy:

I to w sumie z grubsza jeśli chodzi o konfigurację githuba.

Testujemy czy działa:

morfik:~$ ssh -T git@github.com Hi morfikov! You've successfully authenticated, but GitHub does not provide shell access.

Teraz wystarczy założyć jakieś repozytorium i możemy przejść do konfiguracji klienta.

Tu oczywiście musimy sobie zainstalować paczkę git -- to jest tekstowy klient. Jeśli komuś nie odpowiada operowanie na konsoli, może skorzystać z graficznego narzędzie co się zwie git-cola .

Mając już swoje własne repozytorium oraz odpowiednie pakiety w systemie, odpalamy terminal i klonujemy to repozytorium:

$ git clone https://github.com/morfikov/conffiles Cloning into 'conffiles'... remote: Counting objects: 61, done. remote: Compressing objects: 100% (29/29), done. remote: Total 61 (delta 29), reused 58 (delta 29) Unpacking objects: 100% (61/61), done. Checking connectivity... done.

By komunikować się z tym repozytorium, potrzebne są odpowiednie adresy, a te można podejrzeć przez:

$ cd conffiles $ git remote -v origin https://github.com/morfikov/conffiles (fetch) origin https://github.com/morfikov/conffiles (push)

I jak widać, jest tutaj link zaczynający się od https i jeśli spróbowalibyśmy zrobić np. push, zostanie wyrzucone zapytanie o użytkownika oraz hasło:

$ git push Username for 'https://github.com': morfikov Password for 'https://morfikov@github.com':

I tego właśnie chcemy uniknąć -- raz, że przesyłanie hasła przez sieć wyszło z mody, a dwa, to lepiej nie utrudniać sobie zanadto życia pamiętaniem zbędnych rzeczy.

By pozbyć się hasła, musimy zmienić te dwa powyższe adresy. Nie jest to jakoś specjalnie trudne, jedyne co musimy zrobić to dostosować poniższą linijkę:

$ git remote set-url origin git@github.com:morfikov/conffiles.git

W moim przypadku nazwa użytkownika to morfikov, zaś nazwa repozytorium to conffiles (adres: https://github.com/morfikov/conffiles).

Po odpowiednim dostosowaniu tej powyższej linijki i wklepaniu jej do terminala, adresy powinny ulec zmianie:

$ git remote set-url origin git@github.com:morfikov/conffiles.git $ git remote -v origin git@github.com:morfikov/conffiles.git (fetch) origin git@github.com:morfikov/conffiles.git (push)

Teraz push powinien przejść bez problemu:

$ git push Everything up-to-date

Jeśli nie chce nam się przechodzić przez proces zmiany linków, możemy sklonować repozytorium w poniższy sposób:

$ git clone git@github.com:morfikov/conffiles.git

Linki zostaną automatycznie ustawione na ssh.

Podpisywanie swojej pracy na githubie przy pomocy kluczy GPG

$
0
0

W tym artykule zostanie przedstawiony sposób na wykorzystanie kluczy GPG jeśli chodzi o działania przeprowadzane na githubie. Będziemy w ten sposób w stanie podpisać swoje commity czy tagi, by było wiadomo czy zmiany, które zostały poczynione, tak naprawdę pochodzą od nas. Oczywiście to może się wydać przesadą dla wielu ludzi ale skoro jest możliwość wykorzystania kluczy GPG, to czemu z tego nie skorzystać?

Jak można się domyśleć, potrzebne będą nam klucze GPG ale sposób ich tworzenia oraz konfiguracja systemu nie zostaną tutaj opisane. To zostało z robione w tym artykule.

Jeśli mamy już wygenerowane klucze, możemy przejść do działania.

  1. Definiowanie klucza

Plik konfiguracyjny gita ma sporo użytecznych opcji. Jedną z nich jest ta odpowiadająca za sprecyzowanie klucza, którym będziemy podpisywać pewne rzeczy. Rozchodzi się oczywiście o user.signingkey . By dodać odpowiedni wpis, listujemy pierw prywatne klucze szyfrujące:

$ gpg --list-secret-keys

/home/morfik/.gnupg/secring.gpg

sec 4096R/0x72F3A416B820057A 2014-08-08 Key fingerprint = 9F30 BD23 F4A2 3921 5E29 A3B6 72F3 A416 B820 057A uid Mikhail Morfikov <morfik@nsa.com> ssb 4096R/0x46DF79598289C782 2014-08-08

Teraz wpisujemy w terminal poniższą linijkę:

$ git config --global user.signingkey 0x72F3A416B820057A

Spowoduje to dodanie do pliku konfiguracyjnego gita (~/.gitconfig) odpowiednich wpisów -- można oczywiście ręcznie wyedytować ten plik i dodać poniższą zwrotkę:

[user] ... signingkey = 0x72F3A416B820057A

Od tej pory, git (jeśli poproszony o to) będzie podpisywał tagi oraz commity.

  1. Podpisywanie tagów

Spróbujmy zatem coś podpisać. Na początek tagi:

$ git tag -s v1.0 -m 'morfiprojekt'

You need a passphrase to unlock the secret key for user: "Mikhail Morfikov <morfik@nsa.com>" 4096-bit RSA key, ID 0x72F3A416B820057A, created 2014-08-08

Jak widać, zostaliśmy poproszeni o hasło do klucza. Popatrzmy zatem na sam tag:

$ git show v1.0 tag v1.0 Tagger: Mikhail Morfikov <morfik@nsa.com> Date: Mon Feb 16 17:48:13 2015 +0100

morfiprojekt -----BEGIN PGP SIGNATURE-----

iQIcBAABCgAGBQJU4h9NAAoJEM0EaBB3G2UgsuMQAKtAx9m/bG4zCtsrSH5Mq832 +P6YPkZMqbnXCITVRy7HqVigFDunYtGXu5Y6ZfUYV+kjRlAXMnMQHYFghwVej7cu Os3WEu2OFs1sbyzSgUkpVlVcHsjO4TjoKoZum7Wgk3IIzONdreyv8nrYsNjiPb5F UTdu5ERb/AHExzS2wS6MXdBl/PtAY8b+o2vdWahhuZ5nIHC2F5GK6m05Dhkr6LvE 2ikO4pKZY+/toDV9Q1xalUDIloaeB5pcB+2VOuLBQYKT8OaVjfSt9vH6ZrJbe7SE oJ7cSIMRhPbqz5kCqEoYesOoOA6J75FaeWiEx0DNHlegnVg6CqkSwPyeeccVrY4H hslNYEf3lEGWV4HakwuOZFq1Rx+R6D/vnMCoFED/S56W2GLIv7HfPveb3AW+1Pap rFbZ0SGIarSePLUF+qkvD53qeQ5HoV05laCKIUp9D93ybryjA6YiMib8sylh7DOr GwWuLi06hpzQw4QN1Vj8Cmw900J8MB5GpW7NoxN00NBz6sWNpnBeDmBpS77tcyOy KGyrGO5MzCfIKA79jJaBBSUB9h3G94haNDoYPbMrv3x6Sx8CIsDds8cQ+YSDlnKS 94Kf7yJ/9QNiX15dmo8j21+oIjQlaoq9aX2TtvxND4ELJhIE0ulIobU5xZy1Bc0d Gc7txjpF4eQsOQh+l4Ka =7UmQ -----END PGP SIGNATURE-----

Widzimy, że została dodana do niego sygnatura. Zweryfikujmy ją zatem. Do tego celu potrzebny będzie klucz publiczny tej osoby co ten tag podpisała, a sam proces weryfikacji wygląda jak poniżej:

$ git tag -v v1.0 object 75f7bdc3ef9f6846371cf24604a53f5d9d9e51ad type commit tag v1.0 tagger Mikhail Morfikov <morfik@nsa.com> 1424105293 +0100

morfiprojekt gpg: Signature made Mon 16 Feb 2015 05:48:13 PM CET gpg: using RSA key 0x72F3A416B820057A gpg: Good signature from "Mikhail Morfikov <morfik@nsa.com>" [ultimate] Primary key fingerprint: 9F30 BD23 F4A2 3921 5E29 A3B6 72F3 A416 B820 057A

Wygląda dobrze.

  1. Podpisywanie commitów

No to teraz spróbujmy podpisać commita:

$ git status On branch master Your branch is up-to-date with 'origin/master'. Untracked files: (use "git add <file>..." to include in what will be committed)

jakis_tam_plik_testowy

nothing added to commit but untracked files present (use "git add" to track)

$ git add .

$ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage)

new file: jakis_tam_plik_testowy

$ git commit -a -S -m 'test podpisu commita' You need a passphrase to unlock the secret key for user: "Mikhail Morfikov <morfik@nsa.com>" 4096-bit RSA key, ID 0x72F3A416B820057A, created 2014-08-08

[master 2332031] test podpisu commita 1 file changed, 1 insertion(+) create mode 100644 jakis_tam_plik_testowy

$ git status On branch master Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits) nothing to commit, working directory clean

I teraz już tylko zostało zweryfikowanie podpisu:

$ git log --show-signature -1 commit 23320312843f5631dd15851eb61483ef3a4491a4 gpg: Signature made Mon 16 Feb 2015 06:15:29 PM CET gpg: using RSA key 0x72F3A416B820057A gpg: Good signature from "Mikhail Morfikov <morfik@nsa.com>" [ultimate] Primary key fingerprint: 9F30 BD23 F4A2 3921 5E29 A3B6 72F3 A416 B820 057A Author: Mikhail Morfikov <morfik@nsa.com> Date: Mon Feb 16 18:15:29 2015 +0100

test podpisu commita

I tutaj również wszystko przebiegło pomyślnie.

Więcej informacji na temat wykorzystania kluczy GPG w przypadku gita można znaleźć tutaj.

Krótka lekcja gita

$
0
0

Od paru dni eksperymentuję sobie z gitem i postanowiłem zrobić drobną ściągawkę na temat jego obsługi z poziomu linii poleceń. Konfigurowanie systemu jak i samego githuba tak by korzystać z kluczy SSH jak i GPG zdążyłem już opisać i nie będę tego poruszał w tym tekście. Oczywiście te dwie rzeczy nie są wymagane do pracy z gitem ale przydają się. W każdym razie, tutaj zajmę się podstawowymi operacjami jakie zwykle człowiek będzie dokonywał gdy przyjdzie mu korzystać z gita.

Zdaję sobie sprawę, że są różne nakładki graficzne na gita ale jak się okaże po przeczytaniu tego artykułu, cmd nie jest taki straszny, choć sama dokumentacja może przerazić, bo jest tego dość sporo i raczej wszystkiego od razu nie ogarniemy.

Na sam początek doinstalujmy paczkę git , bo to w niej znajdziemy narzędzia, przy pomocy których będziemy dokonywać zmian w repozytorium. Pakiet jest dostępny w debianie, także sama instalacja nie powinna nam przysporzyć problemów.

  1. Konfiguracja gita

Gita konfiguruje się za pomocą polecenia git config . Tutaj jest obszerny opis poszczególnych opcji. Dodatkowe informacje można znaleźć również tutaj.

Konfiguracji można dokonywać na dwa sposoby -- przy pomocy powyższego narzędzia, albo też przez ręczne uzupełnianie plików konfiguracyjnych, a te są czytane z określonych lokalizacji i w określonej kolejności. Pierwszym z nich jest plik systemowy (dodanie --system do git config) i ten jest zlokalizowany w /etc/gitconfig -- zwykle nie jest obecny w systemie. Drugi w kolejności jest plik użytkownika (dodane --global do git config) i jest to ~/.gitconfig (ew. ~/.config/git/config , jeśli istnieje). To zwykle na nim będziemy operować dodając nowe opcje lub zmieniając stare. Ostatnie miejsce gdzie git zagląda w poszukiwaniu konfiguracji, to lokalizacja repozytorium. Po wydaniu git clone lub git init , plik konfiguracyjny będzie dostępny w repo/.git/config . To jest lokalna konfiguracja, z której będzie korzystało określone repozytorium i jeśli mamy jakieś niestandardowe opcje, które chcemy zaaplikować tylko do tego danego repo, to właśnie w tym pliku musimy je umieścić. Można także określić swój własny plik przy pomocy opcji -f dopisanej do git config . Nam jednak wystarczy plik użytkownika.

Jeśli chodzi o zapis opcji konfiguracyjnych, to jest trochę inaczej. Pierw jest czytany plik konfiguracyjny repozytorium, następnie plik użytkownika i na końcu konfiguracja systemowa. Dlatego też by wstępnie skonfigurować sobie gita, trzeba pamiętać o dopisaniu do git config opcji --global .

Dość tego gadania, pora przejść do działania. Na początek skonfigurujmy sobie kilka podstawowych parametrów:

$ git config --global user.name "Mikhail Morfikov" $ git config --global user.email morfik@nsa.com $ git config --global gpg.program gpg $ git config --global user.signingkey 0x72F3A416B820057A $ git config --global push.default simple $ git config --global color.ui always $ git config --global core.whitespace blank-at-eol,blank-at-eof,space-before-tab,tabwidth=4 $ git config --global merge.tool meld $ git config --global diff.tool meld $ git config --global core.editor vim $ git config --global core.pager less $ git config --global core.excludesfile ~/.config/git/.gitignore_global $ git config --global core.ignorecase false $ git config --global core.eol lf $ git config --global core.autocrlf input $ git config --global web.browser firefox $ git config --global browser.firefox.path /opt/firefox/firefox $ git config --global browser.firefox.cmd 'firefox -P default' $ git config --global log.date iso8601 $ git config --global log.decorate full

Powyższe opcje mówią raczej same za siebie i nie trzeba ich dodatkowo wyjaśniać. Oczywiście nie musimy wszystkiego ręcznie wpisywać i ustawiać -- można dociągnąć paczkę git-gui , odpalić wersję gui via git gui i wejść tam w opcje i pozmieniać wedle uznania. To powinno wygenerować dość przyzwoity plik konfiguracyjny, z tym, że nie wszystko idzie ustawić w ten sposób. Poza tym, graficzne aplikacje ustawiają swoje własne opcje i ignorują przy tym niektóre parametry wpisane w pliku konfiguracyjnym.

  1. Tworzenie repozytorium

Mamy z głowy zatem wstępną konfigurację gita. Przydałoby się teraz poćwiczyć umiejętność operowania na repozytorium. Pierw musimy się o jakieś postarać. Tworzymy zatem dedykowany katalog, przechodzimy do niego i robimy repozytorium:

morfik:~$ mkdir repozytoria/practice-makes-perfect/

morfik:~$ cd repozytoria/practice-makes-perfect/

morfik:~/repozytoria/practice-makes-perfect$ git init Initialized empty Git repository in /home/morfik/repozytoria/practice-makes-perfect/.git/

morfik:~/repozytoria/practice-makes-perfect$ ls -al total 12K drwxr-xr-x 3 morfik morfik 4.0K 2015-02-17 11:20:51 ./ drwxr-xr-x 3 morfik morfik 4.0K 2015-02-17 11:20:01 ../ drwxr-xr-x 7 morfik morfik 4.0K 2015-02-17 11:20:51 .git/

Został utworzony katalog .git , w którym to znajdować się będą wszystkie informacje na temat przeprowadzanych zmian w repozytorium. Póki co, nic tam jeszcze zbytnio nie ma:

morfik:~/repozytoria/practice-makes-perfect$ tree .git/ .git/ ├── HEAD ├── branches ├── config ├── description ├── hooks │   ├── applypatch-msg.sample │   ├── commit-msg.sample │   ├── post-update.sample │   ├── pre-applypatch.sample │   ├── pre-commit.sample │   ├── pre-push.sample │   ├── pre-rebase.sample │   ├── prepare-commit-msg.sample │   └── update.sample ├── info │   └── exclude ├── objects │   ├── info │   └── pack └── refs ├── heads └── tags

9 directories, 13 files

Jak widać, mamy tam kilka przykładowych skryptów (pliki .sample), i to co nas bardziej interesuje, czyli pliki HEAD, description i config .

W pliku description trzymany jest opis repozytorium. Dobrze jest edytować ten plik i dopisać krótki opis.

Plik config już po części omówiliśmy, z tym, że trzeba wspomnieć o jednej ważnej rzeczy -- ustawienia z plików konfiguracyjnych się sumują, czyli jeśli w tym pliki są jakieś ustawienia, których nie zdefiniowaliśmy w dwóch pozostałych plikach konfiguracyjnych -- zostaną one uwzględnione. Podobnie jest z hierarchią plików i ustawione tutaj opcje, które już istnieją w pozostałych plikach konfiguracyjnych, będą mieć pierwszeństwo.

By połapać się jak wygląda konfiguracja dla jakiegoś określonego repozytorium, przechodzimy do jego głównego katalogu i wydajemy poniższe polecenie:

$ git config -l ... core.repositoryformatversion=0 core.filemode=true core.bare=false core.logallrefupdates=true

Powyższe opcje odpowiadają dokładnie tym określonym w pliku konfiguracyjnym config repozytorium.

Ostatni plik to HEAD . Standardowo wygląda on tak:

morfik:~/repozytoria/practice-makes-perfect$ cat .git/HEAD ref: refs/heads/master

Są to informacje na temat gałęzi, w której aktualnie się znajdujemy -- więcej o nim będzie w dalszej części artykułu.

  1. Plik licencji i README

Pliki w repozytorium powinny mieć licencję. Jeśli nie zdefiniujemy licencji, wtedy wszystkie udostępniane pliki będą na domyślnej licencji ustalonej prawnie, czyli brak kopiowania/zmieniania plików. W debianie pliki z licencjami są zlokalizowane w /usr/share/common-licenses/ . Mamy tam do wyboru:

$ ls -al /usr/share/common-licenses total 220K drwxr-xr-x 2 root root 4.0K 2014-12-06 18:54:52 ./ drwxr-xr-x 335 root root 12K 2015-02-17 10:15:18 ../ -rw-r--r-- 1 root root 12K 2004-12-19 21:30:25 Apache-2.0 -rw-r--r-- 1 root root 6.0K 1996-12-16 03:58:50 Artistic -rw-r--r-- 1 root root 1.5K 1999-08-26 14:06:20 BSD lrwxrwxrwx 1 root root 8 2014-11-30 13:37:40 GFDL -> GFDL-1.3 -rw-r--r-- 1 root root 20K 2010-03-24 00:34:05 GFDL-1.2 -rw-r--r-- 1 root root 23K 2008-11-03 17:47:07 GFDL-1.3 lrwxrwxrwx 1 root root 5 2014-11-30 13:37:40 GPL -> GPL-3 -rw-r--r-- 1 root root 13K 2010-03-24 00:34:05 GPL-1 -rw-r--r-- 1 root root 18K 2010-03-24 00:34:05 GPL-2 -rw-r--r-- 1 root root 35K 2007-07-02 00:55:35 GPL-3 lrwxrwxrwx 1 root root 6 2014-11-30 13:37:40 LGPL -> LGPL-3 -rw-r--r-- 1 root root 25K 2010-03-25 18:29:55 LGPL-2 -rw-r--r-- 1 root root 26K 2010-03-24 00:34:05 LGPL-2.1 -rw-r--r-- 1 root root 7.5K 2010-03-24 00:34:01 LGPL-3

Pliki w tym repo będą na licencji GPL-2. Kopiujemy zatem plik do głównego katalogu repozytorium:

morfik:~/repozytoria/practice-makes-perfect$ cp /usr/share/common-licenses/GPL-2 ./LICENSE morfik:~/repozytoria/practice-makes-perfect$ ls -al total 32K drwxr-xr-x 3 morfik morfik 4.0K 2015-02-17 12:01:59 ./ drwxr-xr-x 3 morfik morfik 4.0K 2015-02-17 11:20:01 ../ drwxr-xr-x 7 morfik morfik 4.0K 2015-02-17 11:53:48 .git/ -rw-r--r-- 1 morfik morfik 18K 2015-02-17 12:01:59 LICENSE

Przydałoby się także stworzyć plik README.md , który to będzie wyświetlany na głównej stronie repozytorium na githubie.

morfik:~/repozytoria/practice-makes-perfect$ touch README.md morfik:~/repozytoria/practice-makes-perfect$ echo "This is a testing repository for learning purposes"> README.md

  1. Wprowadzanie zmian w repozytorium

To przygotowaliśmy wstępnie repozytorium. Musimy jeszcze uwzględnić te zmiany, tak by git je zapamiętał. Najpierw sprawdzamy co tak naprawdę git zarejestrował:

morfik:~/repozytoria/practice-makes-perfect$ git status On branch master

Initial commit

Untracked files: (use "git add <file>..." to include in what will be committed)

LICENSE README.md

nothing added to commit but untracked files present (use "git add" to track)

Oba pliki zostały wykryte ale jeszcze ich stan nie podlega monitorowaniu. Zgodnie z informacją, dodajemy je:

morfik:~/repozytoria/practice-makes-perfect$ git add *

morfik:~/repozytoria/practice-makes-perfect$ git status On branch master

Initial commit

Changes to be committed: (use "git rm --cached <file>..." to unstage)

new file: LICENSE new file: README.md

Teraz już tylko wystarczy zaaplikować zmiany:

morfik:~/repozytoria/practice-makes-perfect$ git commit -a -S -m 'Repository setup'

You need a passphrase to unlock the secret key for user: "Mikhail Morfikov <morfik@nsa.com>" 4096-bit RSA key, ID 0x72F3A416B820057A, created 2013-11-13

[master (root-commit) 4de0d7f] Repository setup 2 files changed, 340 insertions(+) create mode 100644 LICENSE create mode 100644 README.md

Wyżej zostało wypisane to jakie pliki zostały zmienione wraz z usuniętymi i dodanymi linijkami. W tym przypadku tworzyliśmy pliki, zatem zostały dodane nowe linijki (+).

Jeśli nie korzystamy z kluczy GPG, nie podajemy opcji -S . Z kolei parametr -a odpowiada za uwzględnienie wszystkich plików, które zostały zmodyfikowane lub usunięte, za wyjątkiem tych nowych, których nie chcemy włączać póki co do repozytorium. Opcja -m odpowiada za treść wiadomości, która zostanie uwzględniona w logu.

Zmienił się także nieco wygląd drzewa katalogów repozytorium:

morfik:~/repozytoria/practice-makes-perfect$ tree -a . ├── .git │   ├── COMMIT_EDITMSG │   ├── HEAD │   ├── branches │   ├── config │   ├── description │   ├── hooks │   │   ├── applypatch-msg.sample │   │   ├── commit-msg.sample │   │   ├── post-update.sample │   │   ├── pre-applypatch.sample │   │   ├── pre-commit.sample │   │   ├── pre-push.sample │   │   ├── pre-rebase.sample │   │   ├── prepare-commit-msg.sample │   │   └── update.sample │   ├── index │   ├── info │   │   └── exclude │   ├── logs │   │   ├── HEAD │   │   └── refs │   │   └── heads │   │   └── master │   ├── objects │   │   ├── 22 │   │   │   └── fb3a8ab3ec2e800d1e22255204ec8d735d3d43 │   │   ├── 4d │   │   │   └── e0d7f07def79578ed908669c9bc0da4383a3b7 │   │   ├── d1 │   │   │   └── 59169d1050894d3ea3b98e1c965c4058208fe1 │   │   ├── e4 │   │   │   └── 67acb33a14fd0f651500057a6364403c1ebd38 │   │   ├── info │   │   └── pack │   └── refs │   ├── heads │   │   └── master │   └── tags ├── LICENSE └── README.md

17 directories, 24 files

Zostało dodanych kilka obiektów, oraz został utworzony log.

  1. Log

Sam log można przeglądać przy pomocy poniższego polecenia:

morfik:~/repozytoria/practice-makes-perfect$ git log commit 4de0d7f07def79578ed908669c9bc0da4383a3b7 (HEAD, refs/heads/master) Author: Mikhail Morfikov <morfik@nsa.com> Date: 2015-02-17 12:21:27 +0100

Repository setup

Log jest póki co krótki, bo zrobiliśmy tylko jeden commit. W przypadku gdy wprowadzamy wiele zmian, powyższe polecenie może nam zwrócić sporo informacji.

Oczywiście opcji, które można sprecyzować, by odpowiednio formatować logi, jest całe mnóstwo. Te częściej używane są z kolei przystępnie opisane tutaj.

Generalnie rzecz biorąc, na początek przydadzą nam się poniższe parametry.

Uwzględnianie zmian w commitach:

morfik:~/repozytoria/practice-makes-perfect$ git log -p commit 4de0d7f07def79578ed908669c9bc0da4383a3b7 (HEAD, refs/heads/master) Author: Mikhail Morfikov <morfik@nsa.com> Date: 2015-02-17 12:21:27 +0100

Repository setup

diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. ...

Zwracanie kilka ostatnich pozycji, w tym też i ostatniego commita:

morfik:~/repozytoria/practice-makes-perfect$ git log -1 commit 4de0d7f07def79578ed908669c9bc0da4383a3b7 (HEAD, refs/heads/master) Author: Mikhail Morfikov <morfik@nsa.com> Date: 2015-02-17 12:21:27 +0100

Repository setup

Zwracanie wybranego commita:

morfik:~/repozytoria/practice-makes-perfect$ git log 4de0d7f07def79578ed908669c9bc0da4383a3b7 commit 4de0d7f07def79578ed908669c9bc0da4383a3b7 (HEAD, refs/heads/master) Author: Mikhail Morfikov <morfik@nsa.com> Date: 2015-02-17 12:21:27 +0100

Repository setup

Powyżej został zwrócony commit w oparciu o hash. Przydatne jeśli chcemy wyświetlić informacje, a dysponujemy jedynie tym ciągiem.

Zwracanie commitów z określonego przedziału czasowego:

morfik:~/repozytoria/practice-makes-perfect$ git log --since=2.weeks --until=now commit 4de0d7f07def79578ed908669c9bc0da4383a3b7 (HEAD, refs/heads/master) Author: Mikhail Morfikov <morfik@nsa.com> Date: 2015-02-17 12:21:27 +0100

Repository setup

Można także używać dat w postaci: "2015-02-16 12:00:02", przykładowo:

morfik:~/repozytoria/practice-makes-perfect$ git log --since=yesterday --until="2015-02-17 12:22:00" commit 4de0d7f07def79578ed908669c9bc0da4383a3b7 (HEAD, refs/heads/master) Author: Mikhail Morfikov <morfik@nsa.com> Date: 2015-02-17 12:21:27 +0100

Repository setup

Przy czym nie są obowiązkowe obie pozycje --since i --until , możemy równie dobrze podać tylko jeden z nich.

Wyświetlanie commitów określonego autora:

morfik:~/repozytoria/practice-makes-perfect$ git log --author=morfik commit 4de0d7f07def79578ed908669c9bc0da4383a3b7 (HEAD, refs/heads/master) Author: Mikhail Morfikov <morfik@nsa.com> Date: 2015-02-17 12:21:27 +0100

Repository setup

Co ciekawe, wpisanie morfik zwraca commita, mimo, że nie ma tam takiego autora. W manie można wyczytać, że to jest wzór a nie autor, czyli wszystkie commity zawierające w polu Author morfik, zostaną zwrócone.

Statystyki commitów:

morfik:~/repozytoria/practice-makes-perfect$ git log --stat commit 4de0d7f07def79578ed908669c9bc0da4383a3b7 (HEAD, refs/heads/master) Author: Mikhail Morfikov <morfik@nsa.com> Date: 2015-02-17 12:21:27 +0100

Repository setup

LICENSE | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + 2 files changed, 340 insertions(+)

Dostosowywanie wyglądu loga:

morfik:~/repozytoria/practice-makes-perfect$ git log --pretty=format:"%H - %an, %ad : %s" 4de0d7f07def79578ed908669c9bc0da4383a3b7 - Mikhail Morfikov, 2015-02-17 12:21:27 +0100 : Repository setup

Powyższe opcje możemy łączyć, dostając bardziej przefiltrowany log.

  1. Zdalna kopia repozytorium

Pora przesłać kopię repozytorium na githuba. Pierw jednak musimy odwiedzić stronę githuba i utworzyć tam repozytorium -- nie da rady inaczej stworzyć repo na githubie, zwłaszcza jeśli ma się włączone uwierzytelnianie dwuskładnikowe.

Jako, że wcześniej stworzyliśmy plik README.md i LICENCE, nie musimy ich tutaj definiować -- zostaną przesłane przy synchronizacji.

Po pomyślnym utworzeniu repozytorium, powinno zostać wyświetlone podsumowanie:

Jak widać, mamy tam między innymi linki potrzebne do synchronizacji -- zarówno po https jak i ssh. Dodatkowo jest też instrukcja jak stworzyć lokalne repo (to już zrobiliśmy) i jak dokonać synchronizacji.

Wracamy zatem do terminala i dodajemy zdalne ścieżki:

morfik:~/repozytoria/practice-makes-perfect$ git remote add origin git@github.com:morfikov/practice-makes-perfect.git

morfik:~/repozytoria/practice-makes-perfect$ git remote -v origin git@github.com:morfikov/practice-makes-perfect.git (fetch) origin git@github.com:morfikov/practice-makes-perfect.git (push)

Jeśli w tej chwili spróbowalibyśmy dać push , dostaniemy poniższy komunikat:

morfik:~/repozytoria/practice-makes-perfect$ git push fatal: The current branch master has no upstream branch. To push the current branch and set the remote as upstream, use

git push --set-upstream origin master

Zgodnie z instrukcją wydajemy poniższe polecenie:

morfik:~/repozytoria/practice-makes-perfect$ git push --set-upstream origin master Counting objects: 4, done. Delta compression using up to 2 threads. Compressing objects: 100% (4/4), done. Writing objects: 100% (4/4), 7.57 KiB | 0 bytes/s, done. Total 4 (delta 0), reused 0 (delta 0) To git@github.com:morfikov/practice-makes-perfect.git * [new branch] master -> master Branch master set up to track remote branch master from origin.

W tej chwili jeśli odwiedzimy repozytorium na githubie powinniśmy ujrzeć już pliki:

  1. Cofanie zmian

Musimy także wiedzieć jak cofać/odrzucać zmiany wprowadzane do repozytorium, a te z kolei dzielimy z grubsza na dwie kategorie. Pierwsza z nich to zmiany przed dokonaniem commita, drugi zaś po dokonaniu.

Stwórzmy zatem nowy plik w repozytorium:

morfik:~/repozytoria/practice-makes-perfect$ touch test_file

morfik:~/repozytoria/practice-makes-perfect$ echo "some random text"> test_file

morfik:~/repozytoria/practice-makes-perfect$ git add .

morfik:~/repozytoria/practice-makes-perfect$ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage)

new file: test_file

Nie możemy teraz sobie od tak tego pliku usunąć, tj. przy pomocy rm lub wciskając delete na klawiaturze -- to jest traktowane jako kolejna zmiana:

morfik:~/repozytoria/practice-makes-perfect$ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage)

new file: test_file

Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory)

deleted: test_file

Zgodnie z wypisanymi instrukcjami, by cofnąć zmiany, wpisujemy:

morfik:~/repozytoria/practice-makes-perfect$ git reset --soft HEAD test_file

Jeśli teraz sprawdzimy status gita, zobaczymy, że plik aktualnie nie jest śledzony:

morfik:~/repozytoria/practice-makes-perfect$ git status On branch master Your branch is up-to-date with 'origin/master'. Untracked files: (use "git add <file>..." to include in what will be committed)

test_file

nothing added to commit but untracked files present (use "git add" to track)

Teraz już można spokojnie usunąć plik z gita:

morfik:~/repozytoria/practice-makes-perfect$ rm test_file

morfik:~/repozytoria/practice-makes-perfect$ git status On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean

A jak sprawa wygląda w przypadku gdy dokonamy commita? Stwórzmy zatem jeszcze jeden plik testowy:

morfik:~/repozytoria/practice-makes-perfect$ touch test_file

morfik:~/repozytoria/practice-makes-perfect$ echo "some random text"> test_file

morfik:~/repozytoria/practice-makes-perfect$ git add .

morfik:~/repozytoria/practice-makes-perfect$ git commit -S -a -m "mistake"

You need a passphrase to unlock the secret key for user: "Mikhail Morfikov <morfik@nsa.com>" 4096-bit RSA key, ID 0x72F3A416B820057A, created 2013-11-13

[master e175de8] mistake 1 file changed, 1 insertion(+) create mode 100644 test_file

Możemy pójść nawet o krok dalej i przesłać zmiany na githuba:

morfik:~/repozytoria/practice-makes-perfect$ git push Counting objects: 3, done. Delta compression using up to 2 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 964 bytes | 0 bytes/s, done. Total 3 (delta 0), reused 0 (delta 0) To git@github.com:morfikov/practice-makes-perfect.git 4de0d7f..e175de8 master -> master

Sprawdzając log możemy dostrzec nowy commit:

morfik:~/repozytoria/practice-makes-perfect$ git log commit e175de8b05df16c5f2b7d2c2c23a932a1c9efeaa (HEAD, refs/remotes/origin/master, refs/heads/master) Author: Mikhail Morfikov <morfik@nsa.com> Date: 2015-02-17 16:59:49 +0100

mistake

commit 4de0d7f07def79578ed908669c9bc0da4383a3b7 Author: Mikhail Morfikov <morfik@nsa.com> Date: 2015-02-17 12:21:27 +0100

Repository setup

Spróbujmy się tego jakoś pozbyć. Najpierw musimy ustalić gdzie jest HEAD. Zwykle będzie na ostatnim commicie ale zakładając, że nie wiemy gdzie dokładnie jest HEAD -- sprawdzamy:

morfik:~/repozytoria/practice-makes-perfect$ cat .git/HEAD ref: refs/heads/master

morfik:~/repozytoria/practice-makes-perfect$ cat .git/refs/heads/master e175de8b05df16c5f2b7d2c2c23a932a1c9efeaa

morfik:~/repozytoria/practice-makes-perfect$ git show e175de8b05df16c5f2b7d2c2c23a932a1c9efeaa commit e175de8b05df16c5f2b7d2c2c23a932a1c9efeaa (HEAD, refs/remotes/origin/master, refs/heads/master) Author: Mikhail Morfikov <morfik@nsa.com> Date: 2015-02-17 16:59:49 +0100

mistake

diff --git a/test_file b/test_file new file mode 100644 index 0000000..4ab08b3 --- /dev/null +++ b/test_file @@ -0,0 +1 @@ +some random text

Czyli tak jak podejrzewaliśmy, jest na ostatnim. Jeśli chcemy cofnąć zmiany tylko z tego ostatniego commita, to musimy zmienić położenie HEAD na przedostatni commit:

morfik:~/repozytoria/practice-makes-perfect$ git log commit e175de8b05df16c5f2b7d2c2c23a932a1c9efeaa (HEAD, refs/remotes/origin/master, refs/heads/master) Author: Mikhail Morfikov <morfik@nsa.com> Date: 2015-02-17 16:59:49 +0100

mistake

commit 4de0d7f07def79578ed908669c9bc0da4383a3b7 Author: Mikhail Morfikov <morfik@nsa.com> Date: 2015-02-17 12:21:27 +0100

Repository setup

morfik:~/repozytoria/practice-makes-perfect$ git reset --soft HEAD~1

morfik:~/repozytoria/practice-makes-perfect$ git log commit 4de0d7f07def79578ed908669c9bc0da4383a3b7 (HEAD, refs/heads/master) Author: Mikhail Morfikov <morfik@nsa.com> Date: 2015-02-17 12:21:27 +0100

Repository setup

Jeśli zmian by było więcej i nie chciałoby nam się liczyć ile commitów trzeba wrócić aby doprowadzić repozytorium do stanu używalności, możemy skorzystać z hashów i zresetować repo w oparciu o nie, przykładowo:

morfik:~/repozytoria/practice-makes-perfect$ git log --format=oneline e175de8b05df16c5f2b7d2c2c23a932a1c9efeaa (HEAD, refs/remotes/origin/master, refs/heads/master) mistake 4de0d7f07def79578ed908669c9bc0da4383a3b7 Repository setup

morfik:~/repozytoria/practice-makes-perfect$ git reset --soft 4de0d7f07def79578ed908669c9bc0da4383a3b7

morfik:~/repozytoria/practice-makes-perfect$ git log --format=oneline 4de0d7f07def79578ed908669c9bc0da4383a3b7 (HEAD, refs/heads/master) Repository setup

Zatem lokalnie cofnęliśmy zmiany ostatniego commita:

morfik:~/repozytoria/practice-makes-perfect$ git status On branch master Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded. (use "git pull" to update your local branch) Changes to be committed: (use "git reset HEAD <file>..." to unstage)

new file: test_file

Jak widzimy wyżej, git uważa, że nasze lokalne repozytorium jest ździebko nieaktualne i według niego musimy zrobić git pull by dokonać aktualizacji. Problem w tym, że właśnie chcemy czegoś odwrotnego, czyli cofnąć zmiany wprowadzone z zdalnym repo githuba.

Co się stanie jeśli damy push w tym momencie? Sprawdźmy:

morfik:~/repozytoria/practice-makes-perfect$ git push To git@github.com:morfikov/practice-makes-perfect.git ! [rejected] master -> master (non-fast-forward) error: failed to push some refs to 'git@github.com:morfikov/practice-makes-perfect.git' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Integrate the remote changes (e.g. hint: 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Można się było tego spodziewać -- git odrzucił proponowane zmiany, bo nasze repo jest "nieaktualne". Musimy skorzystać z opcji -f (force):

morfik:~/repozytoria/practice-makes-perfect$ git push -f Total 0 (delta 0), reused 0 (delta 0) To git@github.com:morfikov/practice-makes-perfect.git + e175de8...4de0d7f master -> master (forced update)

  1. Przywrócenie stanu

Jest tylko jeden problem -- to powyższe działanie wymazuje kompletnie ślad na temat usunięcia zmian, co nie zawsze jest pożądane. Musimy jeszcze wymyśleć jak zapisać w logu taką informację.

Tworzymy zatem kolejny plik testowy, robimy commita i przesyłamy zmiany do zdalnego gita:

morfik:~/repozytoria/practice-makes-perfect$ touch test_file

morfik:~/repozytoria/practice-makes-perfect$ echo "some random text"> test_file

morfik:~/repozytoria/practice-makes-perfect$ git add .

morfik:~/repozytoria/practice-makes-perfect$ git commit -S -a -m "mistake" You need a passphrase to unlock the secret key for user: "Mikhail Morfikov <morfik@nsa.com>" 4096-bit RSA key, ID 0x72F3A416B820057A, created 2013-11-13

[master 49f8b65] mistake 1 file changed, 1 insertion(+) create mode 100644 test_file

morfik:~/repozytoria/practice-makes-perfect$ git push Counting objects: 3, done. Delta compression using up to 2 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 964 bytes | 0 bytes/s, done. Total 3 (delta 0), reused 0 (delta 0) To git@github.com:morfikov/practice-makes-perfect.git 4de0d7f..49f8b65 master -> master

morfik:~/repozytoria/practice-makes-perfect$ git log --format=oneline 49f8b65ed0d2ae0c7f17fd0003af832f61c7885a (HEAD, refs/remotes/origin/master, refs/heads/master) mistake 4de0d7f07def79578ed908669c9bc0da4383a3b7 Repository setup

By cofnąć zmiany i zachować informacje o tej o tej czynności, wydajemy poniższe polecenie:

morfik:~/repozytoria/practice-makes-perfect$ git revert 49f8b65ed0d2ae0c7f17fd0003af832f61c7885a [master 172d0fd] Revert "mistake" 1 file changed, 1 deletion(-) delete mode 100644 test_file

Sprawdźmy zatem log:

morfik:~/repozytoria/practice-makes-perfect$ git log --format=oneline 172d0fd7634ff0dd1140ca50f0f37a9211223251 (HEAD, refs/heads/master) Revert "mistake" 49f8b65ed0d2ae0c7f17fd0003af832f61c7885a (refs/remotes/origin/master) mistake 4de0d7f07def79578ed908669c9bc0da4383a3b7 Repository setup

Został utworzony nowy commit, który cofnął zmiany tego wskazanego przy pomocy hasha.

Teraz tylko wystarczy zsynchronizować zdalne repo:

morfik:~/repozytoria/practice-makes-perfect$ git push Counting objects: 2, done. Delta compression using up to 2 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (2/2), 246 bytes | 0 bytes/s, done. Total 2 (delta 1), reused 0 (delta 0) To git@github.com:morfikov/practice-makes-perfect.git 49f8b65..172d0fd master -> master

Sprawdźmy co zarejestrował github:

  1. Odpowiednie narzędzia

W pliku konfiguracyjnym zdefiniowaliśmy trzy opcje, które pomogą nam w pracach z gitem -- mowa o zewnętrznych narzędziach: merge.tool meld , diff.tool meld oraz core.editor vim . To z jakich narzędzi możemy korzystać w przypadku merge.tool i diff.tool można ustalić przez:

morfik:~/repozytoria/practice-makes-perfect$ git difftool --tool-help 'git difftool --tool=<tool>' may be set to one of the following: araxis meld vimdiff vimdiff2 vimdiff3

The following tools are valid, but not currently available: bc3 codecompare deltawalker diffmerge diffuse ecmerge emerge gvimdiff gvimdiff2 gvimdiff3 kdiff3 kompare opendiff p4merge tkdiff xxdiff

Some of the tools listed above only work in a windowed environment. If run in a terminal-only session, they will fail.

Jeśli chodzi o edytor tekstu, czy w ogóle o tekstowe narzędzia, to w ich przypadku, będziemy mieli do dyspozycji kolorowanie wyjścia.

Tak wygląda vim podczas robienia commita (git commit):

A tu przykład diffa (git diff):

Choć ja tam wolę graficznego melda i niezbyt przepadam za tekstowymi diffami (git difftool):

Jest jeszcze git merge i git mergetool, odpowiednio tekstowy i GUI ale póki co jeszcze nie było dane mi z nich skorzystać, także nic na temat tej funkcjonalności nie napiszę, może kiedyś.

No i to w sumie by było na tyle -- pozostaje nam tworzyć nowe pliki, aktualizować/usuwać stare, robić commity i pushować wszystko na githuba. Więcej informacji zawsze można znaleźć w helpie githuba , lokalnie w manach lub też na https://www.kernel.org/pub/software/scm/git/docs/ .


Tworzenie paczek deb — poradnik młodego maintainera

$
0
0
  1. Potrzebne pakiety
  2. Konfiguracja narzędzi

    2.1. dh-make
    2.2. gnupg
    2.3. devscripts
    2.4. lintian
    2.5. apt-file
    2.6. pbuilder
    2.7. ccache
    2.8. sudo
  3. Przygotowanie środowiska chroot

  4. Źródła i informacje o nich
  5. Katalog debian/

    5.1. Tworzenie szkieletu
    5.2. debian/control
    5.3. debian/rules
    5.4. debian/changelog i debian/upstream.changelog
    
            5.4.1. debian/NEWS
    
    5.5. debian/copyright
    5.6. debian/watch i debian/upstream/signing-key.asc
    
            5.6.1. Podpisy cyfrowe źródeł
    
    5.7. debian/manpage.* i debian/*.manpages (dh_installman)
    
            5.7.1. Automatyczne generowanie manuali
    
    5.8. debian/*.docs (dh_installdocs)
    5.9. Pliki demonów (dh_installinit)
    
            5.9.1. debian/*.init
            5.9.2. debian/*default
            5.9.3. debian/*service (dh_systemd_enable, dh_systemd_start)
            5.9.4. debian/*tmpfile
    
    5.10. debian/*.symbols
    5.11. debian/*.dirs (dh_installdirs)
    5.12. debian/*.install (dh_install)
    5.13. debian/compat
    5.14. debian/*.links (dh_link)
    5.15. debian/*.lintian-overrides i debian/source/lintian-overrides
    5.16. source/format
    5.17. source/local-options i source/options
    5.18. debian/patches/ i debian/patches/series
    
            5.18.1. Nagłówek łaty
    
    5.19. debian/*.examples (dh_installexamples)
    5.20. debian/*.templates
    5.21. debian/conffiles (dh_installdeb)
    5.22. debian/*.cron.* (dh_installcron)
    5.23. debian/*.logrotate (dh_installlogrotate)
    5.24. debian/*.postinst, debian/*.postrm, debian/*.preinst, debian/*.prerm
    5.25. *.desktop
    
  6. Hardening pakietów

  7. Budowanie źródeł
  8. Budowanie pakietu

    8.1. Manualne budowanie pakietów
    8.2. Instalowanie zbudowanego pakietu
    
  9. Makulatura

Wieki temu opisywałem jak aktualizować debianowe paczki i to była w miarę prosta robota, bo nie wymagała zbytnio wiedzy na temat całego tego skomplikowanego procesu budowania pakietów. Ten poradnik zaś ma na celu zebranie wszystkich istotniejszych informacji związanych z obsługą rozmaitych narzędzi, takich jak dh_make, dpkg-buildpackage, pbuilder, quilt czy lintian, tak by tworzyć pakiety w prosty sposób i przy tym równając do najwyższych standardów debiana.

Przed napisaniem tego artykułu, moje pojęcie o budowaniu pakietów było raczej przeciętnie znikome -- wszystko co wiedziałem zawarłem w wyżej podlinkowanym wpisie i nie było tego za wiele. Od tamtego czasu sporo się zmieniło, a przez ostatnich parę tygodni praktycznie cały wolny czas przeznaczałem na naukę budowania paczek od podstaw. W sumie udało mi się ich zbudować 13 (+8 aktualizacji) i nie jest to mała liczba biorąc pod uwagę fakt braku obeznania w debianowych narzędziach służących budowie pakietów. Poza tym, z każdą kolejną paczką dochodziły mi nowe rzeczy, a to generowało problemy, które trzeba było w jakiś sposób rozwiązać -- jest bardzo małe prawdopodobieństwo, że znajdą się dwie paczki w debianie, które da radę zbudować w ten sam sposób, no może za wyjątkiem skryptowych projektów.

Sporo rzeczy z tego mojego poprzedniego poradnika zostanie tutaj zaimportowanych, z tym, że opisy poszczególnych opcji zostaną rozbudowane, tak by było wiadomo co od czego jest i do czego służy. Dodatkowo, zostanie wprowadzony cały szereg innych rzeczy, o których nie pisałem wcześniej, a to z tego powodu, że albo były zbyt skomplikowane by je ogarnąć za pierwszym podejściem, albo też zwyczajnie nie miałem o niektórych rzeczach bladego pojęcia, co po części może tłumaczyć te początkowe trudności.

  1. Potrzebne pakiety

By móc zacząć budować pakiety z prawdziwego zdarzenia niczym debianowy maintainer, musimy doinstalować szereg pakietów. Poniżej znajduje się krótka lista:

  • packaging-dev -- meta pakiet, który zainstaluje min:

     - build-essential -- bez tego nie ma nawet co podchodzić do budowania pakietów.
     - debhelper -- szereg programów zajmujących się obrabianiem pliku debian/rules .
     - dh-make -- debianizuje źródła (tworzy katalog debian/).
     - devscripts -- ten pakiet zawiera szereg skryptów ułatwiających zarządzanie plikami w katalogu debian/ , więcej info o tym jakie skrypty ten pakiet zawiera (oraz ich zależności) można odczytać z opisu samego pakietu, np. w aptitude.
     - lintian -- weryfikuje poprawność zbudowanych pakietów.
     - pbuilder -- automatyzuje cały proces budowania.
     - quilt -- tworzy łaty (i zarządza nimi) w oparciu o zmiany dokonywane na źródłach.
    
  • gnupg -- obsługa kluczy gpg, wymagane do podpisywania plików .dsc i .changes .

  • desktop-file-utils -- weryfikuje składnię plików .desktop .
  • ccache -- przyśpiesza znacznie rekompilację pakietów.
  • dh-* -- różne moduły dla debhelpera, potrzebne podczas budowania pewnych pakietów, np. te posiadające pliki .service dla systemd wymagać będą dh-systemd , etc.
  • gmanedit -- ułatwia tworzenie manuali.
  • help2man -- generuje manualne dla plików wykonywalnych w oparciu o parametr --help .
  • piuparts -- testuje instalację, usuwanie i aktualizację zbudowanych pakietów.
  • apt-file -- przeszukuje pakiety w oparciu o wzorzec nazwy pliku.
  • patchutils, wdiff -- dodatkowe narzędzia do pracy z łatami.
  • blhc -- testuje log z budowania pakietu pod kątem braku określonych flag.
  • hardening-includes -- zawiera narzędzie hardening-check pomagające ustalić poziom bezpieczeństwa plików wykonywalnych.
  • python-minimal -- zawiera narzędzie pyversions pomagające ustalić wersję pythona.
  • binutils, strace -- binutils zawiera narzędzie dpkg-depcheck , które przy pomocy strace może pomóc w ustalaniu zależności.
  • fakeroot -- symuluje uprawnienia super użytkownika.
  • sudo -- przekazuje część uprawnień roota zwykłemu użytkownikowi.

Jak widać jest tego dość sporo, no i oczywiście będzie tego więcej gdy każdy z powyższych pakietów dociągnie swoje zależności. Poza tym powyższym, dojdą nam jeszcze pewnie inne pakiety w zależności od tego co tak naprawdę będziemy budować i w jaki sposób ale o tym za moment.

Dla ułatwienia, poniżej jest linijka instalująca wszystkie powyższe narzędzia:

aptitude install packaging-dev gnupg desktop-file-utils ccache \

gmanedit help2man piuparts apt-file patchutils wdiff blhc hardening-includes \ python-minimal binutils strace fakeroot

Powyższe pakiety są (za wyjątkiem pewnych dodatków) jedynymi pakietami, które będziemy instalować w swoim systemie głównym. Wszelkie zależności budowanych pakietów będą już pakowane do środowiska chroot, które zostanie zbudowane przez pbuilder. Takie rozwiązanie pomoże nam utrzymać porządek w systemie.

Upychanie plików w paczkach ma na celu jedynie ich organizację i niczym zbytnio nie różni się od zwykłego przekopiowania ich do odpowiednich katalogów (czy zainstalowania via make install), no może poza faktem, że w przypadku paczki, wszystkie pliki są śledzone przez menadżer pakietów. Chodzi generalnie o to, że w przypadku gdyby się pojawiła nowsza wersja jakiegoś programu, lub zwyczajnie chcielibyśmy się pozbyć go z systemu, to może to być dość problematyczne. W przypadku jednego czy dwóch programów, które nie mają za wiele plików, usunięcie ich raczej nie powinno sprawić problemu, a co w przypadku bardziej rozbudowanych projektów? Część z nich potrafi się pomyślnie odinstalować sama jeśli skrypt makefile obsługuje taki ficzer ale nawet w takim przypadku trzeba, po pierwsze, trzymać źródła, a po drugie, musimy zainstalować wszystkie zależności potrzebne do zbudowania takiego pakietu w swoim systemie. W przypadku budowania paczek, te problemy nas nie dotyczą.

  1. Konfiguracja narzędzi

By cały proces bawienia się w maintainera przebiegał sprawnie, musimy pierw skonfigurować szereg narzędzi.

2.1. dh-make

Standardowo przy wywoływaniu polecenia dh_make podczas debianizowania źródeł, musimy podawać kilka dodatkowych parametrów, tak by określić kto buduje paczkę. Możemy sobie wyeksportować odpowiednie zmienny i uprościć nieco cały ten proces. W tym celu dodajemy poniższe linijki do pliku ~/.bashrc :

DEBEMAIL="morfik@nsa.com" DEBFULLNAME="Mikhail Morfikov" export DEBEMAIL DEBFULLNAME

2.2. gnupg

Jeśli chcemy robić coś większego z paczkami, np. przesyłać je do repozytorium debiana, będziemy potrzebować kluczy gpg by taką paczkę podpisać. Samo generowanie kluczy jak i bezpieczną konfigurację samego narzędzia gpg zdążyłem opisać i artykuł na ten temat można odnaleźć tutaj.

2.3. devscripts

Jak wspomniałem na początku, w tym pakiecie znajduje się szereg użytecznych skryptów, które będziemy wykorzystywać w swojej pracy. Jednym z częściej używanych narzędzi będzie debsign , który to będzie nam podpisywał pliki .changes i .dsc zawierające między innymi sumy kontrolne. I tu podobnie jak w przypadku narzędzia dh-make , możemy określić kila parametrów, tak by nie musieć ich wpisywać za każdym razem gdy chcemy podpisać jakąś paczkę.

Konfiguracja pakietu devscripts jest trzymana w /etc/devscripts.conf . Dobrze jest przejrzeć ten plik, choć objętościowo może nieco przytłoczyć. W każdym razie interesujące nas opcje to:

.. DEBSIGN_PROGRAM=gpg ... DEBSIGN_SIGNLIKE=gpg ... DEBSIGN_KEYID=B820057A ...

Możemy także zweryfikować wprowadzone dane wydając poniższe polecenie:

$ debsign --help ... Default settings modified by devscripts configuration files: DEBSIGN_PROGRAM=gpg DEBSIGN_KEYID=B820057A

2.4. lintian

Konfiguracja lintiana trzymana jest w pliku /etc/lintianrc i w dużej mierze odpowiada za to jaki rodzaj błędów będzie nam pokazywany i w jaki sposób. Poniżej mój plik:

/etc/lintianrc -- Lintian configuration file

#

Note, that Lintian has reasonable default values for all variables

specified below. Thus, you don't have to change this file unless you

want something special.

Also note, that this file uses a special syntax:

Empty lines are allowed, comments are introduced by a hash sign (#).

All other lines must have the format

VAR=text

or

VAR="text"

It is allowed to use ~' and$HOME' in the variables, but not other

shell/environment variables.

Enable info tags by default (--display info)

display-info = yes

Enable pedantic tags by default (--pedantic)

pedantic = yes

Enable experimental tags by default (--display-experimental)

display-experimental = no

Enable colored output for terminal output (--color)

color = always

Show overridden tags (--show-overrides)

show-overrides = yes

Ignore all overrides (--no-override)

override = no

Verbose output by default (--verbose)

verbose = no

info = no

Quiet by default (--quiet)

quiet = yes

Specify a laboratory--a directory where Lintian should store some info

about packages being checked.

LINTIAN_LAB="/media/Kabi/pbuilder/lintian"

Use a different directory for temporary files - useful if /tmp is a

tmpfs with "limited" capacity.

TMPDIR="/var/tmp"

Jeśli jesteśmy początkującymi amatorami, możemy się nieco pogubić w tym co będzie próbował nam powiedzieć lintian. Dobrze jest przestawić z początku opcję verbose oraz info na yes . Spowoduje to wyświetlenie dość obszernej informacji na temat każdego z błędu. Zawsze można wpisać kod błędu w google i pierwszy wynik odeśle nas na stronę lintiana i tam na pewno znajdziemy wyjaśnienie.

2.5. apt-file

To narzędzie nie jest bezpośrednio powiązane z budowaniem paczek, niemniej jednak bardzo się przydaje, bo bardzo często będziemy postawieni w sytuacji gdzie pakiet nie będzie mógł się poprawnie zbudować i to przez brak jakiegoś pliku i tu właśnie będzie można ten plik namierzyć za pomocą apt-file .

Jako takiej konfiguracji ten pakiet nie posiada. Trzeba jednak wygenerować sobie index i regularnie go aktualizować -- to w nim jest trzymana lista wszystkich plików we wszystkich pakietach w całej dystrybucji. By utworzyć/zaktualizować index, wydajemy poniższe polecenie:

root:~# apt-file update Downloading Index http://ftp.pl.debian.org/debian/dists/testing/main/Contents-amd64.diff/Index: % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 7933 100 7933 0 0 60044 0 --:--:-- --:--:-- --:--:-- 60098 Downloading 4 patches: % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 911 100 911 0 0 11869 0 --:--:-- --:--:-- --:--:-- 11986 100 29 100 29 0 0 1064 0 --:--:-- --:--:-- --:--:-- 0 100 102 100 102 0 0 3203 0 --:--:-- --:--:-- --:--:-- 3203 100 855 100 855 0 0 29407 0 --:--:-- --:--:-- --:--:-- 29407 Applying patches... ...

Taka mała uwaga -- to jest index systemowy i wszyscy użytkownicy z niego korzystają. Istnieje możliwość generowanie indexu jako zwykły użytkownik, na wypadek gdyby root się opieprzał i nie aktualizował tego systemowego regularnie.

Szukanie potrzebnego pakietu wygląda mniej więcej tak: podczas kompilacji zostaje wyrzucony jakiś błąd, np. coś podobnego do tego poniżej:

CMake Error at /usr/lib/x86_64-linux-gnu/cmake/Qt5LinguistTools/Qt5LinguistToolsConfig.cmake:22 (message): The package "Qt5LinguistTools" references the file

"/usr/lib/x86_64-linux-gnu/qt5/bin/lrelease"

but this file does not exist. Possible reasons include:

Szukamy zatem lrelease (można także wpisać całą ścieżkę):

morfik:~$ apt-file search lrelease facter: /usr/lib/ruby/vendor_ruby/facter/kernelrelease.rb lazarus-doc-1.2.4: /usr/share/doc/lazarus/1.2.4/lcl/graphics/trasterimage.internalreleasebitmaphandle.html lazarus-doc-1.2.4: /usr/share/doc/lazarus/1.2.4/lcl/graphics/trasterimage.internalreleasemaskhandle.html lazarus-doc-1.2.4: /usr/share/doc/lazarus/1.2.4/lcl/graphics/trasterimage.internalreleasepalette.html picard: /usr/lib/picard/picard/plugins/old/originalreleasedate.py qt4-linguist-tools: /usr/bin/lrelease-qt4 qt4-linguist-tools: /usr/lib/x86_64-linux-gnu/qt4/bin/lrelease qt4-linguist-tools: /usr/share/man/man1/lrelease-qt4.1.gz qt4-linguist-tools: /usr/share/qt4/bin/lrelease qtchooser: /usr/bin/lrelease qtcreator: /usr/share/qtcreator/externaltools/lrelease.xml qtcreator-data: /usr/share/qtcreator/externaltools/lrelease.xml qttools5-dev-tools: /usr/lib/x86_64-linux-gnu/qt5/bin/lrelease

W tym przypadku jest to qttools5-dev-tool i to jego trzeba dopisać do zależności budowania pakietu.

2.6. pbuilder

To będzie nasz główny automat, który zrobi praktycznie cała robotę za nas, przynajmniej jeśli chodzi o zbudowanie pakietu. Trzeba mu tylko skonfigurować szereg parametrów. Przykładowy plik konfiguracyjny dla pbuildera znajduje się w /usr/share/doc/pbuilder/examples/pbuilderrc -- trzeba go skopiować do katalogu /etc/ i odpowiednio przerobić. Można także zrobić sobie lokalną wersję tego pliku i umieścić go w katalogu domowym w ~/.pbuilderrc .

Poniżej znajduje się mój aktualny plik konfiguracyjny:

pbuilder defaults; edit /etc/pbuilderrc to override these and see

pbuilderrc.5 for documentation

BASETGZ=/media/Kabi/pbuilder/base.tgz EXTRAPACKAGES="apt-utils debconf-utils ccache eatmydata libfile-fcntllock-perl"

export DEBIAN_BUILDARCH=athlon

BUILDPLACE=/media/Kabi/pbuilder/build/ MIRRORSITE=http://ftp.de.debian.org/debian/

OTHERMIRROR="deb http://www.home.com/updates/ ./"

export http_proxy=http://your-proxy:8080/

USEPROC=yes USEDEVPTS=yes USENETWORK=no USERUNSHM=yes USEDEVFS=no BUILDRESULT=/media/Kabi/pbuilder/result/

specifying the distribution forces the distribution on "pbuilder update"

DISTRIBUTION=sid

specifying the architecture passes --arch= to debootstrap; the default is

to use the architecture of the host

ARCHITECTURE=dpkg --print-architecture

specifying the components of the distribution, for instance to enable all

components on Debian use "main contrib non-free" and on Ubuntu "main

restricted universe multiverse"

COMPONENTS="main"

specify the cache for APT

APTCACHE="/media/Kabi/pbuilder/pbuilder_apt_cache/" APTCACHEHARDLINK="no" REMOVEPACKAGES="no"

HOOKDIR="/usr/lib/pbuilder/hooks"

HOOKDIR="/media/Kabi/pbuilder/hooks"

NB: this var is private to pbuilder; ccache uses "CCACHE_DIR" instead

CCACHEDIR="/var/cache/pbuilder/ccache" ccache -M 20G

CCACHEDIR="/media/Kabi/pbuilder/ccache" export CCACHE_DIR="/media/Kabi/pbuilder/ccache"

make debconf not interact with user

export DEBIAN_FRONTEND="noninteractive"

for pbuilder debuild

BUILDSOURCEROOTCMD="fakeroot" PBUILDERROOTCMD="sudo -E"

use cowbuilder for pdebuild

PDEBUILD_PBUILDER="cowbuilder"

additional build results to copy out of the package build area

ADDITIONAL_BUILDRESULTS=(xunit.xml .coverage)

command to satisfy build-dependencies; the default is an internal shell

implementation which is relatively slow; there are two alternate

implementations, the "experimental" implementation,

"pbuilder-satisfydepends-experimental", which might be useful to pull

packages from experimental or from repositories with a low APT Pin Priority,

and the "aptitude" implementation, which will resolve build-dependencies and

build-conflicts with aptitude which helps dealing with complex cases but does

not support unsigned APT repositories

PBUILDERSATISFYDEPENDSCMD="/usr/lib/pbuilder/pbuilder-satisfydepends"

PBUILDERSATISFYDEPENDSCMD="/usr/lib/pbuilder/pbuilder-satisfydepends-experimental"

Arguments for $PBUILDERSATISFYDEPENDSCMD.

PBUILDERSATISFYDEPENDSOPT=()

You can optionally make pbuilder accept untrusted repositories by setting

this option to yes, but this may allow remote attackers to compromise the

system. Better set a valid key for the signed (local) repository with

$APTKEYRINGS (see below).

ALLOWUNTRUSTED=no

Option to pass to apt-get always.

export APTGETOPT=()

Option to pass to aptitude always.

export APTITUDEOPT=()

Command-line option passed on to dpkg-buildpackage.

DEBBUILDOPTS="-IXXX -iXXX"

DEBBUILDOPTS="-j1 -pgpg -kB820057A -sa"

APT configuration files directory

APTCONFDIR="/media/Kabi/pbuilder/pbuilder_apt_conf/"

the username and ID used by pbuilder, inside chroot. Needs fakeroot, really

BUILDUSERID=1234 BUILDUSERNAME=morfik

BINDMOUNTS is a space separated list of things to mount

inside the chroot.

BINDMOUNTS="${CCACHE_DIR}"

Set the debootstrap variant to 'buildd' type.

DEBOOTSTRAPOPTS=( '--variant=buildd' '--keyring' '/usr/share/keyrings/debian-archive-keyring.gpg' )

or unset it to make it not a buildd type.

unset DEBOOTSTRAPOPTS

Keyrings to use for package verification with apt, not used for debootstrap

(use DEBOOTSTRAPOPTS). By default the debian-archive-keyring package inside

the chroot is used.

APTKEYRINGS=()

Set the PATH I am going to use inside pbuilder: default is "/usr/sbin:/usr/bin:/sbin:/bin"

export PATH="/usr/sbin:/usr/bin:/sbin:/bin"

export PATH="/usr/lib/ccache:${PATH}"

SHELL variable is used inside pbuilder by commands like 'su'; and they need sane values

export SHELL=/bin/bash

The name of debootstrap command, you might want "cdebootstrap".

DEBOOTSTRAP="debootstrap"

default file extension for pkgname-logfile

PKGNAME_LOGFILE_EXTENTION="_$(dpkg --print-architecture).build"

default PKGNAME_LOGFILE

PKGNAME_LOGFILE=""

default AUTOCLEANAPTCACHE

AUTOCLEANAPTCACHE="no"

default COMPRESSPROG

COMPRESSPROG="gzip"

W EXTRAPACKAGES umieściłem kilka dodatkowych pakietów, które będą instalowane po wypakowaniu środowiska chroot, a to ze względu na szereg ostrzeżeń jakie wyrzucał mi pbuilder podczas budowania pakietów. Te pozycje tutaj nie są obowiązkowe i raczej nic się paczkom nie stanie z powodu ich braku.

2.7. ccache

W przypadku ccache nie musimy już zbytnio nic robić, bo wszystko zostało już określone w pliku konfiguracyjnym pbuildera -- konkretnie chodzi o te wpisy:

... EXTRAPACKAGES=...ccache... ...

NB: this var is private to pbuilder; ccache uses "CCACHE_DIR" instead

CCACHEDIR="/var/cache/pbuilder/ccache" ccache -M 20G

CCACHEDIR="/media/Kabi/pbuilder/ccache" export CCACHE_DIR="/media/Kabi/pbuilder/ccache" ...

Tylko jest jeden problem -- ten ccache zadziała jedynie przy wywoływaniu polecenia pbuilder --build . Jeśli z jakiegoś powodu nam paczka się nie zbuduje i będziemy chcieli sprawdzić co się schrzaniło i zostaniemy zrzuceni do środowiska wewnątrz chroot, to po tym jak poprawimy błąd i będziemy próbować budować pakiet via dpkg-buildpackage , nie będziemy mieli dostępu do ccache i pakiet się będzie budował tak jakbyśmy nie korzystali z ccache. Nie mam pojęcia czemu się tak dzieje, być może to bug, albo coś z powyższą konfiguracją, albo pbuilder tak po prostu już ma.

2.8. sudo

Dostęp do narzędzia pbuilder jest standardowo zarezerwowany jedynie dla użytkownika root. Nie jest to zbytnio wygodne i przydałoby się umożliwić korzystanie z niego zwykłemu użytkownikowi. W tym celu edytujemy konfigurację sudo wpisując w terminalu visudo i dopisujemy poniższe linijki:

Host_Alias HOSTY = localhost,morfikownia

morfik HOSTY = (root) NOPASSWD: /usr/sbin/pbuilder

Więcej informacji na temat samego sudo jak i pliku konfiguracyjnego można znaleźć tutaj.

  1. Przygotowanie środowiska chroot

Pbuilder musi na czymś operować, inaczej odmówi współpracy. Musimy mu stworzyć podstawowe środowisko pracy -- chodzi o zrobienia minimalnego i do tego spakowanego chroota, który będzie używany w każdym procesie budowania pakietów. Takie minimalistyczne środowisko ma na celu zapewnienie, że pakiet będzie się budował poprawnie (zależności) na 99% maszyn, pod warunkiem, że się zbuduje bez problemu w tym chroocie.

Musimy stworzyć także szereg katalogów, do których ścieżki podaliśmy w pliku konfiguracyjnym pbuildera. Dodatkowo musimy także dostosować konfigurację dla apt. Jeśli chodzi o same repozytoria zaś, to raczej poniżej sida nie ma co schodzić -- jeśli jakichś pakietów nie ma w repo testowym czy stabilny, to albo przez licencję, albo niespełnione zależności, które zwykle muszą być w najnowszych wersjach, a te są z reguły w sidzie i experimental.

Tworzymy zatem katalog bazowy:

$ mkdir /media/Kabi/pbuilder/

$ mkdir /media/Kabi/pbuilder/{hooks,build,result,pbuilder_apt_cache,ccache,pbuilder_apt_conf,lintian}

$ cp /etc/apt/sources.list /media/Kabi/pbuilder/pbuilder_apt_conf/

W pliku sources.list zostawiamy jedynie wpisy od sida:

SID

deb http://ftp.pl.debian.org/debian/ sid main non-free contrib

Pewnie zdarzy się nam taki przypadek, że pakiet, który chcemy zbudować, ma w zależnościach inny pakiet, który dopiero co zbudowaliśmy i jak z takiej sytuacji wybrnąć? Potrzebne nam będzie własne repozytorium. Niekoniecznie musimy jakieś tworzyć przy pomocy reprepro ale ja na dobrą sprawę nie umiem inaczej. xD W każdym razie, to jak stworzyć swoje własne repozytorium opisałem tutaj. Wpisy do takiego repozytorium dodajemy do konfiguracji apt dla pbuildera:

local

deb file:/media/Kabi/repozytorium/debian/ sid main contrib non-free

deb-src file:/media/Kabi/repozytorium/debian/ sid main contrib non-free

deb http://deb.morfikownia.lh/debian/ sid main contrib non-free deb-src http://deb.morfikownia.lh/debian/ sid main contrib non-free

Wszystkie zewnętrzne repozytoria będą wymagać publicznych kluczy gpg -- trzeba je również dostarczyć pbuilderowi. Kopiujemy zatem systemowy keyring apt:

$ cp /etc/apt/trusted.gpg /media/Kabu/pbuilder/pbuilder_apt_conf/

Tworzymy spakowane środowisko chroot. Po wydaniu poniższego polecenia, zostanie zainicjowany debootstrap, który pobierze minimalnego debiana (sid), który to zostanie wstępnie skonfigurowany i upchnięty w paczce .tgz :

morfik:~$ sudo pbuilder create W: /root/.pbuilderrc does not exist I: Distribution is sid. I: Current time: Thu Feb 19 12:36:23 CET 2015 I: pbuilder-time-stamp: 1424345783 I: Building the build environment I: running debootstrap /usr/sbin/debootstrap I: Retrieving Release I: Retrieving Release.gpg I: Checking Release signature I: Valid Release signature (key id A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553) I: Retrieving Packages I: Validating Packages ... I: creating base tarball [/media/Kabi/pbuilder/base.tgz] I: cleaning the build env I: removing directory /media/Kabi/pbuilder/build//46518 and its subdirectories

W ten sposób utworzona paczka będzie wypakowywana za każdym razem gdy będziemy budować jakiś pakiet przy pomocy sudo pbuilder --build . Niemniej jednak, całe wypakowane środowisko, niezależnie od powodzenia akcji budowania, zostanie na zakończenie usunięte. Jeśli będziemy budować wiele razy i to tylko jeden pakiet, można edytować tego spakowanego chroota i doinstalować tam szereg zależności, tak by podczas budowania nie były w kółko pobierane i instalowane. By edytować środowisko, wpisujemy poniższe polecenie:

$ sudo pbuilder --login --save-after-login

Każdy system, nawet ten minimalny chroot zrobiony przy pomocy debootstrapa, wymaga by go aktualizować w miarę regularnie, a konkretnie, przed budowaniem pakietu. By zaktualizować środowisko, wpisujemy:

$ sudo pbuilder --update

  1. Źródła i informacje o nich

Tam na necie jest wiele rozmaitych miejsc gdzie można znaleźć źródła pakietu, który chcemy zbudować. Zwykle będzie to strona projektu lub też i jakiś git, np. github. Niemniej jednak, w tych lokalizacjach bardzo rzadko spotkamy się ze źródłami, które pozwolą nam na zbudowanie pakietu tuż po ściągnięciu ich na dysk.

W sporej części przypadków, większość roboty jaką będziemy musieli odwalić, to zbieranie informacji na temat samego projektu -- to na jakiej jest licencji, jakie ma zależności, kto prowadzi dany projekt i tego typu podobne sprawy. Czasem możemy pójść nieco na skróty i skorzystać z czyjejś pracy, tak by nieco przyśpieszyć zbieranie tych informacji.

Jeśli strona projektu nie jest w najlepszym stanie i brakuje kluczowych dla nas informacji, możemy oczywiście wysłać maila do twórcy i poprosić go o stosowne info ale to zajmuje czas. Możemy także zajrzeć na debianowy git -- dostępny pod adresem http://anonscm.debian.org/ i tam spróbować odnaleźć interesujący nas projekt. Jeśli doszukamy się go, możemy być pewni, że część pracy przeprowadził już ktoś za nas.

Innym miejscem jest repozytorium AUR archlinuxa -- tam zawsze idzie coś wyszukać, tylko paczki nie są zbytnio kompatybilne z debianem i trzeba wiedzieć gdzie i czego szukać. Włazimy zatem na stronę https://aur.archlinux.org/ i szukamy interesującego nas pakietu -- załóżmy, że to będzie monitorix :

Jak widzimy pakiet został odnaleziony i mamy tam info o licencji i o zależnościach. Niemniej jednak, to nie wszystko co możemy wyciągnąć z AUR. Tam w prawym górnym rogu jest PKGBUILD . Jest to plik, na podstawie którego buduje się pakiet dla archlinuxa. Jak on nam może pomóc? Zajrzyjmy do niego:

Contributor: graysky <graysky AT archlinux dot us>

pkgname=monitorix pkgver=3.6.0 pkgrel=4 pkgdesc='A lightweight system monitoring tool that uses rrd databases.' arch=('any') url='http://www.monitorix.org' license=('GPLv2') depends=('perl' 'perl-cgi' 'perl-mailtools' 'perl-mime-lite' 'perl-libwww' 'perl-dbi' 'perl-xml-simple' 'perl-config-simple' 'perl-config-general' 'rrdtool' 'perl-http-server-simple') optdepends=( 'anything-sync-daemon: offload your databases to tmpfs to save i/o to your disk.' 'hddtemp: enable support for hdd temp monitoring.' 'lm_sensors: enable support for system temp monitoring.' 'nvidia: enable support for nVidia card temp and usage monitoring.' 'smartmontools: enable support for hdd bad sector monitoring.' 'terminus-font: if graphs do not contain characters, you may need this font package.') conflicts=$pkgname-git backup=(etc/$pkgname/$pkgname.conf etc/$pkgname.conf) install=readme.install source=("http://www.$pkgname.org/$pkgname-$pkgver.tar.gz""unfuck_Makefile.patch""unfuck_Makefile2.patch") sha256sums=('73097a65554871c66d6e1877ae432acd4a7e4cf35b413a77a15aeed3bb9dd90d' 'd1fe56d5b29a3f63a7a03b4f845aee68241e9dfb163d69af33a011f1483054fd' '10c6b420119fbafae9b5f5186a67c638dadf7aeae0d9e77ca32ba641cf2beced')

prepare() { cd "$pkgname-$pkgver"

# fix Makefile patch -Np1 -i "$srcdir/unfuck_Makefile.patch" patch -Np1 -i "$srcdir/unfuck_Makefile2.patch"

# use Arch default location for http servers and enable built-in httpd sed -i -e '/^base_dir/ s,var\/lib\/monitorix\/www,srv\/http\/monitorix,' \ -i -e '/^<httpd_builtin>/{$!N; s/y/n/}' $pkgname.conf }

package() { cd "$pkgname-$pkgver" make DESTDIR="$pkgdir" BASEDIR=/srv/http/monitorix \ WWWDIR=/srv/http/monitorix install-systemd-all

# Arch provides the license so do not duplicate it rm -f "$pkgdir/usr/share/doc/$pkgname/COPYING"

# remove unneed files rm -f "$pkgdir/usr/share/doc/$pkgname/README.OpenBSD" rm -f "$pkgdir/usr/share/doc/$pkgname/README.NetBSD" rm -f "$pkgdir/usr/share/doc/$pkgname/README.FreeBSD" }

Jak widać jest trochę więcej informacji.

W tym przypadku akurat strona projektu jest w miarę rozsądna i można się doszukać na niej wszystkich informacji. Czasem jednak nie wiadomo skąd nawet pobrać źródła pakietu, a jeśli się przyjrzymy, to odnajdziemy bezpośredni link do źródeł.

Dalej mamy info o dwóch łatach ale gdzie one są? Musimy się cofnąć na stronę AUR i tam mamy Download tarball i w niej są potrzebne patche, które możemy zaimportować do debiana w celu późniejszego nałożenia ich na źródła.

Dalej mamy informacje na temat dokonywania określonych operacji na plikach dostarczanych z pakietem, które również możemy wykorzystać przy tworzeniu paczki, tylko trzeba wziąć poprawkę na ścieżki.

  1. Katalog debian/

Katalog debian/ zawsze będziemy tworzyć po wypakowaniu źródeł i to w nim będziemy dokonywać większości zmian, dlatego też musimy poznać nieco jego strukturę. Poniżej postaram się opisać wszystkie pliki z tego katalogu, z którymi się spotkałem budując pakiety.

Generalnie rzecz biorąc, w oparciu o dane określone w tych plikach, narzędzie install będzie kopiować odpowiednie pliki/foldery i budować z tego drzewo katalogów, które następnie zostanie przeniesione do pakietu wynikowego. Dlatego też dobrze jest sobie przyswoić poszczególne parametry tego polecenia, bo to ułatwi ewentualne szukanie przyczyn problemów, np z błędnymi uprawnieniami plików.

5.1 Tworzenie szkieletu

Zakładając, że nie udało nam się znaleźć zdebianizowanych źródeł, musimy przejść przez proces ich zmiany. Na sam początek pobieramy źródła takie jak widzimy na stronie projektu i wypakowujemy je:

morfik:~$ mkdir debian_build

morfik:~$ cd debian_build/

morfik:~/debian_build$ wget http://www.monitorix.org/monitorix-3.6.0.tar.gz --2015-02-19 13:54:16-- http://www.monitorix.org/monitorix-3.6.0.tar.gz Resolving www.monitorix.org (www.monitorix.org)... 82.98.146.100 Connecting to www.monitorix.org (www.monitorix.org)|82.98.146.100|:80... connected. HTTP request sent, awaiting response... 200 OK Length: 235408 (230K) [application/x-gzip] Saving to: ‘monitorix-3.6.0.tar.gz’

monitorix-3.6.0.tar.gz 100%[===============>] 229.89K 433KB/s in 0.5s

2015-02-19 13:54:17 (433 KB/s) - ‘monitorix-3.6.0.tar.gz’ saved [235408/235408]

morfik:~/debian_build$ tar xpf monitorix-3.6.0.tar.gz

morfik:~/debian_build$ ls -al total 252K drwxr-xr-x 3 morfik morfik 4.0K 2015-02-19 13:56:05 ./ drwxr-xr-x 98 morfik morfik 12K 2015-02-19 13:53:42 ../ drwxr-xr-x 6 morfik morfik 4.0K 2014-08-20 10:14:55 monitorix-3.6.0/ -rw-r--r-- 1 morfik morfik 230K 2014-08-20 10:39:43 monitorix-3.6.0.tar.gz

Przechodzimy teraz do wypakowanego katalogu:

morfik:~/debian_build$ cd monitorix-3.6.0/

morfik:~/debian_build/monitorix-3.6.0$ ls -a ./ COPYING README.OpenBSD monitorix.cgi* ../ Changes README.md monitorix.conf docs/ Makefile README.nginx monitorixico.png lib/ README logo_bot.png man/ README.FreeBSD logo_top.png reports/ README.NetBSD monitorix*

Tworzymy katalog debian/ przy pomocy dh_make :

morfik:~/debian_build/monitorix-3.6.0$ dh_make -s -c gpl2 -f ../monitorix-3.6.0.tar.gz Maintainer name : Mikhail Morfikov Email-Address : morfik@nsa.com Date : Thu, 19 Feb 2015 14:00:01 +0100 Package Name : monitorix Version : 3.6.0 License : gpl2 Type of Package : Single Hit <enter> to confirm: Done. Please edit the files in the debian/ subdirectory now. You should also check that the monitorix Makefiles install into $DESTDIR and not in / .

Nazwa maintainera oraz adres email został automatycznie uzupełnione w oparciu o zmienne DEBEMAIL oraz DEBFULLNAME , które podaliśmy wcześniej w pliku ~/.bashrc . W zależności od tego jaki pakiet będziemy budować, możemy skorzystać ze wzorców plików -- inaczej wyglądają one w przypadku bibliotek, a inaczej w przypadku modułów kernela, etc. W tym przypadku budujemy pojedynczą binarkę i dlatego skorzystaliśmy z opcji -s. Opcja -c gpl2 odpowiada za uzupełnienie pliku copyright (o nim później) o odpowiedni tekst licencji. Ostatnia opcja -f odpowiada za podanie pliku z upstreamowymi źródłami. To w oparciu o ten plik będą robione ewentualne patche (o tym też później), bo źródeł upstreamowych jako takich nie wolno nam zmieniać i nie mylić tego z plikami, które mamy w wypakowanym katalogu.

Powinniśmy mieć już dostępny katalog debian/ . Z kolei w katalogu nadrzędnym powinna pojawić się dodatkowa paczka -- monitorix_3.6.0.orig.tar.gz :

morfik:~/debian_build/monitorix-3.6.0$ ls -al ../ total 484K drwxr-xr-x 3 morfik morfik 4.0K 2015-02-19 14:00:05 ./ drwxr-xr-x 98 morfik morfik 12K 2015-02-19 13:53:42 ../ drwxr-xr-x 7 morfik morfik 4.0K 2015-02-19 14:00:05 monitorix-3.6.0/ -rw-r--r-- 1 morfik morfik 230K 2014-08-20 10:39:43 monitorix-3.6.0.tar.gz -rw-r--r-- 1 morfik morfik 230K 2014-08-20 10:39:43 monitorix_3.6.0.orig.tar.gz

Nazwa nowego pliku ze źródłami ma swój zdefiniowany format, który wygląda tak: pakiet_wersja.orig.tar.gz.

Przechodzimy do katalogu debian/:

morfik:~/debian_build/monitorix-3.6.0$ cd debian/

morfik:~/debian_build/monitorix-3.6.0/debian$ ls -a ./ compat manpage.sgml.ex postinst.ex ../ control manpage.xml.ex postrm.ex source/ copyright menu.ex preinst.ex README.Debian docs monitorix.cron.d.ex prerm.ex README.source init.d.ex monitorix.default.ex rules* changelog manpage.1.ex monitorix.doc-base.EX watch.ex

Jak widać, został utworzonych szereg plików ale nie wszystkie z nich zawsze będą nam potrzebne. Dobrze jest też wiedzieć, że w przypadku gdy skasujemy, naszym zdaniem, niepotrzebne pliki, możemy nakazać dh_make aby przywrócił ich szablony. By odzyskać skasowane pliki, będziemy musieli wydać poniższe polecenie:

morfik:~/debian_build/monitorix-3.6.0$ dh_make --addmissing ... File source/format exists, skipping. File changelog exists, skipping. File compat exists, skipping. ...

Nowe pliki powinny być już dostępne w katalogu debian/ i jak widać wyżej, system nie ruszył już tych plików, które istniały -- jedynie dodał te brakujące.

5.2. debian/control

Jednym z ważniejszych plików jest debian/control . To w nim są definiowane min. zależności potrzebne do zbudowania/instalacji pakietu i to w oparciu o te zależności właśnie menadżery pakietów, takie jak apt-get czy aptitude, będą wiedzieć jak zainstalować konkretny pakiet. W tym przypadku, ten plik wygląda następująco:

Source: monitorix Section: net Priority: optional Maintainer: Mikhail Morfikov <morfik@nsa.com> Build-Depends: debhelper (>= 9), dh-systemd (>= 1.5) Standards-Version: 3.9.6 Homepage: http://www.monitorix.org/ Vcs-Git: git://github.com/mikaku/Monitorix.git Vcs-Browser: https://github.com/mikaku/Monitorix

Package: monitorix Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, rrdtool, perl, librrds-perl, libwww-perl, libdbi-perl, libxml-simple-perl, libhttp-server-simple-perl, libconfig-general-perl, libio-socket-ssl-perl, libmailtools-perl, libmime-lite-perl, libcgi-pm-perl Suggests: hddtemp, lm-sensors, smartmontools Description: Web system monitoring tool Monitorix is a free, open source, lightweight system monitoring tool designed to monitor as many services and system resources as possible. It has been created to be used under production UNIX/Linux servers, but due to its simplicity and small size you may also use it to monitor embedded devices as well.

Trochę tego jest -- jedziemy zatem od góry. Linijka Source określa nazwę źródła, czyli to co zostanie pobrane po wydaniu polecenia apt-get source paczka , z tym, że bez wersji i sufixu .tar.gz .

Dalej mamy Section i odpowiada to za przypisanie pakietu do konkretnej sekcji, a tych jest dość sporo. Wszystkie można znaleźć tutaj . Tylko taka mała uwaga, zwykle tam w linku spotkamy się z nazwami typu "Administration Utilities" lub "Network" i to nie są ta nazwy, które musimy wpisać do pliku debian/control . Jeśli klikniemy w daną sekcję, na samej górze dopiero dostaniemy prawidłową nazwę, przykładowo: Software Packages in "sid", Subsection net -- i to właśnie to musimy wpisać.

Kolejna linijka to Priority i określa ona jak ważna jest paczka z punktu widzenia prawidłowego działania systemu i z reguły tutaj będziemy wpisywać optional albo extra . Różnica między tymi dwoma polega na tym, że ten pierwszy nie koliduje z żadnymi pakietami, które mają ustawiony priorytet required , important lub standard , czyli pakiety wchodzące w skład bardzo podstawowej instalacji systemu.

Następnie mamy Maintainer , czyli osobę, która budowała i będzie się opiekować danym pakietem.

Kolejna pozycja to Build-Depends i jest to nic innego jak zależności, które muszą zostać spełnione aby podjąć próbę budowania pakietu. Jeśli jakaś zależność nie zostanie spełniona, pbuilder nawet nie podejmie się próby stworzenia takiego pakietu. Nie zawsze też pakiet zbuduje się nam poprawnie w przypadku gdy wszystkie zależności zostaną zaspokojone. Wtedy będzie trzeba poszukać tych brakujących pakietów, których zapomnieliśmy dodać lub zwyczajnie je przeoczyliśmy i dlatego wymagane jest budowanie paczek w minimalnym środowisku chroot. I taka mała uwaga odnośnie "bardzo podstawowych" zależności, np. gcc . Jeśli zdefiniujemy gcc w tutaj zależnościach, system upomni się o sprecyzowanie konkretnej wersji takiego pakietu. Jeśli korzystamy z dodatkowych modułów dla debhelpera, tak jak w tym przypadku wykorzystywany jest dh-systemd, trzeba ten pakiet również uwzględnić w zależnościach.

Zależności będą podane na stronie projektu ale czasem (albo i często) nazwy będą bardzo nieprecyzyjne, np. qt5 i ciężko będzie nam ustalić, o który pakiet tak naprawdę może chodzić. Zwykle też do źródeł będzie dołączony plik README lub INSTALL z instrukcjami na temat budowy programu. Przykład:

REQUIREMENTS

Monitorix requires some others packages to be installed that your GNU/Linux distribution may or may not have:

  • Perl
  • Perl-CGI
  • Perl-libwww
  • Perl-MailTools
  • Perl-MIME-Lite
  • Perl-DBI
  • Perl-XML-Simple
  • Perl-Config-General
  • Perl-HTTP-Server-Simple
  • perl-IO-Socket-SSL
  • RRDtool and its Perl bindings (perl-rrdtool or rrdtool-perl)
  • (Optional) a CGI capable Web server (Apache, Nginx, lighttpd, etc.)

Z tym, że trzeba rozróżnić zależności potrzebne do budowania pakietu i zależności potrzebne do poprawnego działania programu.

Jeśli dany pakiet posiada plik configure , możemy poszukać na podstawie tego pliku potrzebnych zależności przy pomocy dpkg-depcheck . Z tym, że trzeba mieć na uwadze, że ten dpkg-depcheck wyrzuca zależności potrzebne do wykonania się polecenia i niekoniecznie wszystkie pakiety, które nam zwróci musimy wpisać jako zależności w budowanej paczce. Poza tym informacje o zależnościach są czasem niezbyt precyzyjne, np. nie wiemy nic wersji danej zależności. Poniżej przykład:

$ dpkg-depcheck -d ./configure checking build system type... x86_64-unknown-linux-gnu checking host system type... x86_64-unknown-linux-gnu

...

Packages needed: libc6-i386 cpio perl libmagic1:amd64 libreadline6:amd64 libltdl7:amd64 mime-support libffi6:amd64 libfakeroot:amd64 make-guile file libssl-dev:amd64 pkg-config libgc1c2:amd64 libglib2.0-0:amd64 libsodium13:amd64 libunistring0:amd64 libsigsegv2:amd64 zlib1g-dev:amd64 gawk guile-2.0-libs:amd64

Zwykle będą nas interesować pakiety zaczynające się od lib , do których to będzie trzeba dodać końcówkę -dev i taki pakiet dać w zależnociach. Trzeba także pamiętać, że część z powyższych zależności może być pociągnięta przez jakiś metapakiet np. build-essential i możemy sobie darować ich wpisywanie do pliku debian/control . Na dobrą sprawę, powyższe wyjście dobrze jest traktować orientacyjne, a nie dosłownie.

Innym sposobem na ustalenie zależności może być posłużenie się objdump , z tym, że ten skanuje pliki wykonywalne i by móc z niego skorzystać, musimy mieć uprzednio skompilowany program -- przydatne to za bardzo nie jest. xD W każdym razie, jeśli już mamy w systemie jakiś pakiet, to zależności ustalamy tak:

$ objdump -p /usr/sbin/dnscrypt-proxy | grep NEEDED NEEDED libsodium.so.13 NEEDED libdl.so.2 NEEDED libm.so.6 NEEDED libc.so.6

Podobnie jak w przypadku dpkg-depcheck, obcinamy .so.* i dołączamy sufix -dev .

Następnie mamy Standards-Version i jest to wersja standardu polityki debiana jaka ma być spełniona aby zbudować tę paczkę i zawsze trzeba ustawiać tutaj najnowszą wersję, obecnie jest to 3.9.6 . Jeśli w późniejszym czasie wersja ulegnie zmianie, pakiet trzeba będzie przebudować i prawdopodobnie będą potrzebne też jakieś mniejsze zmiany by spełnić wymogi nowszej wersji standardu.

Opcje Homepage , Vcs-Git oraz Vcs-Browser określają położenie projektu w sieci i czy korzysta z jakiegoś systemu kontroli wersji (VCS). Jeśli projekt nie korzysta z VCS, możemy usunąć te linijki z pliku.

Część opisową źródeł mamy z głowy. Druga część pliku dotyczy tego co zostanie zbudowane, czyli jaki pakiet opuści plac budowy.

Linijka z Package określa nazwę pakietu, domyślnie taka sama jak nazwa źródła.

Kolejna linijka to Architecture i tu możemy wpisać all albo any . Różnica między tymi dwoma tkwi w rodzaju budowanych plików. Jeśli budujemy skrypty, wtedy tak naprawdę nie budujemy ich tylko kopiujemy pliki do paczki, a taki skrypt może być odpalony na każdej architekturze i w takim przypadku wybieramy all . Z kolei pliki wymagające kompilacji trzeba budować dla każdej architektury osobno i tutaj dajemy zwykle any , chyba, że pakiet ma wyraźnie zaznaczone na stronie projektu, że przeznaczony jest tylko dla np. amd64 czy i386 . Wtedy podajemy wedle opisu. Taka mała uwaga jeszcze -- przyjdzie nam budować pakiety, które będą się składać ze skryptów, obrazków, mp3 i całego mnóstwa innych rzeczy, którym normalnie byśmy nadali arch all ale dodatkowo będą zawierać jeden lub kilka plików binarnych i z tego powodu arch all odpada ale też nie możemy zbudować takiego pakietu z arch any , bo lintian będzie się rzucał, że marnujemy miejsce na serwerze, bo przecie z jego perspektywy, jeśli jakiś pakiet zawiera znaczne ilości plików niezależnych od architektury, to nie możemy dawać arch any i musimy dać all i jak z takiej sytuacji wybrnąć? Trzeba pakiet podzielić na dwie części. W jednej z nich dać pliki wymagające kompilacji, a w drugiej (zwykle paczka-common) dać wszystkie pliki niezależne od architektury i dodać odpowiednie zależności do paczki trzymającej plik binarny -- o tym będzie więcej przy okazji omawiania pliku debian/rules .

Następne linijki to Depends Suggests Recommends Conflicts , Breaks , Provides i Replaces i są to zależności, które muszą być spełnione przy instalacji pakietu. Nie wszystkie z wyżej wymienionych opcji będziemy zawsze używać. Zwykle ograniczymy się do pierwszych trzech. Różnice między nimi są następujące -- jeśli pakiet wymaga do działania innego pakietu, dajemy go w Depends, jeśli nasz pakiet może się obyć bez innego pakietu ale traci na tym trochę ze swojej funkcjonalności, to dajemy tamten pakiet w Recommends . Jeśli jakiś pakiet przydaje się ale można bez niego żyć, to dopisujemy go do Suggests . Jeśli nasz pakiet dostarcza pliki dostępne w innych pakietach, dajemy ten drugi pakiet w Conflics. Z kolei Breaks będziemy używać przy przenoszeniu plików z jednego pakietu do innego, np. przy podziale pakietu na kilka mniejszych. Jeśli nasz pakiet jest alternatywą dla innego pakietu, np. firefox jest alternatywą dla chrome (i vice versa), możemy wpisać w polu Provides www-browser i wtedy każdy inny pakiet, który ma w swoich zależnościach www-browser , przy instalacji będzie prosił o zainstalowanie firefoxa albo chrome (ew. obu). Jeśli chodzi o Replaces , to zwykle jest używany on (w połączeniu z Conflicts) przy zastępowaniu starych i nieaktualnych już pakietów, np. jeśli mamy do czynienia z forkami jakichś projektów i projekt główny nie jest już rozwijany ale w repozytorium wciąż jest dostępna paczka z nim -- generalnie nie możemy mieć zainstalowanych obu tych pakietów jednocześnie.

Każde z tych pól może zawierać określoną wersję danego pakietu. Wykorzystujemy do tego następujące operatory: << , <= , = , >= , and >> . Jeśli pakiet ma być w określonej wersji, to dajemy = , jeśli ma być mniejszy lub równy, to wtedy używamy <= , a jeśli większy lub równy to >= . Jeśli zaś wersja ma być mniejsza, to korzystamy z << , a jeśli większa, to >> .

Jeśli chodzi zaś o same zależności wymagane do prawidłowego działania pakietu, to ${shlibs:Depends} i ${misc:Depends} automatycznie ustalą czego paczka potrzebuje w oparciu o zależności potrzebne do zbudowania tego pakietu. Niemniej jednak, czasem (jak w tym przypadku) trzeba sprecyzować kilka dodatkowych pakietów. Ponadto, jeśli budujemy paczkę ze skryptami perla, trzeba dopisać ${perl:Depends} , jeśli jest to pythonowy skrypt, to dajemy ${python:Depends} lub ${python3:Depends} w zależności od wersji pythona. Wszystkie te dodatkowe listy z generowanymi pakietami są wpisywane do pliku debian/control w paczce wynikowej i możemy te zależności dokładnie obejrzeć i ewentualnie oszacować czy czegoś brakuje. Więcej informacji na temat określania zależności między pakietami, można znaleźć tutaj. Wspomnieć też należy, że to nie są jedyne opcje, które możemy wykorzystać przy podstawianiu zmiennych, więcej o pozostałych można przeczytać w manie deb-substvars .

I ostatnia pozycja w tym pliku to Description , czyli opis pakietu. Ten po dwukropku zwykle jest krótki i nie powinien przekraczać 65 znaków -- więcej zostanie obciętych. Jeśli zaś chodzi o dłuższy opis, to wpisujemy go bezpośrednio pod tą linijką, z tym, że wcinamy tekst o jedną spację i długość linijki nie może przekraczać 80 znaków. Każda nowa linia musi być wcięta. Jeśli chcemy zrobić odstęp między paragrafami (pusta linia), to dajemy kropkę (również wciętą) i dalej nowy paragraf. Jeśli chcemy skorzystać z list, czyli wypunktować różne rzeczy, wcinamy linijkę przy pomocy dwóch spacji i dajemy myślnik albo gwiazdkę -- ja zwykle daję gwiazdki.

5.3. debian/rules

Jak sama nazwa wskazuje, ten plik będzie zawierał szereg reguł, w oparciu o które pakiet zostanie zbudowany. Generalnie rzecz biorac jest to plik makefile tylko nieco inny.

Budowanie pakietu odbywa się w etapach -- wywoływany jest pierwszy i dokonywane są zdefiniowane w nim reguły, po czym następuje przejście do kolejnego etapu i aplikowane są reguły określone tutaj i tak dalej aż do samego końca.

Poniżej znajduje się minimalny plik debian/rules :

!/usr/bin/make -f

export DH_VERBOSE = 1 export DH_OPTIONS = -v

%: dh $@

Dobrze jest wyeksportować te dwie dodatkowe zmienne DH_VERBOSE oraz DH_OPTIONS . Uwidocznią one poszczególne etapy budowania pakietu i będziemy widzieć każde polecenie jakie będzie wykonywane, dzięki czemu znacznie przyśpieszymy proces przyswajania sobie całej tej potrzebnej nam wiedzy z zakresu budowania pakietów.

Dalej w pliku mamy %: i jest to wildcard oznaczający każdy target (etap) przy budowaniu pakietu, a tych jest sporo. Poniżej jest zobrazowany proces budowania paczki dnscrypt-proxy:

fakeroot debian/rules clean dh clean --with systemd,autotools-dev dh_testdir dh_auto_clean dh_clean

debian/rules build dh build --with systemd,autotools-dev dh_testdir dh_auto_configure dh_auto_build dh_auto_test

fakeroot debian/rules binary dh binary --with systemd,autotools-dev dh_testroot dh_prep dh_installdirs dh_auto_install dh_install dh_installdocs dh_installchangelogs dh_installexamples dh_installman dh_installcatalogs dh_installcron dh_installdebconf dh_installemacsen dh_installifupdown dh_installinfo dh_systemd_enable dh_installinit dh_systemd_start dh_installmenu dh_installmime dh_installmodules dh_installlogcheck dh_installlogrotate dh_installpam dh_installppp dh_installudev dh_installwm dh_installgsettings dh_bugfiles dh_ucf dh_lintian dh_gconf dh_icons dh_perl dh_usrlocal dh_link dh_installxfonts dh_compress dh_fixperms dh_strip dh_makeshlibs dh_shlibdeps dh_installdeb dh_gencontrol dh_md5sums dh_builddeb

W każdym z powyższych targetów może znajdować się szereg akcji, np:

dh_installman man --recode UTF-8 ./dnscrypt-proxy.8 > dnscrypt-proxy.8.new chmod 644 dnscrypt-proxy.8.new mv -f dnscrypt-proxy.8.new dnscrypt-proxy.8 man --recode UTF-8 ./hostip.8 > hostip.8.new chmod 644 hostip.8.new mv -f hostip.8.new hostip.8

Każdy z etapów wywołuje określone narzędzie, które ma na celu coś zrobić. Z reguły są to skrypty zaczynające się od dh_ i każdy z nich ma swój własny manual -- warto poczytać jeśli potrzebujemy informacji na temat pewnych opcji pojawiających się w logu podczas budowania. Nie zawsze będziemy korzystać ze wszystkich wyżej wylistowanych targetów. To zależeć będzie od tego co tak naprawdę będziemy budować, przykładowo: jeśli budujemy pakiet mający pliki unitów dla systemd, to logiczne jest, że będziemy przechodzić przez etap dh_systemd_enable i dh_systemd_start . Warto też wiedzieć, że szereg z powyższych targetów ma swoje pliki konfiguracyjne w katalogu debian/ , np. targetowi dh_install przypisany jest plik *.install .

Wszelkie moduły, z których chcemy skorzystać przy budowie paczki, precyzujemy po dh $@ . Poniżej przykład skorzystania z modułu dh_systemd :

... %: dh $@ --with dh_systemd ...

Jeśli modułów było by więcej, dodajemy je kolejno oddzielając je od siebie za pomocą przecinka. Musimy także pamiętać o dodaniu odpowiednich zależności w pliku debian/control .

Jeśli chodzi o dalszą część pliku debian/rules, to nasuwa się pytanie -- skąd ja mam wiedzieć co tutaj wpisać i jakie reguły zaaplikować? Zwykle debhelper wykryje upstreamowy plik makefile i powinien sobie z procesem budowania poradzić bez naszej ingerencji ale czasem szereg plików trzeba będzie usunąć, a niektóre stworzyć lub przenieść w inne miejsce, tak by paczka miała ręce i nogi i nie zawierała przy tym zbędnych śmieci.

Jeśli kiedyś zdarzyło nam się instalować pakiet ręcznie, tj. via ./configure (dh_auto_configure) , make (dh_auto_build) i make install (dh_auto_install), to może nam to podsunąć kilka pomysłów, bo tak na dobrą sprawę, to jak sama nazwa wskazuje makefile tworzy pliki. Zatem jest to prosta instrukcja gdzie wgrać jakie pliki by program działał jak trza. Zatem możemy podejrzeć plik makefile dołączony do źródeł i prześledzić co tak naprawdę w nim się odbywa. Z reguły pliki makefile są długie i nie będę tutaj przytaczał całości -- rzucimy jedynie okiem na najważniejsze jego fragmenty:

PN = monitorix

PREFIX ?= /usr CONFDIR = /etc BASEDIR = /var/lib/monitorix/www LIBDIR = /var/lib/monitorix INITDIR_SYSTEMD = $(PREFIX)/lib/systemd/system INITDIR_OTHER = $(CONFDIR)/init.d BINDIR = $(PREFIX)/bin DOCDIR = $(PREFIX)/share/doc/$(PN) MAN5DIR = $(PREFIX)/share/man/man5 MAN8DIR = $(PREFIX)/share/man/man8

RM = rm -f RMD = rmdir SED = sed INSTALL = install -p INSTALL_PROGRAM = $(INSTALL) -m755 INSTALL_SCRIPT = $(INSTALL) -m755 INSTALL_DATA = $(INSTALL) -m644 INSTALL_DIR = $(INSTALL) -d

Powyżej mamy nagłówek pliku makefile monitorixa. Jak widać jest ustawianych szereg zmiennych. Głównie precyzowane są katalogi, do których powędrują pliki, jak i same polecenia instalujące pliki w tych katalogach.

Dalej mamy już zwykle operacje na plikach, np:

install-bin: $(Q)echo -e '\033[1;32mInstalling script and modules...\033[0m' $(INSTALL_DIR) "$(DESTDIR)$(BINDIR)" $(INSTALL_PROGRAM) $(PN) "$(DESTDIR)$(BINDIR)/$(PN)"

$(INSTALL_DIR) "$(DESTDIR)$(BASEDIR)/cgi" $(INSTALL_DIR) "$(DESTDIR)$(BASEDIR)/imgs" $(INSTALL_PROGRAM) $(PN).cgi "$(DESTDIR)$(BASEDIR)/cgi/$(PN).cgi" $(INSTALL_DATA) logo_bot.png "$(DESTDIR)$(BASEDIR)/logo_bot.png" $(INSTALL_DATA) logo_top.png "$(DESTDIR)$(BASEDIR)/logo_top.png" $(INSTALL_DATA) monitorixico.png "$(DESTDIR)$(BASEDIR)/monitorixico.png"

$(INSTALL_DIR) "$(DESTDIR)$(CONFDIR)/$(PN)" $(INSTALL_DATA) $(PN).conf "$(DESTDIR)$(CONFDIR)/$(PN)/$(PN).conf" ...

I jak widać niczym się to zbytnio nie różni o zwykłego ctrl+c z jednego miejsca i ctrl+v w inne miejsce. Zatem mamy już mniej więcej obraz tego co tak naprawdę się będzie działo podczas budowania pakietu -- debhelper przetworzy ten plik makefile i zainstaluje poszczególne pliki w zdefiniowanych lokalizacjach, a potem z tego zrobi paczkę. Z tym, że trzeba wziąć pod uwagę jedną rzecz -- w tym przypadku mamy do czynienia ze skrypt perla i tutaj nie odbywa się żadna kompilacja. Niemniej jednak, po kompilacji są tworzone pliki wynikowe i to w dużej mierze właśnie te pliki będą upychane w odpowiednich katalogach.

Jeśli nie chce nam się zbytnio brodzić w pliku makefile, to z reguły informacje na temat budowania pakietu będą podane w pliku README albo INSTALL, które są dołączone do paczki ze źródłami. Przykładowo:

INSTALLATION

Running a make install-xxx as root will distribute the files to the file system. Most users will want to select from three options depending on target init system (do not run all four)!

# make install-systemd-all # make install-upstart-all # make install-debian-all # make install-redhat-all

Alternatively, users may override any of the in make targets. For example:

$ make DESTDIR=~/pub BASEDIR=/srv/http/monitorix install-systemd-all ...

I tu już wiemy dokładnie czego szukać w pliku makefile i jak zainstalować ten programik. Nam potrzebne są 2 (max 3) z tych 4 wyżej wymienionych rzeczy -- w końcu budujemy paczkę dla debiana, zatem plik debian/rules powinien przybrać poniższą postać:

!/usr/bin/make -f

export DH_VERBOSE = 1

%: dh $@

override_dh_auto_install: dh_auto_install -- \ install-systemd-all \ install-upstart-all \ install-debian-all

Normalnie proces budowy przechodząc przez poszczególne etapy dotrze do targetu dh_auto_install , który wykona instrukcje zawarte w pliku makefile, czyli zainstaluje wszystko co tam jest podane, a tego nie zawsze chcemy. Dlatego też, mamy możliwość nadpisywania szeregu etapów budowania przez dopisanie override_* . Powyżej nadpisaliśmy etap automatycznej instalacji przekazując do polecenia make trzy parametry, uzyskując w ten sposób dokładnie taką samą sekwencję poleceń (za wyjątkiem jednego), która była określona w pliku README .

Kluczowe w tej zwrotce z dh_auto_install jest zrozumienie po co na końcu tego polecenia dodawane są -- , bo można także podać parametry bez tych dwóch myślników. Jaka jest zatem różnica? Jeśli wywołujemy jakiś target z -- , to wszystkie parametry znajdujące się za tymi myślnikami są dołączane do wynikowego polecenia. W przypadku gdy nie podamy tych myślników, system zresetuje wszystkie poprzednie opcje i zamiast nich użyje te, które zostaną podane bezpośrednio za wywoływanym targetem.

Weźmy sobie przykład skryptu configure . Domyślnie ma on określone, dajmy na to, takie parametry --prefix=/usr --localstatedir=/var . Jeśli chcielibyśmy dodać kolejny parametr, korzystamy z myślników:

dh_auto_configure -- --sysconfdir=/etc

Jeśli chcielibyśmy użyć kompletnie innych wartości dla skryptu configure, pomijamy -- , przykładowo:

dh_auto_configure --prefix=/usr/local --localstatedir=/usr/local/var --sysconfdir=/usr/local/etc

Mamy jeszcze kilka innych opcji tyczących się nadpisywania targetów. Jeśli, przykładowo, odpowiadałby nam etap instalacji ale chcielibyśmy coś dodać do niego (przed albo po), wtedy musimy wywołać jego target i dodać swoje polecenia przed lub po nim, przykładowo:

... override_dh_auto_install: dh_auto_install -- install install-gui rm debian/tmp/usr/share/doc/ansifilter/ChangeLog rm debian/tmp/usr/share/doc/ansifilter/COPYING rm debian/tmp/usr/share/doc/ansifilter/INSTALL rm debian/tmp/usr/share/man/man1/ansifilter.1.gz ...

Powyżej został wywołany make z dwoma parametrami install oraz install-gui , poza tym, część plików automatycznie zainstalowanych, zostanie usunięta, tak by nie trafiła do wynikowego pakietu.

Jeśli natomiast chcielibyśmy nadpisać jakiś etap całkowicie, tak by nie wykonała się w nim żadna akcja, to możemy to zrobić precyzując jedynie sam target + override, przykładowo:

override_dh_auto_install:

A jeśli pasowałoby nam jedynie nadpisać standardowe akcje, wtedy nie wywołujemy dh_auto_install , tylko od razu precyzujemy własne linijki, przykładowo:

... override_dh_auto_install: install -d -m 755 debian/napi/usr/share/napi/ install -d -m 755 debian/napi/usr/bin/ install -m755 ./napi.sh debian/napi/usr/bin/ install -m755 ./subotage.sh debian/napi/usr/bin/ install -m755 ./napi_common.sh debian/napi/usr/share/napi/ ...

Jeśli instalujemy jakieś pliki, ścieżki do nich podajemy względem głównego katalogu ze źródłami. Z kolei jeśli chcemy jakiś plik usunąć, to zwykle podajemy ścieżki debian/tmp/ lub debian/nazwa_pakietu/ + odpowiednia ścieżka w drzewie katalogu, np. debian/tmp/usr/share/doc/ansifilter/INSTALL . Jeśli nie usunęlibyśmy tego pliku, w paczce znalazłby się on pod /usr/share/doc/ansifilter/INSTALL .

5.4. debian/changelog i debian/upstream.changelog

Każdy projekt musi mieć listę wprowadzanych zmian, a te z kolei dzielimy na takie, które sami wprowadzamy lub też zostały uwzględnione w upstreamie. Generalnie rzecz biorąc, większość projektów utrzymuje swój plik changelog (z reguły zlokalizowany w głównym katalogu źródeł) i nie musimy się o niego martwić. Niemniej jednak, spotkamy się z takimi projektami, które nie mają pliku changeloga, lub w ogóle nie posiadają żadnej historii zmian za wyjątkiem kolejnego numerku wersji.

Jeśli jest to przypadek pierwszy, czyli projekt ma changelog, np. na swojej stronie, ale nie dostarcza pliku, w którym zmiany by były uwzględnione, możemy taki plik zrobić i do niego skopiować zawartość strony www. Plik taki nazywamy upstream.changelog . Format tego pliku jest chyba dowolny, np. może wyglądać tak:

Version 2.2

  • Fix problems with small displays like 80×25
  • Fix ATA compliance recognition (see bug #57)
  • Replace “Press any key” with “Press ‘m’ for menu”
  • Rework signal handling during procedure for stability
  • Improve build system

Version 2.1

  • Enhanced smart, smart_noreverse copying strategies;
  • Introduced new copying strategies skipfail, skipfail_noreverse;
  • Introduce journaling of copying and automatic resuming of interrupted copying;
  • Support procedure parameters overriding by ~/.whddrc config file;
  • Several bug fixes. ...

Trzeba tylko poinformować debhelpera by przepisał nazwę pliku, pod którą ten changelog będzie widoczny w wynikowej paczce, przykładowo:

override_dh_installchangelogs: dh_installchangelogs -k debian/upstream.changelog

Powyższy kod wpisujemy oczywiście do pliku debian/rules i stworzy on linka changelog do pliku upstream.changelog . Więcej informacji na temat dh_installchangelogs można znaleźć w manie.

Jeśli chodzi zaś o te zmiany, które sami wprowadzamy, to dopisujemy je do pliku debian/changelog , który na początku ma poniższą postać:

monitorix (3.6.0-1) unstable; urgency=low

  • Initial release (Closes: #nnnn)

    -- Mikhail Morfikov <morfik@nsa.com> Thu, 19 Feb 2015 14:00:01 +0100

Oczywiście nie edytujemy tego pliku ręcznie (choć można). Do jego obsługi mamy narzędzie dch , do którego doklejamy tylko odpowiedni parametr i zwykle to będzie -a (dodanie nowej pozycji w istniejącym już wpisie), -i (utworzenie nowego wpisu), -r (zaktualizowanie sygnatury czasowej), oraz -v (zmiana wersji).

Przy zmianie wersji trzeba jednak uważać, bo zostanie zmieniona nazwa katalogu roboczego, przykładowo:

morfik:~/debian_build/monitorix-3.5.0$ dch -v 3.6.0 dch warning: New package version is Debian native whilst previous version was not dch warning: your current directory has been renamed to: ../monitorix-3.6.0

morfik:~/debian_build/monitorix-3.5.0$ cd ..

morfik:~/debian_build$ cd monitorix-3.6.0/

morfik:~/debian_build/monitorix-3.6.0$

W przypadku gdy będziemy chcieli włączyć pakiet do repozytorium debiana, trzeba będzie założyć stosowny wątek na bugtrackerze, któremu zostanie przypisany odpowiedni numer identyfikacyjny i to ten numer będziemy musieli podać w pliku debian/changelog , np. (Closes: #123456 . Ma to na celu zautomatyzowanie procesu śledzenia i zamykania błędów, bo plik debian/changelog jest skanowany w poszukiwaniu pewnych wyrażeń i np. BTS po dodaniu powyższego pakietu automatycznie zamknie zawarte w nim kody błędów, oczywiście o ile wpiszemy poprawne numerki. To samo tyczy się zgłaszania kolejnych błędów. Jeśli uda nam się je poprawić albo zostaną poprawione w upstreamie, to wystarczy dopisać w changelogu numerki zgłoszonych przez kogoś błędów i po przesłaniu paczki, system zamknie je automatycznie. Bez tego automatu, sami musielibyśmy to robić.

Jeśli chcielibyśmy się bawić w maintainera z prawdziwego zdarzenia, trzeba będzie nam przyswoić umiejętność operowania na listach mailingowych debiana. To tam będziemy mieć dostęp do bugtrackera, gdzie będą zgłaszane i omawiane błędy w pakietach, którymi będziemy musieli się zająć. Debian ma także kilka użytecznych narzędzi, które pomogą nam w tym zadaniu i jednym z nich jest reportbug -- przydaje się nie tylko do zgłaszania błędów. Zbiór list mailingowych debiana można znaleźć tutaj, z kolei pod tym linkiem można znaleźć garść użytecznych informacji na temat tego jak używać samych list.

Skrypt dch jest dość rozbudowany i sporo opcji i jeśli ktoś chciałby w pełni zgłębić możliwości tego narzędzia, to informacje znajdzie w manie. Więcej informacji na temat formatu samego pliku debian/changelog można znaleźć tutaj.

5.4.1. debian/NEWS

Wszystkie ważne informacje na temat zmian w pakiecie możemy wrzucić również do tego pliku. Podczas instalacji nowszej wersji takiego pakietu, narzędzie takie jak apt-listchanges wyrzuci monit z tekstem, który tam umieścimy. Więcej informacji na temat dokładnej zasady działania tego mechanizmu można znaleźć w manualu.

Format tego pliku jest podobny do formatu pliku debian/changelog , z tym, że nie zawiera gwiazdek. Przy pomocy narzędzia dpkg-parsechangelog możemy sprawdzić poprawność tego pliku:

morfik:~/debian_build/ansifilter-1.11$ dpkg-parsechangelog -ldebian/NEWS Source: ansifilter Version: 1.11-1 Distribution: unstable Urgency: low Maintainer: Mikhail Morfikov <morfik@nsa.com> Date: Tue, 03 Feb 2015 09:19:10 +0100 Changes: ansifilter (1.11-1) unstable; urgency=low . Some important news Some important news Some important news Some important news

5.5. debian/copyright

Licencja jest chyba jedną z tych rzeczy na jaką debian kładzie największy nacisk. Samych licencji mamy całe mnóstwo ale cześć z nich jest odrzucana przez politykę debiana i jeśli będziemy pakować jakąś aplikację na jednej z takich licencji, ten pakiet nigdy nie trafi do głównego repozytorium debiana.

Licencje akceptowalne przed debiana można odczytać z dh_make przy tworzeniu pakietu:

$ dh_make --help -c, --copyright <type> use <type> of license in copyright file (apache|artistic|bsd|gpl|gpl2|gpl3|lgpl|lgpl2| lgpl3|mit)

Pliki licencji są zlokalizowane w katalogu /usr/share/common-licenses/ :

$ ls -al /usr/share/common-licenses/ total 220K drwxr-xr-x 2 root root 4.0K 2014-12-06 18:54:52 ./ drwxr-xr-x 336 root root 12K 2015-02-17 17:10:41 ../ -rw-r--r-- 1 root root 12K 2004-12-19 21:30:25 Apache-2.0 -rw-r--r-- 1 root root 6.0K 1996-12-16 03:58:50 Artistic -rw-r--r-- 1 root root 1.5K 1999-08-26 14:06:20 BSD lrwxrwxrwx 1 root root 8 2014-11-30 13:37:40 GFDL -> GFDL-1.3 -rw-r--r-- 1 root root 20K 2010-03-24 00:34:05 GFDL-1.2 -rw-r--r-- 1 root root 23K 2008-11-03 17:47:07 GFDL-1.3 lrwxrwxrwx 1 root root 5 2014-11-30 13:37:40 GPL -> GPL-3 -rw-r--r-- 1 root root 13K 2010-03-24 00:34:05 GPL-1 -rw-r--r-- 1 root root 18K 2010-03-24 00:34:05 GPL-2 -rw-r--r-- 1 root root 35K 2007-07-02 00:55:35 GPL-3 lrwxrwxrwx 1 root root 6 2014-11-30 13:37:40 LGPL -> LGPL-3 -rw-r--r-- 1 root root 25K 2010-03-25 18:29:55 LGPL-2 -rw-r--r-- 1 root root 26K 2010-03-24 00:34:05 LGPL-2.1 -rw-r--r-- 1 root root 7.5K 2010-03-24 00:34:01 LGPL-3

Nie musimy całej treści tych plików kopiować do debian/copyright . Możemy jedynie dać nagłówek i zawrzeć odnośnik do jednego z powyższych plików -- tak jak to robi standardowo dh_make . Są też licencje, które nie widnieją w powyższym katalogu i równocześnie są akceptowane przez debiana, np. MIT, i w takim przypadku trzeba podać treść całej licencji w pliku debian/copyright .

Zwykle każdy plik ma w nagłówku u siebie licencje (przynajmniej powinien mieć) ale przeglądanie dziesiątek czy setek plików w celu ustalenia, który jest na jakiej licencji może być lekko męczące. Na szczęście mamy do dyspozycji narzędzie licensecheck , które wywołane z opcją -r w głównym katalogu, zwróci nam listę plików wraz z ich licencją, przykładowo:

$ licensecheck -r * docs/monitorix-alert.sh: No copyright UNKNOWN docs/htpasswd.pl: No copyright UNKNOWN lib/fail2ban.pm: GPL (v2 or later) lib/HTTPServer.pm: GPL (v2 or later) lib/int.pm: GPL (v2 or later) lib/user.pm: GPL (v2 or later) lib/port.pm: GPL (v2 or later) lib/ftp.pm: GPL (v2 or later) lib/traffacct.pm: GPL (v2 or later) lib/system.pm: GPL (v2 or later) lib/libvirt.pm: GPL (v2 or later) ...

Czasem nie wszystkie pliki zostaną uwzględnione w powyższym listingu, domyślnie będą to te pasujące do następującego wzorca: '.(c(c|pp|xx)?|h(h|pp|xx)?|f(77|90)?|go|p(l|m)|xs|sh|php|py(|x)|rb|java|js|vala|el|sc(i|e)|cs|pas|inc|dtd|xsl|mod|m|tex|mli?|(c|l)?hs)$' . Jeśli któryś z plików w naszym pakiecie się nie łapie pod ten wzorzec, możemy ręcznie określić własny przy pomocy opcji -c .

O te pliki, które nie mają licencji, trzeba będzie się dopytać, chyba, że na stronie projektu jest informacja, że "pliki są na GPL-2", wtedy wszystko jest już jasne.

Poniżej przykład pliku debian/copyright wygenerowanego przez dh_make :

Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: monitorix Source: http://www.monitorix.org

Files: * Copyright: 2005-2014 Jordi Sanfeliu <jordi@fibranet.cat.> License: GPL-2.0+

Files: debian/* Copyright: 2015 Mikhail Morfikov <morfik@nsa.com> License: GPL-2.0+

License: GPL-2.0+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. . This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/> . On Debian systems, the complete text of the GNU General Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".

Jeśli chodzi o samą strukturę tego pliku, to w pierwszej linijce mamy Format i zwykle jest taki jak wyżej. Uzupełniamy Upstream-Name i Source , odpowiednio, nazwę pakietu oraz skąd zostały pobrane źródła.

Dalej mamy określanie praw do plików. Jeśli wszystkie pliki w źródłach pochodzą od jednej osoby, wtedy w linijce z Files dajemy * . Jeśli autorów jest więcej i każdy z nich rości sobie prawa do innego pliku lub plików w danym katalogu, musimy te pliki wypunktować oddzielając je spacją, przykład:

Files: src/libsodium/crypto_auth/hmacsha256/cp/hmac_hmacsha256.c src/libsodium/crypto_auth/hmacsha512256/cp/hmac_hmacsha512256.c src/libsodium/crypto_hash/sha256/cp/hash_sha256.c src/libsodium/crypto_hash/sha512/cp/hash_sha512.c src/libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.h src/libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c Copyright: 2005,2007,2009 Colin Percival License: BSD-2-clause

Sekcji z Files może być dowolna ilość, tak by każdy plik miał określoną licencję, Jeśli któryś z nich zostanie pominięty, lintian będzie miał z tym problem i nam to oświadczy. Z reguły to my będziemy mieć prawa do plików w katalogu debian/ , bo je tworzymy.

W linijce z Copyright podajemy informacje na temat tego kto jest właścicielem praw autorskich do plików w formie "data nazwisko email" (email nie jest obowiązkowy). Jeśli autorów by było więcej, wtedy definiujemy ich jeden pod drugim np:

Files: src/libsodium/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h src/libsodium/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c src/libsodium/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c Copyright: 2009 Colin Percival 2012, 2013 Alexander Peslyak License: BSD-2-clause

Ostatnia rzecz o której trzeba wspomnieć to License i bynajmniej nie chodzi tutaj o rodzaj licencji tylko o sposób jej definiowania. Generalnie można to robić na dwa sposoby. Jeden z nich zakłada dołączania pod linijką z License treści licencji ale to troszeczkę psuje całą estetykę i lepiej jest tego nie robić. Alternatywne rozwiązanie zakłada zdefiniowanie poszczególnych bloków plików jeden pod drugim i dopiero na końcu podanie treść licencji, przykładowo:

Files: * Copyright: © 2015 William Jon McCann © 2015 Peter de Ridder © 2015 Simon Steinbeiß License: GPL-2

Files: debian/* Copyright: © 2013 Yves-Alexis Perez License: GPL-2

Files: src/gs-content.c src/gs-content.h src/gs-debug.c src/gs-debug.h src/gs-grab-x11.c src/gs-grab.h src/gs-listener-dbus.c src/gs-listener-dbus.h src/gs-listener-x11.c src/gs-listener-x11.h src/gs-manager.c src/gs-manager.h src/gs-monitor.c src/gs-monitor.h src/gs-window.h src/light-locker-command.c src/light-locker.c src/light-locker.h src/preview.c Copyright: 2004-2005, William Jon McCann 2004-2006, William Jon McCann 2004-2008, William Jon McCann 2005, William Jon McCann License: GPL-2+

Files: src/gs-window-x11.c Copyright: 2004-2008, William Jon McCann 2008-2011, Red Hat, Inc License: GPL-2+

Files: src/gs-bus.h Copyright: 2010, Saleem Abdulrasool License: GPL-2+

Files: data/*.1 Copyright: 2007 Sven Arvidsson 2014 Peter de Ridder License: GPL-2+

License: GPL-2 On Debian systems, the complete text of the GNU General Public License version 2 can be found in `/usr/share/common-licenses/GPL-2'.

License: GPL-2+ On Debian systems, the complete text of the GNU General Public License can be found in `/usr/share/common-licenses/GPL-2'.

Formatowanie pliku odbywa się dokładnie na takich samych zasadach co w przypadku pliku debian/control , czyli paragrafy (np. w licencjach) są oddzielone kropkami, a nowe linie są wcięta minimum o jedną spację.

5.6. debian/watch i debian/upstream/signing-key.asc

W oparciu o te pliki, narzędzie uscan potrafi zweryfikować czy pojawiła się nowsza wersja jakiejś aplikacji. Plik debian/watch będzie wyglądał mniej więcej tak:

version=3 opts=filenamemangle=s/.+\/v?(\d\S).tar.gz/Monitorix-$1.tar.gz/ \ https://github.com/mikaku/Monitorix/tags ./v?(\d\S*).tar.gz

Linijka z version obecnie przyjmuje wartość 3 , natomiast kolejna linijka jest nieco skomplikowana -- mamy tam wyrażenia regularne perla. Nie będziemy zajmować się tutaj samymi wyrażeniami i skupimy się na wzorcach, które jedynie będziemy dostosowywać. Więcej informacji o samych wyrażeniach regularnych można znaleźć tutaj.

Większość projektów jest hostowana na githubie czy sourceforge i w ich przypadku możemy skorzystać z czyjejś pracy, czyli skopiować sobie tę powyższą linijkę i odpowiednio dostosować. Powyżej mamy przykład projektu hostowanego na githubie i raczej przerobienie linku nie powinno przysporzyć problemów.

Wszystkie inne większe strony z projektami opensource mają swoje regułki zebrane pod tym linkiem . Jeśli tam nie znajdziemy strony, z której pobraliśmy źródła, będziemy musieli sami naskrobać odpowiednią regułkę. Wprawdzie nie jest to obowiązkowe ale znacząco ułatwia późniejsze aktualizowanie źródeł, bo wystarczy, że w katalogu ze źródłami wydamy polecenie uscan i ten już sprawdzi czy pojawiła się nowsza wersja w upstreamie. Jeśli tak, pobierze ją i automatycznie dostosuje nazwy plików, co przyśpieszy migrację pakietu do nowszej wersji.

Po uzupełnieniu pliku, aktualizację przeprowadzamy w poniższy sposób:

morfik:~/debian_build/monitorix-3.6.0$ uscan --verbose -- Scanning for watchfiles in . -- Found watchfile in ./debian -- In debian/watch, processing watchfile line: opts=filenamemangle=s/.+\/v?(\d\S).tar.gz/Monitorix-$1.tar.gz/ https://github.com/mikaku/Monitorix/tags ./v?(\d\S*).tar.gz -- Found the following matching hrefs: /mikaku/Monitorix/archive/v3.6.0.tar.gz (3.6.0) /mikaku/Monitorix/archive/v3.5.1.tar.gz (3.5.1) /mikaku/Monitorix/archive/v3.5.0.tar.gz (3.5.0) Newest version on remote site is 3.6.0, local version is 3.6.0 => Package is up to date -- Scan finished

Jak widzimy wyżej, plik debian/watch został odnaleziony i przetworzony, zwracając 3 pliki o różnych wersjach. Jako, że posiadam najnowszą wersję źródeł, żadna akcja mająca na celu dokonanie aktualizacji nie została podjęta.

5.6.1. Podpisy cyfrowe źródeł

Trzeba jeszcze wspomnieć o jeden ważnej rzeczy, mianowicie o podpisach cyfrowych. Jeśli budujemy projekt, który ma podpisane źródła, koniecznie musimy weryfikować ich podpis, z tym, że będziemy potrzebować klucza publicznego osoby składającej sygnaturę. Poniżej jest przedstawiony proces pozyskiwania klucza publicznego.

Na sam początek odwiedzamy stronę projektu i patrzymy co za pliki są do pobrania:

dnscrypt-proxy-1.4.3.tar.gz 05-Jan-2015 17:14 1560345 dnscrypt-proxy-1.4.3.tar.gz.sig 10-Feb-2015 11:00 543

Pobieramy oba pliki i przechodzimy do katalogu gdzie zostały pobrane:

$ ls -al dnscrypt-proxy-1.4.3.tar.gz* -rw-r--r-- 1 morfik morfik 1.5M 2015-02-20 15:37:28 dnscrypt-proxy-1.4.3.tar.gz -rw-r--r-- 1 morfik morfik 543 2015-02-20 15:37:31 dnscrypt-proxy-1.4.3.tar.gz.sig

Próbujemy póki co ręcznie zweryfikować podpis:

$ gpg --verify dnscrypt-proxy-1.4.3.tar.gz.sig gpg: assuming signed data in `dnscrypt-proxy-1.4.3.tar.gz' gpg: Signature made Tue 10 Feb 2015 12:00:24 PM CET gpg: using RSA key 0x62F25B592B6F76DA gpg: Can't check signature: public key not found

Jak widzimy, nie można zweryfikować sygnatury, bo nie posiadamy klucza publicznego. Szukamy go zatem i importujemy:

$ gpg --search-keys 0x62F25B592B6F76DA gpg: searching for "0x62F25B592B6F76DA" from hkps server hkps.pool.sks-keyservers.net (1) Frank Denis <github@pureftpd.org> Frank Denis <frank.denis@corp.ovh.com> Frank Denis (Jedi/Sector One) <j@pureftpd.org> Frank Denis (Jedi/Sector One) <pgp@pureftpd.org> Frank Denis (Jedi/Sector One) <0daydigest@pureftpd.org> 4096 bit RSA key 0x210627AABA709FE1, created: 2015-02-10

Keys 1-1 of 1 for "0x62F25B592B6F76DA". Enter number(s), N)ext, or Q)uit > 1 gpg: requesting key 0x210627AABA709FE1 from hkps server hkps.pool.sks-keyservers.net gpg: key 0x210627AABA709FE1: public key "Frank Denis (Jedi/Sector One) <pgp@pureftpd.org>" imported gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model gpg: depth: 0 valid: 2 signed: 1 trust: 0-, 0q, 0n, 0m, 0f, 2u gpg: depth: 1 valid: 1 signed: 0 trust: 1-, 0q, 0n, 0m, 0f, 0u gpg: next trustdb check due at 2017-07-15 gpg: Total number processed: 1 gpg: imported: 1 (RSA: 1)

Klucz został zaimportowany do naszego lokalnego keyringa. Jeśli teraz byśmy spróbowali sprawdzić sygnaturę, podpis powinien zostać zweryfikowany. Musimy teraz wydobyć ten klucz z keyringa i zapisać go w formacie ascii do pliku:

$ mkdir debian/upstream/

$ gpg --armor --export 0x62F25B592B6F76DA > debian/upstream/signing-key.asc

$ ls -al debian/upstream/signing-key.asc -rw-r--r-- 1 morfik morfik 11K 2015-02-20 15:51:17 debian/upstream/signing-key.asc

Zatem klucz publiczny jest już na swoim miejscu. Musimy jeszcze nieco dostosować linijkę w pliku debian/watch tak by uscan automatycznie weryfikował podpis bez naszej ingerencji:

version=3 opts=pgpsigurlmangle=s/$/.sig/ \ http://download.dnscrypt.org/dnscrypt-proxy/dnscrypt-proxy-([0-9].+).tar.gz

Od tej pory gdy się pojawi nowsza wersja pakietu, zostanie ona pobrana po wywołaniu uscan , a sygnatura zostanie zweryfikowana automatycznie. Poniżej przykład:

morfik:~/debian_build/dnscrypt-proxy-1.3.0$ uscan --verbose -- Scanning for watchfiles in . -- Found watchfile in ./debian -- In debian/watch, processing watchfile line: opts=pgpsigurlmangle=s/$/.sig/ http://download.dnscrypt.org/dnscrypt-proxy/dnscrypt-proxy-([0-9].+).tar.gz -- Found the following matching hrefs: dnscrypt-proxy-1.4.0.tar.gz (1.4.0) dnscrypt-proxy-1.4.1.tar.gz (1.4.1) dnscrypt-proxy-1.4.2.tar.gz (1.4.2) dnscrypt-proxy-1.4.3.tar.gz (1.4.3) Newest version on remote site is 1.4.3, local version is 1.3.0 => Newer version available from http://download.dnscrypt.org/dnscrypt-proxy/dnscrypt-proxy-1.4.3.tar.gz -- Downloading updated package dnscrypt-proxy-1.4.3.tar.gz -- Downloading OpenPGP signature for package as dnscrypt-proxy-1.4.3.tar.gz.pgp -- Verifying OpenPGP signature dnscrypt-proxy-1.4.3.tar.gz.pgp for dnscrypt-proxy-1.4.3.tar.gz gpgv: Signature made Tue 10 Feb 2015 12:00:24 PM CET using RSA key ID 2B6F76DA gpgv: Good signature from "Frank Denis (Jedi/Sector One) <pgp@pureftpd.org>" gpgv: aka "Frank Denis <github@pureftpd.org>" gpgv: aka "Frank Denis <frank.denis@corp.ovh.com>" gpgv: aka "Frank Denis (Jedi/Sector One) <j@pureftpd.org>" gpgv: aka "Frank Denis (Jedi/Sector One) <0daydigest@pureftpd.org>" -- Successfully downloaded updated package dnscrypt-proxy-1.4.3.tar.gz -- Successfully symlinked ../dnscrypt-proxy-1.4.3.tar.gz to ../dnscrypt-proxy_1.4.3.orig.tar.gz. -- Scan finished

Jak widzimy, źródła nowszej wersji programu zostały pobrane, a sygnatura sprawdzona.

5.7. debian/manpage.* i debian/*.manpages (dh_installman)

Dokumentacja projektu to bardzo ważna rzecz i bez niej ani rusz. To właśnie na jej podstawie wiemy jakie zadania ma realizować dany program. Zwykle jest nieco bardziej obszerna niż parametr --help doczepiony do wywołanego programu. Jeśli dany projekt się szanuje, powinien wypuścić przyzwoitą dokumentację i dołączyć ją paczki ze źródłami. Nie zawsze jednak taki manual ma odpowiednią formę. Pod tym linkiem znajduje się krótki tutorial na temat składni stosowanej w plikach manuala wykorzystywanych w debianie. Będziemy musieli się tego nauczyć, w przeciwnym wypadku, może się zdarzyć tak, że nasze paczki zostaną bez dokumentacji, a to niedobrze.

Z grubsza będziemy mieli styczność z trzema rodzajami przypadków. W pierwszym z nich nie będzie żadnej dokumentacji, w drugim będzie dokumentacja ale trzeba będzie ją przeformatować, w ostatnim zaś będziemy musieli poprawić błędy w formatowaniu, które wypunktuje nam lintian. Pomijam oczywiście ten rzadki przypadek, w którym wszystko będzie jak trza i nie będziemy musieli nic robić.

Manuale tyczą się głównie plików wykonywalnych i według polityki debiana, każdy taki plik musi mieć manual, nawet jeśli jest to jakaś aplikacja GUI z dwoma przyciskami na krzyż, z których jeden to OK, a drugi to ANULUJ. xD Nazwy plików manuali mają również swój format np. napi.1 . Numerki są od 1-9 , w zależności od tego o czym jest konkretna strona manuala. Najczęściej jednak będziemy się spotykać z numerkami 1 (info o opcjach, które program może przyjąć) i 5 (pliki konfiguracyjne). Jeśli kogoś interesują pozostałe numerki, może o nich poczytać w man man . :]

Bardzo rzadko będziemy tworzyć plik manuala od podstaw, jeśli się jednak na to zdecydujemy, istnieją graficzne narzędzia, które mogą nam ułatwić to zadanie. Jednym z nich jest gmanedit . W pozostałych przypadkach będziemy szli na skróty. Samo poprawianie poszczególnych linijek w pliku nie powinno sprawić problemów, zwłaszcza jeśli się opanuje składnię pliku manuala. Możemy także korzystać z polecenia man -l plik-mana.1 aby podejrzeć jak wyglądać będzie ten manual w systemie.

5.7.1. Automatyczne generowanie manuali

Watro też wspomnieć iż istnieje możliwość wygenerowania pliku manuala w oparciu o polecenie --help , z tym, że nie zawsze wszystkie aplikacje posiadają w swoim wyposażeniu ten parametr. Poza tym, jeśli chodzi o aplikacje GUI, muszą one mieć dostęp do sesji graficznej by taki manual wygenerować. I takim automatycznym generowaniem plików manuali zajmuje się help2man . Można go wywołać bezpośrednio przy budowaniu paczki, z tym, że to pociąga za sobą dodatkowe zależności oraz kilka linijek w pliku debian/rules , a konkretnie trzeba będzie nadpisać target dh_installman oraz uwzględnić ten nowy plik przy czyszczeniu w targecie dh_clean. Poniżej przykład:

override_dh_installman: help2man -N --no-discard-stderr --version-string='0.3.3' -n 'feature-rich screen recorder that supports X11 and OpenGL' debian/simplescreenrecorder/usr/bin/simplescreenrecorder > simplescreenrecorder.1 help2man -N --no-discard-stderr --version-string='0.3.3' -n 'inject the GLInject library into a given command' debian/simplescreenrecorder/usr/bin/ssr-glinject > ssr-glinject.1 dh_installman simplescreenrecorder.1 ssr-glinject.1

override_dh_clean: dh_clean -- simplescreenrecorder.1 ssr-glinject.1

Możemy także wygenerować plik manuala po zbudowaniu paczki i wrzucić go później do katalogu debian/ .

Jeśli zdecydujemy się na to drugie wyjście, to manual generujemy w poniższy sposób:

$ which napi /usr/bin/napi

$ help2man /usr/sbin/napi > napi.1

Tak wygenerowany plik dobrze jest przejrzeć i poprawić ewentualne błędy.

Mając już pliki manuali, musimy uwzględnić je w debian/*.manpages , gdzie gwiazdka zwykle odpowiada nazwie pakietu, do którego ten manual ma trafić. Generalnie chodzi o to, że w przypadku gdy budujemy większy projekt, który ma kilka paczek, to raczej chcielibyśmy aby manual od jednego pliku trafił do konkretnej paczki, podobnie z pozostałymi. Poniżej przykład pliku napi.manpages :

debian/napi.1 debian/subotage.1

Format tego pliku jest prosty. Każda linijka to jeden plik manuala i określamy w niej położenie samego pliku w katalogu ze źródłami. Jako, że stworzyliśmy dopiero co nowe pliki manuala, to umieściliśmy je w podkatalogu debian/ . Nie używamy tutaj początkowego / , bo ścieżki są względne.

Istnieje także możliwość zmiany położenia i wtedy po spacji dodajemy kolejną ścieżkę, która określa lokalizację pliku w wynikowej paczce i też nie używamy początkowego / , przykładowo:

debian/napi.1 usr/share/man/man1/

Z reguły nie ma takiej potrzeby i wystarczy określić tylko pierwszą ścieżkę, druga zostanie dobrana automatycznie na podstawie numerka.

5.8. debian/*.docs (dh_installdocs)

Ten plik będzie zawierał ścieżki do plików, które niosą ze sobą jakąś przydatną z punktu widzenia projektu informację ale nie są to manuale. Zwykle ich nazwy będą pisane dużymi lietrami, np. README -- ze wszystkich takich plików robimy listę. Trzeba tylko się pilnować, by nie umieszczać śmieci np. nie potrzebujemy pliku INSTALL, czy plików związanych z innymi dystrybucjami linuxa. Pakujemy tu tylko co się tyczy debiana. Poniżej przykład pliku:

AUTHORS BUGS COLABORATION README.md

Z reguły system powinien wykryć cześć plików ale dobrze jest przejrzeć główny katalog źródeł i posprawdzać czy coś nie zostało pominięte.

5.9. Pliki demonów (dh_installinit)

Nie będę tutaj przytaczał żadnych skryptów -- chodzi o skrypty sysvinit, unity systemd i podobne pliki związane z odpalaniem usług systemowych, bo to jest poza zakresem tego poradnika. Niemniej jednak, zostanie załączony link do dokumentacji poszczególnych plików, tak by mieć jakiś punkt zaczepienia.

5.9.1. debian/*.init

Niby debhelper tworzy plik *.init.d ale wszędzie w paczkach spotkałem się tylko z samym *.init . W każdym razie, nie ma to większego znaczenia, z której nazwy skorzystamy -- oba pliki odpowiadają za instalowanie skryptów startowych sysvinit, tych w katalogu /etc/init.d/ . By sprawnie tworzyć takie skrypty, trzeba zrozumieć sam nagłówek LSB oraz ogarnąć narzędzie start-stop-daemon. Dodatkowo trzeba również opanować obsługę debianowego sh (dash) , tak by uniknąć bashismów.

Skrypty init dobrze jest także potraktować poleceniem sh -n , które zwróci ewentualne problemy ze składnią, przykładowo:

$ sh -n dnscrypt-proxy

Jeśli jakieś błędy się pojawią, trzeba będzie je poprawić.

5.9.2. debian/*default

Plik *.default odpowiada za konfigurację skryptu init trzymaną w katalogu /etc/default/. Generalnie chodzi o możliwość zachowania części z ustawionych opcji, które zwykle powinny być stałe i nie ulegać resetowaniu podczas aktualizacji pakietu. Sam skrypt init może ulec zmianie ale w stopniu, w którym nie powinien ingerować w opcje określone tutaj w tym pliku, przynajmniej taka jest teoria.

Ten plik zawiera jedynie szereg zmiennych i trochę komentarzy, a do tego raczej nie potrzebujemy manuala.

5.9.3. debian/*service (dh_systemd_enable, dh_systemd_start)

W tym pliku jest trzymana konfiguracja unitów dla systemd. By z nich skorzystać musimy w pliku debian/rules uwzględnić moduł dh_systemd . Dokładne informacje na temat opcji, które możemy użyć w plikach unitów, możemy znaleźć w dokumentacji systemd dostępnej tutaj. Jest tego dość sporo i dla ułatwienia podpowiem tylko, że interesować nas będą głównie strony od systemd.service oraz systemd.unit.

5.9.4. debian/*tmpfile

W tym pliku jest trzymana konfiguracja plików tymczasowych, które są niezbędne do działania danego programu. Wszystkie pliki i katalogi określone tutaj będą tworzone i konfigurowane automatycznie na starcie systemu. Dokładne informacje na temat formatu samego pliku można znaleźć tutaj.

5.10. debian/*.symbols

Z tym plikiem spotkamy się jedynie przy budowaniu bibliotek, co nie jest prostym zadaniem. Zakładając, że udało nam się zbudować bibliotekę, będziemy musieli wygenerować dla niej plik *.symbols , a tego możemy dokonać jedynie mając do dyspozycji paczkę wynikową, także zbudowanie biblioteki wymaga przepakowania jej co najmniej jeden dodatkowy raz.

Do generowania symboli posłuży nam narzędzie dpkg-gensymbols , zaś do wypakowania paczki dpkg-deb . Sam proces przebiega mniej więcej w poniższy sposób:

$ dpkg-deb -x /media/Kabi/pbuilder/result/libssr-glinject_0.3.3-1_amd64.deb /tmp/libssr-glinject $ dpkg-gensymbols -v0.3.3 -plibssr-glinject -P/tmp/libssr-glinject -Olibssr-glinject.symbols $ sed -i s/0.3.3$/0.3.3\~/g libssr-glinject.symbols

Pierwsza linijka wypakowuje paczkę z biblioteką, druga generuje symbole, a trzecia dopisuje do wersji znaczek ~ , o który domagał się lintian.

Tak stworzony plik przenosimy do katalogu debian/ i budujemy paczkę jeszcze raz.

Czasem też się zdarzy tak, że nazwa, którą nadaliśmy paczce z biblioteką, jest niewłaściwa. Jak zatem ustalić odpowiednią nazwę? Do tego celu posłuży nam narzędzie readelf , poniżej przykład:

$ readelf -d /usr/lib/x86_64-linux-gnu/libssr-glinject.so | grep SONAME 0x000000000000000e (SONAME) Library soname: [libssr-glinject.so]

I już wiemy, że paczka ma się nazywać libssr-glinject .

Więcej informacji na temat symboli można znaleźć tutaj i tutaj.

5.11. debian/*.dirs (dh_installdirs)

Jeśli do zbudowania pakietu potrzebne nam są dodatkowe katalogi, które standardowo nie są tworzone, oznaczać to może najprawdopodobniej błąd w pliku makefile. Możemy te katalogi wpisać do tego pliku i poprawić tym samym ten błąd. Jeśli dodajemy pliki do debian/*.install , to nie musimy tutaj uwzględniać tych katalogów.

5.12. debian/*.install (dh_install)

Jeśli z jakiegoś powodu pewne pliki nie są brane pod uwagę przez makefile i zwyczajnie nie zostaną utworzone w paczce wynikowej, musimy je tutaj określić.

Ten plik będziemy także wykorzystywać do rozdzielania plików na mniejsze paczki ale tutaj taka mała uwaga -- pierw musimy zbudować pakiet bez jakiegokolwiek rozdzielania na mniejsze i zobaczyć jakie pliki uzyskamy w paczce wynikowej. Jeśli na samym początku zaczniemy bawić wpisami w *.install , jest wysokie prawdopodobieństwo, że pogubimy część potrzebnych plików, bo nie zostaną one w tych plikach *.install uwzględnione.

Jeśli z jednego źródła chcemy zbudować dwie paczki, potrzebne będą nam dwa pliki .install . Każdy z nich będzie miał nazwę wynikowego pakietu. Poniżej jest przykład budowania pakietu simplescreenrecorder i biblioteki libssr-glinject -- oba są budowane z tych samych źródeł. By odseparować pewne pliki od siebie i upchnąć je w osobnych paczkach, tworzymy poniższe pliki:

Plik debian/simplescreenrecorder.install :

usr/share/ usr/bin/

Plik debian/libssr-glinject.install :

usr/lib/*/libssr-glinject.so

W powyższym przykładzie jest podana tylko jedna ścieżka -- druga może być podana po spacji. Pierwsza z nich określa skąd kopiować plik, druga gdzie go wrzucić (w drzewie katalogu paczki). Jeśli nie podamy tej drugiej ścieżki, zostanie przyjęta domyślnie i będzie taka sama jak pierwsza. Co do samych plików, to możemy precyzować każdy z osobna uwzględniając przy tym nazwę pliku w pierwszej ścieżce, albo też możemy podawać ścieżki do całych katalogów, tak jak to widać wyżej. Trzeba pamiętać o tym, że przy pomocy *.install nie damy rady przepisać nazwy pliku -- druga ścieżka zawsze ma postać katalogu.

Jeśli chodzi o same biblioteki, to przy instalowaniu plików trzeba uważać, bo w systemie są różne ścieżki w zależności od jego architektury. Zamiast podawać dokładną ścieżkę, można użyć wildcarda, tak by dopasować pewnej jej części i sprawić tym samym, że pakiet zbuduje się na innej architekturze niż był pierwotnie budowany. Zwykle będzie to wyglądać tak: usr/lib/*/ , kluczowa jest tutaj ta gwiazdka w trzecim członie i to ona upchnie plik biblioteki w odpowiednim folderze (normalnie byśmy tam podali np. x86_64-linux-gnu).

Po rozdzieleniu paczek, trzeba będzie także odpowiednio uzupełnić plik debian/control tak by dodać opisy i zależności, przykładowo:

... Package: simplescreenrecorder Architecture: i386 amd64 Pre-Depends: ${misc:Pre-Depends} Depends: ${shlibs:Depends}, ${misc:Depends} Recommends: libssr-glinject Description: Feature-rich screen recorder (main program) SimpleScreenRecorder is a feature-rich screen recorder that supports X11 and OpenGL. It has a Qt-based graphical user interface. It can record the entire creen or part of it, or record OpenGL applications directly. The recording can be paused and resumed at any time. Many different file formats and codecs are supported . This package contains the main program.

Package: libssr-glinject Architecture: i386 amd64 Multi-Arch: same Pre-Depends: ${misc:Pre-Depends} Depends: ${shlibs:Depends}, ${misc:Depends}, simplescreenrecorder Description: Feature-rich screen recorder (GLInject library) SimpleScreenRecorder is a feature-rich screen recorder that supports X11 and OpenGL. It has a Qt-based graphical user interface. It can record the entire screen or part of it, or record OpenGL applications directly. The recording can be paused and resumed at any time. Many different file formats and codecs are supported . This package contains the GLInject library.

5.13. debian/compat

Ten plik określa poziom kompatybilności debhelpera i obecnie ma zawierać cyfrę 9 . Za co odpowiada ten poziom kompatybilności, to chyba nikt nie wie. xD

5.14. debian/*.links (dh_link)

Ten plik ma na celu tworzenie linków do plików, których nie chcemy bezpośrednio kopiować, bo, jakby nie patrzeć, to zajmuje cenne zasoby dyskowe, poza tym mniej danych trzeba przesłać przez sieć. Poniżej jest przykład takiego linku:

usr/share/man/man1/ansifilter.1.gz usr/share/man/man1/ansifilter-gui.1.gz

Ta linijka stworzy link ansifilter-gui.1.gz do pliku /usr/share/man/man1/ansifilter.1.gz w wynikowej paczce.

5.15. debian/*.lintian-overrides i debian/source/lintian-overrides

Te dwa pliki są wykorzystywane przez narzędzie lintian, które po przeskanowaniu paczek/źródeł wyrzuca komunikaty w przypadku gdy coś odbiega od ustalonego standardu. Niemniej jednak, czasem się zdarza tak, że lintan będzie miał buga, albo też jego błąd tak naprawdę nie będzie żadnym błędem i będzie można cały komunikat zakwalifikować jako false-positive.

W obu przypadkach mamy możliwość ukrycia tych komunikatów, tak by nas już więcej nie niepokoiły. Jeśli problem dotyczy źródeł, będziemy wykorzystywać plik debian/source/lintian-overrides , natomiast jeśli lintian ma problem z jakąś paczką wynikową, wtedy trzeba będzie stworzyć osobny plik z nazwą paczki i sufixem .lintian-overrides . Poniżej przykład.

Źródła powinny zostać zweryfikowane, a to zwykle odbywa się przez sprawdzenie sygnatury gpg. Nie każdy serwis daje nam taką możliwość i nie mamy tak naprawdę żadnego pola manewru w sytuacji gdy twórca źródeł nie podpisał swojego dzieła cyfrowo. Jeśli napotkamy podobny problem, to jako, że komunikat dotyczy źródeł pakietu, wrzucamy poniższą linijkę do pliku debian/source/lintian-overrides :

light-locker source: debian-watch-may-check-gpg-signature

Spora część komunikatów będzie jednak dotyczyć paczek wynikowych. Poniżej jest przykład ukrycia błędu w paczce libssr-glinject . W katalogu debian tworzymy plik libssr-glinject.lintian-overrides i wrzucamy do niego np. coś takiego:

libssr-glinject: shlib-without-versioned-soname usr/lib/*/libssr-glinject.so libssr-glinject.so libssr-glinject: pkg-has-shlibs-control-file-but-no-actual-shared-libs

By stworzyć takie pliki musimy znać komunikat błędu, nazwę paczki oraz nazwę pliku, którego błąd dotyczy. Wszystkie te informacje wypisze nam lintian po przeskanowaniu paczek. Poniżej jest przykład:

W: libssr-glinject: shlib-without-versioned-soname usr/lib/x86_64-linux-gnu/libssr-glinject.so libssr-glinject.so E: libssr-glinject: pkg-has-shlibs-control-file-but-no-actual-shared-libs

Jak widać, praktycznie niczym się te linijki z błędami nie różnią od tego co wpisaliśmy wyżej w pliku, no za wyjątkiem początkowych W: i E: .

Struktura obu powyższych plików jest taka sama i dokładnie opisana jest tutaj .

5.16. source/format

Ten plik określa format źródeł pakietu i z reguły wpisujemy w nim 3.0 (native) dla natywnych debianowych pakietów, oraz 3.0 (quilt) dla wszystkiego innego i zwykle będziemy budować właśnie ten drugi rodzaj, gdzie wszystkie zmiany dokonywane przez nas na źródłach będą rejestrowane i zapisywane w plikach w katalogu debian/patches/ (o nim później). Takie zmiany po wypakowaniu źródeł będą automatycznie nakładane przez dpkg-source .

5.17. source/local-options i source/options

W tych plikach możemy zdefiniować opcje dla narzędzia dpkg-source wywoływanego z parametrami -b lub --print-format . Użyteczne mogą się okazać --compression czy --compression-level , z tym, że dodajemy je do pliku bez tych dwóch myślników na początku, przykładowo:

compression = "bzip2" compression-level = 9

Jedyną różnica między tymi dwoma plikami jest to, że source/local-options nie będzie dołączany w zbudowanych źródłach.

Wszystkie dostępne opcje dla dpkg-source są przystępnie opisane w manualu.

5.18. debian/patches/ i debian/patches/series

Jako, że nie możemy bezpośrednio zmieniać upstreamowych źródeł, musimy robić łatki by przy ich pomocy nanieść pożądane zmiany. Jeśli zmienimy pewnie pliki w źródłach, po czym spróbujemy zbudować taki pakiet, zostanie nam wypisany poniższy komunikat:

... dpkg-source -b monitorix-3.6.0 dpkg-source: info: using source format `3.0 (quilt)' dpkg-source: info: building monitorix using existing ./monitorix_3.6.0.orig.tar.gz dpkg-source: info: local changes detected, the modified files are: monitorix-3.6.0/monitorix dpkg-source: error: aborting due to unexpected upstream changes, see /tmp/monitorix_3.6.0-1.diff.6zxg54 dpkg-source: info: you can integrate the local changes with dpkg-source --commit dpkg-buildpackage: error: dpkg-source -b monitorix-3.6.0 gave error exit status 2 debuild: fatal error at line 1376: dpkg-buildpackage -rfakeroot -d -us -uc -S -sa failed

By zbudować taki pakiet musimy stworzyć łatę przy pomocy dpkg-source --commit .

Jest też jeszcze inne narzędzie, które ułatwia zarządzanie uprzednio stworzonymi patchami i jest to quilt . Pomoże nam on nie tylko w zakładaniu/ściąganiu łat ale również w ich edycji.

Musimy wiedzieć jak działa quilt by sprawnie operować na łatach. Przede wszystkim, mamy do dyspozycji plik debian/patches/series i to w nim są zawarte informacje, jakie patche i w jakiej kolejności mają być założone na źródła. Poniżej przykładowy plik:

disable-update-check

proper-tempfiles

assure-quit-keybinding fix_desktop_file.patch

W katalogu debian/patches/ mamy zaś:

morfik:~/debian_build/minitube-2.3.1$ ls -al debian/patches/ total 28K drwxr-xr-x 2 morfik morfik 4.0K 2015-02-12 20:13:12 ./ drwxr-xr-x 4 morfik morfik 4.0K 2015-02-15 04:55:45 ../ -rw-r--r-- 1 morfik morfik 968 2014-09-05 23:02:33 assure-quit-keybinding -rw-r--r-- 1 morfik morfik 427 2014-09-05 23:02:33 disable-update-check -rw-r--r-- 1 morfik morfik 396 2015-02-12 20:13:12 fix_desktop_file.patch -rw-r--r-- 1 morfik morfik 2.5K 2014-09-05 23:02:33 proper-tempfiles -rw-r--r-- 1 morfik morfik 85 2015-02-12 19:34:19 series

Patche są zakładane w kolejności od góry do dołu z perspektywy pliku debian/patches/series . Zatem pierw zostanie założony patch disable-update-check , potem by został założony proper-tempfiles ale, że jest wykomentowany, to zostanie pominięty, następnie jest zakładany assure-quit-keybinding i tak dalej, aż do końca pliku.

By założyć kolejny patch, korzystamy z quilt push, by ściągnąć obecny patch, dajemy quilt pop . Parametr -a dopisany do obu z powyższych poleceń, odpowiednio założy i ściągnie wszystkie łaty. Jeśli przez przypadek usunęliśmy pliki z patchami ale przy tym uprzednio ich nie ściągnęliśmy, będziemy musieli posłużyć się opcją -f . By sprawdzić, jaki patch jest aktualnie założony, wydajemy quilt applied . Możemy także przeprowadzać różne operacje na samych łatach np. zmieniać ich nazwy. Dobrze jest rzucić okiem na manual quilta , gdzie znajdziemy opis wszystkich przydatnych funkcji. Można również zajrzeć pod ten adres , gdzie znajdziemy opis praktycznego zastosowania tego narzędzia.

5.18.1. Nagłówek łaty

Z bardziej przydatnych rzeczy musimy jeszcze wiedzieć co nieco o edycji nagłówków plików łat. Każdy patch musi bowiem spełniać standard DEP-3 , który definiuje szereg pół wykorzystywanych w nagłówkach.

Generalnie rzecz biorąc, wzór nagłówka wygląda następująco (wygenerowany przez dpkg-source --commit):

Description: <short summary of the patch> TODO: Put a short summary on the line above and replace this paragraph with a longer explanation of this change. Complete the meta-information with other relevant fields (see below for details). To make it easier, the information below has been extracted from the changelog. Adjust it or drop it. . monitorix (3.6.0-1) unstable; urgency=medium . * Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
Author: Mikhail Morfikov <morfik@nsa.com>


The information above should follow the Patch Tagging Guidelines, please checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch> Bug: <url in upstream bugtracker> Bug-Debian: https://bugs.debian.org/<bugnumber> Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber> Forwarded: <no|not-needed|url proving that it has been forwarded> Reviewed-By: <name and email of someone who approved the patch> Last-Update: <YYYY-MM-DD>

Jeśli nie chce nam się wypełniać wszystkich linijek, albo zwyczajnie nie jesteśmy w posiadaniu informacji, które moglibyśmy tam umieścić, możemy ograniczyć się do dwóch obowiązkowych pól, czyli Description: oraz Author (opis i autor) -- resztę kasujemy.

Spotkamy się także z sytuacjami, gdzie ktoś stworzy lub podeśle patch ale nie poda w nim żadnego nagłówka lub informacje w nim będą błędne. Być może nawet sami zapomnimy zmienić powyższy nagłówek, lub zwyczajnie go przeoczymy i nie uwzględnimy w łacie. W takich przypadkach możemy oczywiście dokonać edycji nagłówka, z tym, że dobrze jest to zrobić via quilt header --dep3 -e . Spowoduje to utworzenie domyślnego nagłówka, co ułatwi nam nieco robotę.

5.19. debian/*.examples (dh_installexamples)

Pozycje w tym pliku będą instalowane pod /usr/share/docs/nazwa_paczki/examples/ i generalnie będziemy tutaj umieszczać pliki zawierające przykłady, np. konfiguracji.

5.20. debian/*.templates

Ten plik jest używany do interakcji z użytkownikiem przy instalacji pakietu i odbywa się to przez zadawanie pytań, na które trzeba udzielić odpowiedzi i w oparciu o nie można skonfigurować pakiet. Generalnie rzecz biorąc nie spotkałem się z tym plikiem i za bardzo nic na jego temat nie napiszę. Za to, pod tym linkiem jest przykład jego wykorzystania.

5.21. debian/conffiles (dh_installdeb)

Debian automatycznie oznacza wszystkie pliki w katalogu /etc/ jako pliki konfiguracyjne i ich domyślnie ani nie usuwa przy pozbywaniu się pakietu z systemu ani też nie nadpisuje ich przy instalacji/aktualizacji pakietu. Jeśli się przyjrzymy procesowi budowania paczki, dostrzeżemy tam coś takiego:

... dh_installdeb ... find debian/monitorix/etc -type f -printf '/etc/%P' | LC_ALL=C sort >> debian/monitorix/DEBIAN/conffiles chmod 644 debian/monitorix/DEBIAN/conffiles ...

Dlatego też, nie musimy tworzyć pliku debian/conffiles by powpisywać tam wszystkie pliki konfiguracyjne z katalogu /etc/ . Natomiast, jeśli zajrzymy do paczki wynikowej, zobaczymy tam, że został utworzy plik debian/connfiles i jest tam lista plików, np:

/etc/init.d/monitorix /etc/logrotate.d/monitorix /etc/monitorix/conf.d/debian.conf /etc/monitorix/monitorix.conf /etc/sysconfig/monitorix

By usunąć te pliki trzeba korzystać z opcji purge (np. przy aptitude). Z kolei jeśli chodzi o nowsze wersje tych plików, to sprawdzane są sumy kontrolne i jeśli się różnią, wtedy dostajemy stosowne powiadomienie i podejmujemy akcję dotyczącą ewentualnego nadpisania tego pliku, choć i tak stary (ew. nowy) plik będzie backupowany. Jeśli sumy są takie same, pliki nadpisywane są bez jakiegokolwiek powiadamiania nas o tym, no bo w sumie i tak nie dokonywaliśmy żadnych zmian w tych plikach.

Plik debian/conffiles znajduje jedynie zastosowanie w przypadku gdy konfiguracja budowanego pakietu znajduje się poza katalogiem /etc/ , co zwykle nie powinno mieć miejsca.

5.22. debian/.cron. (dh_installcron)

Czasami zdarzy się tak, że pewna funkcjonalność dostarczana wraz z budowanym pakietem będzie wymagać okresowego wywoływania jakichś operacji. Możemy to osiągnąć przez stworzenie jednego z pięciu (ew. kilku) plików: debian/.cron.hourly , debian/.cron.daily , debian/.cron.weekly , debian/.cron.monthly , debian/*.cron.d . Każdy z tych plików powędruje w określone miejsce w systemie, odpowiednio będzie to katalog /etc/cron.hourly/ , /etc/cron.daily/ , /etc/cron.monthly/ , /etc/cron.weekly/ oraz /etc/cron.d/ . Do pierwszych czterech wrzuca się skrypty, zaś do ostatniego plik, który musi ma być w formacie określonym przez crontab .

5.23. debian/*.logrotate (dh_installlogrotate)

Jeśli nasza paczka będzie zawierać demony, które będą logować zdarzenia, dobrze jest także zadbać o rotację logów, tak by jeden plik nie rozrastał się w nieskończoność. Wszystkie pliki określone w debian/*.logrotate powędrują do /etc/logrotate.d/ , zaś sam format tych plików określony jest w manie.

5.24. debian/.postinst, debian/.postrm, debian/.preinst, debian/.prerm

Te cztery pliki to skrypty maintainera i nie biorą one udziału przy budowaniu pakietu. Za to, potrafią robić pewne rzeczy przy instalowaniu, usuwaniu i aktualizowaniu paczki. To właśnie tutaj dodajemy np. nowego użytkownika, czy nadajemy uprawnienia pewnym plikom. Zwykle nie będziemy musieli tworzyć tych skryptów, jeśli jednak zdecydujemy się na nie, to musimy bardzo uważać, by czasem nie skasować sobie połowy systemu.

Skrypt preinst jest wywoływany przed rozpakowaniem paczki, z kolei skrypt postinst po jej rozpakowaniu. Podobnie z dwoma pozostałymi skryptami -- prerm jest wywoływany przed usunięciem pakietu, a postrm po usunięciu.

Dokładny proces instalowania/deinstalowania/aktualizowania pakietu jest opisany tutaj . Są tam wyszczególnione wszystkie akcje podejmowane podczas powyższych czynności. Z kolei zaś, pod tym linkiem można znaleźć przykłady samych skryptów. Dobrze jest też zajrzeć w katalog debian/ innych pakietów, by podejrzeć jak inni maintainerzy tworzą te skrypty.

5.25. *.desktop

Ten plik nie jest bezpośrednio związany z katalogiem debian/ ale jest bardzo użyteczny w przypadku aplikacji graficznych, bo na jego podstawie mogą zostać utworzone skróty w menu, w które można kliknąć myszą. Format tego pliku jest opisany tutaj. Warto wiedzieć, że istnieje także narzędzie, który może pomóc nam w weryfikacji składni tego pliku. Jest to desktop-file-validate (pakiet desktop-file-utils).

  1. Hardening pakietów

Jeśli nasz pakiet zawierać będzie pliki wykonywalne, trzeba będzie je skompilować i trzeba będzie to zrobić z pewnymi określonymi flagami.

Większość projektów ma już ustawione pewne flagi domyślne, czasem może się zdarzyć tak, że akurat to są te flagi, których my potrzebujemy. Niemniej jednak, mi się przytrafił taki projekt, którego nie szło z początku niczym ruszyć. W przypadku jednej z paczek trzeba było edytować plik makefile , z kolei w przypadku drugiej trzeba było odprawić większe czary ale o tym za moment.

Na sam początek prześledźmy część pliku makefile:

...

Compiler, tools and options

CC = gcc CXX = g++ DEFINES = -DO2 -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED CFLAGS = -pipe -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector --param=ssp-buffer-size=4 -Wall -W -D_REENTRANT $(DEFINES) CXXFLAGS = -pipe -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector --param=ssp-buffer-size=4 -Wall -W -D_REENTRANT $(DEFINES) INCPATH = -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I.. -I. -I. LINK = g++ LFLAGS = -Wl,-O1,--sort-common,--as-needed,-z,relro -Wl,-O1 LIBS = $(SUBLIBS) -L/usr/lib -lQtGui -lQtCore -lpthread AR = ar cqs RANLIB = QMAKE = /usr/bin/qmake-qt4 TAR = tar -cf COMPRESS = gzip -9f COPY = cp -f SED = sed COPY_FILE = $(COPY) COPY_DIR = $(COPY) -r STRIP = strip INSTALL_FILE = install -m 644 -p INSTALL_DIR = $(COPY_DIR) INSTALL_PROGRAM = install -m 755 -p DEL_FILE = rm -f SYMLINK = ln -f -s DEL_DIR = rmdir MOVE = mv -f CHK_DIR_EXISTS= test -d MKDIR = mkdir -p ...

Mamy tam takie linijki jak CFLAGS , CXXFLAGS oraz LFLAGS . To właśnie te pozycje musimy zmienić. To jakie flagi musimy ustawić, możemy odnaleźć na wiki debiana, do poczytania tutaj, tutaj i tutaj . Nie zagłębiając się w szczegóły, zwykle wystarczy dopisać na początku pliku debian/rules , te poniższe linijki:

export DEB_BUILD_MAINT_OPTIONS = hardening=+all DPKG_EXPORT_BUILDFLAGS = 1 include /usr/share/dpkg/buildflags.mk

Po zbudowaniu paczki, możemy sprawdzić czy powyższe rozwiązanie zadziałało i wykorzystujemy do tego celu polecenie hardening-check (pakiet hardening-includes), przykładowo:

$ hardening-check /usr/bin/ansifilter-gui /usr/bin/ansifilter-gui: Position Independent Executable: no, normal executable! Stack protected: no, not found! Fortify Source functions: no, only unprotected functions found! Read-only relocations: no, not found! Immediate binding: no, not found!

Jeśli widzimy log jak powyżej, oznacza to, że flagi nie zostały poprawnie ustawione i trzeba kombinować jak je poprawić. Najłatwiejszym sposobem jest oczywiście edycja flag w plikach źródłowych, z tym, że nie zawsze to działa, np. projekty które są budowane przy pomocy qmake generują sobie plik makefile i co z tego, że przepiszemy flagi, jak podczas budowania, ten plik zostanie nadpisany. Na wiki debiana jest kilka przykładów opisujących min. qmake czy cmake i możemy z nich skorzystać. W tym przypadku (qmake) trzeba było edytować plik .pro i ustawić w nim:

QMAKE_CPPFLAGS *= -g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -fPIE -pie -Wl,-z,relro -Wl,-z,now QMAKE_CFLAGS *= -g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -fPIE -pie -Wl,-z,relro -Wl,-z,now QMAKE_CXXFLAGS *= -g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -fPIE -pie -Wl,-z,relro -Wl,-z,now QMAKE_LFLAGS *= -g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -fPIE -pie -Wl,-z,relro -Wl,-z,now

W każdej linijce zostały zawarte flagi, które zwracał dpkg-buildflags przy ustawieniu hardening=+all, przykładowo:

dpkg-buildflags --status dpkg-buildflags: status: environment variable DEB_BUILD_OPTIONS=parallel=2 dpkg-buildflags: status: environment variable DEB_HOST_ARCH=amd64 dpkg-buildflags: status: vendor is Debian dpkg-buildflags: status: hardening features: bindnow=no format=yes fortify=yes pie=no relro=yes stackprotector=yes stackprotectorstrong=yes dpkg-buildflags: status: qa features: bug=no canary=no dpkg-buildflags: status: reproducible features: timeless=no dpkg-buildflags: status: CFLAGS [vendor]: -g -O2 -fstack-protector-strong -Wformat -Werror=format-security dpkg-buildflags: status: CPPFLAGS [vendor]: -D_FORTIFY_SOURCE=2 dpkg-buildflags: status: CXXFLAGS [vendor]: -g -O2 -fstack-protector-strong -Wformat -Werror=format-security dpkg-buildflags: status: FCFLAGS [vendor]: -g -O2 -fstack-protector-strong dpkg-buildflags: status: FFLAGS [vendor]: -g -O2 -fstack-protector-strong dpkg-buildflags: status: GCJFLAGS [vendor]: -g -O2 -fstack-protector-strong dpkg-buildflags: status: LDFLAGS [vendor]: -Wl,-z,relro dpkg-buildflags: status: OBJCFLAGS [vendor]: -g -O2 -fstack-protector-strong -Wformat -Werror=format-security dpkg-buildflags: status: OBJCXXFLAGS [vendor]: -g -O2 -fstack-protector-strong -Wformat -Werror=format-security

Sprawdzając plik wykonywalny przy pomocy hardening-check , log zmienił się nieco:

$ hardening-check /usr/bin/ansifilter-gui /usr/bin/ansifilter-gui: Position Independent Executable: yes Stack protected: yes Fortify Source functions: yes (some protected functions found) Read-only relocations: yes Immediate binding: yes

I dokładnie o takie coś nam chodzi.

Jeśli mamy problem z ustaleniem jakich flag brakuje, pomocne może okazać się narzędzie blhc . Wszystko czego nam potrzeba by z niego skorzystać, to log z budowania pakietu. Jeśli dysponujemy takowym, brakujące flagi sprawdzamy w poniższy sposób:

$ blhc --color --build build_log W-dpkg-buildflags-missing|CPPFLAGS 16 (of 32) missing|

$ blhc --color build_log CXXFLAGS missing (-g): g++ -c -O2 -fstack-protector-strong -Wformat -Werror=format-security arg_parser.cpp -o arg_parser.o CPPFLAGS missing (-D_FORTIFY_SOURCE=2): g++ -c -O2 -fstack-protector-strong -Wformat -Werror=format-security arg_parser.cpp -o arg_parser.o CXXFLAGS missing (-g): g++ -c -O2 -fstack-protector-strong -Wformat -Werror=format-security stringtools.cpp -o stringtools.o ...

Jak widzimy wyżej, kilku obiektom brakuje flagi -g oraz -D_FORTIFY_SOURCE=2 . Trzeba mieć też na uwadze fakt, że przez taki hardening można nieco popsuć funkcjonalność pakietu.

  1. Budowanie źródeł

Jeśli już dostosowaliśmy wszystkie pliki w katalogu debian/ , przyszedł czas na zbudowanie źródeł. W tym celu przechodzimy do głównego katalogu ze źródłami i wydajemy poniższe polecenie:

morfik:~/debian_build/monitorix-3.6.0$ debuild -S -sa dpkg-buildpackage -rfakeroot -d -us -uc -S -sa dpkg-buildpackage: source package monitorix dpkg-buildpackage: source version 3.6.0-1 dpkg-buildpackage: source distribution unstable dpkg-buildpackage: source changed by Mikhail Morfikov <morfik@nsa.com> dpkg-source --before-build monitorix-3.6.0 fakeroot debian/rules clean dh clean --with systemd dh_testdir dh_auto_clean dh_clean rm -f debian/monitorix.substvars rm -f debian/monitorix..debhelper rm -rf debian/monitorix/ rm -f debian/.debhelper.log rm -f debian/files find . ( ( \( -path .*/.git -o -path .*/.svn -o -path .*/.bzr -o -path .*/.hg -o -path .*/CVS ) -prune -o -type f -a \( -name '##' -o -name '.~' -o -name '~' -o -name DEADJOE \ -o -name '.orig' -o -name '.rej' -o -name '.bak' \ -o -name '..orig' -o -name ..rej -o -name '.SUMS' \ -o -name TAGS -o ( -path '/.deps/' -a -name '*.P' ) \) -exec rm -f {} + ) -o \( -type d -a -name autom4te.cache -prune -exec rm -rf {} + ) ) rm -f *-stamp dpkg-source -b monitorix-3.6.0 dpkg-source: info: using source format `3.0 (quilt)' dpkg-source: info: building monitorix using existing ./monitorix_3.6.0.orig.tar.gz dpkg-source: info: building monitorix in monitorix_3.6.0-1.debian.tar.xz dpkg-source: info: building monitorix in monitorix_3.6.0-1.dsc dpkg-genchanges -S -sa >../monitorix_3.6.0-1_source.changes dpkg-genchanges: including full source code in upload dpkg-source --after-build monitorix-3.6.0 dpkg-buildpackage: full upload (original source is included) Now running lintian... Finished running lintian. Now signing changes and any dsc files... signfile monitorix_3.6.0-1.dsc B820057A

You need a passphrase to unlock the secret key for user: "Mikhail Morfikov <morfik@nsa.com>" 4096-bit RSA key, ID 0x72F3A416B820057A, created 2013-11-13

signfile monitorix_3.6.0-1_source.changes B820057A

You need a passphrase to unlock the secret key for user: "Mikhail Morfikov <morfik@nsa.com>" 4096-bit RSA key, ID 0x72F3A416B820057A, created 2013-11-13

Successfully signed dsc and changes files

Skrypt dbuild , w zależności od konfiguracji, zainicjuje dpkg-buildpackage oraz kilka dodatkowych narzędzi Podczas całego procesu, wszystkie łaty, które założyliśmy, zostaną automatycznie ściągnięte (quilt), a sam katalog debian/ zostanie oddzielony od źródeł i upchnięty w osobnej paczce (dpkg-source). Takie rozwiązanie ma na celu zmniejszenie ruchu sieciowego repozytorium, no bo jeśli aktualizujemy paczkę, to wystarczy pobrać tylko katalog debian/ i nie ma potrzeby przy tym pobierać samych źródeł z repozytorium, które czasami mogą ważyć nawet i dziesiątki czy setki MiB. Same źródła zostaną sprawdzone pod kątem ewentualnych błędów (lintian). Zostaną także wygenerowane trzy dodatkowe pliki: .build , .dsc oraz changes . Po całym procesie pliki .dsc i .changes zostaną podpisane cyfrowo (gpg).

W pliku .build będzie umieszczony log z operacji budowania źródeł -- dokładnie to samo zostanie wydrukowane w terminalu (patrz wyżej).

Plik .dsc zawiera min. sumy kontrole spakowanych źródeł i katalogu debian , poniżej przykład:

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512

Format: 3.0 (quilt) Source: monitorix Binary: monitorix Architecture: any Version: 3.6.0-1 Maintainer: Mikhail Morfikov <morfik@nsa.com> Homepage: http://www.monitorix.org/ Standards-Version: 3.9.6 Vcs-Browser: https://github.com/mikaku/Monitorix Vcs-Git: git://github.com/mikaku/Monitorix.git Build-Depends: debhelper (>= 9), dh-systemd (>= 1.5) Package-List: monitorix deb net optional arch=any Checksums-Sha1: 8cc3ca4335e8df43b869c8c5b1f022e277ccbb2e 235408 monitorix_3.6.0.orig.tar.gz 75fab9bd790637a9e0ad8287655c575b32dca225 5936 monitorix_3.6.0-1.debian.tar.xz Checksums-Sha256: 73097a65554871c66d6e1877ae432acd4a7e4cf35b413a77a15aeed3bb9dd90d 235408 monitorix_3.6.0.orig.tar.gz db873234776c25a1747b619096d9e04422702df63d41fe22b922a80139d0585f 5936 monitorix_3.6.0-1.debian.tar.xz Files: df52ee19d2b117eaf798d0ee99861daf 235408 monitorix_3.6.0.orig.tar.gz df26f7ca9ac0c15fb94409961d75ed18 5936 monitorix_3.6.0-1.debian.tar.xz

-----BEGIN PGP SIGNATURE-----

iQIcBAEBCgAGBQJU6bmwAAoJEM0EaBB3G2UgBaMQALClc5WH/8Xhj3ZZ1IQqkL/J XPcdqCd8ELcn9Az7RhtDcYqdaqddCsm84gQY59lNTspX0g2FLEUPDBcHaHRc224H qpmeQDKwC/Sx/h6VYwVi9Ts+JDP9XG1HcKllBnVmgvEcNdmCYv3rjkt1wHQTrhAm YH7X4EKK5kSxGUc1PEG4+puKG/23AiKuT7dcyMqYWyi1pi2XMkL9CZCpH2aK+UqH 6j348OVxbubqvd7+EnVEUkpkPzHjm54Q9J7J/HhSaWMmm+oWf6eS9F0ZUE/zWOAH 0AuR2MkDpTqNTbPzSNeZIW+NqmHe94dZH7jpv8mYgNai9t5m4uXsUbiYL8/LqcnH 9WBxd5+X/3c+W9fm/Akjjujcz7cvR1LVIJgSyTioi4+OHs6yJo1j7/xp+bkuGJze 31tMS8pLGOxqXOwV5uWta7vEOMs/TbfDjCqGIiZ3Z0j42uyILnZMHE2pj9HUDX/N Xw+CQ/XODlFOoWIx0pPF6pTeCLm/B6c6gc+iablB9Ry1wEmDa3xsVISKptyAFiAl uq/z+HPIRSaQUApn+NArAlry7VPXkO+l5ryKVlRrYXCMMNduywoqlOhrQdh2tDcf BouhfMlR9vkpz2RNU4c9HjTryLXi/bM1zDJ2M0HiKXl6k+tD76ph5viD+qXafnO9 /B1anZdDuD6X30/1E8QG =rs3/ -----END PGP SIGNATURE-----

Na tym etapie, plik .changes zbytnio się nie różni od pliku .dsc ale to w nim będą zawarte sumy kontrole wszystkich wyprodukowanych przez nas paczek. Jest tam również kilka dodatkowych informacji, takich jak np. numery błędów, które ten pakiet ma zamykać. Poniżej przykład:

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512

Format: 1.8 Date: Thu, 29 Jan 2015 20:52:49 +0100 Source: monitorix Binary: monitorix Architecture: source Version: 3.6.0-1 Distribution: unstable Urgency: low Maintainer: Mikhail Morfikov <morfik@nsa.com> Changed-By: Mikhail Morfikov <morfik@nsa.com> Description: monitorix - Web system monitoring tool Closes: 111111 Changes: monitorix (3.6.0-1) unstable; urgency=low . * Initial release (Closes: #111111) Checksums-Sha1: da3fa8ce6465cf65f459c0caa70ea290e944184e 1795 monitorix_3.6.0-1.dsc 8cc3ca4335e8df43b869c8c5b1f022e277ccbb2e 235408 monitorix_3.6.0.orig.tar.gz 75fab9bd790637a9e0ad8287655c575b32dca225 5936 monitorix_3.6.0-1.debian.tar.xz Checksums-Sha256: 10d2986e0e2e8d11a0d87705562f39c51ccaf8bd1a8e1bdc985870f6b053db4e 1795 monitorix_3.6.0-1.dsc 73097a65554871c66d6e1877ae432acd4a7e4cf35b413a77a15aeed3bb9dd90d 235408 monitorix_3.6.0.orig.tar.gz db873234776c25a1747b619096d9e04422702df63d41fe22b922a80139d0585f 5936 monitorix_3.6.0-1.debian.tar.xz Files: 833bed810f8be87ebe0e110720c98aa9 1795 net optional monitorix_3.6.0-1.dsc df52ee19d2b117eaf798d0ee99861daf 235408 net optional monitorix_3.6.0.orig.tar.gz df26f7ca9ac0c15fb94409961d75ed18 5936 net optional monitorix_3.6.0-1.debian.tar.xz

-----BEGIN PGP SIGNATURE-----

iQIcBAEBCgAGBQJU6bm7AAoJEM0EaBB3G2UgQmcP/3lSkkbcVU8rd8ob4PawmWE/ nSOYqWH6zHklmeY8mmKSVK1BRrffzyXN/jf4bX6g2dKVcJI40BcN1JD7Ix8unmFj x/dhb0Q1dc783sc46S+7Jss5ytDieF5lDxsW9vmykep4XRJ/y+pvXH7CicSUCgyR Yl6+CyK1pPxCCJ/5nDMLXeuETvDRfjevPsTO4Nq43KoDHzTy1hmxHaKx6H2z4crt QPs5kLAk5LTesjcZ8Q5XLOq3CrGcnmArvWK3EprNPM7/XNznF0ngaX0iuAg7OPfL CY+rimWL6NVUo5HOO0HwA4Khv5jybmxiEM3lG6G1tQi5sLIYba0jFeDNGYeiYLv8 CatQnnX6DQNOiLmFoAPdp2tu4LAjIe0hU/Y45nBYykR6DgB3OSdXgCRlmuelodyA bC9OEAHr8kPbi84h11l021mDTbQi7yvl7tSpu5INZqYDXtnZcsUADFiCBe5txqAp yhgVRhC0LIhfDF4JWn2zUK8mslV79UJO6wTdrboXI9bq0vOyPQWoooLJxm/vsD0l cNvKLe57VSSV1e8FRl9iVuDoH6UMptumBRRiuH+kbN1m7euGKpq43F6X0tSSoe4s UgmqHL2UbBlS4Yoy9IOkUNbw+XlAg0Px8tVbl9UzLUK0BA8OiJeOR1XnvUKd2rJz Pp74HfHk/n5DlKRDH2L9 =yacn -----END PGP SIGNATURE-----

By podpisać oba te pliki potrzebne będą nam klucze gpg.

  1. Budowanie pakietu

Po zbudowaniu źródeł, przyszedł czas na zbudowanie pakietu. W tym celu przechodzimy do katalogu nadrzędnego (tam gdzie jest plik .dsc) i zaprzęgamy pbuildera do roboty:

morfik:~/debian_build/monitorix-3.6.0$ cd ..

morfik:~/debian_build$ ls -al total 272K drwxr-xr-x 3 morfik morfik 4.0K 2015-02-22 12:12:59 ./ drwxr-xr-x 98 morfik morfik 12K 2015-02-22 10:36:10 ../ drwxr-xr-x 8 morfik morfik 4.0K 2015-02-12 12:38:41 monitorix-3.6.0/ -rw-r--r-- 1 morfik morfik 5.8K 2015-02-22 12:12:43 monitorix_3.6.0-1.debian.tar.xz -rw-r--r-- 1 morfik morfik 1.8K 2015-02-22 12:12:59 monitorix_3.6.0-1.dsc -rw-r--r-- 1 morfik morfik 1.8K 2015-02-22 12:12:59 monitorix_3.6.0-1_source.build -rw-r--r-- 1 morfik morfik 2.1K 2015-02-22 12:12:59 monitorix_3.6.0-1_source.changes -rw-r--r-- 1 morfik morfik 230K 2015-01-31 18:33:24 monitorix_3.6.0.orig.tar.gz

morfik:~/debian_build$ sudo pbuilder --build ./monitorix_3.6.0-1.dsc

W: /root/.pbuilderrc does not exist I: using fakeroot in build. I: pbuilder: network access will be disabled during build I: Current time: Sun Feb 22 12:48:24 CET 2015 I: pbuilder-time-stamp: 1424605704 I: Building the build Environment I: extracting base tarball [/media/Kabi/pbuilder/base.tgz] I: creating local configuration I: copying local configuration I: mounting /proc filesystem I: mounting /run/shm filesystem I: mounting /dev/pts filesystem I: Mounting /media/Kabi/pbuilder/ccache ...

W tej chwili pbuilder wypakowuje przygotowanego wcześniej chroota. Po wypakowaniu sprawdzane i instalowane są zależności:

... I: Installing the build-deps W: no hooks of type D found -- ignoring -> Attempting to parse the build-deps -> Considering build-depdebhelper (>= 9) -> Trying to add debhelper -> Considering build-dep dh-systemd (>= 1.5) -> Trying to add dh-systemd -> Installing debhelper dh-systemd Reading package lists... Done Building dependency tree
Reading state information... Done The following extra packages will be installed: bsdmainutils file gettext gettext-base groff-base intltool-debian libasprintf0c2 libcroco3 libffi6 libglib2.0-0 libicu52 libmagic1 libpipeline1 libunistring0 libxml2 man-db po-debconf Suggested packages: wamerican wordlist whois vacation dh-make augeas-tools gettext-doc groff less www-browser libmail-box-perl Recommended packages: curl wget lynx-cur autopoint libasprintf-dev libgettextpo-dev libglib2.0-data shared-mime-info xdg-user-dirs xml-core libmail-sendmail-perl The following NEW packages will be installed: bsdmainutils debhelper dh-systemd file gettext gettext-base groff-base intltool-debian libasprintf0c2 libcroco3 libffi6 libglib2.0-0 libicu52 libmagic1 libpipeline1 libunistring0 libxml2 man-db po-debconf 0 upgraded, 19 newly installed, 0 to remove and 0 not upgraded. Need to get 0 B/15.8 MB of archives. After this operation, 55.8 MB of additional disk space will be used. ... -> Finished parsing the build-deps ...

Po ich zainstalowaniu, kopiowane są pliki źródłowe do chroota:

... I: Copying source file I: copying [./monitorix_3.6.0-1.dsc] I: copying [./monitorix_3.6.0.orig.tar.gz] I: copying [./monitorix_3.6.0-1.debian.tar.xz] ...

Źródła są następnie wypakowywane i wszystkie łaty są nakładane na nie:

... I: Extracting source ... dpkg-source: info: extracting monitorix in monitorix-3.6.0 dpkg-source: info: unpacking monitorix_3.6.0.orig.tar.gz dpkg-source: info: unpacking monitorix_3.6.0-1.debian.tar.xz dpkg-source: info: applying unfuck_Makefile.patch dpkg-source: info: applying unfuck_Makefile2.patch dpkg-source: info: applying systemd.patch dpkg-source: info: applying fix-manpages.patch ...

Po czym rozpoczyna się właściwa faza budowania pakietu:

... I: Building the package ...

Dalej już tylko są wywoływane poszczególne targety debhelpera (linijki z dh_) i jeśli proces zakończy się bez błędów, zbudowane w ten sposób paczki wędrują do katalogu docelowego. Jest także generowany plik .changes :

... dh_builddeb dpkg-deb --build debian/monitorix .. dpkg-deb: building package monitorix' in../monitorix_3.6.0-1_amd64.deb'. dpkg-genchanges -sa >../monitorix_3.6.0-1_amd64.changes ...

Po zakończeniu, środowisko chroot jest usuwane:

... I: removing directory /media/Kabi/pbuilder/build//34733 and its subdirectories ...

Paczki powinny się znaleźć w tym katalogu, który określiliśmy w konfiguracji pbuildera.

Poniżej jest plik .changes , który został wygenerowany po zbudowaniu pakietu:

Format: 1.8 Date: Thu, 29 Jan 2015 20:52:49 +0100 Source: monitorix Binary: monitorix Architecture: source amd64 Version: 3.6.0-1 Distribution: unstable Urgency: low Maintainer: Mikhail Morfikov <morfik@nsa.com> Changed-By: Mikhail Morfikov <morfik@nsa.com> Description: monitorix - Web system monitoring tool Closes: 111111 Changes: monitorix (3.6.0-1) unstable; urgency=low . * Initial release (Closes: #111111) Checksums-Sha1: 4eec08729e0b7a1bfe2a6e83006c40f725a748b0 944 monitorix_3.6.0-1.dsc 8cc3ca4335e8df43b869c8c5b1f022e277ccbb2e 235408 monitorix_3.6.0.orig.tar.gz 161c6485599777294be7ab420825ed1f29670cca 5896 monitorix_3.6.0-1.debian.tar.xz aed14e43b9604dc0bdfdc54ea05df91edb33d50b 156398 monitorix_3.6.0-1_amd64.deb Checksums-Sha256: 579ae2d225d74ff831aeacf632e597f0c833caf52b2e47ccc7ba2c03aacc6fc4 944 monitorix_3.6.0-1.dsc 73097a65554871c66d6e1877ae432acd4a7e4cf35b413a77a15aeed3bb9dd90d 235408 monitorix_3.6.0.orig.tar.gz fe189dae7e9da596bce6693f0decaa082717c914d4756b7f92f3f79fc76d01c6 5896 monitorix_3.6.0-1.debian.tar.xz 951ddd2ace33cac27cd1c02ec695ffce9cd5e6e2d6758676851003e72969ae83 156398 monitorix_3.6.0-1_amd64.deb Files: da6f05a8071ec0c09c5703a616cbfe2f 944 net optional monitorix_3.6.0-1.dsc df52ee19d2b117eaf798d0ee99861daf 235408 net optional monitorix_3.6.0.orig.tar.gz 5c657b3fb5cf84873f6400317a2c17f2 5896 net optional monitorix_3.6.0-1.debian.tar.xz adede69324183ba2248c093263e06934 156398 net optional monitorix_3.6.0-1_amd64.deb

I jak widzimy, sumy kontrole zostały wygenerowane również dla pakietu .deb. Niemniej jednak, ten plik changes nie został jeszcze podpisany -- musimy to zrobić:

morfik:~/debian_build$ debsign /media/Kabi/pbuilder/result/monitorix_3.6.0-1_amd64.changes signfile /media/Kabi/pbuilder/result/monitorix_3.6.0-1.dsc B820057A

You need a passphrase to unlock the secret key for user: "Mikhail Morfikov <morfik@nsa.com>" 4096-bit RSA key, ID 0x72F3A416B820057A, created 2013-11-13

signfile /media/Kabi/pbuilder/result/monitorix_3.6.0-1_amd64.changes B820057A

You need a passphrase to unlock the secret key for user: "Mikhail Morfikov <morfik@nsa.com>" 4096-bit RSA key, ID 0x72F3A416B820057A, created 2013-11-13

Successfully signed dsc and changes files

Została nam jeszcze ostania rzecz, czyli zweryfikowanie czy stworzona przez nas paczka zawiera jakieś błędy. Wołamy zatem lintiana by sprawdził wszystkie paczki, które znajdzie w wygenerowanym przed chwilą pliku .changes :

morfik:~/debian_build$ rm -R /media/Kabi/pbuilder/lintian/*

morfik:~/debian_build$ lintian --setup-lab

morfik:~/debian_build$ lintian /media/Kabi/pbuilder/result/monitorix_3.6.0-1_amd64.changes

Jeśli chodzi o samego lintiana jeszcze, to dobrze jest usunąć poprzednie katalogi robocze, bo śmieci tam zgromadzone, mogą wpłynąć na wyniki skanowania.

W tym przypadku nie ma żadnych błędów ani ostrzeżeń, zatem paczka została zbudowana pomyślnie i pewnie spełnia wszystkie standardy debiana, co otwiera drogę do umieszczenia jej w oficjalnym repozytorium dystrybucji.

8.1. Manualne budowanie pakietów

Prawdopodobnie zdarzy się tak, że z jakiegoś powodu utkniemy i trzeba będzie przetestować szereg rzeczy, tak by doprowadzić proces budowania pakietu do końca. Jeśli będziemy z każdą drobną poprawką wywoływać pbuildera, to nas szlag trafi w oczekiwaniu na zainstalowanie wszystkich tych zależności w chroocie. Nie chcemy też sobie zaśmiecać systemu tymi zbędnymi pakietami używanymi jedynie przy budowaniu paczki. Mamy do wyboru dwie opcje, z których jedna została opisana już na początku. Druga opcja to skorzystanie z hooka , który jest dostępny w katalogu /usr/share/doc/pbuilder/examples/ . Mowa o C10shell -- umożliwia on przerwanie operacji przy ewentualnych błędach podczas budowania paczki i zrzucenie nas do shella wewnątrz środowiska chroot. Standardowo pbuilder by przerwał akcję i posprzątał po sobie. Linkujemy ten hook:

$ ln -s /usr/share/doc/pbuilder/examples/C10shell /media/Kabi/pbuilder/hooks/

Od tego momentu, jeśli pbuilder napotka błąd, doinstaluje w chroocie min. edytor vim i da nam szansę sprawdzić czemu pakiet się nie zbudował.

Musimy umieć się poruszać wewnątrz środowiska chroot. Przede wszystkim, znajdziemy się w katalogu ze źródłami (tam gdzie jest katalog debian/), z tym, że nasz katalog roboczy zostanie zmieniony nieco:

root@morfikownia:~/monitorix-3.6.0# pwd /tmp/buildd/monitorix-3.6.0

Sama edycja plików nie powinna przysporzyć problemów, jedynie co, to trzeba opanować vima, choć można też i to obejść ale o tym za moment.

Jeśli problemy będą tkwić w ścieżkach plików, zawsze możemy porównać je z tym co wypisał nam debhelper . Przykładowo:

... dh_install -- cp -a ./docs/debian.conf debian/monitorix/etc/monitorix/conf.d/ ...

Powyższy wycinek z logu mówi, że plik debian.conf z folderu ./docs/ (wszystko odbywa się względem naszego katalogu roboczego), czyli w sumie jest to /tmp/buildd/monitorix-3.6.0//docs/debian.conf ma zostać przekopiowany do debian/monitorix/etc/monitorix/conf.d/ . Zajrzyjmy zatem do tego tajemniczego katalogu debian/monitorix/ :

root@morfikownia:~/monitorix-3.6.0# ls -al debian/monitorix total 24 drwxr-xr-x 6 morfik morfik 4096 Feb 22 12:50 . drwxr-xr-x 5 morfik morfik 4096 Feb 22 12:50 .. drwxr-xr-x 6 morfik morfik 4096 Feb 22 12:50 etc drwxr-xr-x 3 morfik morfik 4096 Feb 22 12:50 lib drwxr-xr-x 5 morfik morfik 4096 Feb 22 12:50 usr drwxr-xr-x 3 morfik morfik 4096 Feb 22 12:50 var

Widzimy tutaj, że jest to część struktury folderów, która przypomina tę z naszego systemu operacyjnego. To tutaj właśnie się buduje cały projekt, czyli w odpowiednie miejsca są kopiowane dostarczane z projektem pliki -- cała filozofia budowy pakietu. xD Jeśli z jakiegoś powodu coś nie gra, to tu zaczynamy poszukiwania, oczywiście podpierając się logiem debhelpera.

Gdy już ustalimy w czym tkwił problem, budujemy testowo paczkę, z tym, że korzystamy już bezpośrednio z narzędzia dpkg-buildpackage :

root@morfikownia:~/monitorix-3.6.0# dpkg-buildpackage -uc -us -b ...

Jeśli paczka się zbuduje, znaczy, że możemy opuścić ten chroot.

Co do samego vima -- powyższe środowisko to chroot, zatem mamy dostęp do jego plików z maszyny hosta, wystarczy znaleźć miejsce gdzie się ulokował ten chroot. Miejsce gdzie zaczynamy poszukiwania jest określone w pliku konfiguracyjnym pbuildera. Jako, że środowiska są wypakowywane za każdym razem, tworzone są foldery z numerkami pidów procesu pbuildera, przykładowo:

morfik:~$ ls -al /media/Kabi/pbuilder/build/ total 12K drwx------ 3 morfik morfik 4.0K 2015-02-22 13:49:35 ./ drwx------ 6 morfik morfik 4.0K 2015-02-19 22:13:38 ../ drwxr-xr-x 21 root root 4.0K 2015-02-22 13:49:40 69865/

Jeśli chcielibyśmy w trybie graficznym edytować np. plik debian/rules , to używamy ścieżki /media/Kabi/pbuilder/build/69865/tmp/buildd/monitorix-3.6.0/debian/rules .

8.2. Instalowanie zbudowanego pakietu

Jeśli mamy obawy co do tego jak zachowa się paczka podczas jej instalacji w systemie, możemy skorzystać z narzędzia piuparts , które w środowisku chroot przetestuje wszystkie kombinacje instalacji/deinstalacji i aktualizacji pakietu i zwróci obszerny log na temat modyfikowanych plików. Na końcu zostanie także przedstawione podsumowanie, przykładowo:

piuparts /media/Kabi/pbuilder/result/ansifilter-gui_1.11-1_amd64.deb -b /media/Kabi/pbuilder/base.tgz

0m0.0s INFO: ------------------------------------------------------------------------------ 0m0.0s INFO: To quickly glance what went wrong, scroll down to the bottom of this logfile. 0m0.0s INFO: FAQ available at https://wiki.debian.org/piuparts/FAQ 0m0.0s INFO: The FAQ also explains how to contact us in case you think piuparts is wrong. 0m0.0s INFO: ------------------------------------------------------------------------------ 0m0.0s INFO: piuparts version 0.62 starting up. 0m0.0s INFO: Command line arguments: /usr/sbin/piuparts /media/Kabi/pbuilder/result/ansifilter-gui_1.11-1_amd64.deb -b /media/Kabi/pbuilder/base.tgz 0m0.0s INFO: Running on: Linux morfikownia 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt4-3 (2015-02-03) x86_64 0m0.0s DEBUG: Starting command: ['dpkg', '--info', '/media/Kabi/pbuilder/result/ansifilter-gui_1.11-1_amd64.deb'] ... 1m19.9s INFO: PASS: All tests. 1m19.9s INFO: piuparts run ends.

I to z grubsza by było tyle.

  1. Makulatura

https://www.debian.org/doc/manuals/maint-guide/first.en.html https://www.debian.org/doc/manuals/maint-guide/dreq.en.html https://www.debian.org/doc/manuals/maint-guide/dother.en.html http://raphaelhertzog.com/2012/08/08/how-to-use-quilt-to-manage-patches-in-debian-packages/ https://www.debian.org/doc/debian-policy/index.html https://www.debian.org/doc/manuals/developers-reference/index.html https://wiki.debian.org/IntroDebianPackaging https://dug.net.pl/tekst/297/bezpieczna_konfiguracja_gpg/ https://dug.net.pl/tekst/301/tworzenie_paczek_deb/ https://wiki.debian.org/Hardening https://wiki.debian.org/ReleaseGoals/SecurityHardeningBuildFlags https://wiki.debian.org/HardeningWalkthrough http://debian-handbook.info/browse/stable/sect.building-first-package.html http://liw.fi/manpages/ https://wiki.debian.org/ConfigPackages https://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.html http://dep.debian.net/deps/dep3/ https://lintian.debian.org/manual/

Ręczne kamuflowanie używanego systemu w Iceweasel/Firefox

$
0
0

Odwiedzając stronę internetową przeglądarka wysyła do serwera swoje dane identyfikujące. Dane te zawierają m.in. nazwę systemu operacyjnego używanego przez Internautę, a informacje te mogą posłużyć do stworzenia odcisku palca (fingerprint) identyfikującego daną osobę w sieci. Oprócz tego inne dane strona może wyciągnąć od przeglądarki poprzez obiekt navigator używając języka javascript, a następnie wysłać na serwer. System Linux jest mało popularny, dlatego jeśli nie chcemy wyróżniać się w Internecie warto zmienić informacje wysyłane przez przeglądarkę na takie, które są wysyłane przez przeglądarki uruchomione na systemie Windows.

Na początek spis linków do strona za pomocą których można sprawdzić wysyłane informacje przez naszą przeglądarkę:

  • http://ip-check.info
  • http://www.ip-score.com
  • https://amiunique.org
  • https://panopticlick.eff.org/
  • http://browserspy.dk/browser.php
  • https://duckduckgo.com/?q=my+user+agent&ia=answer

Oprócz tego napisałem prostą stronkę za pomocą której można wyświetlić część eksponowanych światu informacji. Wystarczy zapisać ją w pliku np testUA.html i otworzyć ten plik zapisany na dysku w przeglądarce. Warto zauważyć, że strona ta nie wyświetli wielu informacji identyfikujących, a jedynie te zmieniane w tym HOWTO.

function funkcja(){
NOWALINIA = "\n"

nazwaKodowaAplikacji = navigator.appCodeName;
nazwaAplikacji = navigator.appName;
wersjaAplikacji = navigator.appVersion;
platformaUruchomieniowaFF = navigator.platform;
identyfikatorBudowy = navigator.buildID;
oscpu = navigator.oscpu;
jezyk = navigator.language;
producent = navigator.vendor;
producentSub = navigator.vendorSub;
uAgent = navigator.userAgent;
produkt = navigator.product;
produktSub = navigator.productSub;


zmienna = "nazwaKodowaAplikacji:" + nazwaKodowaAplikacji + NOWALINIA +"nazwaAplikacji:" + nazwaAplikacji + NOWALINIA +"wersjaAplikacji:" +  wersjaAplikacji + NOWALINIA +"platformaUruchomieniowaFF:" + platformaUruchomieniowaFF + NOWALINIA +"identyfikatorBudowy:" + identyfikatorBudowy + NOWALINIA +"oscpu:" + oscpu + NOWALINIA +"jezyk:" + jezyk + NOWALINIA +"UserAgent:" + uAgent + NOWALINIA +"producent:" + producent + NOWALINIA +"producentSub:" + producentSub + NOWALINIA +"produkt:" + produkt + NOWALINIA +"produktSub:" + produktSub;
alert(zmienna);
return true;
}




Kliknij!

A więc zaczynamy. W tym FAQ podam jakimi wpisami warto się zainteresować, a także przykładowe wpisy upodabniające przeglądarkę do Firefox 37 uruchomionego na Windowsie 8.1. Warto pamiętać, że co 6 tygodni wydana zostaje nowa wersja Firefoksa, co oznacza że wpisy się dosyć szybko deaktualizują. Otwieramy stronę, na której będziemy zmieniać ustawienia przeglądarki: w pasek adresu wpisujemy about:config na stronie, która się otworzy wpisy dodaje się poprzez kliknięcie prawym przyciskiem myszy na obszar z wpisami, wybraniu z menu kontekstowego "Dodaj ustawienie typu" ->"Łańcuch (string)". Wartości wpisów już istniejących zmienia się klikając na nie dwukrotnie. A więc zmieniamy:

general.useragent.override na "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0"
general.useragent.override.[site_address] wartość # dla konkretnej strony
general.oscpu.override na "Windows NT 6.3; WOW64"
general.platform.override na "Win32"
general.appversion.override na "5.0 (Windows)"
general.buildID.override na "20150402191859"

Druga linijka pozwala ustawić UA wysyłany konkretnej stronie i można ją pominąć.

Co przez to osiągnęliśmy? Administrator strony na którą wchodzimy widzi w logu fałszywe informacje o systemie. Przeglądarka dalej nie blokuje reklam, szpiegujących elementów ładowanych z serwerów firm zarabiających na sprzedawaniu naszych danych, danych wysyłanych przez wtyczki takie jak np Flash Player. Informację o systemie serwer mógłby uzyskać analizując wysyłane pakiety TCP, gdyż różne systemy operacyjne odrobinę inaczej liczą numery wpisywane do nagłówka pakietu (mimo to wszystkie są zgodne z RFC).

Serwer Radicale czyli sposób na zsynchronizowany kalendarz i książkę adresową używając np. Thunderbirda na Windowsie i Linuksie

$
0
0

Serwer Radicale to aplikacja, które zapewnia za pomocą protokołów CalDav i CardDav usługi przechowywania i synchronizacji kalendarzy i książek adresowych. Obecnie wiele programów potrafi z niego korzystać m.in. Evolution, a używając odpowiednich wtyczek również Thunderbird. W tym HOWTO przedstawię jak na Linuksie i Windowsie uruchomić ten serwer, a także jak sprawić by móc z jego możliwości korzystać w klientach poczty Thunderbird i Evolution. Użyte w tym poradniku oprogramowanie:

Debian Jessie 8 amd64, Icedove 31.5.0-1 amd64 z repozytorium, serwer Radicale z repowersja 0.9-1

Windows 8.1 64 bit, zainstalowany 64 bitowy Python 2.7.9, serwer Radicale 0.9

W konfiguracji zastosowano HTTP basic access authentication do celu zachowania porządku. Oprócz tego różne klienty różnie implementują protokoły i czasem podczas zapisywania zmian potrafiły stworzyć duplikaty i przed tym można się ochronić w.w. uwierzytelnianiem. Poniższa konfiguracja nakazuje nasłuchiwania na interfejsie wewnętrznym, także nie będzie możliwe nawiązanie bezpośredniego połączenia z zewnątrz. Sugerowałbym jednak zabezpieczenie tego portu (zablokowanie nawiązywania połączeń na nim na interfejsach innych niż lo) również na firewallu. Dodatkowo wyłączona jest szyfrowana transmisja danych poprzez https i uwierzytelnianie serwera. Jeśli chcemy połączyć się zachowując tajność danych z serwerem nie zmieniając jego konfiguracji, możemy przekierować porty na tunel SSH. Więcej o tej metodzie tutaj.

Dane będą przechowywane w plikach tekstowych na partycji z systemem plików NTFS zamontowanej w katalogu /dyskF/ na Linuksie lub P:\ pod Windowsem. Dokładna ścieżka do kolekcji kalendarzy i książek adresowych: /dyskF/Radicale/collections lub P:\Radicale\collections.

Radicale na systemie Debian Jessie Gnu/Linux

Na początek oczywiście instalujemy serwer Radicale i tworzymy katalog dla naszej konfiguracji.

#apt-get install radicale
#mkdir /etc/default/radicaleKatalog

A co z katalogiem, w którym Radicale ma zapisywać dane?

Instalujemy również Thunderbird lub Icedove. Co i jak zainstalować zostawiam czytelnikowi.

Konfiguracja serwera Radicale. Konfigurację serwera należy zapisać do odpowiednich plików edytorem np nano uruchomionym na koncie roota.

Zawartość /etc/default/radicaleKatalog/config

# -*- mode: conf -*-
# vim:ft=cfg

# Plik konfiguracyjny dla Radicale - Prostego serwera kalendarza
#
# Umieść go w /etc/radicale/config (globalnie)
# lub ~/.config/radicale/config (konfiguracja lokalnego użytkownika)
# Konfiguracja do użytku osobistego, a nie dla np firmy. Brak uwierzytalniania autentyczności
# tożsamości przez serwer Radicale. Hasło używane dla zachowania porządku, by programy nie zaczęły
# nawzajem zmieniać sobie wpisów

[server]
# Adres IPv4 i port na którym nasłuchuje serwer.
hosts = 127.0.0.1:5232
# Flaga ustawiająca tryb działania w trybie daemon - używa forkowania procesów. Działa tylko na systemach Uniksopodobnych
daemon = True
# Ścieżka do pliku przechowującego numer identyfikujący proces Radicale
pid="/var/run/radicale/radicale.pid"
# Czy uruchomić działania poprzez protokół https
ssl = False
# Czy używać odwróconego DNS by w logach zapisać rozwiązany adres domenowy klienta
dns_lookup = False
# URL korzenia drzewa zasobów CalDAV i CardDav na serwerze Radicale
base_prefix = /
# Wiadomość wyświetlana u użytkownika klienta, gdy wyświetlana jest prośba o podanie hasła
realm = Serwer Radicale wymaga podania hasła, by móc kontynuować

[encoding]
# Kodowanie znaków w odpowiedziach na żądania
request = utf-8
# Kodowanie znaków przechowywanych danych
stock = utf-8

[auth]
# Metoda uwierzytelniania użytkownika
# Wartości: None | htpasswd | IMAP | LDAP | PAM | courier | http | remote_user | custom
type = htpasswd

# Ścieżka do pliku Htpasswd
htpasswd_filename = /etc/default/radicaleKatalog/users
# Sposób hashowania hasła w htpasswd
# Wartości: plain | sha1 | crypt
# Plain to nie hashowane. Nie używa się go do tajnych haseł, ale w tym przypadku hasło w Radicale jest tylko do uniemożliwienia
# niektórym klientom wprowadzać niepotrzebne zmiany. Bardziej to pomoc przy zachowaniu porządku niż zapewnienie bezpieczeństwa.
htpasswd_encryption = plain


[git]
# Opcje git-a
# Wysyłający aktualizację
committer = Radicale

[rights]
# Backend odpowiadający za uprawnienia
# Wartości: None | authenticated | owner_only | owner_write | from_file | custom
type = from_file
# Plik zapewniający informację o prawach, gdy używamy opcji from_file
file = /etc/default/radicaleKatalog/rights


[storage]
# Backend odpowiadający za przechowywanie danych
# Wartości: filesystem | multifilesystem | database | custom
type = filesystem
# Katalog do przechowywania kolekcji danych. Zostanie utworzony, jeśli nie istnieje.
filesystem_folder = /dyskF/Radicale/collections

[logging]
# Plik konfigurujący logowanie
# Jeśli nie podano pliku z konfiguracją, prosta informacja jest wyświetlana na standardowym wyjściu
# Jeśli chcesz wiedzieć więcej o składni pliku z konfiguracyjnego, przeczytaj:
# http://docs.python.org/library/logging.config.html
config = /etc/default/radicaleKatalog/logging
# Ustaw, by poziom logowania nie był debug (co oznacza, że będzie logował niewiele informacji_
debug = False

Zawartość pliku /etc/default/radicaleKatalog/users. W pliku tym wpisujemy loginy i hasła do HTTP basic access authentication.

uzytkownik:tajneHasloUzytkownika
gosc:gosc

Zawartość pliku /etc/default/radicaleKatalog/rights. Właściciel jest ustalany poprzez ścieżkę dostępu do zasobu (kalendarza/książki adresowej)

# Pozwój wszystkim odczytywać wszelkie kolekcje danych, nawet użytkownikowi nieautoryzowanemu (anonymous)
[allow-everyone-read]
user: .*
collection: .*
permission: r

# Nadaj uprawnienia do zapisu właścicielom
[owner-write]
user: .+
collection: ^%(login)s/.+$
permission: rw

Zawartość pliku /etc/default/radicaleKatalog/logging. Tutaj nudne ustawienia dotyczące logowania informacji.

# -*- mode: conf -*-
# vim:ft=cfg
# Plik konfigurujący logowanie w Radicale
#
#
# Inne uchwyty są dostępne. By znaleźć o nich więcej informacji, zajrzyj na:
# http://docs.python.org/library/logging.config.html


# Loggers, handlers and formatters keys

[loggers]
# Loggers names, main configuration slots
keys = root

[handlers]
# Logging handlers, defining logging output methods
keys = console,file

[formatters]
# Logging formatters
keys = simple,full


# Loggers

[logger_root]
# Root logger
level = DEBUG
handlers = file
# Enable the following instead if you also want console logging
#handlers = console,file


# Handlers

[handler_console]
# Console handler
class = StreamHandler
level = DEBUG
args = (sys.stdout,)
formatter = simple

[handler_file]
# File handler
class = FileHandler
args = ('/var/log/radicale/radicale.log',)
level = INFO
formatter = full


# Formatters

[formatter_simple]
# Simple output format
format = %(message)s

[formatter_full]
# Full output format
format = %(asctime)s - %(levelname)s: %(message)s

Tworzymy katalog, w którym przechowywana będzie kolekcja kalendarzy i książek adresowych:

mkdir /dyskF/Radicale/collections/ -p
chown radicale:radicale /dyskF/Radicale/collections/

Na koniec edytujemy plik /etc/default/radicale

# Linijka ta pozwala uruchomić usługę Radicale podczas startu systemu
ENABLE_RADICALE=yes

# Opcja dla Radicale, każąca czytać plik konfiguracyjny z odpowiedniej ścieżki
RADICALE_OPTS="--config=/etc/default/radicaleKatalog/config"

# Spraw by skrypt init był głośny (wypisywał dużo informacji)
# (Adnotacja: To sprawia, żę tylko skrypt init jest głośny, nie serwer sam w sobie)
VERBOSE=yes

Jak już pisałem, można dodatkowo zabezpieczyć serwer przed połączeniami na ten port na firewallu. Przykładowa regułka, która jednak powinna być za każdym razem przy bootowaniu systemu uruchamiana:

iptables -I INPUT 1 -p tcp ! -i lo  --dport 5232 -j REJECT

Przydzielamy odpowiednie uprawnienia dla pliku users

chown radicale:radicale /etc/default/radicaleKatalog/users
chmod u=rw,g=,o= /etc/default/radicaleKatalog/users

Uruchamiamy serwer Radicale:

/bin/systemctl restart radicale && echo "Sukces" || echo "Porażka"

Czy jakiś program słucha na porcie 5232 można sprawdzić poleceniem:

ss -ntlup | grep 5232

Za pomocą Gita zapisujemy historię zmian

/bin/systemctl stop radicale
#apt-get install python-dulwich
cd /dyskF/Radicale/collections/
git init

To wszystko. Radicale będzie korzystał z Gita (poprzez dulwich) do zapisywania wszelkich zmian. Za pomocą

git log

można odczytać historię zmian (daty zmian).

git log -4

Pokaże ostatnie cztery zmiany w kolekcjach. Gdy odczytamy numery interesujących commitów, można obejrzeć co robiły wpisując polecenie:

git diff długiNumerHeksadecymalnyCommitu^ długiNumerHeksadecymalnyCommitu pokaże co zmienił

Uruchamiamy ponownie serwer Radicale:

/bin/systemctl start radicale && echo "Sukces" || echo "Porażka"

Thunderbird - wyłączanie sprawdzania zgodności wersji dodatku z wersją klienta poczty.

Czasem może zajść potrzeba, by wyłączyć sprawdzanie zgodności dodatku np. gdy korzystamy z wersji beta klienta poczty. Oczywiście czasem może to być ryzykowne, tj. wtyczka przestanie działać stabilnie.

W Thunderbird/Icedove wyświetlamy menu (przycisk z trzema poziomymi liniami) -> Preferencje -> Preferencje. W nowo otwartym oknie Zakładka Zaawansowane, podzakładka Ogólne. Przycisk edytor ustawień.

Prawym przyciskiem myszy klikamy na obszarze z listą ustawień. Dodaj ustawienie typu -> Wartość logiczna (Boolean). Dla wersji programu Thunderbird 37.0 lub 37.0.1 wpisujemy nazwę

extensions.checkCompatibility.37.0 i wartość False

Thunderbird/Icedove instalacja dodatku Lightning (kalendarz) i połączenie z Radicale

Przechodzimy na stronę www pozwalającą pobrać dodatek Lightning Pobieramy dodatek za pomocą przeglądarki i zapisujemy w jakimś miejscu na dysku. Następnie w Thunderbird/Icedove wyświetlamy menu (przycisk z trzema poziomymi liniami) -> Dodatki (Add-ons). W otworzonej zakładce klikamy na przycisk obok pola wpisywania tytułu szukanego dodatku (przycisk z trzema ? wajchami ? o możliwości ruchu w górę i dół) -> Zainstaluj dodatek z pliku (Install Add-on from file) i wybieramy pobrany plik. Po instalacji uruchamiamy ponownie Thunderbird/Lightning.

Po udanej instalacji dodatku w oknie klienta poczty w prawym górnym rogu, pod przyciskiem X pozwalającym wyłączyć go, pojawiły się ikony pozwalające przejść do kalendarza i listy zadań. Klikamy na ikonę kalendarza. Pojawia się nowa zakładka. W lewej dolnej części okna (pod istniejącym już domyślnym kalendarzem) klikamy prawym przyciskiem myszy, wybieramy Nowy kalendarz (New Calendar). W oknie, które powinno się pojawić, wybieramy kalendarz zdalny (on the network), następnie CalDav i podajemy ścieżkę w formacie:

http://login:haslo@domena:numerPortu/wlasciciel/nazwaKalendarza.ics/

w tym poradniku przyjmuję:

login to uzytkownik

haslo to tajneHasloUzytkownika

domena to adres IP loopback (pętli zwrotnej) czyli 127.0.0.1

numerPortu to 5232

wlasciciel to uzytkownik

nazwaKalendarza to glownyKalendarz

Należy pamiętać o slashu na końcu, gdyż wskazujemy na katalog! W takim razie ścieżka, którą wpisujemy do pola przyjmie postać:

http://uzytkownik:tajneHasloUzytkownika@127.0.0.1:5232/uzytkownik/glownyKalendarz.ics/

Następnie wpisujemy nazwę np. Główny kalendarz. Można zakończyć tworzenie kalendarza. Można teraz odznaczyć poprzedni kalendarz i pozostawić zaznaczony tylko nowo utworzony.

Thunderbird/Icedove instalacja dodatku SOGo Connector (książka adresowa) i połączenie z Radicale

SOGo Connector jest dodatkiem, który pozwala tworzyć książkę adresową zsynchronizowaną z serwerem za pomocą protokołu CardDav. Został napisany przez Inverse inc. Można go pobrać z repozytorium (pakiet nazywa się xul-ext-sogo-connector) lub ze strony tej lub tej. Podobnie jak w przypadku wcześniejszego dodatku pobieramy plik na dysk (obecnie najnowsza wersja sogo-connector-31.0.1.xpi), a następnie w Thunderbirdzie/Icedove instalujemy dodatek i restartujemy klienta poczty.

W kliencie poczty z menu wybieramy Narzędzia -> Książka adresowa (lub skrót na klawiaturze ctrl-shift-b). W nowo otworzonym oknie wybieramy Plik -> Utwórz -> Remote Address Book. Wpisujemy nazwę np. Główna książka adresowa i ścieżkę dostępu (URL) w formacie takim jak poprzednio, oprócz końcówki. Tym razem ścieżka przyjmie postać:

http://uzytkownik:tajneHasloUzytkownika@127.0.0.1:5232/uzytkownik/glownaKsiazkaAdresowa.vcf/

Ja zwykle zaznaczam jeszcze opcję "Show notifications when saving a card". Klikamy ok. W tym momencie można ręcznie jeszcze wymusić synchronizację (która powinna jednak już być) przez kliknięcie prawym przyciskiem myszy na nazwę nowo utworzonej książki adresowej w lewym obszarze okna i wybranie Synchronize.

Możemy utworzyć nową wizytówkę. Po jej wypełnieniu i zatwierdzeniu powinna się pojawić chmurka z napisem: "1 upload, 0 download, 0 delete".

Integracja kalendarza w kliencie poczty Evolution, a co za tym idzie również i aplecie kalendarza w środowisku graficznym Gnome 3.

W środowisku graficznym Gnome 3 na środku górnej belki znajduje się początek nazwy dnia tygodnia i aktualny czas. Gdy się na ten napis kliknie wyświetli się aplet kalendarza. Użytkownicy Gnome powinni być zadowolenie z możliwości integracji kalendarza z serwerem Radicale i co za tym idzie wyświetlaniem się w nim wydarzeń wprowadzonych w kalendarzu Lightning w kliencie poczty Thunderbird/Icedove.

Uruchamiamy program Evolution. W lewym dolnym obszarze okna Evolution klikamy na Kalendarz. Następnie wybieramy: Plik -> Nowy -> Kalendarz. Typ: CalDav. Nazwa np. Główny kalendarz. Zaznaczmy: "Ustaw jako domyślny kalendarz". Adres URL tym razem bez loginu i hasła czyli ścieżka ma wyglądać tak:

http://127.0.0.1:5232/uzytkownik/glownyKalendarz.ics/

Jako użytkownik możemy podać gosc lub uzytkownik w zależności od tego czy chcemy móc edytować kalendarz w Evolution. Ja nie chcę, więc wybrałem gosc. Proponuję zmniejszyć odstęp czasowy odświeżania kalendarza do kilku minut.


Serwer Radicale na systemie Windows 8.1 64 bit

Instalacja Pythona 2.*

Ze względu na to, że serwer Radicale napisany jest w Pythonie, należy zainstalować jego interpreter. Według dokumentacji dla użytkownika działa on na wersjach 2.7 i wielu wersjach 3.*, ale dodatki najlepiej działają z wersją 2.7.*, dlatego polecam taką zainstalować. Podczas instalacji wersji 2.7 miałem problem. Strona odsyłała do wersji 32 bitowej instalatora msi. Po jej zainstalowaniu nie udało się go uruchomić. Po próbie odinstalowania (nie zakończonej powodzeniem), a następnie instalacji 64 bitowej wersji interpretera udało się uruchomić interpreter. Polecam się zainstalować z gałęzi 2.7.* najnowszą wersję 64 bit dla 64 bitowych systemów ze strony. Plik obecnie nazywa się python-2.7.9.amd64.msi

Jeśli chodzi o sam proces instalacji Pythona, to wartości domyślne są prawie ok, to znaczy warto zaznaczyć Add python.exe to Path.

Pobieranie i rozpakowanie/instalowanie Radicale

Strona obecnie wyświetla do pobrania najnowszą wersję 1.0, ale ze względu na to, że na Debianie zainstalowana wersja to 0.9, również tutaj pobiorę 0.9.

Pobrany plik należy rozpakować. Ja rozpakowałem go do C:\Program Files\, więc po rozpakowaniu w katalogu C:\Program Files\Radicale-0.9\ mam m.in. plik README.

Pliki konfiguracyjne

Do tworzenia i edycji plików używałem programu notepad++.

Plik C:\Program Files\Radicale-0.9\config

# -*- mode: conf -*-
# vim:ft=cfg

# Plik konfiguracyjny dla Radicale - Prostego serwera kalendarza
# Windows
#
# Umieść go w /etc/radicale/config (globalnie)
# lub ~/.config/radicale/config (konfiguracja lokalnego użytkownika)
# Konfiguracja do użytku osobistego, a nie dla np firmy. Brak uwierzytalniania autentyczności
# tożsamości przez serwer Radicale. Hasło używane dla zachowania porządku, by programy nie zaczęły
# nawzajem zmieniać sobie wpisów

[server]
# Adres IPv4 i port na którym nasłuchuje serwer.
hosts = 127.0.0.1:5232
# Flaga ustawiająca tryb działania w trybie daemon - używa forkowania procesów. Działa tylko na systemach Uniksopodobnych
daemon = False
# Ścieżka do pliku przechowującego numer identyfikujący proces Radicale
#pid="/var/run/radicale/radicale.pid"
# Czy uruchomić działania poprzez protokół https
ssl = False
# Czy używać odwróconego DNS by w logach zapisać rozwiązany adres domenowy klienta
dns_lookup = False
# URL korzenia drzewa zasobów CalDAV i CardDav na serwerze Radicale
base_prefix = /
# Wiadomość wyświetlana u użytkownika klienta, gdy wyświetlana jest prośba o podanie hasła
realm = Serwer Radicale wymaga podania hasła, by móc kontynuować

[encoding]
# Kodowanie znaków w odpowiedziach na żądania
request = utf-8
# Kodowanie znaków przechowywanych danych
stock = utf-8

[auth]
# Metoda uwierzytelniania użytkownika
# Wartości: None | htpasswd | IMAP | LDAP | PAM | courier | http | remote_user | custom
type = htpasswd

# Ścieżka do pliku Htpasswd
htpasswd_filename = C:\Program Files\Radicale-0.9\users
# Sposób hashowania hasła w htpasswd
# Wartości: plain | sha1 | crypt
# Plain to nie hashowane. Nie używa się go do tajnych haseł, ale w tym przypadku hasło w Radicale jest tylko do uniemożliwienia
# niektórym klientom wprowadzać niepotrzebne zmiany. Bardziej to pomoc przy zachowaniu porządku niż zapewnienie bezpieczeństwa.
htpasswd_encryption = plain


#[git]
# Opcje git-a
# Wysyłający aktualizację
#committer = Radicale

[rights]
# Backend odpowiadający za uprawnienia
# Wartości: None | authenticated | owner_only | owner_write | from_file | custom
type = from_file
# Plik zapewniający informację o prawach, gdy używamy opcji from_file
file = C:\Program Files\Radicale-0.9\rights


[storage]
# Backend odpowiadający za przechowywanie danych
# Wartości: filesystem | multifilesystem | database | custom
type = filesystem
# Katalog do przechowywania kolekcji danych. Zostanie utworzony, jeśli nie istnieje.
filesystem_folder = P:\Radicale\collections

[logging]
# Plik konfigurujący logowani
# Jeśli nie podano pliku z konfiguracją, prosta informacja jest wyświetlana na standardowym wyjściu
# Jeśli chcesz wiedzieć więcej o składni pliku z konfiguracyjnego, przeczytaj:
# http://docs.python.org/library/logging.config.html
config = C:\Program Files\Radicale-0.9\logging
# Ustaw, by poziom logowania nie był debug (co oznacza, że będzie logował niewiele informacji)
debug = False

Plik C:\Program Files\Radicale-0.9\users

uzytkownik:tajneHasloUzytkownika
gosc:gosc

Plik C:\Program Files\Radicale-0.9\rights

# Pozwój wszystkim odczytywać wszelkie kolekcje danych
[allow-everyone-read]
user: .*
collection: .*
permission: r

# Nadaj uprawnienia do zapisu właścicielom
[owner-write]
user: .+
collection: ^%(login)s/.+$
permission: rw

Plik C:\Program Files\Radicale-0.9\logging

# -*- mode: conf -*-
# vim:ft=cfg

# Plik konfigurujący zapisujący informacje Radicale na Windowsie
#
# Jeśli chcesz więcej informacji, przeczytaj:
# http://docs.python.org/library/logging.config.html


# Loggers, handlers and formatters keys

[loggers]
# Loggers names, main configuration slots
keys = root

[handlers]
# Logging handlers, defining logging output methods
keys = console,file

[formatters]
# Logging formatters
keys = simple,full


# Loggers

[logger_root]
# Root logger
level = DEBUG
handlers = file
# Enable the following instead if you also want console logging
#handlers = console,file


# Handlers

[handler_console]
# Console handler
class = StreamHandler
level = DEBUG
args = (sys.stdout,)
formatter = simple

[handler_file]
# File handler
class = FileHandler
args = ('P:/Radicale/logi/radicale.log',)
level = INFO
formatter = full


# Formatters

[formatter_simple]
# Simple output format
format = %(message)s

[formatter_full]
# Full output format
format = %(asctime)s - %(levelname)s: %(message)s

Przykład blokowania połączeń przychodzących na port 5232

Ze względu na to, że serwer Radicale będzie nasłuchiwał połączeń przychodzących, warto zablokować połączenia na jego port z zewnątrz. To tylko przykład. To czy odpowiednio zadziała zależy od tego, jak skonfigurowany jest firewall w Windowsie:

netsh advfirewall firewall add rule name="Port Radicale" dir=in action=block protocol=TCP localport=5232 interfacetype=wireless,lan,ras

Tworzenie usługi Radicale

Ze względu na to, że chcemy niedługo po uruchomieniu systemu mieć dostęp do kalendarza i książki adresowej bez dodatkowego klikania, najlepiej rozwiązać uruchamianie serwera jako usługi.

Potrzebny będzie nam program open source zwany NSSM - the Non-Sucking Service Manager. Ja pobrałem go stąd w wersji 2.24. Program pobieramy, rozpakowujemy programem do rozpakowywania archiwów do jakiegoś katalogu (tymczasowo). Z katalogu tego, zależnie od wersji systemu (32 czy 64 bit) wchodzimy do katalogu win64 lub win32 i kopiujemy plik nssm.exe do katalogu C:\Windows\System32. Zainstalowaliśmy nssm.

Tworzymy usługę. Tworzymy katalog C:\Windows\uslugi. W nim umieszczamy plik radicale.bat (zwróć uwagę na rozszerzenie) z zawartością:

C:\Python27\python.exe  "C:\Program Files\Radicale-0.9\radicale.py" --config="C:\Program Files\Radicale-0.9\config"

Za pomocą nssm tworzymy z tego usługę. Wykonujemy polecenia:

nssm install Radicale C:\Windows\uslugi\radicale.bat
nssm set Radicale AppDirectory P:\Radicale
nssm set Radicale AppPriority BELOW_NORMAL_PRIORITY_CLASS
nssm set Radicale Start SERVICE_DELAYED_AUTO_START
nssm start Radicale

Aby sprawdzić czy usługa działą (według nssm) wykonaj:

nssm status Radicale

Aby sprawdzić czy jakiś program nasłuchuje na porcie 5232 (jeśli port jest zablokowany na firewallu, nie oznacza to możliwości połączenia z zewnątrz):

netstat -ao | findstr 5232

Aby sprawdzić czy uruchomiony jest jakiś proces zawierający w którymś miejscu (nazwa, argumenty) wyraz radicale:

wmic process list  | findstr /I radicale

Przekierowanie połączenia na określony port przez szyfrowany tunel za pomocą OpenSSH

$
0
0

Oprogramowanie użyte w tym poradniku Debian Jessie 8 amd64 OpenSSH_6.7p1 Debian-3

Czasem zdarza się, że aplikacje komunikują się przez sieć, jednak nie posiadają one możliwości dokonania bezpiecznego połączenia (m.in. szyfrowanego). Może być też tak, że nie jesteśmy pewni wykonania kodu odpowiedzialnego za przesyłanie i wolelibyśmy użyć czegoś bardziej sprawdzonego. Jednym z lepiej sprawdzonych programów jest OpenSSH. Za jego pomocą można bezpiecznie przesyłać dane.

W tym HOWTO przedstawię, jak połączyć za pomocą dwa zaufane komputery poprzez niezaufaną sieć. Od razu chcę zaznaczyć, że o ile konto do którego zalogowany przez OpenSSH użytkownik nie będzie kontem roota, to jest ono potencjalnie niebezpieczne, dlatego nie należy go przydzielać nikomu komu nie ufamy. Załóżmy więc, że w ten sposób łączymy tylko dwa własne komputery.

Jak to wygląda? Na pewno musimy mieć serwer i klient, łączące się poprzez sieć. Normalnie więc wyglądałoby to tak:

serwer <Niezaufana Sieć> klient

Można jednak skorzystać z OpenSSH i wtedy będzie wyglądało to tak:

serwer<loopback>zdalny OpenSSH(port 33773) <Niezaufana Sieć> lokalny OpenSSH<loopback>klient

Instancja sshd po stronie serwera będzie uruchomiona na koncie zwykłego użytkownika i logowanie do niej będzie udostępnione osobie, której ufamy na tyle by pokazać i pozwolić zmieniać nasz kalendarz i książkę adresową, ale nie na tyle by przekazać jej uprawnienia roota.

Instalujemy potrzebne pakiety:

apt-get install openssh-server openssh-client

Na początku tworzymy instancję OpenSSH po stronie serwera. Załóżmy, że serwer i klient nasłuchują tak, jak w przypadku poradnika o Radicale tj serwer aplikacji nasłuchuje na porcie 5232 tylko na interfejsie wewnętrznym. Stworzona instancja OpenSSH po stronie serwera nasłuchuje na porcie 33773 i pozwala łączyć się zaufanym osobom poprzez niezaufaną sieć do serwera Radicale. Na komputerze klienckim uruchomiony jest, oprócz normalnego klienta Kalendarza, klient OpenSSH. Klient OpenSSH pozwala łączyć się poprzez siebie do serwera OpenSSH i razem z nim współpracując tworzą bezpieczny tunel poprzez niezaufaną sieć. Klient Kalendarza łączy się z lokalnym klientem OpenSSH i nawet nie widzi, co dzieje się dalej.

Na początku tworzymy nowe konto użytkownika tunelSSH, który ma dostęp do urządzeń sieciowych (grupa netdev), a także niezbyt wysoki UID, by nie było go widać podczas logowania (to nie musi być w końcu komputer-serwer z prawdziwego zdarzenia, a tylko daemon świadczący jakąś usługę):

#useradd --create-home --home-dir=/home/tunelSSH/ --groups=netdev \
 --comment "Konto użytkownika uruchamiającego tunel SSH"  --shell="/bin/bash" \
 -K UID_MIN=20 -K UID_MAX=499 -K GID_MIN=20 tunelSSH

Tworzymy teraz konfigurację dla serwera tunelującego w pliku /etc/default/tunelSSH.conf:

Protocol 2
AllowTcpForwarding yes
AuthenticationMethods publickey
AuthorizedKeysFile /kluczeSSH/tunelSSH/autoryzowaneKlucze.pub
X11Forwarding no
AllowStreamLocalForwarding no
AllowUsers tunelSSH
Compression yes
ChallengeResponseAuthentication no # wyłączenie PAM
ClientAliveCountMax 3
ClientAliveInterval 20
DebianBanner no
PermitRootLogin no
UsePAM no
PrintMotd no
AddressFamily inet
Ciphers aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com
KbdInteractiveAuthentication no
KerberosAuthentication no
ListenAddress 0.0.0.0:33773
MaxAuthTries 2
MaxSessions 3
MaxStartups 2
PasswordAuthentication no
PermitOpen 127.0.0.1:5232
PermitTunnel no
PermitUserEnvironment no
SyslogFacility AUTH
TCPKeepAlive no # masz opcje ClientAlive od tego
UsePrivilegeSeparation no # by uruchomić openssh jako zwykły użytkownik
#klucz musi być inny niż klucz OpenSSH uruchomionego na koncie roota!
HostKey /kluczeSSH/tunelSSH/kluczHostaEdLiczba
PidFile /var/run/tunelSSH/tunelSSH.pid

Tworzenie klucza dla instancji OpenSSH na serwerze.

Pamiętaj: to musi być inny klucz niż klucz dla OpenSSH uruchomionego na koncie roota!

#mkdir /kluczeSSH/tunelSSH/ -p
#chgrp  tunelSSH /kluczeSSH/tunelSSH/
#chmod g+rw /kluczeSSH/tunelSSH/
#su tunelSSH
ssh-keygen -t ed25519 -f /kluczeSSH/tunelSSH/kluczHostaEdLiczba -N ''
ssh-keygen -t ed25519 -f /kluczeSSH/tunelSSH/autoryzowaneKlucze -N ''
exit
#chmod g-rw /kluczeSSH/tunelSSH/ -R

Kopiujemy plik (w bezpieczny sposób!) /kluczeSSH/tunelSSH/autoryzowaneKlucze na klienta do katalogu ~/.ssh/ do pliku id_ed25519.

Taki nasłuchujący połączeń OpenSSH można by uruchomić za pomocą

/usr/sbin/sshd -f /etc/default/tunelSSH.conf

Jednak oczywiście lepiej byłoby to opakować w skrypt startujący podczas bootowania. Stwórzmy więc taki.

Plik /etc/init.d/tunelSSH.sh

#! /bin/sh
### BEGIN INIT INFO
# Provides:          tunelPoprzezSSH
# Required-Start:    $local_fs $named $network $syslog
# Required-Stop:     $local_fs $named $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Tunel SSH
# Description:       Tunel SSH
### END INIT INFO

PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="Tunel SSH"
NAME=sshd
DAEMON=/usr/sbin/$NAME
DATADIR=/home/tunelSSH/
DAEMON_ARGS="-f /etc/default/tunelSSH.conf"
PIDDIR=/var/run/tunelSSH/
PIDFILE=/var/run/tunelSSH/tunelSSH.pid
SCRIPTNAME=/etc/init.d/tunelSSH.sh
USER=tunelSSH
GROUP=tunelSSH

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0



# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
    # Return
    #   0 if daemon has been started
    #   1 if daemon was already running
    #   2 if daemon could not be started
    if [ ! -d $PIDDIR ]
    then
        mkdir $PIDDIR
    fi
    chown $USER:$GROUP $PIDDIR
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test --chuid $USER > /dev/null || return 1
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid $USER -- $DAEMON_ARGS > /dev/null || return 2
}

#
# Function that stops the daemon/service
#
do_stop()
{
    # Return
    #   0 if daemon has been stopped
    #   1 if daemon was already stopped
    #   2 if daemon could not be stopped
    #   other if a failure occurred
    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME --chuid $USER
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2
    # Wait for children to finish too if this is a daemon that forks
    # and if the daemon is only ever run from this initscript.
    # If the above conditions are not satisfied then add some other code
    # that waits for the process to drop all resources that could be
    # needed by services started subsequently.  A last resort is to
    # sleep for some time.
    start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON --chuid $USER
    [ "$?" = 2 ] && return 2
    # Many daemons don't delete their pidfiles when they exit.
    rm -f $PIDFILE
    return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
    start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME --chuid $USER
    return 0
}

case "$1" in
  start)
    [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC""$NAME"
    do_start
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  stop)
    [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC""$NAME"
    do_stop
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  status)
    status_of_proc -p $PIDFILE "$DAEMON""$NAME"&& exit 0 || exit $?
    ;;
  reload)
    log_daemon_msg "Reloading $DESC""$NAME"
    do_reload
    log_end_msg $?
    ;;
  restart)
    log_daemon_msg "Restarting $DESC""$NAME"
    do_stop
    case "$?" in
      0|1)
        do_start
        case "$?" in
            0) log_end_msg 0 ;;
            1) log_end_msg 1 ;; # Old process is still running
            *) log_end_msg 1 ;; # Failed to start
        esac
        ;;
      *)
        # Failed to stop
        log_end_msg 1
        ;;
    esac
    ;;
  *)
    echo "Usage: $SCRIPTNAME {status|start|stop|reload|restart}">&2
    exit 3
    ;;
esac

Teraz dodajemy daemon/usługę do systemu:

chmod +x /etc/init.d/tunelSSH.sh
insserv tunelSSH.sh

Zabezpieczanie za pomocą fail2ban

W Internecie dochodzi do ataków na nasłuchujące połączeń serwery SSH. Nie powinno dojść do sytuacji, w której atakujący metodą brute force dostanie się do naszego serwera poprzez SSH autoryzowane kluczami, ale z drugiej strony dlaczego nie dodać następnego zabezpieczenia?

apt-get install fail2ban
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Edytujemy /etc/fail2ban/jail.local, ustawiając banaction na

banaction = iptables-allports

A następnie przeładowujemy komendą:

/etc/init.d/fail2ban restart

Instancja OpenSSH na kliencie

Na serwerze nasłuchuje już OpenSSH na porcie 33773. Pozwoli on zalogować się do konta tunelSSH, a także połączyć się z lokalnym (wobec serwera) portem 5232 na interfejsie loopback. Trzeba jednak jakoś się z nim połączyć. Jak już piałem powyżej, kopiujemy plik (w bezpieczny sposób!) z serwera z katalogu /kluczeSSH/tunelSSH/autoryzowaneKlucze na klienta do katalogu ~/.ssh/ do pliku id_ed25519. Następnie wystarczy wykonać:

ssh -L 4500:[127.0.0.1]:5232 adresSerwera -p 33773 -l tunelSSH

Pod adresSerwera oczywiście należy podstawić adres IP serwera. Parametr -p określa port, na którym nasłuchuje OpenSSH na serwerze. Parametr -l określa do jakiego konta użytkownika ssh ma się zalogować.

Jeśli wykonaliśmy powyższe polecenie, wtedy możemy połączyć się na kliencie z portem 4500 na interfejsie loopback (adres ip 127.0.0.1). Pakiety wysłane na ten port zostaną przesłane do serwera OpenSSH, a następnie wewnątrz serwera przekierowane z OpenSSH na port 5232, na którym może nasłuchiwać serwer Radicale.

MPD - instalacja, konfiguracja, używanie

$
0
0
    Informacje wstępne
    Instalacja
    Konfiguracja
            Tryb systemowy a tryb użytkownika
            Edycja pliku mpd.conf
            Wybór klienta
            Pierwsze uruchomienie
            Ustawienie zmiennych systemowych
            Potencjalne problemy
            Automatyczne uruchamianie

        Używanie
        Instalacja i konfiguracja mpdscribble
                Przygotowanie pliku konfiguracyjnego
                Konfiguracja trybu systemowego
                Konfiguracja trybu użytkownika

            Zakończenie

Informacje wstępne MPD (Music Player Daemon) to dość nietypowy odtwarzacz muzyczny stworzony z myślą o systemach uniksowatych (w tym o Linuksie). Spośród konkurencji wyróżnia go przede wszystkim implementacja modelu klient — serwer, czyli odseparowanie warstwy „grającej” od warstwy „sterującej”. Dzięki temu muzyka może grać nawet wtedy, gdy środowisko graficzne nie jest włączone, zaś sam odtwarzacz bardzo oszczędnie wykorzystuje zasoby komputera. Program jest idealnym rozwiązaniem dla osób często restartujących środowisko graficzne, pracujących na minimalistycznych menedżerach okien oraz posiadających wiekowe/słabe komputery. Majsterkowicze mogą zainstalować go na komputerze bez monitora (np. Raspberry Pi) i sterować nim z dowolnego urządzenia w sieci lokalnej (np. telefonu z Androidem), tworząc w ten sposób własne rozwiązanie typu home audio system (HTCP). Niniejszy artykuł krok po kroku opisuje, jak uruchomić MPD. Zajmiemy się jego instalacją, konfiguracją, wyborem klienta oraz podstawami debugowania. Na końcu przyjrzymy się mpdscribble, niewielkiemu programowi służącemu do wysyłania informacji o odtwarzanych utworach na Last.fm. Artykuł powstał w opraciu o Debiana w wersji 8.2, ale zamieszczone instrukcje mogą być przydatne również dla użytkowników innych dystrybucji. Instalacja MPD znajduje się w repozytoriach wszystkich aktualnie wspieranych wersji Debiana, dzięki czemu instalacja sprowadza się do wydania (jako root) polecenia: apt-get install mpd Konfiguracja Tryb systemowy a tryb użytkownika Domyślnie MPD działa w trybie systemowym — uruchamiany jest podczas startu systemu, przyjmuje uprawnienia specjalnego użytkownika i działa w tle, oczekując na dalsze instrukcje. Alternatywnie może zostać uruchomiony w trybie użytkownika, czyli tak samo jak właściwie wszystkie inne programy wykorzystywane podczas codziennej pracy z komputerem (przeglądarka internetowa, pakiet biurowy, odtwarzacz filmów itd.). MPD uruchomiony w ten sposób nie będzie odtwarzał muzyki gdy nie mamy uruchomionego środowiska graficznego, ale lepiej zintegruje się z pozostałymi komponentami współczesnego systemu linuksowego, takimi jak PulseAudio oraz udisks2. Z punktu widzenia niniejszego poradnika, różnica pomiędzy trybem systemowym a trybem użytkownika sprowadza się do lokalizacji pliku konfiguracyjnego oraz sposobu automatycznego uruchamiania programu. Niezależnie od tego, który tryb wybierzemy, MPD będzie działał tak samo dobrze i oferował ten sam zestaw funkcji. Edycja pliku mpd.conf mpd.conf to główny plik konfiguracyjny MPD; bez niego program nie będzie mógł być uruchomiony. W trybie systemowym jest to plik /etc/mpd.conf, zaś w trybie użytkownika — $HOME/.config/mpd/mpd.conf. Ten pierwszy jest tworzony podczas instalacji pakietu MPD, ten drugi musimy utworzyć samodzielnie. Jako podstawę możemy wykorzystać plik /usr/share/doc/mpd/examples/mpdconf.example.gz. Edycja pliku mpd.conf nie powinna nastręczyć specjalnych trudności, ponieważ każda zmienna jest poprzedzona wyczerpującym komentarzem. W razie wątpliwości możemy również skonsultować się z dokumentacją, wydając polecenie man mpd.conf. Najbardziej podstawowa konfiguracja dla trybu systemowego wygląda następująco: music_directory "/home/user/muzyka" playlist_directory "/home/user/muzyka" db_file "/var/lib/mpd/mpd.db" log_file "/var/log/mpd.log" user "mpd" audio_output { type "alsa" name "My ALSA Device" } Podczas modyfikacji pliku konfiguracyjnego powinniśmy zwrócić szczególną uwagę na dwie kwestie. Po pierwsze, wybór odpowiedniego wyjścia audio — bez tego nic nie usłyszymy w głośnikach. Po drugie, użytkownik uruchamiający program musi mieć uprawnienia wystarczające do odczytu wszystkich katalogów wskazanych w mpd.conf oraz odczytu i zapisu wszystkich wymienionych plików. Wybór klienta MPD potrafi tylko i wyłącznie odtwarzać muzykę. Nawet do tak prostego zadania jak jej uruchomienie lub zatrzymanie potrzebujemy osobnego programu, zwanego klientem. Zróżnicowanie programów klienckich jest ogromne. Jedne są kontrolowane przy pomocy wiersza poleceń, inne działają w środowisku graficznym, jeszcze innymi zarządzamy przy pomocy przeglądarki internetowej. Niektóre posiadają tylko podstawowe funkcje, inne mają ich tak wiele, że sterowanie MPD wydaje się być dodatkiem do czegoś zupełnie innego. W skrócie — każdy znajdzie coś dla siebie. Kompletna lista klientów znajduje się na stronach wiki MPD. Osobiście polecam wypróbować ncmpc++, doskonały program działający w terminalu tekstowym, wykorzystujący bibliotekę ncurses. W Debianie możemy go zainstalować wydając polecenie apt-get install ncmpcpp Pierwsze uruchomienie Przede wszystkim musimy uruchomić MPD. Gdy program działa w trybie systemowym, należy wydać komendę: systemctl start mpd Z kolei w trybie użytkownika wystarczy mpd Następnie uruchamiamy wybranego klienta. Pomimo poprawnego uruchomienia obu programów, biblioteka utworów w MPD będzie pusta. Jest tak, ponieważ nie została ona odświeżona. W ncmpc++ wystarczy wcisnąc przycisk u na klawiaturze (jak update). Niektóre inne klienty automatycznie odświeżają bibliotekę w momencie ich uruchomienia lub przy wykryciu zmian w metadanych plików. Ustawienie zmiennych systemowych Większość klientów domyślnie próbuje się połączyć z serwerem 127.0.0.1 na porcie 6600. Jeżeli uruchamiasz MPD na swoim komputerze i nie zmieniałeś ustawień portu (zmienna port), możesz spokojnie pominąć ten punkt. Jeśli jednak zmieniałeś port lub chcesz się połączyć z serwerem MPD działającym na innym komputerze w sieci, musisz ustawić zmienne systemowe. Zmienne są tylko dwie i ich nazwy jasno wskazują za co odpowiadają: MPD_HOST (nazwa/adres komputera) i MPD_PORT (port). Środowisko należy skonfigurować w taki sposób, aby zmienne te były ustawione w chwili uruchomienia klienta. Jednym ze sposobów jest ich zdefiniowanie w poleceniu uruchamiającym klienta: MPD_HOST=host MPD_PORT=port ncmpcpp Alternatywnie możemy je określić dla bieżącej sesji powłoki za pomocą polecenia export: export MPD_HOST=host MPD_PORT=port To drugie polecenie możemy dopisać do swojego pliku $HOME/.bash_profile (lub jego odpowiednika w używanej powłoce), dzięki czemu będą już zawsze skonfigurowane. Potencjalne problemy Jeżeli po uruchomieniu klienta nie widzisz zawartości biblioteki muzycznej, nie słyszysz nic w głośnikach pomimo wybrania pliku lub niepokoi Cię coś innego, uruchom MPD w następujący sposób: mpd --no-daemon --verbose --stdout Dzięki temu otrzymasz szczegółowy raport błędu na standardowym wyjściu konsoli. Zazwyczaj będzie on powiązany z brakiem któregoś z plików lub jego niewłaściwymi uprawnieniami. Problemy te z łatwością naprawisz przy pomocy touch, chmod oraz chown. Jeżeli wykorzystujesz MPD w trybie systemowym, możesz spróbować automatycznie naprawić wszystkie problemy przy pomocy skryptu fix-mpd-permissions.sh. Na specjalną uwagę zasługuje błąd o braku katalogu, podobny do poniższego: music directory is not a directory: "/home/user/muzyka" Może się on pojawić wtedy, kiedy użytkownik MPD nie posiada uprawnień do wykonania któregokolwiek z katalogów w podanej ścieżce. Dla przykładu, katalog domowy użytkownika w Arch Linux ma domyślnie uprawnienia 700. MPD działajacy w trybie systemowym, pracujący na uprawnieniach innego użytkownika, nie będzie w stanie odczytać jego zawartości. Rozwiązaniem jest oczywiście ustawienie atrybutu wykonywalności dla wszystkich katalogów pojawiających się w ścieżce music_directory. Jeżeli wybrany przez Ciebie klient w ogóle się nie uruchamia lub pokazuje komunikat o braku połączenia z serwerem, przede wszystkim upewnij się, że serwer jest włączony (może wadliwy wpis w pliku konfiguracyjnym uniemożliwia jego start?). Następnie sprawdź, czy klient łączy się z odpowiednim komputerem na odpowiednim porcie. Automatyczne uruchamianie Gdy MPD działa w trybie systemowym, o jego automatyczne uruchomienie zadba systemd. Nie jest wymagana żadna dodatkowa akcja z naszej strony. Natomiast jeżeli MPD działa w trybie użytkownika, to sami musimy się upewnić, że zostanie on uruchomiony zaraz po zalogowaniu. Przede wszystkim musimy wyłączyć automatyczne uruchamianie systemowej instancji MPD. Służy do tego polecenie: systemctl disable mpd Jeżeli używamy jednego ze środowisk graficznych zgodnych ze standardem XDG, takiego jak GNOME albo KDE SC, to nie musimy już nic więcej robić. Pakiet MPD w Debianie dostarcza plik /etc/xdg/autostart/mpd.desktop, który poinstruuje środowisko graficzne o konieczności uruchomienia programu w momencie logowania. W przeciwnym wypadku pozostaje nam ręczne uruchomienie MPD. Najprościej jest tego dokonać przy pomocy polecenia: if ! ps -C mpd > /dev/null 2>&1; then mpd & ; fi Taka konstrukcja zapobiega wielokrotnemu uruchomieniu MPD w sytuacji, gdy ten sam użytkownik zaloguje się więcej niż raz. Polecenie to należy dopisać do skryptu wykonywanego podczas uruchamiania środowiska graficznego lub umieścić w pliku ~/.bash_profile. Używanie W tym momencie powinniśmy móc bez problemów łączyć się z MPD za pomocą wybranego klienta i odsłuchać dowolny utwór z posiadanej biblioteki. Konkretny sposób wykonania tych czynności zależy od wybranego klienta. W przypadku ncmpc++ można wcisnąć klawisz 1 (cyfra jeden), który pokaże ekran pomocy zawierający wszystkie skróty klawiaturowe obsługiwane przez odtwarzacz. Instalacja i konfiguracja mpdscribble mpdscribble jest prostym programem, który wysyła utwory odtwarzane przez MPD do serwisów Last.fm, Libre.fm oraz Jamendo. Jeżeli nie wiesz, do czego służą wymienione serwisy i nie interesuje Cię to, możesz spokojnie pominąć dalszą część artykułu. mpdscribble można zainstalować wydając polecenie: apt-get install mpdscribble Podobnie jak MPD, mpdscribble może działać w trybie systemowym lub w trybie użytkownika. Jednocześnie tryby działania programów nie muszą być ze sobą zgodne — nawet gdy MPD działa w trybie systemowym, to nic nie stoi na przeszkodzie, aby każdy użytkownik miał swoją własną instancję mpdscribble. Przygotowanie pliku konfiguracyjnego Podczas instalacji pakietu utworzony zostanie plik /etc/mpdscribble.conf, przeznaczony dla mpdscribble działającego w trybie systemowym. Jeżeli chcemy uruchomić program w trybie użytkownika, powinniśmy skorzystać z pliku $HOME/.mpdscribble/mpdscribble.conf; za jego wzór może posłużyć /usr/share/mpdscribble/mpdscribble.conf. Struktura pliku konfiguracyjnego mpdscribble jest bardzo zbliżona do struktury pliku mpd.conf. Większość zmiennych jest dobrze opisanych, a w razie potrzeby można zajrzeć do man mpdscribble. Po pominięciu komentarzy, zawartość pliku przeznaczonego dla programu działającego w trybie systemowym może wyglądać następująco: pidfile = /var/run/mpdscribble.pid log = syslog verbose = 1 daemon_user = mpdscribble username = nazwa_użytkownika_last.fm password = hasło_last.fm journal = /var/cache/mpdscribble/lastfm.cache Zamiast hasła możemy wpisać jego sumę kontrolną MD5, co delikatnie zwiększy bezpieczeństwo. Suma ta jest ciągiem znaków podobnym do c64e698ece633f5cfa9c081eb9535988 i możemy ją obliczyć przy pomocy polecenia: echo -n 'hasło_last.fm' |md5sum |awk '{print $1}' Jeżeli informacje o słuchanych utworach chcemy wysyłać do kilku serwisów jednocześnie, albo korzystamy z serwisu innego niż Last.fm, nasz plik konfiguracyjny musimy rozbudować o sekcje. Każda sekcja składa się z nazwy w nawiasach kwadratowych (np. [Jamendo]) i zawiera zmienne url, username, password oraz (opcjonalnie) journal. Więcej szczegółów znajdziemy w przykładowym pliku konfiguracyjnym. Konfiguracja trybu systemowego systemd automatycznie uruchomi mpdscribble podczas uruchamiania komputera, więc konfiguracja trybu systemowego kończy się wraz z przygotowaniem pliku konfiguracyjnego. Konfiguracja trybu użytkownika Podczas przygotowywania mpdscribble do działania w trybie użytkownika powinniśmy zwrócić uwagę na trzy kwestie. Po pierwsze, musimy samodzielnie utworzyć wszystkie pliki oraz katalogi do których odnosimy się w pliku ~/.mpdscribble/mpdscribble.conf. mpdscribble nie utworzy ich automatycznie, nawet wtedy, gdy będzie miał odpowiednie uprawnienia. Po drugie, mpdscribble nie potrafi interpretować zmiennych systemowych (jak $HOME) oraz zapisu skróconego ~. Wszystkie ścieżki muszą być podane w całości. Po trzecie, plik konfiguracyjny nie powinien zawierać zmiennej daemon_user. Jeżeli ją podamy, to mpdscribble i tak zakończy pracę natychmiast po uruchomieniu z powodu braku uprawnień do zmiany użytkownika. Ponadto musimy zadbać o to, aby mpdscribble uruchamiał się automatycznie w trakcie logowania użytkownika. Muszą to zrobić również użytkownicy środowisk graficznych zgodnych z XDG, ponieważ pakiet mpdscribble nie dostarcza odpowiedniego pliku .desktop. Możemy do tego wykorzystać odpowiednio zmodyfikwoane polecenie zamieszczone w podpunkcie Automatyczne uruchamianie powyżej. Większość użytkowników będzie również chciała wyłączyć systemową instancję mpdscribble, co można osiągnąć następującym poleceniem: systemctl disable mpdscribble Faktem jest, że program uruchomiony w trybie systemowym może spokojnie działać obok programu działającego w trybie użytkownika, ale taka konfiguracja raczej mija się z celem. Zakończenie Właściwie to byłoby na tyle — MPD jest w pełni sprawne, można nim sterować oraz wysyła informacje o granych utworach do serwisu Last.fm. Czego chcieć więcej?

Darmowy certyfikat który akceptuje CA:)

$
0
0

Dzień dobry.

Dzisiaj opiszemy sobie jak szybko zainstalować sobie na serwerze, komputerze, vpsie darmowy certyfikat który będzie akceptowany przez CA i w magicznym sposobem pojawi się kłódeczka przy apache albo wykorzystamy certyfikat do innych ciekawych celów poczty jabbera etc.

Najpierw używając gita ściagamy całą zawartość aplikacji która generuje nam certyfikaty:

$ git clone https://github.com/letsencrypt/letsencrypt
$ cd letsencrypt

Potem wpisujemy posiadając apache następujące polecenie:

./letsencrypt-auto --apache

I wszystkie brakujace paczki zostaną pobrane i zainstalowane na Debianie. Potem wystarczy że odpowiemy na kilka pytań certyfikat zostanie wygenerowany oraz serwer przeładowany i całość będzie działać w kilka minut. Dodatkowo jeśli ktoś nie posiada apacha można rozwinąć:

./letsencrypt-auto certonly --standalone -d example.com -d www.example.com

Lub też jeśli ktoś posiada dowolny inny serwer www i chce wskazać katalog docelowy gdzie znajduje się strona:

./letsencrypt-auto certonly --webroot -w /var/www/example -d example.com -d www.example.com -w /var/www/thing -d thing.is -d m.thing.is

Odnawianie certyfikatu można wykonać poleceniem

 ./letsencrypt

Lub jeśli posiadamy rozwiązanie niestandardowe składnia jest następująca

./letsencrypt-auto certonly --keep-until-renewal --webroot -w /var/www/example.com -d example.com,www.example.com -w /var/www/thing -d thing.is,m.thing.is

Anulowanie certyfikatu:

letsencrypt revoke --cert-path example-cert.pem

Link do projektu https://letsencrypt.org/

Automatyczne właczenie IPv6 - tunel 6to4 przy starcie PPPOE,

$
0
0

Cześć

Połączenia PPPOE realizowane przez demona pppd bywają dosyć niestabilne, czasem gubi się połączenie, jest potem automatycznie wznawiane, zmienia się IP, itp.

Dlatego standardowe metody ustawiania interfejsu 6to4 w /etc/network/interfaces w Debianie czy /etc/conf.d/net w Gentoo się niezbyt sprawdzają, bo po prostu nie można restartować usług sieciowych przy każdym padzie pppd.

Na szczęście demon pppd potrafi uruchamiać skrypty przy nawiązaniu i zerwaniu połączenia, skrypty do wykonania umieszcza się w folderach /etc/ppp/ip{up|down}.d/ i tam można umieścić skrypty do ustawiania tunelu 6to4.

A więc do dzieła:

Tworzymy odpowiednie skrypty (wykonać z uprawnieniami roota), wystarczy wkleić do terminala:

cat  /etc/ppp/ip-up.d/70-6to4-up.sh
#!/bin/sh

INTERFACE="\$1"
INT6="6to4\$1"

ip route get 192.88.99.1 | grep "\$INTERFACE" 2>&1>/dev/null || exit 0

IPADDR=\$(ip route get 192.88.99.1 | awk 'NR==1 {print \$NF}');
IP6ADDR=\$(ipv4="\$IPADDR"; printf "2002:%02x%02x:%02x%02x::1" \`echo \$ipv4 | tr "."""\`)

ip tunnel add \$INT6 mode sit ttl 128 remote any local \$IPADDR
ip link set dev \$INT6 up
ip -6 addr add "\$IP6ADDR"/16 dev \$INT6
ip -6 route add default via ::192.88.99.1 dev \$INT6 metric 1
6TO4UP

Skrypt do automatycznego tworzenia tunelu 6to4 gotowy.

cat  /etc/ppp/ip-down.d/70-6to4-down.sh
#!/bin/sh

INTERFACE="\$1"
INT6="6to4\$1"

ip -6 route flush dev \$INT6
ip link set dev \$INT6 down
ip tunnel del \$INT6
6TO4DOWN

Skrypt do zamykania połączenia 6to4 razem z demonem pppd gotowy.

Teraz mały test:

wyłączamy pppoe:

poff
ip -6 route show | grep 6to4

i ponownie włączamy:

pon
ip -6 route show | grep 6to4
::/96 dev 6to4ppp0  proto kernel  metric 256
2002::/16 dev 6to4ppp0  proto kernel  metric 256
default via ::192.88.99.1 dev 6to4ppp0  metric 1

Jak widać, interfejs 6to4ppp0 gotowy, routing ipv6 gotowy.

W przypadku używania vwdial proszę restart połączenia realizować przez ten program.

Sprawdzamy czy działa:

ping6 -c3 ipv6.google.com
PING ipv6.google.com(fra02s27-in-x02.1e100.net) 56 data bytes
64 bytes from fra02s27-in-x02.1e100.net: icmp_seq=1 ttl=59 time=33.9 ms
64 bytes from fra02s27-in-x02.1e100.net: icmp_seq=2 ttl=59 time=34.6 ms
64 bytes from fra02s27-in-x02.1e100.net: icmp_seq=3 ttl=59 time=34.0 ms

--- ipv6.google.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 33.944/34.205/34.637/0.374 ms

Jeszcze tylko trzeba ustawić firewalla dla Ipv6, w skrypcie do ustawienia ip6tables (można też wkleić do /etc/rc.local - przed exit):

ip6tables -F
ip6tables -X
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
ip6tables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
ip6tables -A INPUT -m conntrack --ctstate INVALID,NEW -j REJECT

Mam nadzieję, że komuś się przyda. ;)

Pozdro


Sznurki:

http://www.tldp.org/HOWTO/Linux+IPv6-HOWTO/index.html

http://www.tldp.org/HOWTO/Linux+IPv6-HOWTO/configuring-ipv6to4-tunnels.html


[OpenBSD] OpenSSH jako serwer SFTP czyli bezpieczny serwer plików

$
0
0

Wersja oprogramowania

Poradnik pisany wobec serwera OpenSSH, w wersji 7.3, uruchomionego w rozwojowej wersji systemu OpenBSD-current (sierpień 2016).

Co przedstawia poradnik

Poradnik pokazuje jak dla dwóch określonych użytkowników (Andrzej, Magda, a w zasadzie odpowiednio: _ssh_andrzej, _ssh_magda), których rozróżnimy za pomocą używanych przez nich kluczy, pozwolić na dostęp do serwera plików SFTP (zapis, odczyt, zmiana uprawnień) bez możliwości uruchamiania komend. Istnieje możliwość innego ustawienia ścieżki chrootowania i dzięki temu również izolacji kont użytkowników SFTP między sobą, ale to odebrałoby możliwość udostępniania swoich plików (w swoim katalogu przez zmianę uprawnień) innym użytkownikom. Użytkownicy będą mogli edytować również listę swoich kluczy publicznych. Można by tę możliwość uniemożliwić umiejscawiając te pliki poza chrootem i/lub nadająć odpowiednie uprawnienia i flagi na pliku. Poza nimi do serwera będzie mógł się zalogować klient _ssh_default też autoryzując się przez klucz, ale nie posiadająć uprawnień do modyfikacji i zapisu plików, katalogów. Użytkownicy Andrzej i Magda również będą widzieć zawartość katalogu użytkownika _ssh_default. Poradnik skupia się na części serwerowej. Serwer będzie uruchomiony na adresie pętli lokalnej 127.0.0.1, więc trzeba go zmienić, jeśli się chce go udostępnić w sieci lokalnej lub Internecie.

Jak zwiększyć swoją wiedzę korzystając z tego poradnika

Osobom chcącym z niego skorzystać proponuję poczytać w manual-u co oznaczają poszczególne polecenia i parametry podane do nich, gdyż większości nie opisałem. Manual można znaleźć korzystając z polecenia man lub czytać online w przeglądarce. Druga opcja jest szczególnie przydatna osobom nie posiadającym zainstalowanego systemu OpenBSD. Osoby korzystające z Gnu/Linuksa (np Debiana) powinny niestety porównać znaczenie opcji w manualu zarówno systemu OpenBSD jak i np Debiana. Obecnie manual OpenBSD znajduje się pod adresem: http://man.openbsd.org/ lub wpisując man w terminalu/konsoli.

Jeśli czytasz manual, a i tak czegoś nie jesteś pewna(y) to oczywiście można zapytać tutaj na forum.

Kilka słów o protokołach FTP, FTPS, SFTP

Protokół FTP służy do przesyłania plików między klientem a serwerem. Powstawał w czasach krystalizowania się stosu TCP/IP i wymaga archaicznych rozwiązań m.in. otwierania dwóch połączeń TCP między klientem a serwerem. Zdefiniowane są dwa tryby, z czego jeden wymaga otwarcia w kliencie portu na firewallu, a drugi wymaga otwarcia szeregu portów na serwerze. Mocno utrudniają one tworzenie sensownej polityki firewalla. FTP sam w sobie nie zapewnia bezpieczeństwa tj szyfrowania, autoryzacji z użyciem kryptografi. W późniejszym czasie stworzono rozszerzenie protokołu FTP w postaci FTPS, które dodaje szyfrowanie i autoryzację, ale dalej nie jest to najlepsze rozwiązanie. Dodatkowo szyfrowanie utrudnia możliwość dynamicznego otwierania portów na firewallu, co było jednym z rozwiązań wcześniej wspomnianych problemów z trybami i połączeniami TCP.

Na szczęście istnieje protokół SFTP. Jest to protokół z punktu widzenia osoby używającej klienta podobny do FTP, lecz działający z użyciem jednego, stałego portu i od początku projektowany jako bezpieczny (m.in. tunelowany w bezpiecznym połączeniu np protokołu SSH).

Zabezpieczenia

Zabezpieczenie danych między kontami na serwerze opiera się na tradycyjnych Uniksowych uprawnieniach do plików. Użytkownicy powinni więc sami uważać z jakimi uprawnieniami tworzą pliki. Procesy użytkowników będą zchrootowane, co w połączeniu ze zrzucaniem uprawnień przez proces powinno ochronić przed dostępem do reszty drzewa katalogów. Komenda sftp jest wymuszana w konfiguracji, co oznacza odebranie prawa do innych komend. Innymi słowy nie można korzystać z shella. Niestety nie jest ograniczony rozmiar plików i całkowita objętość wszystkich plików. Najbezpieczniej byłoby podmontować /mnt/chroots/ jako oddzielny system plików i dodać dodatkową ochronę przed złośliwym zapełnieniem za pomocą quota'y i ograniczenia maksymalnego rozmiaru pliku. Jeśli jednak założymy, że użytkownicy są w miarę zaufani i nie będą próbować szkodzić serwerowi (np znajomi albo to osobisty serwer) to serwer jest całkiem bezpieczny. Dane użytkownika będą dosyć bezpieczne jeśli będzie chronił swój klucz prywatny i nie nadawał na swoich plikach zbyt luźnych uprawnień. Oprócz tego przydałby się proaktywny firewall potrafiący zablokować hosty po IP w czasie prób skanowania portów i wielokrotnych połączeniach w krótkim czasie do serwera OpenSSH. Możnaby pokusić się również o zwiększenie logowanych informacji o działaniach użytkowników.

Last but not least: Oczywiście dalej ważne jest w odpowiednio krótkim czasie instalowanie zaaktualizowanej wersji oprogramowania, by łatać publicznie znane dziury.

OpenBSD a wydajność dostępu (odczyt, zapis) do dużych ilości danych w postaci plików

Złożone projekty, które są dostępne na rynku, zwykle mają zarówno mocne jak i słabe strony. Tak też jest z OpenBSD. Niestety system plików (FFS) jak i podsystem pamięci masowej w systemie OpenBSD jest relatywnie słabą stroną systemu. System plików jest dosyć prymitywny. W innych systemach operacyjnych pamięć podręczna systemu operacyjnego potrafi dosyć wydatnie zwiększyć wydajność odczytu i zapisu na dysk, a w OpenBSD nie jest to zbyt skuteczne. Plusem dla tej części systemu operacyjnego to stabilność systemu plików. Istnieje też możliwość skorzystania z programowego RAID-a wbudowanego w OpenBSD. W przypadku prostego serwera dla siebie i znajomych ograniczenia nie powinny dać się we znaki, ale w przypadku tworzenia bardziej obciążanego (pod względem ilości danych, rządań zapisu i odczytu) serwera warto zastanowić się nad wyborem innego systemu operacyjnego np FreeBSD z systemem plików ZFS.

Niestety nie wszystkie zabezpieczenia przed włamaniami, wbudowane w OpenSSH (mam namyśli separację procesów, zadań i przywilejów - z ang. Privilege separation), nie zawsze na innych systemach operacyjnych działają tak poprawnie jak w systemie OpenBSD.

Do dzieła

Dane będą przechowywane w podkatalogach /mnt/chroots/sftp/home/. Zakładam, że mogę zmieniać uprawnienia /chroots, bo tam jeszcze nie ma innych podkatalogów.

mkdir -p /mnt/chroots/sftp/home/

Tworzymy grupę zbiorczą dla wszystkich użytkowników logujących się do sftp:

groupadd _ssh_wszyscy

Nadajemy uprawniania:

chown    root:wheel /mnt/chroots
# R oznacza nadanie uprawnień wszystkim podfolderom i plikom w nich. P oznacza nie podążanie za żadnym symlinkami.
chown -RP root:_ssh_wszyscy /mnt/chroots/sftp/
chmod -RP 640 /mnt/chroots
chmod    1600 /mnt/chroots/sftp/
# Na katalogach, i tylko dla nich, nadajemy uprawnienia właścicielowi i grupie, by mogli do nich wchodzić
find /mnt/chroots/ -type d -exec chmod ug+x {} \;
chmod     o+x /mnt/chroots
# Odpowiednik Gnu/Linuksowego chattr +a
chflags uappnd /mnt/chroots/sftp

Na początku tworzone są katalogi użytkowników i plik name, który w łatwy sposób pozwoli zorientować się jako kto są zalogowani.

mkdir -p /mnt/chroots/sftp/home/ssh_andrzej
mkdir -p /mnt/chroots/sftp/home/ssh_magda
mkdir -p /mnt/chroots/sftp/home/ssh_shared_ro
echo "Andrzej"> /mnt/chroots/sftp/home/ssh_andrzej/name
echo "Magda"> /mnt/chroots/sftp/home/ssh_magda/name
echo "Domyślny"> /mnt/chroots/sftp/home/ssh_shared_ro/name

Oprócz tego można też wrzucić plik fałszywej powłoki wewnątrz chroota

mkdir -p /mnt/chroots/sftp/bin
ln -s /bin/date  /mnt/chroots/sftp/bin/date
chown -RP root:wheel /mnt/chroots/sftp/bin/
chmod a+x            /mnt/chroots/sftp/bin/
chmod 511            /mnt/chroots/sftp/bin/date

Tworzymy konta użytkowników, ustawiamy fake'owego shella, dodajemy użytkowników do zbiorczej grupy _ssh_wszyscy:

useradd -d /mnt/chroots/sftp/home/ssh_shared_ro -G _ssh_wszyscy -e 0  -s /bin/date  _ssh_default
useradd -d /mnt/chroots/sftp/home/ssh_andrzej   -G _ssh_wszyscy -e 0  -s /bin/date  _ssh_andrzej
useradd -d /mnt/chroots/sftp/home/ssh_magda     -G _ssh_wszyscy -e 0  -s /bin/date  _ssh_magda

Nadajemy uprawnienia katalogom:

chown -RP         root:_ssh_wszyscy /mnt/chroots/sftp/home/ssh_shared_ro
chown -RP _ssh_andrzej:_ssh_andrzej /mnt/chroots/sftp/home/ssh_andrzej
chown -RP _ssh_magda:_ssh_magda     /mnt/chroots/sftp/home/ssh_magda
chmod -RP  600 /mnt/chroots/sftp/home/ssh_andrzej
chmod -RP  600 /mnt/chroots/sftp/home/ssh_magda
chmod -RP  440 /mnt/chroots/sftp/home/ssh_shared_ro
find /mnt/chroots/sftp/home -type d -exec chmod ug+x {} \;
chmod +t      /mnt/chroots/sftp/home/ssh_shared_ro
# uchg to słabszy odpowiednik Gnu/Linuksowego chattr +i. schg to mocniejsza wersja chattr +i.
chflags uchg   /mnt/chroots/sftp/home/ssh_shared_ro/name
chmod +t       /mnt/chroots/sftp/home
chflags uappnd /mnt/chroots/sftp/home/

Tworzenie kluczy dla hosta W tym celu tworzymy tymczasowy katalog. Warto pamiętać, że /tmp jest zwykle czyszczone podczas restartu.

mkdir -p       /tmp/klucze_ssh
chown -RP root /tmp/klucze_ssh
chmod -RP 600  /tmp/klucze_ssh
cd /tmp/klucze_ssh

Właściwa część tworzenia kluczy. Dla hosta zawsze bez hasła

ssh-keygen -f ssh_host_ed25519_key -o -t ed25519
ssh-keygen -b 3072 -f ssh_host_rsa_key -o -t rsa

Klucze należy przenieść do miejsca, w którym będzie ich szukał serwer OpenSSH. Skopiowanie i nadanie uprawnień.

cp ssh_host_*[key,pub] /etc/ssh/
chown root:wheel /etc/ssh/ssh_host_*[key,pub]
chmod 600        /etc/ssh/ssh_host_*[key,pub]

Tworzenie kluczy dla użytkowników Dla uproszczenia też stworzyłem bez hasła

ssh-keygen -C andrzej -f ssh_id_andrzej_ed25519_key     -o -t ed25519
ssh-keygen -C andrzej -b 3072 -f ssh_id_andrzej_rsa_key -o -t rsa
ssh-keygen -C magda   -f ssh_id_magda_ed25519_key       -o -t ed25519
ssh-keygen -C magda   -b 3072 -f ssh_id_magda_rsa_key   -o -t rsa
ssh-keygen -C default -f ssh_id_default_ed25519_key     -o -t ed25519
ssh-keygen -C default -b 3072 -f ssh_id_default_rsa_key -o -t rsa

Stworzone zostały klucze publiczne i prywatne w typach rsa i ed25519. Daje to 4 pliki na użytkownika. Po podanych komendach stworzone zostanie łącznie 12 plików.

Pliki z końcówką .pub to pliki publiczne. Należy je wrzucić do podkatalogu ~/.ssh/authorized_keys2 w katalogach domowych użytkowników na serwerze.

mkdir -p /mnt/chroots/sftp/home/ssh_andrzej/\.ssh/
mkdir -p /mnt/chroots/sftp/home/ssh_magda/\.ssh/
mkdir -p /mnt/chroots/sftp/home/ssh_shared_ro/\.ssh/

Dopisujemy klucze

Restrict wyłącza forwardowanie itp, ale opcje w sshd_config mają pierszeństwo. Poza tym użytkownicy Andrzej i Magda mogą zmieniać własne pliki, również authorized_keys2, więc mogą usunąć restrict.

awk '{printf "restrict ";print $0}' ssh_id_andrzej_*pub > /mnt/chroots/sftp/home/ssh_andrzej/.ssh/authorized_keys2
awk '{printf "restrict ";print $0}' ssh_id_magda_*pub   > /mnt/chroots/sftp/home/ssh_magda/.ssh/authorized_keys2
awk '{printf "restrict ";print $0}' ssh_id_default_*_key.pub > /mnt/chroots/sftp/home/ssh_shared_ro/.ssh/authorized_keys2

Zmieniamy uprawnienia:

chown -RP _ssh_andrzej:_ssh_andrzej /mnt/chroots/sftp/home/ssh_andrzej/.ssh/
chown -RP _ssh_magda:_ssh_magda     /mnt/chroots/sftp/home/ssh_magda/.ssh/
chown -RP _ssh_default:_ssh_default /mnt/chroots/sftp/home/ssh_shared_ro/.ssh/
chmod   600  /mnt/chroots/sftp/home/ssh_andrzej/\.ssh/authorized_keys2
chmod   600  /mnt/chroots/sftp/home/ssh_magda/\.ssh/authorized_keys2
chmod   400  /mnt/chroots/sftp/home/ssh_shared_ro/\.ssh/authorized_keys2
# uchg to słabszy odpowiednik Gnu/Linuksowego chattr +i. schg to mocniejsza wersja chattr +i.
chflags uchg /mnt/chroots/sftp/home/ssh_shared_ro/\.ssh/authorized_keys2
chmod   700  /mnt/chroots/sftp/home/ssh_andrzej/\.ssh/
chmod   700  /mnt/chroots/sftp/home/ssh_magda/\.ssh/
chmod  1500  /mnt/chroots/sftp/home/ssh_shared_ro/.ssh/
chflags uchg /mnt/chroots/sftp/home/ssh_shared_ro
chflags uchg /mnt/chroots/sftp/home/ssh_shared_ro/.ssh/
chflags uchg /mnt/chroots/sftp/home/ssh_magda/.ssh/
chflags uchg /mnt/chroots/sftp/home/ssh_andrzej/.ssh/

Możemy przenieść klucze prywatne do klienta

Pliki bez końcówki pub (czyli kończące się na key) to klucze prywatne. Należy je w bezpieczny sposób przenieść na klienta do podkatalogu ~/.ssh/ w katalogu domowym użytkownika do plików id_rsa i id_ed25519.

Zakładając, że testujemy i mamy klienta na tym samym komputerze co serwer, testowy klient ma być uruchomiony na koncie użytkownika test i chcemy mięć dostęp do serwera z poziomu użytkownika default, plik klucza prywatnego typu ed25519 przeniesiemy poleceniami:

cp ssh_id_default_ed25519_key /home/test/.ssh/id_ed25519
chown test:test /home/test/.ssh/id_ed25519
chmod 600 /home/test/.ssh/id_ed25519

Podobnie z kluczami publicznymi:

cp ssh_id_default_ed25519_key.pub /home/test/.ssh/id_ed25519.pub
chown test:test /home/test/.ssh/id_ed25519.pub
chmod 600 /home/test/.ssh/id_ed25519.pub

Przenieśliśmy klucze typu ed25519. Analogicznie przenosimy klucze RSA.

Zawartość wklejana do pliku konfiguracji

Główny plik konfiguracji ma domyślną ścieżkę /etc/ssh/sshd_config. Jego zmiana jednak na nasz spowoduje uruchomienie tylko i wyłącznie SFTP, czyli nie można będzie zalogować się i wydawać komend! Jeśli masz zdalny serwer prawdopodobnie chcesz stworzyć inną usługę sshd i wgrać konfigurację dla niej pod inną ścieżką (by nie utracić zdalnego dostępu do serwera), ale w tym poradniku dla uproszczenia ustawiam go jako /etc/ssh/sshd_config.

ListenAddress 127.0.0.1
AllowGroups _ssh_wszyscy
#
ChallengeResponseAuthentication no
ClientAliveCountMax 1
ClientAliveInterval 15
Compression yes
Ciphers chacha20-poly1305@openssh.com,aes128-gcm@openssh.com,aes256-gcm@openssh.com
HostKeyAlgorithms ssh-ed25519,ssh-rsa
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com
PubkeyAcceptedKeyTypes ssh-ed25519,ssh-rsa
IPQoS throughput
KbdInteractiveAuthentication no
PasswordAuthentication no
LoginGraceTime 10
MaxAuthTries 2
MaxSessions 3
MaxStartups 2
PermitTunnel no
PermitUserEnvironment no
PermitUserRC no
X11Forwarding no
StrictModes yes
AuthorizedKeysFile "%h/.ssh/authorized_keys2"
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
AllowAgentForwarding no
AllowTcpForwarding no
AllowStreamLocalForwarding no
PermitTTY no
PermitRootLogin no
UsePrivilegeSeparation sandbox

Subsystem       sftp    internal-sftp

ChrootDirectory /mnt/chroots/sftp/
ForceCommand internal-sftp -R -d /home/ssh_shared_ro

Match User _ssh_andrzej
    ForceCommand internal-sftp -d /home/ssh_andrzej  -u 007

Match User _ssh_magda
    ForceCommand internal-sftp -d /home/ssh_magda    -u 007

Po tym można zrestartować sshd:

rcctl -f restart sshd

I sprawdzić jego stan:

rcctl check sshd

Połączenie klienta do serwera SFTP

Aby użytkownik test na komputerze kliencie mógł uwierzytalnić się jako inny użytkownik, z użyciem kluczy prywatnych z jego podkatalogu ~/.ssh/, należy użyć komendy:

sftp -i /home/test/.ssh/id_ed25519  _ssh_default@127.0.0.1

Automatyczny backup z użyciem incron

$
0
0

Cześć

Właśnie wdrożyłem automatyczny backup folderu /etc/ - całej ważnej konfiguracji systemu przy użyciu incrona, działa to elegancko:

Jak to zrobić?

Instalacja i konfiguracja jest banalna:

Instalujemy incron i rdiff-backup W Debianie:

aptitude install incron rdiff-backup

W Gentoo jest troszkę więcej zabawy

emerge -q incron rdiff-backup

Konfiguracja? w pliku konfiguracyjnym nie musiałem dodawać ani kropki, tylko go stworzyć:

touch /etc/incron.conf

następnie tworzymy skrypt odpowiedzialny za sam backup:

nano /usr/local/sbin/etcbackup

wklejamy tam np:

#!/bin/bash
rdiff-backup /etc /home/etc

potem uprawnienia:

chmod 700 /usr/local/sbin/etcbackup

i przykładowa konfiguracja zadań incrona:

cat /etc/incron.d/etcbackup

/etc/  IN_CREATE,IN_DELETE,IN_CLOSE_WRITE,IN_MODIFY /usr/local/sbin/etcbackup

Potem start demona - w Debianie raczej restart, Debian sam uruchamia i dodaje do autostartu zainstalowane demony. W Gentoo z OpenRC trzeba dodać do usług startowych i uruchomić ręcznie:

rc-update add incrond default
/etc/init.d/incrond start

Czy działa? Wystarczyło zmodyfikować dowolny plik w /etc/, i w logach prawie natychmiast mamy komunikat:

Aug 21 08:54:29 localhost incrond[26374]: (system::etcbackup) CMD (/usr/local/sbin/etcbackup)

Incrond nie wymaga dużo zasobów systemowych, trzeba tylko być ostrożnym z synchronizacją jakichś olbrzymich katalogów gdzie często są jakieś zmiany.

Użycie RAM u mnie:

psmem | grep incron
264.0 KiB +   1.6 MiB =   1.9 MiB   incrond

Mama nadzieję, że komuś się przyda. :)

Pozdro

Sznurki:

http://www.nongnu.org/rdiff-backup/examples.html

https://www.howtoforge.com/tutorial/trigger-commands-on-file-or-directory-changes-with-incron/

Instalacja natywnego Debiana arm64 na Raspberry Pi 3

$
0
0

Raspberry Pi 3 zawiera w sobie 64 bitowy procesor Broadcom BCM2837, lecz oferowana oficjalna dystrybucja będąca forkiem Debiana, działa tylko w wersji dla procesorów 32 bitowych.

Przez jednego z developerów Debiana został przygotowany obraz instalacyjny systemu, który umieszczamy na karcie pamięci.

Przedstawiam jak wykonać te czynności po systemem Linux, w innych trzeba użyć właściwych dla nich narzędzi. Aktualnie dostępna wersja to 2018-01-08, z czasem może się to zmienić także proponuje sprawdzić na stronie: https://people.debian.org/~stapelberg/raspberrypi3/ czy nie ma dostępnych aktualizacji. Większość elementów działa w systemie działa jak w systemie Raspbian, bluetooth nie był testowany.

Instalacja systemu na karcie SD

$ wget https://people.debian.org/~stapelberg/raspberrypi3/2018-01-08/2018-01-08-raspberry-pi-3-buster-PREVIEW.img.xz
$ xzcat 2018-01-08-raspberry-pi-3-buster-PREVIEW.img.xz | dd of=/dev/sdb bs=64k oflag=dsync status=progress

Gdzie /dev/sdb wskazujemy naszą kartę pamięci.

Uwaga!!! System po instalacji dostępne ma ssh tylko z prywatnych klas adresowych sieci lokalnych.

Sprawdzamy na swoim serwerze dhcp adres IP urządzania i logujemy się na ssh na konto root lub podłączamy się je do monitora, wykonując czynności analogicznie to tych z ssh. Hasło to raspberry

$ ssh root@rpi3
# Password is “raspberry”

Po pierwszym zalogowaniu zmieniany hasło do użytkownika root:

passwd root

Następną czynnością jest usunięcie lub zakomentowanie repozytorium gałęzi nie stabilnej:

nano /etc/apt/sources.list

i usuwamy linie z repozytorium sid/unstable. W moim przypadku jest ona ostatnia.

Aktualizujemy listę repozytoriów:

apt-get update

Aktualizujemy system:

apt-get dist-upgrade

Po poprawnym zaktualizowaniu systemu należy zainstalować jądro większe jak 4.14. W tym momencie (stan na 13 marca 2018) meta pakiety z gałęzi testowej repozytorium nie pobierają go. Należy to wykonać ręcznie:

wget http://ftp.de.debian.org/debian/pool/main/l/linux-latest/linux-image-arm64_4.15+90_arm64.deb
dpkg -i linux-image-arm64_4.15+90_arm64.deb
apt-get install -f

Następnie należy zaktualizować konfigurację bootloadera wykonując:

/etc/kernel/postinst.d/raspi3-firmware

i resetować urządzenie:

reboot

Po ponownym włączeniu powinno już działać nowe jądro:

Linux rpi3 4.15.0-1-arm64 #1 SMP Debian 4.15.4-1 (2018-02-18) aarch64 GNU/Linux

Jeśli wszystko działa poprawnie warto usunąć starszą zbędną wersje:

apt-get purge linux-image-4.14.0-3-arm64

Jeśli będziemy korzystać z ssh łącząc się z poza sieci lokalnych, należy wyczyścić konfiguracje iptables:

iptables -F

i usunąć konfiguracje z plików:

/etc/iptables/rules.v4
/etc/iptables/rules.v6

Wszelkie pytania można zgłaszać na listę https://lists.alioth.debian.org/mailman/listinfo/pkg-raspi-maintainers

Autologowanie pod tty -> systemd

$
0
0

Cześć!

Jest to wpis uzupełniający do wpisu zatytułowanego "Zastąpienie ekranu logowania - autostart X i autologowanie" popełnionego przez mati75 jakieś 7 lat temu.

Pokrótce, najpierw z prawami root'a w terminalu wykonujemy:

# systemctl edit getty@tty1.service

W tym momencie powinien odpalić się domyślny edytor tekstowy w konsoli. Wklepujemy i zapisujemy:

[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin user --noclear %I $TERM

Po czym restartujemy system i tyle. To jest dokładnie takie samo rozwiązanie proponowane, jakie proponuje wiki Archa.

Własny Debian LiveUSB

$
0
0

Live USB możemy bardzo prosto utworzyć instalując system z użyciem debootastrapa i uzupełniając go w chroocie o jądro, gruba i potrzebne nam narzędzia.

Artykuł ten prezentuje krok po kroku proces budowy własnego live usb. Zaprezentowane w nim zostały polecenia i konfiguracje m.in. związane z następującymi zagadnieniami:

  • gpt; efi / uefi; grub;
  • montowanie obrazu dysku z pliku (mount disk image from file);
  • chroot; montowanie i odmontowywanie specjalnych systemów plików dla chroot; odmontowywanie systemów montowanych z opcją rbind (rbind umount);
  • debootstrap;
  • optymalizacja dla systemów na pamięciach flash: dane zmienne na tmpfs (ramdysk).

Nie jest to skrypt, który można uruchomić i czekać na gotowy produkt w postaci live USB. Jest to natomiast poradnik, który należy czytać i świadomie wykonywać kolejne podane w nim polecenia. Wymagane jest co najmniej ustawienie zmiennych DEV (wskazującej na urządzenie blokowe na którym prowadzimy instalację) oraz MNT wskazujące na punkt montowania tworzonego rootfs'a. Część prezentowanych ustawień jest opcjonalnych (np. konfiguracja apt'a) i odzwierciedla preferencje autora.

Obraz w pliku

Utworzenie obrazu dysku w pliku, a następnie przekopiowanie go przy pomocy dd na nośnik, jest opcjonalne, ale niekiedy może znacząco przyspieszyć proces instalacji.

dd if=/dev/zero of=usb.img bs=1M count=1913
losetup --partscan --find --show usb.img

Przygotowanie tablicy partycji

# tworzymy tablicę partycji typu gpt
# zasadniczo wystarczył by zwykły MBR z partycją EFI, ale zrobimy hybrydę GPT + MBR
parted $DEV "mklabel gpt"

# tworzy partycję która posłuży do wgrania gruba (musi mieć co najmniej 128 kiB)
# należy zaznaczyć iż nie jest to partycja /boot
# jest to surowe (bez filesystemu) miejsce na dysku gdzie zostanie wgrany
# fragment gruba normalnie wgrywany do MBR
parted $DEV "mkpart grub 0 2MB";

# ustawiamy dla tej partycji flagę "GRUB BIOS partition"
parted $DEV "set 1 bios_grub on";

parted $DEV "mkpart efi 2MB 200MB";
parted $DEV "set 2 boot on";

# resztę dysku możemy podzielić wg uznania,
# tutaj robimy jedną dużą partycję o nazwie rootfs
parted $DEV "mkpart rootfs 200MB 100%";


# przy pomocy gdisk utworzenie hybrid MBR
gdisk $DEV
# r ->
#      o
#      h ->
#           1 2 3
#           n 83 n
#           ef y
#           83 n
#      o
#      w -> 
#           y

if [ -e ${DEV}1 ]; then
    DEVp=${DEV}
elif [ -e ${DEV}p1 ]; then
    DEVp=${DEV}p
else
    print "ERROR cant find device for partitions on ${DEV}"
fi

mkfs.vfat -F 32 ${DEVp}2
mkfs.xfs ${DEVp}3

Instalacja systemu

# zamontowanie systemu plików
mount ${DEVp}3 ${MNT}

# ustawiamy adres mirrora i instalowaną gałąź Debiana
# (chyba że był wcześniej były ustawione)
MIRROR=${MIRROR:="ftp://ftp.icm.edu.pl/pub/Linux/debian/"}
SUITE="stretch"

# instalujemy system debootstrapem
debootstrap ${SUITE} ${MNT} ${MIRROR}

Chroot

# zamontowanie /proc, /sys i /dev na potrzeby chroot'a
mount -t proc  proc  $MNT/proc
mount -t sysfs sysfs $MNT/sys
mount -o rbind /dev  $MNT/dev

# ustawienie zmiennych środowiskowych
export DEV DEVp MIRROR SUITE
export LC_ALL="C.UTF-8"

# chroot
chroot $MNT

Uwaga: wszystkie następne kroki wykonywane są wewnątrz chroot'a

Podstawowa konfiguracja systemu

# używamy UTF-8
echo 'LANG="C.UTF-8"' > /etc/default/locale;
echo 'set -a; . /etc/default/locale; set +a' > /etc/profile.d/locale.sh

# w /etc/fstab ustawiamy rootfs na read-only, a /tmp na tmpfs
# /var/run i /var/lock są współcześnie linkami do /run na tmpfs
cat  /etc/fstab
/dev/disk/by-uuid/$UUID  /     xfs    ro        0  0
tmpfs                    /tmp  tmpfs  defaults  0  0
EOF

# katalogi często pisane na ramdysku
# /tmp będzie punktem montowania więc go czyścimy
rm -fr /var/tmp;   ln -s /run/tmp   /var/tmp
rm -fr /var/log;   ln -s /run/log   /var/log

cat > etc/tmpfiles.d/on_tmpfs.conf  /etc/network/interfaces.d/eth0 
echo "iface eth0 inet dhcp">> /etc/network/interfaces.d/eth0

# ssh pozwala na logowanie na root'a i nie jest automatycznie uruchamine
sed -e 's|^[# ]*PermitRootLogin.*$|PermitRootLogin yes|' -i /etc/ssh/sshd_config
systemctl  disable  ssh.service

# różne ustawienia
systemctl  mask  hwclock-save.service systemd-random-seed.service udev-finish.service \
                systemd-update-utmp-runlevel.service systemd-update-utmp.service
rm /usr/lib/modules-load.d/ipmievd.conf
echo "liveUSB"> /etc/hostname

# hasło root'a
passwd

# konfiguracja użytkownika - skrypty do montowania i odmontowywania chroot'ów
# oraz fałszywa historia linii poleceń (z tym co może nam się przydać w przyszłości)
cat  /root/prepareChroot.sh
#!/bin/bash

if [ \$# -ne 2 ]; then
        echo USAGE: \$0 device mountpoint
        exit
fi

DEV=\$1
MNT=\$2

mount \$DEV \$MNT
mount -t proc  proc  \$MNT/proc
mount -t sysfs sysfs \$MNT/sys
mount -o rbind /dev  \$MNT/dev

chroot \$MNT
EOF
chmod +x /root/prepareChroot.sh

cat  /root/umountChroot.sh
if [ \$# -ne 2 ]; then
        echo USAGE: \$0 mountpoint
        exit
fi

MNT=\$1

umount \$MNT/proc
umount \$MNT/sys
mount --make-rslave \$MNT/dev ; umount -R \$MNT/dev
umount \$MNT
EOF
chmod +x /root/umountChroot.sh

cat  /root/.bash_history
mount -o remount,rw /
systemctl start ssh.service
/root/prepareChroot.sh /dev/sdb1 /mnt/1
chroot /mnt/1
/root/umountChroot.sh /mnt/1
EOF
ln -s /root/.bash_history /.bash_history

# samobójstwo bash'a ... zapobiega zapisaniu historii linii poleceń
# skutkuje też wyjściem z chroot'a
kill -9 $BASHPID

Odmontowanie chroot'a

Uwaga: wszystkie następne kroki wykonywane poza chroot-em

umount $MNT/boot/efi/
umount $MNT/run
umount $MNT/tmp
umount $MNT/proc
umount $MNT/sys
mount --make-rslave $MNT/dev
umount -R $MNT/dev
umount $MNT
losetup -d $DEV

Licencja

Copyright (c) 2015-2019, Robert Paciorek <rrp@opcode.eu.org>

To jest wolny i otwarty dokument/oprogramowanie. Redystrybucja, użytkowanie i/lub modyfikacja SĄ DOZWOLONE na warunkach licencji MIT.

This is free and open document/software. Redistribution, use and/or modify ARE PERMITTED under the terms of the MIT license.

The MIT License:

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Viewing all 160 articles
Browse latest View live