暗号化されたZFSミラーにルートでDebianをインストールする

画像







まえがき



別の都市で働く必要があるため、ラップトップを購入する必要がありました。

徐々に、それを静止した車と同期させる問題は成熟しました。

私のプロジェクトはすべてギタで実行されますが、すべてのコードが完全に私のものではないため、githubにアップロードしたくありません。







この問題を解決するために、NASの構築を開始しました。これにより、特に追加機能が提供されます。







この問題を解決するために現在利用可能なオペレーティングシステムを調査した結果、FreeNAS開発者の1人によって作成された、FreeBSDベースのFreeNASおよびDebianベースのOpenMediaVaultが最も多様であり、広く使用され、したがって開発されたという結論に至りました。







FreeNASは安定しており、便利で、柔軟性があり、一般的に優れていますが、インストールしようとしたときに、FreeBSD bsdinstallの代わりに、ディスクを選択してルートパスワードを入力するだけの完全に削除されたインストーラーを見ました:ディスクをパーティション分割することさえできません。

GELI LinuxのcryptsetupとBSD partnyが好きでした。

暗号化されたパーティションにrootを作成しようとすると、ZFSですでにrootを使用しているという事実にもかかわらず、このタスクは簡単ではないことに気付きました。

次に、FreeNASがOSではなくアプリケーションであることを証明し始めたFreeNASコミュニティと話し合った後、OMVをインストールすることにしました。







さらに、Debianは私のメインOSであり、Linuxを使用することでより簡単になると約束されました...







まったくそうではないことが判明しました。 私のような構成を作成するタスクは決して簡単ではありません。 したがって、私はこの記事を書くことにしました。







既存のリソース



ZFS for Linuxプロジェクトガイドがメインドキュメントであり、これがなければ、さらに長い時間をかける必要があります。

少なくとも簡単に見る必要があります。







ほとんどの作業を手動で行ったところ、ミラーを整理することなく、同様のタスクを実行するスクリプトに出会いました。







さて、私はまだここでcryptsetup man 、Debian暗号化ガイド記事、ZFSドキュメントについて言及します (元のドキュメントへのリンクがあります)。







ZFSに関する多くの情報がFreeNASフォーラムにあります。







そして、すでにこの記事を書いている過程で、月の下では何も新しいものではないことが判明しました。







ただし、私のスキームは多少異なり、欠点と利点の両方があります。







ディスク構成スキーム



システムは、MicronとSamsung PROの2つのSSDにインストールされます(将来、それらを参照します)。







各SSDには次のパーティションスキームがあります。









part_system



およびpart_slog



XTSモードで暗号化されます。







一般的に、次のようになります。







 SSD1: [part_boot] -> [ext4] <---> SSD2 SSD1: [part_system] -> [crypto_xts] -> [zfs_mirror] <---> SSD2 SSD1: [part_slog] -> [crypto_xts] -> [zfs_zil_mirror] <---> SSD2
      
      





ZILとシステムルートは、ZFSを使用して2番目のSSDに複製されます。







準備する



  1. ISO Debianをダウンロードします
  2. USBフラッシュにイメージをインストールします。


設置



さらなる行動は、主にマニュアルから借用されており、私の説明の一部とともに提供されています。

すべてのコマンドがルートとして実行されることを前提としています。







ZFSのインストールに必要なcontribをsources.listに追加します



echo "deb http://ftp.debian.org/debian stretch main contrib" > /etc/apt/sources.list && apt-get update









debootstrapおよびzfs-dkmsをインストールします



apt-get install debootstrap linux-headers-$(uname -r) zfs-dkms









cryptsetupをインストールする



apt-get install cryptsetup









ランダムデータでSSDをドライブする



dd if=/dev/urandom bs=4M oflag=direct of=/dev/disk/by-id/ata-Samsung_SSD_850_PRO && blkdiscard /dev/disk/by-id/ata-Samsung_SSD_850_PRO





dd if=/dev/urandom bs=4M oflag=direct of=/dev/disk/by-id/ata-Micron_1100 && blkdiscard /dev/disk/by-id/ata-Micron_1100









250 GB SSDの場合、これには約30分かかります。

blkdiscard呼び出しは、SSD上のすべてのブロックを未使用としてマークします。







ダウンロード用のセクションを作成する



sgdisk -a1 -n1:34:2047 -t1:EF02 -n2:0:+1G -t2:8300 /dev/disk/by-id/ata-Samsung_SSD_850_PRO





sgdisk -a1 -n1:34:2047 -t1:EF02 -n2:0:+1G -t2:8300 /dev/disk/by-id/ata-Micron_1100









ここで、その後GRUBがインストールされます。

最初の小さなセクションの作成は必須です。これがないと起動しません。







システムパーティションを作成する



sgdisk -n3::+32G -t3:8300 -c3:part_system1 /dev/disk/by-id/ata-Samsung_SSD_850_PRO





sgdisk -n3::+32G -t3:8300 -c3:part_system2 /dev/disk/by-id/ata-Micron_1100









SLOGセクションを作成する



sgdisk -n4::+5G -t4:8300 -c4:part_slog1 /dev/disk/by-id/ata-Samsung_SSD_850_PRO && sgdisk -n4::+5G -t4:8300 -c4:part_slog2 /dev/disk/by-id/ata-Micron_1100









この記事では、それらは決して使用されません。







暗号化されたルートパーティションを作成する



cryptsetupにあまり精通していない場合は、Debianのドキュメントを参考にしてください。

LUKSを使用します。これにより、暗号化の作業が多少簡単になります。







cryptsetup --cipher aes-xts-plain64 --key-size 512 --verify-passphrase --hash sha512 --use-random -v luksFormat /dev/disk/by-id/ata-Samsung_SSD_850_PRO-part3





cryptsetup --cipher aes-xts-plain64 --key-size 512 --verify-passphrase --hash sha512 --use-random -v luksFormat /dev/disk/by-id/ata-Micron_1100-part3









次に、セクションを開く必要があります。







cryptsetup luksOpen /dev/disk/by-id/ata-Samsung_SSD_850_PRO-part3 root_crypt1





cryptsetup luksOpen /dev/disk/by-id/ata-Micron_1100-part3 root_crypt2









正しいパスワードを入力すると、暗号化に使用される新しいブロックデバイスが作成されます。

ZFSルートプールをホストします。







ルートZFSプールを作成する



  modprobe zfs zpool create -o ashift=12 \ -O atime=off -O canmount=off -O compression=lz4 -O normalization=formD \ -O mountpoint=/ -R /mnt \ rpool mirror /dev/disk/by-id/dm-name-root_crypt*
      
      





現在、ミラー化された両方の暗号化されたパーティションを含むプールがあります。







ashiftパラメーターに関する注意

ashift



指定したブロックサイズを取得するためにデュースを上げる必要がある度合い。

12は4Kブロックです。

blockdev --getbsz /dev/<disk>



コマンドblockdev --getbsz /dev/<disk>



を使用するか、デバイスの技術仕様からブロックサイズを取得できます。

ブロックサイズがディスクのセクターサイズと一致しない場合、パフォーマンスが低下します。

最新のハードドライブのセクターサイズは4Kで、セクターエミュレーションは512バイトです。

高速で低容量のSASディスク(数百GB程度)を除き、セクターサイズは512バイトのままです。







ルートFSのデータセットを作成する



zfs create -o canmount=off -o mountpoint=none rpool/ROOT





zfs create -o canmount=noauto -o mountpoint=/ rpool/ROOT/debian









ルートをブート可能にする



zfs mount rpool/ROOT/debian





zpool set bootfs=rpool/ROOT/debian rpool









他のデータセットを作成する



zfs create -o setuid=off rpool/home





zfs create -o mountpoint=/root rpool/home/root





zfs create -o canmount=off -o setuid=off -o exec=off rpool/var





zfs create -o com.sun:auto-snapshot=false rpool/var/cache





zfs create rpool/var/log





zfs create rpool/var/spool





zfs create -o com.sun:auto-snapshot=false -o exec=on rpool/var/tmp









この段階で、FS構造の準備ができました。







最小システムを設定する



chmod 1777 /mnt/var/tmp





debootstrap stretch /mnt && zfs set devices=off rpool









システムを構成する



echo nas > /mnt/etc/hostname





echo "rpool/ROOT/debian / zfs defaults,noatime 0 0" > /mnt/etc/fstab





echo "tmpfs /tmp tmpfs nosuid,nodev 0 0" >> /mnt/etc/fstab









ここで/ tmpはtmpfsとしてマウントされ、/はZFS上にあります。

次に、 /mnt/etc/hosts



を修正する必要があり/mnt/etc/hosts



。 ホスト名「nas」を追加する必要があります。

そして、ネットワークインターフェース設定を/mnt/etc/network/interfaces.d



追加します(必須):









これは重要なポイントです! これを行わないと、再起動後にネットワークやインストールされたパッケージなしで自分自身が見つかります。 しないでください-ネットワークはまだ手動で解除する必要があります。







インストール済みシステムに切り替える



mount --rbind /dev /mnt/dev && mount --rbind /proc /mnt/proc && mount --rbind /sys /mnt/sys





chroot /mnt /bin/bash --login





mount /tmp









さらに、インストールされたシステムですべての作業が行われます







APTを構成し、必要なパッケージをインストールする





ZFSモジュールの組み立てには、具体的な時間がかかります。







cryptsetupを構成する



必ずinitramfsに含めてください:

sed -i 's/#CRYPTSETUP=/CRYPTSETUP=y/' /etc/cryptsetup-initramfs/conf-hook









次に、/ usr / share / initramfs-tools / hooks / cryptrootのcryptrootフックを修正し、/ etc / initrmafs-tools / scripts / local-top / cryptrootのスクリプトを置き換える必要があります。

Debian Stretchのcryptsetupパッケージには2つの問題があります。









ZFSのバグは長い間巻き上げられており、そこに私の改善が送られてきました。

パスワードキャッシングのバグを開始して修正を送信したため、すでに修正されている可能性があります。







ただし、完全なスクリプトと差分を提供します。







/ usr / share / initramfs-tools / hooks / cryptroot
 #!/bin/sh PREREQ="" prereqs() { echo "$PREREQ" } case $1 in prereqs) prereqs exit 0 ;; esac . /usr/share/initramfs-tools/hook-functions # get_fs_devices() - determine source device(s) of mount point from /etc/fstab # # expected arguments: # * fstab mount point (full path) # # This function searches for the first entry from /etc/fstab which has the # given mountpoint set. It returns the canonical_device() of corresponding # source device (first field in /etc/fstab entry). # In case of btrfs, canoncial_device() of all btrfs source devices (possibly # more than one) are returned. # get_fs_devices() { local device mount type options dump pass local wantmount="$1" if [ ! -r /etc/fstab ]; then return 1 fi grep -s '^[^#]' /etc/fstab | \ while read device mount type options dump pass; do if [ "$mount" = "$wantmount" ]; then local devices if [ "$type" = "btrfs" ]; then for dev in $(btrfs filesystem show $(canonical_device "$device" --no-simplify) 2>/dev/null | sed -r -e 's/.*devid .+ path (.+)/\1/;tx;d;:x') ; do devices="${devices:+$devices }$(canonical_device "$dev")" done elif [ "$type" = "zfs" ]; then zpool="$(echo "$device"|sed 's#^/dev/zvol/##;s#\([^/]*\).*#\1#')" for ss in $(zpool list -Pv "$zpool"); do cdev=$(canonical_device "$ss" 2>/dev/null) || continue devices="${devices:+$devices }$cdev" done || return 0 else devices=$(canonical_device "$device") || return 0 fi printf '%s' "$devices" return fi done } # get_resume_devices() - determine devices used for system suspend/hibernate # # expected arguments: # * none # # This function searches well known places for devices that are used for system # suspension and/or hibernation. It returns canonical_device() of any detected # devices and prints a warning if more than one device is detected. # get_resume_devices() { local device opt count dupe candidates devices derived candidates="" # First, get a list of potential resume devices # uswsusp if [ -e /etc/uswsusp.conf ]; then device=$(sed -rn 's/^resume device[[:space:]]*[:=][[:space:]]*// p' /etc/uswsusp.conf) if [ -n "$device" ]; then candidates="${candidates:+$candidates }$device" fi fi # uswsusp - again... if [ -e /etc/suspend.conf ]; then device=$(sed -rn 's/^resume device[[:space:]]*[:=][[:space:]]*// p' /etc/suspend.conf) if [ -n "$device" ]; then candidates="${candidates:+$candidates }$device" fi fi # regular swsusp for opt in $(cat /proc/cmdline); do case $opt in resume=*) device="${opt#resume=}" candidates="${candidates:+$candidates }$device" ;; esac done # initramfs-tools >=0.129 device="${RESUME:-auto}" if [ "$device" != none ]; then if [ "$device" = auto ]; then # next line from /usr/share/initramfs-tools/hooks/resume device="$(grep ^/dev/ /proc/swaps | sort -rnk3 | head -n 1 | cut -d " " -f 1)" if [ -n "$device" ]; then device="UUID=$(blkid -s UUID -o value "$device" || true)" fi fi candidates="${candidates:+$candidates }$device" fi # Now check the sanity of all candidates devices="" count=0 for device in $candidates; do # Remove quotes around device candidate device=$(printf '%s' "$device" | sed -r -e 's/^"(.*)"\s*$/\1/' -e "s/^'(.*)'\s*$/\1/") # Weed out clever defaults if [ "$device" = "<path_to_resume_device_file>" ]; then continue fi # Detect devices required by decrypt_derived derived=$(get_derived_device "$device") if [ -n "$derived" ]; then devices="${devices:+$devices }$derived" fi device=$(canonical_device "$device") || return 0 # Weed out duplicates dupe=0 for opt in $devices; do if [ "$device" = "$opt" ]; then dupe=1 fi done if [ $dupe -eq 1 ]; then continue fi # This device seems ok devices="${devices:+$devices }$device" count=$(( $count + 1 )) done if [ $count -gt 1 ]; then echo "cryptsetup: WARNING: found more than one resume device candidate:" >&2 for device in $devices; do echo " $device" >&2 done fi if [ $count -gt 0 ]; then printf '%s' "$devices" fi return 0 } # get_initramfs_devices() - determine devices with explicit 'initramfs' option # # expected arguments: # * none # # This function processes entries from /etc/crypttab with the 'initramfs' # option set. For each processed device, potential get_derived_device() # devices are determined. The canonical_device() of each detected device # is returned. # get_initramfs_devices() { local device opt count dupe target source key options candidates devices derived candidates="$(grep -s '^[^#]' /etc/crypttab | \ while read target source key options; do if printf '%s' "$options" | grep -Eq "^(.*,)?initramfs(,.*)?$"; then echo " /dev/mapper/$target" fi done;)" devices="" count=0 for device in $candidates; do # Detect devices required by decrypt_derived derived=$(get_derived_device "$device") if [ -n "$derived" ]; then devices="${devices:+$devices }$derived" fi device=$(canonical_device "$device") || return 0 # Weed out duplicates dupe=0 for opt in $devices; do if [ "$device" = "$opt" ]; then dupe=1 fi done if [ $dupe -eq 1 ]; then continue fi # This device seems ok devices="${devices:+$devices }$device" count=$(( $count + 1 )) done if [ $count -gt 0 ]; then printf '%s' "$devices" fi return 0 } # get_derived_device() - determine dependency devices for decrypt_derived # # expected arguments: # * crypttab target device name (either <name> or /dev/mapper/<name>) # # This function takes a target device name and checks whether this device has # the decrypt_derived keyscript set in /etc/crypttab. If true, the dependency # device required for the decrypt_derived keyscript is detected and its # canonical_device() returned if it's not listed in $rootdevs. # get_derived_device() { local device derived device="$1" derived="$( awk -vtarget="${device#/dev/mapper/}" \ '$1 == target && $4 ~ /^(.*,)?keyscript=([^,]*\/)?decrypt_derived(,.*)?$/ {print $3; exit}' \ /etc/crypttab )" if [ -n "$derived" ]; then if node_is_in_crypttab "$derived"; then derived=$(canonical_device "/dev/mapper/$derived") || return 0 if ! printf '%s' "$rootdevs" | tr ' ' '\n' | grep -Fxq "$derived"; then printf '%s' "$derived" fi else echo "cryptsetup: WARNING: decrypt_derived device $derived not found in crypttab" >&2 fi fi } # node_is_in_crypttab() - test whether a device is configured in /etc/crypttab # # expected arguments: # * crypttab target device names (without /dev/mapper/ prefix) # # This function takes a target device name and fails if it is not # configured in /etc/crypttab. # node_is_in_crypttab() { [ -f /etc/crypttab ] || return 1 sed -n '/^[^#]/ s/\s.*//p' /etc/crypttab | grep -Fxq "$1" } # node_or_pv_is_in_crypttab() - test whether devices are configured in /etc/crypttab # # expected arguments: # * crypttab target device names (without /dev/mapper/ prefix), or LVM # logical volume device-mapper name (format <VG>-<LV>) # # This function fails unless every argument is either a target device # name configured in /etc/crypttab, or an LVM logical volume # device-mapper name (format <VG>-<LV>) with only parents devices (PVs) # configured in /etc/crypttab. # node_or_pv_is_in_crypttab() { local node lvmnodes lvmnode for node in "$@"; do if ! node_is_in_crypttab "$node"; then lvmnodes="$(get_lvm_deps "$node" --assert-crypt)" || return 1 [ "$lvmnodes" ] || return 1 for lvmnode in $lvmnodes; do node_is_in_crypttab "$lvmnode" || return 1 done fi done return 0 } # get_lvm_deps() - determine the parent devices (PVs) of a LVM logical volume # # expected arguments: # * LVM logical volume device-mapper name (format <VG>-<LV>) # * optional options to the function # # This function takes a LVM logical volume name and determines the corresponding # crypted physical volumes (PVs). It returns the name of the underlying # device-mapper crypt devices (without /dev/mapper). # If option '--assert-crypt' is given as second argument, then the # function fails unless all PVs are dm-crypt devices. # get_lvm_deps() { local node opt deps maj min depnode node="$1" opt="${2:-}" if [ -z "$node" ]; then echo "cryptsetup: WARNING: get_lvm_deps - invalid arguments" >&2 return 1 fi if ! deps=$(vgs --noheadings -o pv_name $(dmsetup --noheadings splitname $node | cut -d':' -f1) 2>/dev/null); then # $node is not a LVM node, stopping here [ "$opt" != '--assert-crypt' ] && return 0 || return 1 fi # We should now have a list of physical volumes for the VG for dep in $deps; do depnode=$(dmsetup info -c --noheadings -o name "$dep" 2>/dev/null) if [ -z "$depnode" ]; then [ "$opt" != '--assert-crypt' ] && continue || return 1 fi if [ "$(dmsetup table "$depnode" 2>/dev/null | cut -d' ' -f3)" != "crypt" ]; then get_lvm_deps "$depnode" $opt || return 1 continue fi printf '%s\n' "$depnode" done return 0 } # get_device_opts() - determine and set options for a crypttab target device # # expected arguments: # * crypttab target device name (without /dev/mapper/ prefix) # * optional extra options # # This function determines options for a crypttab target device and sets them # accordingly. In order to detect the options, it parses the corresponding # /etc/crypttab entry and takes optional extra options as second argument. # Some sanity checks are done on the corresponding source device and configured # options. # After everything is processed, the options are saved in '$OPTIONS' for later # access by parent functions. # get_device_opts() { local target source link extraopts rootopts opt key target="$1" extraopts="$2" KEYSCRIPT="" KEYFILE="" # key file to copy to the initramfs image CRYPTHEADER="" OPTIONS="" if [ -z "$target" ]; then echo "cryptsetup: WARNING: get_device_opts - invalid arguments" >&2 return 1 fi opt="$( awk -vtarget="$target" '$1 == target {gsub(/[ \t]+/," "); print; exit}' /etc/crypttab )" source=$( printf '%s' "$opt" | cut -d " " -f2 ) key=$( printf '%s' "$opt" | cut -d " " -f3 ) rootopts=$( printf '%s' "$opt" | cut -d " " -f4- ) if [ -z "$opt" ] || [ -z "$source" ] || [ -z "$key" ] || [ -z "$rootopts" ]; then echo "cryptsetup: WARNING: invalid line in /etc/crypttab for $target - $opt" >&2 return 1 fi # Sanity checks for $source if [ -h "$source" ]; then link=$(readlink -nqe "$source") if [ -z "$link" ]; then echo "cryptsetup: WARNING: $source is a dangling symlink" >&2 return 1 fi if [ "$link" != "${link#/dev/mapper/}" ]; then echo "cryptsetup: NOTE: using $link instead of $source for $target" >&2 source="$link" fi fi if [ "UUID=${source#UUID=}" = "$source" -a ! \( -b "/dev/disk/by-uuid/${source#UUID=}" -o -b "/dev/disk/by-partuuid/${source#UUID=}" \) ] || [ "UUID=${source#UUID=}" != "$source" -a ! -b "$source" ]; then echo "cryptsetup: WARNING: Invalid source device $source" >&2 fi # Sanity checks for $key if [ "$key" = "/dev/random" ] || [ "$key" = "/dev/urandom" ]; then echo "cryptsetup: WARNING: target $target has a random key, skipped" >&2 return 1 fi if [ -n "$extraopts" ]; then rootopts="$extraopts,$rootopts" fi # We have all the basic options, let's go trough them OPTIONS="target=$target,source=$source" local IFS_BCK="$IFS" local IFS=", " unset HASH_FOUND unset LUKS_FOUND for opt in $rootopts; do case $opt in cipher=*) OPTIONS="$OPTIONS,$opt" ;; size=*) OPTIONS="$OPTIONS,$opt" ;; hash=*) OPTIONS="$OPTIONS,$opt" HASH_FOUND=1 ;; tries=*) OPTIONS="$OPTIONS,$opt" ;; discard) OPTIONS="$OPTIONS,$opt" ;; luks) LUKS_FOUND=1 ;; header=*) opt="${opt#header=}" if [ ! -e "$opt" ]; then echo "cryptsetup: WARNING: target $target has an invalid header, skipped" >&2 return 1 fi CRYPTHEADER="$opt" OPTIONS="$OPTIONS,header=$CRYPTHEADER" ;; tcrypt) OPTIONS="$OPTIONS,$opt" ;; keyscript=*) opt="${opt#keyscript=}" if [ ! -x "/lib/cryptsetup/scripts/$opt" ] && [ ! -x "$opt" ]; then echo "cryptsetup: WARNING: target $target has an invalid keyscript, skipped" >&2 return 1 fi KEYSCRIPT="$opt" OPTIONS="$OPTIONS,keyscript=/lib/cryptsetup/scripts/$(basename "$opt")" ;; keyslot=*) OPTIONS="$OPTIONS,$opt" ;; veracrypt) OPTIONS="$OPTIONS,$opt" ;; lvm=*) OPTIONS="$OPTIONS,$opt" ;; rootdev) OPTIONS="$OPTIONS,$opt" ;; resumedev) OPTIONS="$OPTIONS,$opt" ;; *) # Presumably a non-supported option ;; esac done IFS="$IFS_BCK" # Warn for missing hash option, unless we have a LUKS partition if [ -z "$HASH_FOUND" ] && [ -z "$LUKS_FOUND" ]; then echo "WARNING: Option hash missing in crypttab for target $target, assuming ripemd160." >&2 echo " If this is wrong, this initramfs image will not boot." >&2 echo " Please read /usr/share/doc/cryptsetup/README.initramfs.gz and add" >&2 echo " the correct hash option to your /etc/crypttab." >&2 fi # Warn that header only applies to a LUKS partition currently if [ -n "$CRYPTHEADER" ] && [ -z "$LUKS_FOUND" ]; then echo "WARNING: Option LUKS missing in crypttab for target $target." >&2 echo " Headers are only supported for LUKS devices." >&2 fi # If keyscript is set, the "key" is just an argument to the script if [ "$key" != "none" ] && [ -z "$KEYSCRIPT" ]; then case "$key" in $KEYFILE_PATTERN) KEYFILE="$key" key="/cryptroot-keyfiles/${target}.key" ;; *) key=$(readlink -e "$key") # test whether $target is a root device (or parent of the root device) if printf '%s' "$OPTIONS" | grep -Eq '^(.*,)?rootdev(,.*)?$'; then echo "cryptsetup: WARNING: root target $target uses a key file, skipped" >&2 return 1 # test whether a) key file is not on root fs # or b) root fs is not encrypted elif [ "$(stat -c %m -- "$key" 2>/dev/null)" != / ] || ! node_or_pv_is_in_crypttab $rootdevs; then echo "cryptsetup: WARNING: $target's key file $key is not on an encrypted root FS, skipped" >&2 return 1 fi if printf '%s' "$OPTIONS" | grep -Eq '^(.*,)?resumedev(,.*)?$'; then # we'll be able to decrypt the device, but won't be able to use it for resuming echo "cryptsetup: WARNING: resume device $source uses a key file" >&2 fi # prepend "/root" (to be substituted by the real root FS # mountpoint "$rootmnt" in the boot script) to the # absolute filename key="/root$key" ;; esac OPTIONS="$OPTIONS,keyscript=cat" fi OPTIONS="$OPTIONS,key=$key" } # get_device_modules() - determine required crypto kernel modules for device # # expected arguments: # * crypttab target device name (without /dev/mapper/ prefix) # # This function determines the required crypto kernel modules for cipher, # block cipher and optionally ivhash of the target device and returns them. # get_device_modules() { local node value cipher blockcipher ivhash node="$1" # Check the ciphers used by the active root mapping value=$(dmsetup table "$node" | cut -d " " -f4) cipher=$(echo "$value" | cut -d ":" -f1 | cut -d "-" -f1) blockcipher=$(echo "$value" | cut -d ":" -f1 | cut -d "-" -f2) ivhash=$(echo "$value" | cut -d ":" -s -f2) if [ -n "$cipher" ]; then echo "$cipher" else return 1 fi if [ -n "$blockcipher" ] && [ "$blockcipher" != "plain" ]; then echo "$blockcipher" fi if [ -n "$ivhash" ] && [ "$ivhash" != "plain" ]; then echo "$ivhash" fi return 0 } # canonical_device() - determine the # # expected arguments: # * device (either full path or LABEL=<x> or UUID=<y>) # * optional options to the function # # This function takes a device as argument and determines the corresponding # canonical device name. # If option '--no-simplify' is given as second argument, then the origin device # path after unraveling LABEL= and UUID= format and following symlinks is # returned. # If no option is given, the device is further unraveled and depending on the # device path, either the corresponding device-mapper path (as found in # /dev/mapper/) or the the corresponding disk symlink (as found in # /dev/disk/by-*/) is returned. # canonical_device() { local dev altdev original dev="$1" opt="$2" if [ "${dev#LABEL=}" != "$dev" ]; then altdev="${dev#LABEL=}" dev="/dev/disk/by-label/$(printf '%s' "$altdev" | sed 's,/,\\x2f,g')" elif [ "${dev#UUID=}" != "$dev" ]; then altdev="${dev#UUID=}" dev="/dev/disk/by-uuid/$altdev" fi original="$dev" if [ -h "$dev" ]; then dev=$(readlink -e "$dev") fi if [ "$opt" = "--no-simplify" ]; then printf '%s' "$dev" return 0 fi if [ "x${dev%/dev/dm-*}" = "x" ]; then # try to detect corresponding symlink in /dev/mapper/ for dmdev in /dev/mapper/*; do if [ "$(readlink -e "$dmdev")" = "$dev" ]; then dev="$dmdev" fi done fi altdev="${dev#/dev/mapper/}" if [ "$altdev" != "$dev" ]; then printf '%s' "$altdev" return 0 elif [ "x${original%/dev/disk/by-*/*}" = "x" ]; then # support crypttab UUID/LABEL entries # this is a /dev/disk/by-*/ path so return just the 'basename' echo "${original##/dev/disk/by-*/}" return 0 fi echo "cryptsetup: WARNING: failed to detect canonical device of $original" >&2 return 1 } # add_device() - Process a given device and add to /conf/conf.d/cryptroot # # expected arguments: # * device name (either crypttab target device name without /dev/mapper/ prefix # or LVM device-mapper name in format '<VG>:<LV>') # # This function takes a device name, does all required processing and adds the # result with all device options to /conf/conf.d/cryptroot in the initramfs. # Additionally, it returns required kernel modules. # add_device() { local node nodes lvmnodes opts lastopts i count nodes="$1" opts="" # Applied to all nodes lastopts="" # Applied to last node if [ -z "$nodes" ]; then return 0 fi # Flag root and resume devices if printf '%s' "$rootdevs" | tr ' ' '\n' | grep -Fxq "$nodes"; then opts="${opts:+$opts,}rootdev" fi if printf '%s' "$resumedevs" | tr ' ' '\n' | grep -Fxq "$nodes"; then opts="${opts:+$opts,}resumedev" fi # Check that it is a node under /dev/mapper/ # nodes=$(canonical_device "$nodes") || return 0 # Can we find this node in crypttab if ! node_is_in_crypttab "$nodes"; then # dm node but not in crypttab, is it a lvm device backed by dm-crypt nodes? lvmnodes=$(get_lvm_deps "$nodes") || return 1 # not backed by any dm-crypt nodes; stop here if [ -z "$lvmnodes" ]; then return 0 fi # It is a lvm device! opts="${opts:+$opts,}lvm=$nodes" nodes="$lvmnodes" fi # Prepare to setup each node count=$(printf '%s' "$nodes" | wc -w) i=1 for node in $nodes; do # Prepare the additional options if [ $i -eq $count ]; then if [ -n "$lastopts" ]; then opts="${opts:+$opts,}$lastopts" fi fi # Get crypttab root options if ! get_device_opts "$node" "$opts"; then continue fi printf '%s\n' "$OPTIONS" >>"$DESTDIR/conf/conf.d/cryptroot" # If we have a keyscript, make sure it is included if [ -n "$KEYSCRIPT" ]; then if [ ! -d "$DESTDIR/lib/cryptsetup/scripts" ]; then mkdir -p "$DESTDIR/lib/cryptsetup/scripts" fi if [ -e "/lib/cryptsetup/scripts/$KEYSCRIPT" ]; then copy_exec "/lib/cryptsetup/scripts/$KEYSCRIPT" /lib/cryptsetup/scripts >&2 elif [ -e "$KEYSCRIPT" ]; then copy_exec "$KEYSCRIPT" /lib/cryptsetup/scripts >&2 elif KSTYPE="$(type "$KEYSCRIPT" 2>&1)"; then if [ -x "${KSTYPE#"$KEYSCRIPT" is }" ]; then copy_exec "${KSTYPE#"$KEYSCRIPT" is }" /lib/cryptsetup/scripts >&2 fi else echo "cryptsetup: WARNING: failed to find keyscript $KEYSCRIPT" >&2 continue fi elif [ -n "$KEYFILE" ]; then case "$KEYFILE" in $KEYFILE_PATTERN) mkdir -pm0700 "$DESTDIR/cryptroot-keyfiles" cp --preserve=all "$KEYFILE" "$DESTDIR/cryptroot-keyfiles/${node}.key" ;; esac fi # If we have a LUKS header, make sure it is included # TODO: make it configurable to include the LUKS header into initramfs # disabled for now due to security reasons if [ -n "$CRYPTHEADER" ]; then if [ ! -d "$DESTDIR/conf/conf.d/cryptheader" ]; then mkdir -p "$DESTDIR/conf/conf.d/cryptheader" fi #if [ -e "$CONFDIR/conf.d/cryptheader/$CRYPTHEADER" ]; then # copy_exec "$CONFDIR/conf.d/cryptheader/$CRYPTHEADER" /conf/conf.d/cryptheader >&2 #elif [ -e "$CRYPTHEADER" ]; then # copy_exec "$CRYPTHEADER" /conf/conf.d/cryptheader >&2 #else # echo "cryptsetup: WARNING: failed to find LUKS header $CRYPTHEADER" >&2 # continue #fi fi # Calculate needed modules modules=$(get_device_modules $node | sort | uniq) if [ -z "$modules" ]; then echo "cryptsetup: WARNING: failed to determine cipher modules to load for $node" >&2 continue fi echo dm_mod echo dm_crypt echo "$modules" # Load hardware aes module if cpu_has_aesni; then echo aesni fi i=$(( $i + 1 )) done return 0 } # cpu_has_aesni() - Detect whether the host CPU has AES-NI support # # expected arguments: # * none # # This functions returns true when the host CPU has AES-NI support. # cpu_has_aesni() { return $(grep -q "^flags\s*:\s*.*aes" /proc/cpuinfo) } # add_crypto_modules() - determine kernel module path and add to initramfs # # expected arguments: # * kernel module name # # This function takes a kernel module name, determines the corresponding path # and runs manual_add_modules() from initramfs hook functions to add the module # to the initramfs. # add_crypto_modules() { local mod file altmod found genericfound mod="$1" found="" genericfound="" if [ -z "$mod" ]; then return 1 fi # We have several potential sources of modules (in order of preference): # # a) /lib/modules/$VERSION/kernel/arch/$ARCH/crypto/$mod-$specific.ko # b) /lib/modules/$VERSION/kernel/crypto/$mod_generic.ko # c) /lib/modules/$VERSION/kernel/crypto/$mod.ko # # and (currently ignored): # # d) /lib/modules/$VERSION/kernel/drivers/crypto/$specific-$mod.ko for file in $(find "$MODULESDIR/kernel/arch/" -name "$mod-*.ko" 2>/dev/null); do altmod="${file##*/}" altmod="${altmod%.ko}" manual_add_modules "$altmod" found="yes" done for file in $(find "$MODULESDIR/kernel/crypto/" -name "${mod}_generic.ko" 2>/dev/null); do altmod="${file##*/}" altmod="${altmod%.ko}" manual_add_modules "$altmod" found="yes" genericfound="yes" done if [ -z "$genericfound" ]; then for file in $(find "$MODULESDIR/kernel/crypto/" -name "${mod}.ko" 2>/dev/null); do altmod="${file##*/}" altmod="${altmod%.ko}" manual_add_modules "$altmod" found="yes" done fi if [ -z "$found" ]; then return 1 fi return 0 } # # Begin real processing # setup="no" rootdevs="" usrdevs="" resumedevs="" # XXX Backward compatibility: remove once Stretch has been promoted stable for v in CRYPTSETUP KEYFILE_PATTERN; do if eval [ "\${$v+x}" ]; then echo "WARNING: Setting $v in /etc/initramfs-tools/initramfs.conf" \ "is deprecated and will stop working in the future." \ "Use /etc/cryptsetup-initramfs/conf-hook instead." >&2 fi done # Load the hook's config if [ -f "/etc/cryptsetup-initramfs/conf-hook" ]; then . /etc/cryptsetup-initramfs/conf-hook fi # Include cryptsetup modules, regardless of _this_ machine configuration if [ -n "$CRYPTSETUP" ] && [ "$CRYPTSETUP" != "n" ]; then setup="yes" fi if [ "$KEYFILE_PATTERN" ]; then setup="yes" case "${UMASK:-$(umask)}" in 0[0-7]77) ;; *) echo "WARNING: permissive UMASK (${UMASK:-$(umask)})." \ "Private key material inside the initrd might be left unprotected." >&2 ;; esac fi # Find the root and resume device(s) if [ -r /etc/crypttab ]; then rootdevs=$(get_fs_devices /) if [ -z "$rootdevs" ]; then echo "cryptsetup: WARNING: could not determine root device from /etc/fstab" >&2 fi usrdevs=$(get_fs_devices /usr) resumedevs=$(get_resume_devices) initramfsdevs=$(get_initramfs_devices) fi # Load the config opts and modules for each device for dev in $rootdevs $usrdevs $resumedevs $initramfsdevs; do if ! modules=$(add_device "$dev"); then echo "cryptsetup: FAILURE: could not determine configuration for $dev" >&2 continue fi if [ -n "$modules" ]; then setup="yes" fi if [ "$setup" = "no" ]; then continue fi if [ "$MODULES" = "most" ]; then archcrypto="$(find "$MODULESDIR/kernel/arch" -type d -name "crypto" 2>/dev/null)" if [ -n "$archcrypto" ]; then copy_modules_dir "${archcrypto##*${MODULESDIR}/}" fi copy_modules_dir "kernel/crypto" else for mod in $modules; do add_crypto_modules $mod done fi done # With large initramfs, we always add a basic subset of modules if [ "$MODULES" != "dep" ] && [ "$setup" = "yes" ]; then for mod in aes cbc chainiv cryptomgr krng sha256 xts; do add_crypto_modules $mod done fi # See if we need to add the basic components if [ "$setup" = "yes" ]; then for mod in dm_mod dm_crypt; do manual_add_modules $mod done copy_exec /sbin/cryptsetup copy_exec /sbin/dmsetup copy_exec /lib/cryptsetup/askpass # We need sed. Either via busybox or as standalone binary. if [ "$BUSYBOX" = "n" ] || [ ! -e ${BUSYBOXDIR}/busybox ]; then copy_exec /bin/sed fi fi exit 0
      
      





diff / usr / share / initramfs-tools / hooks / cryptroot cryptroot
 45a46,51 > elif [ "$type" = "zfs" ]; then > zpool="$(echo "$device"|sed 's#^/dev/zvol/##;s#\([^/]*\).*#\1#')" > for ss in $(zpool list -Pv "$zpool"); do > cdev=$(canonical_device "$ss" 2>/dev/null) || continue > devices="${devices:+$devices }$cdev" > done || return 0 375c381 < if [ "UUID=${source#UUID=}" = "$source" -a ! -b "/dev/disk/by-uuid/${source#UUID=}" ] || [ "UUID=${source#UUID=}" != "$source" -a ! -b "$source" ]; then --- > if [ "UUID=${source#UUID=}" = "$source" -a ! \( -b "/dev/disk/by-uuid/${source#UUID=}" -o -b "/dev/disk/by-partuuid/${source#UUID=}" \) ] || [ "UUID=${source#UUID=}" != "$source" -a ! -b "$source" ]; then
      
      





/ etc / initramfs-tools / scripts / local-top
 #!/bin/sh PREREQ="cryptroot-prepare" # # Standard initramfs preamble # prereqs() { # Make sure that cryptroot is run last in local-top for req in $(dirname $0)/*; do script=${req##*/} if [ $script != cryptroot ]; then echo $script fi done } case $1 in prereqs) prereqs exit 0 ;; esac # source for log_*_msg() functions, see LP: #272301 . /scripts/functions # # Helper functions # message() { if [ -x /bin/plymouth ] && plymouth --ping; then plymouth message --text="$@" elif [ -p /dev/.initramfs/usplash_outfifo ] && [ -x /sbin/usplash_write ]; then usplash_write "TEXT-URGENT $@" else echo "$@" >&2 fi return 0 } udev_settle() { # Wait for udev to be ready, see https://launchpad.net/bugs/85640 if command -v udevadm >/dev/null 2>&1; then udevadm settle --timeout=30 elif command -v udevsettle >/dev/null 2>&1; then udevsettle --timeout=30 fi return 0 } parse_options() { local cryptopts cryptopts="$1" if [ -z "$cryptopts" ]; then return 1 fi # Defaults cryptcipher=aes-cbc-essiv:sha256 cryptsize=256 crypthash=ripemd160 crypttarget=cryptroot cryptsource="" cryptheader="" cryptlvm="" cryptkeyscript="" cryptkey="" # This is only used as an argument to an eventual keyscript cryptkeyslot="" crypttries=3 crypttcrypt="" cryptveracrypt="" cryptrootdev="" cryptdiscard="" CRYPTTAB_OPTIONS="" local IFS=" ," for x in $cryptopts; do case $x in hash=*) crypthash=${x#hash=} ;; size=*) cryptsize=${x#size=} ;; cipher=*) cryptcipher=${x#cipher=} ;; target=*) crypttarget=${x#target=} export CRYPTTAB_NAME="$crypttarget" ;; source=*) cryptsource=${x#source=} if [ ${cryptsource#UUID=} != $cryptsource ]; then cryptsource="/dev/disk/by-uuid/${cryptsource#UUID=}" elif [ ${cryptsource#LABEL=} != $cryptsource ]; then cryptsource="/dev/disk/by-label/$(printf '%s' "${cryptsource#LABEL=}" | sed 's,/,\\x2f,g')" elif [ ${cryptsource#ID=} != $cryptsource ]; then cryptsource="/dev/disk/by-id/${cryptsource#ID=}" fi export CRYPTTAB_SOURCE="$cryptsource" ;; header=*) cryptheader=${x#header=} if [ ! -e "$cryptheader" ] && [ -e "/conf/conf.d/cryptheader/$cryptheader" ]; then cryptheader="/conf/conf.d/cryptheader/$cryptheader" fi export CRYPTTAB_HEADER="$cryptheader" ;; lvm=*) cryptlvm=${x#lvm=} ;; keyscript=*) cryptkeyscript=${x#keyscript=} ;; key=*) if [ "${x#key=}" != "none" ]; then cryptkey=${x#key=} fi export CRYPTTAB_KEY="$cryptkey" ;; keyslot=*) cryptkeyslot=${x#keyslot=} ;; tries=*) crypttries="${x#tries=}" case "$crypttries" in *[![:digit:].]*) crypttries=3 ;; esac ;; tcrypt) crypttcrypt="yes" ;; veracrypt) cryptveracrypt="--veracrypt" ;; rootdev) cryptrootdev="yes" ;; discard) cryptdiscard="yes" ;; esac PARAM="${x%=*}" if [ "$PARAM" = "$x" ]; then VALUE="yes" else VALUE="${x#*=}" fi CRYPTTAB_OPTIONS="$CRYPTTAB_OPTIONS $PARAM" eval export CRYPTTAB_OPTION_$PARAM="\"$VALUE\"" done export CRYPTTAB_OPTIONS if [ -z "$cryptsource" ]; then message "cryptsetup ($crypttarget): source parameter missing" return 1 fi return 0 } activate_vg() { # Sanity checks if [ ! -x /sbin/lvm ]; then message "cryptsetup ($crypttarget): lvm is not available" return 1 fi # Detect and activate available volume groups /sbin/lvm vgscan /sbin/lvm vgchange -ay --sysinit return $? } setup_mapping() { local opts count cryptopen cryptremove NEWROOT is_luks opts="$1" is_luks=0 if [ -z "$opts" ]; then return 0 fi parse_options "$opts" || return 1 if [ -z "$cryptkeyscript" ]; then if [ ${cryptsource#/dev/disk/by-uuid/} != $cryptsource ]; then # UUIDs are not very helpful diskname="$crypttarget" else diskname="$cryptsource ($crypttarget)" fi cryptkeyscript="/lib/cryptsetup/askpass" cryptkey="1Please unlock disk $diskname: " elif ! type "$cryptkeyscript" >/dev/null; then message "cryptsetup ($crypttarget): error - script \"$cryptkeyscript\" missing" return 1 fi if [ "$cryptkeyscript" = "cat" ] && [ "${cryptkey#/root/}" != "$cryptkey" ]; then # skip the mapping if the root FS is not mounted yet sed -rn 's/^\s*[^#]\S*\s+(\S+)\s.*/\1/p' /proc/mounts | grep -Fxq "$rootmnt" || return 1 # substitute the "/root" prefix by the real root FS mountpoint otherwise cryptkey="${rootmnt}/${cryptkey#/root/}" fi if [ -n "$cryptheader" ] && ! type "$cryptheader" >/dev/null; then message "cryptsetup ($crypttarget): error - LUKS header \"$cryptheader\" missing" return 1 fi # The same target can be specified multiple times # eg root and resume lvs-on-lvm-on-crypto if [ -e "/dev/mapper/$crypttarget" ]; then return 0 fi modprobe -q dm_crypt # Make sure the cryptsource device is available if [ ! -e $cryptsource ]; then activate_vg fi # If the encrypted source device hasn't shown up yet, give it a # little while to deal with removable devices # the following lines below have been taken from # /usr/share/initramfs-tools/scripts/local, as suggested per # https://launchpad.net/bugs/164044 if [ ! -e "$cryptsource" ]; then log_begin_msg "Waiting for encrypted source device..." # Default delay is 180s if [ -z "${ROOTDELAY}" ]; then slumber=180 else slumber=${ROOTDELAY} fi if [ -x /sbin/usplash_write ]; then /sbin/usplash_write "TIMEOUT ${slumber}" || true fi slumber=$(( ${slumber} * 10 )) while [ ! -e "$cryptsource" ]; do # retry for LVM devices every 10 seconds if [ ${slumber} -eq $(( ${slumber}/100*100 )) ]; then activate_vg fi /bin/sleep 0.1 slumber=$(( ${slumber} - 1 )) [ ${slumber} -gt 0 ] || break done if [ ${slumber} -gt 0 ]; then log_end_msg 0 else log_end_msg 1 || true fi if [ -x /sbin/usplash_write ]; then /sbin/usplash_write "TIMEOUT 15" || true fi fi udev_settle # We've given up, but we'll let the user fix matters if they can if [ ! -e "${cryptsource}" ]; then echo " ALERT! ${cryptsource} does not exist." echo " Check cryptopts=source= bootarg: cat /proc/cmdline" echo " or missing modules, devices: cat /proc/modules; ls /dev" panic -r "Dropping to a shell. Will skip ${cryptsource} if you can't fix." fi if [ ! -e "${cryptsource}" ]; then return 1 fi # Prepare commands cryptopen="/sbin/cryptsetup -T 1" if [ "$cryptdiscard" = "yes" ]; then cryptopen="$cryptopen --allow-discards" fi if [ -n "$cryptheader" ]; then cryptopen="$cryptopen --header=$cryptheader" fi if [ -n "$cryptkeyslot" ]; then cryptopen="$cryptopen --key-slot=$cryptkeyslot" fi if /sbin/cryptsetup isLuks ${cryptheader:-$cryptsource} >/dev/null 2>&1; then is_luks=1 cryptopen="$cryptopen open --type luks $cryptsource $crypttarget --key-file=-" elif [ "$crypttcrypt" = "yes" ]; then cryptopen="$cryptopen open --type tcrypt $cryptveracrypt $cryptsource $crypttarget" else cryptopen="$cryptopen -c $cryptcipher -s $cryptsize -h $crypthash open --type plain $cryptsource $crypttarget --key-file=-" fi cryptremove="/sbin/cryptsetup remove $crypttarget" NEWROOT="/dev/mapper/$crypttarget" # Try to get a satisfactory password $crypttries times count=0 while [ $crypttries -le 0 ] || [ $count -lt $crypttries ]; do export CRYPTTAB_TRIED="$count" if [ $count -gt 1 ]; then /bin/sleep 3 fi if [ -z "$cryptkeyscript" -a "$is_luks" -eq "1" ]; then cryptkey="Unlocking the disk $cryptsource ($crypttarget)\nEnter passphrase: " if [ -x /bin/plymouth ] && plymouth --ping; then cryptkeyscript="plymouth ask-for-password --prompt" cryptkey=$(echo -e "$cryptkey") else cryptkeyscript="/lib/cryptsetup/askpass" fi fi if [ -n "$CACHED_PASSWORD" ]; then if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \ echo -n "$CACHED_PASSWORD" | $cryptopen 2>/dev/null; then unset CACHED_PASSWORD fi fi count=$(( $count + 1 )) if [ -z "$CACHED_PASSWORD" ]; then CACHED_PASSWORD="`$cryptkeyscript \"$cryptkey\"`" if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \ echo -n "$CACHED_PASSWORD" | $cryptopen; then message "cryptsetup: cryptsetup failed, bad password or options?" unset CACHED_PASSWORD continue fi fi if [ ! -e "$NEWROOT" ]; then message "cryptsetup ($crypttarget): unknown error setting up device mapping" return 1 fi #FSTYPE='' #eval $(fstype < "$NEWROOT") FSTYPE="$(/sbin/blkid -s TYPE -o value "$NEWROOT")" # See if we need to setup lvm on the crypto device #if [ "$FSTYPE" = "lvm" ] || [ "$FSTYPE" = "lvm2" ]; then if [ "$FSTYPE" = "LVM_member" ] || [ "$FSTYPE" = "LVM2_member" ]; then if [ -z "$cryptlvm" ]; then message "cryptsetup ($crypttarget): lvm fs found but no lvm configured" return 1 elif ! activate_vg; then # disable error message, LP: #151532 #message "cryptsetup ($crypttarget): failed to setup lvm device" return 1 fi # Apparently ROOT is already set in /conf/param.conf for # flashed kernels at least. See bugreport #759720. if [ -f /conf/param.conf ] && grep -q "^ROOT=" /conf/param.conf; then NEWROOT=$(sed -n 's/^ROOT=//p' /conf/param.conf) else NEWROOT=${cmdline_root:-/dev/mapper/$cryptlvm} if [ "$cryptrootdev" = "yes" ]; then # required for lilo to find the root device echo "ROOT=$NEWROOT" >>/conf/param.conf fi fi #eval $(fstype < "$NEWROOT") FSTYPE="$(/sbin/blkid -s TYPE -o value "$NEWROOT")" fi #if [ -z "$FSTYPE" ] || [ "$FSTYPE" = "unknown" ]; then if [ -z "$FSTYPE" ]; then message "cryptsetup ($crypttarget): unknown fstype, bad password or options?" udev_settle $cryptremove unset CACHED_PASSWORD continue fi # decrease $count by 1, apparently last try was successful. count=$(( $count - 1 )) message "cryptsetup ($crypttarget): set up successfully" export CACHED_PASSWORD break done failsleep=60 # make configurable later? if [ "$cryptrootdev" = "yes" ] && [ $crypttries -gt 0 ] && [ $count -ge $crypttries ]; then message "cryptsetup ($crypttarget): maximum number of tries exceeded" message "cryptsetup: going to sleep for $failsleep seconds..." sleep $failsleep exit 1 fi udev_settle return 0 } exit_script() { CACHED_PASSWORD="`dd bs=512 if=/dev/random count=1 2>/dev/null `" unset CACHED_PASSWORD exit $1 } # # Begin real processing # # Do we have any kernel boot arguments? cmdline_cryptopts='' unset cmdline_root for opt in $(cat /proc/cmdline); do case $opt in cryptopts=*) opt="${opt#cryptopts=}" if [ -n "$opt" ]; then if [ -n "$cmdline_cryptopts" ]; then cmdline_cryptopts="$cmdline_cryptopts $opt" else cmdline_cryptopts="$opt" fi fi ;; root=*) opt="${opt#root=}" case $opt in /*) # Absolute path given. Not lilo major/minor number. cmdline_root=$opt ;; *) # lilo major/minor number (See #398957). Ignore esac ;; esac done if [ -n "$cmdline_cryptopts" ]; then # Call setup_mapping separately for each possible cryptopts= setting for cryptopt in $cmdline_cryptopts; do setup_mapping "$cryptopt" done exit 0 fi # Do we have any settings from the /conf/conf.d/cryptroot file? if [ -r /conf/conf.d/cryptroot ]; then while read mapping <&3; do setup_mapping "$mapping" 3<&- done 3< /conf/conf.d/cryptroot fi exit_script 0
      
      





diff / usr / share / initramfs-tools / scripts / local-top / cryptroot cryptroot
 35a36,37 > elif [ -p /dev/.initramfs/usplash_outfifo ] && [ -x /sbin/usplash_write ]; then > usplash_write "TEXT-URGENT $@" 101a104,105 > elif [ ${cryptsource#ID=} != $cryptsource ]; then > cryptsource="/dev/disk/by-id/${cryptsource#ID=}" 182c186 < local opts count cryptopen cryptremove NEWROOT --- > local opts count cryptopen cryptremove NEWROOT is_luks 183a188 > is_luks=0 199c204 < cryptkey="Please unlock disk $diskname: " --- > cryptkey="1Please unlock disk $diskname: " 244a250,252 > if [ -x /sbin/usplash_write ]; then > /sbin/usplash_write "TIMEOUT ${slumber}" || true > fi 262a271,273 > if [ -x /sbin/usplash_write ]; then > /sbin/usplash_write "TIMEOUT 15" || true > fi 291a303 > is_luks=1 304a317,337 > if [ $count -gt 1 ]; then > /bin/sleep 3 > fi > > if [ -z "$cryptkeyscript" -a "$is_luks" -eq "1" ]; then > cryptkey="Unlocking the disk $cryptsource ($crypttarget)\nEnter passphrase: " > if [ -x /bin/plymouth ] && plymouth --ping; then > cryptkeyscript="plymouth ask-for-password --prompt" > cryptkey=$(echo -e "$cryptkey") > else > cryptkeyscript="/lib/cryptsetup/askpass" > fi > fi > > if [ -n "$CACHED_PASSWORD" ]; then > if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \ > echo -n "$CACHED_PASSWORD" | $cryptopen 2>/dev/null; then > unset CACHED_PASSWORD > fi > fi > 307c340,341 < if [ ! -e "$NEWROOT" ]; then --- > if [ -z "$CACHED_PASSWORD" ]; then > CACHED_PASSWORD="`$cryptkeyscript \"$cryptkey\"`" 309,310c343,345 < $cryptkeyscript "$cryptkey" | $cryptopen; then < message "cryptsetup ($crypttarget): cryptsetup failed, bad password or options?" --- > echo -n "$CACHED_PASSWORD" | $cryptopen; then > message "cryptsetup: cryptsetup failed, bad password or options?" > unset CACHED_PASSWORD 355a391 > unset CACHED_PASSWORD 362a399,401 > > export CACHED_PASSWORD > 378a418,424 > exit_script() > { > CACHED_PASSWORD="`dd bs=512 if=/dev/random count=1 2>/dev/null `" > unset CACHED_PASSWORD > exit $1 > } > 425c471 < exit 0 --- > exit_script 0
      
      





crypttabに追加:







echo "root_crypt1 /dev/disk/by-id/ata-Samsung_SSD_850_PRO-part3 none luks,discard" >> /mnt/etc/crypttab





echo "root_crypt2 /dev/disk/by-id/ata-Micron_1100-part3 none luks,discard" >> /mnt/etc/crypttab









ここでは、ディスクはUUIDで示されていませんこれは意図的に行われます。

cryptrootフック、または何らかの理由で私が修正したスクリプト(これについて)はUUIDで誤って機能し、セクションが表示されませんでした。







ブートローダーをインストールし、ルートFSを認識することを確認します



apt-get install grub-pc





grub-probe /



-「zfs」を出力する必要があります







ZFSミラーにブートローダーをインストールするための推奨オプションは、この記事で見ることができます







ブートローダーを構成し、ブートレコードにインストールする



echo GRUB_PRELOAD_MODULES=\"part_gpt zfs\" >> /etc/default/grub





echo GRUB_DISABLE_OS_PROBER=true >> /etc/default/grub





echo "export ZPOOL_VDEV_NAME_PATH=YES" > /etc/profile.d/grub2_zpool_fix.sh





ZPOOL_VDEV_NAME_PATH=YES update-grub





update-initramfs -u -k all









ブートセクションの初期化



cd && tar -C / -cf boot.tar /boot





mkfs.ext4 -L boot1 -m0 /dev/disk/by-id/ata-Samsung_SSD_850_PRO-part2





mkfs.ext4 -L boot2 -m0 /dev/disk/by-id/ata-Micron_1100-part2









ブートローダーをインストールする



mount /dev/disk/by-id/ata-Samsung_SSD_850_PRO-part2 /boot && tar -C / -xf boot.tar





update-initramfs -k all -u -t && update-grub





grub-install --bootloader-id=debian1 --recheck --no-floppy /dev/disk/by-id/ata-Samsung_SSD_850_PRO





umount /boot





mount /dev/disk/by-id/ata-Micron_1100-part2 /boot && tar -C / -xf boot.tar





update-initramfs -k all -u -t && update-grub





grub-install --bootloader-id=debian2 --recheck --no-floppy /dev/disk/by-id/ata-Micron_1100





umount /boot









ルートパスワードを設定する



passwd









スナップショットを作成する



zfs snapshot rpool/ROOT/debian@install









アンマウントして再起動する



umount /tmp





exit





mount | grep -v zfs | tac | awk '/\/mnt/ {print $3}' | xargs -i{} umount -lf {}





zpool export rpool





reboot









インストールされたシステムを起動し、セットアップを実行します



( ONLINE):

zpool status -v









SSH .

:

zfs create rpool/home/user





adduser user





cp -a /etc/skel/.[!.]* /home/user





chown -R user:user /home/user





usermod -a -G audio,cdrom,dip,floppy,netdev,plugdev,sudo,video user











apt dist-upgrade --yes









Debian ZFS .







FAQ



?



.

:









, , , .







EFI ?



:









ZFS ?



, , .







/boot ZFS?



, . grub .







?



Grub , (, , cryptroot).

, .







FreeBSD, ZFS " "?



, NAS WEB-. FreeBSD — , , FreeNAS.

OpenMediaVault — , Debian.







謝辞



, , Debian: , .

FreeNAS, ZFS.

, ZFS Linux.








All Articles