calamares-nixos-extensions: add filesystem type chooser with btrfs support (#475297)
This commit is contained in:
@@ -20,8 +20,20 @@ extraMounts:
|
||||
mountPoint: /sys/firmware/efi/efivars
|
||||
efi: true
|
||||
|
||||
# Ensure the right fmask/dmask is set on the ESP, as it will be
|
||||
# picked up by nixos-generate-config later
|
||||
# Btrfs subvolume layout for NixOS
|
||||
# Empty subvolume for / means no subvolume (top-level) for GRUB compatibility
|
||||
btrfsSubvolumes:
|
||||
- mountPoint: /
|
||||
subvolume: ""
|
||||
- mountPoint: /home
|
||||
subvolume: /home
|
||||
- mountPoint: /nix
|
||||
subvolume: /nix
|
||||
|
||||
# Mount options by filesystem type
|
||||
# nixos-generate-config picks these up for hardware-configuration.nix
|
||||
mountOptions:
|
||||
- filesystem: efi
|
||||
options: [ fmask=0077, dmask=0077 ]
|
||||
- filesystem: btrfs
|
||||
options: [ compress=zstd, noatime ]
|
||||
|
||||
@@ -12,11 +12,29 @@ userSwapChoices:
|
||||
|
||||
luksGeneration: luks2
|
||||
|
||||
defaultFileSystemType: "ext4"
|
||||
|
||||
availableFileSystemTypes:
|
||||
- ext4
|
||||
- btrfs
|
||||
- xfs
|
||||
- f2fs
|
||||
|
||||
showNotEncryptedBootMessage: false
|
||||
|
||||
bios:
|
||||
mountPoint: "/boot"
|
||||
minimumSize: 512MiB
|
||||
recommendedSize: 1GiB
|
||||
label: "BOOT"
|
||||
|
||||
partitionLayout:
|
||||
- name: "root"
|
||||
- name: "boot"
|
||||
filesystem: "ext4"
|
||||
mountPoint: "/boot"
|
||||
size: 1GiB
|
||||
- name: "root"
|
||||
filesystem: "unknown"
|
||||
noEncrypt: false
|
||||
mountPoint: "/"
|
||||
size: 100%
|
||||
|
||||
@@ -45,6 +45,15 @@ cfgbootbios = """ # Bootloader.
|
||||
|
||||
"""
|
||||
|
||||
cfgbootbiosbtrfs = """ # Bootloader.
|
||||
boot.loader.grub.enable = true;
|
||||
boot.loader.grub.device = "@@bootdev@@";
|
||||
boot.loader.grub.useOSProber = true;
|
||||
# Use provided UUIDs instead of blkid probing (required for btrfs subvolumes)
|
||||
boot.loader.grub.fsIdentifier = "provided";
|
||||
|
||||
"""
|
||||
|
||||
cfgbootnone = """ # Disable bootloader.
|
||||
boot.loader.grub.enable = false;
|
||||
|
||||
@@ -360,6 +369,46 @@ def catenate(d, key, *values):
|
||||
d[key] = "".join(values)
|
||||
|
||||
|
||||
def fix_btrfs_subvolumes(hardware_config, partitions):
|
||||
"""
|
||||
Fix btrfs subvolume configuration in hardware-configuration.nix.
|
||||
|
||||
nixos-generate-config generates incorrect subvol options for btrfs
|
||||
by setting them to mount points instead of actual subvolume names.
|
||||
This function corrects the subvol options to match what Calamares configured.
|
||||
"""
|
||||
# Map of mount points to their correct btrfs subvolume names
|
||||
# These match what is configured in mount.conf btrfsSubvolumes
|
||||
# Root uses top-level (no subvolume) for GRUB compatibility
|
||||
subvol_map = {
|
||||
"/home": "home",
|
||||
"/nix": "nix",
|
||||
}
|
||||
|
||||
# Check if root is actually btrfs
|
||||
root_is_btrfs = False
|
||||
for part in partitions:
|
||||
if part.get("mountPoint") == "/" and part.get("fs") == "btrfs":
|
||||
root_is_btrfs = True
|
||||
break
|
||||
|
||||
if not root_is_btrfs:
|
||||
return hardware_config
|
||||
|
||||
libcalamares.utils.debug("Fixing btrfs subvolume configuration")
|
||||
|
||||
# Fix subvol options for each mount point
|
||||
# nixos-generate-config may generate "subvol=/" instead of "subvol=@"
|
||||
for mount_point, correct_subvol in subvol_map.items():
|
||||
# Match any "subvol=<something>" and replace with correct subvolume
|
||||
# This handles cases like "subvol=/" or "subvol=/home"
|
||||
pattern = r'(fileSystems\."{}"[^;]*"subvol=)[^"]*"'.format(re.escape(mount_point))
|
||||
replacement = r'\g<1>{}"'.format(correct_subvol)
|
||||
hardware_config = re.sub(pattern, replacement, hardware_config, flags=re.DOTALL)
|
||||
|
||||
return hardware_config
|
||||
|
||||
|
||||
def run():
|
||||
"""NixOS Configuration."""
|
||||
|
||||
@@ -388,11 +437,22 @@ def run():
|
||||
|
||||
# Pick config parts and prepare substitution
|
||||
|
||||
# Check if root filesystem is btrfs
|
||||
root_is_btrfs = False
|
||||
for part in gs.value("partitions"):
|
||||
if part.get("mountPoint") == "/" and part.get("fs") == "btrfs":
|
||||
root_is_btrfs = True
|
||||
break
|
||||
|
||||
# Check bootloader
|
||||
if fw_type == "efi":
|
||||
cfg += cfgbootefi
|
||||
elif bootdev != "nodev":
|
||||
cfg += cfgbootbios
|
||||
# Use btrfs-specific config to avoid blkid issues with subvolumes
|
||||
if root_is_btrfs:
|
||||
cfg += cfgbootbiosbtrfs
|
||||
else:
|
||||
cfg += cfgbootbios
|
||||
catenate(variables, "bootdev", bootdev)
|
||||
else:
|
||||
cfg += cfgbootnone
|
||||
@@ -734,9 +794,20 @@ def run():
|
||||
libcalamares.utils.error(e.output.decode("utf8"))
|
||||
return (_("nixos-generate-config failed"), _(e.output.decode("utf8")))
|
||||
|
||||
# Check for unfree stuff in hardware-configuration.nix
|
||||
# Read and fix hardware-configuration.nix
|
||||
hf = open(root_mount_point + "/etc/nixos/hardware-configuration.nix", "r")
|
||||
htxt = hf.read()
|
||||
hf.close()
|
||||
|
||||
hardware_modified = False
|
||||
|
||||
# Fix btrfs subvolume configuration if needed
|
||||
htxt_fixed = fix_btrfs_subvolumes(htxt, gs.value("partitions"))
|
||||
if htxt_fixed != htxt:
|
||||
htxt = htxt_fixed
|
||||
hardware_modified = True
|
||||
|
||||
# Check for unfree stuff in hardware-configuration.nix
|
||||
search = re.search(r"boot\.extraModulePackages = \[ (.*) \];", htxt)
|
||||
|
||||
# Check if any extraModulePackages are defined, and remove if only free packages are allowed
|
||||
@@ -765,14 +836,17 @@ def run():
|
||||
)
|
||||
)
|
||||
expkgs.remove(pkg)
|
||||
hardwareout = re.sub(
|
||||
htxt = re.sub(
|
||||
r"boot\.extraModulePackages = \[ (.*) \];",
|
||||
"boot.extraModulePackages = [ {}];".format(
|
||||
"".join(map(lambda x: x + " ", expkgs))
|
||||
),
|
||||
htxt,
|
||||
)
|
||||
# Write the hardware-configuration.nix file
|
||||
hardware_modified = True
|
||||
|
||||
# Write the hardware-configuration.nix file if modified
|
||||
if hardware_modified:
|
||||
libcalamares.utils.host_env_process_output(
|
||||
[
|
||||
"cp",
|
||||
@@ -780,7 +854,7 @@ def run():
|
||||
root_mount_point + "/etc/nixos/hardware-configuration.nix",
|
||||
],
|
||||
None,
|
||||
hardwareout,
|
||||
htxt,
|
||||
)
|
||||
|
||||
# Write the configuration.nix file
|
||||
@@ -789,6 +863,14 @@ def run():
|
||||
status = _("Installing NixOS")
|
||||
libcalamares.job.setprogress(0.3)
|
||||
|
||||
try:
|
||||
subprocess.check_output(
|
||||
["pkexec", "chmod", "755", root_mount_point],
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
libcalamares.utils.warning("Failed to set permissions on {}: {}".format(root_mount_point, e.output))
|
||||
|
||||
# build nixos-install command
|
||||
nixosInstallCmd = [ "pkexec" ]
|
||||
nixosInstallCmd.extend(generateProxyStrings())
|
||||
|
||||
Reference in New Issue
Block a user