mirror of
https://github.com/NixOS/nix
synced 2025-06-28 09:31:16 +02:00
darwin: encrypt nix volume if filevault is enabled
This commit is contained in:
parent
dc6a8f1548
commit
eab14a642c
6 changed files with 1186 additions and 434 deletions
|
@ -43,7 +43,7 @@ readonly NIX_INSTALLED_CACERT="@cacert@"
|
|||
#readonly NIX_INSTALLED_CACERT="/nix/store/7dxhzymvy330i28ii676fl1pqwcahv2f-nss-cacert-3.49.2"
|
||||
readonly EXTRACTED_NIX_PATH="$(dirname "$0")"
|
||||
|
||||
readonly ROOT_HOME=$(echo ~root)
|
||||
readonly ROOT_HOME=~root
|
||||
|
||||
if [ -t 0 ]; then
|
||||
readonly IS_HEADLESS='no'
|
||||
|
@ -59,14 +59,18 @@ headless() {
|
|||
fi
|
||||
}
|
||||
|
||||
contactme() {
|
||||
contact_us() {
|
||||
echo "You can open an issue at https://github.com/nixos/nix/issues"
|
||||
echo ""
|
||||
echo "Or feel free to contact the team:"
|
||||
echo " - IRC: in #nixos on irc.freenode.net"
|
||||
echo " - twitter: @nixos_org"
|
||||
echo " - forum: https://discourse.nixos.org"
|
||||
}
|
||||
get_help() {
|
||||
echo "We'd love to help if you need it."
|
||||
echo ""
|
||||
echo "If you can, open an issue at https://github.com/nixos/nix/issues"
|
||||
echo ""
|
||||
echo "Or feel free to contact the team,"
|
||||
echo " - on IRC #nixos on irc.freenode.net"
|
||||
echo " - on twitter @nixos_org"
|
||||
contact_us
|
||||
}
|
||||
|
||||
uninstall_directions() {
|
||||
|
@ -102,7 +106,6 @@ $step. Delete the files Nix added to your system:
|
|||
and that is it.
|
||||
|
||||
EOF
|
||||
|
||||
}
|
||||
|
||||
nix_user_for_core() {
|
||||
|
@ -170,7 +173,7 @@ failure() {
|
|||
header "oh no!"
|
||||
_textout "$RED" "$@"
|
||||
echo ""
|
||||
_textout "$RED" "$(contactme)"
|
||||
_textout "$RED" "$(get_help)"
|
||||
trap finish_cleanup EXIT
|
||||
exit 1
|
||||
}
|
||||
|
@ -201,6 +204,95 @@ ui_confirm() {
|
|||
return 1
|
||||
}
|
||||
|
||||
printf -v _UNCHANGED_GRP_FMT "%b" $'\033[2m%='"$ESC" # "dim"
|
||||
# bold+invert+red and bold+invert+green just for the +/- below
|
||||
# red/green foreground for rest of the line
|
||||
printf -v _OLD_LINE_FMT "%b" $'\033[1;7;31m-'"$ESC ${RED}%L${ESC}"
|
||||
printf -v _NEW_LINE_FMT "%b" $'\033[1;7;32m+'"$ESC ${GREEN}%L${ESC}"
|
||||
|
||||
_diff() {
|
||||
# simple colorized diff comatible w/ pre `--color` versions
|
||||
diff --unchanged-group-format="$_UNCHANGED_GRP_FMT" --old-line-format="$_OLD_LINE_FMT" --new-line-format="$_NEW_LINE_FMT" --unchanged-line-format=" %L" "$@"
|
||||
}
|
||||
|
||||
confirm_rm() {
|
||||
local path="$1"
|
||||
if ui_confirm "Can I remove $path?"; then
|
||||
_sudo "to remove $path" rm "$path"
|
||||
fi
|
||||
}
|
||||
|
||||
confirm_edit() {
|
||||
local path="$1"
|
||||
local edit_path="$2"
|
||||
cat <<EOF
|
||||
|
||||
Nix isn't the only thing in $path,
|
||||
but I think I know how to edit it out.
|
||||
Here's the diff:
|
||||
EOF
|
||||
|
||||
# could technically test the diff, but caller should do it
|
||||
_diff "$path" "$edit_path"
|
||||
if ui_confirm "Does the change above look right?"; then
|
||||
_sudo "remove nix from $path" cp "$edit_path" "$path"
|
||||
fi
|
||||
}
|
||||
|
||||
_SERIOUS_BUSINESS="${RED}%s:${ESC} "
|
||||
password_confirm() {
|
||||
local do_something_consequential="$1"
|
||||
if ui_confirm "Can I $do_something_consequential?"; then
|
||||
# shellcheck disable=SC2059
|
||||
sudo -kv --prompt="$(printf "${_SERIOUS_BUSINESS}" "Enter your password to $do_something_consequential")"
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Support accumulating reminders over the course of a run and showing
|
||||
# them at the end. An example where this helps: the installer changes
|
||||
# something, but it won't work without a reboot. If you tell the user
|
||||
# when you do it, they may miss it in the stream. The value of the
|
||||
# setting isn't enough to decide whether to message because you only
|
||||
# need to message if you *changed* it.
|
||||
|
||||
# reminders stored in array delimited by empty entry; if ! headless,
|
||||
# user is asked to confirm after each delimiter.
|
||||
_reminders=()
|
||||
((_remind_num=1))
|
||||
|
||||
remind() {
|
||||
# (( arithmetic expression ))
|
||||
if (( _remind_num > 1 )); then
|
||||
header "Reminders"
|
||||
for line in "${_reminders[@]}"; do
|
||||
echo "$line"
|
||||
if ! headless && [ "${#line}" = 0 ]; then
|
||||
if read -r -p "Press enter/return to acknowledge."; then
|
||||
printf $'\033[A\33[2K\r'
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
reminder() {
|
||||
printf -v label "${BLUE}[ %d ]${ESC}" "$_remind_num"
|
||||
_reminders+=("$label")
|
||||
if [[ "$*" = "" ]]; then
|
||||
while read -r line; do
|
||||
_reminders+=("$line")
|
||||
done
|
||||
else
|
||||
# this expands each arg to an array entry (and each entry will
|
||||
# ultimately be a separate line in the output)
|
||||
_reminders+=("$@")
|
||||
fi
|
||||
_reminders+=("")
|
||||
((_remind_num++))
|
||||
}
|
||||
|
||||
__sudo() {
|
||||
local expl="$1"
|
||||
local cmd="$2"
|
||||
|
@ -221,18 +313,18 @@ _sudo() {
|
|||
local expl="$1"
|
||||
shift
|
||||
if ! headless; then
|
||||
__sudo "$expl" "$*"
|
||||
__sudo "$expl" "$*" >&2
|
||||
fi
|
||||
sudo "$@"
|
||||
}
|
||||
|
||||
|
||||
readonly SCRATCH=$(mktemp -d -t tmp.XXXXXXXXXX)
|
||||
function finish_cleanup {
|
||||
readonly SCRATCH=$(mktemp -d "${TMPDIR:-/tmp/}tmp.XXXXXXXXXX")
|
||||
finish_cleanup() {
|
||||
rm -rf "$SCRATCH"
|
||||
}
|
||||
|
||||
function finish_fail {
|
||||
finish_fail() {
|
||||
finish_cleanup
|
||||
|
||||
failure <<EOF
|
||||
|
@ -244,45 +336,46 @@ EOF
|
|||
}
|
||||
trap finish_fail EXIT
|
||||
|
||||
channel_update_failed=0
|
||||
function finish_success {
|
||||
finish_cleanup
|
||||
|
||||
finish_success() {
|
||||
ok "Alright! We're done!"
|
||||
if [ "x$channel_update_failed" = x1 ]; then
|
||||
echo ""
|
||||
echo "But fetching the nixpkgs channel failed. (Are you offline?)"
|
||||
echo "To try again later, run \"sudo -i nix-channel --update nixpkgs\"."
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Before Nix will work in your existing shells, you'll need to close
|
||||
them and open them again. Other than that, you should be ready to go.
|
||||
|
||||
Try it! Open a new terminal, and type:
|
||||
$(poly_extra_try_me_commands)
|
||||
$ nix-shell -p nix-info --run "nix-info -m"
|
||||
$(poly_extra_setup_instructions)
|
||||
Thank you for using this installer. If you have any feedback, don't
|
||||
hesitate:
|
||||
|
||||
$(contactme)
|
||||
Thank you for using this installer. If you have any feedback or need
|
||||
help, don't hesitate:
|
||||
|
||||
$(contact_us)
|
||||
EOF
|
||||
|
||||
remind
|
||||
finish_cleanup
|
||||
}
|
||||
|
||||
finish_uninstall_success() {
|
||||
ok "Alright! Nix should be removed!"
|
||||
|
||||
cat <<EOF
|
||||
If you spot anything this uninstaller missed or have feedback,
|
||||
don't hesitate:
|
||||
|
||||
$(contact_us)
|
||||
EOF
|
||||
remind
|
||||
finish_cleanup
|
||||
}
|
||||
|
||||
remove_nix_artifacts() {
|
||||
failure "Not implemented yet"
|
||||
}
|
||||
|
||||
cure_artifacts() {
|
||||
poly_cure_artifacts
|
||||
# remove_nix_artifacts (LATER)
|
||||
}
|
||||
|
||||
validate_starting_assumptions() {
|
||||
poly_validate_assumptions
|
||||
|
||||
if [ $EUID -eq 0 ]; then
|
||||
failure <<EOF
|
||||
Please do not run this script with root privileges. We will call sudo
|
||||
when we need to.
|
||||
EOF
|
||||
fi
|
||||
|
||||
if type nix-env 2> /dev/null >&2; then
|
||||
warning <<EOF
|
||||
Nix already appears to be installed. This installer may run into issues.
|
||||
|
@ -444,18 +537,46 @@ create_build_users() {
|
|||
|
||||
create_directories() {
|
||||
# FIXME: remove all of this because it duplicates LocalStore::LocalStore().
|
||||
task "Setting up the basic directory structure"
|
||||
if [ -d "$NIX_ROOT" ]; then
|
||||
# if /nix already exists, take ownership
|
||||
#
|
||||
# Caution: notes below are macOS-y
|
||||
# This is a bit of a goldilocks zone for taking ownership
|
||||
# if there are already files on the volume; the volume is
|
||||
# now mounted, but we haven't added a bunch of new files
|
||||
|
||||
# this is probably a bit slow; I've been seeing 3.3-4s even
|
||||
# when promptly installed over a fresh single-user install.
|
||||
# In case anyone's aware of a shortcut.
|
||||
# `|| true`: .Trashes errors w/o full disk perm
|
||||
|
||||
# rumor per #4488 that macOS 11.2 may not have
|
||||
# sbin on path, and that's where chown is, but
|
||||
# since this bit is cross-platform:
|
||||
# - first try with `command -vp` to try and find
|
||||
# chown in the usual places
|
||||
# - fall back on `command -v` which would find
|
||||
# any chown on path
|
||||
# if we don't find one, the command is already
|
||||
# hiding behind || true, and the general state
|
||||
# should be one the user can repair once they
|
||||
# figure out where chown is...
|
||||
local get_chr_own="$(command -vp chown)"
|
||||
if [[ -z "$get_chr_own" ]]; then
|
||||
get_chr_own="$(command -v chown)"
|
||||
fi
|
||||
_sudo "to take root ownership of existing Nix store files" \
|
||||
"$get_chr_own" -R "root:$NIX_BUILD_GROUP_NAME" "$NIX_ROOT" || true
|
||||
fi
|
||||
_sudo "to make the basic directory structure of Nix (part 1)" \
|
||||
mkdir -pv -m 0755 /nix /nix/var /nix/var/log /nix/var/log/nix /nix/var/log/nix/drvs /nix/var/nix{,/db,/gcroots,/profiles,/temproots,/userpool} /nix/var/nix/{gcroots,profiles}/per-user
|
||||
install -dv -m 0755 /nix /nix/var /nix/var/log /nix/var/log/nix /nix/var/log/nix/drvs /nix/var/nix{,/db,/gcroots,/profiles,/temproots,/userpool} /nix/var/nix/{gcroots,profiles}/per-user
|
||||
|
||||
_sudo "to make the basic directory structure of Nix (part 2)" \
|
||||
mkdir -pv -m 1775 /nix/store
|
||||
|
||||
_sudo "to make the basic directory structure of Nix (part 3)" \
|
||||
chgrp "$NIX_BUILD_GROUP_NAME" /nix/store
|
||||
install -dv -g "$NIX_BUILD_GROUP_NAME" -m 1775 /nix/store
|
||||
|
||||
_sudo "to place the default nix daemon configuration (part 1)" \
|
||||
mkdir -pv -m 0555 /etc/nix
|
||||
install -dv -m 0555 /etc/nix
|
||||
}
|
||||
|
||||
place_channel_configuration() {
|
||||
|
@ -475,7 +596,7 @@ This installation tool will set up your computer with the Nix package
|
|||
manager. This will happen in a few stages:
|
||||
|
||||
1. Make sure your computer doesn't already have Nix. If it does, I
|
||||
will show you instructions on how to clean up your old one.
|
||||
will show you instructions on how to clean up your old install.
|
||||
|
||||
2. Show you what we are going to install and where. Then we will ask
|
||||
if you are ready to continue.
|
||||
|
@ -574,6 +695,7 @@ EOF
|
|||
}
|
||||
|
||||
install_from_extracted_nix() {
|
||||
task "Installing Nix"
|
||||
(
|
||||
cd "$EXTRACTED_NIX_PATH"
|
||||
|
||||
|
@ -589,9 +711,8 @@ $NIX_INSTALLED_NIX.
|
|||
EOF
|
||||
fi
|
||||
|
||||
cat ./.reginfo \
|
||||
| _sudo "to load data for the first time in to the Nix Database" \
|
||||
"$NIX_INSTALLED_NIX/bin/nix-store" --load-db
|
||||
_sudo "to load data for the first time in to the Nix Database" \
|
||||
"$NIX_INSTALLED_NIX/bin/nix-store" --load-db < ./.reginfo
|
||||
|
||||
echo " Just finished getting the nix database ready."
|
||||
)
|
||||
|
@ -610,6 +731,7 @@ EOF
|
|||
}
|
||||
|
||||
configure_shell_profile() {
|
||||
task "Setting up shell profiles: ${PROFILE_TARGETS[*]}"
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
if [ -e "$profile_target" ]; then
|
||||
_sudo "to back up your current $profile_target to $profile_target$PROFILE_BACKUP_SUFFIX" \
|
||||
|
@ -629,14 +751,27 @@ configure_shell_profile() {
|
|||
tee -a "$profile_target"
|
||||
fi
|
||||
done
|
||||
# TODO: should we suggest '. $PROFILE_NIX_FILE'? It would get them on
|
||||
# their way less disruptively, but a counter-argument is that they won't
|
||||
# immediately notice if something didn't get set up right?
|
||||
reminder "Nix won't work in active shell sessions until you restart them."
|
||||
}
|
||||
|
||||
cert_in_store() {
|
||||
# in a subshell
|
||||
# - change into the cert-file dir
|
||||
# - get the phyiscal pwd
|
||||
# and test if this path is in the Nix store
|
||||
[[ "$(cd -- "$(dirname "$NIX_SSL_CERT_FILE")" && exec pwd -P)" == "$NIX_ROOT/store/"* ]]
|
||||
}
|
||||
|
||||
setup_default_profile() {
|
||||
_sudo "to installing a bootstrapping Nix in to the default Profile" \
|
||||
task "Setting up the default profile"
|
||||
_sudo "to install a bootstrapping Nix in to the default profile" \
|
||||
HOME="$ROOT_HOME" "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_NIX"
|
||||
|
||||
if [ -z "${NIX_SSL_CERT_FILE:-}" ] || ! [ -f "${NIX_SSL_CERT_FILE:-}" ]; then
|
||||
_sudo "to installing a bootstrapping SSL certificate just for Nix in to the default Profile" \
|
||||
if [ -z "${NIX_SSL_CERT_FILE:-}" ] || ! [ -f "${NIX_SSL_CERT_FILE:-}" ] || cert_in_store; then
|
||||
_sudo "to install a bootstrapping SSL certificate just for Nix in to the default profile" \
|
||||
HOME="$ROOT_HOME" "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_CACERT"
|
||||
export NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt
|
||||
fi
|
||||
|
@ -645,9 +780,13 @@ setup_default_profile() {
|
|||
# Have to explicitly pass NIX_SSL_CERT_FILE as part of the sudo call,
|
||||
# otherwise it will be lost in environments where sudo doesn't pass
|
||||
# all the environment variables by default.
|
||||
_sudo "to update the default channel in the default profile" \
|
||||
HOME="$ROOT_HOME" NIX_SSL_CERT_FILE="$NIX_SSL_CERT_FILE" "$NIX_INSTALLED_NIX/bin/nix-channel" --update nixpkgs \
|
||||
|| channel_update_failed=1
|
||||
if ! _sudo "to update the default channel in the default profile" \
|
||||
HOME="$ROOT_HOME" NIX_SSL_CERT_FILE="$NIX_SSL_CERT_FILE" "$NIX_INSTALLED_NIX/bin/nix-channel" --update nixpkgs; then
|
||||
reminder <<EOF
|
||||
I had trouble fetching the nixpkgs channel (are you offline?)
|
||||
To try again later, run: sudo -i nix-channel --update nixpkgs
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -662,6 +801,17 @@ EOF
|
|||
}
|
||||
|
||||
main() {
|
||||
# TODO: I've moved this out of validate_starting_assumptions so we
|
||||
# can fail faster in this case. Sourcing install-darwin... now runs
|
||||
# `touch /` to detect Read-only root, but it could update times on
|
||||
# pre-Catalina macOS if run as root user.
|
||||
if [ $EUID -eq 0 ]; then
|
||||
failure <<EOF
|
||||
Please do not run this script with root privileges. We will call sudo
|
||||
when we need to.
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
# shellcheck source=./install-darwin-multi-user.sh
|
||||
. "$EXTRACTED_NIX_PATH/install-darwin-multi-user.sh"
|
||||
|
@ -675,17 +825,24 @@ main() {
|
|||
welcome_to_nix
|
||||
chat_about_sudo
|
||||
|
||||
cure_artifacts
|
||||
# TODO: there's a tension between cure and validate. I moved the
|
||||
# the sudo/root check out of validate to the head of this func.
|
||||
# Cure is *intended* to subsume the validate-and-abort approach,
|
||||
# so it may eventually obsolete it.
|
||||
validate_starting_assumptions
|
||||
|
||||
setup_report
|
||||
|
||||
if ! ui_confirm "Ready to continue?"; then
|
||||
ok "Alright, no changes have been made :)"
|
||||
contactme
|
||||
get_help
|
||||
trap finish_cleanup EXIT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
poly_prepare_to_install
|
||||
|
||||
create_build_group
|
||||
create_build_users
|
||||
create_directories
|
||||
|
@ -695,6 +852,7 @@ main() {
|
|||
configure_shell_profile
|
||||
|
||||
set +eu
|
||||
# shellcheck disable=SC1091
|
||||
. /etc/profile
|
||||
set -eu
|
||||
|
||||
|
@ -706,5 +864,20 @@ main() {
|
|||
trap finish_success EXIT
|
||||
}
|
||||
|
||||
# set an empty initial arg for bare invocations in case we need to
|
||||
# disambiguate someone directly invoking this later.
|
||||
if [ "${#@}" = 0 ]; then
|
||||
set ""
|
||||
fi
|
||||
|
||||
main
|
||||
# ACTION for override
|
||||
case "${1-}" in
|
||||
# uninstall)
|
||||
# shift
|
||||
# uninstall "$@";;
|
||||
# install == same as the no-arg condition for now (but, explicit)
|
||||
""|install)
|
||||
main;;
|
||||
*) # holding space for future options (like uninstall + install?)
|
||||
failure "install-multi-user: invalid argument";;
|
||||
esac
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue