Unverified Commit 0752a52b authored by Chuck Lantz's avatar Chuck Lantz Committed by GitHub

Nix feature (#228)

parent 748be932
......@@ -38,6 +38,7 @@ jobs:
"rust",
"sshd",
"terraform",
"nix",
]
baseImage:
[
......@@ -88,6 +89,7 @@ jobs:
"rust",
"sshd",
"terraform",
"nix",
]
steps:
- uses: actions/checkout@v2
......
......@@ -38,6 +38,7 @@ jobs:
rust: ./**/rust/**
sshd: ./**/sshd/**
terraform: ./**/terraform/**
nix: ./**/nix/**
test:
needs: [detect-changes]
......
## OS Support
This Feature should work on recent versions of Debian/Ubuntu, RedHat Enterprise Linux, Fedora, RockyLinux, and Alpine Linux.
## Location of Flakes
Currently `flakeUri` works best with a remote URI (e.g., `github:nixos/nixpkgs/nixpkgs-unstable#hello`) as local files need to be in the image.
> Proposed support for lifecycle hooks in Features ([#60](https://github.com/devcontainers/spec/issues/60)) would allow for expressions files or Flakes to exist in the source tree to be automatically installed on initial container startup, but today you will have to manually add the appropriate install command to `postCreateCommand` to your `devcontainer.json` instead.
## Multi-user vs. single-user installs
This Dev Container Feature supports two installation models for Nix: multi-user and single user. Multi-user is the default, but each has pros and cons.
| Installation Model | Pros | Cons |
| --- | --- | --- |
| *Multi-User* | Nix can be used with any user including root.<br /><br />Also still works if the UID or GID of any user is updated. | Only works with Nix 2.11 and up due to a Nix installer limitation.<br /><br />Container must run either: run as root (but `remoteUser` in devcontainer.json can be non-root), or includes `sudo` with the `remoteUser` being configured to use it. <br /><br />Note that automated start of the `nix-daemon` requires passwordless `sudo` if the container itself (e.g., `containerUser`) is not running as root. Manual startup using `sudo` can require a password, however (more next). |
| *Single-User* | Does not require the container to run as root or `sudo` to be included in the image. | Only works with the user specified in the `userName` property or an auto-detected user. If this user's UID/GID is updated, that user will no longer be able to work with Nix. This is primarily a consideration when running on Linux where the UID/GID is sync'd to the local user. |
### Manually starting the Nix daemon
If you have `sudo` in your base image, but have a password set so automatic startup is not possible, you can manually start the Nix daemon by running the following command in a terminal:
```bash
sudo /usr/local/share/nix-entrypoint.sh
```
This same command can be used to restart the daemon if it has stopped for some reason. Logs are available at `/tmp/nix-daemon.log`.
\ No newline at end of file
{
"id": "nix",
"version": "1.0.0",
"name": "Nix Package Manager",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/nix",
"description": "Installs the Nix package manager and optionally a set of packages.",
"options": {
"version": {
"type": "string",
"proposals": ["latest", "2.11"],
"default": "latest",
"description": "Version of Nix to install."
},
"multiUser": {
"type": "boolean",
"default": true,
"description": "Perform a multi-user install (instead of single user)"
},
"packages": {
"type": "string",
"default": "",
"description": "Optional comma separated list of Nix packages to install in profile."
},
"flakeUri": {
"type": "string",
"default": "",
"description": "Optional URI to a Nix Flake to install in profile."
}
},
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
],
"containerEnv": {
"PATH": "/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:${PATH}"
},
"entrypoint": "/usr/local/share/nix-entrypoint.sh"
}
\ No newline at end of file
#!/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!"
\ No newline at end of file
#!/bin/bash
# Attempt to start daemon
set +e
if ! pidof nix-daemon > /dev/null 2>&1; then
start_ok=false
if [ "$(id -u)" = "0" ]; then
( . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh; /nix/var/nix/profiles/default/bin/nix-daemon > /tmp/nix-daemon.log 2>&1 ) &
if [ "$?" = "0" ]; then
start_ok=true
fi
elif type sudo > /dev/null 2>&1; then
sudo -n sh -c '. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh; /nix/var/nix/profiles/default/bin/nix-daemon > /tmp/nix-daemon.log 2>&1' &
if [ "$?" = "0" ]; then
start_ok=true
fi
fi
if [ "${start_ok}" = "false" ]; then
echo -e 'Failed to start nix-daemon as root. Set multiUser to false in your feature configuraiton if you would\nprefer to run the container as a non-root. You may also start the daemon manually if you have sudo\ninstalled and configured for your user by running "sudo -c nix-daemon &"'
fi
fi
exec "$@"
#!/bin/bash
set -e
echo "(*) Executing post-installation steps..."
# Install list of packages in profile if specified.
if [ ! -z "${PACKAGES}" ] && [ "${PACKAGES}" != "none" ]; then
echo "Installing packages \"${PACKAGES}\" in profile..."
nix-env --install ${PACKAGES}
fi
# Install Nix flake in profile if specified
if [ ! -z "${FLAKEURI}" ] && [ "${FLAKEURI}" != "none" ]; then
echo "Installing flake ${FLAKEURI} in profile..."
nix profile install "${FLAKEURI}"
fi
nix-collect-garbage --delete-old
nix-store --optimise
# Function to run apt-get if needed
apt_get_update_if_needed()
{
export DEBIAN_FRONTEND=noninteractive
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
# Function to run apt-get if command exists
apt_get_update_if_exists()
{
if type apt-get > /dev/null 2>&1; then
apt-get update
fi
}
# Checks if packages are installed and installs them if not
check_packages() {
if type dpkg > /dev/null 2>&1 && dpkg -s $1 > /dev/null 2>&1; then
return 0
elif type apk > /dev/null 2>&1 && apk -e info $2 > /dev/null 2>&1; then
return 0
elif type rpm > /dev/null 2>&1 && rpm -q $3 > /dev/null 2>&1; then
return 0
else
echo "Unable to find package manager to check for packages."
exit 1
fi
install_packages "$@"
return $?
}
# Checks if command exists, installs it if not
# check_command <command> "<apt packages to install>" "<apk packages to install>" "<dnf/yum packages to install>"
check_command() {
command_to_check=$1
shift
if type "${command_to_check}" > /dev/null 2>&1; then
return 0
fi
install_packages "$@"
return $?
}
# Installs packages using the appropriate package manager (apt, apk, dnf, or yum)
# install_packages "<apt packages to install>" "<apk packages to install>" "<dnf/yum packages to install>"
install_packages() {
if type apt-get > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends $1
elif type apk > /dev/null 2>&1; then
apk add $2
elif type dnf > /dev/null 2>&1; then
dnf install -y $3
elif type yum > /dev/null 2>&1; then
yum install -y $3
else
echo "Unable to find package manager to install ${command_to_check}"
exit 1
fi
}
# If in automatic mode, determine if a user already exists, if not use root
detect_user() {
local user_variable_name=${1:-username}
local possible_users=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
if [ "${!user_variable_name}" = "auto" ] || [ "${!user_variable_name}" = "automatic" ]; then
declare -g ${user_variable_name}=""
for current_user in ${possible_users[@]}; do
if id -u "${current_user}" > /dev/null 2>&1; then
declare -g ${user_variable_name}="${current_user}"
break
fi
done
fi
if [ "${!user_variable_name}" = "" ] || [ "${!user_variable_name}" = "none" ] || ! id -u "${!user_variable_name}" > /dev/null 2>&1; then
declare -g ${user_variable_name}=root
fi
}
# Import the specified key in a variable name passed in as
receive_gpg_keys() {
local keys=${!1}
local keyring_args=""
if [ ! -z "$2" ]; then
mkdir -p "$(dirname \"$2\")"
keyring_args="--no-default-keyring --keyring $2"
fi
# Use a temporary locaiton for gpg keys to avoid polluting image
export GNUPGHOME="/tmp/tmp-gnupg"
mkdir -p ${GNUPGHOME}
chmod 700 ${GNUPGHOME}
echo -e "disable-ipv6\n${GPG_KEY_SERVERS}" > ${GNUPGHOME}/dirmngr.conf
# GPG key download sometimes fails for some reason and retrying fixes it.
local retry_count=0
local gpg_ok="false"
set +e
until [ "${gpg_ok}" = "true" ] || [ "${retry_count}" -eq "5" ];
do
echo "(*) Downloading GPG key..."
( echo "${keys}" | xargs -n 1 gpg -q ${keyring_args} --recv-keys) 2>&1 && gpg_ok="true"
if [ "${gpg_ok}" != "true" ]; then
echo "(*) Failed getting key, retring in 10s..."
(( retry_count++ ))
sleep 10s
fi
done
set -e
if [ "${gpg_ok}" = "false" ]; then
echo "(!) Failed to get gpg key."
exit 1
fi
}
# Figure out correct version of a three part version number is not passed
find_version_from_git_tags() {
local variable_name=$1
local requested_version=${!variable_name}
if [ "${requested_version}" = "none" ]; then return; fi
local repository=$2
# Normally a "v" is used before the version number, but support alternate cases
local prefix=${3:-"tags/v"}
# Some repositories use "_" instead of "." for version number part separation, support that
local separator=${4:-"."}
# Some tools release versions that omit the last digit (e.g. go)
local last_part_optional=${5:-"false"}
# Some repositories may have tags that include a suffix (e.g. actions/node-versions)
local version_suffix_regex=$6
local escaped_separator=${separator//./\\.}
local break_fix_digit_regex
if [ "${last_part_optional}" = "true" ]; then
break_fix_digit_regex="(${escaped_separator}[0-9]+)?"
else
break_fix_digit_regex="${escaped_separator}[0-9]+"
fi
local version_regex="[0-9]+${escaped_separator}[0-9]+${break_fix_digit_regex}${version_suffix_regex//./\\.}"
# If we're passed a matching version number, just return it, otherwise look for a version
if ! echo "${requested_version}" | grep -E "^${versionMatchRegex}$" > /dev/null 2>&1; then
local version_list="$(git ls-remote --tags ${repository} | grep -oP "${prefix}\\K${version_regex}$" | tr -d ' ' | tr "${separator}" "." | sort -rV)"
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then
declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)"
else
set +e
declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|${version_suffix_regex//./\\.}|$)")"
set -e
fi
if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then
echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2
exit 1
fi
fi
echo "Adjusted ${variable_name}=${!variable_name}"
}
# Soft version matching that resolves a version for a given package in the *current apt-cache*
# Return value is stored in first argument (the unprocessed version)
apt_cache_version_soft_match() {
# Version
local variable_name="$1"
local requested_version=${!variable_name}
# Package Name
local package_name="$2"
# Exit on no match?
local exit_on_no_match="${3:-true}"
# Ensure we've exported useful variables
. /etc/os-release
local architecture="$(dpkg --print-architecture)"
dot_escaped="${requested_version//./\\.}"
dot_plus_escaped="${dot_escaped//+/\\+}"
# Regex needs to handle debian package version number format: https://www.systutorials.com/docs/linux/man/5-deb-version/
version_regex="^(.+:)?${dot_plus_escaped}([\\.\\+ ~:-]|$)"
set +e # Don't exit if finding version fails - handle gracefully
fuzzy_version="$(apt-cache madison ${package_name} | awk -F"|" '{print $2}' | sed -e 's/^[ \t]*//' | grep -E -m 1 "${version_regex}")"
set -e
if [ -z "${fuzzy_version}" ]; then
echo "(!) No full or partial for package \"${package_name}\" match found in apt-cache for \"${requested_version}\" on OS ${ID} ${VERSION_CODENAME} (${architecture})."
if $exit_on_no_match; then
echo "Available versions:"
apt-cache madison ${package_name} | awk -F"|" '{print $2}' | grep -oP '^(.+:)?\K.+'
exit 1 # Fail entire script
else
echo "Continuing to fallback method (if available)"
return 1;
fi
fi
# Globally assign fuzzy_version to this value
# Use this value as the return value of this function
declare -g ${variable_name}="=${fuzzy_version}"
echo "${variable_name}=${!variable_name}"
}
# Checks if a marker file exists with the correct contents
# check_marker <marker path> [argument to be validated]...
check_marker() {
local marker_path="$1"
shift
local verifier_string="$(echo "$@")"
if [ -e "${marker_path}" ] && [ "${verifier_string}" = "$(cat ${marker_path})" ]; then
return 1
else
return 0
fi
}
# Updates marker for future checking
# update_marker <marker path> [argument to be validated]...
update_marker() {
local marker_path="$1"
shift
mkdir -p "$(dirname "${marker_path}")"
echo "$(echo "$@")" > "${marker_path}"
}
# run_if_exists <command> <command arguments>...
run_if_exists() {
if [ -e "$1" ]; then
"$@"
fi
}
# run_as_user_if_exists <username> <command> <command arguments>...
run_as_user_if_exists() {
local username=$1
shift
if [ -e "$1" ]; then
local command_string="$@"
su "${username}" -c "${command_string//"/\\"}"
fi
}
# symlink_if_ne <source> <target>
symlink_if_ne() {
if [ ! -e "$2" ]; then
ln -s "$1" "$2"
fi
}
# Update a rc/profile file if it exists and string is not already present
update_rc_file() {
# see if folder containing file exists
local rc_file_folder="$(dirname "$1")"
if [ ! -d "${rc_file_folder}" ]; then
echo "${rc_file_folder} does not exist. Skipping update of $1."
elif [ ! -e "$1" ] || [[ "$(cat "$1")" != *"$2"* ]]; then
echo "$2" >> "$1"
fi
}
# Update a file if with string if not already present
# create_or_update_file <file> <string>
create_or_update_file() {
if [ ! -e "$1" ] || [[ "$(cat "$1")" != *"$2"* ]]; then
echo "$2" >> "$1"
fi
}
# Use semver logic to decrement a version number then look for the closest match
find_prev_version_from_git_tags() {
local variable_name=$1
local current_version=${!variable_name}
local repository=$2
# Normally a "v" is used before the version number, but support alternate cases
local prefix=${3:-"tags/v"}
# Some repositories use "_" instead of "." for version number part separation, support that
local separator=${4:-"."}
# Some tools release versions that omit the last digit (e.g. go)
local last_part_optional=${5:-"false"}
# Some repositories may have tags that include a suffix (e.g. actions/node-versions)
local version_suffix_regex=$6
# Try one break fix version number less if we get a failure. Use "set +e" since "set -e" can cause failures in valid scenarios.
set +e
major="$(echo "${current_version}" | grep -oE '^[0-9]+' || echo '')"
minor="$(echo "${current_version}" | grep -oP '^[0-9]+\.\K[0-9]+' || echo '')"
breakfix="$(echo "${current_version}" | grep -oP '^[0-9]+\.[0-9]+\.\K[0-9]+' 2>/dev/null || echo '')"
set -e
# Handle situations like Go's odd version pattern where "0" releases omit the last part
if [ "${breakfix}" = "" ] || [ "${breakfix}" = "0" ]; then
((minor=minor-1))
declare -g ${variable_name}="${major}.${minor}"
# Look for latest version from previous minor release
find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}"
else
((breakfix=breakfix-1))
if [ "${breakfix}" = "0" ] && [ "${last_part_optional}" = "true" ]; then
declare -g ${variable_name}="${major}.${minor}"
else
declare -g ${variable_name}="${major}.${minor}.${breakfix}"
fi
fi
}
\ No newline at end of file
#!/bin/bash
set -e
# Optional: Import test library bundled with the devcontainer CLI
source dev-container-features-test-lib
uid="$(id -u)"
echo "Current user UID is ${uid}."
if [ "${uid}" != "1000" ]; then
echo "Current user UID was adjusted."
fi
set +e
vscode_uid="$(id -u vscode)"
set -e
if [ "${vscode_uid}" != "" ]; then
echo "User vscode UID is ${vscode_uid}."
if [ "${vscode_uid}" != "1000" ]; then
echo "User vscode UID was adjusted."
fi
fi
nix_uid="$(stat /nix -c "%u")"
echo "/nix UID is ${nix_uid}."
# Feature-specific tests
# The 'check' command comes from the dev-container-features-test-lib.
check "nix" type nix
check "hello" type hello
# Report result
# If any of the checks above exited with a non-zero exit code, the test will fail.
reportResults &2>1
\ No newline at end of file
#!/bin/bash
set -e
# Optional: Import test library bundled with the devcontainer CLI
source dev-container-features-test-lib
uid="$(id -u)"
echo "Current user UID is ${uid}."
if [ "${uid}" != "1000" ]; then
echo "Current user UID was adjusted."
fi
set +e
vscode_uid="$(id -u vscode)"
set -e
if [ "${vscode_uid}" != "" ]; then
echo "User vscode UID is ${vscode_uid}."
if [ "${vscode_uid}" != "1000" ]; then
echo "User vscode UID was adjusted."
fi
fi
nix_uid="$(stat /nix -c "%u")"
echo "/nix UID is ${nix_uid}."
# Feature-specific tests
# The 'check' command comes from the dev-container-features-test-lib.
check "nix-env" type nix-env
check "install" nix-env --install vim
check "vim_installed" type vim
# Report result
# If any of the checks above exited with a non-zero exit code, the test will fail.
reportResults &2>1
\ No newline at end of file
#!/bin/bash
set -e
# Optional: Import test library bundled with the devcontainer CLI
source dev-container-features-test-lib
uid="$(id -u)"
echo "Current user UID is ${uid}."
if [ "${uid}" != "1000" ]; then
echo "Current user UID was adjusted."
fi
set +e
vscode_uid="$(id -u vscode)"
set -e
if [ "${vscode_uid}" != "" ]; then
echo "User vscode UID is ${vscode_uid}."
if [ "${vscode_uid}" != "1000" ]; then
echo "User vscode UID was adjusted."
fi
fi
nix_uid="$(stat /nix -c "%u")"
echo "/nix UID is ${nix_uid}."
cat /etc/os-release
# Feature-specific tests
# The 'check' command comes from the dev-container-features-test-lib.
check "nix-env" type nix-env
check "install" nix-env --install vim
check "vim_installed" type vim
# Report result
# If any of the checks above exited with a non-zero exit code, the test will fail.
reportResults &2>1
\ No newline at end of file
#!/bin/bash
set -e
# Optional: Import test library bundled with the devcontainer CLI
source dev-container-features-test-lib
uid="$(id -u)"
echo "Current user UID is ${uid}."
nix_uid="$(stat /nix -c "%u")"
echo "/nix UID is ${nix_uid}."
cat /etc/os-release
# Feature-specific tests
# The 'check' command comes from the dev-container-features-test-lib.
check "nix-env" type nix-env
check "install" nix-env --install vim
check "vim_installed" type vim
# Report result
# If any of the checks above exited with a non-zero exit code, the test will fail.
reportResults &2>1
\ No newline at end of file
#!/bin/bash
set -e
# Optional: Import test library bundled with the devcontainer CLI
source dev-container-features-test-lib
uid="$(id -u)"
echo "Current user UID is ${uid}."
nix_uid="$(stat /nix -c "%u")"
echo "/nix UID is ${nix_uid}."
cat /etc/os-release
# Feature-specific tests
# The 'check' command comes from the dev-container-features-test-lib.
check "nix-env" type nix-env
check "install" nix-env --install vim
check "vim_installed" type vim
# Report result
# If any of the checks above exited with a non-zero exit code, the test will fail.
reportResults &2>1
\ No newline at end of file
#!/bin/bash
set -e
# Optional: Import test library bundled with the devcontainer CLI
source dev-container-features-test-lib
uid="$(id -u)"
echo "Current user UID is ${uid}."
nix_uid="$(stat /nix -c "%u")"
echo "/nix UID is ${nix_uid}."
cat /etc/os-release
# Feature-specific tests
# The 'check' command comes from the dev-container-features-test-lib.
check "nix-env" type nix-env
check "install" nix-env --install vim
check "vim_installed" type vim
# Report result
# If any of the checks above exited with a non-zero exit code, the test will fail.
reportResults &2>1
\ No newline at end of file
#!/bin/bash
set -e
# Optional: Import test library bundled with the devcontainer CLI
source dev-container-features-test-lib
uid="$(id -u)"
echo "Current user UID is ${uid}."
nix_uid="$(stat /nix -c "%u")"
echo "/nix UID is ${nix_uid}."
cat /etc/os-release
# Feature-specific tests
# The 'check' command comes from the dev-container-features-test-lib.
check "nix-env" type nix-env
check "install" nix-env --install vim
check "vim_installed" type vim
# Report result
# If any of the checks above exited with a non-zero exit code, the test will fail.
reportResults &2>1
\ No newline at end of file
#!/bin/bash
set -e
# Optional: Import test library bundled with the devcontainer CLI
source dev-container-features-test-lib
uid="$(id -u)"
echo "Current user UID is ${uid}."
if [ "${uid}" != "1000" ]; then
echo "Current user UID was adjusted."
fi
set +e
vscode_uid="$(id -u vscode)"
set -e
if [ "${vscode_uid}" != "" ]; then
echo "User vscode UID is ${vscode_uid}."
if [ "${vscode_uid}" != "1000" ]; then
echo "User vscode UID was adjusted."
fi
fi
nix_uid="$(stat /nix -c "%u")"
echo "/nix UID is ${nix_uid}."
cat /etc/os-release
# Feature-specific tests
# The 'check' command comes from the dev-container-features-test-lib.
check "nix-env" type nix-env
check "vim_installed" type vim
check "node_installed" type node
check "yarn_installed" type yarn
# Report result
# If any of the checks above exited with a non-zero exit code, the test will fail.
reportResults &2>1
\ No newline at end of file
{
"single-user-install": {
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"remoteUser": "vscode",
"features": {
"nix": {
"multiUser": false
}
}
},
"version": {
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"remoteUser": "vscode",
"features": {
"nix": {
"multiUser": false,
"version": "2.10"
}
}
},
"multi-user-install": {
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"remoteUser": "vscode",
"features": {
"nix": {
"multiUser": true
}
}
},
"os-ubuntu": {
"image": "ubuntu",
"remoteUser": "root",
"features": {
"nix": {
"multiUser": true
}
}
},
"os-debian": {
"image": "debian",
"remoteUser": "root",
"features": {
"nix": {
"multiUser": true
}
}
},
"os-rockylinux": {
"image": "rockylinux:9",
"remoteUser": "root",
"features": {
"nix": {
"multiUser": true
}
}
},
"os-fedora": {
"image": "fedora",
"remoteUser": "root",
"features": {
"nix": {
"multiUser": true
}
}
},
"os-alpine": {
"image": "mcr.microsoft.com/devcontainers/base:alpine",
"remoteUser": "vscode",
"features": {
"nix": {
"multiUser": true
}
}
},
"packages": {
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"remoteUser": "vscode",
"features": {
"nix": {
"packages": "nodejs,vim,yarn"
}
}
},
"flake": {
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"remoteUser": "vscode",
"features": {
"nix": {
"flakeUri": "github:nixos/nixpkgs/nixpkgs-unstable#hello"
}
}
}
}
\ No newline at end of file
#!/bin/bash
set -e
# Optional: Import test library bundled with the devcontainer CLI
source dev-container-features-test-lib
uid="$(id -u)"
echo "Current user UID is ${uid}."
if [ "${uid}" != "1000" ]; then
echo "Current user UID was adjusted."
fi
set +e
vscode_uid="$(id -u vscode)"
set -e
if [ "${vscode_uid}" != "" ]; then
echo "User vscode UID is ${vscode_uid}."
if [ "${vscode_uid}" != "1000" ]; then
echo -e "User vscode UID was adjusted.\nWARNING: This scenario is not expected to work, so adjusting owner on Nix."
sudo chown -R vscode /nix
fi
fi
nix_uid="$(stat /nix -c "%u")"
echo "/nix UID is ${nix_uid}."
if [ "${nix_uid}" != "${vscode_uid}" ]; then
echo -e "WARNING: User UID does not match /nix owner. This scenario is not expected to work, so adjusting owner of /nix for testing purposes."
sudo chown -R vscode /nix
fi
cat /etc/os-release
# Feature-specific tests
# The 'check' command comes from the dev-container-features-test-lib.
check "nix-env" type nix-env
check "install" nix-env --install vim
check "vim_installed" type vim
# Report result
# If any of the checks above exited with a non-zero exit code, the test will fail.
reportResults &2>1
\ No newline at end of file
#!/bin/bash
set -e
# Optional: Import test library bundled with the devcontainer CLI
source dev-container-features-test-lib
uid="$(id -u)"
echo "Current user UID is ${uid}."
if [ "${uid}" != "1000" ]; then
echo "Current user UID was adjusted."
fi
set +e
vscode_uid="$(id -u vscode)"
set -e
if [ "${vscode_uid}" != "" ]; then
echo "User vscode UID is ${vscode_uid}."
if [ "${vscode_uid}" != "1000" ]; then
echo "User vscode UID was adjusted."
fi
fi
nix_uid="$(stat /nix -c "%u")"
echo "/nix UID is ${nix_uid}."
cat /etc/os-release
# Feature-specific tests
# The 'check' command comes from the dev-container-features-test-lib.
check "nix-env" type nix-env
check "install" nix-env --install vim
check "vim_installed" type vim
# Report result
# If any of the checks above exited with a non-zero exit code, the test will fail.
reportResults &2>1
\ No newline at end of file
#!/bin/bash
set -e
# Optional: Import test library bundled with the devcontainer CLI
source dev-container-features-test-lib
uid="$(id -u)"
echo "Current user UID is ${uid}."
if [ "${uid}" != "1000" ]; then
echo "Current user UID was adjusted."
fi
set +e
vscode_uid="$(id -u vscode)"
set -e
if [ "${vscode_uid}" != "" ]; then
echo "User vscode UID is ${vscode_uid}."
if [ "${vscode_uid}" != "1000" ]; then
echo "User vscode UID was adjusted."
fi
fi
nix_uid="$(stat /nix -c "%u")"
echo "/nix UID is ${nix_uid}."
if [ "${nix_uid}" != "${vscode_uid}" ]; then
echo -e "WARNING: User UID does not match /nix owner. This scenario is not expected to work, so adjusting owner of /nix for testing purposes."
sudo chown -R vscode /nix
fi
cat /etc/os-release
# Feature-specific tests
# The 'check' command comes from the dev-container-features-test-lib.
check "nix-env" type nix-env
check "install" nix-env --install vim
check "vim_installed" type vim
# Report result
# If any of the checks above exited with a non-zero exit code, the test will fail.
reportResults &2>1
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment