We had a macOS user present in Matrix with some confusion because the
lack of a clear task statement here made them think the error meant
that a problem had occurred during the preceding task in a macOS
install: "Fixing any leftover Nix volume state"
This adds an explicit unmount of the store volume to avoid cases
where the installer can hang in await_volume when:
- the user already has a store volume
- that volume is already mounted somewhere other than /nix
- they do not take a path through the installer that results in an
explicit unmount (as both removing and encrypting the volume
would do)
ShellCheck correctly warns:
In scripts/install-nix-from-closure.sh line 218:
echo -e "\nif [ -e $p ]; then . $p; fi # added by Nix installer" >> "$fn"
^-- SC3037: In POSIX sh, echo flags are undefined.
In scripts/install-nix-from-closure.sh line 229:
echo -e "\nif [ -e $p ]; then . $p; fi # added by Nix installer" >> "$fn"
^-- SC3037: In POSIX sh, echo flags are undefined.
Indeed, this actually breaks on Ubuntu where /bin/sh is dash.
Fixes#5458.
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
As reported in #5198, volume creation can fail with a permission error
for some macOS users (probably secondary user accounts?) Sudo appears
to be sufficient to avoid this.
While I'm here, I also updated the sudo invocation added in 079bde2ae
to use the _sudo explanation wrapper.
This reverts commit 909d8cb293.
This messes up PATH priority since /etc/profile gets sourced AFTER
/etc/zshenv and it sets the system paths so
$HOME/.nix-profile/bin:/nix/var/nix/profiles/default/bin is behind
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin. See discussion in
https://github.com/NixOS/nix/issues/4169.
When commit 233b61d3d6 (#4224) renamed
@binaryTarball_${system}@ to @tarballHash_${system}@, it updated this
reference for every platform except Darwin.arm64.
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
While the progress dots during the copying of the store work fine on a
normal terminal, those look pretty off if the script is run inside a
provisioning script of e.g. `vagrant` or `packer` where `stderr` and
`stdout` are captured:
default: .
default: ..
default: .
default: .
default: .
To work around this, the script checks with `-t 0` if it's
running on an actual terminal and doesn't show the progress if that's not
the case.
gnu-config standardized on aarch64 for machine name so host_cpu part
of $system will always be aarch64. That means system will be
aarch64-darwin too.
uname however could report either “aarch64” (if gnu coreutils) or
“arm64” (if apple’s uname). We should support both for compatiblity
here.
NIX_PROFILES is space separated list of directories, and passing it into
for as is is considered to be 1-element list with the whole string. With
shwordsplit option Zsh emulates other shells in this regard ans
implicitely splits unquoted strings into words.
Fixes#4167.
Env vars for ZSH were moved from /etc/zshrc to /etc/zshenv in #3608
to address an issue with zshrc getting clobbered by OS updates, but
/etc/zshenv doesn't exist by default--so *nothing* would get set up
for zsh users unless they already happened to have /etc/zshenv.
Creating these files if they don't exist. Also cut separate creation
of profile.d/nix.sh, which isn't needed now.
Some of the changes in #3788 to support non-systemd Nix installs
don't appear to be aware that the darwin installer exists, which
resulted in some skipped steps and inappropriate instructions.
As mentioned in previous commit, Big Sur changes the syntax for the
xpath command slightly.
In the process of testing out replacements for these, I noticed a few
small simplification wins.
- xpath -> xmllint: xpath's cli interface changed in Big Sur
rather than add conditional logic for picking the correct
syntax for xpath, I'm changing to xmllint --xpath, which
appears to be consistent across versions I've tested...
- /plist/dict/key[text()='Writable']/following-sibling::true[1]
doesn't do quite what's expected. It was written to try to
select a <true /> node paired with the Writable key, but it
will also select the *next* <true /> node that appears even
if it was paired with another key.
- I think there's also a logic bug in the conditionals here.
I'm not sure anyone ever actuall saw it, thanks to the xpath
bug, though. With the xpath fix, this conditional passes if /nix
does not exist, / IS writable, and the version is Catalina+.
I think it meant to test for /nix does not exist, / is NOT
writable, and the version is Catalina+. I reworked this lightly
to make it a little clearer at the code level.
On macOS the system tar has builtin support for lzma while xz isn't
available as a separate binary. There's no builtin package manager
there available either so having to install lzma (without nix) would be
rather painful.
This should handle installation scenarios we can handle with
anything resembling confidence. Goal is approximating the existing
setup--not enforcing a best-practice...
Approaches (+ installer-handled, - manual) and configs each covers:
+ no change needed; /nix OK on boot volume:
All pre-Catalina (regardless of T2 or FileVault use)
+ create new unencrypted volume:
Catalina, pre-T2, no FileVault
+ create new encrypted-at-rest volume:
Catalina, pre-T2, FileVault
Catalina, T2, no FileVault
- require user to pre-create encrypted volume
Catalina, T2, FileVault
The default login shell for users on macOS 10.15 changed from bash to
zsh. So while generally nonstandard we need to configure it to make nix
function out of the box on macOS.
Starting macOS 10.15 /nix can't be creasted directly anymore due to the
readonly filesystem, but synthetic.conf was introduced to enable
creating mountpoints or symlinks for special usecases like package
managers.
The install-multi-user script uses blue, green, and red colors, as
well as bold and underline, to add helpful formatting that helps
structure its rather voluminous output.
Unfortunately, the terminal escape sequences it uses are not quite
well-formed. The relevant information is all there, just obscured
by some extra noise, a leading parameter `38`. Empirically, the
result is:
* On macOS, in both Terminal.app and iTerm2, the spurious `38` is
ignored, the rest of the escape sequence is applied, and the colors
show up as intended.
* On Linux, in at least gnome-terminal and xterm, the spurious `38`
and the next parameter after it are ignored, and what's left is
applied. So in the sequence `38;4;32`, the 4 (underline) is
ignored but the 32 (green) takes effect; in a more typical sequence
like `38;34`, the 34 (blue) is ignored and nothing happens.
These codes are all unchanged since this script's origins as a
Darwin-only script -- so the fact that they work fine in common macOS
terminals goes some way to explain how the bug arose.
Happily, we can make the colors work as intended by just deleting the
extra `38;`. Tested in all four terminals mentioned above; the new
codes work correctly on all of them, and on the two macOS terminals
they work exactly the same as before.
---
In a bit more technical detail -- perhaps more than anyone, me
included, ever wanted to know, but now that I've gone and learned it
I'll write it down anyway :) -- here's what's happening in these codes:
An ECMA-48 "control sequence" begins with `\033[` aka "CSI", contains
any number of parameters as semicolon-separated decimal numbers (plus
sometimes other wrinkles), and ends with a byte from 0x40..0x7e. In
our case, with `m` aka "SGR", "Select Graphic Rendition".
An SGR control sequence `\033[...m` sets colors, fonts, text styles,
etc. In particular a parameter `31` means red, `32` green, `34` blue,
`4` underline, and `0` means reset to normal. Those are all we use.
There is also a `38`. This is used for setting colors too... but it
needs arguments. `38;5;nn` is color nn from a 256-color palette, and
`38;2;rr;gg;bb` has the given RGB values.
There is no meaning defined for `38;1` or `38;34` etc. On seeing a
parameter `38` followed by an unrecognized argument for it, apparently
some implementations (as seen on macOS) discard only the `38` and
others (as seen on Linux) discard the argument too before resuming.
After installing Nix, I found that all the files and directories
initially copied into the store were writable, with mode 644 or 755:
drwxr-xr-x 9 root root 4096 Dec 31 1969 /nix/store/ddmmzn4ggz1f66lwxjy64n89864yj9w9-nix-2.3.3
The reason is that that's how they were in the unpacked tarball, and
the install-multi-user script used `rsync -p` without doing anything
else to affect the permissions.
The plain `install` script for a single-user install takes care to
do a `chmod -R a-w` on each store path copied. We could do the same
here with one more command; or we can pass `--chmod` to rsync, to
have it write the files with the desired modes in the first place.
Tested the new `rsync` command on both a Linux machine with a
reasonably-modern rsync (3.1.3) and a Mac with its default, ancient,
rsync 2.6.9, and it works as expected on both. Thankfully the latter
is just new enough to have `--chmod`, which dates to rsync 2.6.7.
On a systemd-based Linux distribution: If the user has previously had multi-user Nix installed on the system, removed it and then reinstalled multi-user Nix again the old nix-daemon.service will still be running when `scripts/install-systemd-multi-user.sh` tries to start it which results in nothing being done and the old daemon continuing its run.
When a normal user then tries to use Nix through the daemon the nix binary will fail to connect to the nix-daemon as it does not belong to the currently installed Nix system. See below for steps to reproduce the issue that motivated this change.
$ sh <(curl https://nixos.org/nix/install) --daemon
$ sudo rm -rf /etc/nix /nix /root/.nix-profile /root/.nix-defexpr /root/.nix-channels /home/nix-installer/.nix-profile /home/nix-installer/.nix-defexpr /home/nix-installer/.nix-channels ~/.nix-channels ~/.nix-defexpr/ ~/.nix-profile /etc/profile.d/nix.sh.backup-before-nix /etc/profile.d/nix.sh; sed -i '/added by Nix installer$/d' ~/.bash_profile
$ unset NIX_REMOTE
$ sh <(curl https://nixos.org/nix/install) --daemon
└$ export NIX_REMOTE=daemon
└$ nix-env -iA nixpkgs.hello
installing 'hello-2.10'
error: cannot connect to daemon at '/nix/var/nix/daemon-socket/socket': No such file or directory
(use '--show-trace' to show detailed location information)
└$ sudo systemctl restart nix-daemon.service
└$ nix-env -iA nixpkgs.hello
installing 'hello-2.10'
these paths will be fetched (6.09 MiB download, 27.04 MiB unpacked):
/nix/store/2g75chlbpxlrqn15zlby2dfh8hr9qwbk-hello-2.10
/nix/store/aag9d1y4wcddzzrpfmfp9lcmc7skd7jk-glibc-2.27
copying path '/nix/store/aag9d1y4wcddzzrpfmfp9lcmc7skd7jk-glibc-2.27' from 'https://cache.nixos.org'...
copying path '/nix/store/2g75chlbpxlrqn15zlby2dfh8hr9qwbk-hello-2.10' from 'https://cache.nixos.org'...
building '/nix/store/w9adagg6vlikr799nkkqc9la5hbbpgmi-user-environment.drv'...
created 2 symlinks in user environment
In the multi-user install script, we originally made sure no previous
references to Nix existed. This prevented any previous installs from
contaminating the new install. However, some users need the ability to
repair their existing Nix installation without uninstalling all
references to Nix. This change allows users with existing Nix
installations to use the installer, while still outputing a warning
message on the dangers of this. As a result, the multi-user install
script work much more like the single-user install script has worked
in the past.
This is a requirement for macOS Catalina users now that
/Library/LaunchDaemons/org.nixos.nix-daemon.plisg is not managed by
the Nix store. If there is ever a change to the .plist, all users will
need to rerun this install script to get the new changes. Otherwise,
changes to the launch daemon will require manual interventions.
On Catalina, the /nix filesystem might not be mounted at start time.
To avoid this service not starting, we need to keep the launch agent
outside of the Nix store. A wait4pid will hold for our /nix dir to be
mounted.
Fixes#3125.