mirror of
https://github.com/foo-dogsquared/nixos-config.git
synced 2025-01-31 04:58:01 +00:00
wrapper-manager/sandboxing/bubblewrap: init launcher submodule
At the end of the day, I decided to make it in nixpkgs' runtime shell (GNU Bash) instead of Rust because it'll be a pain in the ass.
This commit is contained in:
parent
e042128be3
commit
3a4833d46d
@ -55,7 +55,7 @@ let
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
#./launcher.nix
|
||||
./launcher.nix
|
||||
./dbus-filter.nix
|
||||
./filesystem.nix
|
||||
];
|
||||
@ -77,27 +77,18 @@ in
|
||||
|
||||
config = lib.mkIf (config.sandboxing.variant == "bubblewrap") (lib.mkMerge [
|
||||
{
|
||||
# TODO: All of the Linux-exclusive flags could be handled by the
|
||||
# launcher instead. ALSO MODULARIZE THIS CRAP!
|
||||
# Ordering of the arguments here matter(?).
|
||||
sandboxing.bubblewrap.extraArgs =
|
||||
cfg.extraArgs
|
||||
++ lib.optionals stdenv.isLinux [
|
||||
"--proc" "/proc"
|
||||
"--dev" "/dev"
|
||||
]
|
||||
++ lib.mapAttrsToList
|
||||
(var: metadata:
|
||||
if metadata.action == "unset"
|
||||
then "--unsetenv ${var}"
|
||||
else "--setenv ${var} ${metadata.value}")
|
||||
if metadata.action == "unset" then
|
||||
"--unsetenv ${var}"
|
||||
else if lib.elem metadata.action [ "prefix" "suffix" ] then
|
||||
"--setenv ${var} ${lib.escapeShellArg (lib.concatStringsSep metadata.separator metadata.value)}"
|
||||
else
|
||||
"--setenv ${var} ${metadata.value}")
|
||||
config.env;
|
||||
|
||||
arg0 = lib.getExe' submoduleCfg.package "bwrap";
|
||||
prependArgs = lib.mkBefore
|
||||
(submoduleCfg.extraArgs
|
||||
++ [ "--" config.sandboxing.wraparound.arg0 ]
|
||||
++ config.sandboxing.wraparound.extraArgs);
|
||||
}
|
||||
|
||||
(lib.mkIf submoduleCfg.enableNetwork {
|
||||
|
81
modules/wrapper-manager/sandboxing/bubblewrap/launcher.nix
Normal file
81
modules/wrapper-manager/sandboxing/bubblewrap/launcher.nix
Normal file
@ -0,0 +1,81 @@
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.sandboxing.bubblewrap.launcher;
|
||||
|
||||
bubblewrapModuleFactory = { isGlobal ? false }: {
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
description = ''
|
||||
Package containing the specialized Bubblewrap launcher used for this
|
||||
module.
|
||||
'';
|
||||
default = if isGlobal then pkgs.callPackage ./launcher/package.nix { } else cfg.package;
|
||||
};
|
||||
|
||||
integrations = let
|
||||
mkLauncherEnableOption = service: serviceName: lib.mkEnableOption "launcher integration for ${serviceName}" // {
|
||||
default = if isGlobal then true else cfg.integrations.${service}.enable;
|
||||
};
|
||||
in {
|
||||
pipewire.enable = mkLauncherEnableOption "pipewire" "Pipewire";
|
||||
pulseaudio.enable = mkLauncherEnableOption "pulseaudio" "PulseAudio";
|
||||
wayland.enable = mkLauncherEnableOption "wayland" "Wayland desktop sessions";
|
||||
x11.enable = mkLauncherEnableOption "x11" "X11-based desktop sessions";
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options.sandboxing.bubblewrap.launcher = bubblewrapModuleFactory { isGlobal = true; };
|
||||
|
||||
options.wrappers =
|
||||
let
|
||||
bubblewrapLauncherSubmodule = { config, lib, name, ... }: let
|
||||
submoduleCfg = config.sandboxing.bubblewrap.launcher;
|
||||
envSuffix = word: "WRAPPER_MANAGER_BWRAP_LAUNCHER_${word}";
|
||||
in {
|
||||
options.sandboxing.bubblewrap.launcher = bubblewrapModuleFactory { isGlobal = false; };
|
||||
|
||||
config = lib.mkIf (config.sandboxing.variant == "bubblewrap") (lib.mkMerge [
|
||||
{
|
||||
arg0 = lib.getExe' submoduleCfg.package "wrapper-manager-bubblewrap-launcher";
|
||||
prependArgs = lib.mkBefore
|
||||
(config.sandboxing.bubblewrap.extraArgs
|
||||
++ [ "--" config.sandboxing.wraparound.arg0 ]
|
||||
++ config.sandboxing.wraparound.extraArgs);
|
||||
env = {
|
||||
"${envSuffix "BWRAP"}".value = lib.getExe' config.sandboxing.bubblewrap.package "bwrap";
|
||||
# We're just unsetting autoconfigure since we're configuring this
|
||||
# through the module system anyways and would allow the user to
|
||||
# have some more control over what can be enabled.
|
||||
"${envSuffix "AUTOCONFIGURE"}".value = "";
|
||||
};
|
||||
}
|
||||
|
||||
(lib.mkIf config.sandboxing.bubblewrap.dbus.enable {
|
||||
env.${envSuffix "DBUS_PROXY"}.value = lib.getExe' config.sandboxing.bubblewrap.dbus.filter.package "xdg-dbus-proxy";
|
||||
env.${envSuffix "DBUS_PROXY_ARGS"}.value = lib.concatStringsSep " " config.sandboxing.bubblewrap.dbus.filter.extraArgs;
|
||||
})
|
||||
|
||||
(lib.mkIf submoduleCfg.integrations.pulseaudio.enable {
|
||||
env.${envSuffix "PULSEAUDIO"}.value = "1";
|
||||
})
|
||||
|
||||
(lib.mkIf submoduleCfg.integrations.pipewire.enable {
|
||||
env.${envSuffix "PIPEWIRE"}.value = "1";
|
||||
})
|
||||
|
||||
(lib.mkIf submoduleCfg.integrations.x11.enable {
|
||||
env.${envSuffix "X11"}.value = "1";
|
||||
})
|
||||
|
||||
(lib.mkIf submoduleCfg.integrations.wayland.enable {
|
||||
env.${envSuffix "WAYLAND"}.value = "1";
|
||||
})
|
||||
]);
|
||||
};
|
||||
in
|
||||
lib.mkOption {
|
||||
type = with lib.types; attrsOf (submodule bubblewrapLauncherSubmodule);
|
||||
};
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2024 Gabriel Arazas <foodogsquared@foodogsquared.one>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# A specialized launcher intended to handle a bunch of things in runtime such
|
||||
# as adding flags when in certain systems and running xdg-dbus-proxy if
|
||||
# required. Take note, we don't enforce any security model whatsoever, it's
|
||||
# just a launcher that adds `bwrap` arguments in runtime for certain
|
||||
# situations.
|
||||
#
|
||||
# Take note, we have the following design constraints for this launcher:
|
||||
#
|
||||
# * Using only the nixpkgs runtime shell and a few common dependencies found on
|
||||
# Unix-adjacent systems.
|
||||
# * No additional command-line options which means no flags and command-line
|
||||
# parsing. This is essentially just a Bubblewrap wrapper.
|
||||
# * If we ever let the user configure things, it should be done with
|
||||
# environment variables with `WRAPPER_MANAGER_BWRAP_LAUNCHER` prefix. It's very
|
||||
# long but who cares.
|
||||
# * Ideally, there should be no options to clear the environment in this
|
||||
# launcher. Let the user do it themselves if they want.
|
||||
|
||||
declare -a additional_flags
|
||||
: "${XDG_RUNTIME_DIR:="/run/user/$(id -u)"}"
|
||||
: "${WRAPPER_MANAGER_BWRAP_LAUNCHER_BWRAP:="bwrap"}"
|
||||
: "${WRAPPER_MANAGER_BWRAP_LAUNCHER_DBUS_PROXY:="xdg-dbus-proxy"}"
|
||||
: "${WRAPPER_MANAGER_BWRAP_LAUNCHER_AUTOCONFIGURE:="1"}"
|
||||
|
||||
is_autoconfigured_or() {
|
||||
local service="$1"
|
||||
[ "${WRAPPER_MANAGER_BWRAP_LAUNCHER_AUTOCONFIGURE}" = "1" ] || [ "${service}" = "1" ]
|
||||
}
|
||||
|
||||
# Bubblewrap is aggressively Linux-exclusive so we can add some things in here
|
||||
# that are surely common within most Linux distros but just in case...
|
||||
case "$(uname)" in
|
||||
Linux*)
|
||||
additional_flags+=(--proc /proc)
|
||||
additional_flags+=(--dev /dev)
|
||||
additional_flags+=(--dev-bind /dev/dri /dev/dri)
|
||||
additional_flags+=(--tmpfs /tmp)
|
||||
additional_flags+=(--ro-bind /sys/dev/char)
|
||||
additional_flags+=(--ro-bind /sys/devices/pci0000:00)
|
||||
|
||||
# Check if we're in a NixOS system.
|
||||
if [[ -f /etc/NIXOS ]]; then
|
||||
additional_flags+=(--ro-bind /run/opengl-driver/ /run/opengl-driver/)
|
||||
|
||||
if [[ -d /run/opengl-driver-32 ]]; then
|
||||
additional_flags+=(--ro-bind /run/opengl-driver-32 /run/opengl-driver-32/)
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# TODO: Much of the flags added here are so far just cargo-culted lmao.
|
||||
# Investigate it pls for the love of God.
|
||||
|
||||
# Bind Wayland if it's detected to be running on one.
|
||||
if is_autoconfigured_or "${WRAPPER_MANAGER_BWRAP_LAUNCHER_WAYLAND}" && [ -S "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" ]; then
|
||||
additional_flags+=(--ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}")
|
||||
fi
|
||||
|
||||
# Bind Pipewire if it's detected.
|
||||
if is_autoconfigured_or "${WRAPPER_MANAGER_BWRAP_LAUNCHER_PIPEWIRE}" && [ -S "${XDG_RUNTIME_DIR}/pipewire-0" ]; then
|
||||
additional_flags+=(--ro-bind "${XDG_RUNTIME_DIR}/pipewire-0")
|
||||
fi
|
||||
|
||||
# Bind PulseAudio if it's detected and configured.
|
||||
if is_autoconfigured_or "${WRAPPER_MANAGER_BWRAP_LAUNCHER_PULSEAUDIO}" && [ -e "${XDG_RUNTIME_DIR}/pulse/pid" ]; then
|
||||
additional_flags+=(--ro-bind "${XDG_RUNTIME_DIR}/pulse")
|
||||
fi
|
||||
|
||||
# Bind X11 thingies if it's configured and detected.
|
||||
if is_autoconfigured_or "${WRAPPER_MANAGER_BWRAP_LAUNCHER_X11}" && [ "${XAUTHORITY}" ]; then
|
||||
additional_flags+=(--ro-bind "${XAUTHORITY}")
|
||||
additional_flags+=(--ro-bind "/tmp/.X11-unix")
|
||||
fi
|
||||
|
||||
# Fork the D-Bus proxy in case it is needed. We only need to know if its needed
|
||||
# if the *DBUS_PROXY_ARGS envvar is set.
|
||||
if [ -n "${WRAPPER_MANAGER_BWRAP_LAUNCHER_DBUS_PROXY_ARGS}" ]; then
|
||||
(
|
||||
${WRAPPER_MANAGER_BWRAP_LAUNCHER_BWRAP} "${additional_flags[@]}" \
|
||||
-- "${WRAPPER_MANAGER_BWRAP_LAUNCHER_DBUS_PROXY}" "${WRAPPER_MANAGER_BWRAP_LAUNCHER_DBUS_PROXY_ARGS[@]}"
|
||||
) &
|
||||
fi
|
||||
|
||||
exec ${WRAPPER_MANAGER_BWRAP_LAUNCHER_BWRAP} "${additional_flags[@]}" "$@"
|
@ -0,0 +1,13 @@
|
||||
project('wrapper-manager-bubblewrap-launcher',
|
||||
version: '0.1.0',
|
||||
license: 'MIT',
|
||||
meson_version: '>=0.54.0',
|
||||
)
|
||||
|
||||
configure_file(
|
||||
input: 'app.sh',
|
||||
output: meson.project_name(),
|
||||
install_dir: get_option('bindir'),
|
||||
install_mode: 'rwxr-xr-x',
|
||||
install: true
|
||||
)
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
stdenv,
|
||||
lib,
|
||||
meson,
|
||||
ninja
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "wrapper-manager-bubblewrap-launcher";
|
||||
version = "0.1.0";
|
||||
|
||||
src = lib.cleanSource ./.;
|
||||
|
||||
nativeBuildInputs = [ meson ninja ];
|
||||
|
||||
meta = {
|
||||
description = "wrapper-manager specialized launcher for Bubblewrap environments";
|
||||
license = lib.licenses.mit;
|
||||
mainProgram = finalAttrs.pname;
|
||||
};
|
||||
})
|
Loading…
Reference in New Issue
Block a user