From 751d7a6714344e2783f881465d326fc5a610bf2e Mon Sep 17 00:00:00 2001 From: zimbatm Date: Sun, 15 Dec 2019 15:54:10 +0100 Subject: [PATCH] devcontainer: init --- README.md | 1 + images/devcontainer/README.md | 6 + images/devcontainer/default.nix | 126 +++++++++++++++++++++ images/devcontainer/root/etc/bashrc | 6 + images/devcontainer/root/etc/group | 6 + images/devcontainer/root/etc/nsswitch.conf | 11 ++ images/devcontainer/root/etc/pam.d/other | 4 + images/devcontainer/root/etc/passwd | 32 ++++++ images/devcontainer/root/etc/shadow | 32 ++++++ images/nix/default.nix | 17 +-- lib/mkUserEnvironment.nix | 78 +++++++++++++ overlay.nix | 19 ++++ 12 files changed, 322 insertions(+), 16 deletions(-) create mode 100644 images/devcontainer/README.md create mode 100644 images/devcontainer/default.nix create mode 100644 images/devcontainer/root/etc/bashrc create mode 100644 images/devcontainer/root/etc/group create mode 100644 images/devcontainer/root/etc/nsswitch.conf create mode 100644 images/devcontainer/root/etc/pam.d/other create mode 100644 images/devcontainer/root/etc/passwd create mode 100644 images/devcontainer/root/etc/shadow create mode 100644 lib/mkUserEnvironment.nix diff --git a/README.md b/README.md index 2d19e1b..d36cc5b 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ All images are automatically built and pushed to Docker Hub. | [nixpkgs/busybox](https://hub.docker.com/r/nixpkgs/busybox) | [![](https://images.microbadger.com/badges/image/nixpkgs/busybox.svg)](https://microbadger.com/images/nixpkgs/busybox) | [![](https://images.microbadger.com/badges/image/nixpkgs/busybox:nixos-19.03.svg)](https://microbadger.com/images/nixpkgs/busybox:nixos-19.03) | [![](https://images.microbadger.com/badges/image/nixpkgs/busybox:nixos-19.09.svg)](https://microbadger.com/images/nixpkgs/busybox:nixos-19.09) | | [nixpkgs/couchpotato](https://hub.docker.com/r/nixpkgs/couchpotato) | [![](https://images.microbadger.com/badges/image/nixpkgs/couchpotato.svg)](https://microbadger.com/images/nixpkgs/couchpotato) | [![](https://images.microbadger.com/badges/image/nixpkgs/couchpotato:nixos-19.03.svg)](https://microbadger.com/images/nixpkgs/couchpotato:nixos-19.03) | [![](https://images.microbadger.com/badges/image/nixpkgs/couchpotato:nixos-19.09.svg)](https://microbadger.com/images/nixpkgs/couchpotato:nixos-19.09) | | [nixpkgs/curl](https://hub.docker.com/r/nixpkgs/curl) | [![](https://images.microbadger.com/badges/image/nixpkgs/curl.svg)](https://microbadger.com/images/nixpkgs/curl) | [![](https://images.microbadger.com/badges/image/nixpkgs/curl:nixos-19.03.svg)](https://microbadger.com/images/nixpkgs/curl:nixos-19.03) | [![](https://images.microbadger.com/badges/image/nixpkgs/curl:nixos-19.09.svg)](https://microbadger.com/images/nixpkgs/curl:nixos-19.09) | +| [nixpkgs/devcontainer](https://hub.docker.com/r/nixpkgs/devcontainer) | [![](https://images.microbadger.com/badges/image/nixpkgs/devcontainer.svg)](https://microbadger.com/images/nixpkgs/devcontainer) | [![](https://images.microbadger.com/badges/image/nixpkgs/devcontainer:nixos-19.03.svg)](https://microbadger.com/images/nixpkgs/devcontainer:nixos-19.03) | [![](https://images.microbadger.com/badges/image/nixpkgs/devcontainer:nixos-19.09.svg)](https://microbadger.com/images/nixpkgs/devcontainer:nixos-19.09) | | [nixpkgs/docker-compose](https://hub.docker.com/r/nixpkgs/docker-compose) | [![](https://images.microbadger.com/badges/image/nixpkgs/docker-compose.svg)](https://microbadger.com/images/nixpkgs/docker-compose) | [![](https://images.microbadger.com/badges/image/nixpkgs/docker-compose:nixos-19.03.svg)](https://microbadger.com/images/nixpkgs/docker-compose:nixos-19.03) | [![](https://images.microbadger.com/badges/image/nixpkgs/docker-compose:nixos-19.09.svg)](https://microbadger.com/images/nixpkgs/docker-compose:nixos-19.09) | | [nixpkgs/kubectl](https://hub.docker.com/r/nixpkgs/kubectl) | [![](https://images.microbadger.com/badges/image/nixpkgs/kubectl.svg)](https://microbadger.com/images/nixpkgs/kubectl) | [![](https://images.microbadger.com/badges/image/nixpkgs/kubectl:nixos-19.03.svg)](https://microbadger.com/images/nixpkgs/kubectl:nixos-19.03) | [![](https://images.microbadger.com/badges/image/nixpkgs/kubectl:nixos-19.09.svg)](https://microbadger.com/images/nixpkgs/kubectl:nixos-19.09) | | [nixpkgs/kubernetes-helm](https://hub.docker.com/r/nixpkgs/kubernetes-helm) | [![](https://images.microbadger.com/badges/image/nixpkgs/kubernetes-helm.svg)](https://microbadger.com/images/nixpkgs/kubernetes-helm) | [![](https://images.microbadger.com/badges/image/nixpkgs/kubernetes-helm:nixos-19.03.svg)](https://microbadger.com/images/nixpkgs/kubernetes-helm:nixos-19.03) | [![](https://images.microbadger.com/badges/image/nixpkgs/kubernetes-helm:nixos-19.09.svg)](https://microbadger.com/images/nixpkgs/kubernetes-helm:nixos-19.09) | diff --git a/images/devcontainer/README.md b/images/devcontainer/README.md new file mode 100644 index 0000000..753126c --- /dev/null +++ b/images/devcontainer/README.md @@ -0,0 +1,6 @@ +# Nix VSCode DevContainer + +WIP + +Related to https://github.com/zimbatm/vscode-devcontainer-nix + diff --git a/images/devcontainer/default.nix b/images/devcontainer/default.nix new file mode 100644 index 0000000..779e926 --- /dev/null +++ b/images/devcontainer/default.nix @@ -0,0 +1,126 @@ +# A fat and modifiable Nix image +# +# TODO: create a suid wrapper for sudo. + +# sudo: setrlimit(RLIMIT_CORE): Operation not permitted +{ dockerTools +, closureInfo +, bashInteractive +, cacert +, coreutils +, curl +, gcc-unwrapped +, gitReallyMinimal +, glibc +, gnutar +, gzip +, iana-etc +, iproute +, nix +, openssh +, shadow +, sudo +, xz +, mkUserEnvironment +}: +let + # generate a user profile for the image + profile = mkUserEnvironment { + derivations = [ + coreutils + # add /bin/sh + bashInteractive + nix + + # runtime dependencies of nix + cacert + gitReallyMinimal + gnutar + gzip + xz + + # for haskell binaries + iana-etc + + # for user management + shadow + sudo + + # for the vscode extension + gcc-unwrapped + iproute + ]; + }; + + image = dockerTools.buildImage { + name = "devcontainer"; + + contents = [ ]; + + extraCommands = '' + # create the Nix DB + export NIX_REMOTE=local?root=$PWD + export USER=nobody + ${nix}/bin/nix-store --load-db < ${closureInfo { rootPaths = [ profile ]; }}/registration + + # set the user profile + ${profile}/bin/nix-env --profile nix/var/nix/profiles/default --set ${profile} + + # minimal + mkdir -p bin usr/bin + ln -s /nix/var/nix/profiles/default/bin/sh bin/sh + ln -s /nix/var/nix/profiles/default/bin/env usr/bin/env + + # might as well... + ln -s /nix/var/nix/profiles/default/bin/bash bin/bash + + # setup iana-etc for haskell binaries + mkdir etc + ln -s /nix/var/nix/profiles/default/etc/protocols etc/protocols + ln -s /nix/var/nix/profiles/default/etc/services etc/services + + # setup shadow + mkdir etc/pam.d + cp ${./root/etc/bashrc} etc/bashrc + cp ${./root/etc/group} etc/group + cp ${./root/etc/passwd} etc/passwd + cp ${./root/etc/shadow} etc/shadow + cp ${./root/etc/nsswitch.conf} etc/nsswitch.conf + cp ${./root/etc/pam.d/other} etc/pam.d/other + + # make sure /tmp exists + mkdir -m 0777 tmp + + # allow ubuntu ELF binaries to run. VSCode copies it's own. + mkdir -p lib64 + ln -s ${glibc}/lib64/ld-linux-x86-64.so.2 lib64/ld-linux-x86-64.so.2 + + # VSCode assumes that /sbin/ip exists + mkdir sbin + ln -s /nix/var/nix/profiles/default/bin/ip sbin/ip + ''; + + config = { + Cmd = [ "/nix/var/nix/profiles/default/bin/bash" ]; + Env = [ + "ENV=/nix/var/nix/profiles/default/etc/profile.d/nix.sh" + "GIT_SSL_CAINFO=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" + "LD_LIBRARY_PATH=/nix/var/nix/profiles/default/lib" + "NIX_PATH=nixpkgs=${toString }" + "PAGER=cat" + "PATH=/nix/var/nix/profiles/default/bin" + "SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" + ]; + Labels = { + # https://github.com/microscaling/microscaling/blob/55a2d7b91ce7513e07f8b1fd91bbed8df59aed5a/Dockerfile#L22-L33 + "org.label-schema.vcs-ref" = "master"; + "org.label-schema.vcs-url" = "https://github.com/nix-community/docker-nixpkgs"; + }; + }; + }; +in +image // { + meta = image.meta // { + description = "Nix devcontainer for VSCode"; + }; +} diff --git a/images/devcontainer/root/etc/bashrc b/images/devcontainer/root/etc/bashrc new file mode 100644 index 0000000..814bc54 --- /dev/null +++ b/images/devcontainer/root/etc/bashrc @@ -0,0 +1,6 @@ +# interactive session +if [[ $- == *i* ]]; then + +PS1='\[\033[0;32;40m\][nix]$\[\033[0m\] ' + +fi diff --git a/images/devcontainer/root/etc/group b/images/devcontainer/root/etc/group new file mode 100644 index 0000000..d395e7f --- /dev/null +++ b/images/devcontainer/root/etc/group @@ -0,0 +1,6 @@ +root:x:0: +wheel:x:1: +tty:x:3: +users:x:100: +nixbld:x:30000:nixbld1,nixbld2,nixbld3,nixbld4,nixbld5,nixbld6,nixbld7,nixbld8,nixbld9,nixbld10,nixbld11,nixbld12,nixbld13,nixbld14,nixbld15,nixbld16,nixbld17,nixbld18,nixbld19,nixbld20,nixbld21,nixbld22,nixbld23,nixbld24,nixbld25,nixbld26,nixbld27,nixbld28,nixbld29,nixbld30 +nogroup:x:65534: diff --git a/images/devcontainer/root/etc/nsswitch.conf b/images/devcontainer/root/etc/nsswitch.conf new file mode 100644 index 0000000..59a2141 --- /dev/null +++ b/images/devcontainer/root/etc/nsswitch.conf @@ -0,0 +1,11 @@ +passwd: files mymachines systemd +group: files mymachines systemd +shadow: files + +hosts: files mymachines dns myhostname +networks: files + +ethers: files +services: files +protocols: files +rpc: files diff --git a/images/devcontainer/root/etc/pam.d/other b/images/devcontainer/root/etc/pam.d/other new file mode 100644 index 0000000..84e14ff --- /dev/null +++ b/images/devcontainer/root/etc/pam.d/other @@ -0,0 +1,4 @@ +account sufficient pam_unix.so +auth sufficient pam_rootok.so +password requisite pam_unix.so nullok sha512 +session required pam_unix.so diff --git a/images/devcontainer/root/etc/passwd b/images/devcontainer/root/etc/passwd new file mode 100644 index 0000000..53c5262 --- /dev/null +++ b/images/devcontainer/root/etc/passwd @@ -0,0 +1,32 @@ +root:x:0:0:root:/root:/nix/var/nix/profiles/default/bin/bash +nixbld1:x:30001:30000:Nix build user 1:/var/empty:/sbin/nologin +nixbld2:x:30002:30000:Nix build user 2:/var/empty:/sbin/nologin +nixbld3:x:30003:30000:Nix build user 3:/var/empty:/sbin/nologin +nixbld4:x:30004:30000:Nix build user 4:/var/empty:/sbin/nologin +nixbld5:x:30005:30000:Nix build user 5:/var/empty:/sbin/nologin +nixbld6:x:30006:30000:Nix build user 6:/var/empty:/sbin/nologin +nixbld7:x:30007:30000:Nix build user 7:/var/empty:/sbin/nologin +nixbld8:x:30008:30000:Nix build user 8:/var/empty:/sbin/nologin +nixbld9:x:30009:30000:Nix build user 9:/var/empty:/sbin/nologin +nixbld10:x:30010:30000:Nix build user 10:/var/empty:/sbin/nologin +nixbld11:x:30011:30000:Nix build user 11:/var/empty:/sbin/nologin +nixbld12:x:30012:30000:Nix build user 12:/var/empty:/sbin/nologin +nixbld13:x:30013:30000:Nix build user 13:/var/empty:/sbin/nologin +nixbld14:x:30014:30000:Nix build user 14:/var/empty:/sbin/nologin +nixbld15:x:30015:30000:Nix build user 15:/var/empty:/sbin/nologin +nixbld16:x:30016:30000:Nix build user 16:/var/empty:/sbin/nologin +nixbld17:x:30017:30000:Nix build user 17:/var/empty:/sbin/nologin +nixbld18:x:30018:30000:Nix build user 18:/var/empty:/sbin/nologin +nixbld19:x:30019:30000:Nix build user 19:/var/empty:/sbin/nologin +nixbld20:x:30020:30000:Nix build user 20:/var/empty:/sbin/nologin +nixbld21:x:30021:30000:Nix build user 21:/var/empty:/sbin/nologin +nixbld22:x:30022:30000:Nix build user 22:/var/empty:/sbin/nologin +nixbld23:x:30023:30000:Nix build user 23:/var/empty:/sbin/nologin +nixbld24:x:30024:30000:Nix build user 24:/var/empty:/sbin/nologin +nixbld25:x:30025:30000:Nix build user 25:/var/empty:/sbin/nologin +nixbld26:x:30026:30000:Nix build user 26:/var/empty:/sbin/nologin +nixbld27:x:30027:30000:Nix build user 27:/var/empty:/sbin/nologin +nixbld28:x:30028:30000:Nix build user 28:/var/empty:/sbin/nologin +nixbld29:x:30029:30000:Nix build user 29:/var/empty:/sbin/nologin +nixbld30:x:30030:30000:Nix build user 30:/var/empty:/sbin/nologin +nobody:x:65534:65534:nobody:/:/sbin/nologin diff --git a/images/devcontainer/root/etc/shadow b/images/devcontainer/root/etc/shadow new file mode 100644 index 0000000..c86d8b9 --- /dev/null +++ b/images/devcontainer/root/etc/shadow @@ -0,0 +1,32 @@ +root:!::0::::: +nixbld1:!:18237:0:99999:7::: +nixbld2:!:18237:0:99999:7::: +nixbld3:!:18237:0:99999:7::: +nixbld4:!:18237:0:99999:7::: +nixbld5:!:18237:0:99999:7::: +nixbld6:!:18237:0:99999:7::: +nixbld7:!:18237:0:99999:7::: +nixbld8:!:18237:0:99999:7::: +nixbld9:!:18237:0:99999:7::: +nixbld10:!:18237:0:99999:7::: +nixbld11:!:18237:0:99999:7::: +nixbld12:!:18237:0:99999:7::: +nixbld13:!:18237:0:99999:7::: +nixbld14:!:18237:0:99999:7::: +nixbld15:!:18237:0:99999:7::: +nixbld16:!:18237:0:99999:7::: +nixbld17:!:18237:0:99999:7::: +nixbld18:!:18237:0:99999:7::: +nixbld19:!:18237:0:99999:7::: +nixbld20:!:18237:0:99999:7::: +nixbld21:!:18237:0:99999:7::: +nixbld22:!:18237:0:99999:7::: +nixbld23:!:18237:0:99999:7::: +nixbld24:!:18237:0:99999:7::: +nixbld25:!:18237:0:99999:7::: +nixbld26:!:18237:0:99999:7::: +nixbld27:!:18237:0:99999:7::: +nixbld28:!:18237:0:99999:7::: +nixbld29:!:18237:0:99999:7::: +nixbld30:!:18237:0:99999:7::: +nobody:!::0::::: diff --git a/images/nix/default.nix b/images/nix/default.nix index caadfaf..620bb3e 100644 --- a/images/nix/default.nix +++ b/images/nix/default.nix @@ -3,7 +3,7 @@ , cacert , coreutils , curl -, git +, gitReallyMinimal , gnutar , gzip , iana-etc @@ -11,21 +11,6 @@ , xz }: let - # gitMinimal still ships with perl and python - gitReallyMinimal = ( - git.override { - perlSupport = false; - pythonSupport = false; - withManual = false; - withpcre2 = false; - } - ).overrideAttrs ( - _: { - # installCheck is broken when perl is disabled - doInstallCheck = false; - } - ); - image = dockerTools.buildImageWithNixDb { inherit (nix) name; diff --git a/lib/mkUserEnvironment.nix b/lib/mkUserEnvironment.nix new file mode 100644 index 0000000..03b7495 --- /dev/null +++ b/lib/mkUserEnvironment.nix @@ -0,0 +1,78 @@ +{ writeText, lib }: +# Build a user environment purely with nix. +# +# The original implementation is a mix of C++ and nix code. +# +# See https://github.com/nixos/nix/blob/f4b94958543138671bc3641fc126589a5cffb24b/src/nix-env/user-env.cc +# +# TODO: +# * also add the drvPath if the keepDerivations nix settings is set +# * support "disabled" mode that breaks nix-env? +# * remove the use of writeText. builtins.toFile forbits the use of references +# to derivations, which makes it impossible to create exactly the same +# manifest file as `nix-env`. +# +# Arguments: +# * derivations: a list of derivations +{ + # A list of derivations to install + derivations +}: +# Supporting code +with builtins; +let + # Escape Nix strings + stringEscape = str: + "\"" + ( + replaceStrings + [ "\\" "\"" "\n" "\r" "\t" ] + [ "\\\\" "\\" "\\n" "\\r" "\\t" ] + str + ) + + "\""; + + # Like builtins.JSON but to output Nix code + toNix = value: + if isString value then stringEscape value + else if isInt value then toString value + else if isPath value then toString value + else if true == value then "true" + else if false == value then "false" + else if null == value then "null" + else if isAttrs value then + "{ " + concatStringsSep " " (lib.mapAttrsToList (k: v: "${k} = ${toNix v};") value) + " }" + else if isList value then + "[ ${ concatStringsSep " " (map toNix value) } ]" + else throw "type ${typeOf value} not supported"; + + # Generate a nix-env compatible manifest.nix file + genManifest = drv: + let + outputs = + drv.meta.outputsToInstall or + # install the first output + [ (head drv.outputs) ]; + + base = { + inherit (drv) meta name outPath system type; + out = { inherit (drv) outPath; }; + inherit outputs; + }; + + toOut = name: { + outPath = drv.${name}.outPath; + }; + + outs = lib.genAttrs outputs toOut; + in + base // outs; + + writeManifest = derivations: + writeText "env-manifest.nix" ( + toNix (map genManifest derivations) + ); +in +import { + inherit derivations; + manifest = writeManifest derivations; +} diff --git a/overlay.nix b/overlay.nix index 3eff36b..e864878 100644 --- a/overlay.nix +++ b/overlay.nix @@ -9,4 +9,23 @@ in # docker images must be lower-cased docker-nixpkgs = importDir (path: pkgs.callPackage path {}) ./images; + + # used to build nix-env compatible user environments + mkUserEnvironment = pkgs.callPackage ./lib/mkUserEnvironment.nix {}; + + # gitMinimal still ships with perl and python + gitReallyMinimal = ( + pkgs.git.override { + perlSupport = false; + pythonSupport = false; + withManual = false; + withpcre2 = false; + } + ).overrideAttrs ( + _: { + # installCheck is broken when perl is disabled + doInstallCheck = false; + } + ); + }