Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite syschdemd #126

Merged
merged 1 commit into from
Aug 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
- uses: actions/download-artifact@v2
with:
name: installer

- name: Generate checksums
run: |
for x in *.tar.gz; do
Expand Down
16 changes: 8 additions & 8 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,16 @@
pkgs = import nixpkgs { inherit system; };
in
{
checks.check-format = pkgs.runCommand "check-format"
{
buildInputs = with pkgs; [ nixpkgs-fmt ];
} ''
nixpkgs-fmt --check ${./.}
mkdir $out # success
'';
checks = {
check-format = pkgs.runCommand "check-format" { nativeBuildInputs = with pkgs; [ nixpkgs-fmt shfmt ]; } ''
nixpkgs-fmt --check ${./.}
shfmt -i 2 -d ${./scripts}/*.sh
mkdir $out # success
'';
};

devShell = pkgs.mkShell {
nativeBuildInputs = with pkgs; [ nixpkgs-fmt ];
nativeBuildInputs = with pkgs; [ nixpkgs-fmt shfmt ];
};
}
);
Expand Down
2 changes: 1 addition & 1 deletion modules/wsl-distro.nix
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ with builtins; with lib;
config =
let
cfg = config.wsl;
syschdemd = import ../syschdemd.nix { inherit lib pkgs config; inherit (cfg) automountPath defaultUser; defaultUserHome = config.users.users.${cfg.defaultUser}.home; };
syschdemd = pkgs.callPackage ../scripts/syschdemd.nix { inherit (cfg) automountPath defaultUser; };
in
mkIf cfg.enable {

Expand Down
51 changes: 51 additions & 0 deletions scripts/syschdemd.nix
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
,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

}:
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;
}
136 changes: 136 additions & 0 deletions scripts/syschdemd.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#!/usr/bin/env bash
set -euo pipefail

[ "${NIXOS_WSL_DEBUG:-}" == "1" ] && set -x
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[ "${NIXOS_WSL_DEBUG:-}" == "1" ] && set -x
[[ -v NIXOS_WSL_DEBUG ]] && set -x

testing if it is set to anything maybe makes it easier if people accidentally use true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, applied.


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

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 \
--propagation=unchanged \
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 "$@"
6 changes: 6 additions & 0 deletions scripts/wrapper.sh
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
28 changes: 0 additions & 28 deletions syschdemd.nix

This file was deleted.

78 changes: 0 additions & 78 deletions syschdemd.sh

This file was deleted.