Skip to content

Commit b83215a

Browse files
committed
add script to migrate macOS 15 Sequoia nixbld UIDs
While we don't have any easy way to forcibly notify everyone about the impending breakage (or forcibly migrate the users on their system), this script enables those who do hear about the problem to migrate their systems before they take the macOS update. It should also enable people who only discover it after the update when a build fails to ~fix their installs without a full reinstall.
1 parent caabdb0 commit b83215a

File tree

1 file changed

+85
-14
lines changed

1 file changed

+85
-14
lines changed

scripts/sequoia-nixbld-user-migration.sh

100644100755
Lines changed: 85 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,106 @@
22

33
((NEW_NIX_FIRST_BUILD_UID=331))
44

5+
nix_user_n() {
6+
printf "_nixbld%d" "$1"
7+
}
8+
59
id_available(){
610
dscl . list /Users UniqueID | grep -E '\b'"$1"'\b' >/dev/null
711
}
812

9-
change_nixbld_names_and_ids(){
10-
local name uid next_id
13+
any_nixbld(){
14+
dscl . list /Users UniqueID | grep -E '\b_nixbld' >/dev/null
15+
}
16+
17+
re_create_nixbld_user(){
18+
local name uid
19+
20+
name="$1"
21+
uid="$2"
22+
23+
sudo /usr/bin/dscl . -create "/Users/$name" UniqueID "$uid"
24+
sudo /usr/bin/dscl . -create "/Users/$name" "IsHidden" "1"
25+
sudo /usr/bin/dscl . -create "/Users/$name" "NFSHomeDirectory" "/var/empty"
26+
sudo /usr/bin/dscl . -create "/Users/$name" "RealName" "Nix build user $uid"
27+
sudo /usr/bin/dscl . -create "/Users/$name" "UserShell" "/sbin/nologin"
28+
sudo /usr/bin/dscl . -create "/Users/$name" "PrimaryGroupID" "$NEW_NIX_FIRST_BUILD_UID"
29+
}
30+
31+
hit_id_cap(){
32+
echo "We've hit UID 400 without placing all of your users :("
33+
echo "You should use the commands in this script as a starting"
34+
echo "point to review your UID-space and manually move the"
35+
echo "remaining users (or delete them, if you don't need them)."
36+
}
37+
38+
change_nixbld_uids(){
39+
local name next_id user_n
40+
1141
((next_id=NEW_NIX_FIRST_BUILD_UID))
42+
((user_n=1))
43+
name="$(nix_user_n "$user_n")"
44+
1245
echo "Attempting to migrate _nixbld users."
46+
47+
echo "Migrating nixbld group to GID $NEW_NIX_FIRST_BUILD_UID"
48+
sudo dscl . -create "/Groups/nixbld" PrimaryGroupID "$NEW_NIX_FIRST_BUILD_UID"
49+
50+
# we know that we have *some* nixbld users, but macOS may have
51+
# already clobbered the first few users if this system has been
52+
# upgraded
53+
54+
echo "Checking first for missing early users."
55+
56+
until dscl . read "/Users/$name" &>/dev/null; do
57+
# iterate for a clean ID
58+
while id_available "$next_id"; do
59+
((next_id++))
60+
if ((next_id >= 400)); then
61+
hit_id_cap
62+
exit 1
63+
fi
64+
done
65+
66+
re_create_nixbld_user "$name" "$next_id"
67+
echo " $name was missing; created with uid: $next_id"
68+
69+
((user_n++))
70+
name="$(nix_user_n "$user_n")"
71+
done
72+
1373
echo "Each _nixbld# user should have its UID moved to $next_id+"
14-
while read -r name uid; do
15-
echo " Checking $name (uid: $uid)"
74+
75+
# start at _nixbld1 and increment until _nixbld<n> doesn't exist
76+
while dscl . read "/Users/$name" &>/dev/null; do
1677
# iterate for a clean ID
1778
while id_available "$next_id"; do
1879
((next_id++))
1980
if ((next_id >= 400)); then
20-
echo "We've hit UID 400 without placing all of your users :("
21-
echo "You should use the commands in this script as a starting"
22-
echo "point to review your UID-space and manually move the"
23-
echo "remaining users (or delete them, if you don't need them)."
81+
hit_id_cap
2482
exit 1
2583
fi
2684
done
2785

28-
# first 2 are cleanup, it's OK if they aren't here
29-
sudo dscl . delete "/Users/$name" dsAttrTypeNative:_writers_passwd &>/dev/null || true
30-
sudo dscl . change "/Users/$name" NFSHomeDirectory "/private/var/empty 1" "/var/empty" &>/dev/null || true
31-
sudo dscl . change "/Users/$name" UniqueID "$uid" "$next_id"
86+
sudo dscl . -create "/Users/$name" UniqueID "$next_id"
3287
echo " $name migrated to uid: $next_id"
33-
done < <(dscl . list /Users UniqueID | grep _nixbld | sort -n -k2)
88+
89+
((user_n++))
90+
name="$(nix_user_n "$user_n")"
91+
done
92+
93+
if ((user_n == 1)); then
94+
echo "Didn't find _nixbld1. Perhaps you have single-user Nix?"
95+
exit 1
96+
else
97+
echo "Migrated $((user_n - 1)) users. If you want to double-check, try:"
98+
echo "dscl . list /Users UniqueID | grep _nixbld | sort -n -k2"
99+
fi
34100
}
35101

36-
change_nixbld_names_and_ids
102+
if any_nixbld; then
103+
change_nixbld_uids
104+
else
105+
echo "Didn't find any _nixbld users. Perhaps you have single-user Nix?"
106+
exit 1
107+
fi

0 commit comments

Comments
 (0)