如何在一块硬盘上使用UEFI安装两个独立的Ubuntu系统?

出于安全考虑,我想在一台只有一个硬盘的电脑上使用UEFI安装一个完全独立的第二操作系统。这两个安装都应该能够使用不同的LUKS加密分区作为根设备(在加密之上的逻辑卷管理),并且需要能够使用它们自己的内核。
拥有两个不同操作系统的双重引导并不是什么大问题。Ubuntu和Fedora不会相互干扰,并且可以共享EFI系统分区,但是如果安装两个Ubuntu系统,它们会因为要在相同的EFI位置安装它们自己的Grub实例而发生冲突。
有没有办法在Ubuntu安装过程中将Grub安装到与`/boot/efi/EFI/ubuntu`不同的位置?我需要一种持久的方式,这样软件包更新和内核/Grub更新仍然会安装在那个路径下。就像Fedora的Grub会安装在`/boot/efi/EFI/fedora`一样。我在Grub中找不到那个配置选项。如果可以的话,我的Dell UEFI启动菜单将允许我选择要加载的操作系统。也许我在efibootmgr和grub-efi之间缺少一些连接。
或者,是否可能使用两个Ubuntu安装中的一个单独的Grub安装,并自动检测正确的引导设置?我的意思是,我知道`os-prober`会找到另一个带有内核的`/boot`分区,但它如何知道该操作系统的正确引导参数(例如,作为根文件系统的锁定加密卷内的LVM卷)?我可以理解它可以处理未加密的单分区安装,但它无法匹配一个`/boot`与其对应的根文件系统,对吗?而且如果加密的话完全不可能。因此,这将需要大量手动调整Grub配置文件。我也不喜欢这个共享引导程序配置的选项,这使得两个操作系统在某种程度上不够隔离。
我对服务器的基于文本的专家安装没问题,顺便说一下。只要在每次内核/Grub更新时不需要重复这些步骤,我也可以进行一些自定义配置。

1这个问题(以及答案)非常有帮助,因为我需要在同一台机器上连续进行多个独立的Ubuntu桌面安装,用于测试目的,并且为了简单起见,使用相同的硬盘。只是想确认一下 - Ubuntu更新会默认更新grub安装吗?而grub又是通用于不同的Ubuntu安装的。Ubuntu安装中的Linux内核组件实际上是放在UEFI分区和grub中的吗? - matanster
我添加了这个,是因为我希望巩固对其中纠缠的理解,同时为这个场景构建一个更加详尽的架构。 - matanster
4个回答

我有两个建议...
选项1:分开的ESP
在EFI下,引导加载程序位于“EFI系统分区(ESP)”上。我用引号括起来的“the”是因为没有规定你只能有一个ESP。如果你在硬盘上创建了两个ESP,你可以使用其中一个进行第一次安装,第二个ESP用于第二次安装。这应该可以很顺利地工作,尽管你需要手动创建分区(在安装过程中使用“其他选项”),至少对于第二个Ubuntu安装来说。
这种方法的一个问题是,尽管EFI规范明确说明可以创建任意数量的ESP,但某些软件可能会对此感到困惑。其中一个突出的例子是Windows安装程序,至少在Windows 7上(我不知道Windows 8或更高版本);当Windows 7安装程序看到一个带有两个ESP的磁盘时,它会出现故障并做一些奇怪的事情。据我所知,它无法正确完成自己的安装。可以想象,Windows修复工具可能会遇到同样的问题。如果您在此系统上没有启动Windows,这应该不是什么大问题。如果您正在使用Windows启动,您只需要意识到这个问题,因为如果遇到问题,您可以通过临时更改非Windows ESP的类型代码来轻松解决。请注意,Windows在带有多个ESP的磁盘上可以正常启动;只是安装程序对这种磁盘感到困扰而已。
另一个问题是如何在两个发行版之间切换。您可能需要使用类似于GRUB Customizer的工具来自定义一个或两个安装的GRUB设置。另一个(但不冲突的)选择是使用固件自带的引导管理器在两个GRUB安装之间进行切换,并且使用每个安装来引导其自己版本的Ubuntu。
第二种选择:放弃GRUB(或至少放弃Ubuntu的GRUB工具)
GRUB在你的情况下存在的问题是,你有两个安装,并且GRUB维护工具很可能会对这种配置感到困惑。这个观察结果导致了一个明显的解决方案,那就是你应该简单地不使用这些工具。有几个其他适用于Linux的EFI引导加载程序,其中大多数比GRUB更容易手动维护。你可以设置ELILO、SYSLINUX、Fedora的修补过的GRUB Legacy、gummiboot或者rEFInd,并手动管理你的两个安装。事实上,因为rEFInd在每次启动时都会检测内核,所以一旦设置好,rEFInd几乎不需要维护。或者,你也可以手动编辑你的grub.cfg文件来实现你想要的功能,而不依赖于GRUB的设置脚本。
除了rEFInd之外,所有这些工具在更新内核时都需要你进行配置更改,这可能会有些麻烦。还有一个问题是何时以及如何安装额外的引导程序。我可能会推迟到第二个Ubuntu安装之后再安装它,因为每个安装都会将自己的GRUB注册为默认的引导加载程序,而你希望覆盖掉这个默认设置。

请注意,这些工具都无法从加密文件系统或LVM读取内核,因此您需要为每个Ubuntu安装设置单独的未加密的/boot分区。根据我看到的大多数说明,这是设置加密Ubuntu安装的方式,所以除非您想要在磁盘加密的“最前沿”玩耍,否则不会有太大问题。

一些EFI启动加载程序有额外的特定分区或文件系统要求。特别是ELILO、SYSLINUX和gummiboot都要求内核位于FAT分区上,并且ESP对此最好。您可以通过将ESP挂载到/boot来实现此目的,在Ubuntu中这是一个不太可靠的解决方案,因为某些软件包更新需要符号链接。如果您有两个独立的Ubuntu安装,这样做也会遇到问题,因为它们都会尝试占用相同的文件。(在这种情况下,“ESP”实际上指的是“引导加载程序运行的分区”,所以您可以在这种情况下只有一个ESP。)GRUB Legacy和rEFInd对此更加灵活。

我的建议

个人而言,我会使用rEFInd来实现这个功能 - 但由于我是rEFInd的维护者,所以我并不完全客观。事实上,我有一台电脑可以在三个Ubuntu安装之间多重引导,而rEFInd可以很好地在它们之间切换。这个特定的系统没有使用加密,但我怀疑这对rEFInd来说不会造成任何新问题。
话虽如此,单独的ESP也应该可以正常工作,但需要注意的是,您可能需要使用GRUB Customizer来调整至少一个GRUB副本的设置。

非常好的建议,谢谢!我相信你关于规范允许拥有多个ESP的说法是正确的,但我怀疑我的Dell Latitude UEFI实现是否也支持它。它只允许我通过单个独立驱动器浏览路径。不过我还是要亲自试一试。 - gertvdijk
如果你的戴尔电脑的EFI实现如此糟糕,以至于无法处理多个ESP(EFI系统分区),那么你应该将其退回商店并要求退款。说真的,这种糟糕的情况表明固件的可靠性堪忧,我不会相信它能够完成最基本的任务。实际上,我认为情况不会那么糟糕;我从未听说过有EFI无法处理多个ESP的情况。 - Rod Smith

我在使用单个ESP时采用以下方法:
我为每个操作系统创建了额外的引导加载程序。
sudo grub-install --bootloader-id=ID

为每个操作系统使用不同的ID

例如:

我安装了Ubuntu 16.04和Ubuntu 18.04。我启动Ubuntu 16.04并运行

sudo grub-install --bootloader-id=Ubuntu1604

然后我从Ubuntu 18.04启动后运行
sudo grub-install --bootloader-id=Ubuntu1804

在UEFI设置中,我看到了名为Ubuntu1604Ubuntu1804的新引导项,并重新排列引导顺序将其中一个新项设置为第一位。
我还可以在ESP中看到这些名称的文件夹。
当系统升级带来了新版本的grub时,它会重新安装一个全新的grub实例到ESP上的ubuntu文件夹中,这不会影响我自己创建的引导加载程序,但我需要再次重新排列引导顺序,因为ubuntu项将被推到引导顺序的第一位。
这是我的配置中efibootmgr -v显示的内容:
~$ efibootmgr -v 当前启动项:0001 超时时间:0 秒 启动顺序:0001,0002,0004,0000,0003,0005 Boot0000* ubuntu HD(1,GPT,249ac0f6-d3e4-4b91-91d5-6e8d63c093c3,0x800,0x9a000)/File(\EFI\ubuntu\shimx64.efi) Boot0001* US1804 HD(1,GPT,249ac0f6-d3e4-4b91-91d5-6e8d63c093c3,0x800,0x9a000)/File(\EFI\US1804\grubx64.efi) Boot0002* US1604 HD(1,GPT,249ac0f6-d3e4-4b91-91d5-6e8d63c093c3,0x800,0x9a000)/File(\EFI\US1604\grubx64.efi) Boot0003* UEFI OS HD(1,GPT,249ac0f6-d3e4-4b91-91d5-6e8d63c093c3,0x800,0x9a000)/File(\EFI\BOOT\BOOTX64.EFI) Boot0004* US1904 HD(1,GPT,249ac0f6-d3e4-4b91-91d5-6e8d63c093c3,0x800,0x9a000)/File(\EFI\US1904\shimx64.efi) Boot0005* ubuntu HD(1,GPT,249ac0f6-d3e4-4b91-91d5-6e8d63c093c3,0x800,0x9a000)/File(EFI\Ubuntu\grubx64.efi)

还是对我没用。我将/etc/default/grub中的默认设置更改为GRUB_DISTRIBUTOR="Bionic_18_04",并重新安装grub,但它仍然使用这个作为UEFI默认ID。但每次启动时它只使用/EFI/ubuntu/grub.cfg作为默认引导位置,而不是我新的/EFI/bionic_18_04/grub.cfg。 - oldfred
@oldfred 对我来说,这个方法已经连续几年以来都很好地运行着三重启动。 - mook765
尝试了你的命令,而不是在/etc/default/grub中重新命名。没有任何区别。UEFI设置为默认引导新条目。但它使用我的/efi/ubuntu作为默认引导,而不是新的/EFI/ubuntu1804文件夹中的grub。我认为是grub而不是UEFI造成了差异。 - oldfred
@oldfred请查看我答案中添加的efibootmgr -v输出。它可以正常工作。您可能有其他更改,防止您这样做。我所描述的是我所做的唯一使其正常工作的事情。 - mook765
我确实检查了efibootmgr -v,并设置了新的条目,但启动时却引导到了/EFI/ubuntu中的grub。我的引导是/EFI/ubuntu1804/shimx64.efi。你是使用grubx64.efi还是shimx64.efi,也许这就是区别所在?我已经关闭了安全启动,但它默认将shim作为第一个ubuntu1804条目。在某个时候,我在/EFI文件夹中有很多UEFI条目或文件夹,导致启动出现问题,不得不使用另一块驱动器上的rEFInd来引导。因此,我现在不希望/EFI文件夹中有太多内容或UEFI条目。 - oldfred
@oldfred 我没有做任何其他事情,所有的引导程序工作都在我的系统中完成。19.04安装了shimx64.efi,旧版本的发行版安装了grubx64.efi。我从未碰过任何东西。安全启动已禁用。当我安装新版本时,我会删除旧版本,删除ESP中相关的文件夹和启动菜单条目。然后我只需使用--bootloader-id选项安装一个新的grub实例,就这样。我以前使用过GRUB_DISTRIBUTOR,但对/etc/grub.d/05_debian_theme的副作用不满意。 - mook765
很高兴它对你有用。我会继续尝试实验。我做过一个实验,就是安装Debian来看看grub的区别。安装程序让我直接安装到我的硬盘(sdb),而不是默认的固态硬盘(sda)。无论是sda、sdb还是外部闪存驱动器,Ubiquity总是会覆盖我的主要工作环境18.04的安装。 - oldfred
让我们在聊天中继续这个讨论。 - mook765

这是我用来在单个硬盘上使用UEFI双引导两个LUKS加密的Ubuntu系统的步骤,采用了Rod Smith之前推荐的第二种选项。这是针对Ubuntu 18.04.1-desktop的。在安装过程中,不再提供家目录加密作为选项,因为对eCryptfs的可靠性和维护存在疑虑。建议使用LUKS代替,所以我认为这是拥有多个用户的加密家目录的最佳选择。
    1. 使用Live USB启动,这是通过下载ISO文件并使用启动磁盘创建工具格式化和设置USB驱动器完成的。
    1. 使用GParted对磁盘进行分区。这是基于https://help.ubuntu.com/community/ManualFullSystemEncryption上的建议,并使用Ubuntu安装程序在选择全磁盘加密时设置的一些默认值。
      • EFI系统分区/512MiB/FAT32/引导,esp(标志)
      • 引导系统#1/732MiB/EXT4
      • 引导系统#2/732MiB/EXT4
      • 加密数据#1/[期望大小]/已清除
      • 加密数据#2/[期望大小]/已清除
    1. 重新启动进入Live USB
      • 安装Ubuntu
      • 选择安装偏好设置
      • 选择“其他”作为磁盘布局的分区方式,然后在该分区配置中进行安装:
        • 在底部菜单中,将“EFI系统分区”选为引导加载程序。
        • 选择“加密数据#1”,选择“物理设备进行加密”,然后输入要用于分区的加密密码。
        • 选择新创建的带有EXT4的分区,并将挂载点更改为“/”。
        • 选择“引导系统#1”,并将其挂载点设置为“/boot”。
      • 继续安装
    1. 重新启动进入新安装
      • 通过“apt-get install refind”安装“refind”,并让它自动安装到ESP(EFI系统分区)。
    1. 重新启动进入Live USB
      • 对于#2引导系统和加密数据#2分区,重复步骤3和4,安装第二个Ubuntu安装。
    1. 根据需要配置和升级每个安装。

我尝试了使用单个ESP和分开的引导程序ID的方法,效果还不错。我可以确认update-grub能够检测到所有的Ubuntu安装,即使它们位于加密的LVM上,有独立的未加密/boot分区。
只有一个问题是,尽管在EFI固件中首先选择了"主要"安装,但grub仍然显示"非主要"安装的启动菜单。所以我不得不再次运行grub-install,这次没有指定bootloader-id。不确定为什么会出现这种情况,它本不应该使用默认的EFI/ubuntu下的grub.cfg文件。