-
-
Notifications
You must be signed in to change notification settings - Fork 120
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Mostly just a big pile of cleanups. Important changes: - refactor and clean up the code, fix all the shellcheck complaints - stop trying to guess paths in scripts and wrap them correctly instead - use nsfs instead of trying to figure out the right PID to copy namespaces from - clean up $WSLPATH to remove extra impure entries - don't try to restart systemd if it died - make sure the store is read-only before we do anything, so systemd can't mess with it - reformat shell scripts with shfmt
- Loading branch information
Showing
8 changed files
with
205 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
{ runCommand | ||
, makeWrapper | ||
, lib | ||
, coreutils | ||
, daemonize | ||
, glibc | ||
, gnugrep | ||
, systemd | ||
, util-linux | ||
, defaultUser | ||
, automountPath | ||
, | ||
}: | ||
let | ||
mkWrappedScript = | ||
{ name | ||
, src | ||
, path | ||
, ... | ||
} @ args: | ||
runCommand name ({ nativeBuildInputs = [ makeWrapper ]; } // args) '' | ||
install -Dm755 ${src} $out/bin/${name} | ||
patchShebangs $out/bin/${name} | ||
substituteAllInPlace $out/bin/${name} | ||
wrapProgram $out/bin/${name} --prefix PATH ':' ${lib.escapeShellArg path} | ||
''; | ||
|
||
wrapper = mkWrappedScript { | ||
name = "nixos-wsl-systemd-wrapper"; | ||
src = ./wrapper.sh; | ||
path = lib.makeSearchPath "" [ | ||
"/run/wrappers/bin" # mount | ||
"${systemd}/lib/systemd" # systemd | ||
]; | ||
}; | ||
in | ||
mkWrappedScript { | ||
name = "syschdemd"; | ||
src = ./syschdemd.sh; | ||
path = lib.makeBinPath [ | ||
"/run/wrappers" # mount | ||
coreutils | ||
daemonize | ||
glibc # getent | ||
gnugrep | ||
systemd # machinectl | ||
util-linux # nsenter | ||
wrapper | ||
]; | ||
inherit defaultUser automountPath; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
#!/usr/bin/env bash | ||
set -euo pipefail | ||
|
||
[ "${NIXOS_WSL_DEBUG:-}" == "1" ] && set -x | ||
|
||
rundir="/run/nixos-wsl" | ||
pidfile="$rundir/unshare.pid" | ||
|
||
ensure_root() { | ||
if [ $EUID -ne 0 ]; then | ||
echo "[ERROR] Requires root! :( Make sure the WSL default user is set to root" >&2 | ||
exit 1 | ||
fi | ||
} | ||
|
||
activate() { | ||
mount --bind -o ro /nix/store /nix/store | ||
|
||
mount --bind "@automountPath@" "@automountPath@" | ||
mount --make-rshared "@automountPath@" | ||
|
||
LANG="C.UTF-8" /nix/var/nix/profiles/system/activate | ||
} | ||
|
||
create_rundir() { | ||
if [ ! -d $rundir ]; then | ||
mkdir -p $rundir/ns | ||
touch $rundir/ns/{pid,mount} | ||
fi | ||
} | ||
|
||
is_unshare_alive() { | ||
[ -e $pidfile ] && [ -d "/proc/$(<$pidfile)" ] | ||
} | ||
|
||
run_in_namespace() { | ||
nsenter \ | ||
--pid=$rundir/ns/pid \ | ||
--mount=$rundir/ns/mount \ | ||
-- "$@" | ||
} | ||
|
||
start_systemd() { | ||
daemonize \ | ||
-o $rundir/stdout \ | ||
-e $rundir/stderr \ | ||
-l $rundir/systemd.lock \ | ||
-p $pidfile \ | ||
-E LOCALE_ARCHIVE=/run/current-system/sw/lib/locale/locale-archive \ | ||
"$(command -v unshare)" \ | ||
--fork \ | ||
--pid=$rundir/ns/pid \ | ||
--mount=$rundir/ns/mount \ | ||
--mount-proc=/proc \ | ||
nixos-wsl-systemd-wrapper | ||
|
||
# Wait for systemd to start | ||
while ! (run_in_namespace systemctl is-system-running -q --wait) &>/dev/null; do | ||
sleep 1 | ||
|
||
if ! is_unshare_alive; then | ||
echo "[ERROR] systemd startup failed!" | ||
|
||
echo "[ERROR] stderr:" | ||
cat $rundir/stderr | ||
|
||
echo "[ERROR] stdout:" | ||
cat $rundir/stdout | ||
|
||
exit 1 | ||
fi | ||
done | ||
} | ||
|
||
get_shell() { | ||
getent passwd "$1" | cut -d: -f7 | ||
} | ||
|
||
get_home() { | ||
getent passwd "$1" | cut -d: -f6 | ||
} | ||
|
||
is_in_container() { | ||
[ "${INSIDE_NAMESPACE:-}" == "true" ] | ||
} | ||
|
||
clean_wslpath() { | ||
echo "$PATH" | tr ':' '\n' | grep -E "^@automountPath@" | tr '\n' ':' | ||
} | ||
|
||
main() { | ||
ensure_root | ||
|
||
if [ ! -e "/run/current-system" ]; then | ||
activate | ||
fi | ||
|
||
if [ ! -e "$rundir" ]; then | ||
create_rundir | ||
fi | ||
|
||
if ! is_in_container && ! is_unshare_alive; then | ||
start_systemd | ||
fi | ||
|
||
if [ $# -gt 0 ]; then | ||
# wsl seems to prefix with "-c" | ||
shift | ||
command="$*" | ||
else | ||
command=$(get_shell @defaultUser@) | ||
fi | ||
|
||
# If we're executed from inside the container, e.g. sudo | ||
if is_in_container; then | ||
exec $command | ||
fi | ||
|
||
# If we are currently in /root, this is probably because the directory that WSL was started is inaccessible | ||
# cd to the user's home to prevent a warning about permission being denied on /root | ||
if [ "$PWD" == "/root" ]; then | ||
cd "$(get_home @defaultUser@)" | ||
fi | ||
|
||
# Pass external environment but filter variables specific to root user. | ||
exportCmd="$(export -p | grep -vE ' (HOME|LOGNAME|SHELL|USER)=')" | ||
|
||
run_in_namespace \ | ||
machinectl \ | ||
--quiet \ | ||
--uid=@defaultUser@ \ | ||
--setenv=INSIDE_NAMESPACE=true \ | ||
--setenv=WSLPATH="$(clean_wslpath)" \ | ||
shell .host \ | ||
/bin/sh -c "cd \"$PWD\"; $exportCmd; source /etc/set-environment; exec $command" | ||
} | ||
|
||
main "$@" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#!/usr/bin/env bash | ||
set -euxo pipefail | ||
|
||
mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc | ||
|
||
exec systemd |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.