diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index aace491..6895eb0 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -74,7 +74,7 @@ jobs: with: persist-credentials: false - - name: Check REUSE compliance + - name: Run ShellCheck shell: bash run: | find . -type f -name '*.sh' -execdir shellcheck '{}' + diff --git a/README.md b/README.md index 60a9c94..bf607ee 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,14 @@ after installation (such as setting up the Homebrew cache and running If Homebrew has not already been set up on the user's system, a systemd-tmpfiles configuration copies this installation to `/home/linuxbrew` and transfers -ownership of it to UID 1000. The package also sets up systemd services to -automatically update Homebrew, as well as shell completions for the bash and -fish shells. +ownership of it to the `linuxbrew` user. The package also sets up systemd +services to automatically update Homebrew, as well as shell completions for the +bash and fish shells. + +To make it more convenient for authorized users to manage the Homebrew +installation, the `brew-proxy` package can be installed. This includes a +DBus-activated service that allows authorized users to execute `brew` commands +as the `linuxbrew` user via the `brew-proxy` command. ## Credit diff --git a/etc/profile.d/brew.sh b/etc/profile.d/brew.sh index 19788bb..102481c 100644 --- a/etc/profile.d/brew.sh +++ b/etc/profile.d/brew.sh @@ -1,10 +1,22 @@ -#!/usr/bin/env bash +#!/bin/sh # SPDX-FileCopyrightText: Copyright 2025 Universal Blue # SPDX-FileCopyrightText: Copyright 2025 The BlueBuild Authors +# SPDX-FileCopyrightText: Copyright 2026 Daniel Hast # # SPDX-License-Identifier: Apache-2.0 -if [[ -d /home/linuxbrew/.linuxbrew && $- == *i* && "$(/usr/bin/id -u)" != 0 ]]; then - eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" +if [ -x /home/linuxbrew/.linuxbrew/bin/brew ] && [ "$(/usr/bin/id -u)" != 0 ]; then + case "$-" in + *i*) + # Begin output of `brew shellenv bash` (lightly edited for formatting) + export HOMEBREW_PREFIX='/home/linuxbrew/.linuxbrew' + export HOMEBREW_CELLAR='/home/linuxbrew/.linuxbrew/Cellar' + export HOMEBREW_REPOSITORY='/home/linuxbrew/.linuxbrew/Homebrew' + export PATH="/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin${PATH+:$PATH}"; + [ -z "${MANPATH-}" ] || export MANPATH=":${MANPATH#:}" + export INFOPATH="/home/linuxbrew/.linuxbrew/share/info:${INFOPATH:-}" + # End output of `brew shellenv bash` + ;; + esac fi diff --git a/homebrew-template.spec b/homebrew-template.spec index 027e1e0..2144941 100644 --- a/homebrew-template.spec +++ b/homebrew-template.spec @@ -34,6 +34,7 @@ Requires: gcc Requires: git-core >= 2.7.0 Requires: zstd %{?systemd_requires} +Recommends: brew-proxy # Filter out unwanted automatic dependencies. For documentation, see: # https://docs.fedoraproject.org/en-US/packaging-guidelines/AutoProvidesAndRequiresFiltering/ @@ -52,6 +53,7 @@ patch -p0 < homebrew-install.patch mkdir .linuxbrew env -i HOME=/home/linuxbrew PATH=/usr/bin:/bin:/usr/sbin:/sbin NONINTERACTIVE=1 \ HOMEBREW_BREW_LOCAL_GIT_REMOTE="${PWD}/brew.git" /bin/bash ./homebrew-install.sh +chmod -R u=rwX,go=rX .linuxbrew %install # main brew installation @@ -62,46 +64,53 @@ cp -a .linuxbrew %{buildroot}%{_datadir}/homebrew install -Dp -m 644 -t %{buildroot}%{_sysconfdir}/homebrew etc/homebrew/brew.env # systemd units for automatic brew updates -install -Dp -m 644 -t %{buildroot}%{_userunitdir} usr/lib/systemd/user/* +install -Dp -m 644 -t %{buildroot}%{_unitdir} usr/lib/systemd/system/* # brew shell environment and completions install -Dp -m 644 -t %{buildroot}%{_sysconfdir}/profile.d etc/profile.d/brew*.sh install -Dp -m 644 -t %{buildroot}%{_datadir}/fish/vendor_conf.d usr/share/fish/vendor_conf.d/brew-fish-completions.fish +# systemd-sysusers +install -Dp -m 644 -t %{buildroot}%{_sysusersdir} usr/lib/sysusers.d/homebrew.conf + # systemd-tmpfiles install -Dp -m 644 -t %{buildroot}%{_tmpfilesdir} usr/lib/tmpfiles.d/homebrew.conf %post -%systemd_user_post brew-update.service -%systemd_user_post brew-update.timer -%systemd_user_post brew-upgrade.service -%systemd_user_post brew-upgrade.timer +%systemd_post brew-update.service +%systemd_post brew-update.timer +%systemd_post brew-upgrade.service +%systemd_post brew-upgrade.timer %preun -%systemd_user_preun brew-update.service -%systemd_user_preun brew-update.timer -%systemd_user_preun brew-upgrade.service -%systemd_user_preun brew-upgrade.timer +%systemd_preun brew-update.service +%systemd_preun brew-update.timer +%systemd_preun brew-upgrade.service +%systemd_preun brew-upgrade.timer %postun -%systemd_user_postun_with_reload brew-update.service -%systemd_user_postun_with_restart brew-update.timer -%systemd_user_postun_with_reload brew-upgrade.service -%systemd_user_postun_with_restart brew-upgrade.timer +%systemd_postun_with_reload brew-update.service +%systemd_postun_with_restart brew-update.timer +%systemd_postun_with_reload brew-upgrade.service +%systemd_postun_with_restart brew-upgrade.timer %files +%doc README.md %{_datadir}/homebrew -%{_userunitdir}/brew-update.service -%{_userunitdir}/brew-update.timer -%{_userunitdir}/brew-upgrade.service -%{_userunitdir}/brew-upgrade.timer +%{_unitdir}/brew-update.service +%{_unitdir}/brew-update.timer +%{_unitdir}/brew-upgrade.service +%{_unitdir}/brew-upgrade.timer %{_datadir}/fish/vendor_conf.d/brew-fish-completions.fish +%{_sysusersdir}/homebrew.conf %{_tmpfilesdir}/homebrew.conf %config(noreplace) %{_sysconfdir}/homebrew %config(noreplace) %{_sysconfdir}/profile.d/brew.sh %config(noreplace) %{_sysconfdir}/profile.d/brew-bash-completions.sh %changelog +* Mon Apr 06 2026 Daniel Hast + - Switch to linuxbrew-owned installation * Fri Feb 27 2026 Daniel Hast - Use tmpfiles.d in place of brew-setup.service * Mon Feb 23 2026 Daniel Hast diff --git a/usr/lib/systemd/user/brew-update.service b/usr/lib/systemd/system/brew-update.service similarity index 53% rename from usr/lib/systemd/user/brew-update.service rename to usr/lib/systemd/system/brew-update.service index cb7a2b6..19e6539 100644 --- a/usr/lib/systemd/user/brew-update.service +++ b/usr/lib/systemd/system/brew-update.service @@ -6,11 +6,16 @@ [Unit] Description=Auto-update Brew binary -After=default.target -ConditionUser=1000 -ConditionFileIsExecutable=/home/linuxbrew/.linuxbrew/bin/brew +After=multi-user.target +ConditionFileIsExecutable=|/home/linuxbrew/.linuxbrew/bin/brew +# If the path is a symbolic link, the above check has to follow the link, which +# fails on some systems due to SELinux not allowing the system service manager +# to read file contents in home directories. So we add a second triggering +# condition making the unit start if the path is a symbolic link. +ConditionPathIsSymbolicLink=|/home/linuxbrew/.linuxbrew/bin/brew [Service] +User=linuxbrew Type=oneshot Environment=HOMEBREW_CELLAR=/home/linuxbrew/.linuxbrew/Cellar Environment=HOMEBREW_PREFIX=/home/linuxbrew/.linuxbrew diff --git a/usr/lib/systemd/user/brew-update.timer b/usr/lib/systemd/system/brew-update.timer similarity index 95% rename from usr/lib/systemd/user/brew-update.timer rename to usr/lib/systemd/system/brew-update.timer index cd6c09a..e216a63 100644 --- a/usr/lib/systemd/user/brew-update.timer +++ b/usr/lib/systemd/system/brew-update.timer @@ -7,7 +7,6 @@ [Unit] Description=Timer for updating Brew binary Wants=timers.target -ConditionUser=1000 [Timer] OnStartupSec=10min diff --git a/usr/lib/systemd/user/brew-upgrade.service b/usr/lib/systemd/system/brew-upgrade.service similarity index 66% rename from usr/lib/systemd/user/brew-upgrade.service rename to usr/lib/systemd/system/brew-upgrade.service index 47b19bd..9484462 100644 --- a/usr/lib/systemd/user/brew-upgrade.service +++ b/usr/lib/systemd/system/brew-upgrade.service @@ -6,11 +6,16 @@ [Unit] Description=Auto-upgrade Brew packages -After=default.target -ConditionUser=1000 -ConditionFileIsExecutable=/home/linuxbrew/.linuxbrew/bin/brew +After=multi-user.target +ConditionFileIsExecutable=|/home/linuxbrew/.linuxbrew/bin/brew +# If the path is a symbolic link, the above check has to follow the link, which +# fails on some systems due to SELinux not allowing the system service manager +# to read file contents in home directories. So we add a second triggering +# condition making the unit start if the path is a symbolic link. +ConditionPathIsSymbolicLink=|/home/linuxbrew/.linuxbrew/bin/brew [Service] +User=linuxbrew Type=oneshot Environment=HOMEBREW_CELLAR=/home/linuxbrew/.linuxbrew/Cellar Environment=HOMEBREW_PREFIX=/home/linuxbrew/.linuxbrew diff --git a/usr/lib/systemd/user/brew-upgrade.timer b/usr/lib/systemd/system/brew-upgrade.timer similarity index 95% rename from usr/lib/systemd/user/brew-upgrade.timer rename to usr/lib/systemd/system/brew-upgrade.timer index 9a0c453..848c77c 100644 --- a/usr/lib/systemd/user/brew-upgrade.timer +++ b/usr/lib/systemd/system/brew-upgrade.timer @@ -7,7 +7,6 @@ [Unit] Description=Timer for upgrading Brew packages Wants=timers.target -ConditionUser=1000 [Timer] OnStartupSec=30min diff --git a/usr/lib/sysusers.d/homebrew.conf b/usr/lib/sysusers.d/homebrew.conf new file mode 100644 index 0000000..ac4964e --- /dev/null +++ b/usr/lib/sysusers.d/homebrew.conf @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: Copyright 2026 Daniel Hast +# +# SPDX-License-Identifier: Apache-2.0 OR MIT + +u! linuxbrew - "Homebrew administrator,,,,umask=0022" /home/linuxbrew diff --git a/usr/lib/tmpfiles.d/homebrew.conf b/usr/lib/tmpfiles.d/homebrew.conf index 9f7b95b..e52129e 100644 --- a/usr/lib/tmpfiles.d/homebrew.conf +++ b/usr/lib/tmpfiles.d/homebrew.conf @@ -2,6 +2,6 @@ # # SPDX-License-Identifier: Apache-2.0 OR MIT -d /home/linuxbrew 0755 1000 1000 - - -C /home/linuxbrew/.linuxbrew - 1000 1000 - /usr/share/homebrew/.linuxbrew -d /var/tmp/homebrew 0700 1000 1000 3d - +d /home/linuxbrew 0755 linuxbrew linuxbrew - +C /home/linuxbrew/.linuxbrew - linuxbrew linuxbrew - /usr/share/homebrew/.linuxbrew +d /var/tmp/homebrew 0700 linuxbrew linuxbrew 3d diff --git a/usr/share/fish/vendor_conf.d/brew-fish-completions.fish b/usr/share/fish/vendor_conf.d/brew-fish-completions.fish index 120c4fd..65795cf 100644 --- a/usr/share/fish/vendor_conf.d/brew-fish-completions.fish +++ b/usr/share/fish/vendor_conf.d/brew-fish-completions.fish @@ -2,18 +2,31 @@ # SPDX-FileCopyrightText: Copyright 2025 Universal Blue # SPDX-FileCopyrightText: Copyright 2025 The BlueBuild Authors +# SPDX-FishCopyrightText: Copyright 2026 Daniel Hast # # SPDX-License-Identifier: Apache-2.0 #shellcheck disable=all -if status --is-interactive; and test $(/usr/bin/id -u) -ne 0 - if [ -d /home/linuxbrew/.linuxbrew ] - /home/linuxbrew/.linuxbrew/bin/brew shellenv fish | source - if test -d (brew --prefix)/share/fish/completions - set -p fish_complete_path (brew --prefix)/share/fish/completions +if status --is-interactive && not fish_is_root_user + if test -d '/home/linuxbrew/.linuxbrew' + # Begin output of `brew shellenv fish` (lightly edited for formatting) + set --global --export HOMEBREW_PREFIX '/home/linuxbrew/.linuxbrew' + set --global --export HOMEBREW_CELLAR '/home/linuxbrew/.linuxbrew/Cellar' + set --global --export HOMEBREW_REPOSITORY '/home/linuxbrew/.linuxbrew/Homebrew' + fish_add_path --global --move --path '/home/linuxbrew/.linuxbrew/bin' '/home/linuxbrew/.linuxbrew/sbin' + if test -n "$MANPATH[1]" + set --global --export MANPATH '' $MANPATH end - if test -d (brew --prefix)/share/fish/vendor_completions.d - set -p fish_complete_path (brew --prefix)/share/fish/vendor_completions.d + if not contains '/home/linuxbrew/.linuxbrew/share/info' $INFOPATH + set --global --export INFOPATH '/home/linuxbrew/.linuxbrew/share/info' $INFOPATH + end + # End output of `brew shellenv fish` + + if test -d '/home/linuxbrew/.linuxbrew/share/fish/completions' + set -p fish_complete_path '/home/linuxbrew/.linuxbrew/share/fish/completions' + end + if test -d '/home/linuxbrew/.linuxbrew/share/fish/vendor_completions.d' + set -p fish_complete_path '/home/linuxbrew/.linuxbrew/share/fish/vendor_completions.d' end end end