Delete the existing installer
We're not going to use it.
Fixes: #31
Change-Id: Ib17a2eb6cae1ecbbf9ad1062e576ba6107a3c13b
This commit is contained in:
parent
c26599b143
commit
93cc063344
100
flake.nix
100
flake.nix
|
@ -74,40 +74,6 @@
|
||||||
cross = forAllCrossSystems (crossSystem: make-pkgs crossSystem "stdenv");
|
cross = forAllCrossSystems (crossSystem: make-pkgs crossSystem "stdenv");
|
||||||
});
|
});
|
||||||
|
|
||||||
installScriptFor = systems:
|
|
||||||
with nixpkgsFor.x86_64-linux.native;
|
|
||||||
runCommand "installer-script"
|
|
||||||
{ buildInputs = [ nix ];
|
|
||||||
}
|
|
||||||
''
|
|
||||||
mkdir -p $out/nix-support
|
|
||||||
|
|
||||||
# Converts /nix/store/50p3qk8k...-nix-2.4pre20201102_550e11f/bin/nix to 50p3qk8k.../bin/nix.
|
|
||||||
tarballPath() {
|
|
||||||
# Remove the store prefix
|
|
||||||
local path=''${1#${builtins.storeDir}/}
|
|
||||||
# Get the path relative to the derivation root
|
|
||||||
local rest=''${path#*/}
|
|
||||||
# Get the derivation hash
|
|
||||||
local drvHash=''${path%%-*}
|
|
||||||
echo "$drvHash/$rest"
|
|
||||||
}
|
|
||||||
|
|
||||||
substitute ${./scripts/install.in} $out/install \
|
|
||||||
${pkgs.lib.concatMapStrings
|
|
||||||
(system: let
|
|
||||||
tarball = if builtins.elem system crossSystems then self.hydraJobs.binaryTarballCross.x86_64-linux.${system} else self.hydraJobs.binaryTarball.${system};
|
|
||||||
in '' \
|
|
||||||
--replace '@tarballHash_${system}@' $(nix --experimental-features nix-command hash-file --base16 --type sha256 ${tarball}/*.tar.xz) \
|
|
||||||
--replace '@tarballPath_${system}@' $(tarballPath ${tarball}/*.tar.xz) \
|
|
||||||
''
|
|
||||||
)
|
|
||||||
systems
|
|
||||||
} --replace '@nixVersion@' ${version}
|
|
||||||
|
|
||||||
echo "file installer $out/install" >> $out/nix-support/hydra-build-products
|
|
||||||
'';
|
|
||||||
|
|
||||||
testNixVersions = pkgs: client: daemon: let
|
testNixVersions = pkgs: client: daemon: let
|
||||||
nix = pkgs.callPackage ./package.nix {
|
nix = pkgs.callPackage ./package.nix {
|
||||||
pname =
|
pname =
|
||||||
|
@ -146,8 +112,7 @@
|
||||||
binaryTarball = nix: pkgs:
|
binaryTarball = nix: pkgs:
|
||||||
let
|
let
|
||||||
inherit (pkgs) buildPackages;
|
inherit (pkgs) buildPackages;
|
||||||
inherit (pkgs) cacert;
|
installerClosureInfo = buildPackages.closureInfo { rootPaths = [ nix ]; };
|
||||||
installerClosureInfo = buildPackages.closureInfo { rootPaths = [ nix cacert ]; };
|
|
||||||
in
|
in
|
||||||
|
|
||||||
buildPackages.runCommand "nix-binary-tarball-${version}"
|
buildPackages.runCommand "nix-binary-tarball-${version}"
|
||||||
|
@ -156,45 +121,7 @@
|
||||||
}
|
}
|
||||||
''
|
''
|
||||||
cp ${installerClosureInfo}/registration $TMPDIR/reginfo
|
cp ${installerClosureInfo}/registration $TMPDIR/reginfo
|
||||||
cp ${./scripts/create-darwin-volume.sh} $TMPDIR/create-darwin-volume.sh
|
|
||||||
substitute ${./scripts/install-nix-from-closure.sh} $TMPDIR/install \
|
|
||||||
--subst-var-by nix ${nix} \
|
|
||||||
--subst-var-by cacert ${cacert}
|
|
||||||
|
|
||||||
substitute ${./scripts/install-darwin-multi-user.sh} $TMPDIR/install-darwin-multi-user.sh \
|
|
||||||
--subst-var-by nix ${nix} \
|
|
||||||
--subst-var-by cacert ${cacert}
|
|
||||||
substitute ${./scripts/install-systemd-multi-user.sh} $TMPDIR/install-systemd-multi-user.sh \
|
|
||||||
--subst-var-by nix ${nix} \
|
|
||||||
--subst-var-by cacert ${cacert}
|
|
||||||
substitute ${./scripts/install-multi-user.sh} $TMPDIR/install-multi-user \
|
|
||||||
--subst-var-by nix ${nix} \
|
|
||||||
--subst-var-by cacert ${cacert}
|
|
||||||
|
|
||||||
if type -p shellcheck; then
|
|
||||||
# SC1090: Don't worry about not being able to find
|
|
||||||
# $nix/etc/profile.d/nix.sh
|
|
||||||
shellcheck --exclude SC1090 $TMPDIR/install
|
|
||||||
shellcheck $TMPDIR/create-darwin-volume.sh
|
|
||||||
shellcheck $TMPDIR/install-darwin-multi-user.sh
|
|
||||||
shellcheck $TMPDIR/install-systemd-multi-user.sh
|
|
||||||
|
|
||||||
# SC1091: Don't panic about not being able to source
|
|
||||||
# /etc/profile
|
|
||||||
# SC2002: Ignore "useless cat" "error", when loading
|
|
||||||
# .reginfo, as the cat is a much cleaner
|
|
||||||
# implementation, even though it is "useless"
|
|
||||||
# SC2116: Allow ROOT_HOME=$(echo ~root) for resolving
|
|
||||||
# root's home directory
|
|
||||||
shellcheck --external-sources \
|
|
||||||
--exclude SC1091,SC2002,SC2116 $TMPDIR/install-multi-user
|
|
||||||
fi
|
|
||||||
|
|
||||||
chmod +x $TMPDIR/install
|
|
||||||
chmod +x $TMPDIR/create-darwin-volume.sh
|
|
||||||
chmod +x $TMPDIR/install-darwin-multi-user.sh
|
|
||||||
chmod +x $TMPDIR/install-systemd-multi-user.sh
|
|
||||||
chmod +x $TMPDIR/install-multi-user
|
|
||||||
dir=nix-${version}-${pkgs.system}
|
dir=nix-${version}-${pkgs.system}
|
||||||
fn=$out/$dir.tar.xz
|
fn=$out/$dir.tar.xz
|
||||||
mkdir -p $out/nix-support
|
mkdir -p $out/nix-support
|
||||||
|
@ -204,15 +131,8 @@
|
||||||
--mtime='1970-01-01' \
|
--mtime='1970-01-01' \
|
||||||
--absolute-names \
|
--absolute-names \
|
||||||
--hard-dereference \
|
--hard-dereference \
|
||||||
--transform "s,$TMPDIR/install,$dir/install," \
|
|
||||||
--transform "s,$TMPDIR/create-darwin-volume.sh,$dir/create-darwin-volume.sh," \
|
|
||||||
--transform "s,$TMPDIR/reginfo,$dir/.reginfo," \
|
--transform "s,$TMPDIR/reginfo,$dir/.reginfo," \
|
||||||
--transform "s,$NIX_STORE,$dir/store,S" \
|
--transform "s,$NIX_STORE,$dir/store,S" \
|
||||||
$TMPDIR/install \
|
|
||||||
$TMPDIR/create-darwin-volume.sh \
|
|
||||||
$TMPDIR/install-darwin-multi-user.sh \
|
|
||||||
$TMPDIR/install-systemd-multi-user.sh \
|
|
||||||
$TMPDIR/install-multi-user \
|
|
||||||
$TMPDIR/reginfo \
|
$TMPDIR/reginfo \
|
||||||
$(cat ${installerClosureInfo}/store-paths)
|
$(cat ${installerClosureInfo}/store-paths)
|
||||||
'';
|
'';
|
||||||
|
@ -288,8 +208,7 @@
|
||||||
perlBindings = forAllSystems (system: nixpkgsFor.${system}.native.nix.perl-bindings);
|
perlBindings = forAllSystems (system: nixpkgsFor.${system}.native.nix.perl-bindings);
|
||||||
|
|
||||||
# Binary tarball for various platforms, containing a Nix store
|
# Binary tarball for various platforms, containing a Nix store
|
||||||
# with the closure of 'nix' package, and the second half of
|
# with the closure of 'nix' package.
|
||||||
# the installation script.
|
|
||||||
binaryTarball = forAllSystems (system: binaryTarball nixpkgsFor.${system}.native.nix nixpkgsFor.${system}.native);
|
binaryTarball = forAllSystems (system: binaryTarball nixpkgsFor.${system}.native.nix nixpkgsFor.${system}.native);
|
||||||
|
|
||||||
# docker image with Nix inside
|
# docker image with Nix inside
|
||||||
|
@ -340,26 +259,11 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
installTests = forAllSystems (system:
|
|
||||||
let pkgs = nixpkgsFor.${system}.native; in
|
|
||||||
pkgs.runCommand "install-tests" {
|
|
||||||
againstSelf = testNixVersions pkgs pkgs.nix pkgs.pkgs.nix;
|
|
||||||
againstCurrentUnstable =
|
|
||||||
# FIXME: temporarily disable this on macOS because of #3605.
|
|
||||||
if system == "x86_64-linux"
|
|
||||||
then testNixVersions pkgs pkgs.nix pkgs.nixUnstable
|
|
||||||
else null;
|
|
||||||
# Disabled because the latest stable version doesn't handle
|
|
||||||
# `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work
|
|
||||||
# againstLatestStable = testNixVersions pkgs pkgs.nix pkgs.nixStable;
|
|
||||||
} "touch $out");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
checks = forAllSystems (system: {
|
checks = forAllSystems (system: {
|
||||||
binaryTarball = self.hydraJobs.binaryTarball.${system};
|
binaryTarball = self.hydraJobs.binaryTarball.${system};
|
||||||
perlBindings = self.hydraJobs.perlBindings.${system};
|
perlBindings = self.hydraJobs.perlBindings.${system};
|
||||||
installTests = self.hydraJobs.installTests.${system};
|
|
||||||
nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system};
|
nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system};
|
||||||
rl-next =
|
rl-next =
|
||||||
let pkgs = nixpkgsFor.${system}.native;
|
let pkgs = nixpkgsFor.${system}.native;
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
((NEW_NIX_FIRST_BUILD_UID=301))
|
|
||||||
|
|
||||||
id_available(){
|
|
||||||
dscl . list /Users UniqueID | grep -E '\b'$1'\b' >/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
change_nixbld_names_and_ids(){
|
|
||||||
local name uid next_id
|
|
||||||
((next_id=NEW_NIX_FIRST_BUILD_UID))
|
|
||||||
echo "Attempting to migrate nixbld users."
|
|
||||||
echo "Each user should change from nixbld# to _nixbld#"
|
|
||||||
echo "and their IDs relocated to $next_id+"
|
|
||||||
while read -r name uid; do
|
|
||||||
echo " Checking $name (uid: $uid)"
|
|
||||||
# iterate for a clean ID
|
|
||||||
while id_available "$next_id"; do
|
|
||||||
((next_id++))
|
|
||||||
if ((next_id >= 400)); then
|
|
||||||
echo "We've hit UID 400 without placing all of your users :("
|
|
||||||
echo "You should use the commands in this script as a starting"
|
|
||||||
echo "point to review your UID-space and manually move the"
|
|
||||||
echo "remaining users (or delete them, if you don't need them)."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ $name == _* ]]; then
|
|
||||||
echo " It looks like $name has already been renamed--skipping."
|
|
||||||
else
|
|
||||||
# first 3 are cleanup, it's OK if they aren't here
|
|
||||||
sudo dscl . delete /Users/$name dsAttrTypeNative:_writers_passwd &>/dev/null || true
|
|
||||||
sudo dscl . change /Users/$name NFSHomeDirectory "/private/var/empty 1" "/var/empty" &>/dev/null || true
|
|
||||||
# remove existing user from group
|
|
||||||
sudo dseditgroup -o edit -t user -d $name nixbld || true
|
|
||||||
sudo dscl . change /Users/$name UniqueID $uid $next_id
|
|
||||||
sudo dscl . change /Users/$name RecordName $name _$name
|
|
||||||
# add renamed user to group
|
|
||||||
sudo dseditgroup -o edit -t user -a _$name nixbld
|
|
||||||
echo " $name migrated to _$name (uid: $next_id)"
|
|
||||||
fi
|
|
||||||
done < <(dscl . list /Users UniqueID | grep nixbld | sort -n -k2)
|
|
||||||
}
|
|
||||||
|
|
||||||
change_nixbld_names_and_ids
|
|
|
@ -1,33 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
# set -x
|
|
||||||
|
|
||||||
|
|
||||||
# mapfile BUILDS_FOR_LATEST_EVAL < <(
|
|
||||||
# curl -H 'Accept: application/json' https://hydra.nixos.org/jobset/nix/master/evals | \
|
|
||||||
# jq -r '.evals[0].builds[] | @sh')
|
|
||||||
BUILDS_FOR_LATEST_EVAL=$(
|
|
||||||
curl -sS -H 'Accept: application/json' https://hydra.nixos.org/jobset/nix/master/evals | \
|
|
||||||
jq -r '.evals[0].builds[]')
|
|
||||||
|
|
||||||
someBuildFailed=0
|
|
||||||
|
|
||||||
for buildId in $BUILDS_FOR_LATEST_EVAL; do
|
|
||||||
buildInfo=$(curl --fail -sS -H 'Accept: application/json' "https://hydra.nixos.org/build/$buildId")
|
|
||||||
|
|
||||||
finished=$(echo "$buildInfo" | jq -r '.finished')
|
|
||||||
|
|
||||||
if [[ $finished = 0 ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
buildStatus=$(echo "$buildInfo" | jq -r '.buildstatus')
|
|
||||||
|
|
||||||
if [[ $buildStatus != 0 ]]; then
|
|
||||||
someBuildFailed=1
|
|
||||||
echo "Job “$(echo "$buildInfo" | jq -r '.job')” failed on hydra: $buildInfo"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
exit "$someBuildFailed"
|
|
|
@ -1,875 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -eu
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
# I'm a little agnostic on the choices, but supporting a wide
|
|
||||||
# slate of uses for now, including:
|
|
||||||
# - import-only: `. create-darwin-volume.sh no-main[ ...]`
|
|
||||||
# - legacy: `./create-darwin-volume.sh` or `. create-darwin-volume.sh`
|
|
||||||
# (both will run main())
|
|
||||||
# - external alt-routine: `./create-darwin-volume.sh no-main func[ ...]`
|
|
||||||
if [ "${1-}" = "no-main" ]; then
|
|
||||||
shift
|
|
||||||
readonly _CREATE_VOLUME_NO_MAIN=1
|
|
||||||
else
|
|
||||||
readonly _CREATE_VOLUME_NO_MAIN=0
|
|
||||||
# declare some things we expect to inherit from install-multi-user
|
|
||||||
# I don't love this (because it's a bit of a kludge).
|
|
||||||
#
|
|
||||||
# CAUTION: (Dec 19 2020)
|
|
||||||
# This is a stopgap. It doesn't cover the full slate of
|
|
||||||
# identifiers we inherit--just those necessary to:
|
|
||||||
# - avoid breaking direct invocations of this script (here/now)
|
|
||||||
# - avoid hard-to-reverse structural changes before the call to rm
|
|
||||||
# single-user support is verified
|
|
||||||
#
|
|
||||||
# In the near-mid term, I (personally) think we should:
|
|
||||||
# - decide to deprecate the direct call and add a notice
|
|
||||||
# - fold all of this into install-darwin-multi-user.sh
|
|
||||||
# - intentionally remove the old direct-invocation form (kill the
|
|
||||||
# routine, replace this script w/ deprecation notice and a note
|
|
||||||
# on the remove-after date)
|
|
||||||
#
|
|
||||||
readonly NIX_ROOT="${NIX_ROOT:-/nix}"
|
|
||||||
|
|
||||||
_sudo() {
|
|
||||||
shift # throw away the 'explanation'
|
|
||||||
/usr/bin/sudo "$@"
|
|
||||||
}
|
|
||||||
failure() {
|
|
||||||
if [ "$*" = "" ]; then
|
|
||||||
cat
|
|
||||||
else
|
|
||||||
echo "$@"
|
|
||||||
fi
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
task() {
|
|
||||||
echo "$@"
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# usually "disk1"
|
|
||||||
root_disk_identifier() {
|
|
||||||
# For performance (~10ms vs 280ms) I'm parsing 'diskX' from stat output
|
|
||||||
# (~diskXsY)--but I'm retaining the more-semantic approach since
|
|
||||||
# it documents intent better.
|
|
||||||
# /usr/sbin/diskutil info -plist / | xmllint --xpath "/plist/dict/key[text()='ParentWholeDisk']/following-sibling::string[1]/text()" -
|
|
||||||
#
|
|
||||||
local special_device
|
|
||||||
special_device="$(/usr/bin/stat -f "%Sd" /)"
|
|
||||||
echo "${special_device%s[0-9]*}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# make it easy to play w/ 'Case-sensitive APFS'
|
|
||||||
readonly NIX_VOLUME_FS="${NIX_VOLUME_FS:-APFS}"
|
|
||||||
readonly NIX_VOLUME_LABEL="${NIX_VOLUME_LABEL:-Nix Store}"
|
|
||||||
# Strongly assuming we'll make a volume on the device / is on
|
|
||||||
# But you can override NIX_VOLUME_USE_DISK to create it on some other device
|
|
||||||
readonly NIX_VOLUME_USE_DISK="${NIX_VOLUME_USE_DISK:-$(root_disk_identifier)}"
|
|
||||||
NIX_VOLUME_USE_SPECIAL="${NIX_VOLUME_USE_SPECIAL:-}"
|
|
||||||
NIX_VOLUME_USE_UUID="${NIX_VOLUME_USE_UUID:-}"
|
|
||||||
readonly NIX_VOLUME_MOUNTD_DEST="${NIX_VOLUME_MOUNTD_DEST:-/Library/LaunchDaemons/org.nixos.darwin-store.plist}"
|
|
||||||
|
|
||||||
if /usr/bin/fdesetup isactive >/dev/null; then
|
|
||||||
test_filevault_in_use() { return 0; }
|
|
||||||
# no readonly; we may modify if user refuses from cure_volume
|
|
||||||
NIX_VOLUME_DO_ENCRYPT="${NIX_VOLUME_DO_ENCRYPT:-1}"
|
|
||||||
else
|
|
||||||
test_filevault_in_use() { return 1; }
|
|
||||||
NIX_VOLUME_DO_ENCRYPT="${NIX_VOLUME_DO_ENCRYPT:-0}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
should_encrypt_volume() {
|
|
||||||
test_filevault_in_use && (( NIX_VOLUME_DO_ENCRYPT == 1 ))
|
|
||||||
}
|
|
||||||
|
|
||||||
substep() {
|
|
||||||
printf " %s\n" "" "- $1" "" "${@:2}"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
volumes_labeled() {
|
|
||||||
local label="$1"
|
|
||||||
xsltproc --novalid --stringparam label "$label" - <(/usr/sbin/ioreg -ra -c "AppleAPFSVolume") <<'EOF'
|
|
||||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
|
||||||
<xsl:output method="text"/>
|
|
||||||
<xsl:template match="/">
|
|
||||||
<xsl:apply-templates select="/plist/array/dict/key[text()='IORegistryEntryName']/following-sibling::*[1][text()=$label]/.."/>
|
|
||||||
</xsl:template>
|
|
||||||
<xsl:template match="dict">
|
|
||||||
<xsl:apply-templates match="string" select="key[text()='BSD Name']/following-sibling::*[1]"/>
|
|
||||||
<xsl:text>=</xsl:text>
|
|
||||||
<xsl:apply-templates match="string" select="key[text()='UUID']/following-sibling::*[1]"/>
|
|
||||||
<xsl:text>
</xsl:text>
|
|
||||||
</xsl:template>
|
|
||||||
</xsl:stylesheet>
|
|
||||||
EOF
|
|
||||||
# I cut label out of the extracted values, but here it is for reference:
|
|
||||||
# <xsl:apply-templates match="string" select="key[text()='IORegistryEntryName']/following-sibling::*[1]"/>
|
|
||||||
# <xsl:text>=</xsl:text>
|
|
||||||
}
|
|
||||||
|
|
||||||
right_disk() {
|
|
||||||
local volume_special="$1" # (i.e., disk1s7)
|
|
||||||
[[ "$volume_special" == "$NIX_VOLUME_USE_DISK"s* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
right_volume() {
|
|
||||||
local volume_special="$1" # (i.e., disk1s7)
|
|
||||||
# if set, it must match; otherwise ensure it's on the right disk
|
|
||||||
if [ -z "$NIX_VOLUME_USE_SPECIAL" ]; then
|
|
||||||
if right_disk "$volume_special"; then
|
|
||||||
NIX_VOLUME_USE_SPECIAL="$volume_special" # latch on
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
[ "$volume_special" = "$NIX_VOLUME_USE_SPECIAL" ]
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
right_uuid() {
|
|
||||||
local volume_uuid="$1"
|
|
||||||
# if set, it must match; otherwise allow
|
|
||||||
if [ -z "$NIX_VOLUME_USE_UUID" ]; then
|
|
||||||
NIX_VOLUME_USE_UUID="$volume_uuid" # latch on
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
[ "$volume_uuid" = "$NIX_VOLUME_USE_UUID" ]
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
cure_volumes() {
|
|
||||||
local found volume special uuid
|
|
||||||
# loop just in case they have more than one volume
|
|
||||||
# (nothing stops you from doing this)
|
|
||||||
for volume in $(volumes_labeled "$NIX_VOLUME_LABEL"); do
|
|
||||||
# CAUTION: this could (maybe) be a more normal read
|
|
||||||
# loop like:
|
|
||||||
# while IFS== read -r special uuid; do
|
|
||||||
# # ...
|
|
||||||
# done <<<"$(volumes_labeled "$NIX_VOLUME_LABEL")"
|
|
||||||
#
|
|
||||||
# I did it with for to skirt a problem with the obvious
|
|
||||||
# pattern replacing stdin and causing user prompts
|
|
||||||
# inside (which also use read and access stdin) to skip
|
|
||||||
#
|
|
||||||
# If there's an existing encrypted volume we can't find
|
|
||||||
# in keychain, the user never gets prompted to delete
|
|
||||||
# the volume, and the install fails.
|
|
||||||
#
|
|
||||||
# If you change this, a human needs to test a very
|
|
||||||
# specific scenario: you already have an encrypted
|
|
||||||
# Nix Store volume, and have deleted its credential
|
|
||||||
# from keychain. Ensure the script asks you if it can
|
|
||||||
# delete the volume, and then prompts for your sudo
|
|
||||||
# password to confirm.
|
|
||||||
#
|
|
||||||
# shellcheck disable=SC1097
|
|
||||||
IFS== read -r special uuid <<< "$volume"
|
|
||||||
# take the first one that's on the right disk
|
|
||||||
if [ -z "${found:-}" ]; then
|
|
||||||
if right_volume "$special" && right_uuid "$uuid"; then
|
|
||||||
cure_volume "$special" "$uuid"
|
|
||||||
found="${special} (${uuid})"
|
|
||||||
else
|
|
||||||
warning <<EOF
|
|
||||||
Ignoring ${special} (${uuid}) because I am looking for:
|
|
||||||
disk=${NIX_VOLUME_USE_DISK} special=${NIX_VOLUME_USE_SPECIAL:-${NIX_VOLUME_USE_DISK}sX} uuid=${NIX_VOLUME_USE_UUID:-any}
|
|
||||||
EOF
|
|
||||||
# TODO: give chance to delete if ! headless?
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
warning <<EOF
|
|
||||||
Ignoring ${special} (${uuid}), already found target: $found
|
|
||||||
EOF
|
|
||||||
# TODO reminder? I feel like I want one
|
|
||||||
# idiom that reminds some warnings, or warns
|
|
||||||
# some reminders?
|
|
||||||
# TODO: if ! headless, chance to delete?
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [ -z "${found:-}" ]; then
|
|
||||||
readonly NIX_VOLUME_USE_SPECIAL NIX_VOLUME_USE_UUID
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_encrypted() {
|
|
||||||
local volume_special="$1" # (i.e., disk1s7)
|
|
||||||
# Trying to match the first line of output; known first lines:
|
|
||||||
# No cryptographic users for <special>
|
|
||||||
# Cryptographic user for <special> (1 found)
|
|
||||||
# Cryptographic users for <special> (2 found)
|
|
||||||
/usr/sbin/diskutil apfs listCryptoUsers -plist "$volume_special" | /usr/bin/grep -q APFSCryptoUserUUID
|
|
||||||
}
|
|
||||||
|
|
||||||
test_fstab() {
|
|
||||||
/usr/bin/grep -q "$NIX_ROOT apfs rw" /etc/fstab 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
test_nix_root_is_symlink() {
|
|
||||||
[ -L "$NIX_ROOT" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
test_synthetic_conf_either(){
|
|
||||||
/usr/bin/grep -qE "^${NIX_ROOT:1}($|\t.{3,}$)" /etc/synthetic.conf 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
test_synthetic_conf_mountable() {
|
|
||||||
/usr/bin/grep -q "^${NIX_ROOT:1}$" /etc/synthetic.conf 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
test_synthetic_conf_symlinked() {
|
|
||||||
/usr/bin/grep -qE "^${NIX_ROOT:1}\t.{3,}$" /etc/synthetic.conf 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
test_nix_volume_mountd_installed() {
|
|
||||||
test -e "$NIX_VOLUME_MOUNTD_DEST"
|
|
||||||
}
|
|
||||||
|
|
||||||
# current volume password
|
|
||||||
test_keychain_by_uuid() {
|
|
||||||
local volume_uuid="$1"
|
|
||||||
# Note: doesn't need sudo just to check; doesn't output pw
|
|
||||||
security find-generic-password -s "$volume_uuid" &>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
get_volume_pass() {
|
|
||||||
local volume_uuid="$1"
|
|
||||||
_sudo \
|
|
||||||
"to confirm keychain has a password that unlocks this volume" \
|
|
||||||
security find-generic-password -s "$volume_uuid" -w
|
|
||||||
}
|
|
||||||
|
|
||||||
verify_volume_pass() {
|
|
||||||
local volume_special="$1" # (i.e., disk1s7)
|
|
||||||
local volume_uuid="$2"
|
|
||||||
_sudo "to confirm the password actually unlocks the volume" \
|
|
||||||
/usr/sbin/diskutil apfs unlockVolume "$volume_special" -verify -stdinpassphrase -user "$volume_uuid"
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_pass_works() {
|
|
||||||
local volume_special="$1" # (i.e., disk1s7)
|
|
||||||
local volume_uuid="$2"
|
|
||||||
get_volume_pass "$volume_uuid" | verify_volume_pass "$volume_special" "$volume_uuid"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create the paths defined in synthetic.conf, saving us a reboot.
|
|
||||||
create_synthetic_objects() {
|
|
||||||
# Big Sur takes away the -B flag we were using and replaces it
|
|
||||||
# with a -t flag that appears to do the same thing (but they
|
|
||||||
# don't behave exactly the same way in terms of return values).
|
|
||||||
# This feels a little dirty, but as far as I can tell the
|
|
||||||
# simplest way to get the right one is to just throw away stderr
|
|
||||||
# and call both... :]
|
|
||||||
{
|
|
||||||
/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t || true # Big Sur
|
|
||||||
/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -B || true # Catalina
|
|
||||||
} >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
test_nix() {
|
|
||||||
test -d "$NIX_ROOT"
|
|
||||||
}
|
|
||||||
|
|
||||||
test_voldaemon() {
|
|
||||||
test -f "$NIX_VOLUME_MOUNTD_DEST"
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_mount_command() {
|
|
||||||
local cmd_type="$1" # encrypted|unencrypted
|
|
||||||
local volume_uuid mountpoint cmd=()
|
|
||||||
printf -v volume_uuid "%q" "$2"
|
|
||||||
printf -v mountpoint "%q" "$NIX_ROOT"
|
|
||||||
|
|
||||||
case "$cmd_type" in
|
|
||||||
encrypted)
|
|
||||||
cmd=(/bin/sh -c "/usr/bin/security find-generic-password -s '$volume_uuid' -w | /usr/sbin/diskutil apfs unlockVolume '$volume_uuid' -mountpoint '$mountpoint' -stdinpassphrase");;
|
|
||||||
unencrypted)
|
|
||||||
cmd=(/usr/sbin/diskutil mount -mountPoint "$mountpoint" "$volume_uuid");;
|
|
||||||
*)
|
|
||||||
failure "Invalid first arg $cmd_type to generate_mount_command";;
|
|
||||||
esac
|
|
||||||
|
|
||||||
printf " <string>%s</string>\n" "${cmd[@]}"
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_mount_daemon() {
|
|
||||||
local cmd_type="$1" # encrypted|unencrypted
|
|
||||||
local volume_uuid="$2"
|
|
||||||
cat <<EOF
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>RunAtLoad</key>
|
|
||||||
<true/>
|
|
||||||
<key>Label</key>
|
|
||||||
<string>org.nixos.darwin-store</string>
|
|
||||||
<key>ProgramArguments</key>
|
|
||||||
<array>
|
|
||||||
$(generate_mount_command "$cmd_type" "$volume_uuid")
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
_eat_bootout_err() {
|
|
||||||
/usr/bin/grep -v "Boot-out failed: 36: Operation now in progress"
|
|
||||||
}
|
|
||||||
|
|
||||||
# TODO: remove with --uninstall?
|
|
||||||
uninstall_launch_daemon_directions() {
|
|
||||||
local daemon_label="$1" # i.e., org.nixos.blah-blah
|
|
||||||
local daemon_plist="$2" # abspath
|
|
||||||
substep "Uninstall LaunchDaemon $daemon_label" \
|
|
||||||
" sudo launchctl bootout system/$daemon_label" \
|
|
||||||
" sudo rm $daemon_plist"
|
|
||||||
}
|
|
||||||
|
|
||||||
uninstall_launch_daemon_prompt() {
|
|
||||||
local daemon_label="$1" # i.e., org.nixos.blah-blah
|
|
||||||
local daemon_plist="$2" # abspath
|
|
||||||
local reason_for_daemon="$3"
|
|
||||||
cat <<EOF
|
|
||||||
|
|
||||||
The installer adds a LaunchDaemon to $reason_for_daemon: $daemon_label
|
|
||||||
EOF
|
|
||||||
if ui_confirm "Can I remove it?"; then
|
|
||||||
_sudo "to terminate the daemon" \
|
|
||||||
launchctl bootout "system/$daemon_label" 2> >(_eat_bootout_err >&2) || true
|
|
||||||
# this can "fail" with a message like:
|
|
||||||
# Boot-out failed: 36: Operation now in progress
|
|
||||||
_sudo "to remove the daemon definition" rm "$daemon_plist"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
nix_volume_mountd_uninstall_directions() {
|
|
||||||
uninstall_launch_daemon_directions "org.nixos.darwin-store" \
|
|
||||||
"$NIX_VOLUME_MOUNTD_DEST"
|
|
||||||
}
|
|
||||||
|
|
||||||
nix_volume_mountd_uninstall_prompt() {
|
|
||||||
uninstall_launch_daemon_prompt "org.nixos.darwin-store" \
|
|
||||||
"$NIX_VOLUME_MOUNTD_DEST" \
|
|
||||||
"mount your Nix volume"
|
|
||||||
}
|
|
||||||
|
|
||||||
# TODO: move nix_daemon to install-darwin-multi-user if/when uninstall_launch_daemon_prompt moves up to install-multi-user
|
|
||||||
nix_daemon_uninstall_prompt() {
|
|
||||||
uninstall_launch_daemon_prompt "org.nixos.nix-daemon" \
|
|
||||||
"$NIX_DAEMON_DEST" \
|
|
||||||
"run the nix-daemon"
|
|
||||||
}
|
|
||||||
|
|
||||||
# TODO: remove with --uninstall?
|
|
||||||
nix_daemon_uninstall_directions() {
|
|
||||||
uninstall_launch_daemon_directions "org.nixos.nix-daemon" \
|
|
||||||
"$NIX_DAEMON_DEST"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: remove with --uninstall?
|
|
||||||
synthetic_conf_uninstall_directions() {
|
|
||||||
# :1 to strip leading slash
|
|
||||||
substep "Remove ${NIX_ROOT:1} from /etc/synthetic.conf" \
|
|
||||||
" If nix is the only entry: sudo rm /etc/synthetic.conf" \
|
|
||||||
" Otherwise: sudo /usr/bin/sed -i '' -e '/^${NIX_ROOT:1}$/d' /etc/synthetic.conf"
|
|
||||||
}
|
|
||||||
|
|
||||||
synthetic_conf_uninstall_prompt() {
|
|
||||||
cat <<EOF
|
|
||||||
|
|
||||||
During install, I add '${NIX_ROOT:1}' to /etc/synthetic.conf, which instructs
|
|
||||||
macOS to create an empty root directory for mounting the Nix volume.
|
|
||||||
EOF
|
|
||||||
# make the edit to a copy
|
|
||||||
/usr/bin/grep -vE "^${NIX_ROOT:1}($|\t.{3,}$)" /etc/synthetic.conf > "$SCRATCH/synthetic.conf.edit"
|
|
||||||
|
|
||||||
if test_synthetic_conf_symlinked; then
|
|
||||||
warning <<EOF
|
|
||||||
|
|
||||||
/etc/synthetic.conf already contains a line instructing your system
|
|
||||||
to make '${NIX_ROOT}' as a symlink:
|
|
||||||
$(/usr/bin/grep -nE "^${NIX_ROOT:1}\t.{3,}$" /etc/synthetic.conf)
|
|
||||||
|
|
||||||
This may mean your system has/had a non-standard Nix install.
|
|
||||||
|
|
||||||
The volume-creation process in this installer is *not* compatible
|
|
||||||
with a symlinked store, so I'll have to remove this instruction to
|
|
||||||
continue.
|
|
||||||
|
|
||||||
If you want/need to keep this instruction, answer 'n' to abort.
|
|
||||||
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ask to rm if this left the file empty aside from comments, else edit
|
|
||||||
if /usr/bin/diff -q <(:) <(/usr/bin/grep -v "^#" "$SCRATCH/synthetic.conf.edit") &>/dev/null; then
|
|
||||||
if confirm_rm "/etc/synthetic.conf"; then
|
|
||||||
if test_nix_root_is_symlink; then
|
|
||||||
failure >&2 <<EOF
|
|
||||||
I removed /etc/synthetic.conf, but $NIX_ROOT is already a symlink
|
|
||||||
(-> $(readlink "$NIX_ROOT")). The system should remove it when you reboot.
|
|
||||||
Once you've rebooted, run the installer again.
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if confirm_edit "$SCRATCH/synthetic.conf.edit" "/etc/synthetic.conf"; then
|
|
||||||
if test_nix_root_is_symlink; then
|
|
||||||
failure >&2 <<EOF
|
|
||||||
I edited Nix out of /etc/synthetic.conf, but $NIX_ROOT is already a symlink
|
|
||||||
(-> $(readlink "$NIX_ROOT")). The system should remove it when you reboot.
|
|
||||||
Once you've rebooted, run the installer again.
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
# fallback instructions
|
|
||||||
echo "Manually remove nix from /etc/synthetic.conf"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
add_nix_vol_fstab_line() {
|
|
||||||
local uuid="$1"
|
|
||||||
# shellcheck disable=SC1003,SC2026
|
|
||||||
local escaped_mountpoint="${NIX_ROOT/ /'\\\'040}"
|
|
||||||
shift
|
|
||||||
|
|
||||||
# wrap `ex` to work around problems w/ vim features breaking exit codes
|
|
||||||
# - plugins (see github.com/NixOS/nix/issues/5468): -u NONE
|
|
||||||
# - swap file: -n
|
|
||||||
#
|
|
||||||
# the first draft used `--noplugin`, but github.com/NixOS/nix/issues/6462
|
|
||||||
# suggests we need the less-semantic `-u NONE`
|
|
||||||
#
|
|
||||||
# we'd prefer EDITOR="/usr/bin/ex -u NONE" but vifs doesn't word-split
|
|
||||||
# the EDITOR env.
|
|
||||||
#
|
|
||||||
# TODO: at some point we should switch to `--clean`, but it wasn't added
|
|
||||||
# until https://github.com/vim/vim/releases/tag/v8.0.1554 while the macOS
|
|
||||||
# minver 10.12.6 seems to have released with vim 7.4
|
|
||||||
cat > "$SCRATCH/ex_cleanroom_wrapper" <<EOF
|
|
||||||
#!/bin/sh
|
|
||||||
/usr/bin/ex -u NONE -n "\$@"
|
|
||||||
EOF
|
|
||||||
chmod 755 "$SCRATCH/ex_cleanroom_wrapper"
|
|
||||||
|
|
||||||
EDITOR="$SCRATCH/ex_cleanroom_wrapper" _sudo "to add nix to fstab" "$@" <<EOF
|
|
||||||
:a
|
|
||||||
UUID=$uuid $escaped_mountpoint apfs rw,noauto,nobrowse,suid,owners
|
|
||||||
.
|
|
||||||
:x
|
|
||||||
EOF
|
|
||||||
# TODO: preserving my notes on suid,owners above until resolved
|
|
||||||
# There *may* be some issue regarding volume ownership, see nix#3156
|
|
||||||
#
|
|
||||||
# It seems like the cheapest fix is adding "suid,owners" to fstab, but:
|
|
||||||
# - We don't have much info on this condition yet
|
|
||||||
# - I'm not certain if these cause other problems?
|
|
||||||
# - There's a "chown" component some people claim to need to fix this
|
|
||||||
# that I don't understand yet
|
|
||||||
# (Note however that I've had to add a chown step to handle
|
|
||||||
# single->multi-user reinstalls, which may cover this)
|
|
||||||
#
|
|
||||||
# I'm not sure if it's safe to approach this way?
|
|
||||||
#
|
|
||||||
# I think I think the most-proper way to test for it is:
|
|
||||||
# diskutil info -plist "$NIX_VOLUME_LABEL" | xmllint --xpath "(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1][name()='true']" -; echo $?
|
|
||||||
#
|
|
||||||
# There's also `sudo /usr/sbin/vsdbutil -c /path` (which is much faster, but is also
|
|
||||||
# deprecated and needs minor parsing).
|
|
||||||
#
|
|
||||||
# If no one finds a problem with doing so, I think the simplest approach
|
|
||||||
# is to just eagerly set this. I found a few imperative approaches:
|
|
||||||
# (diskutil enableOwnership, ~100ms), a cheap one (/usr/sbin/vsdbutil -a, ~40-50ms),
|
|
||||||
# a very cheap one (append the internal format to /var/db/volinfo.database).
|
|
||||||
#
|
|
||||||
# But vsdbutil's deprecation notice suggests using fstab, so I want to
|
|
||||||
# give that a whirl first.
|
|
||||||
#
|
|
||||||
# TODO: when this is workable, poke infinisil about reproducing the issue
|
|
||||||
# and confirming this fix?
|
|
||||||
}
|
|
||||||
|
|
||||||
delete_nix_vol_fstab_line() {
|
|
||||||
# TODO: I'm scaffolding this to handle the new nix volumes
|
|
||||||
# but it might be nice to generalize a smidge further to
|
|
||||||
# go ahead and set up a pattern for curing "old" things
|
|
||||||
# we no longer do?
|
|
||||||
EDITOR="/usr/bin/patch" _sudo "to cut nix from fstab" "$@" < <(/usr/bin/diff /etc/fstab <(/usr/bin/grep -v "$NIX_ROOT apfs rw" /etc/fstab))
|
|
||||||
# leaving some parts out of the grep; people may fiddle this a little?
|
|
||||||
}
|
|
||||||
|
|
||||||
# TODO: hope to remove with --uninstall
|
|
||||||
fstab_uninstall_directions() {
|
|
||||||
substep "Remove ${NIX_ROOT} from /etc/fstab" \
|
|
||||||
" If nix is the only entry: sudo rm /etc/fstab" \
|
|
||||||
" Otherwise, run 'sudo /usr/sbin/vifs' to remove the nix line"
|
|
||||||
}
|
|
||||||
|
|
||||||
fstab_uninstall_prompt() {
|
|
||||||
cat <<EOF
|
|
||||||
During install, I add '${NIX_ROOT}' to /etc/fstab so that macOS knows what
|
|
||||||
mount options to use for the Nix volume.
|
|
||||||
EOF
|
|
||||||
cp /etc/fstab "$SCRATCH/fstab.edit"
|
|
||||||
# technically doesn't need the _sudo path, but throwing away the
|
|
||||||
# output is probably better than mostly-duplicating the code...
|
|
||||||
delete_nix_vol_fstab_line patch "$SCRATCH/fstab.edit" &>/dev/null
|
|
||||||
|
|
||||||
# if the patch test edit, minus comment lines, is equal to empty (:)
|
|
||||||
if /usr/bin/diff -q <(:) <(/usr/bin/grep -v "^#" "$SCRATCH/fstab.edit") &>/dev/null; then
|
|
||||||
# this edit would leave it empty; propose deleting it
|
|
||||||
if confirm_rm "/etc/fstab"; then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
echo "Remove nix from /etc/fstab (or remove the file)"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "I might be able to help you make this edit. Here's the diff:"
|
|
||||||
if ! _diff "/etc/fstab" "$SCRATCH/fstab.edit" && ui_confirm "Does the change above look right?"; then
|
|
||||||
delete_nix_vol_fstab_line /usr/sbin/vifs
|
|
||||||
else
|
|
||||||
echo "Remove nix from /etc/fstab (or remove the file)"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_volume() {
|
|
||||||
local volume_special="$1" # (i.e., disk1s7)
|
|
||||||
_sudo "to unmount the Nix volume" \
|
|
||||||
/usr/sbin/diskutil unmount force "$volume_special" || true # might not be mounted
|
|
||||||
_sudo "to delete the Nix volume" \
|
|
||||||
/usr/sbin/diskutil apfs deleteVolume "$volume_special"
|
|
||||||
}
|
|
||||||
|
|
||||||
# aspiration: robust enough to both fix problems
|
|
||||||
# *and* update older darwin volumes
|
|
||||||
cure_volume() {
|
|
||||||
local volume_special="$1" # (i.e., disk1s7)
|
|
||||||
local volume_uuid="$2"
|
|
||||||
header "Found existing Nix volume"
|
|
||||||
row " special" "$volume_special"
|
|
||||||
row " uuid" "$volume_uuid"
|
|
||||||
|
|
||||||
if volume_encrypted "$volume_special"; then
|
|
||||||
row "encrypted" "yes"
|
|
||||||
if volume_pass_works "$volume_special" "$volume_uuid"; then
|
|
||||||
NIX_VOLUME_DO_ENCRYPT=0
|
|
||||||
ok "Found a working decryption password in keychain :)"
|
|
||||||
echo ""
|
|
||||||
else
|
|
||||||
# - this is a volume we made, and
|
|
||||||
# - the user encrypted it on their own
|
|
||||||
# - something deleted the credential
|
|
||||||
# - this is an old or BYO volume and the pw
|
|
||||||
# just isn't somewhere we can find it.
|
|
||||||
#
|
|
||||||
# We're going to explain why we're freaking out
|
|
||||||
# and prompt them to either delete the volume
|
|
||||||
# (requiring a sudo auth), or abort to fix
|
|
||||||
warning <<EOF
|
|
||||||
|
|
||||||
This volume is encrypted, but I don't see a password to decrypt it.
|
|
||||||
The quick fix is to let me delete this volume and make you a new one.
|
|
||||||
If that's okay, enter your (sudo) password to continue. If not, you
|
|
||||||
can ensure the decryption password is in your system keychain with a
|
|
||||||
"Where" (service) field set to this volume's UUID:
|
|
||||||
$volume_uuid
|
|
||||||
EOF
|
|
||||||
if password_confirm "delete this volume"; then
|
|
||||||
remove_volume "$volume_special"
|
|
||||||
else
|
|
||||||
# TODO: this is a good design case for a warn-and
|
|
||||||
# remind idiom...
|
|
||||||
failure <<EOF
|
|
||||||
Your Nix volume is encrypted, but I couldn't find its password. Either:
|
|
||||||
- Delete or rename the volume out of the way
|
|
||||||
- Ensure its decryption password is in the system keychain with a
|
|
||||||
"Where" (service) field set to this volume's UUID:
|
|
||||||
$volume_uuid
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
elif test_filevault_in_use; then
|
|
||||||
row "encrypted" "no"
|
|
||||||
warning <<EOF
|
|
||||||
FileVault is on, but your $NIX_VOLUME_LABEL volume isn't encrypted.
|
|
||||||
EOF
|
|
||||||
# if we're interactive, give them a chance to
|
|
||||||
# encrypt the volume. If not, /shrug
|
|
||||||
if ! headless && (( NIX_VOLUME_DO_ENCRYPT == 1 )); then
|
|
||||||
if ui_confirm "Should I encrypt it and add the decryption key to your keychain?"; then
|
|
||||||
encrypt_volume "$volume_uuid" "$NIX_VOLUME_LABEL"
|
|
||||||
NIX_VOLUME_DO_ENCRYPT=0
|
|
||||||
else
|
|
||||||
NIX_VOLUME_DO_ENCRYPT=0
|
|
||||||
reminder "FileVault is on, but your $NIX_VOLUME_LABEL volume isn't encrypted."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
row "encrypted" "no"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_volume_artifacts() {
|
|
||||||
if test_synthetic_conf_either; then
|
|
||||||
# NIX_ROOT is in synthetic.conf
|
|
||||||
if synthetic_conf_uninstall_prompt; then
|
|
||||||
# TODO: moot until we tackle uninstall, but when we're
|
|
||||||
# actually uninstalling, we should issue:
|
|
||||||
# reminder "macOS will clean up the empty mount-point directory at $NIX_ROOT on reboot."
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if test_fstab; then
|
|
||||||
fstab_uninstall_prompt
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test_nix_volume_mountd_installed; then
|
|
||||||
nix_volume_mountd_uninstall_prompt
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_synthetic_conf() {
|
|
||||||
if test_nix_root_is_symlink; then
|
|
||||||
if ! test_synthetic_conf_symlinked; then
|
|
||||||
failure >&2 <<EOF
|
|
||||||
error: $NIX_ROOT is a symlink (-> $(readlink "$NIX_ROOT")).
|
|
||||||
Please remove it. If nix is in /etc/synthetic.conf, remove it and reboot.
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if ! test_synthetic_conf_mountable; then
|
|
||||||
task "Configuring /etc/synthetic.conf to make a mount-point at $NIX_ROOT" >&2
|
|
||||||
# technically /etc/synthetic.d/nix is supported in Big Sur+
|
|
||||||
# but handling both takes even more code...
|
|
||||||
# See earlier note; `-u NONE` disables vim plugins/rc, `-n` skips swapfile
|
|
||||||
_sudo "to add Nix to /etc/synthetic.conf" \
|
|
||||||
/usr/bin/ex -u NONE -n /etc/synthetic.conf <<EOF
|
|
||||||
:a
|
|
||||||
${NIX_ROOT:1}
|
|
||||||
.
|
|
||||||
:x
|
|
||||||
EOF
|
|
||||||
if ! test_synthetic_conf_mountable; then
|
|
||||||
failure "error: failed to configure synthetic.conf" >&2
|
|
||||||
fi
|
|
||||||
create_synthetic_objects
|
|
||||||
if ! test_nix; then
|
|
||||||
failure >&2 <<EOF
|
|
||||||
error: failed to bootstrap $NIX_ROOT
|
|
||||||
If you enabled FileVault after booting, this is likely a known issue
|
|
||||||
with macOS that you'll have to reboot to fix. If you didn't enable FV,
|
|
||||||
though, please open an issue describing how the system that you see
|
|
||||||
this error on was set up.
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_fstab() {
|
|
||||||
local volume_uuid="$1"
|
|
||||||
# fstab used to be responsible for mounting the volume. Now the last
|
|
||||||
# step adds a LaunchDaemon responsible for mounting. This is technically
|
|
||||||
# redundant for mounting, but diskutil appears to pick up mount options
|
|
||||||
# from fstab (and diskutil's support for specifying them directly is not
|
|
||||||
# consistent across versions/subcommands).
|
|
||||||
if ! test_fstab; then
|
|
||||||
task "Configuring /etc/fstab to specify volume mount options" >&2
|
|
||||||
add_nix_vol_fstab_line "$volume_uuid" /usr/sbin/vifs
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
encrypt_volume() {
|
|
||||||
local volume_uuid="$1"
|
|
||||||
local volume_label="$2"
|
|
||||||
local password
|
|
||||||
|
|
||||||
task "Encrypt the Nix volume" >&2
|
|
||||||
|
|
||||||
# Note: mount/unmount are late additions to support the right order
|
|
||||||
# of operations for creating the volume and then baking its uuid into
|
|
||||||
# other artifacts; not as well-trod wrt to potential errors, race
|
|
||||||
# conditions, etc.
|
|
||||||
|
|
||||||
_sudo "to mount your Nix volume for encrypting" \
|
|
||||||
/usr/sbin/diskutil mount "$volume_label"
|
|
||||||
|
|
||||||
password="$(/usr/bin/xxd -l 32 -p -c 256 /dev/random)"
|
|
||||||
_sudo "to add your Nix volume's password to Keychain" \
|
|
||||||
/usr/bin/security -i <<EOF
|
|
||||||
add-generic-password -a "$volume_label" -s "$volume_uuid" -l "$volume_label encryption password" -D "Encrypted volume password" -j "Added automatically by the Nix installer for use by $NIX_VOLUME_MOUNTD_DEST" -w "$password" -T /System/Library/CoreServices/APFSUserAgent -T /System/Library/CoreServices/CSUserAgent -T /usr/bin/security "/Library/Keychains/System.keychain"
|
|
||||||
EOF
|
|
||||||
builtin printf "%s" "$password" | _sudo "to actually encrypt your Nix volume" \
|
|
||||||
/usr/sbin/diskutil apfs encryptVolume "$volume_label" -user disk -stdinpassphrase
|
|
||||||
|
|
||||||
_sudo "to unmount the encrypted volume" \
|
|
||||||
/usr/sbin/diskutil unmount force "$volume_label"
|
|
||||||
}
|
|
||||||
|
|
||||||
create_volume() {
|
|
||||||
# Notes:
|
|
||||||
# 1) using `-nomount` instead of `-mountpoint "$NIX_ROOT"` to get
|
|
||||||
# its UUID and set mount opts in fstab before first mount
|
|
||||||
#
|
|
||||||
# 2) system is in some sense less secure than user keychain... (it's
|
|
||||||
# possible to read the password for decrypting the keychain) but
|
|
||||||
# the user keychain appears to be available too late. As far as I
|
|
||||||
# can tell, the file with this password (/var/db/SystemKey) is
|
|
||||||
# inside the FileVault envelope. If that isn't true, it may make
|
|
||||||
# sense to store the password inside the envelope?
|
|
||||||
#
|
|
||||||
# 3) At some point it would be ideal to have a small binary to serve
|
|
||||||
# as the daemon itself, and for it to replace /usr/bin/security here.
|
|
||||||
#
|
|
||||||
# 4) *UserAgent exemptions should let the system seamlessly supply the
|
|
||||||
# password if noauto is removed from fstab entry. This is intentional;
|
|
||||||
# the user will hopefully look for help if the volume stops mounting,
|
|
||||||
# rather than failing over into subtle race-condition problems.
|
|
||||||
#
|
|
||||||
# 5) If we ever get users griping about not having space to do
|
|
||||||
# anything useful with Nix, it is possibly to specify
|
|
||||||
# `-reserve 10g` or something, which will fail w/o that much
|
|
||||||
#
|
|
||||||
# 6) getting special w/ awk may be fragile, but doing it to:
|
|
||||||
# - save time over running slow diskutil commands
|
|
||||||
# - skirt risk we grab wrong volume if multiple match
|
|
||||||
_sudo "to create a new APFS volume '$NIX_VOLUME_LABEL' on $NIX_VOLUME_USE_DISK" \
|
|
||||||
/usr/sbin/diskutil apfs addVolume "$NIX_VOLUME_USE_DISK" "$NIX_VOLUME_FS" "$NIX_VOLUME_LABEL" -nomount | /usr/bin/awk '/Created new APFS Volume/ {print $5}'
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_uuid_from_special() {
|
|
||||||
local volume_special="$1" # (i.e., disk1s7)
|
|
||||||
# For reasons I won't pretend to fathom, this returns 253 when it works
|
|
||||||
/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -k "$volume_special" || true
|
|
||||||
}
|
|
||||||
|
|
||||||
# this sometimes clears immediately, and AFAIK clears
|
|
||||||
# within about 1s. diskutil info on an unmounted path
|
|
||||||
# fails in around 50-100ms and a match takes about
|
|
||||||
# 250-300ms. I suspect it's usually ~250-750ms
|
|
||||||
await_volume() {
|
|
||||||
# caution: this could, in theory, get stuck
|
|
||||||
until /usr/sbin/diskutil info "$NIX_ROOT" &>/dev/null; do
|
|
||||||
:
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_volume() {
|
|
||||||
local use_special use_uuid profile_packages
|
|
||||||
task "Creating a Nix volume" >&2
|
|
||||||
|
|
||||||
use_special="${NIX_VOLUME_USE_SPECIAL:-$(create_volume)}"
|
|
||||||
|
|
||||||
_sudo "to ensure the Nix volume is not mounted" \
|
|
||||||
/usr/sbin/diskutil unmount force "$use_special" || true # might not be mounted
|
|
||||||
|
|
||||||
use_uuid=${NIX_VOLUME_USE_UUID:-$(volume_uuid_from_special "$use_special")}
|
|
||||||
|
|
||||||
setup_fstab "$use_uuid"
|
|
||||||
|
|
||||||
if should_encrypt_volume; then
|
|
||||||
encrypt_volume "$use_uuid" "$NIX_VOLUME_LABEL"
|
|
||||||
setup_volume_daemon "encrypted" "$use_uuid"
|
|
||||||
# TODO: might be able to save ~60ms by caching or setting
|
|
||||||
# this somewhere rather than re-checking here.
|
|
||||||
elif volume_encrypted "$use_special"; then
|
|
||||||
setup_volume_daemon "encrypted" "$use_uuid"
|
|
||||||
else
|
|
||||||
setup_volume_daemon "unencrypted" "$use_uuid"
|
|
||||||
fi
|
|
||||||
|
|
||||||
await_volume
|
|
||||||
|
|
||||||
if [ "$(/usr/sbin/diskutil info -plist "$NIX_ROOT" | xmllint --xpath "(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1]" -)" = "<false/>" ]; then
|
|
||||||
_sudo "to set enableOwnership (enabling users to own files)" \
|
|
||||||
/usr/sbin/diskutil enableOwnership "$NIX_ROOT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# TODO: below is a vague kludge for now; I just don't know
|
|
||||||
# what if any safe action there is to take here. Also, the
|
|
||||||
# reminder isn't very helpful.
|
|
||||||
# I'm less sure where this belongs, but it also wants mounted, pre-install
|
|
||||||
if type -p nix-env; then
|
|
||||||
profile_packages="$(nix-env --query --installed)"
|
|
||||||
# TODO: can probably do below faster w/ read
|
|
||||||
# intentionally unquoted string to eat whitespace in wc output
|
|
||||||
# shellcheck disable=SC2046,SC2059
|
|
||||||
if ! [ $(printf "$profile_packages" | /usr/bin/wc -l) = "0" ]; then
|
|
||||||
reminder <<EOF
|
|
||||||
Nix now supports only multi-user installs on Darwin/macOS, and your user's
|
|
||||||
Nix profile has some packages in it. These packages may obscure those in the
|
|
||||||
default profile, including the Nix this installer will add. You should
|
|
||||||
review these packages:
|
|
||||||
$profile_packages
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_volume_daemon() {
|
|
||||||
local cmd_type="$1" # encrypted|unencrypted
|
|
||||||
local volume_uuid="$2"
|
|
||||||
if ! test_voldaemon; then
|
|
||||||
task "Configuring LaunchDaemon to mount '$NIX_VOLUME_LABEL'" >&2
|
|
||||||
# See earlier note; `-u NONE` disables vim plugins/rc, `-n` skips swapfile
|
|
||||||
_sudo "to install the Nix volume mounter" /usr/bin/ex -u NONE -n "$NIX_VOLUME_MOUNTD_DEST" <<EOF
|
|
||||||
:a
|
|
||||||
$(generate_mount_daemon "$cmd_type" "$volume_uuid")
|
|
||||||
.
|
|
||||||
:x
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# TODO: should probably alert the user if this is disabled?
|
|
||||||
_sudo "to launch the Nix volume mounter" \
|
|
||||||
launchctl bootstrap system "$NIX_VOLUME_MOUNTD_DEST" || true
|
|
||||||
# TODO: confirm whether kickstart is necessesary?
|
|
||||||
# I feel a little superstitous, but it can guard
|
|
||||||
# against multiple problems (doesn't start, old
|
|
||||||
# version still running for some reason...)
|
|
||||||
_sudo "to launch the Nix volume mounter" \
|
|
||||||
launchctl kickstart -k system/org.nixos.darwin-store
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_darwin_volume() {
|
|
||||||
setup_synthetic_conf
|
|
||||||
setup_volume
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ "$_CREATE_VOLUME_NO_MAIN" = 1 ]; then
|
|
||||||
if [ -n "$*" ]; then
|
|
||||||
"$@" # expose functions in case we want multiple routines?
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# no reason to pay for bash to process this
|
|
||||||
main() {
|
|
||||||
{
|
|
||||||
echo ""
|
|
||||||
echo " ------------------------------------------------------------------ "
|
|
||||||
echo " | This installer will create a volume for the nix store and |"
|
|
||||||
echo " | configure it to mount at $NIX_ROOT. Follow these steps to uninstall. |"
|
|
||||||
echo " ------------------------------------------------------------------ "
|
|
||||||
echo ""
|
|
||||||
echo " 1. Remove the entry from fstab using 'sudo /usr/sbin/vifs'"
|
|
||||||
echo " 2. Run 'sudo launchctl bootout system/org.nixos.darwin-store'"
|
|
||||||
echo " 3. Remove $NIX_VOLUME_MOUNTD_DEST"
|
|
||||||
echo " 4. Destroy the data volume using '/usr/sbin/diskutil apfs deleteVolume'"
|
|
||||||
echo " 5. Remove the 'nix' line from /etc/synthetic.conf (or the file)"
|
|
||||||
echo ""
|
|
||||||
} >&2
|
|
||||||
|
|
||||||
setup_darwin_volume
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
fi
|
|
|
@ -1,226 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
# System specific settings
|
|
||||||
export NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-301}"
|
|
||||||
export NIX_BUILD_USER_NAME_TEMPLATE="_nixbld%d"
|
|
||||||
|
|
||||||
readonly NIX_DAEMON_DEST=/Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
|
||||||
# create by default; set 0 to DIY, use a symlink, etc.
|
|
||||||
readonly NIX_VOLUME_CREATE=${NIX_VOLUME_CREATE:-1} # now default
|
|
||||||
|
|
||||||
# caution: may update times on / if not run as normal non-root user
|
|
||||||
read_only_root() {
|
|
||||||
# this touch command ~should~ always produce an error
|
|
||||||
# as of this change I confirmed /usr/bin/touch emits:
|
|
||||||
# "touch: /: Operation not permitted" Monterey
|
|
||||||
# "touch: /: Read-only file system" Catalina+ and Big Sur
|
|
||||||
# "touch: /: Permission denied" Mojave
|
|
||||||
# (not matching prefix for compat w/ coreutils touch in case using
|
|
||||||
# an explicit path causes problems; its prefix differs)
|
|
||||||
case "$(/usr/bin/touch / 2>&1)" in
|
|
||||||
*"Read-only file system") # Catalina, Big Sur
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
*"Operation not permitted") # Monterey
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Avoiding the slow semantic way to get this information (~330ms vs ~8ms)
|
|
||||||
# unless using touch causes problems. Just in case, that approach is:
|
|
||||||
# diskutil info -plist / | <find the Writable or WritableVolume keys>, i.e.
|
|
||||||
# diskutil info -plist / | xmllint --xpath "name(/plist/dict/key[text()='Writable']/following-sibling::*[1])" -
|
|
||||||
}
|
|
||||||
|
|
||||||
if read_only_root && [ "$NIX_VOLUME_CREATE" = 1 ]; then
|
|
||||||
should_create_volume() { return 0; }
|
|
||||||
else
|
|
||||||
should_create_volume() { return 1; }
|
|
||||||
fi
|
|
||||||
|
|
||||||
# shellcheck source=./create-darwin-volume.sh
|
|
||||||
. "$EXTRACTED_NIX_PATH/create-darwin-volume.sh" "no-main"
|
|
||||||
|
|
||||||
dsclattr() {
|
|
||||||
/usr/bin/dscl . -read "$1" \
|
|
||||||
| /usr/bin/awk "/$2/ { print \$2 }"
|
|
||||||
}
|
|
||||||
|
|
||||||
test_nix_daemon_installed() {
|
|
||||||
test -e "$NIX_DAEMON_DEST"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_cure_artifacts() {
|
|
||||||
if should_create_volume; then
|
|
||||||
task "Fixing any leftover Nix volume state"
|
|
||||||
cat <<EOF
|
|
||||||
Before I try to install, I'll check for any existing Nix volume config
|
|
||||||
and ask for your permission to remove it (so that the installer can
|
|
||||||
start fresh). I'll also ask for permission to fix any issues I spot.
|
|
||||||
EOF
|
|
||||||
cure_volumes
|
|
||||||
remove_volume_artifacts
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_service_installed_check() {
|
|
||||||
if should_create_volume; then
|
|
||||||
test_nix_daemon_installed || test_nix_volume_mountd_installed
|
|
||||||
else
|
|
||||||
test_nix_daemon_installed
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_service_uninstall_directions() {
|
|
||||||
echo "$1. Remove macOS-specific components:"
|
|
||||||
if should_create_volume && test_nix_volume_mountd_installed; then
|
|
||||||
nix_volume_mountd_uninstall_directions
|
|
||||||
fi
|
|
||||||
if test_nix_daemon_installed; then
|
|
||||||
nix_daemon_uninstall_directions
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_service_setup_note() {
|
|
||||||
if should_create_volume; then
|
|
||||||
echo " - create a Nix volume and a LaunchDaemon to mount it"
|
|
||||||
fi
|
|
||||||
echo " - create a LaunchDaemon (at $NIX_DAEMON_DEST) for nix-daemon"
|
|
||||||
echo ""
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_extra_try_me_commands() {
|
|
||||||
:
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_configure_nix_daemon_service() {
|
|
||||||
task "Setting up the nix-daemon LaunchDaemon"
|
|
||||||
_sudo "to set up the nix-daemon as a LaunchDaemon" \
|
|
||||||
/usr/bin/install -m "u=rw,go=r" "/nix/var/nix/profiles/default$NIX_DAEMON_DEST" "$NIX_DAEMON_DEST"
|
|
||||||
|
|
||||||
_sudo "to load the LaunchDaemon plist for nix-daemon" \
|
|
||||||
launchctl load /Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
|
||||||
|
|
||||||
_sudo "to start the nix-daemon" \
|
|
||||||
launchctl kickstart -k system/org.nixos.nix-daemon
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_group_exists() {
|
|
||||||
/usr/bin/dscl . -read "/Groups/$1" > /dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_group_id_get() {
|
|
||||||
dsclattr "/Groups/$1" "PrimaryGroupID"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_create_build_group() {
|
|
||||||
_sudo "Create the Nix build group, $NIX_BUILD_GROUP_NAME" \
|
|
||||||
/usr/sbin/dseditgroup -o create \
|
|
||||||
-r "Nix build group for nix-daemon" \
|
|
||||||
-i "$NIX_BUILD_GROUP_ID" \
|
|
||||||
"$NIX_BUILD_GROUP_NAME" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_exists() {
|
|
||||||
/usr/bin/dscl . -read "/Users/$1" > /dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_id_get() {
|
|
||||||
dsclattr "/Users/$1" "UniqueID"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_hidden_get() {
|
|
||||||
dsclattr "/Users/$1" "IsHidden"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_hidden_set() {
|
|
||||||
_sudo "in order to make $1 a hidden user" \
|
|
||||||
/usr/bin/dscl . -create "/Users/$1" "IsHidden" "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_home_get() {
|
|
||||||
dsclattr "/Users/$1" "NFSHomeDirectory"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_home_set() {
|
|
||||||
# This can trigger a permission prompt now:
|
|
||||||
# "Terminal" would like to administer your computer. Administration can include modifying passwords, networking, and system settings.
|
|
||||||
_sudo "in order to give $1 a safe home directory" \
|
|
||||||
/usr/bin/dscl . -create "/Users/$1" "NFSHomeDirectory" "$2"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_note_get() {
|
|
||||||
dsclattr "/Users/$1" "RealName"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_note_set() {
|
|
||||||
_sudo "in order to give $username a useful note" \
|
|
||||||
/usr/bin/dscl . -create "/Users/$1" "RealName" "$2"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_shell_get() {
|
|
||||||
dsclattr "/Users/$1" "UserShell"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_shell_set() {
|
|
||||||
_sudo "in order to give $1 a safe shell" \
|
|
||||||
/usr/bin/dscl . -create "/Users/$1" "UserShell" "$2"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_in_group_check() {
|
|
||||||
username=$1
|
|
||||||
group=$2
|
|
||||||
/usr/sbin/dseditgroup -o checkmember -m "$username" "$group" > /dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_in_group_set() {
|
|
||||||
username=$1
|
|
||||||
group=$2
|
|
||||||
|
|
||||||
_sudo "Add $username to the $group group"\
|
|
||||||
/usr/sbin/dseditgroup -o edit -t user \
|
|
||||||
-a "$username" "$group"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_primary_group_get() {
|
|
||||||
dsclattr "/Users/$1" "PrimaryGroupID"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_primary_group_set() {
|
|
||||||
_sudo "to let the nix daemon use this user for builds (this might seem redundant, but there are two concepts of group membership)" \
|
|
||||||
/usr/bin/dscl . -create "/Users/$1" "PrimaryGroupID" "$2"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_create_build_user() {
|
|
||||||
username=$1
|
|
||||||
uid=$2
|
|
||||||
builder_num=$3
|
|
||||||
|
|
||||||
_sudo "Creating the Nix build user (#$builder_num), $username" \
|
|
||||||
/usr/bin/dscl . create "/Users/$username" \
|
|
||||||
UniqueID "${uid}"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_prepare_to_install() {
|
|
||||||
if should_create_volume; then
|
|
||||||
header "Preparing a Nix volume"
|
|
||||||
# intentional indent below to match task indent
|
|
||||||
cat <<EOF
|
|
||||||
Nix traditionally stores its data in the root directory $NIX_ROOT, but
|
|
||||||
macOS now (starting in 10.15 Catalina) has a read-only root directory.
|
|
||||||
To support Nix, I will create a volume and configure macOS to mount it
|
|
||||||
at $NIX_ROOT.
|
|
||||||
EOF
|
|
||||||
setup_darwin_volume
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$(/usr/sbin/diskutil info -plist /nix | xmllint --xpath "(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1]" -)" = "<false/>" ]; then
|
|
||||||
failure "This script needs a /nix volume with global permissions! This may require running sudo /usr/sbin/diskutil enableOwnership /nix."
|
|
||||||
fi
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,284 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
umask 0022
|
|
||||||
|
|
||||||
dest="/nix"
|
|
||||||
self="$(dirname "$0")"
|
|
||||||
nix="@nix@"
|
|
||||||
cacert="@cacert@"
|
|
||||||
|
|
||||||
|
|
||||||
if ! [ -e "$self/.reginfo" ]; then
|
|
||||||
echo "$0: incomplete installer (.reginfo is missing)" >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$USER" ] && ! USER=$(id -u -n); then
|
|
||||||
echo "$0: \$USER is not set" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$HOME" ]; then
|
|
||||||
echo "$0: \$HOME is not set" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# macOS support for 10.12.6 or higher
|
|
||||||
if [ "$(uname -s)" = "Darwin" ]; then
|
|
||||||
IFS='.' read -r macos_major macos_minor macos_patch << EOF
|
|
||||||
$(sw_vers -productVersion)
|
|
||||||
EOF
|
|
||||||
if [ "$macos_major" -lt 10 ] || { [ "$macos_major" -eq 10 ] && [ "$macos_minor" -lt 12 ]; } || { [ "$macos_minor" -eq 12 ] && [ "$macos_patch" -lt 6 ]; }; then
|
|
||||||
# patch may not be present; command substitution for simplicity
|
|
||||||
echo "$0: macOS $(sw_vers -productVersion) is not supported, upgrade to 10.12.6 or higher"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Determine if we could use the multi-user installer or not
|
|
||||||
if [ "$(uname -s)" = "Linux" ]; then
|
|
||||||
echo "Note: a multi-user installation is possible. See https://nixos.org/manual/nix/stable/installation/installing-binary.html#multi-user-installation" >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$(uname -s)" in
|
|
||||||
"Darwin")
|
|
||||||
INSTALL_MODE=daemon;;
|
|
||||||
*)
|
|
||||||
INSTALL_MODE=no-daemon;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# space-separated string
|
|
||||||
ACTIONS=
|
|
||||||
|
|
||||||
# handle the command line flags
|
|
||||||
while [ $# -gt 0 ]; do
|
|
||||||
case $1 in
|
|
||||||
--daemon)
|
|
||||||
INSTALL_MODE=daemon
|
|
||||||
ACTIONS="${ACTIONS}install "
|
|
||||||
;;
|
|
||||||
--no-daemon)
|
|
||||||
if [ "$(uname -s)" = "Darwin" ]; then
|
|
||||||
printf '\e[1;31mError: --no-daemon installs are no-longer supported on Darwin/macOS!\e[0m\n' >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
INSTALL_MODE=no-daemon
|
|
||||||
# intentional tail space
|
|
||||||
ACTIONS="${ACTIONS}install "
|
|
||||||
;;
|
|
||||||
# --uninstall)
|
|
||||||
# # intentional tail space
|
|
||||||
# ACTIONS="${ACTIONS}uninstall "
|
|
||||||
# ;;
|
|
||||||
--yes)
|
|
||||||
export NIX_INSTALLER_YES=1;;
|
|
||||||
--no-channel-add)
|
|
||||||
export NIX_INSTALLER_NO_CHANNEL_ADD=1;;
|
|
||||||
--daemon-user-count)
|
|
||||||
export NIX_USER_COUNT=$2
|
|
||||||
shift;;
|
|
||||||
--no-modify-profile)
|
|
||||||
NIX_INSTALLER_NO_MODIFY_PROFILE=1;;
|
|
||||||
--darwin-use-unencrypted-nix-store-volume)
|
|
||||||
{
|
|
||||||
echo "Warning: the flag --darwin-use-unencrypted-nix-store-volume"
|
|
||||||
echo " is no longer needed and will be removed in the future."
|
|
||||||
echo ""
|
|
||||||
} >&2;;
|
|
||||||
--nix-extra-conf-file)
|
|
||||||
# shellcheck disable=SC2155
|
|
||||||
export NIX_EXTRA_CONF="$(cat "$2")"
|
|
||||||
shift;;
|
|
||||||
*)
|
|
||||||
{
|
|
||||||
echo "Nix Installer [--daemon|--no-daemon] [--daemon-user-count INT] [--yes] [--no-channel-add] [--no-modify-profile] [--nix-extra-conf-file FILE]"
|
|
||||||
|
|
||||||
echo "Choose installation method."
|
|
||||||
echo ""
|
|
||||||
echo " --daemon: Installs and configures a background daemon that manages the store,"
|
|
||||||
echo " providing multi-user support and better isolation for local builds."
|
|
||||||
echo " Both for security and reproducibility, this method is recommended if"
|
|
||||||
echo " supported on your platform."
|
|
||||||
echo " See https://nixos.org/manual/nix/stable/installation/installing-binary.html#multi-user-installation"
|
|
||||||
echo ""
|
|
||||||
echo " --no-daemon: Simple, single-user installation that does not require root and is"
|
|
||||||
echo " trivial to uninstall."
|
|
||||||
echo " (default)"
|
|
||||||
echo ""
|
|
||||||
echo " --yes: Run the script non-interactively, accepting all prompts."
|
|
||||||
echo ""
|
|
||||||
echo " --no-channel-add: Don't add any channels. nixpkgs-unstable is installed by default."
|
|
||||||
echo ""
|
|
||||||
echo " --no-modify-profile: Don't modify the user profile to automatically load nix."
|
|
||||||
echo ""
|
|
||||||
echo " --daemon-user-count: Number of build users to create. Defaults to 32."
|
|
||||||
echo ""
|
|
||||||
echo " --nix-extra-conf-file: Path to nix.conf to prepend when installing /etc/nix/nix.conf"
|
|
||||||
echo ""
|
|
||||||
if [ -n "${INVOKED_FROM_INSTALL_IN:-}" ]; then
|
|
||||||
echo " --tarball-url-prefix URL: Base URL to download the Nix tarball from."
|
|
||||||
fi
|
|
||||||
} >&2
|
|
||||||
|
|
||||||
exit;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "$INSTALL_MODE" = "daemon" ]; then
|
|
||||||
printf '\e[1;31mSwitching to the Multi-user Installer\e[0m\n'
|
|
||||||
exec "$self/install-multi-user" $ACTIONS # let ACTIONS split
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$(id -u)" -eq 0 ]; then
|
|
||||||
printf '\e[1;31mwarning: installing Nix as root is not supported by this script!\e[0m\n'
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "performing a single-user installation of Nix..." >&2
|
|
||||||
|
|
||||||
if ! [ -e "$dest" ]; then
|
|
||||||
cmd="mkdir -m 0755 $dest && chown $USER $dest"
|
|
||||||
echo "directory $dest does not exist; creating it by running '$cmd' using sudo" >&2
|
|
||||||
if ! sudo sh -c "$cmd"; then
|
|
||||||
echo "$0: please manually run '$cmd' as root to create $dest" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! [ -w "$dest" ]; then
|
|
||||||
echo "$0: directory $dest exists, but is not writable by you. This could indicate that another user has already performed a single-user installation of Nix on this system. If you wish to enable multi-user support see https://nixos.org/manual/nix/stable/installation/multi-user.html. If you wish to continue with a single-user install for $USER please run 'chown -R $USER $dest' as root." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# The auto-chroot code in openFromNonUri() checks for the
|
|
||||||
# non-existence of /nix/var/nix, so we need to create it here.
|
|
||||||
mkdir -p "$dest/store" "$dest/var/nix"
|
|
||||||
|
|
||||||
printf "copying Nix to %s..." "${dest}/store" >&2
|
|
||||||
# Insert a newline if no progress is shown.
|
|
||||||
if [ ! -t 0 ]; then
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
for i in $(cd "$self/store" >/dev/null && echo ./*); do
|
|
||||||
if [ -t 0 ]; then
|
|
||||||
printf "." >&2
|
|
||||||
fi
|
|
||||||
i_tmp="$dest/store/$i.$$"
|
|
||||||
if [ -e "$i_tmp" ]; then
|
|
||||||
rm -rf "$i_tmp"
|
|
||||||
fi
|
|
||||||
if ! [ -e "$dest/store/$i" ]; then
|
|
||||||
cp -RPp "$self/store/$i" "$i_tmp"
|
|
||||||
chmod -R a-w "$i_tmp"
|
|
||||||
chmod +w "$i_tmp"
|
|
||||||
mv "$i_tmp" "$dest/store/$i"
|
|
||||||
chmod -w "$dest/store/$i"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo "" >&2
|
|
||||||
|
|
||||||
if ! "$nix/bin/nix-store" --load-db < "$self/.reginfo"; then
|
|
||||||
echo "$0: unable to register valid paths" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# shellcheck source=./nix-profile.sh.in
|
|
||||||
. "$nix/etc/profile.d/nix.sh"
|
|
||||||
|
|
||||||
NIX_LINK="$HOME/.nix-profile"
|
|
||||||
|
|
||||||
if ! "$nix/bin/nix-env" -i "$nix"; then
|
|
||||||
echo "$0: unable to install Nix into your default profile" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install an SSL certificate bundle.
|
|
||||||
if [ -z "$NIX_SSL_CERT_FILE" ] || ! [ -f "$NIX_SSL_CERT_FILE" ]; then
|
|
||||||
"$nix/bin/nix-env" -i "$cacert"
|
|
||||||
export NIX_SSL_CERT_FILE="$NIX_LINK/etc/ssl/certs/ca-bundle.crt"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Subscribe the user to the Nixpkgs channel and fetch it.
|
|
||||||
if [ -z "$NIX_INSTALLER_NO_CHANNEL_ADD" ]; then
|
|
||||||
if ! "$nix/bin/nix-channel" --list | grep -q "^nixpkgs "; then
|
|
||||||
"$nix/bin/nix-channel" --add https://nixos.org/channels/nixpkgs-unstable
|
|
||||||
fi
|
|
||||||
if [ -z "$_NIX_INSTALLER_TEST" ]; then
|
|
||||||
if ! "$nix/bin/nix-channel" --update nixpkgs; then
|
|
||||||
echo "Fetching the nixpkgs channel failed. (Are you offline?)"
|
|
||||||
echo "To try again later, run \"nix-channel --update nixpkgs\"."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
added=
|
|
||||||
p=
|
|
||||||
p_sh=$NIX_LINK/etc/profile.d/nix.sh
|
|
||||||
p_fish=$NIX_LINK/etc/profile.d/nix.fish
|
|
||||||
if [ -z "$NIX_INSTALLER_NO_MODIFY_PROFILE" ]; then
|
|
||||||
# Make the shell source nix.sh during login.
|
|
||||||
for i in .bash_profile .bash_login .profile; do
|
|
||||||
fn="$HOME/$i"
|
|
||||||
if [ -w "$fn" ]; then
|
|
||||||
if ! grep -q "$p_sh" "$fn"; then
|
|
||||||
echo "modifying $fn..." >&2
|
|
||||||
printf '\nif [ -e %s ]; then . %s; fi # added by Nix installer\n' "$p_sh" "$p_sh" >> "$fn"
|
|
||||||
fi
|
|
||||||
added=1
|
|
||||||
p=${p_sh}
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
for i in .zshenv .zshrc; do
|
|
||||||
fn="$HOME/$i"
|
|
||||||
if [ -w "$fn" ]; then
|
|
||||||
if ! grep -q "$p_sh" "$fn"; then
|
|
||||||
echo "modifying $fn..." >&2
|
|
||||||
printf '\nif [ -e %s ]; then . %s; fi # added by Nix installer\n' "$p_sh" "$p_sh" >> "$fn"
|
|
||||||
fi
|
|
||||||
added=1
|
|
||||||
p=${p_sh}
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -d "$HOME/.config/fish" ]; then
|
|
||||||
fishdir=$HOME/.config/fish/conf.d
|
|
||||||
if [ ! -d "$fishdir" ]; then
|
|
||||||
mkdir -p "$fishdir"
|
|
||||||
fi
|
|
||||||
|
|
||||||
fn="$fishdir/nix.fish"
|
|
||||||
echo "placing $fn..." >&2
|
|
||||||
printf '\nif test -e %s; . %s; end # added by Nix installer\n' "$p_fish" "$p_fish" > "$fn"
|
|
||||||
added=1
|
|
||||||
p=${p_fish}
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
p=${p_sh}
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$added" ]; then
|
|
||||||
cat >&2 <<EOF
|
|
||||||
|
|
||||||
Installation finished! To ensure that the necessary environment
|
|
||||||
variables are set, please add the line
|
|
||||||
|
|
||||||
. $p
|
|
||||||
|
|
||||||
to your shell profile (e.g. ~/.profile).
|
|
||||||
EOF
|
|
||||||
else
|
|
||||||
cat >&2 <<EOF
|
|
||||||
|
|
||||||
Installation finished! To ensure that the necessary environment
|
|
||||||
variables are set, either log in again, or type
|
|
||||||
|
|
||||||
. $p
|
|
||||||
|
|
||||||
in your shell.
|
|
||||||
EOF
|
|
||||||
fi
|
|
|
@ -1,222 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
# System specific settings
|
|
||||||
export NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-30001}"
|
|
||||||
export NIX_BUILD_USER_NAME_TEMPLATE="nixbld%d"
|
|
||||||
|
|
||||||
readonly SERVICE_SRC=/lib/systemd/system/nix-daemon.service
|
|
||||||
readonly SERVICE_DEST=/etc/systemd/system/nix-daemon.service
|
|
||||||
|
|
||||||
readonly SOCKET_SRC=/lib/systemd/system/nix-daemon.socket
|
|
||||||
readonly SOCKET_DEST=/etc/systemd/system/nix-daemon.socket
|
|
||||||
|
|
||||||
readonly TMPFILES_SRC=/lib/tmpfiles.d/nix-daemon.conf
|
|
||||||
readonly TMPFILES_DEST=/etc/tmpfiles.d/nix-daemon.conf
|
|
||||||
|
|
||||||
# Path for the systemd override unit file to contain the proxy settings
|
|
||||||
readonly SERVICE_OVERRIDE=${SERVICE_DEST}.d/override.conf
|
|
||||||
|
|
||||||
create_systemd_override() {
|
|
||||||
header "Configuring proxy for the nix-daemon service"
|
|
||||||
_sudo "create directory for systemd unit override" mkdir -p "$(dirname "$SERVICE_OVERRIDE")"
|
|
||||||
cat <<EOF | _sudo "create systemd unit override" tee "$SERVICE_OVERRIDE"
|
|
||||||
[Service]
|
|
||||||
$1
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
escape_systemd_env() {
|
|
||||||
temp_var="${1//\'/\\\'}"
|
|
||||||
echo "${temp_var//\%/%%}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Gather all non-empty proxy environment variables into a string
|
|
||||||
create_systemd_proxy_env() {
|
|
||||||
vars="http_proxy https_proxy ftp_proxy no_proxy HTTP_PROXY HTTPS_PROXY FTP_PROXY NO_PROXY"
|
|
||||||
for v in $vars; do
|
|
||||||
if [ "x${!v:-}" != "x" ]; then
|
|
||||||
echo "Environment=${v}=$(escape_systemd_env ${!v})"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_network_proxy() {
|
|
||||||
# Create a systemd unit override with proxy environment variables
|
|
||||||
# if any proxy environment variables are not empty.
|
|
||||||
PROXY_ENV_STRING=$(create_systemd_proxy_env)
|
|
||||||
if [ -n "${PROXY_ENV_STRING}" ]; then
|
|
||||||
create_systemd_override "${PROXY_ENV_STRING}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_cure_artifacts() {
|
|
||||||
:
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_service_installed_check() {
|
|
||||||
[ "$(systemctl is-enabled nix-daemon.service)" = "linked" ] \
|
|
||||||
|| [ "$(systemctl is-enabled nix-daemon.socket)" = "enabled" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_service_uninstall_directions() {
|
|
||||||
cat <<EOF
|
|
||||||
$1. Delete the systemd service and socket units
|
|
||||||
|
|
||||||
sudo systemctl stop nix-daemon.socket
|
|
||||||
sudo systemctl stop nix-daemon.service
|
|
||||||
sudo systemctl disable nix-daemon.socket
|
|
||||||
sudo systemctl disable nix-daemon.service
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_service_setup_note() {
|
|
||||||
cat <<EOF
|
|
||||||
- load and start a service (at $SERVICE_DEST
|
|
||||||
and $SOCKET_DEST) for nix-daemon
|
|
||||||
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_extra_try_me_commands() {
|
|
||||||
if [ -e /run/systemd/system ]; then
|
|
||||||
:
|
|
||||||
else
|
|
||||||
cat <<EOF
|
|
||||||
$ sudo nix-daemon
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_configure_nix_daemon_service() {
|
|
||||||
if [ -e /run/systemd/system ]; then
|
|
||||||
task "Setting up the nix-daemon systemd service"
|
|
||||||
|
|
||||||
_sudo "to create the nix-daemon tmpfiles config" \
|
|
||||||
ln -sfn "/nix/var/nix/profiles/default$TMPFILES_SRC" "$TMPFILES_DEST"
|
|
||||||
|
|
||||||
_sudo "to run systemd-tmpfiles once to pick that path up" \
|
|
||||||
systemd-tmpfiles --create --prefix=/nix/var/nix
|
|
||||||
|
|
||||||
_sudo "to set up the nix-daemon service" \
|
|
||||||
systemctl link "/nix/var/nix/profiles/default$SERVICE_SRC"
|
|
||||||
|
|
||||||
_sudo "to set up the nix-daemon socket service" \
|
|
||||||
systemctl enable "/nix/var/nix/profiles/default$SOCKET_SRC"
|
|
||||||
|
|
||||||
handle_network_proxy
|
|
||||||
|
|
||||||
_sudo "to load the systemd unit for nix-daemon" \
|
|
||||||
systemctl daemon-reload
|
|
||||||
|
|
||||||
_sudo "to start the nix-daemon.socket" \
|
|
||||||
systemctl start nix-daemon.socket
|
|
||||||
|
|
||||||
_sudo "to start the nix-daemon.service" \
|
|
||||||
systemctl restart nix-daemon.service
|
|
||||||
else
|
|
||||||
reminder "I don't support your init system yet; you may want to add nix-daemon manually."
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_group_exists() {
|
|
||||||
getent group "$1" > /dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_group_id_get() {
|
|
||||||
getent group "$1" | cut -d: -f3
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_create_build_group() {
|
|
||||||
_sudo "Create the Nix build group, $NIX_BUILD_GROUP_NAME" \
|
|
||||||
groupadd -g "$NIX_BUILD_GROUP_ID" --system \
|
|
||||||
"$NIX_BUILD_GROUP_NAME" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_exists() {
|
|
||||||
getent passwd "$1" > /dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_id_get() {
|
|
||||||
getent passwd "$1" | cut -d: -f3
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_hidden_get() {
|
|
||||||
echo "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_hidden_set() {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_home_get() {
|
|
||||||
getent passwd "$1" | cut -d: -f6
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_home_set() {
|
|
||||||
_sudo "in order to give $1 a safe home directory" \
|
|
||||||
usermod --home "$2" "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_note_get() {
|
|
||||||
getent passwd "$1" | cut -d: -f5
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_note_set() {
|
|
||||||
_sudo "in order to give $1 a useful comment" \
|
|
||||||
usermod --comment "$2" "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_shell_get() {
|
|
||||||
getent passwd "$1" | cut -d: -f7
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_shell_set() {
|
|
||||||
_sudo "in order to prevent $1 from logging in" \
|
|
||||||
usermod --shell "$2" "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_in_group_check() {
|
|
||||||
groups "$1" | grep -q "$2" > /dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_in_group_set() {
|
|
||||||
_sudo "Add $1 to the $2 group"\
|
|
||||||
usermod --append --groups "$2" "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_primary_group_get() {
|
|
||||||
getent passwd "$1" | cut -d: -f4
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_user_primary_group_set() {
|
|
||||||
_sudo "to let the nix daemon use this user for builds (this might seem redundant, but there are two concepts of group membership)" \
|
|
||||||
usermod --gid "$2" "$1"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_create_build_user() {
|
|
||||||
username=$1
|
|
||||||
uid=$2
|
|
||||||
builder_num=$3
|
|
||||||
|
|
||||||
_sudo "Creating the Nix build user, $username" \
|
|
||||||
useradd \
|
|
||||||
--home-dir /var/empty \
|
|
||||||
--comment "Nix build user $builder_num" \
|
|
||||||
--gid "$NIX_BUILD_GROUP_ID" \
|
|
||||||
--groups "$NIX_BUILD_GROUP_NAME" \
|
|
||||||
--no-user-group \
|
|
||||||
--system \
|
|
||||||
--shell /sbin/nologin \
|
|
||||||
--uid "$uid" \
|
|
||||||
--password "!" \
|
|
||||||
"$username"
|
|
||||||
}
|
|
||||||
|
|
||||||
poly_prepare_to_install() {
|
|
||||||
:
|
|
||||||
}
|
|
|
@ -1,119 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# This script installs the Nix package manager on your system by
|
|
||||||
# downloading a binary distribution and running its installer script
|
|
||||||
# (which in turn creates and populates /nix).
|
|
||||||
|
|
||||||
{ # Prevent execution if this script was only partially downloaded
|
|
||||||
oops() {
|
|
||||||
echo "$0:" "$@" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
umask 0022
|
|
||||||
|
|
||||||
tmpDir="$(mktemp -d -t nix-binary-tarball-unpack.XXXXXXXXXX || \
|
|
||||||
oops "Can't create temporary directory for downloading the Nix binary tarball")"
|
|
||||||
cleanup() {
|
|
||||||
rm -rf "$tmpDir"
|
|
||||||
}
|
|
||||||
trap cleanup EXIT INT QUIT TERM
|
|
||||||
|
|
||||||
require_util() {
|
|
||||||
command -v "$1" > /dev/null 2>&1 ||
|
|
||||||
oops "you do not have '$1' installed, which I need to $2"
|
|
||||||
}
|
|
||||||
|
|
||||||
case "$(uname -s).$(uname -m)" in
|
|
||||||
Linux.x86_64)
|
|
||||||
hash=@tarballHash_x86_64-linux@
|
|
||||||
path=@tarballPath_x86_64-linux@
|
|
||||||
system=x86_64-linux
|
|
||||||
;;
|
|
||||||
Linux.i?86)
|
|
||||||
hash=@tarballHash_i686-linux@
|
|
||||||
path=@tarballPath_i686-linux@
|
|
||||||
system=i686-linux
|
|
||||||
;;
|
|
||||||
Linux.aarch64)
|
|
||||||
hash=@tarballHash_aarch64-linux@
|
|
||||||
path=@tarballPath_aarch64-linux@
|
|
||||||
system=aarch64-linux
|
|
||||||
;;
|
|
||||||
Linux.armv6l)
|
|
||||||
hash=@tarballHash_armv6l-linux@
|
|
||||||
path=@tarballPath_armv6l-linux@
|
|
||||||
system=armv6l-linux
|
|
||||||
;;
|
|
||||||
Linux.armv7l)
|
|
||||||
hash=@tarballHash_armv7l-linux@
|
|
||||||
path=@tarballPath_armv7l-linux@
|
|
||||||
system=armv7l-linux
|
|
||||||
;;
|
|
||||||
Darwin.x86_64)
|
|
||||||
hash=@tarballHash_x86_64-darwin@
|
|
||||||
path=@tarballPath_x86_64-darwin@
|
|
||||||
system=x86_64-darwin
|
|
||||||
;;
|
|
||||||
Darwin.arm64|Darwin.aarch64)
|
|
||||||
hash=@tarballHash_aarch64-darwin@
|
|
||||||
path=@tarballPath_aarch64-darwin@
|
|
||||||
system=aarch64-darwin
|
|
||||||
;;
|
|
||||||
*) oops "sorry, there is no binary distribution of Nix for your platform";;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Use this command-line option to fetch the tarballs using nar-serve or Cachix
|
|
||||||
if [ "${1:-}" = "--tarball-url-prefix" ]; then
|
|
||||||
if [ -z "${2:-}" ]; then
|
|
||||||
oops "missing argument for --tarball-url-prefix"
|
|
||||||
fi
|
|
||||||
url=${2}/${path}
|
|
||||||
shift 2
|
|
||||||
else
|
|
||||||
url=https://releases.nixos.org/nix/nix-@nixVersion@/nix-@nixVersion@-$system.tar.xz
|
|
||||||
fi
|
|
||||||
|
|
||||||
tarball=$tmpDir/nix-@nixVersion@-$system.tar.xz
|
|
||||||
|
|
||||||
require_util tar "unpack the binary tarball"
|
|
||||||
if [ "$(uname -s)" != "Darwin" ]; then
|
|
||||||
require_util xz "unpack the binary tarball"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if command -v curl > /dev/null 2>&1; then
|
|
||||||
fetch() { curl --fail -L "$1" -o "$2"; }
|
|
||||||
elif command -v wget > /dev/null 2>&1; then
|
|
||||||
fetch() { wget "$1" -O "$2"; }
|
|
||||||
else
|
|
||||||
oops "you don't have wget or curl installed, which I need to download the binary tarball"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "downloading Nix @nixVersion@ binary tarball for $system from '$url' to '$tmpDir'..."
|
|
||||||
fetch "$url" "$tarball" || oops "failed to download '$url'"
|
|
||||||
|
|
||||||
if command -v sha256sum > /dev/null 2>&1; then
|
|
||||||
hash2="$(sha256sum -b "$tarball" | cut -c1-64)"
|
|
||||||
elif command -v shasum > /dev/null 2>&1; then
|
|
||||||
hash2="$(shasum -a 256 -b "$tarball" | cut -c1-64)"
|
|
||||||
elif command -v openssl > /dev/null 2>&1; then
|
|
||||||
hash2="$(openssl dgst -r -sha256 "$tarball" | cut -c1-64)"
|
|
||||||
else
|
|
||||||
oops "cannot verify the SHA-256 hash of '$url'; you need one of 'shasum', 'sha256sum', or 'openssl'"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$hash" != "$hash2" ]; then
|
|
||||||
oops "SHA-256 hash mismatch in '$url'; expected $hash, got $hash2"
|
|
||||||
fi
|
|
||||||
|
|
||||||
unpack=$tmpDir/unpack
|
|
||||||
mkdir -p "$unpack"
|
|
||||||
tar -xJf "$tarball" -C "$unpack" || oops "failed to unpack '$url'"
|
|
||||||
|
|
||||||
script=$(echo "$unpack"/*/install)
|
|
||||||
|
|
||||||
[ -e "$script" ] || oops "installation script is missing from the binary tarball!"
|
|
||||||
export INVOKED_FROM_INSTALL_IN=1
|
|
||||||
"$script" "$@"
|
|
||||||
|
|
||||||
} # End of wrapping
|
|
|
@ -7,7 +7,5 @@ profiledir = $(sysconfdir)/profile.d
|
||||||
|
|
||||||
$(eval $(call install-file-as, $(d)/nix-profile.sh, $(profiledir)/nix.sh, 0644))
|
$(eval $(call install-file-as, $(d)/nix-profile.sh, $(profiledir)/nix.sh, 0644))
|
||||||
$(eval $(call install-file-as, $(d)/nix-profile.fish, $(profiledir)/nix.fish, 0644))
|
$(eval $(call install-file-as, $(d)/nix-profile.fish, $(profiledir)/nix.fish, 0644))
|
||||||
$(eval $(call install-file-as, $(d)/nix-profile-daemon.sh, $(profiledir)/nix-daemon.sh, 0644))
|
|
||||||
$(eval $(call install-file-as, $(d)/nix-profile-daemon.fish, $(profiledir)/nix-daemon.fish, 0644))
|
|
||||||
|
|
||||||
clean-files += $(nix_noinst_scripts)
|
clean-files += $(nix_noinst_scripts)
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
function add_path --argument-names new_path
|
|
||||||
if type -q fish_add_path
|
|
||||||
# fish 3.2.0 or newer
|
|
||||||
fish_add_path --prepend --global $new_path
|
|
||||||
else
|
|
||||||
# older versions of fish
|
|
||||||
if not contains $new_path $fish_user_paths
|
|
||||||
set --global fish_user_paths $new_path $fish_user_paths
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Only execute this file once per shell.
|
|
||||||
if test -n "$__ETC_PROFILE_NIX_SOURCED"
|
|
||||||
exit
|
|
||||||
end
|
|
||||||
|
|
||||||
set __ETC_PROFILE_NIX_SOURCED 1
|
|
||||||
|
|
||||||
set --export NIX_PROFILES "@localstatedir@/nix/profiles/default $HOME/.nix-profile"
|
|
||||||
|
|
||||||
# Populate bash completions, .desktop files, etc
|
|
||||||
if test -z "$XDG_DATA_DIRS"
|
|
||||||
# According to XDG spec the default is /usr/local/share:/usr/share, don't set something that prevents that default
|
|
||||||
set --export XDG_DATA_DIRS "/usr/local/share:/usr/share:/nix/var/nix/profiles/default/share"
|
|
||||||
else
|
|
||||||
set --export XDG_DATA_DIRS "$XDG_DATA_DIRS:/nix/var/nix/profiles/default/share"
|
|
||||||
end
|
|
||||||
|
|
||||||
# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work.
|
|
||||||
if test -n "$NIX_SSH_CERT_FILE"
|
|
||||||
: # Allow users to override the NIX_SSL_CERT_FILE
|
|
||||||
else if test -e /etc/ssl/certs/ca-certificates.crt # NixOS, Ubuntu, Debian, Gentoo, Arch
|
|
||||||
set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-certificates.crt
|
|
||||||
else if test -e /etc/ssl/ca-bundle.pem # openSUSE Tumbleweed
|
|
||||||
set --export NIX_SSL_CERT_FILE /etc/ssl/ca-bundle.pem
|
|
||||||
else if test -e /etc/ssl/certs/ca-bundle.crt # Old NixOS
|
|
||||||
set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-bundle.crt
|
|
||||||
else if test -e /etc/pki/tls/certs/ca-bundle.crt # Fedora, CentOS
|
|
||||||
set --export NIX_SSL_CERT_FILE /etc/pki/tls/certs/ca-bundle.crt
|
|
||||||
else if test -e "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" # fall back to cacert in Nix profile
|
|
||||||
set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ssl/certs/ca-bundle.crt"
|
|
||||||
else if test -e "$NIX_LINK/etc/ca-bundle.crt" # old cacert in Nix profile
|
|
||||||
set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ca-bundle.crt"
|
|
||||||
else
|
|
||||||
# Fall back to what is in the nix profiles, favouring whatever is defined last.
|
|
||||||
for i in $NIX_PROFILES
|
|
||||||
if test -e "$i/etc/ssl/certs/ca-bundle.crt"
|
|
||||||
set --export NIX_SSL_CERT_FILE "$i/etc/ssl/certs/ca-bundle.crt"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
add_path "@localstatedir@/nix/profiles/default/bin"
|
|
||||||
add_path "$HOME/.nix-profile/bin"
|
|
||||||
|
|
||||||
functions -e add_path
|
|
|
@ -1,72 +0,0 @@
|
||||||
# Only execute this file once per shell.
|
|
||||||
if [ -n "${__ETC_PROFILE_NIX_SOURCED:-}" ]; then return; fi
|
|
||||||
__ETC_PROFILE_NIX_SOURCED=1
|
|
||||||
|
|
||||||
NIX_LINK=$HOME/.nix-profile
|
|
||||||
if [ -n "${XDG_STATE_HOME-}" ]; then
|
|
||||||
NIX_LINK_NEW="$XDG_STATE_HOME/nix/profile"
|
|
||||||
else
|
|
||||||
NIX_LINK_NEW=$HOME/.local/state/nix/profile
|
|
||||||
fi
|
|
||||||
if [ -e "$NIX_LINK_NEW" ]; then
|
|
||||||
NIX_LINK="$NIX_LINK_NEW"
|
|
||||||
else
|
|
||||||
if [ -t 2 ] && [ -e "$NIX_LINK_NEW" ]; then
|
|
||||||
warning="\033[1;35mwarning:\033[0m"
|
|
||||||
printf "$warning Both %s and legacy %s exist; using the latter.\n" "$NIX_LINK_NEW" "$NIX_LINK" 1>&2
|
|
||||||
if [ "$(realpath "$NIX_LINK")" = "$(realpath "$NIX_LINK_NEW")" ]; then
|
|
||||||
printf " Since the profiles match, you can safely delete either of them.\n" 1>&2
|
|
||||||
else
|
|
||||||
# This should be an exceptionally rare occasion: the only way to get it would be to
|
|
||||||
# 1. Update to newer Nix;
|
|
||||||
# 2. Remove .nix-profile;
|
|
||||||
# 3. Set the $NIX_LINK_NEW to something other than the default user profile;
|
|
||||||
# 4. Roll back to older Nix.
|
|
||||||
# If someone did all that, they can probably figure out how to migrate the profile.
|
|
||||||
printf "$warning Profiles do not match. You should manually migrate from %s to %s.\n" "$NIX_LINK" "$NIX_LINK_NEW" 1>&2
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
export NIX_PROFILES="@localstatedir@/nix/profiles/default $NIX_LINK"
|
|
||||||
|
|
||||||
# Populate bash completions, .desktop files, etc
|
|
||||||
if [ -z "${XDG_DATA_DIRS-}" ]; then
|
|
||||||
# According to XDG spec the default is /usr/local/share:/usr/share, don't set something that prevents that default
|
|
||||||
export XDG_DATA_DIRS="/usr/local/share:/usr/share:$NIX_LINK/share:/nix/var/nix/profiles/default/share"
|
|
||||||
else
|
|
||||||
export XDG_DATA_DIRS="$XDG_DATA_DIRS:$NIX_LINK/share:/nix/var/nix/profiles/default/share"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work.
|
|
||||||
if [ -n "${NIX_SSL_CERT_FILE:-}" ]; then
|
|
||||||
: # Allow users to override the NIX_SSL_CERT_FILE
|
|
||||||
elif [ -e /etc/ssl/certs/ca-certificates.crt ]; then # NixOS, Ubuntu, Debian, Gentoo, Arch
|
|
||||||
export NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
|
|
||||||
elif [ -e /etc/ssl/ca-bundle.pem ]; then # openSUSE Tumbleweed
|
|
||||||
export NIX_SSL_CERT_FILE=/etc/ssl/ca-bundle.pem
|
|
||||||
elif [ -e /etc/ssl/certs/ca-bundle.crt ]; then # Old NixOS
|
|
||||||
export NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt
|
|
||||||
elif [ -e /etc/pki/tls/certs/ca-bundle.crt ]; then # Fedora, CentOS
|
|
||||||
export NIX_SSL_CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt
|
|
||||||
else
|
|
||||||
# Fall back to what is in the nix profiles, favouring whatever is defined last.
|
|
||||||
check_nix_profiles() {
|
|
||||||
if [ -n "$ZSH_VERSION" ]; then
|
|
||||||
# Zsh by default doesn't split words in unquoted parameter expansion.
|
|
||||||
# Set local_options for these options to be reverted at the end of the function
|
|
||||||
# and shwordsplit to force splitting words in $NIX_PROFILES below.
|
|
||||||
setopt local_options shwordsplit
|
|
||||||
fi
|
|
||||||
for i in $NIX_PROFILES; do
|
|
||||||
if [ -e "$i/etc/ssl/certs/ca-bundle.crt" ]; then
|
|
||||||
export NIX_SSL_CERT_FILE=$i/etc/ssl/certs/ca-bundle.crt
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
check_nix_profiles
|
|
||||||
unset -f check_nix_profiles
|
|
||||||
fi
|
|
||||||
|
|
||||||
export PATH="$NIX_LINK/bin:@localstatedir@/nix/profiles/default/bin:$PATH"
|
|
||||||
unset NIX_LINK
|
|
|
@ -1,10 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
script=$(nix-build -A outputs.hydraJobs.installerScriptForGHA --no-out-link)
|
|
||||||
installerHash=$(echo "$script" | cut -b12-43 -)
|
|
||||||
|
|
||||||
installerURL=https://$CACHIX_NAME.cachix.org/serve/$installerHash/install
|
|
||||||
|
|
||||||
echo "::set-output name=installerURL::$installerURL"
|
|
Loading…
Reference in a new issue