#!/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 "$HYDRA_FOLDER/config/provision/$1"
elif [ -f "$HYDRA_FOLDER/config/provision/$1.conf" ]; then
echo "Using configuration from $HYDRA_FOLDER/config/provision/$1.conf..."
source "$HYDRA_FOLDER/config/provision/$1.conf"
elif [ -f "$APP_BASE/share/config/provision/$1" ]; then
echo "Using configuration from $APP_BASE/share/config/provision/$1..."
source "$APP_BASE/share/config/provision/$1"
elif [ -f "$APP_BASE/share/config/provision/$1.conf" ]; then
echo "Using configuration from $APP_BASE/share/config/provision/$1.conf..."
source "$APP_BASE/share/config/provision/$1.conf"
else
echo "Profile 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 "#