Disassembler

Artificial intelligence is no match for natural stupidity.
10srpna2018

Vzdálená instalace Ubuntu po SSH


Před půl rokem jsem psal o vzdáleném odemykání šifrovaného kořenového souborového systému skrze SSH daemona nastrčeného do init RAMdisku. Tento článek bude z podobného soudku. Občas se mi stane, že potřebuji dodat nebo přeinstalovat server nějaké firmě, která sídlí za sedmero horami, sedmero řekami a sedmero lesy. Dlouhou dobu jsem uvažoval, že by bylo fajn mít nějaký bootovatelný live obraz, který by mi uživatel na druhém konci spustil a na který bych se mohl vzdáleně přihlásit a provádět psí kusy, aniž by server musel na výlet. A přesně takový jsem teď konečně vytvořil.

Debian installer


Drtivá většina mých serverů běží na Ubuntu, takže milé RedHatisty a jiná zvířátka tímto návodem asi nepotěším. Nicméně stejný způsob, jen s několika drobnými odlišnostmi v předávaných hodnotách, se dá použít i pro holý Debian a všechny distribuce na něm založené. Nebo minimálně takové, které používají stejný způsob instalace. Debian installer totiž vše potřebné již v základu umí, a to nejen co se týká vzdáleného přístupu, ale i automatizace celé instalace. Jen je nutno jej nakonfigurovat dle vašich a zákazníkových preferencí. Za pomoci Debian installeru totiž nevytváříte live obraz jako takový, ale prostě jen instalaci automatizujete do té míry, aby udělala většinu předinstalačního nastavení sama a pustila vám SSH, přes které dorazíte zbytek. Uživateli na druhé straně pak stačí vložit médium do počítače, nabootovat z něj, chvíli počkat a jednou stisknout enter pro potvrzení spuštění SSH serveru. Zkrátka, s deb-installerem zvládne instalaci snad i úplný deb-il. Instalace se dá samozřejmě automatizovat úplně celá, ale to není to, co chci, protože mé servery nemají jednotný hardware a často potřebuji šachovat s nastavením disků. Na jednom serveru nastavit RAID, na druhém přihodit disk na zálohy, na dalším nastavit EFI oddíl a tak. Také to má další čistě pragmatický důvod, kterým je zamezení škod v případě, že někdo obraz náhodu nabootuje na počítači, který není předmětem instalace.

Instalační obraz Ubuntu ve výchozí instalaci klade následující dotazy. K nim rovnou připíšu hodnoty, na které je chci nastavit.

Mimo tohle všechno ještě nějak musím vnutit informaci o tom, že chci instalátor přístupný po SSH. Debian installer je natolik šikovný, že mu můžu dát i adresu, odkud si má stáhnout můj veřejný SSH klíč, resp. soubor authorized_keys, abych se mohl připojit bez nějakých primitivních hesel. Na závěr ještě potřebuju donutit instalátor, aby můj SSH klíč zkopíroval do nově nainstalovaného systému.

Debconf


Nástroj, který se stará o čtení a zapisování jednotlivých položek instalátoru se jmenuje debconf. Hodnoty jsou uloženy v textových, lidsky čitelných souborech, což celou práci značně zjednodušuje. Kýžených klíčů a hodnot se nejlépe doberete tak, že si systém jednou ručně nainstalujete a po rebootu z čerstvě nainstalovaného systému vyzobnete soubor /var/log/installer/cdebconf/questions.dat. Stejná taškařice se dá udělat i rovnou z instalačního prostředí, kde pomocí Ctrl+F2 otevřete nové sezení se shellem místo instalátoru a nakouknete do souboru /var/lib/cdebconf/questions.dat. Klíče a hodnoty k nastavení uvedenému výše budou tedy následující:

debian-installer/language=en
debian-installer/country=CZ
localechooser/preferred-locale=en_US.UTF8
keyboard-configuration/layoutcode=us
netcfg/choose_interface=auto
netcfg/get_hostname=new
mirror/country=CZ
mirror/http/mirror=cz.archive.ubuntu.com
mirror/http/proxy= 
hw-detect/load_firmware=true
anna/choose_modules=network-console
network-console/authorized_keys_url=http://example.com/authorized_keys
passwd/username=user
passwd/user-fullname=user
passwd/user-password=Sup3rS3cret
passwd/user-password-again=Sup3rS3cret
time/zone=Europe/Prague
pkgsel/update-policy=none
clock-setup/utc=true
tasksel/first="OpenSSH server"
preseed/late_command="cp -r /.ssh /target/root/"

Přičemž některé klíče bylo nutno vyčíst z dokumentace, k čemuž mi nejlépe posloužil vzorový soubor preseedu.

Remix


Existují v zásadě dva způsoby, jak parametry automatizace předávat. První je jednodušší, ale zato méně čitelný. Druhý je čitelný, ale vyžaduje více kroků. Já jsem strašně líný, takže si vyberu ten první. Čitelnost mě nijak zásadně netrápí, protože soubory budu potřebovat číst jen jednou za dva roky, při vydání nové LTS verze. Nejprve si stáhnu instalační ISO obraz netbootu z http://cdimage.ubuntu.com/netboot/, který je pojmenován jednoduše jako mini.iso. Ten pak namoutuji a zkopíruji jeho obsah včetně zachování všech oprávnění. Následně upravím hlavní konfigurační soubor pro ISOLINUX, který plní funkci zavaděče instalačního obrazu. V tomto souboru se odehrává veškerá magie a parametry pro automatizaci jsou tu předány instalátoru. Pokud chci bootovat i z UEFI, musím ještě znova udělat totéž i pro GRUB. Debianí a odvozená média mají z nějakého důvodu dva různé zavaděče i přesto, že ISOLINUX z UEFI bootovat také umí. Nejspíš jsou k tomu nějaké historické důvody z dob, kdy to ještě neuměl. Nakonec ze souborů v rozbaleném adresáři opět vytvořím ISO obraz a mám hotovo. Ten druhý způsob zahrnuje modifikaci celého RAMdisku, ale zato je možno mít konfiguraci v krásném strukturovaném souboru bokem, jak popisuje Debianí wiki, nicméně ten tu rozebírat nebudu. Můžeme tedy vesele začít bušit příkazy.

wget http://archive.ubuntu.com/ubuntu/dists/bionic-updates/main/installer-amd64/current/images/netboot/mini.iso -O /tmp/mini.iso
mkdir /media/mini
mkdir /tmp/mini_custom
mount /tmp/mini.iso /media/mini -o loop
rsync -a /media/mini/ /tmp/mini_custom/

Nyní je potřeba editovat soubor /tmp/mini_custom/isolinux.cfg. Já jeho obsah úplně celý nahrazuji, takže uživatel vůbec neuvidí žádná menu a rovnou se spustí poloautomatizovaná instalace.

DEFAULT custom
PROMPT 0
LABEL custom
  KERNEL linux
  APPEND initrd=initrd.gz debian-installer/language=en debian-installer/country=CZ localechooser/preferred-locale=en_US.UTF8 keyboard-configuration/layoutcode=us netcfg/choose_interface=auto netcfg/get_hostname=new mirror/country=CZ mirror/http/mirror=cz.archive.ubuntu.com mirror/http/proxy= hw-detect/load_firmware=true anna/choose_modules=network-console network-console/authorized_keys_url=http://example.com/authorized_keys passwd/username=user passwd/user-fullname=user passwd/user-password=Sup3rS3cret passwd/user-password-again=Sup3rS3cret time/zone=Europe/Prague pkgsel/update-policy=none clock-setup/utc=true tasksel/first="OpenSSH server" preseed/late_command="cp -r /.ssh /target/root/"

Formát konfigurace ISOLINUXu bohužel vyžaduje, aby byl APPEND vypsán pouze na jediném řádku, takže ten jediný hnusný dlouhý řádek obsahuje všechny parametry pro automatizaci. Pak udělám totéž pro GRUB použitý při UEFI bootu. Ten má konfiguraci v souboru /tmp/mini_custom/boot/grub/grub.cfg. Jeho obsah nahradím následujícím

set timeout=0
menuentry "custom" {
  linux /linux debian-installer/language=en debian-installer/country=CZ localechooser/preferred-locale=en_US.UTF8 keyboard-configuration/layoutcode=us netcfg/choose_interface=auto netcfg/get_hostname=new mirror/country=CZ mirror/http/mirror=cz.archive.ubuntu.com mirror/http/proxy= hw-detect/load_firmware=true anna/choose_modules=network-console network-console/authorized_keys_url=http://example.com/authorized_keys passwd/username=user passwd/user-fullname=user passwd/user-password=Sup3rS3cret passwd/user-password-again=Sup3rS3cret time/zone=Europe/Prague pkgsel/update-policy=none clock-setup/utc=true tasksel/first="OpenSSH server" preseed/late_command="cp -r /.ssh /target/root/" ---
  initrd /initrd.gz
}

Dál potřebuji zajistit, aby mi UEFI zavaděč fungoval i když obsah image přenesu na USB disk. Standardní CD totiž zavádí pomocí El Torito specifikace, která je rozšířením standardu ISO 9660 a zavaděče definované tímto rozšířením jsou utopeny někde ve struktuře obrazu a nejsou vidět jako soubory v adresářové struktuře média. Při kopírování se na USB disk nepřenesou, takže musím UEFI boot zajistit dle UEFI specifikace, tedy pomocí souboru /efi/boot/bootx64.efi. Ten si vytáhnu ze souboru, který je součástí staženého obrazu netbootu.

mkdir /media/efi
mount /tmp/mini_custom/boot/grub/efi.img /media/efi
rsync -a /media/efi/ /tmp/mini_custom/

Nakonec už stačí jen přebalit ISO. U příkazu genisoimage dbejte zvýšené opatrnosti na pořadí parametrů, jinak se vám může stát, že si přepíšete některý z důležitých souborů zavaděčů anebo naopak nezapíšete nějakou informaci týkající se zavádění ISO obrazu.

genisoimage -r -V Ubuntu -J -l -c boot.cat -b isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e boot/grub/efi.img -no-emul-boot -o /tmp/mini_custom.iso /tmp/mini_custom/

Pak po sobě můžete uklidit.

umount /media/efi
umount /media/mini
rm -rf /media/efi /media/mini /tmp/mini_custom

Gratuluji. V tuto chvíli máte krásný a blbuvzdorný instalátor Ubuntu 18.04 v souboru /tmp/mini_custom.iso.

Z druhé strany


Mít ISO je sice fajn, ale pokud se má instalovat fyzický server, obvykle to není úplně to pravé ořechové. Firma o 30 zaměstnancích nejspíš infrastrukturu s TFTP a PXE bootem mít nebude a tak je potřeba z milého obrazu udělat fyzické médium, typicky jej nacpat na USB klíčenku.

Spousta návodu pro linux by poradila ISO překlopit pomocí dd. To ale nedělejte, protože náš obraz CD není hybridní a není na takovou věc připraven. Navíc místo ISOLINUXu, který je určen pro média typu ISO 9660 jej budeme chtít zavádět SYSLINUXem, který funguje prakticky stejně, ale je ušitý na míru USB a jiný diskovým zařízením. USB disk tedy doporučuji ručně naformátovat třeba fdiskem, vytvořit na něm oddíl typu FAT32 (fdisk typ c) a nastavit jej jako bootovatelný (v jazyku Windows „aktivní“). Pak postupovat v tomto duchu

mkfs.vfat -F 32 /dev/sdx1
mkdir /media/mini /media/usb
mount /tmp/mini_custom.iso /media/mini
mount /dev/sdx1 /media/usb
rsync -a /media/mini/ /media/usb/
cp /media/usb/isolinux.cfg /media/usb/syslinux.cfg
umount /media/usb /media/mini
syslinux -s /dev/sdx1
dd bs=440 count=1 conv=notrunc if=/usr/lib/SYSLINUX/mbr.bin of=/dev/sdx
rm -r /media/mini /media/usb

Nemáte-li binárku zvanou syslinux, najdete ji včetně drahocenných 440 bajtů Master Boot Recordu v balíku s překvapivým názvem syslinux.

Na Windows doporučuji můj oblíbený Universal USB Installer. Ten prostě spustíte, vybere distribuci, soubor s obrazem a USB disk a on se o všechno postará. V tomto případě ovšem nevybírejte Ubuntu Mini (Netboot installer), ačkoliv se zdá být nejrozumnější volbou. UUI počítá s tím, že image není upravený tak, jak ten náš, a na UEFI by nefungoval. Vyberte místo toho třeba Ubuntu Server Installer a upravené ISO mu vnuťte i když nebude mít odpovídající název. Nechcete-li použít UUI, Rufus funguje také uspokojivě.

Universal USB Installer

Po nastartování stroje a výběru patřičného bootovacího zařízení se rozjedou předinstalační kroky. První a zároveň i poslední obrazovka, kde musí uživatel něco potvrdit, je informace o staženém SSH klíči.

Potvrzení stažení SSH klíče

Po jejím odkývání pokračuje další nastavení instalačního prostředí a zastaví se až u prvního neautomatizovaného kroku, kterým je nastavení disků. V tuto chvíli se může hrdinný admin přihlásit na SSH jako uživatel installer. V terminálu pak vybere volbu Start installer a vesele pokračuje rozdělením disků tak, jako by seděl přímo před instalovaným strojem.