Skip to content

Instantly share code, notes, and snippets.

@sveitser
Last active August 17, 2018 11:43
Show Gist options
  • Save sveitser/7130148998926aabc62414494c4f4caf to your computer and use it in GitHub Desktop.
Save sveitser/7130148998926aabc62414494c4f4caf to your computer and use it in GitHub Desktop.
#!/bin/bash
#
# !!! WILL ERASE SELECTED DISK !!!
#
# Installs nixos with full disk encryption.
#
# - Prompts for password initially, after that no interaction should
# be required.
# - At the end it will prompt for a root password, could not make
# echo-ing it into nixos-install work.
# - Reserves 550MB for EFI boot partition, rest for the root volume.
# - After booting, log in as root user and set password for normal user.
#
# USAGE:
# 1. Fill in variables on top.
# 2. $bash install.sh
#
# Based on https://gist.github.com/ladinu/bfebdd90a5afd45dec811296016b2a3f
#
set -e
DISK="/dev/sda"
BOOT="/dev/sda1"
ROOT="/dev/sda2"
NIXOS_USER=""
HOSTNAME=""
SWAP="4G"
NIXOS_VERSION="18.09"
# CONSOLE_KEYMAP="us" # the default
CONSOLE_KEYMAP="colemak/en-latin9"
# XKB_VARIANT="" # the default
XKB_VARIANT="colemak"
CRYPT_VOLUME="/dev/mapper/crypted-nixos"
########################################################
# No need to edit anything below for normal usage. #
########################################################
# Fail if echo isn't builtin to prevent passwords being visible.
builtin echo
read -s -p "Password: " PASSWORD
echo
read -s -p "Confirm: " CONFIRMATION
echo
if [ ! "$PASSWORD" = "$CONFIRMATION" ]; then
echo "Didn't match. Try again."
exit 1
fi
if [[ -e $CRYPT_VOLUME ]]; then
echo "Found existing $CRYPT_VOLUME, trying to purge ... "
echo "Removing existing physical volume label if it exists."
# not too sure about this
echo "Deactivating swap."
swapoff /dev/vg/swap || true
echo "Unmounting file systems."
umount /mnt/boot/efi || true
umount /mnt || true
echo "Removing logical volumes."
lvremove -y vg swap || true
lvremove -y vg root || true
echo "Removing logical volume group."
lvremove -y vg || true
echo "Removing physical volume group."
pvremove -y -f -f $CRYPT_VOLUME || true
echo "Removing device."
dmsetup remove $CRYPT_VOLUME || true
fi
if [[ -e $CRYPT_VOLUME ]]; then
cat <<EOF
$CRYPT_VOLUME still exists, you can try running
dmsetup remove $CRYPT_VOLUME
manually.
EOF
exit 1
fi
echo "Creating partition table."
(echo o # new table
echo Y # yes
echo n # new part
echo # number 1
echo # start
echo '+550M' # end
echo 'ef00' # EFI
echo n # new part
echo # number 2
echo # start
echo # end
echo # linux
echo w # write
echo Y # yes
) | gdisk $DISK
echo "Generating key."
dd if=/dev/urandom of=./keyfile0.bin bs=1024 count=4
echo "Setting up LUKS."
echo $PASSWORD | cryptsetup luksFormat -c aes-xts-plain64 -s 256 -h sha512 $ROOT
echo "Adding key."
echo $PASSWORD | cryptsetup luksAddKey $ROOT keyfile0.bin
echo "Opening crypt volume."
echo $PASSWORD | cryptsetup luksOpen $ROOT crypted-nixos
echo "Setting up LVM."
pvcreate $CRYPT_VOLUME
vgcreate vg $CRYPT_VOLUME
lvcreate -L $SWAP -n swap vg
lvcreate -l '100%FREE' -n root vg
echo "Formatting partitions."
mkfs.fat -F 32 $BOOT
mkswap -L swap /dev/vg/swap
mkfs.ext4 -L root /dev/vg/root
echo "Mounting partitions."
mount /dev/vg/root /mnt
mkdir -p /mnt/boot/efi
mount $BOOT /mnt/boot/efi
swapon /dev/vg/swap
# Create an initrd which only contain the key files
find keyfile*.bin -print0 | sort -z | cpio -o -H newc -R +0:+0 --reproducible --null | gzip -9 > /mnt/boot/initrd.keys.gz
chmod 000 /mnt/boot/initrd.keys.gz
nixos-generate-config --root /mnt
UUID=$(blkid $ROOT -s UUID -o value)
#
# TODO: Is there a better way than to hardcode the config files?
#
cat > /mnt/etc/nixos/configuration.nix <<EOF
{ config, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.efi.efiSysMountPoint = "/boot/efi";
boot.loader.grub = {
enable = true;
device = "nodev";
version = 2;
efiSupport = true;
enableCryptodisk = true;
extraInitrd = /boot/initrd.keys.gz;
};
boot.initrd.luks.devices = [
{
name = "root";
device = "/dev/disk/by-uuid/$UUID";
preLVM = true;
keyFile = "/keyfile0.bin";
allowDiscards = true;
}
];
networking.hostName = "$HOSTNAME";
i18n = {
consoleKeyMap = "$CONSOLE_KEYMAP";
defaultLocale = "en_US.UTF-8";
};
time.timeZone = "Asia/Hong_Kong";
environment.systemPackages = with pkgs; [
# nmon # not available
ag
direnv
firefox
fish
fzf
git
htop
pass
tree
vim
wget
];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
programs.bash.enableCompletion = true;
programs.gnupg.agent = { enable = true; enableSSHSupport = true; };
services.openssh.enable = true;
services.xserver.desktopManager.plasma5.enable = true;
services.xserver.displayManager.sddm.autoLogin.enable = true;
services.xserver.displayManager.sddm.autoLogin.user = "$NIXOS_USER";
services.xserver.displayManager.sddm.enable = true;
services.xserver.enable = true;
services.xserver.xkbVariant = "$XKB_VARIANT";
# Define a user account. Don't forget to set a password with ‘passwd’.
users.extraUsers.$NIXOS_USER = {
isNormalUser = true;
uid = 1000;
extraGroups = [ "wheel" ];
};
# You should change this only after NixOS release notes say you should.
system.stateVersion = "$NIXOS_VERSION"; # Did you read the comment?
}
EOF
nixos-install
echo "Reboot now, good luck!"
# GistID: 7130148998926aabc62414494c4f4caf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment