Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions install/config/boot-permissions-fix.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash

# Fix /boot permissions security issue
# The random seed file and /boot mount should not be world accessible
# See: https://github.com/basecamp/omarchy/issues/5377

echo "Fixing /boot permissions for better security..."
Comment on lines +1 to +7
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This installer script is not referenced by the install pipeline (it is not called from install/config/all.sh, and no other scripts source/execute it), so it won’t actually run during installation.

Copilot uses AI. Check for mistakes.

# Fix /boot directory permissions (should be 700)
sudo chmod 700 /boot 2>/dev/null || echo "Could not change /boot permissions"

# Fix random-seed file permissions if it exists
if [[ -f /boot/loader/random-seed ]]; then
sudo chmod 600 /boot/loader/random-seed 2>/dev/null || echo "Could not change random-seed permissions"
fi

# Ensure /boot is mounted with proper permissions
# Add to fstab if not already present with correct options
if ! grep -q "^/boot" /etc/fstab 2>/dev/null; then
Comment on lines +18 to +19
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fstab check is incorrect: /etc/fstab lines typically start with the device/spec, not the mountpoint, so grep -q "^/boot" will usually miss an existing /boot entry and print a false warning. Also, the comment says “Add to fstab…” but the code only warns and doesn’t add anything.

Suggested change
# Add to fstab if not already present with correct options
if ! grep -q "^/boot" /etc/fstab 2>/dev/null; then
# Warn if /boot is not present in /etc/fstab; this script does not modify fstab
if ! awk '!/^[[:space:]]*#/ && NF >= 2 && $2 == "/boot" { found=1; exit } END { exit !found }' /etc/fstab 2>/dev/null; then

Copilot uses AI. Check for mistakes.
echo "Warning: /boot is not in fstab, permissions may not persist"
fi

# Disable bootctl random seed generation warnings by setting correct permissions
if command -v bootctl &>/dev/null; then
# Run bootctl with proper environment to set correct permissions
sudo bootctl random-seed 2>/dev/null || true
fi

echo "Boot permissions fix complete!"
32 changes: 32 additions & 0 deletions install/config/snapper-home-config.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/bash

# Fix snapper /home config creation for chroot installations
# See: https://github.com/basecamp/omarchy/issues/5344

echo "Ensuring snapper /home config is created..."
Comment on lines +1 to +6
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This installer script is not referenced by the install pipeline (e.g., it is not called from install/config/all.sh, and no other scripts source/execute it), so it won’t run during installation and won’t fix chroot installs as described.

Copilot uses AI. Check for mistakes.

# Check if /home is on a separate subvolume or btrfs
if mountpoint -q /home 2>/dev/null; then
# /home is a separate mount point
if ! sudo snapper list-configs 2>/dev/null | grep -q "home"; then
echo "Creating snapper config for /home..."
sudo snapper -c home create-config /home 2>/dev/null || echo "Warning: Could not create /home snapper config"
fi
elif [[ -d /home/.snapshots ]]; then
# /home has .snapshots subdirectory, ensure config exists
if ! sudo snapper list-configs 2>/dev/null | grep -q "home"; then
echo "Creating snapper config for /home subvolume..."
sudo snapper -c home create-config /home 2>/dev/null || echo "Warning: Could not create /home snapper config"
fi
else
echo "/home is not on a separate subvolume, skipping /home snapper config"
Comment on lines +8 to +22
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The /home detection logic here is likely to miss the chroot case: in chroot installs /home may not be a separate mountpoint yet, and /home/.snapshots won’t exist until after create-config succeeds. Consider detecting whether /home is on btrfs (and preferably a btrfs subvolume) via findmnt/stat/btrfs subvolume show rather than mountpoint/.snapshots existence.

Suggested change
# Check if /home is on a separate subvolume or btrfs
if mountpoint -q /home 2>/dev/null; then
# /home is a separate mount point
if ! sudo snapper list-configs 2>/dev/null | grep -q "home"; then
echo "Creating snapper config for /home..."
sudo snapper -c home create-config /home 2>/dev/null || echo "Warning: Could not create /home snapper config"
fi
elif [[ -d /home/.snapshots ]]; then
# /home has .snapshots subdirectory, ensure config exists
if ! sudo snapper list-configs 2>/dev/null | grep -q "home"; then
echo "Creating snapper config for /home subvolume..."
sudo snapper -c home create-config /home 2>/dev/null || echo "Warning: Could not create /home snapper config"
fi
else
echo "/home is not on a separate subvolume, skipping /home snapper config"
home_uses_btrfs_subvolume() {
local home_fstype
local home_mount_root
home_fstype="$(findmnt -n -o FSTYPE --target /home 2>/dev/null || true)"
[[ "$home_fstype" == "btrfs" ]] || return 1
# Prefer detecting an actual btrfs subvolume so chroot installs work
# even when /home is not mounted separately yet.
if btrfs subvolume show /home >/dev/null 2>&1; then
return 0
fi
# Fall back to checking whether /home is the root of its own mount.
home_mount_root="$(stat -c %m /home 2>/dev/null || true)"
[[ "$home_mount_root" == "/home" ]]
}
# Check if /home is backed by btrfs and is either a subvolume or a separate mount.
if home_uses_btrfs_subvolume; then
if ! sudo snapper list-configs 2>/dev/null | grep -q "home"; then
echo "Creating snapper config for /home..."
sudo snapper -c home create-config /home 2>/dev/null || echo "Warning: Could not create /home snapper config"
fi
else
echo "/home is not on a separate btrfs subvolume, skipping /home snapper config"

Copilot uses AI. Check for mistakes.
fi

# Also ensure root snapper config exists
if ! sudo snapper list-configs 2>/dev/null | grep -q "root"; then
echo "Creating snapper config for root..."
sudo snapper -c root create-config / 2>/dev/null || echo "Warning: Could not create root snapper config"
sudo cp $OMARCHY_PATH/default/snapper/root /etc/snapper/configs/root 2>/dev/null || true
fi

echo "Snapper config check complete!"
Comment on lines +25 to +32
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script calls snapper unconditionally. Other parts of the repo guard snapper usage with a command presence check; without that, a missing snapper binary will cause this to silently do nothing (stderr is redirected) and still print a successful completion message.

Copilot uses AI. Check for mistakes.
25 changes: 25 additions & 0 deletions migrations/1777007500.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

# Fix /boot permissions security issue
# See: https://github.com/basecamp/omarchy/issues/5377

echo "Fixing /boot permissions for better security..."
Comment on lines +1 to +6
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description lists only the snapper /home fix files, but this PR also adds a /boot permissions fix (migrations/1777007500.sh and install/config/boot-permissions-fix.sh). Please update the PR description to reflect the additional scope or split into a separate PR.

Copilot uses AI. Check for mistakes.

# Fix /boot directory permissions (should be 700 for security)
sudo chmod 700 /boot 2>/dev/null || echo "Could not change /boot permissions"

# Fix random-seed file permissions if it exists
if [[ -f /boot/loader/random-seed ]]; then
sudo chmod 600 /boot/loader/random-seed 2>/dev/null || echo "Could not change random-seed permissions"
fi

# Verify the fix
if [[ $(stat -c %a /boot 2>/dev/null) == "700" ]]; then
echo "✓ /boot permissions fixed to 700"
fi

if [[ -f /boot/loader/random-seed ]] && [[ $(stat -c %a /boot/loader/random-seed 2>/dev/null) == "600" ]]; then
echo "✓ random-seed permissions fixed to 600"
fi

notify-send "Boot permissions fixed" "Security improvement applied to /boot"
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using notify-send in a migration is likely to fail in non-graphical contexts (e.g., running updates from TTY/SSH or without a notification daemon). This can add noisy errors or cause confusion; consider removing it or gating it behind a DISPLAY/DBUS session check and ignoring failures.

Suggested change
notify-send "Boot permissions fixed" "Security improvement applied to /boot"
if command -v notify-send >/dev/null 2>&1 && [[ -n "${DISPLAY:-}" || -n "${DBUS_SESSION_BUS_ADDRESS:-}" ]]; then
notify-send "Boot permissions fixed" "Security improvement applied to /boot" >/dev/null 2>&1 || true
fi

Copilot uses AI. Check for mistakes.
46 changes: 46 additions & 0 deletions migrations/1777007501.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash

# Fix snapper /home config for chroot installations
# See: https://github.com/basecamp/omarchy/issues/5344

echo "Fixing snapper /home config..."

# Get absolute path for omarchy
OMARCHY_PATH="${OMARCHY_PATH:-$HOME/.local/share/omarchy}"

# Check if /home is on btrfs and has .snapshots
if [[ -d /home/.snapshots ]] || mountpoint -q /home 2>/dev/null; then
Comment on lines +11 to +12
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The /home gating condition here (mountpoint or existing /home/.snapshots dir) can still skip the chroot scenario where /home is a btrfs subvolume but not mounted separately and has no .snapshots yet. This means the migration may not create the config even when it should.

Suggested change
# Check if /home is on btrfs and has .snapshots
if [[ -d /home/.snapshots ]] || mountpoint -q /home 2>/dev/null; then
home_has_snapper_target() {
[[ -d /home/.snapshots ]] && return 0
mountpoint -q /home 2>/dev/null && return 0
if command -v btrfs >/dev/null 2>&1; then
btrfs subvolume show /home >/dev/null 2>&1 && return 0
fi
return 1
}
# Check if /home is already initialized for snapper or is a btrfs subvolume
if home_has_snapper_target; then

Copilot uses AI. Check for mistakes.
# Check if /home snapper config exists (use anchored match)
if ! sudo snapper list-configs 2>/dev/null | grep -q "^home"; then
echo "Creating snapper config for /home..."
sudo snapper -c home create-config /home 2>/dev/null || echo "Warning: Could not create /home snapper config"

# Copy and modify config from root if available
if [[ -f /etc/snapper/configs/root ]]; then
sudo cp /etc/snapper/configs/root /etc/snapper/configs/home 2>/dev/null || true
sudo sed -i 's|SUBVOLUME="/"|SUBVOLUME="/home"|' /etc/snapper/configs/home 2>/dev/null || true
sudo sed -i 's|TIMELINE_CREATE="yes"|TIMELINE_CREATE="no"|' /etc/snapper/configs/home 2>/dev/null || true
elif [[ -f "$OMARCHY_PATH/default/snapper/root" ]]; then
sudo cp "$OMARCHY_PATH/default/snapper/root" /etc/snapper/configs/home 2>/dev/null || true
sudo sed -i 's|SUBVOLUME="/"|SUBVOLUME="/home"|' /etc/snapper/configs/home 2>/dev/null || true
sudo sed -i 's|TIMELINE_CREATE="yes"|TIMELINE_CREATE="no"|' /etc/snapper/configs/home 2>/dev/null || true
fi

echo "✓ Created snapper /home config"
Comment on lines +16 to +29
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script prints "✓ Created snapper /home config" unconditionally, even if snapper -c home create-config fails (it only echoes a warning but doesn’t change control flow). This can mislead users and hides the fact that the fix didn’t apply.

Suggested change
sudo snapper -c home create-config /home 2>/dev/null || echo "Warning: Could not create /home snapper config"
# Copy default config
if [[ -f /etc/snapper/configs/root ]]; then
sudo cp /etc/snapper/configs/root /etc/snapper/configs/home 2>/dev/null || true
# Modify for /home - don't create timeline snapshots
sudo sed -i 's|SUBVOLUME="/"|SUBVOLUME="/home"|' /etc/snapper/configs/home 2>/dev/null || true
sudo sed -i 's|TIMELINE_CREATE="yes"|TIMELINE_CREATE="no"|' /etc/snapper/configs/home 2>/dev/null || true
fi
echo "✓ Created snapper /home config"
if sudo snapper -c home create-config /home 2>/dev/null; then
# Copy default config
if [[ -f /etc/snapper/configs/root ]]; then
sudo cp /etc/snapper/configs/root /etc/snapper/configs/home 2>/dev/null || true
# Modify for /home - don't create timeline snapshots
sudo sed -i 's|SUBVOLUME="/"|SUBVOLUME="/home"|' /etc/snapper/configs/home 2>/dev/null || true
sudo sed -i 's|TIMELINE_CREATE="yes"|TIMELINE_CREATE="no"|' /etc/snapper/configs/home 2>/dev/null || true
fi
echo "✓ Created snapper /home config"
else
echo "Warning: Could not create /home snapper config"
fi

Copilot uses AI. Check for mistakes.
else
echo "Snapper /home config already exists"
fi
else
echo "/home is not on btrfs or separate subvolume, skipping"
fi

Comment on lines +3 to +36
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces (or re-introduces) a /home snapper config, but the current codebase explicitly avoids /home snapshots (install/login/limine-snapper.sh comment) and migration 1776927490 removes the home config and .snapshots subvolume. Because migrations run in filename order, this new migration would effectively undo 1776927490 on the next update.

Suggested change
# Fix snapper /home config for chroot installations
# See: https://github.com/basecamp/omarchy/issues/5344
echo "Fixing snapper /home config..."
# Check if /home is on btrfs and has .snapshots
if [[ -d /home/.snapshots ]] || mountpoint -q /home 2>/dev/null; then
# Check if /home snapper config exists
if ! sudo snapper list-configs 2>/dev/null | grep -q "^home"; then
echo "Creating snapper config for /home..."
sudo snapper -c home create-config /home 2>/dev/null || echo "Warning: Could not create /home snapper config"
# Copy default config
if [[ -f /etc/snapper/configs/root ]]; then
sudo cp /etc/snapper/configs/root /etc/snapper/configs/home 2>/dev/null || true
# Modify for /home - don't create timeline snapshots
sudo sed -i 's|SUBVOLUME="/"|SUBVOLUME="/home"|' /etc/snapper/configs/home 2>/dev/null || true
sudo sed -i 's|TIMELINE_CREATE="yes"|TIMELINE_CREATE="no"|' /etc/snapper/configs/home 2>/dev/null || true
fi
echo "✓ Created snapper /home config"
else
echo "Snapper /home config already exists"
fi
else
echo "/home is not on btrfs or separate subvolume, skipping"
fi
# Ensure snapper root config exists for chroot installations
# See: https://github.com/basecamp/omarchy/issues/5344
echo "Fixing snapper root config..."

Copilot uses AI. Check for mistakes.
# Ensure root config exists (anchored match)
if ! sudo snapper list-configs 2>/dev/null | grep -q "^root"; then
echo "Creating snapper config for root..."
sudo snapper -c root create-config / 2>/dev/null || true
if [[ -f "$OMARCHY_PATH/default/snapper/root" ]]; then
sudo cp "$OMARCHY_PATH/default/snapper/root" /etc/snapper/configs/root 2>/dev/null || true
fi
fi

echo "Snapper config fix complete!"