mirror of
https://github.com/davegallant/nix-config
synced 2025-08-07 17:32:26 +00:00
Add updated wsl configuration
This commit is contained in:
92
machines/aether/nixos-wsl/modules/build-tarball.nix
Normal file
92
machines/aether/nixos-wsl/modules/build-tarball.nix
Normal 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";
|
||||
};
|
||||
}
|
38
machines/aether/nixos-wsl/modules/docker-desktop.nix
Normal file
38
machines/aether/nixos-wsl/modules/docker-desktop.nix
Normal 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
|
||||
];
|
||||
};
|
||||
}
|
77
machines/aether/nixos-wsl/modules/installer.nix
Normal file
77
machines/aether/nixos-wsl/modules/installer.nix
Normal 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";
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
33
machines/aether/nixos-wsl/modules/tailscale.nix
Normal file
33
machines/aether/nixos-wsl/modules/tailscale.nix
Normal 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";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
137
machines/aether/nixos-wsl/modules/wsl-distro.nix
Normal file
137
machines/aether/nixos-wsl/modules/wsl-distro.nix
Normal 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;
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user