From 8326ff154e92017564bfe3ec599f69fbbc182fab Mon Sep 17 00:00:00 2001 From: Trundle Date: Sun, 11 Jul 2021 02:20:16 +0000 Subject: [PATCH 01/16] Update flakes --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 22ca9ed2..74d3e6bd 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "flake-utils": { "locked": { - "lastModified": 1617631617, - "narHash": "sha256-PARRCz55qN3gy07VJZIlFeOX420d0nGF0RzGI/9hVlw=", + "lastModified": 1623875721, + "narHash": "sha256-A8BU7bjS5GirpAUv4QA+QnJ4CceLHkcXdRp4xITDB0s=", "owner": "numtide", "repo": "flake-utils", - "rev": "b2c27d1a81b0dc266270fa8aeecebbd1807fc610", + "rev": "f7e004a55b120c02ecb6219596820fcd32ca8772", "type": "github" }, "original": { @@ -17,11 +17,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1618064689, - "narHash": "sha256-MGnHpM3bSd5JClA+1ad+jvcfNr0HrYoGmqCc2s7thkM=", + "lastModified": 1625876282, + "narHash": "sha256-z/Gv+11Uzdv3HcQCY+xGi1+iuc3rmCaPzxxDSMnuRAI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ad7604ddbd9b299701fb5e15bc39cff80deffce2", + "rev": "068984c00e0d4e54b6684d98f6ac47c92dcb642e", "type": "github" }, "original": { From fa0feea616359c7b2b98bd478978b9ed975d7a2a Mon Sep 17 00:00:00 2001 From: Alex Griffin Date: Wed, 13 Oct 2021 09:49:16 -0500 Subject: [PATCH 02/16] Pass outer environment to user session Fixes #32. --- syschdemd.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/syschdemd.sh b/syschdemd.sh index 7548c949..9cb730e5 100644 --- a/syschdemd.sh +++ b/syschdemd.sh @@ -40,4 +40,10 @@ if [[ $# -gt 0 ]]; then else cmd="$userShell" fi -exec $sw/nsenter -t $(< /run/systemd.pid) -p -m -- $sw/machinectl -q --uid=@defaultUser@ shell .host /bin/sh -c "cd \"$PWD\"; exec $cmd" + +# Pass external environment but filter variables specific to root user. +exportCmd="$(export -p | $sw/grep -vE ' (HOME|LOGNAME|SHELL|USER)=')" + +exec $sw/nsenter -t $(< /run/systemd.pid) -p -m -- $sw/machinectl -q \ + --uid=@defaultUser@ shell .host /bin/sh -c \ + "cd \"$PWD\"; $exportCmd; exec $cmd" From 7b80b7ee832b5b471ab92a24b9edc30cb5b149f5 Mon Sep 17 00:00:00 2001 From: Alex Griffin Date: Wed, 13 Oct 2021 10:08:39 -0500 Subject: [PATCH 03/16] Add Windows %PATH% to Linux $PATH --- configuration.nix | 3 +++ syschdemd.sh | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/configuration.nix b/configuration.nix index 6d19de0d..1253f837 100644 --- a/configuration.nix +++ b/configuration.nix @@ -13,6 +13,9 @@ in # WSL is closer to a container than anything else boot.isContainer = true; + # Include Windows %PATH% in Linux $PATH. + environment.extraInit = ''PATH="$PATH:$WSLPATH"''; + environment.etc.hosts.enable = false; environment.etc."resolv.conf".enable = false; diff --git a/syschdemd.sh b/syschdemd.sh index 9cb730e5..b4730ba1 100644 --- a/syschdemd.sh +++ b/syschdemd.sh @@ -42,7 +42,7 @@ else fi # Pass external environment but filter variables specific to root user. -exportCmd="$(export -p | $sw/grep -vE ' (HOME|LOGNAME|SHELL|USER)=')" +exportCmd="$(export -p | $sw/grep -vE ' (HOME|LOGNAME|SHELL|USER)='); export WSLPATH=\"$PATH\"" exec $sw/nsenter -t $(< /run/systemd.pid) -p -m -- $sw/machinectl -q \ --uid=@defaultUser@ shell .host /bin/sh -c \ From 7ba3b4d3dcc6b0dc86bbaab34c07c4d26ac48072 Mon Sep 17 00:00:00 2001 From: nzbr Date: Thu, 22 Jul 2021 23:08:25 +0200 Subject: [PATCH 04/16] Add support for WSLg --- configuration.nix | 28 ++++++++++++++++++++++++++++ syschdemd.sh | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/configuration.nix b/configuration.nix index 6d19de0d..e72eff7f 100644 --- a/configuration.nix +++ b/configuration.nix @@ -3,6 +3,7 @@ with lib; let defaultUser = "nixos"; + automountPath = "/mnt"; syschdemd = import ./syschdemd.nix { inherit lib pkgs config defaultUser; }; in { @@ -43,4 +44,31 @@ in # Don't allow emergency mode, because we don't have a console. systemd.enableEmergencyMode = false; + + + # WSLg support + environment.variables = { + DISPLAY = ":0"; + WAYLAND_DISPLAY = "wayland-0"; + + PULSE_SERVER = "${automountPath}/wslg/PulseServer"; + XDG_RUNTIME_DIR = "${automountPath}/wslg/runtime-dir"; + WSL_INTEROP = "/run/WSL/1_interop"; + }; + + environment.etc."wsl.conf".text = '' + [automount] + enabled=true + mountFsTab=true + root=${automountPath}/ + options=metadata,uid=1000,gid=100 + ''; + + system.activationScripts.copy-launchers.text = '' + for x in applications icons; do + echo "Copying /usr/share/$x" + rm -rf /usr/share/$x + cp -r $systemConfig/sw/share/$x/. /usr/share/$x + done + ''; } diff --git a/syschdemd.sh b/syschdemd.sh index 7548c949..c0ddb258 100644 --- a/syschdemd.sh +++ b/syschdemd.sh @@ -40,4 +40,4 @@ if [[ $# -gt 0 ]]; then else cmd="$userShell" fi -exec $sw/nsenter -t $(< /run/systemd.pid) -p -m -- $sw/machinectl -q --uid=@defaultUser@ shell .host /bin/sh -c "cd \"$PWD\"; exec $cmd" +exec $sw/nsenter -t $(< /run/systemd.pid) -p -m -- $sw/machinectl -q --uid=@defaultUser@ shell .host /bin/sh --login -c "cd \"$PWD\"; exec $cmd" From 2410ab8c1ba7f512da09229544683f1d61a7ac98 Mon Sep 17 00:00:00 2001 From: nzbr Date: Tue, 14 Dec 2021 01:45:39 +0100 Subject: [PATCH 05/16] remove (now unneccesary) environment variables --- configuration.nix | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/configuration.nix b/configuration.nix index 198f4de4..aa362fa9 100644 --- a/configuration.nix +++ b/configuration.nix @@ -48,17 +48,6 @@ in # Don't allow emergency mode, because we don't have a console. systemd.enableEmergencyMode = false; - - # WSLg support - environment.variables = { - DISPLAY = ":0"; - WAYLAND_DISPLAY = "wayland-0"; - - PULSE_SERVER = "${automountPath}/wslg/PulseServer"; - XDG_RUNTIME_DIR = "${automountPath}/wslg/runtime-dir"; - WSL_INTEROP = "/run/WSL/1_interop"; - }; - environment.etc."wsl.conf".text = '' [automount] enabled=true @@ -67,11 +56,11 @@ in options=metadata,uid=1000,gid=100 ''; - system.activationScripts.copy-launchers.text = '' - for x in applications icons; do - echo "Copying /usr/share/$x" - rm -rf /usr/share/$x - cp -r $systemConfig/sw/share/$x/. /usr/share/$x - done - ''; + system.activationScripts = { + copy-launchers = stringAfter [] '' + for x in applications icons; do + echo "Copying /usr/share/$x" + ${pkgs.rsync}/bin/rsync -ar --delete $systemConfig/sw/share/$x/. /usr/share/$x + done + ''; } From d5dec7ecdd26e94ef3d56d3a19ef6f1961dce44c Mon Sep 17 00:00:00 2001 From: nzbr Date: Tue, 14 Dec 2021 01:55:31 +0100 Subject: [PATCH 06/16] don't try to enter namespace if already inside it --- configuration.nix | 7 ++++++- syschdemd.sh | 22 +++++++++++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/configuration.nix b/configuration.nix index aa362fa9..c64aa06b 100644 --- a/configuration.nix +++ b/configuration.nix @@ -33,7 +33,12 @@ in extraGroups = [ "root" ]; }; - security.sudo.wheelNeedsPassword = false; + security.sudo = { + extraConfig = '' + Defaults env_keep+=INSIDE_NAMESPACE + ''; + wheelNeedsPassword = false; + }; # Disable systemd units that don't make sense on WSL systemd.services."serial-getty@ttyS0".enable = false; diff --git a/syschdemd.sh b/syschdemd.sh index b4730ba1..87cebac1 100644 --- a/syschdemd.sh +++ b/syschdemd.sh @@ -3,7 +3,7 @@ set -e sw="/nix/var/nix/profiles/system/sw/bin" -systemPath=`${sw}/readlink -f /nix/var/nix/profiles/system` +systemPath=$(${sw}/readlink -f /nix/var/nix/profiles/system) # Needs root to work if [[ $EUID -ne 0 ]]; then @@ -19,16 +19,16 @@ if [ ! -e "/run/systemd.pid" ]; then PATH=/run/current-system/systemd/lib/systemd:@fsPackagesPath@ \ LOCALE_ARCHIVE=/run/current-system/sw/lib/locale/locale-archive \ @daemonize@/bin/daemonize /run/current-system/sw/bin/unshare -fp --mount-proc systemd - /run/current-system/sw/bin/pgrep -xf systemd > /run/systemd.pid + /run/current-system/sw/bin/pgrep -xf systemd >/run/systemd.pid # Wait for systemd to start status=1 while [[ $status -gt 0 ]]; do $sw/sleep 1 status=0 - $sw/nsenter -t $(< /run/systemd.pid) -p -m -- \ - $sw/systemctl is-system-running -q --wait 2>/dev/null \ - || status=$? + $sw/nsenter -t $(/dev/null || + status=$? done fi @@ -42,8 +42,12 @@ else fi # Pass external environment but filter variables specific to root user. -exportCmd="$(export -p | $sw/grep -vE ' (HOME|LOGNAME|SHELL|USER)='); export WSLPATH=\"$PATH\"" +exportCmd="$(export -p | $sw/grep -vE ' (HOME|LOGNAME|SHELL|USER)='); export WSLPATH=\"$PATH\"; export INSIDE_NAMESPACE=true" -exec $sw/nsenter -t $(< /run/systemd.pid) -p -m -- $sw/machinectl -q \ - --uid=@defaultUser@ shell .host /bin/sh -c \ - "cd \"$PWD\"; $exportCmd; exec $cmd" +if [ -z "${INSIDE_NAMESPACE:-}" ]; then + exec $sw/nsenter -t $( Date: Tue, 14 Dec 2021 04:26:52 +0100 Subject: [PATCH 07/16] force-load shell environment - fixes vscode remote --- syschdemd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syschdemd.sh b/syschdemd.sh index 87cebac1..621ebbb4 100644 --- a/syschdemd.sh +++ b/syschdemd.sh @@ -47,7 +47,7 @@ exportCmd="$(export -p | $sw/grep -vE ' (HOME|LOGNAME|SHELL|USER)='); export WSL if [ -z "${INSIDE_NAMESPACE:-}" ]; then exec $sw/nsenter -t $( Date: Tue, 1 Feb 2022 04:01:13 +0100 Subject: [PATCH 08/16] move build-tarball to a flake module --- configuration.nix | 6 +++++- default.nix | 13 +++++++++++++ flake.lock | 17 +++++++++++++++++ flake.nix | 19 +++++++++++++++---- .../build-tarball.nix | 18 +++++++++--------- nixos.nix | 7 +------ 6 files changed, 60 insertions(+), 20 deletions(-) create mode 100644 default.nix rename build-tarball.nix => modules/build-tarball.nix (80%) diff --git a/configuration.nix b/configuration.nix index c64aa06b..05df82f6 100644 --- a/configuration.nix +++ b/configuration.nix @@ -5,10 +5,13 @@ let defaultUser = "nixos"; automountPath = "/mnt"; syschdemd = import ./syschdemd.nix { inherit lib pkgs config defaultUser; }; + nixos-wsl = import ./default.nix; in { - imports = [ + imports = with nixos-wsl.nixosModules; [ "${modulesPath}/profiles/minimal.nix" + + build-tarball ]; # WSL is closer to a container than anything else @@ -68,4 +71,5 @@ in ${pkgs.rsync}/bin/rsync -ar --delete $systemConfig/sw/share/$x/. /usr/share/$x done ''; + }; } diff --git a/default.nix b/default.nix new file mode 100644 index 00000000..873ece49 --- /dev/null +++ b/default.nix @@ -0,0 +1,13 @@ +(import + ( + let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + in + fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } + ) + { + src = ./.; + }).defaultNix diff --git a/flake.lock b/flake.lock index 74d3e6bd..48993f77 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,21 @@ { "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1641205782, + "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { "locked": { "lastModified": 1623875721, @@ -32,6 +48,7 @@ }, "root": { "inputs": { + "flake-compat": "flake-compat", "flake-utils": "flake-utils", "nixpkgs": "nixpkgs" } diff --git a/flake.nix b/flake.nix index 9e44244b..b094c2b1 100644 --- a/flake.nix +++ b/flake.nix @@ -1,19 +1,30 @@ { description = "NixOS WSL"; - inputs.nixpkgs.url = "nixpkgs/nixos-20.09"; - inputs.flake-utils.url = "github:numtide/flake-utils"; + inputs = { + nixpkgs.url = "nixpkgs/nixos-20.09"; + flake-utils.url = "github:numtide/flake-utils"; + + flake-compat = { + url = "github:edolstra/flake-compat"; + flake = false; + }; + }; outputs = { self, nixpkgs, flake-utils, ... }: { + nixosModules = { + build-tarball = import ./modules/build-tarball.nix; + }; + nixosConfigurations.mysystem = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ - (import ./configuration.nix) - (import ./build-tarball.nix) + ./configuration.nix ]; specialArgs = { inherit nixpkgs; }; }; + } // flake-utils.lib.eachDefaultSystem (system: let diff --git a/build-tarball.nix b/modules/build-tarball.nix similarity index 80% rename from build-tarball.nix rename to modules/build-tarball.nix index cbeb1dd1..c91e9c5f 100644 --- a/build-tarball.nix +++ b/modules/build-tarball.nix @@ -1,6 +1,5 @@ -{ config, pkgs, lib, nixpkgs ? , ... }: - -with lib; +{ config, pkgs, lib, ... }: +with builtins; with lib; let pkgs2storeContents = l: map (x: { object = x; symlink = "none"; }) l; @@ -15,9 +14,9 @@ let if [ ! -e $out/nixos/nixpkgs ]; then ln -s . $out/nixos/nixpkgs fi - echo -n ${config.system.nixos.revision} > $out/nixos/.git-revision - echo -n ${config.system.nixos.versionSuffix} > $out/nixos/.version-suffix - echo ${config.system.nixos.versionSuffix} | sed -e s/pre// > $out/nixos/svn-revision + echo -n ${toString config.system.nixos.revision} > $out/nixos/.git-revision + echo -n ${toString config.system.nixos.versionSuffix} > $out/nixos/.version-suffix + echo ${toString config.system.nixos.versionSuffix} | sed -e s/pre// > $out/nixos/svn-revision ''; preparer = pkgs.writeShellScriptBin "wsl-prepare" '' @@ -49,16 +48,17 @@ let # Copy the system configuration mkdir -p ./etc/nixos - cp ${./configuration.nix} ./etc/nixos/configuration.nix - cp ${./syschdemd.nix} ./etc/nixos/syschdemd.nix - cp ${./syschdemd.sh} ./etc/nixos/syschdemd.sh + cp -R ${../.}/. ./etc/nixos/ ''; + in { system.build.tarball = pkgs.callPackage "${nixpkgs}/nixos/lib/make-system-tarball.nix" { # No contents, structure will be added by prepare script contents = [ ]; + fileName = "nixos-wsl-${config.system.nixos.release}-${pkgs.hostPlatform.system}"; + storeContents = pkgs2storeContents [ config.system.build.toplevel channelSources diff --git a/nixos.nix b/nixos.nix index 3a32460c..f9e850fb 100644 --- a/nixos.nix +++ b/nixos.nix @@ -2,12 +2,7 @@ # nix-build -A system -A config.system.build.tarball ./nixos.nix import { - configuration = { - imports = [ - ./configuration.nix - ./build-tarball.nix - ]; - }; + configuration = import ./configuration.nix; system = "x86_64-linux"; } From 9eea29cf18310dedba1c1cd73f8a38a637966ec1 Mon Sep 17 00:00:00 2001 From: nzbr Date: Tue, 1 Feb 2022 07:10:57 +0100 Subject: [PATCH 09/16] move wsl-specific config to a flake module --- configuration.nix | 64 ++++------------------- flake.nix | 1 + modules/build-tarball.nix | 8 ++- modules/wsl-distro.nix | 107 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 56 deletions(-) create mode 100644 modules/wsl-distro.nix diff --git a/configuration.nix b/configuration.nix index 05df82f6..59a962f3 100644 --- a/configuration.nix +++ b/configuration.nix @@ -12,64 +12,18 @@ in "${modulesPath}/profiles/minimal.nix" build-tarball + wsl-distro ]; - # WSL is closer to a container than anything else - boot.isContainer = true; - - # Include Windows %PATH% in Linux $PATH. - environment.extraInit = ''PATH="$PATH:$WSLPATH"''; - - environment.etc.hosts.enable = false; - environment.etc."resolv.conf".enable = false; - - networking.dhcpcd.enable = false; - - users.users.${defaultUser} = { - isNormalUser = true; - extraGroups = [ "wheel" ]; + wsl = { + enable = true; + automountPath = "/mnt"; + defaultUser = "nixos"; + startMenuLaunchers = true; }; - users.users.root = { - shell = "${syschdemd}/bin/syschdemd"; - # Otherwise WSL fails to login as root with "initgroups failed 5" - extraGroups = [ "root" ]; - }; - - security.sudo = { - extraConfig = '' - Defaults env_keep+=INSIDE_NAMESPACE - ''; - wheelNeedsPassword = false; - }; - - # Disable systemd units that don't make sense on WSL - systemd.services."serial-getty@ttyS0".enable = false; - systemd.services."serial-getty@hvc0".enable = false; - systemd.services."getty@tty1".enable = false; - systemd.services."autovt@".enable = false; - - systemd.services.firewall.enable = false; - systemd.services.systemd-resolved.enable = false; - systemd.services.systemd-udevd.enable = false; - - # Don't allow emergency mode, because we don't have a console. - systemd.enableEmergencyMode = false; - - environment.etc."wsl.conf".text = '' - [automount] - enabled=true - mountFsTab=true - root=${automountPath}/ - options=metadata,uid=1000,gid=100 + # Enable nix-flakes by default + nix.extraOptions = '' + experimental-features = nix-command flakes ''; - - system.activationScripts = { - copy-launchers = stringAfter [] '' - for x in applications icons; do - echo "Copying /usr/share/$x" - ${pkgs.rsync}/bin/rsync -ar --delete $systemConfig/sw/share/$x/. /usr/share/$x - done - ''; - }; } diff --git a/flake.nix b/flake.nix index b094c2b1..5f015bc7 100644 --- a/flake.nix +++ b/flake.nix @@ -15,6 +15,7 @@ { nixosModules = { build-tarball = import ./modules/build-tarball.nix; + wsl-distro = import ./modules/wsl-distro.nix; }; nixosConfigurations.mysystem = nixpkgs.lib.nixosSystem { diff --git a/modules/build-tarball.nix b/modules/build-tarball.nix index c91e9c5f..ab112e19 100644 --- a/modules/build-tarball.nix +++ b/modules/build-tarball.nix @@ -46,13 +46,18 @@ let # It's now a NixOS! touch ./etc/NIXOS + # Write wsl.conf so that it is present when NixOS is started for the first time + cp ${config.environment.etc."wsl.conf".source} ./etc/wsl.conf + # Copy the system configuration mkdir -p ./etc/nixos cp -R ${../.}/. ./etc/nixos/ ''; in -{ +mkIf config.wsl.enable { + # These options make no sense without the wsl-distro module anyway + system.build.tarball = pkgs.callPackage "${nixpkgs}/nixos/lib/make-system-tarball.nix" { # No contents, structure will be added by prepare script contents = [ ]; @@ -71,4 +76,5 @@ in compressCommand = "gzip"; compressionExtension = ".gz"; }; + } diff --git a/modules/wsl-distro.nix b/modules/wsl-distro.nix new file mode 100644 index 00000000..355edd62 --- /dev/null +++ b/modules/wsl-distro.nix @@ -0,0 +1,107 @@ +{ lib, pkgs, config, ... }: + +with builtins; with lib; +{ + options.wsl = with types; + let + coercedToStr = coercedTo (oneOf [ bool path int ]) (toString) str; + in + { + enable = mkEnableOption "support for running NixOS as a WSL distribution"; + automountPath = mkOption { + type = str; + default = "/mnt"; + description = "The path where windows drives are mounted (e.g. /mnt/c)"; + }; + automountOptions = mkOption { + type = str; + default = "metadata,uid=1000,gid=100"; + description = "Options to use when mounting windows drives"; + }; + defaultUser = mkOption { + type = str; + default = "nixos"; + description = "The name of the default user"; + }; + startMenuLaunchers = mkEnableOption "shortcuts for GUI applications in the windows start menu"; + wslConf = mkOption { + type = attrsOf (attrsOf coercedToStr); + description = "Entries that are added to /etc/wsl.conf"; + }; + }; + + config = + let + cfg = config.wsl; + syschdemd = import ../syschdemd.nix { inherit lib pkgs config; defaultUser = cfg.defaultUser; }; + in + mkIf cfg.enable { + + wsl.wslConf = { + automount = { + enabled = true; + mountFsTab = true; + root = "${cfg.automountPath}/"; + options = cfg.automountOptions; + }; + }; + + # WSL is closer to a container than anything else + boot.isContainer = true; + + environment = { + # Include Windows %PATH% in Linux $PATH. + extraInit = ''PATH="$PATH:$WSLPATH"''; + + etc = { + "wsl.conf".text = generators.toINI { } cfg.wslConf; + + # DNS settings are managed by WSL + hosts.enable = false; + "resolv.conf".enable = false; + }; + }; + + networking.dhcpcd.enable = false; + + users.users.${cfg.defaultUser} = { + isNormalUser = true; + extraGroups = [ "wheel" ]; # Allow the default user to use sudo + }; + + users.users.root = { + shell = "${syschdemd}/bin/syschdemd"; + # Otherwise WSL fails to login as root with "initgroups failed 5" + extraGroups = [ "root" ]; + }; + + security.sudo = { + extraConfig = '' + Defaults env_keep+=INSIDE_NAMESPACE + ''; + wheelNeedsPassword = mkDefault false; # The default user will not have a password by default + }; + + system.activationScripts.copy-launchers = mkIf cfg.startMenuLaunchers ( + stringAfter [ ] '' + for x in applications icons; do + echo "Copying /usr/share/$x" + ${pkgs.rsync}/bin/rsync -ar --delete $systemConfig/sw/share/$x/. /usr/share/$x + done + '' + ); + + # Disable systemd units that don't make sense on WSL + systemd.services."serial-getty@ttyS0".enable = false; + systemd.services."serial-getty@hvc0".enable = false; + systemd.services."getty@tty1".enable = false; + systemd.services."autovt@".enable = false; + + systemd.services.firewall.enable = false; + systemd.services.systemd-resolved.enable = false; + systemd.services.systemd-udevd.enable = false; + + # Don't allow emergency mode, because we don't have a console. + systemd.enableEmergencyMode = false; + }; +} From 04c3672560fa8876691705ac77542db60221f949 Mon Sep 17 00:00:00 2001 From: nzbr Date: Tue, 1 Feb 2022 08:46:08 +0100 Subject: [PATCH 10/16] fix /usr/share missing on first launch --- modules/wsl-distro.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/wsl-distro.nix b/modules/wsl-distro.nix index 355edd62..fce74ee5 100644 --- a/modules/wsl-distro.nix +++ b/modules/wsl-distro.nix @@ -86,6 +86,7 @@ with builtins; with lib; stringAfter [ ] '' for x in applications icons; do echo "Copying /usr/share/$x" + mkdir -p /usr/share/$x ${pkgs.rsync}/bin/rsync -ar --delete $systemConfig/sw/share/$x/. /usr/share/$x done '' From c4ec3227cf4dedbd0b0a97e313bde81b59a5147e Mon Sep 17 00:00:00 2001 From: nzbr Date: Tue, 1 Feb 2022 08:48:42 +0100 Subject: [PATCH 11/16] adjust artifact path in github action --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index acfd0ea7..b0819fc2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,7 +31,7 @@ jobs: - uses: actions/upload-artifact@v2 with: name: install.tar.gz - path: result/tarball/nixos-system-x86_64-linux.tar.gz + path: result/tarball/*.tar.gz release: if: startsWith(github.ref, 'refs/tags/') @@ -60,6 +60,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} # - asset_name: nixos-system-x86_64-linux.tar.gz - asset_path: nixos-system-x86_64-linux.tar.gz + asset_name: install.tar.gz + asset_path: result/tarball/*.tar.gz asset_content_type: application/gzip From cc0e502b5126d73477675a65005c2d512096c2c6 Mon Sep 17 00:00:00 2001 From: nzbr Date: Wed, 2 Feb 2022 07:11:36 +0100 Subject: [PATCH 12/16] use flake-compat for non-flake nix-build --- .github/workflows/main.yml | 4 ++-- README.rst | 8 ++++---- flake.nix | 1 - modules/build-tarball.nix | 2 +- nixos.nix | 8 -------- 5 files changed, 7 insertions(+), 16 deletions(-) delete mode 100644 nixos.nix diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b0819fc2..600cbfc9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,7 +31,7 @@ jobs: - uses: actions/upload-artifact@v2 with: name: install.tar.gz - path: result/tarball/*.tar.gz + path: result/tarball/nixos-wsl-x86_64-linux.tar.gz release: if: startsWith(github.ref, 'refs/tags/') @@ -61,5 +61,5 @@ jobs: with: upload_url: ${{ steps.create_release.outputs.upload_url }} # asset_name: install.tar.gz - asset_path: result/tarball/*.tar.gz + asset_path: result/tarball/nixos-wsl-x86_64-linux.tar.gz asset_content_type: application/gzip diff --git a/README.rst b/README.rst index a1cb8b26..8fceda69 100644 --- a/README.rst +++ b/README.rst @@ -15,10 +15,10 @@ First, `download the latest release's system tarball Then open up a Terminal, PowerShell or Command Prompt and run:: - wsl --import NixOS .\NixOS\ nixos-system-x86_64-linux.tar.gz --version 2 + wsl --import NixOS .\NixOS\ nixos-wsl-x86_64-linux.tar.gz --version 2 This sets up a new WSL distribution ``NixOS`` that is installed under -``.\NixOS``. ``nixos-system-x86_64-linux.tar.gz`` is the path to the file you +``.\NixOS``. ``nixos-wsl-x86_64-linux.tar.gz`` is the path to the file you downloaded earlier. You might need to change this path or change to the download directory first. @@ -72,10 +72,10 @@ Or, if you want to build with local changes, run inside your checkout:: Without a flakes-enabled Nix, you can build a tarball using:: - nix-build -A system -A config.system.build.tarball ./nixos.nix + nix-build -A nixosConfigurations.mysystem.config.system.build.tarball The resulting mini rootfs can then be found under -``./result-2/tarball/nixos-system-x86_64-linux.tar.gz``. +``./result/tarball/nixos-wsl-x86_64-linux.tar.gz``. License diff --git a/flake.nix b/flake.nix index 5f015bc7..22be5b27 100644 --- a/flake.nix +++ b/flake.nix @@ -23,7 +23,6 @@ modules = [ ./configuration.nix ]; - specialArgs = { inherit nixpkgs; }; }; } // diff --git a/modules/build-tarball.nix b/modules/build-tarball.nix index ab112e19..cd90e6c9 100644 --- a/modules/build-tarball.nix +++ b/modules/build-tarball.nix @@ -62,7 +62,7 @@ mkIf config.wsl.enable { # No contents, structure will be added by prepare script contents = [ ]; - fileName = "nixos-wsl-${config.system.nixos.release}-${pkgs.hostPlatform.system}"; + fileName = "nixos-wsl-${pkgs.hostPlatform.system}"; storeContents = pkgs2storeContents [ config.system.build.toplevel diff --git a/nixos.nix b/nixos.nix deleted file mode 100644 index f9e850fb..00000000 --- a/nixos.nix +++ /dev/null @@ -1,8 +0,0 @@ -# Build with -# nix-build -A system -A config.system.build.tarball ./nixos.nix - -import { - configuration = import ./configuration.nix; - - system = "x86_64-linux"; -} From e844679c6a0413dae78476268e191f0b4844c164 Mon Sep 17 00:00:00 2001 From: nzbr Date: Thu, 3 Feb 2022 07:49:49 +0100 Subject: [PATCH 13/16] add a module for docker-desktop support --- .envrc | 7 +++++++ configuration.nix | 4 ++++ flake.nix | 1 + modules/docker-desktop.nix | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+) create mode 100644 .envrc create mode 100644 modules/docker-desktop.nix diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..c4f5ea4b --- /dev/null +++ b/.envrc @@ -0,0 +1,7 @@ +use_flake() { + watch_file flake.nix + watch_file flake.lock + eval "$(nix print-dev-env)" +} + +use flake diff --git a/configuration.nix b/configuration.nix index 59a962f3..7fe5c53e 100644 --- a/configuration.nix +++ b/configuration.nix @@ -12,6 +12,7 @@ in "${modulesPath}/profiles/minimal.nix" build-tarball + docker-desktop wsl-distro ]; @@ -20,6 +21,9 @@ in automountPath = "/mnt"; defaultUser = "nixos"; startMenuLaunchers = true; + + # Enable integration with Docker Desktop (needs to be installed) + # docker.enable = true; }; # Enable nix-flakes by default diff --git a/flake.nix b/flake.nix index 22be5b27..5638ffa8 100644 --- a/flake.nix +++ b/flake.nix @@ -16,6 +16,7 @@ nixosModules = { build-tarball = import ./modules/build-tarball.nix; wsl-distro = import ./modules/wsl-distro.nix; + docker-desktop = import ./modules/docker-desktop.nix; }; nixosConfigurations.mysystem = nixpkgs.lib.nixosSystem { diff --git a/modules/docker-desktop.nix b/modules/docker-desktop.nix new file mode 100644 index 00000000..a97e4ce3 --- /dev/null +++ b/modules/docker-desktop.nix @@ -0,0 +1,33 @@ +{ config, lib, pkgs, ... }: +with builtins; with lib; { + + options.wsl.docker = with types; { + enable = mkEnableOption "Docker Desktop integration"; + }; + + config = + let + cfg = config.wsl.docker; + in + mkIf (config.wsl.enable && cfg.enable) { + + environment.systemPackages = with pkgs; [ + docker + docker-compose + ]; + + systemd.services.docker-desktop-proxy = { + description = "Docker Desktop proxy"; + script = '' + ${config.wsl.automountPath}/wsl/docker-desktop/docker-desktop-proxy -docker-desktop-root ${config.wsl.automountPath}/wsl/docker-desktop + ''; + wantedBy = [ "multi-user.target" ]; + }; + + users.groups.docker.members = [ + config.wsl.defaultUser + ]; + + }; + +} From 5b81e1e59e127c24778cb7351bdb8e49fe0c3dec Mon Sep 17 00:00:00 2001 From: nzbr Date: Thu, 3 Feb 2022 16:25:52 +0100 Subject: [PATCH 14/16] create an installer tarball to circumvent the unspecified error when running wsl --import --- .github/workflows/main.yml | 35 ++++++++++++--- configuration.nix | 11 ++--- flake.nix | 11 +++-- modules/build-tarball.nix | 7 ++- modules/installer.nix | 88 ++++++++++++++++++++++++++++++++++++++ modules/wsl-distro.nix | 1 + 6 files changed, 135 insertions(+), 18 deletions(-) create mode 100644 modules/installer.nix diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 600cbfc9..f5e552c4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,11 +28,22 @@ jobs: run: | nix build '.#nixosConfigurations.mysystem.config.system.build.tarball' - - uses: actions/upload-artifact@v2 + - name: Upload tarball + uses: actions/upload-artifact@v2 with: - name: install.tar.gz + name: rootfs path: result/tarball/nixos-wsl-x86_64-linux.tar.gz + - name: Build installer + run: | + nix build '.#nixosConfigurations.mysystem.config.system.build.installer' + + - name: Upload installer + uses: actions/upload-artifact@v2 + with: + name: installer + path: result/tarball/nixos-wsl-installer.tar.gz + release: if: startsWith(github.ref, 'refs/tags/') needs: build @@ -43,7 +54,11 @@ jobs: - uses: actions/download-artifact@v2 with: - name: install.tar.gz + name: rootfs + + - uses: actions/download-artifact@v2 + with: + name: installer - name: Create Release id: create_release @@ -59,7 +74,17 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - upload_url: ${{ steps.create_release.outputs.upload_url }} # - asset_name: install.tar.gz + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_name: nixos-wsl-x86_64-linux.tar.gz asset_path: result/tarball/nixos-wsl-x86_64-linux.tar.gz asset_content_type: application/gzip + + - name: Upload installer as release asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_name: nixos-wsl-installer.tar.gz + asset_path: result/tarball/nixos-wsl-installer.tar.gz + asset_content_type: application/gzip diff --git a/configuration.nix b/configuration.nix index 7fe5c53e..89b700be 100644 --- a/configuration.nix +++ b/configuration.nix @@ -2,18 +2,14 @@ with lib; let - defaultUser = "nixos"; - automountPath = "/mnt"; syschdemd = import ./syschdemd.nix { inherit lib pkgs config defaultUser; }; nixos-wsl = import ./default.nix; in { - imports = with nixos-wsl.nixosModules; [ + imports = [ "${modulesPath}/profiles/minimal.nix" - build-tarball - docker-desktop - wsl-distro + nixos-wsl.nixosModules.wsl ]; wsl = { @@ -26,7 +22,8 @@ in # docker.enable = true; }; - # Enable nix-flakes by default + # Enable nix flakes + nix.package = pkgs.nixFlakes; nix.extraOptions = '' experimental-features = nix-command flakes ''; diff --git a/flake.nix b/flake.nix index 5638ffa8..0c19ef4b 100644 --- a/flake.nix +++ b/flake.nix @@ -13,10 +13,13 @@ outputs = { self, nixpkgs, flake-utils, ... }: { - nixosModules = { - build-tarball = import ./modules/build-tarball.nix; - wsl-distro = import ./modules/wsl-distro.nix; - docker-desktop = import ./modules/docker-desktop.nix; + nixosModules.wsl = { + imports = [ + ./modules/build-tarball.nix + ./modules/wsl-distro.nix + ./modules/docker-desktop.nix + ./modules/installer.nix + ]; }; nixosConfigurations.mysystem = nixpkgs.lib.nixosSystem { diff --git a/modules/build-tarball.nix b/modules/build-tarball.nix index cd90e6c9..03d6a609 100644 --- a/modules/build-tarball.nix +++ b/modules/build-tarball.nix @@ -50,8 +50,11 @@ let cp ${config.environment.etc."wsl.conf".source} ./etc/wsl.conf # Copy the system configuration - mkdir -p ./etc/nixos - cp -R ${../.}/. ./etc/nixos/ + mkdir -p ./etc/nixos/nixos-wsl + cp -R ${lib.cleanSource ../.}/. ./etc/nixos/nixos-wsl + mv ./etc/nixos/nixos-wsl/configuration.nix ./etc/nixos/configuration.nix + # Patch the import path to avoid havin a flake.nix in /etc/nixos + sed -i 's|import \./default\.nix|import \./nixos-wsl|' ./etc/nixos/configuration.nix ''; in diff --git a/modules/installer.nix b/modules/installer.nix new file mode 100644 index 00000000..62a750df --- /dev/null +++ b/modules/installer.nix @@ -0,0 +1,88 @@ +{ config, lib, pkgs, ... }: +with builtins; with lib; { + + config = mkIf config.wsl.enable ( + let + mkTarball = pkgs.callPackage "${lib.cleanSource pkgs.path}/nixos/lib/make-system-tarball.nix"; + + busybox-static = pkgs.busybox.override { enableStatic = true; }; + + pkgs2storeContents = map (x: { object = x; symlink = "none"; }); + + installerDependencies = mkTarball { + fileName = "store"; + compressCommand = "cat"; + compressionExtension = ""; + contents = [ ]; + storeContents = with pkgs; pkgs2storeContents [ + pv + ]; + }; + + installer = pkgs.writeScript "installer.sh" '' + #!/bin/sh + set -e + cd / + + echo "Unpacking installer..." + tar xf /store.tar + + echo "Unpacking root file system..." + ${pkgs.pv}/bin/pv /rootfs.tar.gz | tar xz + + echo "Cleaning up installer files..." + rm /rootfs.tar.gz /store.tar /installer.sh + + echo "Activating nix configuration..." + /nix/var/nix/profiles/system/activate + + echo "Starting systemd..." + exec ${config.users.users.root.shell} + ''; + + # Set installer.sh as the root shell + passwd = pkgs.writeText "passwd" '' + root:x:0:0:System administrator:/root:/installer.sh + ''; + in + { + + system.build.installer = mkTarball { + fileName = "nixos-wsl-installer"; + compressCommand = "gzip"; + compressionExtension = ".gz"; + + contents = [ + { + source = let tarball = config.system.build.tarball; in "${tarball}/tarball/${tarball.fileName}.tar${tarball.extension}"; + target = "/rootfs.tar.gz"; + } + { source = "${installerDependencies}/tarball/store.tar"; target = "/store.tar"; } + { source = "${busybox-static}/bin/busybox"; target = "/bin/busybox"; } + { source = config.environment.etc."wsl.conf".source; target = "/etc/wsl.conf"; } + { source = passwd; target = "/etc/passwd"; } + { source = installer; target = "/installer.sh"; } + ]; + + extraCommands = + let + # WSL's --import does not like hardlinks, create symlinks instead + createBusyboxLinks = concatStringsSep "\n" ( + mapAttrsToList + (applet: type: "ln -s /bin/busybox ./bin/${applet}") + (filterAttrs + (applet: type: applet != "busybox") # don't overwrite the original busybox + (readDir "${busybox-static}/bin") + ) + ); + in + pkgs.writeShellScript "busybox-setup" '' + set -e + ${createBusyboxLinks} + ''; + }; + + } + ); + +} diff --git a/modules/wsl-distro.nix b/modules/wsl-distro.nix index fce74ee5..c2eb550f 100644 --- a/modules/wsl-distro.nix +++ b/modules/wsl-distro.nix @@ -48,6 +48,7 @@ with builtins; with lib; # WSL is closer to a container than anything else boot.isContainer = true; + environment.noXlibs = lib.mkForce false; # override xlibs not being installed (due to isContainer) to enable the use of GUI apps environment = { # Include Windows %PATH% in Linux $PATH. From bea54037949e0557cd4750c24d2be173e0901cee Mon Sep 17 00:00:00 2001 From: nzbr Date: Tue, 8 Feb 2022 20:17:12 +0100 Subject: [PATCH 15/16] auto-restart docker-desktop-proxy --- modules/docker-desktop.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/docker-desktop.nix b/modules/docker-desktop.nix index a97e4ce3..3e0d200f 100644 --- a/modules/docker-desktop.nix +++ b/modules/docker-desktop.nix @@ -22,6 +22,10 @@ with builtins; with lib; { ${config.wsl.automountPath}/wsl/docker-desktop/docker-desktop-proxy -docker-desktop-root ${config.wsl.automountPath}/wsl/docker-desktop ''; wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Restart = "on-failure"; + RestartSec = "30s"; + }; }; users.groups.docker.members = [ From 06c777ae81cca1d0b10b368898d11cff5dc30934 Mon Sep 17 00:00:00 2001 From: nzbr Date: Fri, 18 Mar 2022 21:24:01 +0100 Subject: [PATCH 16/16] improve installer --- modules/installer.nix | 68 +++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 45 deletions(-) diff --git a/modules/installer.nix b/modules/installer.nix index 62a750df..65754001 100644 --- a/modules/installer.nix +++ b/modules/installer.nix @@ -5,44 +5,41 @@ with builtins; with lib; { let mkTarball = pkgs.callPackage "${lib.cleanSource pkgs.path}/nixos/lib/make-system-tarball.nix"; - busybox-static = pkgs.busybox.override { enableStatic = true; }; - pkgs2storeContents = map (x: { object = x; symlink = "none"; }); - installerDependencies = mkTarball { - fileName = "store"; - compressCommand = "cat"; - compressionExtension = ""; - contents = [ ]; - storeContents = with pkgs; pkgs2storeContents [ - pv - ]; - }; + rootfs = let tarball = config.system.build.tarball; in "${tarball}/tarball/${tarball.fileName}.tar${tarball.extension}"; installer = pkgs.writeScript "installer.sh" '' - #!/bin/sh + #!${pkgs.busybox}/bin/sh + BASEPATH=$PATH + export PATH=$BASEPATH:${pkgs.busybox}/bin # Add busybox to path + set -e cd / - echo "Unpacking installer..." - tar xf /store.tar - echo "Unpacking root file system..." - ${pkgs.pv}/bin/pv /rootfs.tar.gz | tar xz - - echo "Cleaning up installer files..." - rm /rootfs.tar.gz /store.tar /installer.sh + ${pkgs.pv}/bin/pv ${rootfs} | tar xz echo "Activating nix configuration..." /nix/var/nix/profiles/system/activate + PATH=$BASEPATH:/run/current-system/sw/bin # Use packages from target system + + echo "Cleaning up installer files..." + nix-collect-garbage + rm /nix-path-registration + + echo "Optimizing store..." + nix-store --optimize + echo "Starting systemd..." - exec ${config.users.users.root.shell} + # Don't package the shell here, it's contained in the rootfs + exec ${builtins.unsafeDiscardStringContext config.users.users.root.shell} "$@" ''; # Set installer.sh as the root shell passwd = pkgs.writeText "passwd" '' - root:x:0:0:System administrator:/root:/installer.sh + root:x:0:0:System administrator:/root:${installer} ''; in { @@ -51,35 +48,16 @@ with builtins; with lib; { fileName = "nixos-wsl-installer"; compressCommand = "gzip"; compressionExtension = ".gz"; + extraArgs = "--hard-dereference"; + + storeContents = with pkgs; pkgs2storeContents [ + installer + ]; contents = [ - { - source = let tarball = config.system.build.tarball; in "${tarball}/tarball/${tarball.fileName}.tar${tarball.extension}"; - target = "/rootfs.tar.gz"; - } - { source = "${installerDependencies}/tarball/store.tar"; target = "/store.tar"; } - { source = "${busybox-static}/bin/busybox"; target = "/bin/busybox"; } { source = config.environment.etc."wsl.conf".source; target = "/etc/wsl.conf"; } { source = passwd; target = "/etc/passwd"; } - { source = installer; target = "/installer.sh"; } ]; - - extraCommands = - let - # WSL's --import does not like hardlinks, create symlinks instead - createBusyboxLinks = concatStringsSep "\n" ( - mapAttrsToList - (applet: type: "ln -s /bin/busybox ./bin/${applet}") - (filterAttrs - (applet: type: applet != "busybox") # don't overwrite the original busybox - (readDir "${busybox-static}/bin") - ) - ); - in - pkgs.writeShellScript "busybox-setup" '' - set -e - ${createBusyboxLinks} - ''; }; }