1
0
Fork 0
mirror of https://github.com/LnL7/nix-darwin.git synced 2025-03-31 04:04:45 +00:00

activation-scripts: get rid of user activation

🎉

Closes: #96
This commit is contained in:
Emily 2025-01-11 15:44:41 +00:00
parent 52026cf3eb
commit c8660d0aa4
7 changed files with 104 additions and 61 deletions

View file

@ -62,6 +62,23 @@ in
config = {
assertions =
map
(userActivationOption: {
assertion = !config.system.activationScripts ? ${userActivationOption};
message = ''
The `system.activationScripts.${userActivationOption}` option has
been removed, as all activation now takes place as `root`. Please
restructure your custom activation scripts appropriately,
potentially using `sudo` if you need to run commands as a user.
'';
})
[
"extraUserActivation"
"preUserActivation"
"postUserActivation"
];
system.activationScripts.script.text = ''
#! ${stdenv.shell}
set -e
@ -77,9 +94,9 @@ in
${cfg.activationScripts.preActivation.text}
# We run `etcChecks` again just in case someone runs `activate`
# directly without `activate-user`.
${cfg.activationScripts.etcChecks.text}
${cfg.activationScripts.createRun.text}
${cfg.activationScripts.checks.text}
${cfg.activationScripts.extraActivation.text}
${cfg.activationScripts.groups.text}
${cfg.activationScripts.users.text}
@ -114,45 +131,11 @@ in
fi
'';
# FIXME: activationScripts.checks should be system level
system.activationScripts.userScript.text = ''
#! ${stdenv.shell}
set -e
set -o pipefail
PATH="${activationPath}"
export PATH
systemConfig=@out@
_status=0
trap "_status=1" ERR
# Ensure a consistent umask.
umask 0022
${cfg.activationScripts.preUserActivation.text}
# This should be running at the system level, but as user activation runs first
# we run it here with sudo
${cfg.activationScripts.createRun.text}
${cfg.activationScripts.checks.text}
${cfg.activationScripts.etcChecks.text}
${cfg.activationScripts.extraUserActivation.text}
${cfg.activationScripts.postUserActivation.text}
exit $_status
'';
# Extra activation scripts, that can be customized by users
# don't use this unless you know what you are doing.
system.activationScripts.extraActivation.text = mkDefault "";
system.activationScripts.preActivation.text = mkDefault "";
system.activationScripts.postActivation.text = mkDefault "";
system.activationScripts.extraUserActivation.text = mkDefault "";
system.activationScripts.preUserActivation.text = mkDefault "";
system.activationScripts.postUserActivation.text = mkDefault "";
};
}

View file

@ -4,26 +4,26 @@
system.activationScripts.createRun.text = ''
if [[ $(stat -c '%a' /etc/synthetic.conf) != "644" ]]; then
echo "fixing permissions on /etc/synthetic.conf..."
sudo chmod 644 /etc/synthetic.conf
chmod 644 /etc/synthetic.conf
fi
if [[ $(grep -c '^run\b' /etc/synthetic.conf) -gt 1 ]]; then
echo "found duplicate run entries in /etc/synthetic.conf, removing..."
sudo sed -i "" -e '/^run\tprivate\/var\/run$/d' /etc/synthetic.conf
sed -i "" -e '/^run\tprivate\/var\/run$/d' /etc/synthetic.conf
fi
if ! grep -q '^run\b' /etc/synthetic.conf 2>/dev/null; then
echo "setting up /run via /etc/synthetic.conf..."
printf 'run\tprivate/var/run\n' | sudo tee -a /etc/synthetic.conf >/dev/null
printf 'run\tprivate/var/run\n' | tee -a /etc/synthetic.conf >/dev/null
fi
sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t || true
/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t || true
if [[ ! -L /run ]]; then
printf >&2 'error: apfs.util failed to symlink /run, aborting activation\n'
printf >&2 'To create a symlink from /run to /var/run, please run:\n'
printf >&2 '\n'
printf >&2 "$ printf 'run\tprivate/var/run\n' | sudo tee -a /etc/synthetic.conf\n"
printf >&2 "$ printf 'run\tprivate/var/run\n' | tee -a /etc/synthetic.conf\n"
printf >&2 '$ sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t\n'
printf >&2 '\n'
printf >&2 'The current contents of /etc/synthetic.conf is:\n'

View file

@ -95,7 +95,51 @@ in
nativeBuildInputs = [ pkgs.shellcheck ];
activationScript = cfg.activationScripts.script.text;
activationUserScript = cfg.activationScripts.userScript.text;
# This is for compatibility with older `darwin-rebuild`s and
# thirdparty deployment tools.
#
# TODO: Remove this in 25.11.
activationUserScript = ''
#! ${pkgs.stdenv.shell}
# nix-darwin: deprecated
# Hack to handle upgrades.
if
[[ -e /run/current-system/activate-user ]] \
&& ! grep -q '^# nix-darwin: deprecated$' \
/run/current-system/activate-user
then
exit
fi
printf >&2 '\e[1;31mwarning: `activate-user` is deprecated and will be removed in 25.11\e[0m\n'
printf >&2 'This is usually due to the use of a nonstandard activation/deployment\n'
printf >&2 'tool. If you maintain one of these tools, our advice is:\n'
printf >&2 '\n'
printf >&2 ' You can identify a postuseractivation configuration by the absence\n'
printf >&2 ' of `activate-user` or the second line of the script being\n'
printf >&2 ' `# nix-darwin: deprecated`.\n'
printf >&2 '\n'
printf >&2 ' We recommend running `$systemConfig/sw/bin/darwin-rebuild activate`\n'
printf >&2 ' to activate built configurations; for a preuseractivation\n'
printf >&2 ' configuration this should be run as a normal user, and for a\n'
printf >&2 ' postuseractivation configuration it should be run as `root`.\n'
printf >&2 '\n'
printf >&2 ' If you cant or dont want to use `darwin-rebuild activate`, then you\n'
printf >&2 ' should skip running `activate-user` for postuseractivation\n'
printf >&2 ' configurations and continue running `activate` as `root`.\n'
printf >&2 '\n'
printf >&2 ' In 25.11, `darwin-rebuild` will stop running `activate-user` and this\n'
printf >&2 ' transition script will be deleted; you should be able to safely\n'
printf >&2 ' remove all related logic by then.\n'
printf >&2 '\n'
printf >&2 'Otherwise, you should report this to the deployment tool developers. If\n'
printf >&2 'you dont use a thirdparty deployment tool, please open a bug report\n'
printf >&2 'at <https://github.com/LnL7/nix-darwin/issues/new> and include as much\n'
printf >&2 'detail about your setup as possible.\n'
'';
inherit (cfg) darwinLabel;
darwinVersionJson = (pkgs.formats.json {}).generate "darwin-version.json" (
@ -131,7 +175,6 @@ in
unset activationScript
echo "$activationUserScript" > $out/activate-user
substituteInPlace $out/activate-user --subst-var out
chmod u+x $out/activate-user
unset activationUserScript

View file

@ -155,7 +155,7 @@ in
homeDirectory=$(dscl . -read /Users/nobody NFSHomeDirectory)
homeDirectory=''${homeDirectory#NFSHomeDirectory: }
if ! sudo dscl . -change /Users/nobody NFSHomeDirectory "$homeDirectory" "$homeDirectory" &> /dev/null; then
if ! dscl . -change /Users/nobody NFSHomeDirectory "$homeDirectory" "$homeDirectory" &> /dev/null; then
if [[ "$(launchctl managername)" != Aqua ]]; then
printf >&2 '\e[1;31merror: users cannot be %s over SSH without Full Disk Access, aborting activation\e[0m\n' "$2"
printf >&2 'The user %s could not be %s as `darwin-rebuild` was not executed with Full Disk Access over SSH.\n' "$1" "$2"
@ -176,7 +176,7 @@ in
# and we can reset it to ensure the user gets another prompt
tccutil reset SystemPolicySysAdminFiles > /dev/null
if ! sudo dscl . -change /Users/nobody NFSHomeDirectory "$homeDirectory" "$homeDirectory" &> /dev/null; then
if ! dscl . -change /Users/nobody NFSHomeDirectory "$homeDirectory" "$homeDirectory" &> /dev/null; then
printf >&2 '\e[1;31merror: permission denied when trying to %s user %s, aborting activation\e[0m\n' "$2" "$1"
printf >&2 '`darwin-rebuild` requires permissions to administrate your computer,\n'
printf >&2 'please accept the dialog that pops up.\n'

View file

@ -1,4 +1,4 @@
{ lib, pkgs, ... }:
{ lib, config, pkgs, ... }:
with lib;
@ -15,13 +15,17 @@ with lib;
# Restore any unmanaged `nix-daemon`.
nix.enable = false;
system.activationScripts.postUserActivation.text = mkAfter ''
nix-channel --remove darwin || true
'';
system.activationScripts.postActivation.text = mkAfter ''
nix-channel --remove darwin || true
${lib.optionalString (config.system.primaryUser != null) ''
sudo \
--user=${lib.escapeShellArg config.system.primaryUser} \
--set-home \
-- nix-channel --remove darwin \
|| true
''}
if [[ -L /Applications/Nix\ Apps ]]; then
rm /Applications/Nix\ Apps
fi

View file

@ -190,6 +190,7 @@ if [ "$action" = switch ] || [ "$action" = build ] || [ "$action" = check ] || [
-- "$flake#$flakeAttr.system" \
| jq -r '.[0].outputs.out')
fi
fi
if [ "$action" = list ] || [ "$action" = rollback ]; then
@ -210,6 +211,17 @@ fi
if [ -z "$systemConfig" ]; then exit 0; fi
# TODO: Remove this backwardscompatibility hack in 25.11.
if
[[ -x $systemConfig/activate-user ]] \
&& ! grep -q '^# nix-darwin: deprecated$' "$systemConfig/activate-user"
then
hasActivateUser=1
else
hasActivateUser=
fi
if [ "$action" = switch ]; then
if [ "$USER" != root ] && [ ! -w $(dirname "$profile") ]; then
sudo nix-env -p "$profile" --set "$systemConfig"
@ -219,7 +231,9 @@ if [ "$action" = switch ]; then
fi
if [ "$action" = switch ] || [ "$action" = activate ] || [ "$action" = rollback ]; then
"$systemConfig/activate-user"
if [[ -n $hasActivateUser ]]; then
"$systemConfig/activate-user"
fi
if [ "$USER" != root ]; then
sudo "$systemConfig/activate"
@ -234,5 +248,13 @@ fi
if [ "$action" = check ]; then
export checkActivation=1
"$systemConfig/activate-user"
if [[ -n $hasActivateUser ]]; then
"$systemConfig/activate-user"
else
if [ "$USER" != root ]; then
sudo "$systemConfig/activate"
else
"$systemConfig/activate"
fi
fi
fi

View file

@ -1,10 +1,6 @@
{ config, pkgs, ... }:
{
system.activationScripts.preUserActivation.text = "echo hook preUserActivation";
system.activationScripts.extraUserActivation.text = "echo hook extraUserActivation";
system.activationScripts.postUserActivation.text = "echo hook postUserActivation";
system.activationScripts.preActivation.text = "echo hook preActivation";
system.activationScripts.extraActivation.text = "echo hook extraActivation";
system.activationScripts.postActivation.text = "echo hook postActivation";
@ -14,11 +10,6 @@
awk '/echo hook / {i++ ; print i " => " $0}' "$2" | grep "$1"
}
echo checking activation hooks in /activate-user >&2
countHooks "1 => echo hook preUserActivation" ${config.out}/activate-user
countHooks "2 => echo hook extraUserActivation" ${config.out}/activate-user
countHooks "3 => echo hook postUserActivation" ${config.out}/activate-user
echo checking activation hooks in /activate >&2
countHooks "1 => echo hook preActivation" ${config.out}/activate
countHooks "2 => echo hook extraActivation" ${config.out}/activate