Sunday, 11 October 2015

System Deployment (3 of x)

The desktop installer seems to work (its in day-to-day use now). Currently it builds an e17 desktop on-top of Debian, with enough support to rebuild everything in my repositories. It is stable enough to host the build system for remastering a server: the target environment.

Server overview.

The server is a VPS (virtual private server) running in a data-center belonging to the provided. The virtual machine runs inside a KVM hosting environment. Physical access is simulated through VNC  - importantly this connects to the host rather than the guest so it remains available during reboot and reinstall. Unfortunately the keymap is a bit screwed up and there is no way to change it. Most(!?!) important punctuation can be found by setting the local keymap to US, but it is a minimal environment.

The simulated CD can only be changed by someone with admin privileges on the host, so it requires a support ticket and 24-48hr turn-around time. For this reason it is left set to a virgin debian installer image.

Bootstrap of the installation environment.

One issue that crops up straight away is that although the netinst image can find the virtual driver for installation - it cannot find it directly at boot. This is not a problem for a simple clean install. But the re-installer will use the hd-media kernel/initrd to boot the cdrom image. And this system cannot find the virtual drive.

KVM uses paravirtualisation, so the kernel will need the virtio drivers (in particular virtio_blk) and
these are not in the hd-media images by default. The initial environment will look like this:

Partition 1: 1000MB, ext2, bootable
   /vmlinuz - default kernel image from hd-media
   /initrd.gz - modified hd-media initial ramdisk with extra modules for virtio
   /remaster.iso - preseeded debian installer for the target installer
Partition 2: 1000MB, swap
Partition 3: Remaining space, ext4, mounted as /
Grub installed on the MBR
  - Standard menuitem to boot /dev/vda3 into the target system.
  - Extra menuitem to boot kernel/initrd from /dev/vda1

The standard installer is used through VNC to partition the disk and get a working system onto /dev/vda3. To rebuild the initrd we use the following script in the desktop environment. This saves a huge amount of work: the environment created by the jessie installer is the environment that the jessie installer was built inside.

#!/bin/bash
rm -rf tmpramd
mkdir tmpramd
(cd tmpramd && gunzip -c ../hdmedia/initrd.gz | cpio -i)
cp /lib/modules/3.16.0-4-amd64/kernel/drivers/block/virtio_blk.ko tmpramd/lib/modules/3.16.0-4-amd64/kernel/drivers/block/
mkdir tmpramd/lib/modules/3.16.0-4-amd64/kernel/drivers/virtio
cp /lib/modules/3.16.0-4-amd64/kernel/drivers/virtio/*ko tmpramd/lib/modules/3.16.0-4-amd64/kernel/drivers/virtio/
cp /lib/modules/3.16.0-4-amd64/kernel/drivers/block/virtio_blk.ko tmpramd/lib/modules/3.16.0-4-amd64/kernel/drivers/block/
#sed -e 's:start-udev$:&\n/sbin/modprobe virtio_blk:' tmpramd/init >newinit
#mv newinit tmpramd/init
#chmod +x tmpramd/init
echo >>tmpramd/etc/rcS.d/virtio /sbin/modprobe virtio_blk
chmod +x tempramd/etc/rcS.d/virtio
#echo virtio_blk >>tmpramd/etc/modules
(cd tmpramd && find . | cpio -H newc -o | gzip >../cycled.gz)
scp cycled.gz main@face:initrd.gz

As the comments in the script show there are several ways to do this that do not seem to work. I don't why. If you have any idea please leave a comment. Trying to use /etc/modules to force loading the driver does nothing - perhaps this was 2.4 only thing that has been long superceded in the kernel? Inserting the modprobe into the init for the ramdisk just causes a kernel panic when it fails. Inserting the modprobe into the rcS.d means it is called later in init, when control is passed to the debian-installer-init script. This seems to work. [edit: no it doesn't. Some kind of stateful problem in testing, it looked like it worked but this is currently broken. Will update in a later post]. Inside the clean debian install we create /etc/grub.d/11_remaster and execute update-grub.

#!/bin/sh -e
cat << EOF
menuentry "Remaster ISO" {
set root='(hd0,1)'
#loopback loop /remaster.iso
linux /vmlinuz initrd=/initrd.gz root=/dev/vda1 vga=788 auto=true panic=20 priority=critical preseed/file=/cdrom/preseed.cfg ---
initrd /initrd.gz
}
EOF

This puts us in the position where we can execute the preseeded installer directly from the harddrive to build the target system. There is no way to avoid the partitioning step inside the preseeded installer, so it is vital that the partitions made in the original clean install are identical to those made in the preseeded installer. Overwriting the partition table with the same data does not lose any data on the disk.

The preseeded installer.

As with the desktop install the preseed file is wrapped inside the .iso for the installer. Looks very similar, same partitioning scheme: 1GB for installer images, 1GB for swap, rest for a single / file-system. No dynamic network, hardcoded to the static setup of the target server. The overlay that gets untar'd at the end overwrites the sshd config. No passwords, no root access. Only strong-passphrase keys, the public halves being in the .iso and converted directly into an .ssh/authorized_keys file. There is a single random string with the password for the main user, but this can only be used over VNC. Basic package load for the server.

d-i debian-installer/language string en
d-i debian-installer/country string SE
d-i debian-installer/locale string en_SE.UTF-8
d-i keyboard-configuration/xkb-keymap select sweden

d-i netcfg/choose_interface select eth0

# To pick a particular interface instead:
#d-i netcfg/choose_interface select eth1

# To set a different link detection timeout (default is 3 seconds).
# Values are interpreted as seconds.
#d-i netcfg/link_wait_timeout string 10

# If you have a slow dhcp server and the installer times out waiting for
# it, this might be useful.
#d-i netcfg/dhcp_timeout string 60
#d-i netcfg/dhcpv6_timeout string 60

# If you prefer to configure the network manually, uncomment this line and
# the static network configuration below.
d-i netcfg/disable_autoconfig boolean true

# If you want the preconfiguration file to work on systems both with and
# without a dhcp server, uncomment these lines and the static network
# configuration below.
#d-i netcfg/dhcp_failed note
#d-i netcfg/dhcp_options select Configure network manually

# Static network configuration.
d-i netcfg/get_ipaddress string 46.246.89.132
d-i netcfg/get_netmask string 255.255.255.128
d-i netcfg/get_gateway string 46.246.89.129
d-i netcfg/get_nameservers string 8.8.8.8
d-i netcfg/confirm_static boolean true

# IPv6 example
#d-i netcfg/get_ipaddress string fc00::2
#d-i netcfg/get_netmask string ffff:ffff:ffff:ffff::
#d-i netcfg/get_gateway string fc00::1
#d-i netcfg/get_nameservers string fc00::1
#d-i netcfg/confirm_static boolean true

d-i netcfg/get_hostname string face
d-i netcfg/get_domain string mechani.se
d-i netcfg/hostname string face
d-i netcfg/wireless_wep string # Disable that annoying WEP key dialog.

### Mirror settings
d-i mirror/protocol string ftp
d-i mirror/country string se
d-i mirror/ftp/hostname string ftp.se.debian.org
d-i mirror/ftp/directory string /debian

### Account setup
# Skip creation of a root account (normal user account will be able to
# use sudo).
d-i passwd/root-login boolean false
# Alternatively, to skip creation of a normal user account.
#d-i passwd/make-user boolean false

# Root password, either in clear text
#d-i passwd/root-password password abc
#d-i passwd/root-password-again password abc
# or encrypted using an MD5 hash.
#d-i passwd/root-password-crypted password [MD5 hash]

# To create a normal user account.
d-i passwd/user-fullname string The main user
d-i passwd/username string main
d-i passwd/user-password password xxxxxxxx
d-i passwd/user-password-again password xxxxxxxx

d-i clock-setup/utc boolean true
d-i time/zone string Europe/Stockholm
d-i clock-setup/ntp boolean true

d-i partman-auto/disk string /dev/vda
d-i partman-auto/method string regular
# Manual use of the installer on face reports 30.1GB
d-i partman-auto/expert_recipe string \
remasterPart :: \
1000 1000 1000 ext2 \
$primary{ } $bootable{ } \
method{ keep } \
. \
1000 1000 1000 linux-swap \
$primary{ } \
method{ swap } format{ } \
. \
15000 15000 150000 ext4 \
$primary{ } $bootable{ } \
method{ format } format{ } \
use_filesystem{ } filesystem{ ext4 } \
mountpoint{ / } \
.
#d-i partman/choose_recipe select atomic
d-i partman-auto/choose_recipe select remasterPart
d-i partman/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman-basicmethods/method_only boolean false
d-i partman-md/confirm boolean true

# Package setup
tasksel tasksel/first multiselect minimal
d-i pkgsel/include string openssh-server git python python-dateutil sudo bind9 bind9-host gitolite3 binutils dnsutils authbind curl
popularity-contest popularity-contest/participate boolean false

# MBR
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true
d-i grub-installer/bootdev string /dev/vda
d-i finish-install/reboot_in_progress note

d-i preseed/late_command string \
tar xzf /cdrom/overlay.tgz -C /target ; \
in-target chown -R main:main /home/main ; \
in-target chown root:root /etc/hosts ; \
in-target chown root:root /etc/ssh/sshd_config ; \
chmod 700 /target/home/main/.ssh ; \
in-target chown main:main /home/main/.ssh/authorized_keys ; \
chmod 600 /target/home/main/.ssh/authorized_keys



No comments:

Post a Comment