remote install party - pushing Debian over the internet


What?

We install Debian Linux on a windows computer that is far away from us and only accesible via the internet.

As a friend put it:

"This is somewhat equivalent to constructing a ship in a bottle. Except that the bottle is spray painted black and is possessed by evil demons inside. And if you fail at any step, it gets sealed from inside. Yep, that's pretty much it."

Why?

Toolbox

The full story

Building the ISO

Get the current netboot installer and unpack the iso, then the initrd:

wget http://cdn.debian.net/debian/dists/wheezy/main/installer-amd64/current/images/netboot/mini.iso -O original.iso
# if we are dealing with a 32bit system
# wget http://ftp.nl.debian.org/debian/dists/wheezy/main/installer-i386/current/images/netboot/mini.iso -O original.iso

mkdir mountpoint
mkdir cd-filesystem
sudo mount -o loop -t iso9660 original.iso ./mountpoint
cp -r mountpoint/* cd-filesystem/

mkdir initrd-filesystem
cd initrd-filesystem
gzip -dc ../cd-filesystem/initrd.gz | cpio -id

Now we fill the new file preseed.cfg in the folder "initrd-filesystem" with this:

# Installation Sources
d-i     mirror/http/hostname  string cdn.debian.net
d-i     mirror/http/directory string /debian/
d-i     mirror/suite          string 

# Post install APT setup
d-i     apt-setup/uri_type                select d-i
d-i     apt-setup/hostname                string cdn.debian.net
d-i     apt-setup/directory               string /debian/
d-i     apt-setup/another                 boolean false
d-i     apt-setup/security-updates        boolean true
d-i     finish-install/reboot_in_progress note
d-i     prebaseconfig/reboot_in_progress  note
d-i     apt-setup/non-free                boolean true
d-i     apt-setup/contrib                 boolean true

# Network Configuration
d-i     netcfg/get_hostname     string debian
d-i     netcfg/get_domain       string lan
d-i     netcfg/disable_dhcp     boolean false
d-i     mirror/http/proxy       string
d-i     netcfg/choose_interface select auto
d-i     netcfg/wireless_wep     string

# load non-free firmware if needed
d-i     hw-detect/load_firmware boolean true

# partition largest free chunk without confirmation
d-i     partman-auto/init_automatically_partition select biggest_free
d-i     partman/confirm boolean true
d-i     partman-partitioning/confirm_write_new_label boolean true
d-i     partman/choose_partition select finish
d-i     partman/confirm_nooverwrite boolean true

# install grub no matter what
d-i     grub-installer/with_other_os    boolean true

# Localization
d-i     console-tools/archs                 string skip-config
d-i     debian-installer/locale             string en_US
d-o     keyboard-configuration/xkb-keymap   select us
d-i     languagechooser/language-name-fb    select English
d-i     debian-installer/locale             select en_US.UTF-8
d-i     tzconfig/gmt                        boolean true
d-i     tzconfig/choose_country_zone/Europe select Lisbon
d-i     tzconfig/choose_country_zone_single boolean true
d-i     time/zone                           select  Europe/Lisbon
d-i     clock-setup/utc                     boolean true
d-i     kbd-chooser/method                  select American English
d-i     mirror/country                      string manual
d-i     clock-setup/ntp                     boolean false

# X11 config
xserver-xorg     xserver-xorg/autodetect_monitor              boolean true
xserver-xorg     xserver-xorg/config/monitor/selection-method select medium
xserver-xorg     xserver-xorg/config/monitor/mode-list        select 1024x768 @ 60 Hz
xserver-xorg     xserver-xorg/config/display/modes            multiselect 1024x768, 800x600

# passwords
d-i     passwd/root-password            password thisisverysecret
d-i     passwd/root-password-again      password thisisverysecret
d-i     passwd/user-fullname            string Max Mustermann
d-i     passwd/username                 string max
d-i     passwd/user-password            password thisisverysecret
d-i     passwd/user-password-again      password thisisverysecret

# minimal software selection
tasksel tasksel/first                   multiselect
d-i     pkgsel/include                  string openssh-server openvpn sudo screen

# diable exim4
exim4-config exim4/no_config            boolean true

# run our script
d-i preseed/late_command                string /opt/after_install.sh

Then we also create the script /opt/after_install.sh as follows. It allows our user to use sudo and copies the OpenVPN config.

#/bin/sh
in-target adduser max sudo
cp /opt/awesomevpn.conf /target/etc/openvpn/
exit 0

The following is an example for what /opt/awesomevpn.conf could look like. In particular it is useful to include certificates and the key directly.

client
remote mysuperawesomevpnhostname.com 1194
ca [inline]
cert [inline]
key [inline]
<ca>
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
</key>
comp-lzo yes
dev tun
proto tcp
nobind
auth-nocache
script-security 2
persist-key
persist-tun
ping 60
ping-restart 180
route-nopull

Now we first create a new initrd:

cd initrd-filesystem/
find . | cpio -H newc --create | gzip -9 > ../cd-filesystem/initrd.gz
cd ../cd-filesystem/
cp -p initrd.gz initrd.gz.orig
cd ..

Then we add the non-free firmware, because some computers will not even have network access without it. See DebianInstaller/NetbootFirmware for nice explanations of this hen-egg problem.

mkdir fwdownload
cd fwdownload
wget http://cdimage.debian.org/cdimage/unofficial/non-free/firmware/stable/current/firmware.tar.gz
tar -C firmware -zxf firmware.tar.gz
pax -x sv4cpio -s'%firmware%/firmware%' -w firmware | gzip -c >firmware.cpio.gz

cd ../cd-filesystem
cat initrd.gz.orig ../fwdownload/firmware.cpio.gz > initrd.gz
cd ..

Now we can build a new iso:

genisoimage -r -o rip_`date +%s`.iso -b isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table ./cd-filesystem

Fasten your seatbelt

The preseed configuration needs an empty area on the hard disk. Hence we need to shrink the windows partitions. We use the aged Partition Magic because it allows to partition windows systems almost while they are running. "Almost" meaning that it will reboot to apply changes but no interaction is needed during the reboot.

Now we could burn this image to a cd and start the computer. But wait, we are not at the computer and why waste a whole cd for a few MB? Is there a way to boot the installer from harddisk? Yes! UNetbootin to the rescue!

We transfer the iso to the windows computer and then make UNetbootin install it to C:/.

Now, we do not accept UNetbootin's offer to reboot. Because we would need physical access to the computer to choose it in Windows' boot menu. Instead we first make it the default before rebooting.

On Windows XP the boot menu settings can be accessed by Rightclick on "My Computer", "Properties", going to the "Adavanced" tab and then clicking on "Startup Settings" or so. Please don't ask me how to do this in newer versions ;-)

After making UNetbootin the default, reboot the computer.

Sit back and enjoy

Now you probably have to wait a long time. And probably it will not work the first time you try. Then you should probably call someone who can tell you what's on the screen ;-)

One of the following might have happened:

If everything goes well the installer will install a minimal Debian system with an openssh-server and then reboot into it. The boot loader GRUB will also add an entry for Windows but the default will be Debian.

Finally, if the system is running, thanks to OpenVPN it will also be reachable for us via ssh. Once logged in, we can customize the system however we want it. For example the following commands setup a minimal kde desktop.

apt-get update
apt-get install kdm kde-workspace
/etc/init.d/kdm restart

If you also need to configure the desktop itself without having physical access to the computer, you can also use x11vnc to connect to an X login screen.


CC-BY-SA Malvin Gattinger