Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/manual/src/SUMMARY.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- [Prerequisites](installation/prerequisites-source.md)
- [Obtaining a Source Distribution](installation/obtaining-source.md)
- [Building Nix from Source](installation/building-source.md)
- [Using Nix within Docker](installation/installing-docker.md)
- [Security](installation/nix-security.md)
- [Single-User Mode](installation/single-user.md)
- [Multi-User Mode](installation/multi-user.md)
Expand Down
59 changes: 59 additions & 0 deletions doc/manual/src/installation/installing-docker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Using Nix within Docker

To run the latest stable release of Nix with Docker run the following command:

```console
$ docker -ti run nixos/nix
Unable to find image 'nixos/nix:latest' locally
latest: Pulling from nixos/nix
5843afab3874: Pull complete
b52bf13f109c: Pull complete
1e2415612aa3: Pull complete
Digest: sha256:27f6e7f60227e959ee7ece361f75d4844a40e1cc6878b6868fe30140420031ff
Status: Downloaded newer image for nixos/nix:latest
35ca4ada6e96:/# nix --version
nix (Nix) 2.3.12
35ca4ada6e96:/# exit
```

# What is included in Nix' Docker image?

The official Docker image is created using `pkgs.dockerTools.buildLayeredImage`
(and not with `Dockerfile` as it is usual with Docker images). You can still
base your custom Docker image on it as you would do with any other Docker
image.

The Docker image is also not based on any other image and includes minimal set
of runtime dependencies that are required to use Nix:

- pkgs.nix
- pkgs.bashInteractive
- pkgs.coreutils-full
- pkgs.gnutar
- pkgs.gzip
- pkgs.gnugrep
- pkgs.which
- pkgs.curl
- pkgs.less
- pkgs.wget
- pkgs.man
- pkgs.cacert.out
- pkgs.findutils

# Docker image with the latest development version of Nix

To get the latest image that was built by [Hydra](https://hydra.nixos.org) run
the following command:

```console
$ curl -L https://hydra.nixos.org/job/nix/master/dockerImage.x86_64-linux/latest/download/1 | docker load
$ docker run -ti nix:2.5pre20211105
```

You can also build a Docker image from source yourself:

```console
$ nix build ./\#hydraJobs.dockerImage.x86_64-linux
$ docker load -i ./result
$ docker run -ti nix:2.5pre20211105
```
264 changes: 264 additions & 0 deletions docker.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
{ pkgs ? import <nixpkgs> { }
, lib ? pkgs.lib
, name ? "nix"
, tag ? "latest"
, crossSystem ? null
, channelName ? "nixpkgs"
, channelURL ? "https://nixos.org/channels/nixpkgs-unstable"
}:
let
buildPkgs = pkgs;
targetPkgs =
if crossSystem != null && crossSystem != pkgs.system
then {
aarch64-linux = pkgs.pkgsCross.aarch64-multiplatform;
armv7l-linux = pkgs.pkgsCross.armv7l-hf-multiplatform.system;
x86_64-linux = pkgs.pkgsCross.gnu64;
powerpc64le-linux = pkgs.pkgsCross.musl-power;
i686-linux = pkgs.pkgsCross.gnu32;
}.${crossSystem}
else pkgs;

defaultPkgs = with targetPkgs; [
nix
bashInteractive
coreutils-full
gnutar
gzip
gnugrep
which
curl
less
wget
man
cacert.out
findutils
];

users = {

root = {
uid = 0;
shell = "/bin/bash";
home = "/root";
gid = 0;
};

} // lib.listToAttrs (
map
(
n: {
name = "nixbld${toString n}";
value = {
uid = 30000 + n;
gid = 30000;
groups = [ "nixbld" ];
description = "Nix build user ${toString n}";
};
}
)
(lib.lists.range 1 32)
);

groups = {
root.gid = 0;
nixbld.gid = 30000;
};

userToPasswd = (
k:
{ uid
, gid ? 65534
, home ? "/var/empty"
, description ? ""
, shell ? "/bin/false"
, groups ? [ ]
}: "${k}:x:${toString uid}:${toString gid}:${description}:${home}:${shell}"
);
passwdContents = (
lib.concatStringsSep "\n"
(lib.attrValues (lib.mapAttrs userToPasswd users))
);

userToShadow = k: { ... }: "${k}:!:1::::::";
shadowContents = (
lib.concatStringsSep "\n"
(lib.attrValues (lib.mapAttrs userToShadow users))
);

# Map groups to members
# {
# group = [ "user1" "user2" ];
# }
groupMemberMap = (
let
# Create a flat list of user/group mappings
mappings = (
builtins.foldl'
(
acc: user:
let
groups = users.${user}.groups or [ ];
in
acc ++ map
(group: {
inherit user group;
})
groups
)
[ ]
(lib.attrNames users)
);
in
(
builtins.foldl'
(
acc: v: acc // {
${v.group} = acc.${v.group} or [ ] ++ [ v.user ];
}
)
{ }
mappings)
);

groupToGroup = k: { gid }:
let
members = groupMemberMap.${k} or [ ];
in
"${k}:x:${toString gid}:${lib.concatStringsSep "," members}";
groupContents = (
lib.concatStringsSep "\n"
(lib.attrValues (lib.mapAttrs groupToGroup groups))
);

nixConf = {
sandbox = "false";
build-users-group = "nixbld";
trusted-public-keys = "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=";
};
nixConfContents = (lib.concatStringsSep "\n" (lib.mapAttrsFlatten (n: v: "${n} = ${v}") nixConf)) + "\n";

baseSystem =
let
nixpkgs = targetPkgs.path;
channel = targetPkgs.runCommand "channel-nixos" { } ''
mkdir $out
ln -s ${nixpkgs} $out/nixpkgs
echo "[]" > $out/manifest.nix
'';
rootEnv = pkgs.buildEnv {
name = "root-profile-env";
paths = defaultPkgs;
};
profile = targetPkgs.runCommand "user-environment" { } ''
mkdir $out
cp -a ${rootEnv}/* $out/

cat > $out/manifest.nix <<EOF
[
${lib.concatStringsSep "\n" (builtins.map (drv: let
outputs = drv.outputsToInstall or [ "out" ];
in ''
{
${lib.concatStringsSep "\n" (builtins.map (output: ''
${output} = { outPath = "${lib.getOutput output drv}"; };
'') outputs)}
outputs = [ ${lib.concatStringsSep " " (builtins.map (x: "\"${x}\"") outputs)} ];
name = "${drv.name}";
outPath = "${drv}";
system = "${drv.system}";
type = "derivation";
meta = { };
}
'') defaultPkgs)}
]
EOF
'';
in
targetPkgs.runCommand "base-system"
{
inherit passwdContents groupContents shadowContents nixConfContents;
passAsFile = [
"passwdContents"
"groupContents"
"shadowContents"
"nixConfContents"
];
allowSubstitutes = false;
preferLocalBuild = true;
} ''
env
set -x
mkdir -p $out/etc

cat $passwdContentsPath > $out/etc/passwd
echo "" >> $out/etc/passwd

cat $groupContentsPath > $out/etc/group
echo "" >> $out/etc/group

cat $shadowContentsPath > $out/etc/shadow
echo "" >> $out/etc/shadow

mkdir -p $out/usr
ln -s /nix/var/nix/profiles/share $out/usr/

mkdir -p $out/nix/var/nix/gcroots

mkdir $out/tmp

mkdir -p $out/etc/nix
cat $nixConfContentsPath > $out/etc/nix/nix.conf

mkdir -p $out/root
mkdir -p $out/nix/var/nix/profiles/per-user/root

ln -s ${profile} $out/nix/var/nix/profiles/default-1-link
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's better to initialize the profile by running nix-env -i ${defaultPkgs} or something like that. That way we don't have to generate an (old-style) manifest.nix here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% but if I remember correctly I wasn't able to generate profile with nix-env. Maybe @adisbladis knows more about since this is version of creating profiles.

ln -s $out/nix/var/nix/profiles/default-1-link $out/nix/var/nix/profiles/default
ln -s /nix/var/nix/profiles/default $out/root/.nix-profile

ln -s ${channel} $out/nix/var/nix/profiles/per-user/root/channels-1-link
ln -s $out/nix/var/nix/profiles/per-user/root/channels-1-link $out/nix/var/nix/profiles/per-user/root/channels

mkdir -p $out/root/.nix-defexpr
ln -s $out/nix/var/nix/profiles/per-user/root/channels $out/root/.nix-defexpr/channels
echo "${channelURL} ${channelName}" > $out/root/.nix-channels

mkdir -p $out/bin $out/usr/bin
ln -s ${targetPkgs.coreutils}/bin/env $out/usr/bin/env
ln -s ${targetPkgs.bashInteractive}/bin/bash $out/bin/sh
'';

in
targetPkgs.dockerTools.buildLayeredImageWithNixDb {

inherit name tag;

contents = [ baseSystem ];

extraCommands = ''
rm -rf nix-support
ln -s /nix/var/nix/profiles nix/var/nix/gcroots/profiles
'';

config = {
Cmd = [ "/root/.nix-profile/bin/bash" ];
Env = [
"USER=root"
"PATH=${lib.concatStringsSep ":" [
"/root/.nix-profile/bin"
"/nix/var/nix/profiles/default/bin"
"/nix/var/nix/profiles/default/sbin"
]}"
"MANPATH=${lib.concatStringsSep ":" [
"/root/.nix-profile/share/man"
"/nix/var/nix/profiles/default/share/man"
]}"
"SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
"GIT_SSL_CAINFO=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
"NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
"NIX_PATH=/nix/var/nix/profiles/per-user/root/channels:/root/.nix-defexpr/channels"
];
};

}
7 changes: 7 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,13 @@
installerScript = installScriptFor [ "x86_64-linux" "i686-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" "armv6l-linux" "armv7l-linux" ];
installerScriptForGHA = installScriptFor [ "x86_64-linux" "x86_64-darwin" "armv6l-linux" "armv7l-linux"];

# docker image with Nix inside
dockerImage = nixpkgs.lib.genAttrs linux64BitSystems (system:
import ./docker.nix {
pkgs = nixpkgsFor.${system};
tag = version;
});

# Line coverage analysis.
coverage =
with nixpkgsFor.x86_64-linux;
Expand Down