Initial implementation of a buildImage function with configurable build steps, and an implementation of a mutable image building function

This commit is contained in:
Sander van der Burg 2021-02-11 23:23:02 +01:00 committed by Sander van der Burg
parent c69248bb7c
commit d347c04fd6
43 changed files with 677 additions and 173 deletions

View File

@ -935,9 +935,8 @@ To construct such as an image, we can evaluate a Nix expression (e.g.
}:
let
createMultiProcessImage = import ../../nixproc/create-multi-process-image/create-multi-process-image.nix {
inherit pkgs system;
inherit (pkgs) dockerTools stdenv;
createMultiProcessImage = import ../../nixproc/create-image-from-steps/create-multi-process-image-universal.nix {
inherit pkgs;
};
in
createMultiProcessImage {
@ -946,6 +945,7 @@ createMultiProcessImage {
exprFile = ../webapps-agnostic/processes.nix;
processManager = "supervisord"; # sysvinit, disnix, s6-rc are also valid options
interactive = true; # the default option
manpages = false; # the default option
forceDisableUserChange = false; # the default option
}
```
@ -964,6 +964,8 @@ with the following parameters:
this setting has been enabled, a `.bashrc` will be configured to make
the bash shell usable, and a number of additional packages will be installed
for file and process management operations.
* We can also optionally install `man` in the container so that you can access
manual pages. By default, it is disabled
* It is also possible to adjust the state settings in the processes model.
With `forceDisableUserChange` we can disable user creation and user
switching. It is also possible to control the other state variables, such

View File

@ -5,9 +5,8 @@
}:
let
createMultiProcessImage = import ../../nixproc/create-multi-process-image/create-multi-process-image-universal.nix {
inherit pkgs system;
inherit (pkgs) dockerTools stdenv;
createMultiProcessImage = import ../../nixproc/create-image-from-steps/create-multi-process-image-universal.nix {
inherit pkgs;
};
in
createMultiProcessImage {

View File

@ -1,46 +0,0 @@
{pkgs, system, exprFile, stateDir, runtimeDir, forceDisableUserChange, extraParams}:
let
sysvinitTools = (import ../../../tools {
inherit pkgs system;
}).sysvinit;
generateCompoundProxy = import ../util/generate-compound-proxy.nix {
inherit (pkgs) stdenv writeTextFile;
};
disnixDataDir = "${pkgs.disnix}/share/disnix";
profile = import ./build-disnix-env.nix {
inherit pkgs system exprFile stateDir runtimeDir forceDisableUserChange extraParams disnixDataDir;
};
emptyProfile = import ./build-disnix-env.nix {
inherit pkgs system stateDir runtimeDir forceDisableUserChange extraParams disnixDataDir;
exprFile = null;
};
script = generateCompoundProxy {
path = [ pkgs.dysnomia pkgs.disnix ];
startCommand = "disnix-activate ${profile}";
stopCommand = "disnix-activate -o ${profile} ${emptyProfile}";
};
in
{
runAsRoot = pkgs.lib.optionalString (!forceDisableUserChange) ''
${pkgs.gnused}/bin/sed -i -e "s/CREATE_MAIL_SPOOL=yes/CREATE_MAIL_SPOOL=no/" /etc/default/useradd
mkdir -p /etc/pam.d
cat > /etc/pam.d/su <<EOF
account required pam_unix.so
auth sufficient pam_rootok.so
auth required pam_tally.so
auth sufficient pam_unix.so likeauth try_first_pass
auth required pam_deny.so
password sufficient pam_unix.so nullok sha512
EOF
'';
contents = [ pkgs.shadow pkgs.su pkgs.disnix pkgs.dysnomia ];
cmd = [ script ];
credentialsSpec = null;
}

View File

@ -0,0 +1,40 @@
{pkgs, common, input, result}:
let
disnixTools = (import ../../../../tools {
inherit pkgs;
inherit (common) system;
}).disnix;
generateCompoundProxy = import ../../util/generate-compound-proxy.nix {
inherit (pkgs) stdenv writeTextFile;
};
disnixDataDir = "${pkgs.disnix}/share/disnix";
emptyProfile = import ../build-disnix-env.nix {
inherit pkgs disnixDataDir;
inherit (common) system;
inherit (input) stateDir runtimeDir forceDisableUserChange extraParams;
exprFile = null;
};
profilePath = "/nix/var/nix/profiles/per-user/root/disnix-coordinator/default";
script = generateCompoundProxy {
path = [ pkgs.dysnomia pkgs.disnix ];
startCommand = "disnix-activate -o ${emptyProfile} ${profilePath}";
stopCommand = "disnix-activate -o ${profilePath} ${emptyProfile}";
};
in
result // {
runAsRoot = result.runAsRoot or "" + ''
mkdir -p "$(dirname ${profilePath})"
ln -s ${emptyProfile} ${profilePath}
'';
contents = result.contents or [] ++ [ disnixTools ];
config = result.config or {} // {
Cmd = [ script ];
};
}

View File

@ -0,0 +1,33 @@
{pkgs, common, input, result}:
let
generateCompoundProxy = import ../../util/generate-compound-proxy.nix {
inherit (pkgs) stdenv writeTextFile;
};
disnixDataDir = "${pkgs.disnix}/share/disnix";
profile = import ../build-disnix-env.nix {
inherit pkgs disnixDataDir;
inherit (common) system;
inherit (input) exprFile stateDir runtimeDir forceDisableUserChange extraParams;
};
emptyProfile = import ../build-disnix-env.nix {
inherit pkgs disnixDataDir;
inherit (common) system;
inherit (input) stateDir runtimeDir forceDisableUserChange extraParams;
exprFile = null;
};
script = generateCompoundProxy {
path = [ pkgs.dysnomia pkgs.disnix ];
startCommand = "disnix-activate ${profile}";
stopCommand = "disnix-activate -o ${profile} ${emptyProfile}";
};
in
result // {
config = result.config or {} // {
Cmd = [ script ];
};
}

View File

@ -0,0 +1,5 @@
{pkgs, common, input, result}:
result // {
contents = result.contents or [] ++ [ pkgs.disnix pkgs.dysnomia ];
}

View File

@ -0,0 +1,5 @@
[
../../../create-image-from-steps/steps/su-pam.nix
./disnix.nix
./disnix-dynamic.nix
]

View File

@ -0,0 +1,5 @@
[
../../../create-image-from-steps/steps/su-pam.nix
./disnix.nix
./disnix-static.nix
]

View File

@ -0,0 +1,4 @@
[
./s6-rc.nix
./s6-rc-dynamic.nix
]

View File

@ -0,0 +1,19 @@
{pkgs, common, input, result}:
let
s6-rcTools = (import ../../../../tools {
inherit pkgs;
inherit (common) system;
}).s6-rc;
in
result // {
runAsRoot = result.runAsRoot or "" + ''
# Create empty service directory
mkdir -p /etc/s6/sv
# Initialize s6-rc with a compiled database
mkdir -p /etc/s6/rc
s6-rc-compile /etc/s6/rc/compiled /etc/s6/sv
'';
contents = result.contents or [] ++ [ s6-rcTools ];
}

View File

@ -0,0 +1,22 @@
{pkgs, common, input, result}:
let
profile = import ../build-s6-rc-env.nix {
inherit pkgs;
inherit (common) system;
inherit (input) exprFile extraParams stateDir runtimeDir forceDisableUserChange;
};
in
result // {
runAsRoot = result.runAsRoot or "" + ''
# Initialize s6-rc with a compiled database
mkdir -p /etc/s6/rc
s6-rc-compile /etc/s6/rc/compiled ${profile}/etc/s6/sv
${pkgs.lib.optionalString (!input.forceDisableUserChange) ''
export PATH=$PATH:${pkgs.findutils}/bin:${pkgs.glibc.bin}/bin
${pkgs.dysnomia}/bin/dysnomia-addgroups ${profile}
${pkgs.dysnomia}/bin/dysnomia-addusers ${profile}
''}
'';
}

View File

@ -1,10 +1,6 @@
{pkgs, system, exprFile, stateDir, runtimeDir, forceDisableUserChange, extraParams}:
{pkgs, common, input, result}:
let
profile = import ./build-s6-rc-env.nix {
inherit pkgs system exprFile extraParams stateDir runtimeDir forceDisableUserChange;
};
skelDir = pkgs.stdenv.mkDerivation {
name = "s6-skel-dir";
buildCommand = ''
@ -38,8 +34,8 @@ let
'';
};
in
{
runAsRoot = ''
result // {
runAsRoot = result.runAsRoot or "" + ''
# Run s6-linux-init-maker to configure s6-linux-init as an init system
mkdir -p /etc/s6
s6-linux-init-maker -c /etc/s6/current -p /bin -m 0022 -f ${skelDir} -N -C -B /etc/s6/current
@ -49,12 +45,11 @@ in
# Create s6-log user and group
groupadd -g 2 s6-log
useradd -u 2 -d /dev/null -g s6-log s6-log
# Initialize s6-rc with a compiled database
mkdir -p /etc/s6/rc
s6-rc-compile /etc/s6/rc/compiled ${profile}/etc/s6/sv
'';
contents = [ pkgs.s6-linux-init pkgs.s6 pkgs.s6-rc pkgs.execline ];
cmd = [ "/bin/init" ];
credentialsSpec = profile;
contents = result.contents or [] ++ [ pkgs.s6-linux-init pkgs.s6 pkgs.s6-rc pkgs.execline ];
config = result.config or {} // {
cmd = [ "/bin/init" ];
};
}

View File

@ -0,0 +1,4 @@
[
./s6-rc.nix
./s6-rc-static.nix
]

View File

@ -1,15 +0,0 @@
{pkgs, system, exprFile, stateDir, runtimeDir, forceDisableUserChange, extraParams}:
let
profile = import ./build-supervisord-env.nix {
inherit pkgs system exprFile extraParams stateDir runtimeDir forceDisableUserChange;
};
in
{
runAsRoot = ''
ln -s ${profile} /etc/supervisor
'';
contents = [ pkgs.pythonPackages.supervisor ];
cmd = [ "${pkgs.pythonPackages.supervisor}/bin/supervisord" "--nodaemon" "--configuration" "/etc/supervisor/supervisord.conf" "--logfile" "/var/log/supervisord.log" "--pidfile" "/var/run/supervisord.pid" ];
credentialsSpec = profile;
}

View File

@ -0,0 +1,4 @@
[
./supervisord.nix
./supervisord-dynamic.nix
]

View File

@ -0,0 +1,4 @@
[
./supervisord.nix
./supervisord-static.nix
]

View File

@ -0,0 +1,21 @@
{pkgs, common, input, result}:
let
supervisordTools = (import ../../../../tools {
inherit pkgs;
inherit (common) system;
}).supervisord;
in
result // {
contents = result.contents or [] ++ [ supervisordTools ];
runAsRoot = result.runAsRoot or "" + ''
mkdir -p /etc/supervisor/conf.d
cp ${../supervisord.conf} /etc/supervisor/supervisord.conf
'';
config = result.config or {} // {
Env = result.config.Env or []
++ [ "SUPERVISORD_CONF_DIR=/etc/supervisor" ];
};
}

View File

@ -0,0 +1,20 @@
{pkgs, common, input, result}:
let
profile = import ../build-supervisord-env.nix {
inherit pkgs;
inherit (input) exprFile extraParams stateDir runtimeDir forceDisableUserChange;
inherit (common) system;
};
in
result // {
runAsRoot = result.runAsRoot or "" + ''
ln -s ${profile} /etc/supervisor
${pkgs.lib.optionalString (!input.forceDisableUserChange) ''
export PATH=$PATH:${pkgs.findutils}/bin:${pkgs.glibc.bin}/bin
${pkgs.dysnomia}/bin/dysnomia-addgroups ${profile}
${pkgs.dysnomia}/bin/dysnomia-addusers ${profile}
''}
'';
}

View File

@ -0,0 +1,8 @@
{pkgs, common, input, result}:
result // {
contents = result.contents or [] ++ [ pkgs.pythonPackages.supervisor ];
config = result.config or {} // {
Cmd = [ "${pkgs.pythonPackages.supervisor}/bin/supervisord" "--nodaemon" "--configuration" "/etc/supervisor/supervisord.conf" "--logfile" "/var/log/supervisord.log" "--pidfile" "/var/run/supervisord.pid" ];
};
}

View File

@ -0,0 +1,5 @@
[
../../../create-image-from-steps/steps/su-pam.nix
./sysvinit.nix
./sysvinit-dynamic.nix
]

View File

@ -0,0 +1,5 @@
[
../../../create-image-from-steps/steps/su-pam.nix
./sysvinit.nix
./sysvinit-static.nix
]

View File

@ -0,0 +1,29 @@
{pkgs, common, input, result}:
let
sysvinitTools = (import ../../../../tools {
inherit pkgs;
inherit (common) system;
}).sysvinit;
generateCompoundProxy = import ../../util/generate-compound-proxy.nix {
inherit (pkgs) stdenv writeTextFile;
};
runlevel = "3";
script = generateCompoundProxy {
startCommand = "${sysvinitTools}/bin/nixproc-sysvinit-runactivity --runlevel ${runlevel} start /";
stopCommand = "${sysvinitTools}/bin/nixproc-sysvinit-runactivity --runlevel ${runlevel} -r stop /";
};
in
result // {
runAsRoot = result.runAsRoot or "" + ''
# Make symlink to processes profile
ln -s /nix/var/nix/profiles/processes/etc/rc.d /etc/rc.d
'';
config = result.config or {} // {
Cmd = [ script ];
};
contents = result.contents or [] ++ [ sysvinitTools ];
}

View File

@ -0,0 +1,37 @@
{pkgs, common, input, result}:
let
sysvinitTools = (import ../../../../tools {
inherit pkgs;
inherit (common) system;
}).sysvinit;
generateCompoundProxy = import ../../util/generate-compound-proxy.nix {
inherit (pkgs) stdenv writeTextFile;
};
runlevel = "3";
script = generateCompoundProxy {
startCommand = "${sysvinitTools}/bin/nixproc-sysvinit-runactivity start ${profile}";
stopCommand = "${sysvinitTools}/bin/nixproc-sysvinit-runactivity -r stop ${profile}";
};
profile = import ../build-sysvinit-env.nix {
inherit (input) exprFile stateDir runtimeDir forceDisableUserChange extraParams;
};
in
result // {
runAsRoot = result.runAsRoot or "" + ''
ln -s ${profile}/etc/rc.d /etc/rc.d
${pkgs.lib.optionalString (!input.forceDisableUserChange) ''
export PATH=$PATH:${pkgs.findutils}/bin:${pkgs.glibc.bin}/bin
${pkgs.dysnomia}/bin/dysnomia-addgroups ${profile}
${pkgs.dysnomia}/bin/dysnomia-addusers ${profile}
''}
'';
config = result.config or {} // {
Cmd = [ script ];
};
}

View File

@ -0,0 +1,5 @@
{pkgs, common, input, result}:
result // {
contents = result.contents or [] ++ [ pkgs.sysvinit pkgs.gnugrep pkgs.coreutils ];
}

View File

@ -0,0 +1,8 @@
{pkgs, steps, common ? {}, input}:
let
generatedConfig = import ./generate-config-from-steps.nix {
inherit pkgs common input steps;
};
in
pkgs.dockerTools.buildImage generatedConfig

View File

@ -0,0 +1,13 @@
{pkgs}:
input:
import ./create-multi-process-image.nix {
inherit pkgs;
} (input // {
steps = {
disnix = ../backends/disnix/image-steps/static-steps.nix;
s6-rc = ../backends/s6-rc/image-steps/static-steps.nix;
supervisord = ../backends/supervisord/image-steps/static-steps.nix;
sysvinit = ../backends/sysvinit/image-steps/static-steps.nix;
};
})

View File

@ -0,0 +1,30 @@
{pkgs}:
{processManager, steps, ...}@input:
let
_input = rec {
stateDir = "/var";
runtimeDir = "${stateDir}/run";
forceDisableUserChange = false;
extraParams = {};
} // input;
processManagerSpecificStepsFile = builtins.getAttr processManager steps;
in
import ./create-image-from-steps.nix {
inherit pkgs;
input = _input;
common = {
system = builtins.currentSystem;
};
steps = [
./steps/init.nix
./steps/basic.nix
./steps/interactive.nix
./steps/man.nix
./steps/nix-processmgmt-static.nix
]
++ import processManagerSpecificStepsFile;
}

View File

@ -0,0 +1,13 @@
{pkgs}:
input:
import ./create-mutable-multi-process-image.nix {
inherit pkgs;
} (input // {
steps = {
disnix = ../backends/disnix/image-steps/dynamic-steps.nix;
s6-rc = ../backends/s6-rc/image-steps/dynamic-steps.nix;
supervisord = ../backends/supervisord/image-steps/dynamic-steps.nix;
sysvinit = ../backends/sysvinit/image-steps/dynamic-steps.nix;
};
})

View File

@ -0,0 +1,31 @@
{pkgs}:
{processManager, steps, ...}@input:
let
_input = rec {
stateDir = "/var";
runtimeDir = "${stateDir}/run";
} // input;
processManagerSpecificStepsFile = builtins.getAttr processManager steps;
in
import ./create-image-from-steps.nix {
inherit pkgs;
common = {
system = builtins.currentSystem;
};
input = _input;
steps = [
./steps/init.nix
./steps/basic.nix
./steps/interactive.nix
./steps/man.nix
./steps/nix-processmgmt-dynamic.nix
]
++ import processManagerSpecificStepsFile
++ [
./steps/bootstrap-init.nix
./steps/nix-support.nix
];
}

View File

@ -0,0 +1,18 @@
{pkgs}:
input:
import ./create-image-from-steps.nix {
inherit pkgs input;
common = {
system = builtins.currentSystem;
};
steps = [
./steps/init.nix
./steps/basic.nix
./steps/interactive.nix
./steps/man.nix
./steps/nix-support.nix
];
}

View File

@ -0,0 +1,7 @@
{pkgs, common ? {}, input, steps}:
pkgs.lib.foldl (result: moduleFile:
import moduleFile {
inherit pkgs common input result;
}
) {} steps

View File

@ -0,0 +1,18 @@
{pkgs, common, input, result}:
result // {
runAsRoot = result.runAsRoot or "" + ''
${pkgs.dockerTools.shadowSetup}
# Always create these global state directories, because they are needed quite often
mkdir -p /run /tmp
chmod 1777 /tmp
mkdir -p /var/empty
ln -s ../run /var/run
# Always create nobody/nogroup
groupadd -g 65534 -r nogroup
useradd -u 65534 -r nobody -g nogroup -d /dev/null
'';
}

View File

@ -0,0 +1,31 @@
{pkgs, common, input, result}:
let
cmd = pkgs.lib.escapeShellArgs result.config.Cmd;
in
result // pkgs.lib.optionalAttrs (!(input ? bootstrap) || input.bootstrap) {
runAsRoot = result.runAsRoot or "" + ''
cat > /bin/bootstrap <<EOF
#! ${pkgs.stdenv.shell} -e
# Add nix channel configuration
nix-channel --add https://nixos.org/channels/nixpkgs-unstable
nix-channel --update
nixproc-${input.processManager}-switch &
# Overwrite the bootstrap script, so that it simply just starts the process manager
cat > /bin/bootstrap <<EOR
#! ${pkgs.stdenv.shell} -e
exec ${cmd}
EOR
# Chain load the actual process manager
exec ${cmd}
EOF
chmod 755 /bin/bootstrap
'';
config = result.config or {} // {
Cmd = "/bin/bootstrap";
};
}

View File

@ -0,0 +1,7 @@
{pkgs, common, input, result}:
let
buildImageFormalArgs = builtins.functionArgs pkgs.dockerTools.buildImage;
buildImageArgs = builtins.intersectAttrs buildImageFormalArgs input;
in
buildImageArgs

View File

@ -0,0 +1,37 @@
{pkgs, common, input, result}:
result // pkgs.lib.optionalAttrs (!(input ? interactive) || input.interactive) {
contents = result.contents or [] ++ (with pkgs; [
# An interactive bash shell
bashInteractive
# Basic shell utilities for file management, text manipulation, user management, process management
coreutils diffutils findutils gnugrep gnused glibc.bin less utillinux procps shadow
]);
runAsRoot = result.runAsRoot or "" + ''
mkdir -p /root
cat > /root/.bashrc << "EOF"
alias ls='ls --color=auto'
if [ -n "$PS1" ]
then
if [ "$TERM" != "dumb" -o -n "$INSIDE_EMACS" ]
then
PROMPT_COLOR="1;31m"
let $UID && PROMPT_COLOR="1;32m"
if [ -n "$INSIDE_EMACS" -o "$TERM" == "eterm" -o "$TERM" == "eterm-color" ]
then
# Emacs term mode doesn't support xterm title escape sequence (\e]0;)
PS1="\n\[\033[$PROMPT_COLOR\][\u@\h:\w]\\$\[\033[0m\] "
else
PS1="\n\[\033[$PROMPT_COLOR\][\[\e]0;\u@\h: \w\a\]\u@\h:\w]\\$\[\033[0m\] "
fi
if test "$TERM" = "xterm"
then
PS1="\[\033]2;\h:\u:\w\007\]$PS1"
fi
fi
fi
EOF
'';
}

View File

@ -0,0 +1,11 @@
{pkgs, common, input, result}:
result // pkgs.lib.optionalAttrs (input ? manpages && input.manpages) {
contents = result.contents ++ (with pkgs; [
man groff gzip
]);
config = result.config or {} // {
Env = result.config.Env or [] ++ [ "MANPATH=/share/man:/nix/var/nix/profiles/default/share/man" ];
};
}

View File

@ -0,0 +1,70 @@
{pkgs, common, input, result}:
let
commonTools = (import ../../../tools {
inherit pkgs;
inherit (common) system;
}).common;
# If no processes.nix parameter was provided, generate a template
templateFile = pkgs.writeTextFile {
name = "processes.nix";
text = ''
{ pkgs ? import <nixpkgs> { inherit system; }
, system ? builtins.currentSystem
, stateDir ? "/var"
, runtimeDir ? "''${stateDir}/run"
, logDir ? "''${stateDir}/log"
, cacheDir ? "''${stateDir}/cache"
, tmpDir ? (if stateDir == "/var" then "/tmp" else "''${stateDir}/tmp")
, forceDisableUserChange ? false
, processManager
}:
let
nix-processmgmt-services = builtins.fetchGit {
url = https://github.com/svanderburg/nix-processmgmt-services.git;
ref = "master";
};
sharedConstructors = import "''${nix-processmgmt-services}/examples/services-agnostic/constructors.nix" {
inherit pkgs stateDir runtimeDir logDir cacheDir tmpDir forceDisableUserChange processManager;
};
in
rec {
/*nginx = rec {
port = 8080;
pkg = sharedConstructors.nginxReverseProxyHostBased {
webapps = [];
inherit port;
} {};
};*/
}
'';
};
in
result // {
contents = result.contents or []
++ [ pkgs.dysnomia commonTools ];
runAsRoot = result.runAsRoot or "" + ''
nixproc-init-state --state-dir ${input.stateDir} --runtime-dir ${input.runtimeDir}
# Provide a processes.nix expression
mkdir -p /etc/nixproc
'' + (if input ? exprFile then ''
cp ${input.exprFile} /etc/nixproc/processes.nix
'' else ''
cp ${templateFile} /etc/nixproc/processes.nix
'')
+ ''
chmod 644 /etc/nixproc/processes.nix
'';
config = result.config or {} // {
Env = result.config.Env or [] ++ [
"NIXPROC_PROCESSES=/etc/nixproc/processes.nix"
];
};
}

View File

@ -0,0 +1,14 @@
{pkgs, common, input, result}:
let
commonTools = (import ../../../tools {
inherit pkgs;
inherit (common) system;
}).common;
in
result // {
runAsRoot = result.runAsRoot or "" + ''
# Initialize common state directories
${commonTools}/bin/nixproc-init-state --state-dir ${input.stateDir} --runtime-dir ${input.runtimeDir}
'';
}

View File

@ -0,0 +1,59 @@
{pkgs, common, input, result}:
let
mkDbExtraCommand = contents: let
contentsList = if builtins.isList contents then pkgs.lib.unique contents else [ contents ]; in
''
echo "Generating the nix database..."
echo "Warning: only the database of the deepest Nix layer is loaded."
echo " If you want to use nix commands in the container, it would"
echo " be better to only have one layer that contains a nix store."
export NIX_REMOTE=local?root=$PWD
# A user is required by nix
# https://github.com/NixOS/nix/blob/9348f9291e5d9e4ba3c4347ea1b235640f54fd79/src/libutil/util.cc#L478
export USER=nobody
${pkgs.nix}/bin/nix-store --load-db < ${pkgs.closureInfo {rootPaths = contentsList;}}/registration
mkdir -p nix/var/nix/gcroots/docker/
for i in ${pkgs.lib.concatStringsSep " " contentsList}
do
ln -s $i nix/var/nix/gcroots/docker/$(basename $i)
done;
'';
in
result // rec {
contents = result.contents or [] ++ (with pkgs; [
# Nix
nix.out
# Needed for SSL authentication
cacert
# Needed for fetchgit
git
# Needed for downloading compressed tarballs
gnutar gzip bzip2 xz
]);
extraCommands = result.extraCommands or ""
+ mkDbExtraCommand contents;
runAsRoot = result.runAsRoot or "" + ''
# Initialize groups for Nix
groupadd -g 30000 nixbld
for i in $(seq 1 30)
do
groupadd -g $((30000 + i)) nixbld$i
useradd -d /var/empty -c "Nix build user $i" -u $((30000 + i)) -g nixbld$i -G nixbld nixbld$i
done
'';
config = result.config or {} // {
Env = result.config.Env or [] ++ [
"NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt"
"GIT_SSL_CAINFO=/etc/ssl/certs/ca-bundle.crt"
"NIX_PATH=/nix/var/nix/profiles/per-user/root/channels"
"USER=root"
"PATH=/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/bin:/sbin"
];
};
}

View File

@ -0,0 +1,19 @@
{pkgs, common, input, result}:
result // {
runAsRoot = result.runAsRoot or "" + ''
${pkgs.gnused}/bin/sed -i -e "s/CREATE_MAIL_SPOOL=yes/CREATE_MAIL_SPOOL=no/" /etc/default/useradd
mkdir -p /etc/pam.d
cat > /etc/pam.d/su <<EOF
account required pam_unix.so
auth sufficient pam_rootok.so
auth required pam_tally.so
auth sufficient pam_unix.so likeauth try_first_pass
auth required pam_deny.so
password sufficient pam_unix.so nullok sha512
EOF
'';
contents = result.contents or [] ++ [ pkgs.su pkgs.shadow ];
}

View File

@ -1,26 +0,0 @@
''
mkdir -p /root
cat > /root/.bashrc << "EOF"
alias ls='ls --color=auto'
if [ -n "$PS1" ]
then
if [ "$TERM" != "dumb" -o -n "$INSIDE_EMACS" ]
then
PROMPT_COLOR="1;31m"
let $UID && PROMPT_COLOR="1;32m"
if [ -n "$INSIDE_EMACS" -o "$TERM" == "eterm" -o "$TERM" == "eterm-color" ]
then
# Emacs term mode doesn't support xterm title escape sequence (\e]0;)
PS1="\n\[\033[$PROMPT_COLOR\][\u@\h:\w]\\$\[\033[0m\] "
else
PS1="\n\[\033[$PROMPT_COLOR\][\[\e]0;\u@\h: \w\a\]\u@\h:\w]\\$\[\033[0m\] "
fi
if test "$TERM" = "xterm"
then
PS1="\[\033]2;\h:\u:\w\007\]$PS1"
fi
fi
fi
EOF
''

View File

@ -1,11 +0,0 @@
{dockerTools, stdenv, pkgs, system}:
import ./create-multi-process-image.nix {
inherit dockerTools stdenv pkgs system;
generators = {
disnix = ../backends/disnix/generate-disnix-image-args.nix;
s6-rc = ../backends/s6-rc/generate-s6-rc-image-args.nix;
supervisord = ../backends/supervisord/generate-supervisord-image-args.nix;
sysvinit = ../backends/sysvinit/generate-sysvinit-image-args.nix;
};
}

View File

@ -1,55 +0,0 @@
{dockerTools, stdenv, pkgs, system, generators}:
{ interactive ? true
, exprFile
, extraParams ? {}
, contents ? []
, runAsRoot ? ""
, config ? {}
, processManager
, stateDir ? "/var"
, runtimeDir ? "${stateDir}/run"
, forceDisableUserChange ? false
, ...
}@args:
let
# Determine which parameters can be propagated to buildImage and which are customizations
buildImageFormalArgs = builtins.functionArgs dockerTools.buildImage;
buildImageArgs = removeAttrs (builtins.intersectAttrs buildImageFormalArgs args) [ "contents" "runAsRoot" "config" ];
commonTools = (import ../../tools { inherit pkgs; }).common;
generateImageArgsModule = if builtins.hasAttr processManager generators
then builtins.getAttr processManager generators
else throw "Cannot use process manager: ${processManager} in a multi-process container!";
processManagerArgs = import generateImageArgsModule {
inherit exprFile stateDir runtimeDir forceDisableUserChange extraParams pkgs system;
};
setupProcessManagement = import ../backends/docker/setup.nix {
inherit (pkgs) dockerTools stdenv dysnomia findutils glibc;
inherit (processManagerArgs) credentialsSpec;
inherit commonTools stateDir runtimeDir forceDisableUserChange;
};
in
dockerTools.buildImage ({
contents = stdenv.lib.optionals interactive [ pkgs.glibc.bin pkgs.bashInteractive pkgs.coreutils pkgs.gnugrep pkgs.findutils pkgs.procps pkgs.utillinux pkgs.less ]
++ processManagerArgs.contents
++ contents;
runAsRoot =
setupProcessManagement
+ processManagerArgs.runAsRoot
+ stdenv.lib.optionalString interactive import ./configure-bashrc.nix
+
''
${runAsRoot}
'';
config = stdenv.lib.recursiveUpdate {
Cmd = processManagerArgs.cmd;
} config;
} // buildImageArgs)