#!/bin/bash # # System installer. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public # License along with this program. If not, see # . # Load. source $APP_BASE/lib/hydra/functions || exit 1 hydra_config_load # Create a logical volume. function hydra_provision_lvcreate { local volume="$1" local size="$2" local space if [ -z "$volume" ] || [ "$size" == "0" ]; then return fi if ! lvdisplay $vg/$volume &> /dev/null; then echo "Creating logical volume $volume..." if [ "$size" == "-1" ]; then space="-l 100%FREE" else space="-L $size" fi # See http://forums.funtoo.org/viewtopic.php?id=1206 # https://bbs.archlinux.org/viewtopic.php?id=124615 if [ "$disable_zeroing" == "y" ]; then hydra_safe_run lvcreate -Z n $space -n $volume $vg else hydra_safe_run lvcreate $space -n $volume $vg fi fi } # Cryptsetup wrapper. function hydra_cryptsetup { if [ ! -z "$1" ] && [ -b "$1" ]; then hydra_safe_run cryptsetup --cipher aes-xts-plain64:sha256 --key-size 512 --hash sha512 --iter-time 5000 --use-random luksFormat $1 fi } # Create a physical volume. function hydra_provision_create_volume { local volume="$1" if [ -z "$volume" ] || [ ! -b "/dev/mapper/$vg-$volume" ]; then return fi if [ "$encrypt" == "y" ]; then echo "Creating encrypted $volume device..." hydra_cryptsetup /dev/mapper/$vg-$volume hydra_safe_run cryptsetup luksOpen /dev/mapper/$vg-$volume provision-$volume hydra_safe_run mkfs.ext4 /dev/mapper/provision-$volume if [ "$volume" == "root" ]; then install_device="/dev/mapper/provision-root" fi else echo "Creating $volume device..." mkfs.ext4 /dev/mapper/$vg-$volume if [ "$volume" == "root" ]; then install_device="/dev/mapper/$vg-root" fi fi } # Make sure there is provision config. function hydra_provision_config { local base_arch="`uname -m`" if [ "$base_arch" == "x86_64" ]; then base_arch="amd64" else base_arch="i386" fi hydra_user_config interactive y "Interactive mode? (y/n)" hydra_user_config device /dev/sdb "Destination device" hydra_user_config root_size 20G "Size of root partition" hydra_user_config swap_size 2000 "Swap size (in MB, 0 to not create it)" hydra_user_config home_size 20G "Size of home partition (0 to not create it, -1 for all free space)" hydra_user_config var_size 20G "Size of var partition (0 to not create it, -1 for all free space)" hydra_user_config encrypt y "Encrypt volumes? (y/n)" hydra_user_config garbage y "Pre-fill volumes with garbage? (y/n)" hydra_user_config random_swap y "Random swap? (y/n)" hydra_user_config disable_zeroing n "Disable zeroing of LVM volumes? (y/n)" hydra_user_config hostname machine "Hostname" hydra_user_config domain example.org "Domain" hydra_user_config arch $base_arch "System arch" hydra_user_config version jessie "Distro version" hydra_user_config vg $hostname "Install vg" hydra_user_config grub y "Setup GRUB? (y/n)" hydra_user_config mirror http://http.debian.net/debian/ "Debian mirror" } # Setup. if [ ! -z "$1" ]; then if [ -f "$1" ]; then echo "Using configuration from file $1..." source "$1" elif [ -f "$1.conf" ]; then echo "Using configuration from file $1.conf..." source "$1.conf" elif [ -f "$HYDRA_FOLDER/config/provision/$1" ]; then echo "Using configuration from $HYDRA_FOLDER/config/provision/$1..." source "$1" elif [ -f "$HYDRA_FOLDER/config/provision/$1.conf" ]; then echo "Using configuration from $HYDRA_FOLDER/config/provision/$1.conf..." source "$1.conf" elif [ -f "$APP_BASE/share/config/provision/$1" ]; then echo "Using configuration from $APP_BASE/share/config/provision/$1..." source "$1" elif [ -f "$APP_BASE/share/config/provision/$1.conf" ]; then echo "Using configuration from $APP_BASE/share/config/provision/$1.conf..." source "$1.conf" else echo "File not found: $1" exit 1 fi fi # Get config parameters. hydra_provision_config # Check for requirements. for req in debootstrap cryptsetup grub-pc lvm2 parted mdadm; do hydra_install_package $req done # Warning. if [ "$interactive" == "y" ]; then echo "WARNING: about to create partitions on $device!" echo "WARNING: make sure you have backups of the important data from this device!" echo "Press ENTER to continue, Ctrl-C to abort." read answer fi # Disk partitioning. hydra_safe_run parted -s -- $device mklabel gpt hydra_safe_run parted -s -- $device unit MB mkpart non-fs 2 3 hydra_safe_run parted -s -- $device unit MB mkpart ext2 3 200 hydra_safe_run parted -s -- $device unit MB mkpart ext2 200 -1 hydra_safe_run parted -s -- $device set 1 bios_grub on hydra_safe_run parted -s -- $device set 2 boot on hydra_safe_run parted -s -- $device set 3 lvm on # Use absolute paths for devices. boot_device="$device"2 syst_device="$device"3 reboot_device="`blkid | grep ^$boot_device: | cut -d ' ' -f 2 | sed -e 's/"//g'`" # Create volumes. echo "Creating the needed disk volumes..." if ! pvdisplay $syst_device &> /dev/null; then echo "Creating physical volume..." hydra_safe_run pvcreate $syst_device fi if ! vgdisplay $vg &> /dev/null; then echo "Creating volume group..." hydra_safe_run vgcreate $vg $syst_device fi # Create root partition. hydra_safe_run vgchange -a y $vg hydra_provision_lvcreate root $root_size # Create swap partition if [ "$swap_size" != "0" ]; then hydra_provision_lvcreate swap $swap_size fi # Create home partition. if [ "$home_size" != "0" ]; then hydra_provision_lvcreate home $home_size fi # Create var partition. if [ "$var_size" != "0" ]; then hydra_provision_lvcreate var $var_size fi # Garbage. if [ "$garbage" == "y" ]; then echo "Filling volumes with garbage..." dd if=/dev/urandom of=/dev/mapper/$vg-root if [ -b "/dev/mapper/$vg-home" ]; then dd if=/dev/urandom of=/dev/mapper/$vg-home fi if [ -b "/dev/mapper/$vg-var" ]; then dd if=/dev/urandom of=/dev/mapper/$vg-var fi if [ "$swap_size" != "0" ]; then dd if=/dev/urandom of=/dev/mapper/$vg-swap fi fi # Setup mountpoint and make sure it's not mounted due to a failed install. mkdir -p /tmp/debootstrap umount /tmp/debootstrap &> /dev/null for folder in proc dev home var boot sys; do umount /tmp/debootstrap/$folder &> /dev/null done # Create swap fs. if [ "$swap_size" != "0" ] && [ "$random_swap" != "y" ]; then hydra_cryptsetup /dev/mapper/$vg-swap hydra_safe_run cryptsetup luksOpen /dev/mapper/$vg-swap provision-swap hydra_safe_run mkswap /dev/mapper/provision-swap fi # Create root fs hydra_provision_create_volume root # Create home fs. if [ "$home_size" != "0" ]; then hydra_provision_create_volume home fi # Create var fs. if [ "$var_size" != "0" ]; then hydra_provision_create_volume var fi # Mount root volume. hydra_safe_run mount $install_device /tmp/debootstrap/ # Mount additional volumes. if [ "$home_size" != "0" ]; then mkdir /tmp/debootstrap/home if [ "$encrypt" == "y" ]; then hydra_safe_run mount /dev/mapper/provision-home /tmp/debootstrap/home else hydra_safe_run mount /dev/mapper/$vg-home /tmp/debootstrap/home fi fi if [ "$var_size" != "0" ]; then mkdir /tmp/debootstrap/var if [ "$encrypt" == "y" ]; then hydra_safe_run mount /dev/mapper/provision-var /tmp/debootstrap/var else hydra_safe_run mount /dev/mapper/$vg-var /tmp/debootstrap/var fi fi # Initial system install. echo "Installing base system..." hydra_safe_run debootstrap --arch=$arch $version /tmp/debootstrap/ $mirror # Initial configuration. echo "Applying initial configuration..." mount none -t proc /tmp/debootstrap/proc mount none -t sysfs /tmp/debootstrap/sys mount -o bind /dev/ /tmp/debootstrap/dev echo LANG=C > /tmp/debootstrap/etc/default/locale # Resolver configuration. echo "domain $domain" > /tmp/debootstrap/etc/resolv.conf echo "search $hostname.$domain" >> /tmp/debootstrap/etc/resolv.conf grep nameserver /etc/resolv.conf >> /tmp/debootstrap/etc/resolv.conf # Hostname configuration. echo $hostname.$domain > /tmp/debootstrap/etc/hostname echo "127.0.0.1 localhost" >> /tmp/debootstrap/etc/hosts echo "127.0.0.1 $hostname $hostname.$domain" >> /tmp/debootstrap/etc/hosts # Invert hostname contents to avoid http://projects.puppetlabs.com/issues/2533 tac /tmp/debootstrap/etc/hosts > /tmp/debootstrap/etc/hosts.new mv /tmp/debootstrap/etc/hosts.new /tmp/debootstrap/etc/hosts # Initial upgrade. echo "Applying initial upgrades..." chroot /tmp/debootstrap/ apt-get update chroot /tmp/debootstrap/ apt-get upgrade -y chroot /tmp/debootstrap/ apt-get install locales cryptsetup lvm2 initramfs-tools -y # Crypttab. echo "Configuring crypttab..." echo "# " > /tmp/debootstrap/etc/crypttab if [ "$encrypt" == "y" ]; then cat > /tmp/debootstrap/etc/crypttab <<-EOF root /dev/mapper/$vg-root none luks EOF fi if [ "$home_size" != "0" ] && [ "$encrypt" == "y" ]; then cat >> /tmp/debootstrap/etc/crypttab <<-EOF home /dev/mapper/$vg-home none luks EOF fi if [ "$var_size" != "0" ] && [ "$encrypt" == "y" ]; then cat >> /tmp/debootstrap/etc/crypttab <<-EOF var /dev/mapper/$vg-var none luks EOF fi if [ "$swap_size" != "0" ] && [ "$random_swap" == "y" ]; then cat >> /tmp/debootstrap/etc/crypttab <<-EOF swap /dev/mapper/$vg-swap /dev/random swap,cipher=aes-xts-plain64:sha256 EOF fi if [ "$swap_size" != "0" ] && [ "$random_swap" != "y" ]; then cat >> /tmp/debootstrap/etc/crypttab <<-EOF swap /dev/mapper/$vg-swap none luks,swap EOF fi # Fstab. echo "Configuring fstab..." echo "" > /tmp/debootstrap/etc/fstab if [ "$swap_size" != "0" ]; then cat >> /tmp/debootstrap/etc/fstab <<-EOF /dev/mapper/swap none swap sw 0 0 EOF fi if [ "$encrypt" == "y" ]; then cat >> /tmp/debootstrap/etc/fstab <<-EOF /dev/mapper/root / ext4 defaults,errors=remount-ro 0 1 EOF else cat >> /tmp/debootstrap/etc/fstab <<-EOF /dev/mapper/$vg-root / ext4 defaults,errors=remount-ro 0 1 EOF fi if [ "$home_size" != "0" ]; then if [ "$encrypt" == "y" ]; then cat >> /tmp/debootstrap/etc/fstab <<-EOF /dev/mapper/home /home ext4 defaults,errors=remount-ro 0 2 EOF else cat >> /tmp/debootstrap/etc/fstab <<-EOF /dev/mapper/$vg-home /home ext4 defaults,errors=remount-ro 0 2 EOF fi fi if [ "$var_size" != "0" ]; then if [ "$encrypt" == "y" ]; then cat >> /tmp/debootstrap/etc/fstab <<-EOF /dev/mapper/var /var ext4 defaults,errors=remount-ro 0 2 EOF else cat >> /tmp/debootstrap/etc/fstab <<-EOF /dev/mapper/$vg-var /var ext4 defaults,errors=remount-ro 0 2 EOF fi fi # Grub. if [ "$grub" == "y" ]; then echo "Boot device setup..." hydra_safe_run mkfs.ext4 $boot_device hydra_safe_run mount $boot_device /tmp/debootstrap/boot echo "$reboot_device /boot ext4 defaults,errors=remount-ro 0 2" >> /tmp/debootstrap/etc/fstab echo "Setting up GRUB..." hydra_safe_run chroot /tmp/debootstrap/ apt-get install grub-pc -y fi # Kernel. echo "Installing kernel..." cat > /tmp/debootstrap/etc/initramfs-tools/modules <<-EOF dm-mod dm-crypt dm-raid aes twofish sha256 EOF cat > /tmp/debootstrap/etc/kernel-img.conf <<-EOF do_initrd = Yes EOF if [ "$arch" == "i386" ]; then kernel_arch="686" else kernel_arch="$arch" fi if [ "$version" == "squeeze" ]; then hydra_safe_run chroot /tmp/debootstrap apt-get install linux-image-2.6-vserver-$kernel_arch -y else hydra_safe_run chroot /tmp/debootstrap apt-get install linux-image-$kernel_arch -y fi # Initramfs. echo "Creating initramfs..." hydra_safe_run chroot /tmp/debootstrap update-initramfs -v -u # Utils. echo "Installing basic utilities..." chroot /tmp/debootstrap apt-get install screen cron lsb-release openssl -y # Ssh. echo "Installing OpenSSH daemon..." chroot /tmp/debootstrap apt-get install openssh-server -y echo "OpenSSH fingerprints:" chroot /tmp/debootstrap ssh-keygen -l -f /etc/ssh/ssh_host_dsa_key.pub chroot /tmp/debootstrap ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub # Accounts. echo "Installing sudo..." chroot /tmp/debootstrap apt-get install sudo -y echo "Choose a root password." chroot /tmp/debootstrap passwd root cat <<-EOF Now proceeed with final steps: - Create an user account with sudo privileges. - Network setup. - Review fstab, crypttab and optional GRUB configuration. - Rename volume group $vg if needed, updating fstab and crypttab accordingly. See http://padrao.sarava.org/install for more information. EOF