diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index aace491..351d2e0 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -21,12 +21,6 @@ jobs: name: REUSE spec compliance runs-on: ubuntu-slim steps: - - name: Install dependencies - shell: bash - run: | - sudo apt update - sudo apt install reuse - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -34,7 +28,7 @@ jobs: - name: Check REUSE compliance shell: bash run: | - reuse lint + pipx run reuse lint rpmlint: name: Lint RPM spec diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a0d8718 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: NONE +# +# SPDX-License-Identifier: CC0-1.0 + +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c0bbf39 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,252 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "brew-sandbox" +version = "0.1.0" +dependencies = [ + "anyhow", + "landlock", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "landlock" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49fefd6652c57d68aaa32544a4c0e642929725bdc1fd929367cdeb673ab81088" +dependencies = [ + "enumflags2", + "libc", + "thiserror", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.180" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "syn" +version = "2.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..94e3adf --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: Copyright 2026 Daniel Hast +# +# SPDX-License-Identifier: Apache-2.0 OR MIT + +[workspace] +resolver = "3" +members = ["brew-sandbox"] diff --git a/README.md b/README.md index 6f300eb..b705846 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ # Homebrew + [![homebrew](https://img.shields.io/badge/dynamic/json?color=blue&label=homebrew&query=builds.latest.source_package.version&url=https%3A%2F%2Fcopr.fedorainfracloud.org%2Fapi_3%2Fpackage%3Fownername%3Dsecureblue%26projectname%3Dpackages%26packagename%3Dhomebrew%26with_latest_build%3DTrue)](https://copr.fedorainfracloud.org/coprs/secureblue/packages/package/homebrew/) This repository packages [Homebrew](https://brew.sh/) for Linux as an RPM @@ -20,10 +21,32 @@ then 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. +## Sandbox + +This repository also contains a `homebrew-sandbox` package that provides +sandboxing for the brew command using the [Landlock LSM](https://landlock.io/). +It works by wrapping the brew command in a simple Rust program that sets up the +Landlock sandbox and then passes its arguments on to brew. + +Note that only brew itself is sandboxed, not programs intalled using brew. + +The sandbox allows brew the follow access: + +- Read-write access to `/home/linuxbrew/.linuxbrew`, `/home/linuxbrew/.cache`, + `/var/tmp/homebrew`, and a limited subset of `/dev`; +- Read-only access to `/usr`, `/etc`, `/home/linuxbrew`, and `/proc/cpuinfo`; +- Network access to port 443 only. + +This sandbox can be disabled by setting `_HOMEBREW_SANDBOX=0`, either as an +environment variable or in `/etc/homebrew/brew-sandbox.env`. + +(You can also set the environment variable `_HOMEBREW_SANDBOX_DEBUG` to have the +wrapper program print debug info showing whether the sandbox is active.) + ## Credit -Various files, including the systemd unit files and shell completion scripts, -are adapted from +Various files, including some of the systemd unit files and shell completion +scripts, are adapted from [Universal Blue's Homebrew packaging](https://github.com/ublue-os/brew) and [BlueBuild's brew module](https://github.com/blue-build/modules/tree/main/modules/brew) and are redistributed under the terms of the Apache-2.0 license. diff --git a/REUSE.toml b/REUSE.toml new file mode 100644 index 0000000..ffcb98f --- /dev/null +++ b/REUSE.toml @@ -0,0 +1,6 @@ +version = 1 + +[[annotations]] +path = "Cargo.lock" +SPDX-FileCopyrightText = "NONE" +SPDX-License-Identifier = "CC0-1.0" diff --git a/brew-sandbox/Cargo.toml b/brew-sandbox/Cargo.toml new file mode 100644 index 0000000..68d01e7 --- /dev/null +++ b/brew-sandbox/Cargo.toml @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: Copyright 2026 Daniel Hast +# +# SPDX-License-Identifier: Apache-2.0 OR MIT + +[package] +name = "brew-sandbox" +version = "0.1.0" +edition = "2024" +authors = ["Daniel Hast"] +license = "Apache-2.0 OR MIT" + +[dependencies] +anyhow = "1.0.100" +landlock = "0.4.4" +tracing = "0.1.43" +tracing-subscriber = "0.3.20" diff --git a/brew-sandbox/src/bin/brew.rs b/brew-sandbox/src/bin/brew.rs new file mode 100644 index 0000000..96f8cec --- /dev/null +++ b/brew-sandbox/src/bin/brew.rs @@ -0,0 +1,146 @@ +// SPDX-FileCopyrightText: Copyright 2026 Daniel Hast +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + +use std::{ + fs::{File, create_dir_all}, + io::{BufRead, BufReader, ErrorKind}, + os::unix::{fs::symlink, process::CommandExt}, + path::PathBuf, + process::Command, + sync::LazyLock, +}; + +use anyhow::Result; +use landlock::{ + ABI, Access, AccessFs, AccessNet, NetPort, Ruleset, RulesetAttr, RulesetCreatedAttr, + RulesetStatus, path_beneath_rules, +}; +use tracing::{debug, level_filters::LevelFilter, warn}; + +const PORT_HTTPS: u16 = 443; + +const SANDBOX_ENV_VAR: &str = "_HOMEBREW_SANDBOX"; +const DEBUG_ENV_VAR: &str = "_HOMEBREW_SANDBOX_DEBUG"; + +static HOMEBREW_PREFIX: LazyLock = LazyLock::new(|| { + std::env::var_os("HOMEBREW_PREFIX") + .unwrap_or_else(|| "/home/linuxbrew/.linuxbrew".into()) + .into() +}); + +static HOMEBREW_CACHE: LazyLock = LazyLock::new(|| { + std::env::var_os("HOMEBREW_CACHE") + .unwrap_or_else(|| "/home/linuxbrew/.cache/Homebrew".into()) + .into() +}); + +fn brew_path() -> PathBuf { + HOMEBREW_PREFIX.join(".sandbox/brew-unsandboxed") +} + +fn make_brew_symlink() -> Result<()> { + create_dir_all(HOMEBREW_PREFIX.join(".sandbox"))?; + match symlink("../Homebrew/bin/brew", brew_path()) { + Ok(()) => Ok(()), + Err(err) if matches!(err.kind(), ErrorKind::AlreadyExists) => Ok(()), + Err(err) => Err(err.into()), + } +} + +fn restrict_self() -> Result<()> { + let abi = ABI::V6; + let access_all = AccessFs::from_all(abi); + let access_read = AccessFs::from_read(abi); + let status = Ruleset::default() + .handle_access(access_all)? + .handle_access(AccessNet::from_all(abi))? + .create()? + .add_rules(path_beneath_rules( + &["/etc", "/home/linuxbrew", "/proc/cpuinfo", "/usr"], + access_read, + ))? + .add_rules(path_beneath_rules( + &[ + "/dev/null", + "/dev/ptmx", + "/dev/pts", + "/dev/random", + "/dev/urandom", + "/dev/zero", + "/var/tmp/homebrew", + ], + access_all, + ))? + .add_rules(path_beneath_rules( + &[&**HOMEBREW_CACHE, &**HOMEBREW_PREFIX], + access_all, + ))? + .add_rule(NetPort::new(PORT_HTTPS, AccessNet::ConnectTcp))? + .restrict_self()?; + match status.ruleset { + RulesetStatus::FullyEnforced => debug!("Landlock sandboxing fully enforced."), + RulesetStatus::PartiallyEnforced => { + warn!("Landlock sandboxing only partially enforced.") + } + RulesetStatus::NotEnforced => warn!("Landlock sandboxing not enforced."), + } + Ok(()) +} + +fn should_sandbox() -> Result { + let env_var_test = + |value: &str| !value.is_empty() && value != "0" && value.to_lowercase() != "false"; + + if let Ok(sandbox_var) = std::env::var(SANDBOX_ENV_VAR) { + return Ok(env_var_test(&sandbox_var)); + } + + if let Ok(file) = File::open("/etc/homebrew/brew-sandbox.env") { + for line in BufReader::new(file).lines() { + if let Some((key, value)) = line?.split_once("=") + && key.trim() == SANDBOX_ENV_VAR + { + let value = value.trim(); + return Ok(env_var_test(value)); + } + } + } + + Ok(true) +} + +fn init_logging() { + let filter = if std::env::var_os(DEBUG_ENV_VAR).is_some() { + LevelFilter::DEBUG + } else { + LevelFilter::WARN + }; + tracing_subscriber::fmt() + .compact() + .with_max_level(filter) + .without_time() + .with_writer(std::io::stderr) + .init(); +} + +fn main() -> Result<()> { + // SAFETY: The program is single-threaded. + unsafe { + std::env::set_var("HOME", "/home/linuxbrew"); + std::env::set_var("XDG_CACHE_HOME", "/home/linuxbrew/.cache"); + } + init_logging(); + if should_sandbox()? { + restrict_self()?; + } else { + debug!("Not applying Landlock sandboxing due to {SANDBOX_ENV_VAR} setting.") + } + make_brew_symlink()?; + let mut args = std::env::args_os(); + let error = Command::new(brew_path()) + .arg0(args.next().unwrap()) + .args(args) + .exec(); + Err(error.into()) +} diff --git a/etc/homebrew/brew-sandbox.env b/etc/homebrew/brew-sandbox.env new file mode 100644 index 0000000..6ace50b --- /dev/null +++ b/etc/homebrew/brew-sandbox.env @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: Copyright 2026 Daniel Hast +# +# SPDX-License-Identifier: CC0-1.0 + +# Configures whether the sandboxing provided by the homebrew-sandbox package +# should be enabled or disabled. +# _HOMEBREW_SANDBOX=1 diff --git a/etc/homebrew/brew.env b/etc/homebrew/brew.env index 15f2fbb..2a952a3 100644 --- a/etc/homebrew/brew.env +++ b/etc/homebrew/brew.env @@ -9,3 +9,4 @@ HOMEBREW_CACHE=/home/linuxbrew/.cache/Homebrew HOMEBREW_NO_ANALYTICS=1 HOMEBREW_NO_INSECURE_REDIRECT=1 HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY=1 +HOMEBREW_TEMP=/var/tmp/homebrew diff --git a/homebrew-template.spec b/homebrew-template.spec index 6dd06e5..042aa9a 100644 --- a/homebrew-template.spec +++ b/homebrew-template.spec @@ -26,6 +26,7 @@ Source0: homebrew-@@VERSION@@.tar.gz Source1: homebrew-install.sh Source2: homebrew-brew-git.tar.gz +BuildRequires: cargo-rpm-macros BuildRequires: curl >= 7.41.0 BuildRequires: git-core >= 2.7.0 BuildRequires: systemd-rpm-macros @@ -43,16 +44,24 @@ Requires: zstd Homebrew installs the stuff you need that Apple (or your Linux system) didn't. %prep -%setup -C +%setup -q -C cp -a %{SOURCE1} . patch -p0 < homebrew-install.patch -%setup -T -D -a 2 +%setup -q -T -D -a 2 +%cargo_prep + +%generate_buildrequires +%cargo_generate_buildrequires -t %build 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 +%cargo_build +%{cargo_license_summary} +%{cargo_license} > LICENSE.dependencies + %install # main brew installation mkdir -m 755 -p %{buildroot}%{_datadir}/homebrew @@ -62,9 +71,7 @@ cp -a .linuxbrew %{buildroot}%{_datadir}/homebrew install -Dp -m 644 -t %{buildroot}%{_sysconfdir}/homebrew etc/homebrew/brew.env # systemd units for automatic brew setup and updates -for unit in brew-setup.service brew-update.service brew-update.timer brew-upgrade.service brew-upgrade.timer; do - install -Dp -m 644 -t %{buildroot}%{_unitdir} "usr/lib/systemd/system/${unit}" -done +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 @@ -73,6 +80,12 @@ install -Dp -m 644 -t %{buildroot}%{_datadir}/fish/vendor_conf.d usr/share/fish/ # systemd-tmpfiles install -Dp -m 644 -t %{buildroot}%{_tmpfilesdir} usr/lib/tmpfiles.d/homebrew.conf +# homebrew-sandbox +install -Dp -m 755 -t %{buildroot}%{_datadir}/homebrew-sandbox/.linuxbrew/bin target/rpm/brew +mkdir -p %{buildroot}%{_datadir}/homebrew-sandbox/.linuxbrew/.sandbox +ln -s ../Homebrew/bin/brew %{buildroot}%{_datadir}/homebrew-sandbox/.linuxbrew/.sandbox/brew +install -Dp -m 644 -t %{buildroot}%{_sysconfdir}/homebrew etc/homebrew/brew-sandbox.env + %post %systemd_post brew-setup.service %systemd_post brew-update.service @@ -103,12 +116,47 @@ install -Dp -m 644 -t %{buildroot}%{_tmpfilesdir} usr/lib/tmpfiles.d/homebrew.co %{_unitdir}/brew-upgrade.timer %{_datadir}/fish/vendor_conf.d/brew-fish-completions.fish %{_tmpfilesdir}/homebrew.conf -%config(noreplace) %{_sysconfdir}/homebrew +%config(noreplace) %{_sysconfdir}/homebrew/brew.env %config(noreplace) %{_sysconfdir}/profile.d/brew.sh %config(noreplace) %{_sysconfdir}/profile.d/brew-bash-completions.sh %ghost %config(noreplace) %{_sysconfdir}/.linuxbrew +%package sandbox +Version: 0.1.0 +Summary: Sandboxing for the brew command using Landlock +SourceLicense: Apache-2.0 OR MIT +License: (Apache-2.0 OR MIT) AND MIT +Requires: homebrew + +%description sandbox +This package provides sandboxing for the brew command using the Landlock LSM. +It works by wrapping the brew command in a simple Rust program that sets up the +Landlock sandbox and then passes its arguments on to brew. + +Note that only brew itself is sandboxed, not programs intalled using brew. + +The sandbox allows brew read-write access only to the Homebrew prefix, cache, +and temporary directories and a limited subset of /dev, and read-only access to +/usr and /etc. Network access is limited to port 443. + +%post sandbox +%systemd_post brew-sandbox-setup.service + +%preun sandbox +%systemd_preun brew-sandbox-setup.service + +%postun sandbox +%systemd_postun_with_reload brew-sandbox-setup.service + +%files sandbox +%license LICENSE.dependencies +%{_datadir}/homebrew-sandbox +%{_unitdir}/brew-sandbox-setup.service +%ghost %config(noreplace) %{_sysconfdir}/homebrew/brew-sandbox.env + %changelog +* Sun Feb 1 2026 Daniel Hast + - Add homebrew-sandbox subpackage * Wed Jan 28 2026 Daniel Hast - Update installer commit - Make Homebrew/brew repo part of SRPM diff --git a/usr/lib/systemd/system/brew-sandbox-setup.service b/usr/lib/systemd/system/brew-sandbox-setup.service new file mode 100644 index 0000000..5bc3fe6 --- /dev/null +++ b/usr/lib/systemd/system/brew-sandbox-setup.service @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: Copyright 2026 Daniel Hast +# +# SPDX-License-Identifier: Apache-2.0 OR MIT + +[Unit] +Description=Set up Homebrew sandbox +Wants=multi-user.target brew-setup.service +After=multi-user.target brew-setup.service +ConditionPathIsSymbolicLink=/home/linuxbrew/.linuxbrew/bin/brew +ConditionPathExists=!/home/linuxbrew/.linuxbrew/.sandbox + +[Service] +User=1000 +Type=oneshot +ExecStart=/usr/bin/cp -a /usr/share/homebrew-sandbox/.linuxbrew/.sandbox /home/linuxbrew/.linuxbrew +ExecStart=/usr/bin/install -p -m 755 -t /home/linuxbrew/.linuxbrew/bin /usr/share/homebrew-sandbox/.linuxbrew/bin/brew + +[Install] +WantedBy=multi-user.target brew-setup.service diff --git a/usr/lib/tmpfiles.d/homebrew.conf b/usr/lib/tmpfiles.d/homebrew.conf index 7d2652d..fcdd239 100644 --- a/usr/lib/tmpfiles.d/homebrew.conf +++ b/usr/lib/tmpfiles.d/homebrew.conf @@ -1,8 +1,6 @@ -# 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 +# SPDX-License-Identifier: Apache-2.0 OR MIT -d /var/lib/homebrew 0755 1000 1000 - - -d /var/cache/homebrew 0755 1000 1000 - - d /home/linuxbrew 0755 1000 1000 - - +d /var/tmp/homebrew 0700 1000 1000 3d -