blob: f5b94ce16f1f4f1b42688a79a8815f5c7f1ddfa0 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
{ lib, pkgs, config, options, ... }:
with lib; {
options.wsl = with types; {
enable = mkEnableOption "support for running NixOS as a WSL distribution";
nativeSystemd = mkOption {
type = bool;
default = false;
description = "Use native WSL systemd support";
};
defaultUser = mkOption {
type = str;
default = "nixos";
description = "The name of the default user";
};
startMenuLaunchers = mkEnableOption "shortcuts for GUI applications in the windows start menu";
};
config =
let
cfg = config.wsl;
syschdemd = pkgs.callPackage ../scripts/syschdemd.nix {
automountPath = cfg.wslConf.automount.root;
defaultUser = config.users.users.${cfg.defaultUser};
};
shim = pkgs.callPackage ../scripts/native-systemd-shim/shim.nix { };
bashWrapper = pkgs.runCommand "nixos-wsl-bash-wrapper" { nativeBuildInputs = [ pkgs.makeWrapper ]; } ''
makeWrapper ${pkgs.bashInteractive}/bin/sh $out/bin/sh --prefix PATH ':' ${lib.makeBinPath [pkgs.systemd pkgs.gnugrep]}
'';
bash = if cfg.nativeSystemd then bashWrapper else pkgs.bashInteractive;
in
mkIf cfg.enable (
mkMerge [
{
# WSL uses its own kernel and boot loader
boot = {
initrd.enable = false;
kernel.enable = false;
loader.grub.enable = false;
modprobeConfig.enable = false;
};
# WSL does not support virtual consoles
console.enable = false;
hardware.opengl.enable = true; # Enable GPU acceleration
environment = {
# Only set the options if the files are managed by WSL
etc = mkMerge [
(mkIf config.wsl.wslConf.network.generateHosts {
hosts.enable = false;
})
(mkIf config.wsl.wslConf.network.generateResolvConf {
"resolv.conf".enable = false;
})
];
};
# dhcp is handled by windows
networking.dhcpcd.enable = false;
users.users.${cfg.defaultUser} = {
isNormalUser = true;
uid = 1000;
extraGroups = [ "wheel" ]; # Allow the default user to use sudo
};
# Otherwise WSL fails to login as root with "initgroups failed 5"
users.users.root.extraGroups = [ "root" ];
powerManagement.enable = false;
security.sudo.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 "setting up /usr/share/''${x}..."
if [[ -d $systemConfig/sw/share/$x ]]; then
mkdir -p /usr/share/$x
${pkgs.rsync}/bin/rsync -ar --delete $systemConfig/sw/share/$x/. /usr/share/$x
else
rm -rf /usr/share/$x
fi
done
''
);
populateBin = stringAfter [ ] ''
echo "setting up /bin..."
ln -sf /init /bin/wslpath
ln -sf ${bash}/bin/sh /bin/sh
ln -sf ${pkgs.util-linux}/bin/mount /bin/mount
'';
update-entrypoint.text = ''
mkdir -p /nix/nixos-wsl
ln -sfn ${config.users.users.root.shell} /nix/nixos-wsl/entrypoint
'';
};
# no udev devices can be attached
services.udev.enable = lib.mkDefault false;
systemd = {
# Disable systemd units that don't make sense on WSL
services = {
firewall.enable = false;
systemd-resolved.enable = lib.mkDefault false;
# system clock cannot be changed
systemd-timesyncd.enable = false;
};
# Don't allow emergency mode, because we don't have a console.
enableEmergencyMode = false;
# Link the X11 socket into place. This is a no-op on a normal setup,
# but helps if /tmp is a tmpfs or mounted from some other location.
tmpfiles.rules = [ "L /tmp/.X11-unix - - - - ${cfg.wslConf.automount.root}/wslg/.X11-unix" ];
};
# Start a systemd user session when starting a command through runuser
security.pam.services.runuser.startSession = true;
warnings = flatten [
(optional (config.services.resolved.enable && config.wsl.wslConf.network.generateResolvConf)
"systemd-resolved is enabled, but resolv.conf is managed by WSL (wsl.wslConf.network.generateResolvConf)"
)
(optional ((length config.networking.nameservers) > 0 && config.wsl.wslConf.network.generateResolvConf)
"custom nameservers are set (networking.nameservers), but resolv.conf is managed by WSL (wsl.wslConf.network.generateResolvConf)"
)
(optional ((length config.networking.nameservers) == 0 && !config.services.resolved.enable && !config.wsl.wslConf.network.generateResolvConf)
"resolv.conf generation is turned off (wsl.wslConf.network.generateResolvConf), but no other nameservers are configured (networking.nameservers)"
)
];
}
(mkIf (!cfg.nativeSystemd) {
users.users.root.shell = "${syschdemd}/bin/syschdemd";
security.sudo.extraConfig = ''
Defaults env_keep+=INSIDE_NAMESPACE
'';
wsl.wslConf.user.default = "root";
# Include Windows %PATH% in Linux $PATH.
environment.extraInit = mkIf cfg.interop.includePath ''PATH="$PATH:$WSLPATH"'';
})
(mkIf cfg.nativeSystemd {
wsl.wslConf = {
user.default = config.users.users.${cfg.defaultUser}.name;
boot.systemd = true;
};
system.activationScripts = {
shimSystemd = stringAfter [ ] ''
echo "setting up /sbin/init shim..."
mkdir -p /sbin
ln -sf ${shim}/bin/nixos-wsl-native-systemd-shim /sbin/init
'';
setupLogin = stringAfter [ ] ''
echo "setting up /bin/login..."
mkdir -p /bin
ln -sf ${pkgs.shadow}/bin/login /bin/login
'';
};
environment = {
# preserve $PATH from parent
variables.PATH = [ "$PATH" ];
extraInit = ''
export WSLPATH=$(echo "$PATH" | tr ':' '\0' | command grep -az "^${cfg.wslConf.automount.root}" | tr '\0' ':')
${if cfg.interop.includePath then "" else ''
export PATH=$(echo "$PATH" | tr ':' '\0' | command grep -avz "^${cfg.wslConf.automount.root}" | tr '\0' ':')
''}
'';
};
})
# this option doesn't exist on older NixOS, so hack.
(lib.optionalAttrs (builtins.hasAttr "oomd" options.systemd) {
# systemd-oomd requires cgroup pressure info which WSL doesn't have
systemd.oomd.enable = false;
})
]);
}
|