Compare commits
60
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e57c016891 | ||
|
|
4a1cc42ea8 | ||
|
|
62c4a4eb3a | ||
|
|
9ef9a4b248 | ||
|
|
cc29b97421 | ||
|
|
f9f3e89f87 | ||
|
|
53b9aee230 | ||
|
|
3e46ee3a7d | ||
|
|
c5a68ae77d | ||
|
|
32b2405a2d | ||
|
|
675f163e62 | ||
|
|
5a2a2dcc07 | ||
|
|
10b5fe70d7 | ||
|
|
dc574712f4 | ||
|
|
a881642d0d | ||
|
|
327b58fbed | ||
|
|
c564c50e36 | ||
|
|
0d17d8316a | ||
|
|
450f5fff16 | ||
|
|
d8577a8938 | ||
|
|
aced56e287 | ||
|
|
0ad37939f6 | ||
|
|
76ce1aa6b6 | ||
|
|
796fc7930c | ||
|
|
ca11c1770b | ||
|
|
3ba50bb195 | ||
|
|
9428bb3263 | ||
|
|
54c95c7a6f | ||
|
|
0733ee3106 | ||
|
|
7f438f4451 | ||
|
|
5abb237b6c | ||
|
|
ab10481652 | ||
|
|
4d6c98e75b | ||
|
|
efb53cd066 | ||
|
|
dafd939d12 | ||
|
|
bcaa17d9d2 | ||
|
|
165bbdf8d3 | ||
|
|
cd180ce627 | ||
|
|
7278b18607 | ||
|
|
92b956fb1c | ||
|
|
ae8fa6e247 | ||
|
|
367e9c0e3e | ||
|
|
e7bf496f7a | ||
|
|
4b6997de33 | ||
|
|
c00627a811 | ||
|
|
a370b53f1d | ||
|
|
e1aa52a77e | ||
|
|
7b89415746 | ||
|
|
903a969d76 | ||
|
|
7a1de01ef3 | ||
|
|
8068bb1d81 | ||
|
|
f7e9f335e4 | ||
|
|
5580032733 | ||
|
|
1cd6bd6cfc | ||
|
|
58606b8306 | ||
|
|
4605a97544 | ||
|
|
c798df9b55 | ||
|
|
5a168dab3e | ||
|
|
04260a676b | ||
|
|
131f3820dd |
+10
@@ -0,0 +1,10 @@
|
||||
FROM alpine
|
||||
|
||||
RUN apk update
|
||||
RUN apk add mkpasswd zfs
|
||||
|
||||
COPY LICENSE configuration.nix flake.lock flake.nix install.sh ./
|
||||
COPY hosts ./
|
||||
COPY modules ./
|
||||
|
||||
ENTRYPOINT [ "./install.sh" ]
|
||||
@@ -0,0 +1,5 @@
|
||||
version: "3.9"
|
||||
services:
|
||||
nixos-zfs-installer:
|
||||
image: marcpartensky/nixos-zfs-installer
|
||||
build: .
|
||||
@@ -55,7 +55,7 @@
|
||||
};
|
||||
in {
|
||||
nixosConfigurations = {
|
||||
exampleHost = mkHost "exampleHost" "x86_64-linux";
|
||||
laptop = mkHost "laptop" "x86_64-linux";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
bootDevices = [ "bootDevices_placeholder" ];
|
||||
immutable.enable = false;
|
||||
removableEfi = true;
|
||||
luks.enable = false;
|
||||
luks.enable = True;
|
||||
};
|
||||
};
|
||||
boot.initrd.availableKernelModules = [ "kernelModules_placeholder" ];
|
||||
boot.kernelParams = [ ];
|
||||
networking.hostId = "abcd1234";
|
||||
networking.hostId = "nixos";
|
||||
# read changeHostName.txt file.
|
||||
networking.hostName = "exampleHost";
|
||||
time.timeZone = "Europe/Berlin";
|
||||
networking.hostName = "laptop";
|
||||
time.timeZone = "Europe/Paris";
|
||||
|
||||
# import preconfigured profiles
|
||||
imports = [
|
||||
@@ -0,0 +1,61 @@
|
||||
Audience
|
||||
|
||||
This text is intended for users who wish to remotely unlock their
|
||||
natively encrypted ZFS root filesystem with SSH during the early
|
||||
stages of system boot up.
|
||||
|
||||
=================================================================
|
||||
|
||||
Steps
|
||||
|
||||
By default, the initial RAM disk image, (hereafter refered to as
|
||||
initrd) only includes essential kernel modules needed for mounting the
|
||||
root filesystem.
|
||||
|
||||
To enable network connection during this stage of system boot, you
|
||||
need to instruct NixOS to include kernel modules needed for the
|
||||
network adapter.
|
||||
|
||||
Check which module is needed with:
|
||||
|
||||
nix-shell -p pciutils --run "lspci -v | grep -iA8 'network\|ethernet'"
|
||||
|
||||
Then, add the the modules to
|
||||
|
||||
zfs-root.boot.availableKernelModules
|
||||
|
||||
option inside the per-host configuration file. This file is located
|
||||
at hosts/exampleHost/default.nix.
|
||||
|
||||
By default, initrd uses DHCP auto-configuration for networking. If
|
||||
you need to specify a static IP address, see the documentation for
|
||||
"ip=" kernel command line option for NFS root:
|
||||
|
||||
https://www.kernel.org/doc/Documentation/filesystems/nfs/nfsroot.txt
|
||||
|
||||
Then, add the necessary kernel command line options to
|
||||
|
||||
zfs-root.boot.kernelParams
|
||||
|
||||
option inside the per-host configuration file.
|
||||
|
||||
Finally, you need to generate a pair of SSH private keys exclusively
|
||||
for use with decrypting the root filesystem during boot. This pair of
|
||||
keys should not be used anywhere else. Reasons for this can be found
|
||||
in the documentation NixOS option:
|
||||
|
||||
boot.initrd.network.ssh.hostKeys
|
||||
|
||||
> Do NOT use your regular SSH host private keys for this purpose or
|
||||
> you'll expose them to regular users! Additionally, even if your initrd
|
||||
> supports secrets, if you're using initrd SSH to unlock an encrypted
|
||||
> disk then using your regular host keys exposes the private keys on
|
||||
> your unencrypted boot partition.
|
||||
|
||||
You can generate host key with:
|
||||
|
||||
ssh-keygen -t ed25519 -N "" -f "/var/lib/ssh_unlock_zfs_ed25519_key"
|
||||
ssh-keygen -t rsa -N "" -f "/var/lib/ssh_unlock_zfs_rsa_key"
|
||||
|
||||
If you are performing a system installation, change path from
|
||||
/var/lib to /mnt/var/lib in both commands.
|
||||
Executable
+272
@@ -0,0 +1,272 @@
|
||||
#!/bin/env bash
|
||||
|
||||
log() { echo -e "\n\033[1m${@}\033[0m"; }
|
||||
|
||||
log Checking root
|
||||
mustberoot() {
|
||||
log You must be root
|
||||
exit 1
|
||||
}
|
||||
whoami | grep root || mustberoot
|
||||
|
||||
log Checking connectivity
|
||||
curl -s google.com > /dev/null || exit 1
|
||||
|
||||
log Loading zfs module first
|
||||
modprobe zfs || exit 1
|
||||
|
||||
echo ""
|
||||
lsblk
|
||||
echo ""
|
||||
|
||||
# read -p "disk: " DISK
|
||||
DISK=`lsblk | grep disk | grep -v SWAP | awk '{print $1}' | fzf`
|
||||
DISK=`echo /dev/$DISK`
|
||||
log $disk
|
||||
read -p "swapsize GiB: " SWAPSIZEGIB
|
||||
read -p "reserve GiB: " RESERVEGIB
|
||||
read -sp "password: " POOLPASS
|
||||
|
||||
EMAIL="marc@marcpartensky.com"
|
||||
NAME="Marc Partensky"
|
||||
|
||||
RESERVE=$((RESERVEGIB * 1024))
|
||||
SWAPSIZE=$((SWAPSIZEGIB * 1024))
|
||||
|
||||
|
||||
MNT=$(mktemp -d)
|
||||
|
||||
log Destroying zfs pool rpool and bpool just in case
|
||||
swapoff -a
|
||||
zpool import -fa
|
||||
for i in ${DISK}; do
|
||||
zpool labelclear -f $i
|
||||
done
|
||||
zpool destroy -f bpool
|
||||
zpool destroy -f rpool
|
||||
zpool export -a
|
||||
|
||||
log Unmounting filesystems just in case
|
||||
# ---
|
||||
umount -Rl "${MNT}"
|
||||
|
||||
log Enabling Nix Flakes functionality
|
||||
# ---
|
||||
mkdir -p ~/.config/nix
|
||||
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf
|
||||
|
||||
|
||||
log Installing programs needed for system installation
|
||||
# ---
|
||||
if ! command -v git; then nix-env -f '<nixpkgs>' -iA git; fi
|
||||
if ! command -v jq; then nix-env -f '<nixpkgs>' -iA jq; fi
|
||||
if ! command -v partprobe; then nix-env -f '<nixpkgs>' -iA parted; fi
|
||||
|
||||
|
||||
log Partition the disks
|
||||
# ---
|
||||
partition_disk () {
|
||||
local disk=$1
|
||||
blkdiscard -f $disk || true
|
||||
|
||||
parted --script --align=optimal $disk -- \
|
||||
mklabel gpt \
|
||||
mkpart swap 1MiB $((SWAPSIZE + 1))MiB \
|
||||
mkpart rpool $((SWAPSIZE + 1))MiB -$((RESERVE + 100))MiB \
|
||||
mkpart bpool -$((RESERVE + 100))MiB -$((RESERVE + 3))MiB \
|
||||
mkpart EFI -$((RESERVE + 3))MiB -$((RESERVE + 2))MiB \
|
||||
mkpart BIOS -$((RESERVE + 2))MiB -$((RESERVE + 1))MiB \
|
||||
set 4 esp on \
|
||||
set 5 bios_grub on \
|
||||
set 5 legacy_boot on
|
||||
|
||||
partprobe $disk
|
||||
udevadm settle
|
||||
}
|
||||
|
||||
for i in $DISK; do
|
||||
partition_disk $i || exit 1
|
||||
done
|
||||
|
||||
log disk $DISK
|
||||
|
||||
|
||||
log Creating boot pool
|
||||
# ---
|
||||
# shellcheck disable=SC2046
|
||||
createbpool="zpool create \
|
||||
-o compatibility=grub2 \
|
||||
-o ashift=12 \
|
||||
-o autotrim=on \
|
||||
-O acltype=posixacl \
|
||||
-O canmount=off \
|
||||
-O compression=lz4 \
|
||||
-O devices=off \
|
||||
-O normalization=formD \
|
||||
-O relatime=on \
|
||||
-O xattr=sa \
|
||||
-m /boot \
|
||||
-R $MNT \
|
||||
bpool \
|
||||
`for i in $DISK; do
|
||||
printf '%s ' ${i}3
|
||||
done`"
|
||||
echo $createbpool
|
||||
eval $createbpool
|
||||
|
||||
|
||||
log Creating root pool
|
||||
# ---
|
||||
# shellcheck disable=SC2046
|
||||
echo $POOLPASS | zpool create \
|
||||
-o ashift=12 \
|
||||
-o autotrim=on \
|
||||
-R $MNT \
|
||||
-O acltype=posixacl \
|
||||
-O canmount=off \
|
||||
-O compression=zstd \
|
||||
-O dnodesize=auto \
|
||||
-O normalization=formD \
|
||||
-O relatime=on \
|
||||
-O xattr=sa \
|
||||
-o feature@encryption=enabled \
|
||||
-O encryption=on \
|
||||
-O keyformat=passphrase \
|
||||
-m / \
|
||||
rpool \
|
||||
$(for i in $DISK; do
|
||||
printf '%s ' "${i}p2";
|
||||
done)
|
||||
|
||||
|
||||
log Creating encrypted root system container
|
||||
# ---
|
||||
echo $POOLPASS | zfs create \
|
||||
-o canmount=off \
|
||||
-o mountpoint=none \
|
||||
-o encryption=on \
|
||||
-o keylocation=prompt \
|
||||
-o keyformat=passphrase \
|
||||
rpool/nixos
|
||||
|
||||
|
||||
log Creating system datasets, managing mountpoints with mountpoint=legacy
|
||||
# ---
|
||||
zfs create -o mountpoint=legacy rpool/nixos/root
|
||||
mount -t zfs rpool/nixos/root "${MNT}"/
|
||||
zfs create -o mountpoint=legacy rpool/nixos/home
|
||||
mkdir "${MNT}"/home
|
||||
mount -t zfs rpool/nixos/home "${MNT}"/home
|
||||
zfs create -o mountpoint=legacy rpool/nixos/var
|
||||
zfs create -o mountpoint=legacy rpool/nixos/var/lib
|
||||
zfs create -o mountpoint=legacy rpool/nixos/var/log
|
||||
zfs create -o mountpoint=none bpool/nixos
|
||||
zfs create -o mountpoint=legacy bpool/nixos/root
|
||||
mkdir "${MNT}"/boot
|
||||
mount -t zfs bpool/nixos/root "${MNT}"/boot
|
||||
mkdir -p "${MNT}"/var/log
|
||||
mkdir -p "${MNT}"/var/lib
|
||||
mount -t zfs rpool/nixos/var/lib "${MNT}"/var/lib
|
||||
mount -t zfs rpool/nixos/var/log "${MNT}"/var/log
|
||||
zfs create -o mountpoint=legacy rpool/nixos/empty
|
||||
zfs snapshot rpool/nixos/empty@start
|
||||
|
||||
|
||||
log Formatting and mounting ESP
|
||||
# ---
|
||||
for i in ${DISK}; do
|
||||
mkfs.vfat -n EFI "${i}"4
|
||||
mkdir -p "${MNT}"/boot/efis/"${i##*/}"4
|
||||
mount -t vfat -o iocharset=iso8859-1 "${i}"4 "${MNT}"/boot/efis/"${i##*/}"4
|
||||
done
|
||||
|
||||
|
||||
log Cloning template flake configuration
|
||||
# ---
|
||||
mkdir -p "${MNT}"/etc
|
||||
git clone --depth 1 --branch custom \
|
||||
https://github.com/marcpartensky/nixos-zfs-installer.git "${MNT}"/etc/nixos
|
||||
|
||||
rm -rf "${MNT}"/etc/nixos/.git
|
||||
git -C "${MNT}"/etc/nixos/ init -b master
|
||||
git -C "${MNT}"/etc/nixos/ add "${MNT}"/etc/nixos/
|
||||
git -C "${MNT}"/etc/nixos config user.email $EMAIL
|
||||
git -C "${MNT}"/etc/nixos config user.name $NAME
|
||||
git -C "${MNT}"/etc/nixos commit -nasm 'initial commit'
|
||||
|
||||
|
||||
log Customizing configuration to your hardware
|
||||
# ---
|
||||
for i in ${DISK}; do
|
||||
sed -i \
|
||||
"s|/dev/disk/by-id/|${i%/*}/|" \
|
||||
"${MNT}"/etc/nixos/hosts/nixos/default.nix
|
||||
break
|
||||
done
|
||||
|
||||
diskNames=""
|
||||
for i in ${DISK}; do
|
||||
diskNames="${diskNames} \"${i##*/}\""
|
||||
done
|
||||
|
||||
sed -i "s|\"bootDevices_placeholder\"|${diskNames}|g" \
|
||||
"${MNT}"/etc/nixos/hosts/nixos/default.nix
|
||||
|
||||
sed -i "s|\"abcd1234\"|\"$(head -c4 /dev/urandom | od -A none -t x4| sed 's| ||g' || true)\"|g" \
|
||||
"${MNT}"/etc/nixos/hosts/nixos/default.nix
|
||||
|
||||
sed -i "s|\"x86_64-linux\"|\"$(uname -m || true)-linux\"|g" \
|
||||
"${MNT}"/etc/nixos/flake.nix
|
||||
|
||||
cp "$(command -v nixos-generate-config || true)" ./nixos-generate-config
|
||||
|
||||
chmod a+rwx ./nixos-generate-config
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
echo 'print STDOUT $initrdAvailableKernelModules' >> ./nixos-generate-config
|
||||
|
||||
kernelModules="$(./nixos-generate-config --show-hardware-config --no-filesystems | tail -n1 || true)"
|
||||
|
||||
sed -i "s|\"kernelModules_placeholder\"|${kernelModules}|g" \
|
||||
"${MNT}"/etc/nixos/hosts/nixos/default.nix
|
||||
|
||||
log Setting root password
|
||||
# ---
|
||||
rootPwd=$(mkpasswd2 -m SHA-512)
|
||||
sed -i \
|
||||
"s|rootHash_placeholder|${rootPwd}|" \
|
||||
"${MNT}"/etc/nixos/configuration.nix
|
||||
|
||||
|
||||
log Commiting changes to local repo
|
||||
# ---
|
||||
git -C "${MNT}"/etc/nixos commit -asm 'initial installation'
|
||||
|
||||
log Updating flake lock file to track latest system version
|
||||
# ---
|
||||
nix flake update --commit-lock-file \
|
||||
"git+file://${MNT}/etc/nixos"
|
||||
|
||||
log Installing system and apply configuration
|
||||
# ---
|
||||
nixos-install \
|
||||
--root "${MNT}" \
|
||||
--no-root-passwd \
|
||||
--flake "git+file://${MNT}/etc/nixos#nixos"
|
||||
|
||||
|
||||
log Setuping encrypted swap. This is useful if the available memory is small
|
||||
# ---
|
||||
for i in ${DISK}; do
|
||||
cryptsetup open --type plain --key-file /dev/random "${i}"1 "${i##*/}"1
|
||||
mkswap /dev/mapper/"${i##*/}"1
|
||||
swapon /dev/mapper/"${i##*/}"1
|
||||
done
|
||||
|
||||
log Unmounting filesystems
|
||||
# ---
|
||||
umount -Rl "${MNT}"
|
||||
zpool export -a
|
||||
|
||||
|
||||
log The installation is done, enjoy
|
||||
@@ -41,11 +41,11 @@ in {
|
||||
};
|
||||
partitionScheme = mkOption {
|
||||
default = {
|
||||
biosBoot = "-part5";
|
||||
efiBoot = "-part1";
|
||||
swap = "-part4";
|
||||
bootPool = "-part2";
|
||||
rootPool = "-part3";
|
||||
swap = "1";
|
||||
rootPool = "2";
|
||||
bootPool = "3";
|
||||
efiBoot = "4";
|
||||
biosBoot = "5";
|
||||
};
|
||||
description = "Describe on disk partitions";
|
||||
type = types.attrsOf types.str;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.zfs-root.networking;
|
||||
inherit (lib) types mkDefault mkOption;
|
||||
in {
|
||||
options.zfs-root.networking = {
|
||||
hostName = mkOption {
|
||||
description = "The name of the machine. Used by nix flake.";
|
||||
type = types.str;
|
||||
default = "nixos";
|
||||
};
|
||||
timeZone = mkOption {
|
||||
type = types.str;
|
||||
default = "Etc/UTC";
|
||||
};
|
||||
hostId = mkOption {
|
||||
description = "Set host id";
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
config = {
|
||||
networking.hostId = cfg.hostId;
|
||||
time.timeZone = cfg.timeZone;
|
||||
networking = {
|
||||
firewall.enable = mkDefault true;
|
||||
hostName = cfg.hostName;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
print STDOUT $initrdAvailableKernelModules
|
||||
Reference in New Issue
Block a user