#!/bin/bash
set +o xtrace +o verbose +o errexit -o errtrace
trap 'set +o errexit; return 1' ERR
trap 'set +o xtrace +o verbose +o errexit +o errtrace; return 2' INT TERM
version=0.991

############################################################################
#
#  lmdescrypt 0.991
#
# Download shortlinks: https://4e4.win/lm or http://j.mp/lmdescrypt
#
# This script installs Linux Mint Debian Edition (201403), LMDE2 (201503 or
#  201701), LMDE3 (201808), LMDE4 (202004) or regular Linux Mint 17, 17.1/2/3,
#  18, 18.1/2/3, 19, 20, or Ubuntu 18.04, either i686 or amd64, with MSDOS or
#  GPT partitions, with UEFI or not.
# The result: a fully LUKS encrypted system, with LVM2 volumes of root and
#  swap (and optionally: data) with optional boot partition
#  (with optional boot-from-iso-file).
#
# Shortlink to download the script: http://4e4.win/lmdescrypt
# Tutorial on Linux Mint community:
#  https://community.linuxmint.com/tutorial/view/2265
# Gitlab page: https://gitlab.com/pepa65/lmdescrypt
# Questions? Email pepa65@passchier.net or post an Issue on the gitlab page.
#
############################################################################
### CONTENTS:
## - INSTRUCTIONS for preparation and use
## - SETTINGS to be adjusted
## - FUNCTIONS used internally
## - MAIN action
############################################################################

############################################################################
#### INSTRUCTIONS
############################################################################
##
### 1. Boot the Live environment
##
### 2. Open a Terminal (Menu/Terminal of Ctrl-Alt-T) and enter:
##> sudo -i
##> wget 4e4.win/lmdescrypt
##
### 3. If needed, adapt the SETTINGS section:
##> nano lmdescrypt
##
### 4. Make sure all the partitions mentioned in SETTINGS exist
## For example, (re)partition the drive like this for non-UEFI
##  (erasing all, taking up all space):
##
##> sgdisk -Zon1::+2M -t1:ef02 -c1:BIOS -n 2::-0 -t2:8e00 -c2:X -g /dev/sda
##
## For a UEFI setup instead, this example works:
##
##> sgdisk -Zon1::+260M -t1:ef00 -c1:EFI -n2::-0 -t2:8e00 -c2:X -g /dev/sda
##
##  (This is giving almost the whole drive to the encrypted lvm2)
##
### 5. Start the script:
##
##> source lmdescrypt
##
### 6. Answer the questions as they come up:
##  - set password for encryption
##  Then after a wait for all the preparations to have happened:
##  - set password for user
##  - set timezone
##  - configure keyboard
##
### And that's it!
##
### Installing into a pre-existing environment
##  Using a pre-existing boot-partition, LUKS partition and LVM Logical
##   Volumes is entirely supported.
##  Not having a separate boot partition is also supported: total encryption!
##  Multiple boot setups with other OSes also works out of the box.
##  MBR, GPT partition tables and UEFI work according to configuration.
##
############################################################################

############################################################################
#### SETTINGS
############################################################################
## Review all settings in this section

### The device to be booted (for the grub bootloader: usually a drive!):
grub_device=/dev/sda

## Adjust if needed (not needed if following the suggested partitioning)
## Specify the partitions you created by any valid device path, like:
## /dev/disk/by-label/...  /dev/...  /dev/disk/by-id/...
## Total encryption: boot_part should be empty
## UEFI setup: Must have an efi partition (type ef00) of at least 260M with a
##  VFAT filesystem, will be formatted if not yet formatted!
## GPT non-UEFI setup: Must have a bios partition (type ef02) of at least 2M!
### Partitions to use:
boot_part=
crypt_part=/dev/sda2

## When boot_part is not set, this is ignored
## If the boot partition is too small, the install will fail in the end!
### Set to 1 to include this iso as a file on boot partition to boot from
include_isofile=1

## When booting with total encryption, it is necessary to enter the password
##  twice, once for grub and once for the kernel to decrypt the LUKS partition
## Entering a password only once to unlock is possible by using a keyfile that
##  is stored in the initrd file, but anyone with read access to the initrd
##  file could read it and use it to decrypt the LUKS-encrypted partition!
### Set to 1 to use an initrd keyfile (INSECURE!) when doing total encryption:
insecure_keyfile=0

## Set to 1 only if you already have a LUKS encrypted partition that you want
##  to wipe and start from scratch. If set to 0 and there are pre-existing
##  volumes that you want to erase, you can do it manually:
##>  cryptsetup luksOpen <crypt_part> <crypt_label>
##>  lvremove /dev/<vg_label>/<volumelabel>
### Wipe out the crypt-partition before setup, even if already set up, if 1:
force_reencrypt=0

## No strict need to adjust, unless paranoid. WARNING: Putting 1 here will
##  take a LONG time (depending on partition size) - let it run overnight!
### Check for bad blocks and fill with pseudorandom data if 1:
force_random=0

## No need to adjust unless re-using existing volumes!
## If a Volume Group / Logical Volume with this name EXISTS, IT WILL BE USED!
## The data_label will also be the name of the mountpoint.
## If empty, the default NAME (as in NAME_label) will be used.
### Filesystem labels (no spaces):
boot_label=
vg_label=
crypt_label=
root_label=
swap_label=
data_label=

## Don't allot more space than available, and at least 6GB for root.
## Specify lvm2 volume sizes in gigabytes (G) or megabytes (M), no decimal
##  points or spaces, like: 10G or 200M
## - if empty (only for swap or data) it will NOT BE USED
## - if EXISTING it will NOT be created, and then the Logical Volume needs
##   to exist already (and so should the Volume Group then!)
## - If REST (only for root or data, not both) then the rest of the available
##   space will be used
## - DEFAULT (only for swap) means 40% of RAM size (/sys/power/image_size)
##   (See: https://www.kernel.org/doc/Documentation/power/interface.txt)
### Logical volume usage & sizes:
root_size=REST
swap_size=DEFAULT
data_size=

## Adjust if re-using preexisting boot or data volumes!
## Fill in the desired filesystem-type, empty means it will NOT BE FORMATTED!
##  (Pre-existing filesystem will be kept!)
## Supported for boot and root: btrfs ext2 ext3 ext4 reiserfs xfs.
## For swap: swap. For data: btrfs ext2 ext3 ext4 hfs hfsplus jfs minix msdos
##  ntfs reiserfs vfat xfs
### Filesystems:
boot_fs=ext4
root_fs=ext4
swap_fs=swap
data_fs=

## Adjust if you require another encryption scheme, see /proc/crypto.
## Find the speeds on your hardware (and choose accordingly) by:
##> cryptsetup benchmark
## The -i parameter is the number of milliseconds iterating on THIS system!
### Parameters for cryptsetup luksFormat:
cryptopts='-s 512 -h sha512 -i 5000 --type luks1'

## Adjust according to preference
### Username and hostname (no spaces):
username=me
hostname=mine

## Adjust according to preference; internet connection required!
### Extra packages to install (in between single quotes, seperated by space):
packages=''

############################################################################
#### FUNCTIONS
############################################################################

Echo(){ ## $1=message
	echo -n '________________________________________________________________'
	echo -e '_______________\n'
	echo -e "  $1"
	echo -n '________________________________________________________________'
	echo -e '_______________\n'
}

## To really exit it needs to be followed by 'return' in the main body!
Exit(){ ## $1=message
	Echo "ERROR: $1\n  ABORTING"
}

Warning(){ ## $1=message
	echo -e "\n  WARNING: $1\n"
}

Mkfs(){ ## $1=fs $2=label $3=dev $4=kind
	case $1 in
		hfs|hfsplus|jfs|minix|msdos|vfat|ntfs) [[ ! $4 = data ]] && return 3 ;;&
		## Continue even if the above pattern matched (unless $4 isn't data)
		btrfs) mkfs.$1 -f -L "$2" "$3" ;;
		ext2|ext3|ext4) mkfs.$1 -F -L "$2" "$3" ;;
		hfs) mkfs.$1 -h -v "$2" "$3" ;;
		hfsplus) mkfs.$1 -J -v "$2" "$3" ;;
		jfs) mkfs.$1 -q -L "$2" "$3" ;;
		minix) mkfs.$1 "$3" ;;
		msdos|vfat) mkfs.$1 -n "$2" "$3" ;;
		ntfs) mkfs.$1 -f -F -U -L "$2" "$3" ;;
		reiserfs) mkfs.$1 -ffl "$2" "$3" ;;
		xfs) mkfs.$1 -f -L "$2" "$3" ;;
		*) return 4 ;;
	esac
}

Checklabel(){ ## $1: labelname
	label="$1_label"
	content=$(eval "echo \$$label")
	[[ $content ]] || eval "$label=$1"
	[[ ! $content = ${content/ } ]] &&
		Exit "Label $label contains spaces: '$content'"
}

############################################################################
#### MAIN
############################################################################

self=$(basename $BASH_SOURCE)

## If not run interactively, don't run
[[ $- != *i* ]] &&
	Exit "Must be sourced! Run it like:\n   source $self" &&
	exit 1
((EUID)) &&
	Exit "Must be run with root privileges, do:\n   sudo -i\n   source $self" &&
	return 5

## Set parameters from commandline
for p in "$@"
do
	[[ ! $p =~ ^[a-z_][a-z0-9_]*= ]] &&
		Exit "No variable assignment: $p" && return 6
	q="${p/=/=\'}'"
	! eval "$q" && Exit "Failed argument evaluation: '$p'" && return 7
	echo "    ${q%%=*}: ${q#*=}"
done

## Check existence of mandatory devices
[[ ! -w "$crypt_part" ]] &&
	Exit "Crypt device does not exist or is not writable: '$crypt_part'" &&
	return 8
[[ ! -w "$grub_device" ]] &&
	Exit "Grub device does not exist or is not writable: '$grub_device'" &&
	return 9

## Check names, labels, root_fs
[[ ! $username =~ ^[a-z_][a-z0-9_]*$ ]] &&
	Exit "Illegal format for username: '$username'" && return 10
[[ ! $hostname =~ ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$ ]] &&
	Exit "Illegal format for hostname: '$hostname'" && return 11
Checklabel crypt && return 12
Checklabel vg && return 13
Checklabel boot && return 14
Checklabel root && return 15
Checklabel swap && return 16
Checklabel data && return 17
[[ ! $root_fs =~ ^(btrfs|ext2|ext3|ext4|reiserfs|xfs|)$ ]] &&
	Exit "Wrong value for root_fs: '$root_fs'" && return 18

## Determine root and data partition usage & size
[[ $root_size ]] && [[ ! $root_size = REST ]] &&
	[[ ! $root_size = EXISTING ]] && [[ ! $root_size =~ [1-9][0-9]*[MG] ]] &&
	Exit "Invalid format root_size: '$root_size'" && return 19
if [[ $data_size = REST ]]
then
	[[ $root_size = REST ]] &&
		Exit "Settings data_size and root_size can't both be REST" && return 20
	lvm_data='-l 100%FREE -Zy'
else
	if [[ $data_size && ! $data_size = EXISTING ]]
	then
		[[ ! $data_size =~ [1-9][0-9]*[MG] ]] &&
			Exit "Invalid format data_size: '$data_size'" && return 21
		lvm_data="-L $data_size -Zy"
	fi
fi

## Set swap size
if [[ $swap_size = DEFAULT ]]
then
	lvm_swap="-L $(cat /sys/power/image_size)B -Cy -Zy"
else
	if [[ ! $swap_size = EXISTING ]]
	then
		[[ $swap_size ]] && [[ ! $swap_size =~ [1-9][0-9]*[MG] ]] &&
			Exit "Invalid format swap_size: $swap_size" && return 22
		lvm_swap="-L $swap_size -Cy -Zy"
	fi
fi

## Check type of setup
gdisk=$(echo 2 |gdisk -l "$grub_device")
efi_part=
if ! grep -q ' GPT: not present$' <<<"$gdisk"
then  ## GPT partition scheme
	if [[ -e /sys/firmware/efi ]]
	then  ## UEFI: so it is an amd64 architecture that supports UEFI
		read n discard <<<"$(grep ' EF00  ' <<<"$gdisk" |head -1)"
		[[ -z $n ]] && Exit "UEFI without type ef00 efi partition!" && return 23
		efi_part="$grub_device$n"
		[[ ! $(lsblk "$efi_part" -no FSTYPE) = vfat ]] &&
			mkfs.vfat -n EFI "$efi_part"
	else  ## non-UEFI GPT setup
		! grep -q ' EF02  ' <<<"$gdisk" &&
			Exit "Non-UEFI GPT setup without type ef02 bios partition" && return 24
	fi
fi

Echo "$self $version\n  Install Linux Mint with LUKS encryption"

## Encrypt
pwf=$(mktemp) pwf2=$(mktemp)
chmod 600 "$pwf" "$pwf2"
while [[ ! -s "$pwf" ]]
do
	/lib/cryptsetup/askpass "Enter encryption password:" >"$pwf"
	echo
	if [[ -s "$pwf" ]]
	then
		/lib/cryptsetup/askpass "Enter the same password again:" >"$pwf2"
		echo
		diff -q --label $'\b\b\b\b\b\b\b\bFirst' "$pwf" \
				--label "second password" "$pwf2" || shred -u "$pwf"
		shred -u "$pwf2"
	else
		echo -e "Empty password not allowed\n"
	fi
done

if ((force_reencrypt))
then
	((force_random)) && badblocks -c 10240 -s -w -t random -v "$crypt_part"
	cryptsetup luksFormat $cryptopts "$crypt_part" --key-file "$pwf"
else
	cryptsetup isLuks "$crypt_part" &&
		Warning "$crypt_part is already formatted, reencryption not forced" ||
		cryptsetup luksFormat $cryptopts "$crypt_part" --key-file "$pwf"
fi

if [[ -z $boot_part ]] && ((insecure_keyfile))
then
	key=crypto_keyfile.bin
	dd bs=512 count=4 if=/dev/urandom of="/root/$key"
	cryptsetup luksAddKey "$crypt_part" "/root/$key" --key-file "$pwf"
fi

## Decrypt if not yet mapped
crypt_dev="/dev/mapper/$crypt_label"
[[ ! -b "$crypt_dev" ]] &&
	! cryptsetup luksOpen "$crypt_part" $crypt_label --key-file "$pwf" &&
	shred -u "$pwf" &&
		Exit "Failed to open the encrypted partition $crypt_part" && return 25
shred -u "$pwf"
crypt_uuid=$(blkid -s UUID -o value "$crypt_part")

## Make lvm2 volumes if not there yet and make filesystems if wanted
vgchange -ay
vg_dev="/dev/mapper/$vg_label"
[[ "  $vg_label" = "$(vgs --noheadings -o vg_name)" ]] ||
	vgcreate -Zy $vg_label $crypt_dev
root_dev="/dev/$vg_label/$root_label"
data_dev="/dev/$vg_label/$data_label"
swap_dev="/dev/$vg_label/$swap_label"

## Create & format swap if wanted
if [[ $swap_size ]]
then
	[[ ! -h $swap_dev ]] && lvcreate -Wy $lvm_swap -n $swap_label $vg_label
	if [[ $swap_fs ]]
	then
		[[ ! $swap_fs = swap ]] && Exit "Wrong value for swap_fs: '$swap_fs'" &&
			return 26 ||
			mkswap -f -L $swap_label "$swap_dev"
	fi
fi

## Create and format root partition, and data partition if wanted
[[ ! $root_size = REST ]] && [[ ! -h $root_dev ]] &&
	lvcreate -Wy -L $root_size -Zy -n $root_label $vg_label
if [[ $data_size ]]
then  ## Create if it doesn't exist and format if required
	[[ ! -h $data_dev && $data_size = EXISTING ]] &&
		Exit "There is no existing data device $data_dev" && return 27
		lvcreate -Wy $lvm_data -n $data_label $vg_label
	if [[ $data_fs ]]
	then
		! Mkfs "$data_fs" "$data_label" "$data_dev" data &&
			Exit "Unsupported filesystem $data_fs for data volume $data_dev with label $data_label" &&
			return 28
	else  ## No data filesystem specified: existing or bust
		if [[ $data_size = EXISTING ]]
		then
			! data_fs=$(lsblk "$data_dev" -no FSTYPE 2>/dev/null) &&
				Exit "No filesystem specified for data volumeand none present" &&
				return 29
		else
			Exit "No filesystem specified for data volume"
			return 30
		fi
	fi
fi
[[ $root_size = REST ]] && [[ ! -h $root_dev ]] &&
	lvcreate -Wy -l 100%FREE -Zy -n $root_label $vg_label
if [[ $root_fs ]]
then
	! Mkfs "$root_fs" "$root_label" "$root_dev" root &&
		Exit "Unsupported filesystem $root_fs for root-device $root_dev with label $root_label" &&
		return 31
else
	root_fs=$(lsblk "$root_dev" -no FSTYPE 2>/dev/null)
	[[ -z $root_fs ]] &&
		Exit "Root volume is not has no filesystem, fill in 'root_fs'" &&
		return 32
	[[ ! $root_fs =~ ^(btrfs|ext2|ext3|ext4|reiserfs|xfs)$ ]] &&
		Exit "Root partition has unsupported filesystem: $root_fs" && return 33
fi

if [[ $boot_part ]]
then
	[[ ! $boot_fs =~ ^(btrfs|ext2|ext3|ext4|reiserfs|xfs|)$ ]] &&
		Exit "Wrong value for boot_fs: '$boot_fs'" && return 34
	if [[ $boot_fs ]]
	then
		! Mkfs "$boot_fs" "$boot_label" "$boot_part" boot &&
			Exit "Unsupported filesystem $boot_fs for boot-device $boot_part with label $boot_label" &&
			return 35
	else
		boot_fs=$(lsblk "$boot_part" -no FSTYPE 2>/dev/null)
		[[ -z $boot_fs ]] &&
			Exit "Boot partition $boot_part has no filesystem, fill in 'boot_fs' (or leave boot_part empty)" &&
			return 36
	fi
	boot_uuid=$(blkid -s UUID -o value "$boot_part")
fi

## Mount
[[ $swap_size ]] && swapon "$swap_dev" && swapon -s
target='/target'
mkdir -p "$target"
mount "$root_dev" "$target"
if [[ $boot_part ]]
then
	mkdir -p "$target/boot"
	mount "$boot_part" "$target/boot"
fi
if [[ $data_size ]]
then
	mkdir -p "$target/$data_label"
	mount "$data_dev" "$target/$data_label"
fi

## Copy
rofsde='/lib/live/mount/rootfs/filesystem.squashfs'
rofslm='/rofs'
lmde=0 lmde4=0
if [[ -d /lib/live ]]
then  ## Debian Edition
	[[ -h $rofsde/vmlinuz ]] && lmde4=1
	lmde=1
	rofs=$rofsde
else  ## regular Mint
	rofs=$rofslm
fi
Echo "Copying the system files..."
cp -a "$rofs"/* "$target"
aptsrc="/etc/apt/sources.list"
rm "$target/$aptsrc"
osrelease=$(</etc/os-release)
grep -q '^ID=ubuntu' <<<"$osrelease" && apt-add-repository universe
! grep -q 'Linux Mint 19' <<<"$osrelease" && cp "$aptsrc" "$target/$aptsrc"

## Prepare root
echo "proc /proc proc defaults 0 0" >"$target/etc/fstab"
[[ $root_fs = btrfs ]] &&
	echo "$root_dev / $root_fs defaults,compress 0 1" >>"$target/etc/fstab" ||
	echo "$root_dev / $root_fs defaults,relatime,errors=remount-ro 0 1" \
			>>"$target/etc/fstab"
[[ $swap_size ]] &&
	echo "$swap_dev $swap_label swap sw 0 0" >>"$target/etc/fstab"
[[ $data_size ]] &&
	echo "$data_dev /$data_label $data_fs relatime 0 2" >>"$target/etc/fstab"
p3=none p4=luks
if [[ -z $boot_part ]]
then
	if ((insecure_keyfile))
	then
		keytarget="$target/etc/initramfs-tools/hooks/crypto_keyfile"
		mv "/root/$key" "$target/root/$key"
		chmod 000 "$target/root/$key"
		echo "cp /root/$key \"\${DESTDIR}\"" >"$keytarget"
		chmod +x "$keytarget"
		p3="/$key"
		p4="luks,keyscript=/bin/cat"
	fi
	sed -i '/^GRUB_TIMEOUT/a GRUB_ENABLE_CRYPTODISK=y' "$target/etc/default/grub"
	gcl="GRUB_CMDLINE_LINUX=\"cryptdevice=$crypt_part:$crypt_label\""
	sed -i "s@^GRUB_CMDLINE_LINUX=\"\"@$gcl@" "$target/etc/default/grub"
	sed -i 's@ splash"$@"@' "$target/etc/default/grub"
else
	echo "UUID=$boot_uuid /boot $boot_fs relatime 0 2" >>"$target/etc/fstab"
	if ((include_isofile))
	then
		cd=$(df |grep -o '^/dev/sr..')
		isoname=$(grep '^GRUB_TITLE=' "$target/etc/linuxmint/info")
		isoname=${isoname/GRUB_TITLE=/}
		isofile="/$(date +%s).iso"
		Echo "Copying the iso..."
		dd if=$cd of="$target/boot$isofile"
		(cd "$target/boot"; ln -s "$isofile" "$isoname")
		((lmde)) && dir=live || dir=casper
		sdxn=$(readlink -e "$boot_part")
		x=$(grep -o '/sd.' <<<"$sdxn")
		root="hd$(($(printf '%d' "'${x: -1}")-97)),msdos${sdxn//[^0-9]/}"
		echo "ISO $isoname is on ($root)$isofile"
		cat <<-X >>"$target/etc/grub.d/40_custom"
			menuentry "Boot from ISO $isoname ($isofile)" {
			  set root='$root'
			  set isofile='$isofile'
			  loopback loop \$isofile
			  linux (loop)/$dir/vmlinuz boot=$dir iso-scan/filename=\$isofile noeject noprompt splash -- 
			  initrd (loop)/$dir/initrd.lz
			}
		X
	fi
fi
sed -i 's/^GRUB_TIMEOUT=10/GRUB_TIMEOUT=4/' "$target/etc/default/grub"
sed -i 's/^GRUB_HIDDEN_TIMEOUT=0/#GRUB_HIDDEN_TIMEOUT=0/' "$target/etc/default/grub"
echo "$crypt_label UUID=$crypt_uuid $p3 $p4" >"$target/etc/crypttab"
sed "s/mint/$hostname/g" /etc/hosts >"$target/etc/hosts"
echo $hostname >"$target/etc/hostname"
echo "$LANG UTF-8" >>"$target/etc/locale.gen"
mv "$target/etc/lvm/lvm.conf" "$target/etc/lvm.conf_orig"
echo -e "devices {\n  multipath_component_detection = 0\n  md_component_detection = 0\n}\n\nactivation {\n  udev_sync = 0\n  udev_rules = 0\n}\n" >"$target/etc/lvm/lvm.conf"
mdm=/etc/mdm/mdm.conf
ldm=/etc/lightdm/lightdm.conf
[[ -f $mdm ]] && dm=$mdm || dm=$ldm
sed "s/mint/$username/g" "$dm" >"$target$dm"
rm -- "$target/etc/resolv.conf"  ## remove symlink
cp /etc/resolv.conf "$target/etc"
cryptsetup luksHeaderBackup --header-backup-file "$target/root/$crypt_label.luksHeaderBackup" "$crypt_part"
chmod 400 "$target/root/$crypt_label.luksHeaderBackup"
cp "$(readlink -e $BASH_SOURCE)" "$target/root/$self"
if ((lmde4))
then cp /run/live/medium/live/vmlinuz "$target/boot/vmlinuz-$(uname -r)"
else ((lmde)) &&
	cp /lib/live/mount/medium/live/vmlinuz "$target/boot/vmlinuz-$(uname -r)" ||
	cp /cdrom/casper/vmlinuz "$target/boot/vmlinuz-$(uname -r)"
fi
mount --bind /dev "$target/dev"

## Prepare the chroot script
inside="/root/$self.inside"
( ## Subshell start
cat <<X
#!/bin/bash
set +o verbose -o errtrace
export PS1='\[\033[01;33m\]\w \[\033[01;32m\]\$ \[\033[00m\]'
#hash -l lvmetad && lvmetad -p /lvm.pid
mount -t sysfs sys /sys
mount -t proc proc /proc
mount -t devpts pts /dev/pts
pvscan --cache
locale-gen --purge --no-archive
type -P localectl >/dev/null && localectl set-locale LANG=$LANG
useradd -ms /bin/bash $username
pwf=\$(mktemp) pwf2=\$(mktemp)
chmod 600 "\$pwf" "\$pwf2"
while [[ ! -s "\$pwf" ]]
do
	/lib/cryptsetup/askpass "Enter password for user $username: " >"\$pwf"
	echo
	if [[ -s "\$pwf" ]]
	then
		/lib/cryptsetup/askpass "Enter the same password again: " >"\$pwf2"
		echo
		diff -q --label \$'\b\b\b\b\b\b\b\bFirst' "\$pwf" \
				--label "second password"	"\$pwf2" || shred -u "\$pwf"
		shred "\$pwf2"
	else
		echo -e "Empty password not allowed\n"
	fi
done
chpasswd <<<"$username:\$(cat "\$pwf")"
addgroup $username sudo
X
((lmde)) && echo 'chpasswd <<<"root:$(cat "$pwf")"' || echo 'passwd -l root'
cat <<X
shred -u "\$pwf"
dpkg-reconfigure tzdata
dpkg-reconfigure keyboard-configuration 2>/dev/null
if [[ "$efi_part" ]]
then
	mkdir /media/cdrom
	mdev=$(grep ' iso9660 ' /proc/mounts)
	mount "${mdev%% *}" /media/cdrom
	apt-cdrom -m add -d=/media/cdrom
	sed -i 's/^deb /deb [arch=amd64] /g' "$aptsrc"
fi
if [[ "$packages" ]]
then
	[[ "$efi_part" ]] || apt-get update
	apt-get --yes install $packages
fi
X
if ((lmde))
then
	echo "apt-get -qq purge '^live-.*'"
	echo 'rm -rvf /lib/live'
	echo 'update-initramfs -c -k $(uname -r)'
fi
efi_dir=/boot/efi
cat <<X
chmod 600 "/boot/initrd.img-\$(uname -r)"
if [[ "$efi_part" ]]
then
	mkdir -p "$efi_dir"
	mount "$efi_part" "$efi_dir"
	mkdir -p "$efi_dir/EFI/boot"
	DEBIAN_FRONTEND=noninteractive apt install \
			-o Dpkg::Options::="--force-confdef" \
			-o Dpkg::Options::="--force-confold" --yes --force-yes grub-efi mokutil
	grub-install --force --recheck --target=x86_64-efi --efi-directory="$efi_dir" "$grub_device"
	grep -q '^Linux Mint 17' /etc/issue &&
		sed -i 's/^quick_boot="1"/quick_boot="0"/g' /etc/grub.d/*
	update-grub
	cp "$efi_dir"/EFI/*/grubx64.efi "$efi_dir/EFI/boot/bootx64.efi"
	umount "$efi_dir"
	umount /media/cdrom
	rmdir /media/cdrom
else
	grub-install --force --recheck "$grub_device"
	update-grub
fi
[[ -f $aptsrc ]] && sed -i 's/^deb.* cdrom:.*/#\0/' "$aptsrc"
gconftool-2 --set /apps/gksu/sudo-mode --type bool true 2>/dev/null
umount /dev/pts
umount /proc
umount /sys
[[ -f /lvm.pid ]] && kill -9 \$(cat /lvm.pid) && rm /lvm.pid
exit 0
X
## Subshell end
) >"$target$inside"
chmod +x "$target$inside"

## Enter the fresh installation to finish up
Echo "Finalizing settings on the install"
chroot "$target" "$inside"

[[ $(df --output=pcent $target |tail -1) = 100% ]] &&
	Exit "The filesystem on $root_dev is 100% full" && return 37
[[ $boot_part && $(df --output=pcent $target/boot |tail -1) = 100% ]] &&
	Exit "The filesystem on $boot_part is 100% full" && return 38

mv "$target/etc/lvm.conf_orig" "$target/etc/lvm/lvm.conf"
umount "$target/dev"
[[ $boot_part ]] && umount "$target/boot"
[[ $data_size ]] && umount "$target/$data_label"
umount "$target"
[[ $swap_size ]] && swapoff "$swap_dev"
sync
sleep 1
! vgchange -an && Exit "Not able to close all logical volumes" && return 39
sync
sleep 1
! cryptsetup luksClose $crypt_label &&
	Exit "Not able to cleanly close crypt" &&
	return 40
sync

Echo "Ready for reboot!"

return 0