From 60e83e345d3938574f8d1727df1a57cb1fca54cc Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sun, 25 Dec 2022 17:12:13 -0500 Subject: [PATCH 1/7] Introduce run_app_container script --- app_containers/.local/bin/run_app_container | 56 +++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100755 app_containers/.local/bin/run_app_container diff --git a/app_containers/.local/bin/run_app_container b/app_containers/.local/bin/run_app_container new file mode 100755 index 0000000..88d94d3 --- /dev/null +++ b/app_containers/.local/bin/run_app_container @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +die() { + echo "$1" >&2 + exit 1 +} + +[ -z "$CONTAINER_NAME" ] && die "\$CONTAINER_NAME not set" +[ -z "$DISPLAY" ] && die "\$DISPLAY not set (you must run the script in a desktop environment" + +# From +if [[ -n $DBUS_SESSION_BUS_ADDRESS ]]; then # remove prefix + host_bus=${DBUS_SESSION_BUS_ADDRESS#unix:path=} +else # default guess + host_bus=$XDG_RUNTIME_DIR/bus +fi + +if [[ -n $PULSE_SERVER ]]; then # remove prefix + host_pulse=${PULSE_SERVER#unix:} +else # default guess + host_pulse=$XDG_RUNTIME_DIR/pulse +fi + +# Default username +run_as=user +homedir=/home/user +if [ "$CONTAINER_RUN_AS_ROOT" = true ]; then + run_as=root + homedir=/root +fi + +sudo systemd-nspawn -M $CONTAINER_NAME \ + `# DNS (when containers do not have their own netns)` \ + --bind-ro=/run/systemd/resolve/stub-resolv.conf:/etc/resolv.conf \ + `# GPU` \ + --bind=/dev/dri/card0 \ + --bind=/dev/shm \ + --property=DeviceAllow='char-drm rw' \ + `# Input devices` \ + --bind-ro=/dev/input \ + --property=DeviceAllow='char-input r' \ + `# Xorg / Xwayland` \ + --bind-ro=/tmp/.X11-unix \ + --setenv=DISPLAY=$DISPLAY \ + `# PulseAudio` \ + --bind-ro=$host_pulse:/run/host/pulse \ + --setenv=PULSE_SERVER=unix:/run/host/pulse/native \ + `# DBus` \ + --bind-ro=$host_bus:/run/host/bus \ + --setenv=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/host/bus \ + `# Scaling `\ + --setenv=GDK_SCALE="$GDK_SCALE" \ + `# Extra params` \ + $SYSTEMD_NSPAWN_EXTRA_ARGS \ + `# Launch app` \ + --user=$run_as --chdir=$homedir --as-pid2 $@ From c3d5c58ce30921e096c1044dc3b52b0b3c89fe3a Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sun, 25 Dec 2022 17:34:25 -0500 Subject: [PATCH 2/7] app_containers: Add Wayland handling --- app_containers/.local/bin/run_app_container | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/app_containers/.local/bin/run_app_container b/app_containers/.local/bin/run_app_container index 88d94d3..2e5380f 100755 --- a/app_containers/.local/bin/run_app_container +++ b/app_containers/.local/bin/run_app_container @@ -8,6 +8,14 @@ die() { [ -z "$CONTAINER_NAME" ] && die "\$CONTAINER_NAME not set" [ -z "$DISPLAY" ] && die "\$DISPLAY not set (you must run the script in a desktop environment" +# Create a XDG_RUNTIME_DIR for guest on host +container_xdg_runtime="$(mktemp -d)" +trap 'rm -rf -- "$container_xdg_runtime"' EXIT + +# Link the current wayland session to the container's xdg runtime +# Note that the session itself must be bind-mounted first +ln -s /run/host/$WAYLAND_DISPLAY $container_xdg_runtime/$WAYLAND_DISPLAY + # From if [[ -n $DBUS_SESSION_BUS_ADDRESS ]]; then # remove prefix host_bus=${DBUS_SESSION_BUS_ADDRESS#unix:path=} @@ -21,7 +29,7 @@ else # default guess host_pulse=$XDG_RUNTIME_DIR/pulse fi -# Default username +# Default username (assume `user` always has the same uid as the host user) run_as=user homedir=/home/user if [ "$CONTAINER_RUN_AS_ROOT" = true ]; then @@ -39,9 +47,15 @@ sudo systemd-nspawn -M $CONTAINER_NAME \ `# Input devices` \ --bind-ro=/dev/input \ --property=DeviceAllow='char-input r' \ + `# Xdg runtime` \ + --bind=$container_xdg_runtime:/run/xdg \ + --setenv=XDG_RUNTIME_DIR=/run/xdg \ `# Xorg / Xwayland` \ --bind-ro=/tmp/.X11-unix \ --setenv=DISPLAY=$DISPLAY \ + `# Wayland (note the symlink created before in xdg runtime)` \ + --bind-ro=$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY:/run/host/$WAYLAND_DISPLAY \ + --setenv=WAYLAND_DISPLAY=$WAYLAND_DISPLAY \ `# PulseAudio` \ --bind-ro=$host_pulse:/run/host/pulse \ --setenv=PULSE_SERVER=unix:/run/host/pulse/native \ From 39a6b458a2801b9f83b33bed486c4b28bf35d7c8 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sun, 25 Dec 2022 17:39:32 -0500 Subject: [PATCH 3/7] Add askpass-bemenu --- utils/.local/bin/askpass-bemenu | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100755 utils/.local/bin/askpass-bemenu diff --git a/utils/.local/bin/askpass-bemenu b/utils/.local/bin/askpass-bemenu new file mode 100755 index 0000000..ff69bb6 --- /dev/null +++ b/utils/.local/bin/askpass-bemenu @@ -0,0 +1,7 @@ +#!/bin/sh +/usr/bin/bemenu \ + --prompt "$1" \ + --password \ + --no-exec \ + Date: Sun, 25 Dec 2022 17:40:15 -0500 Subject: [PATCH 4/7] app_containers: Use askpass_bemenu to invoke sudo This makes it work in GUI mode --- app_containers/.local/bin/run_app_container | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app_containers/.local/bin/run_app_container b/app_containers/.local/bin/run_app_container index 2e5380f..9cde486 100755 --- a/app_containers/.local/bin/run_app_container +++ b/app_containers/.local/bin/run_app_container @@ -37,7 +37,7 @@ if [ "$CONTAINER_RUN_AS_ROOT" = true ]; then homedir=/root fi -sudo systemd-nspawn -M $CONTAINER_NAME \ +SUDO_ASKPASS=$HOME/.local/bin/askpass-bemenu sudo -A systemd-nspawn -M $CONTAINER_NAME \ `# DNS (when containers do not have their own netns)` \ --bind-ro=/run/systemd/resolve/stub-resolv.conf:/etc/resolv.conf \ `# GPU` \ From 79aeb5321f2f9e8f280404e3c72c890e154f204d Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sun, 25 Dec 2022 17:58:36 -0500 Subject: [PATCH 5/7] app_containers: Support per-container config We don't use the .nspawn files because they live in /etc... --- app_containers/.local/bin/run_app_container | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app_containers/.local/bin/run_app_container b/app_containers/.local/bin/run_app_container index 9cde486..803cdfc 100755 --- a/app_containers/.local/bin/run_app_container +++ b/app_containers/.local/bin/run_app_container @@ -8,6 +8,12 @@ die() { [ -z "$CONTAINER_NAME" ] && die "\$CONTAINER_NAME not set" [ -z "$DISPLAY" ] && die "\$DISPLAY not set (you must run the script in a desktop environment" +# Source configuration files if any +config="$HOME/.config/app_containers/$CONTAINER_NAME.sh" +if [ -f "$config" ]; then + source "$config" +fi + # Create a XDG_RUNTIME_DIR for guest on host container_xdg_runtime="$(mktemp -d)" trap 'rm -rf -- "$container_xdg_runtime"' EXIT From 529f6e358c01398ca60e1943f7a3e4375c3ee5ba Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sun, 25 Dec 2022 19:00:48 -0500 Subject: [PATCH 6/7] app_containers: Bind the entire /dev/dri subdirectory --- app_containers/.local/bin/run_app_container | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app_containers/.local/bin/run_app_container b/app_containers/.local/bin/run_app_container index 803cdfc..3c8f5c6 100755 --- a/app_containers/.local/bin/run_app_container +++ b/app_containers/.local/bin/run_app_container @@ -47,9 +47,10 @@ SUDO_ASKPASS=$HOME/.local/bin/askpass-bemenu sudo -A systemd-nspawn -M $CONTAINE `# DNS (when containers do not have their own netns)` \ --bind-ro=/run/systemd/resolve/stub-resolv.conf:/etc/resolv.conf \ `# GPU` \ - --bind=/dev/dri/card0 \ + --bind=/dev/dri \ --bind=/dev/shm \ - --property=DeviceAllow='char-drm rw' \ + --property=DeviceAllow='/dev/dri rw' \ + --property=DeviceAllow='/dev/shm rw' \ `# Input devices` \ --bind-ro=/dev/input \ --property=DeviceAllow='char-input r' \ From 2fbffcda507c8e0d826fe0a0297b68fdce7a1d74 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sun, 25 Dec 2022 19:01:08 -0500 Subject: [PATCH 7/7] app_containers: Add automatic shortcut generation --- .../bin/generate_shortcut_container_app | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100755 app_containers/.local/bin/generate_shortcut_container_app diff --git a/app_containers/.local/bin/generate_shortcut_container_app b/app_containers/.local/bin/generate_shortcut_container_app new file mode 100755 index 0000000..064bc88 --- /dev/null +++ b/app_containers/.local/bin/generate_shortcut_container_app @@ -0,0 +1,36 @@ +#!/bin/bash + +die() { + echo "$1" >&2 + exit 1 +} + +container_name="$1" +[ -z "container_name" ] && die "Please provide name of container" +container_root=/var/lib/machines/$container_name + +app_name="$2" +[ -z "$app_name" ] && die "Please provide name of app" + +desktop_file=$container_root/usr/share/applications/$app_name.desktop +desktop_file_content=$(sudo cat $desktop_file 2>/dev/null) +[ $? == 0 ] || die "App $app_name not found in container $container_name" + +icon_name=$(echo "$desktop_file_content" | grep "Icon=" | head -1 | cut -d'=' -f 2) +[ -z "$icon_name" ] && die "No icon defined for app $app_name" + +icon_root=$container_root/usr/share/icons/hicolor +icons=($(sudo find $icon_root -name "$icon_name.*")) +[ ${#icons[@]} == 0 ] && die "Cannot find any icon for app $app_name" + +for icon in ${icons[@]}; do + icon_target=${icon//$icon_root/$HOME/.local/share/icons/hicolor} + icon_target_dir=$(dirname "$icon_target") + echo "Copying $icon to $icon_target in $icon_target_dir" + mkdir -p "$icon_target_dir" + sudo cat "$icon" > "$icon_target" +done + +mkdir -p $HOME/.local/share/applications +echo "$desktop_file_content" | sed -r "s@^Exec=(.*)\$@Exec=env CONTAINER_NAME=$container_name $HOME/.local/bin/run_app_container \\1@g" > $HOME/.local/share/applications/$app_name.desktop +echo "Created $HOME/.local/share/applications/$app_name.desktop"