aboutsummaryrefslogtreecommitdiff
path: root/src/nix/install.sh
blob: 2fc436743f501f15426a2e8c4f7110dfc76bc540 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/bin/bash
# Move to the same directory as this script
set -e
FEATURE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "${FEATURE_DIR}"

# Option defaults
VERSION="${VERSION:-"latest"}"
MULTIUSER="${MULTIUSER:-"true"}"
PACKAGES="${PACKAGES//,/ }"
FLAKEURI="${FLAKEURI:-""}"
USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"

# Nix keys for securly verifying installer download signature per https://nixos.org/download.html#nix-verify-installation
NIX_GPG_KEYS="B541D55301270E0BCF15CA5D8170B4726D7198DE"
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com:80
keyserver hkps://keys.openpgp.org
keyserver hkp://keyserver.pgp.com"

if [ "$(id -u)" -ne 0 ]; then
    echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
    exit 1
fi

# Import common utils
. ./utils.sh

detect_user USERNAME

if [ -e "/nix" ]; then
    echo "(!) Nix is already installed! Skipping installation."
else
    if [ "${USERNAME}" = "root" ] && [ "${MULTIUSER}" != "true" ]; then
        echo "(!) A single user install is not allowed for root. Add a non-root user to your image or set multiUser to true in your feature configuration."
        exit 1
    fi

    # Verify dependencies
    apt_get_update_if_exists
    check_command curl "curl ca-certificates" "curl ca-certificates" "curl ca-certificates"
    check_command gpg2 gnupg2 gnupg gnupg2
    check_command dirmngr dirmngr dirmngr dirmngr
    check_command xz xz-utils xz xz
    check_command git git git git
    check_command xargs findutils findutils findutils

    # Determine version
    find_version_from_git_tags VERSION https://github.com/NixOS/nix "tags/"

    # Download and verify install per https://nixos.org/download.html#nix-verify-installation
    tmpdir="$(mktemp -d)"
    echo "(*) Downloading Nix installer..."
    set +e
    curl -sSLf -o "${tmpdir}/install-nix" https://releases.nixos.org/nix/nix-${VERSION}/install
    exit_code=$?
    set -e
    if [ "$exit_code" != "0" ]; then
        # Handle situation where git tags are ahead of what was is available to actually download
        echo "(!) Nix version ${VERSION} failed to download. Attempting to fall back one version to retry..."
        find_prev_version_from_git_tags VERSION https://github.com/NixOS/nix "tags/"
        curl -sSLf -o "${tmpdir}/install-nix" https://releases.nixos.org/nix/nix-${VERSION}/install
    fi
    curl -sSLf -o "${tmpdir}/install-nix.asc" https://releases.nixos.org/nix/nix-${VERSION}/install.asc
    cd "${tmpdir}"
    receive_gpg_keys NIX_GPG_KEYS
    gpg2 --verify ./install-nix.asc
    cd "${FEATURE_DIR}"

    # Do a multi or single-user setup based on feature config
    if [ "${MULTIUSER}" = "true" ]; then
        echo "(*) Performing multi-user install..."
        sh "${tmpdir}/install-nix" --daemon
    else
        home_dir="$(eval echo ~${USERNAME})"
        if [ ! -e "${home_dir}" ]; then
            echo "(!) Home directory ${home_dir} does not exist for ${USERNAME}. Nix install will fail."
            exit 1
        fi
        echo "(*) Performing single-user install..."
        echo -e "\n**NOTE: Nix will only work for user ${USERNAME} on Linux if the host machine user's UID is $(id -u ${USERNAME}). You will need to chown /nix otherwise.**\n"    
        # Install per https://nixos.org/manual/nix/stable/installation/installing-binary.html#single-user-installation
        mkdir -p /nix
        chown ${USERNAME} /nix ${tmpdir}
        su ${USERNAME} -c "sh \"${tmpdir}/install-nix\" --no-daemon --no-modify-profile"
        # nix installer does not update ~/.bashrc, and USER may or may not be defined, so update rc/profile files directly to handle that
        snippet='
        if [ "${PATH#*$HOME/.nix-profile/bin}" = "${PATH}" ]; then if [ -z "$USER" ]; then USER=$(whoami); fi; . $HOME/.nix-profile/etc/profile.d/nix.sh; fi
        '
        update_rc_file "$home_dir/.bashrc" "${snippet}"
        update_rc_file "$home_dir/.zshenv" "${snippet}"
        update_rc_file "$home_dir/.profile" "${snippet}"    
    fi
    rm -rf "${tmpdir}" "/tmp/tmp-gnupg"
fi

# Set nix config
mkdir -p /etc/nix
create_or_update_file /etc/nix/nix.conf 'sandbox = false' 
if  [ ! -z "${FLAKEURI}" ] && [ "${FLAKEURI}" != "none" ]; then
    create_or_update_file /etc/nix/nix.conf 'experimental-features = nix-command flakes'
fi

# Create entrypoint if needed
if [ ! -e "/usr/local/share/nix-entrypoint.sh" ]; then
    if [ "${MULTIUSER}" = "true" ]; then
        echo "(*) Setting up entrypoint..."
        cp -f nix-entrypoint.sh /usr/local/share/
    else
        echo -e '#!/bin/bash\nexec "$@"' > /usr/local/share/nix-entrypoint.sh
    fi
    chmod +x /usr/local/share/nix-entrypoint.sh
fi

# Install packages, flakes, etc if specified
chmod +x,o+r ${FEATURE_DIR} ${FEATURE_DIR}/post-install-steps.sh
if [ "${MULTIUSER}" = "true" ]; then
    /usr/local/share/nix-entrypoint.sh
    su ${USERNAME} -c "
        . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
        ${FEATURE_DIR}/post-install-steps.sh
    "
else
    su ${USERNAME} -c "
        . \$HOME/.nix-profile/etc/profile.d/nix.sh
        ${FEATURE_DIR}/post-install-steps.sh
    "
fi

echo "Done!"