How to install a new bare metal server at Hetzner ================================================= This is for setting up physical metal at Hetzner. Order ----- 1. get approval for the server, picking the specs from the [main website](https://www.hetzner.com/) 2. head to the [order page](https://robot.your-server.de/order) and pick the right server. pay close attention to the location, you might want to put it alongside other TPO servers (or not!) depending on redundancy or traffic requirements. Click `Add to shopping cart`, leaving all other fields as default. 3. in the `Server login details` page, you should leave `Type` set to `Public key`. If you do not recognize your public SSH key in there, head to the [server list](https://robot.your-server.de/server) and click on [key management](https://robot.your-server.de/key/index) to add your public keys 4. when you're certain of everything, click `Checkout` in the cart, review the order again and click `Order in obligation`. A confirmation email will be sent by Hetzner at the TPA alias when the order is filed. Then you wait for the order to complete before being able to proceed with the install. Ordering physical servers from Hetzner can be very fast: we've seen 2 minutes turn around times. Install ------- At this point you should have received an email from Hetzner with a subject like: Subject: Your ordered SX62 server It should contain the SSH fingerprint, and IP address of the new host which we'll use below. 1. login to the server using the IP address and host key hash provided above: ssh -o FingerprintHash=md5 -o UserKnownHostsFile=~/.ssh/authorized_keys.hetzner-rescue root@159.69.63.226 Note: the `FingerprintHash` parameter above is to make sure we match the hashing algorithm used by Hetzner in their email, which is, at the time of writing, MD5 (!). Newer versions of SSH will also encode the hash as base64 instead of hexadecimal, so you might want to decode the base64 into the latter using this: The `UserKnownHostsFile` is to make sure we don't store the (temporary) SSH host key. perl -MMIME::Base64 -e '$h = unpack("H*", decode_base64(<>)); $h =~ s/(..)(?=.)/\1:/g; print $h, "\n"' 2. Set a hostname (short version, not the FQDN): echo -n 'New hostname: ' && read hn && hostname "$hn" && exec bash 3. Partition disks. This might vary wildly between hosts, but in general, we want: * GPT partitionning, with space for a 8MB grub partition and cleartext `/boot` * software RAID (RAID-1 for two drives, RAID-5 for 3, RAID-10 for 4) * crypto (LUKS) * LVM, with separate volume groups for different medium (SSD vs HDD) We are experimenting with FAI's [setup-storage](https://manpages.debian.org/setup-storage) to partition disks instead of rolling our own scripts. You first need to checkout the installer's configuration: apt install git git clone https://git.torproject.org/admin/tsa-misc cd tsa-misc/installer git show-ref master Check that the above hashes match a trusted copy. Use the following to setup a Ganeti node, for example: apt install fai-setup-storage setup-storage -f "disk-config/gnt-fsn" -X TODO: convert the other existing `tor-install-format-disks-4HDDs` script into a `setup-storage` configuration. And finally mount the filesystems: . /tmp/fai/disk_var.sh mkdir /target mount "$ROOT_PARTITION" /target mkdir /target/boot mount "$BOOT_PARTITION" /target/boot 4. Review the network configuration, since it will end up in the installed instance: cat /target/etc/network/interfaces An example safe configuration is: auto lo iface lo inet loopback allow-hotplug eth0 iface eth0 inet dhcp The latter two lines usually need to be added as they are missing from Hetzner rescue shells: cat >> /etc/network/interfaces <<EOF allow-hotplug eth0 iface eth0 inet dhcp EOF TODO: fix this in a post-install debootstrap hook, or in grml-debootstrap already, see also [upstream issue 105](https://github.com/grml/grml-debootstrap/issues/105) and [issue 136](https://github.com/grml/grml-debootstrap/issues/136). 4. Install the system. This can be done with `grml-debootstrap` which will also configure grub, a root password and so on. This should get you started, assuming the formatted root disk is mounted on `/target` and that the boot device is defined by `$BOOT_DEVICE` (populated above by FAI): mkdir -p /target/run && mount -t tmpfs tgt-run /target/run && mkdir /target/run/udev && mount -o bind /run/udev /target/run/udev && bootdisk=/dev/nvme1n1 && ROOTPASSWORD=$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 30) && apt-get install -y grml-debootstrap && \ sed -e 's/postfix//; s/vlan//; s/bridge-utils//; s/ifenslave//; s/resolvconf//; s/zsh//; s/strace//; s/os-prober//; s/bzip2//; s/file//; s/lsof//; s/most//; $adbus $acryptsetup-initramfs ' /etc/debootstrap/packages > /root/grml-packages && mkdir -p /etc/debootstrap/post-scripts/ && cp /root/tsa-misc/installer/tor-install-luks-setup /etc/debootstrap/post-scripts/ && grml-debootstrap --grub "$BOOT_DEVICE" --target /target \ --hostname `hostname` --release buster \ --mirror https://mirror.hetzner.de/debian/packages/ \ --packages /root/grml-packages \ --password "$ROOTPASSWORD" \ --sshcopyid \ --remove-configs --defaultinterfaces && umount /target/run/udev /target/run 5. Once the bootstrapping is complete, you still need to make sure the system can boot as, the above doesn't (unfortunately) configure everything for you. First, make a reasonable etc/fstab: sed -e 's/^[[:space:]]*//' > /target/etc/fstab << EOF /dev/$vg/root / ext4 errors=remount-ro 0 1 /dev/md/boot /boot ext4 defaults 0 2 /dev/$vg/swap none swap sw 0 0 tmpfs /tmp tmpfs defaults,size=512m 0 0 EOF TODO: take the `fstab` from FAI. 7. setup dropbear-initramfs to unlock the filesystem on boot. this should already have been done by the `tor-install-luks-setup` hook deployed in the grml-debootstrap stage, but if not: /root/tsa-misc/installer/tor-install-luks-setup /target TODO: improve the way that script is deployed. TODO: use the FAI keyfiles and set a LUKS passphrase for the first disk. For example: LUKS_PASSPHRASE=$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 30) && echo $LUKS_PASSPHRASE | cryptsetup luksAddKey /dev/md1 --key-file=/tmp/fai/crypt_dev_md1 && echo $LUKS_PASSPHRASE | cryptsetup luksAddKey /dev/md2 --key-file=/tmp/fai/crypt_dev_md2 && cryptsetup luksRemoveKey /dev/md1 --key-file=/tmp/fai/crypt_dev_md1 && cryptsetup luksRemoveKey /dev/md2 --key-file=/tmp/fai/crypt_dev_md2 ... although that doesn't correctly setup the second disk to use a keyfile. TODO: Those keyfiles are precious: they could be used to bootstrap mandos configuration. Maybe we don't want to `luksRemoveKey` the darn thing. TODO: in an install following the above procedure, a keyfile was left unprotected in `/etc`. Make sure we have strong mechanisms to avoid that ever happening again. For example: chmod 0 /etc/luks/ TODO: in any case, move all of the above in the `tor-install-luks-setup` hook. 8. Review the crypto configuration: cat /target/etc/crypttab If the backing device is *NOT* an SSD, remove the `,discard` option. 9. mount the helper filesystems once more for fs in dev proc run sys ; do mount -o bind /$fs "/target/$fs"; done 10. Do the same with the RAID configuration, probably with something like: chroot /target sh -c "/usr/share/mdadm/mkconf > /etc/mdadm/mdadm.conf" TODO: move to a deboostrap post hook. 11. install grub on any secondary disk, for instance chroot /target grub-install /dev/nvme1n1 13. If any of those latter things changed, you need to regenerate the initramfs: chroot /target update-initramfs -u chroot /target update-grub 14. umount things: umount /target/run/udev || true && for fs in dev proc run sys ; do umount /target/$fs || true done && umount /target/boot && cd / && umount /target 15. close things vgchange -a n cryptsetup luksClose cpv_nvme mdadm --stop /dev/md* 16. Document the LUKS passphrase and root password in `tor-passwords` 17. Cross fingers and reboot: reboot Configuration ------------- See [[new-machine]] for post-install configuration steps, then follow [[new-machine-mandos]] for setting up the mandos client on this host.