Add updated wsl configuration

This commit is contained in:
Dave Gallant
2022-07-30 13:42:28 +00:00
parent e0b6e5782c
commit 328b2a2d95
20 changed files with 3 additions and 4 deletions

View File

@@ -0,0 +1,92 @@
{
config,
pkgs,
lib,
...
}:
with builtins;
with lib; let
pkgs2storeContents = l:
map (x: {
object = x;
symlink = "none";
})
l;
nixpkgs = lib.cleanSource pkgs.path;
channelSources =
pkgs.runCommand "nixos-${config.system.nixos.version}"
{preferLocalBuild = true;}
''
mkdir -p $out
cp -prd ${nixpkgs.outPath} $out/nixos
chmod -R u+w $out/nixos
if [ ! -e $out/nixos/nixpkgs ]; then
ln -s . $out/nixos/nixpkgs
fi
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" ''
set -e
mkdir -m 0755 ./bin ./etc
mkdir -m 1777 ./tmp
# WSL requires a /bin/sh - only temporary, NixOS's activate will overwrite
ln -s ${config.users.users.root.shell} ./bin/sh
# WSL also requires a /bin/mount, otherwise the host fs isn't accessible
ln -s /nix/var/nix/profiles/system/sw/bin/mount ./bin/mount
# Set system profile
system=${config.system.build.toplevel}
./$system/sw/bin/nix-store --store `pwd` --load-db < ./nix-path-registration
rm ./nix-path-registration
./$system/sw/bin/nix-env --store `pwd` -p ./nix/var/nix/profiles/system --set $system
# Set channel
mkdir -p ./nix/var/nix/profiles/per-user/root
./$system/sw/bin/nix-env --store `pwd` -p ./nix/var/nix/profiles/per-user/root/channels --set ${channelSources}
mkdir -m 0700 -p ./root/.nix-defexpr
ln -s /nix/var/nix/profiles/per-user/root/channels ./root/.nix-defexpr/channels
# 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/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
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 = [];
fileName = "nixos-wsl-${pkgs.hostPlatform.system}";
storeContents = pkgs2storeContents [
config.system.build.toplevel
channelSources
preparer
];
extraCommands = "${preparer}/bin/wsl-prepare";
# Use gzip
compressCommand = "gzip";
compressionExtension = ".gz";
};
}

View File

@@ -0,0 +1,38 @@
{
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-user-distro proxy --docker-desktop-root ${config.wsl.automountPath}/wsl/docker-desktop
'';
wantedBy = ["multi-user.target"];
serviceConfig = {
Restart = "on-failure";
RestartSec = "30s";
};
};
users.groups.docker.members = [
config.wsl.defaultUser
];
};
}

View File

@@ -0,0 +1,77 @@
{
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";
pkgs2storeContents = map (x: {
object = x;
symlink = "none";
});
rootfs = let tarball = config.system.build.tarball; in "${tarball}/tarball/${tarball.fileName}.tar${tarball.extension}";
installer = pkgs.writeScript "installer.sh" ''
#!${pkgs.busybox}/bin/sh
BASEPATH=$PATH
export PATH=$BASEPATH:${pkgs.busybox}/bin # Add busybox to path
set -e
cd /
echo "Unpacking root file system..."
${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..."
# 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}
'';
in {
system.build.installer = mkTarball {
fileName = "nixos-wsl-installer";
compressCommand = "gzip";
compressionExtension = ".gz";
extraArgs = "--hard-dereference";
storeContents = with pkgs;
pkgs2storeContents [
installer
];
contents = [
{
source = config.environment.etc."wsl.conf".source;
target = "/etc/wsl.conf";
}
{
source = passwd;
target = "/etc/passwd";
}
];
};
}
);
}

View File

@@ -0,0 +1,33 @@
{
config,
lib,
pkgs,
...
}:
with builtins;
with lib; {
options.wsl.tailscale = with types; {
enable = mkEnableOption "Tailscale for WSL";
};
config = let
cfg = config.wsl.tailscale;
in
mkIf (config.wsl.enable && cfg.enable) {
environment.systemPackages = with pkgs; [
tailscale
];
systemd.services.tailscaled = {
description = "Tailscale WSL";
script = ''
${pkgs.tailscale}/bin/tailscaled
'';
wantedBy = ["multi-user.target"];
serviceConfig = {
Restart = "on-failure";
RestartSec = "30s";
};
};
};
}

View File

@@ -0,0 +1,137 @@
{
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";
};
interop = {
register = mkOption {
type = bool;
default = true;
description = "Explicitly register the binfmt_misc handler for Windows executables";
};
includePath = mkOption {
type = bool;
default = true;
description = "Include Windows PATH in WSL PATH";
};
};
};
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;
binfmt.registrations = mkIf cfg.interop.register {
WSLInterop = {
magicOrExtension = "MZ";
interpreter = "/init";
fixBinary = 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.
extraInit = mkIf cfg.interop.includePath ''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
shell = pkgs.zsh;
};
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"
mkdir -p /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;
};
}