Bubblewrap/Examples: Difference between revisions

From Alpine Linux
(imv example)
m (mpv[-net] set title, showing you are using bwrap)
Line 3: Line 3:
{{Todo|Since bubblewrap can make use of [https://en.wikipedia.org/wiki/Seccomp seccomp], restrictive versions should be added.}}
{{Todo|Since bubblewrap can make use of [https://en.wikipedia.org/wiki/Seccomp seccomp], restrictive versions should be added.}}


{{Note|To try and avoid duplicates, everything will be explained for [[Firefox]] and only when it differs (non obviously) for everything else.  Where applicable this assumes: [[Wayland]] only + [[PipeWire]].}}
{{Note|This page assumes you have already read over [[Bubblewrap]].  To try and avoid duplicates, everything will be explained for [[Firefox]] and only when it differs (non obviously) for everything else.  Where applicable this also assumes: [[Wayland]] only + [[PipeWire]].}}


{{Note|{{Ic|imv}}, {{Ic|mpv}} and {{Ic|zathura}} currently only accept 1 (mandatory, except {{Ic|imv}}) argument.  This should (hopefully) be temporary, until I figure out how to pass multiple arguments (without including everything else).}}
{{Note|{{Ic|imv}}, {{Ic|mpv}} and {{Ic|zathura}} currently only accept 1 (mandatory, except {{Ic|imv}}) argument.  This should (hopefully) be temporary, until I figure out how to pass multiple arguments (without including everything else).}}
Line 412: Line 412:
   /usr/bin/mpv \
   /usr/bin/mpv \
     --player-operation-mode{{=}}pseudo-gui \
     --player-operation-mode{{=}}pseudo-gui \
    --title{{=}}'bwrap {{!}} ${media-title}' \
     "$1"}}
     "$1"}}


Line 423: Line 424:


{{Tip|If you followed [[Bubblewrap#.desktop_integration]], you should remove it from {{Path|"${XDG_DATA_HOME}/applications/bwrap-mpv.desktop"}}.}}
{{Tip|If you followed [[Bubblewrap#.desktop_integration]], you should remove it from {{Path|"${XDG_DATA_HOME}/applications/bwrap-mpv.desktop"}}.}}
--title='bwrap | ${media-title}' \
Set the window title, showing at a glance that you are using {{Ic|bwrap}}.


=== mpv-net ===
=== mpv-net ===
Line 485: Line 489:
   /usr/bin/mpv \
   /usr/bin/mpv \
     --player-operation-mode{{=}}pseudo-gui \
     --player-operation-mode{{=}}pseudo-gui \
    --title{{=}}'bwrap {{!}} ${media-title}' \
     "$@"}}
     "$@"}}



Revision as of 22:57, 6 August 2023

This material is work-in-progress ...

Someone more experienced needs to look over this. I'm not sure it's worth the time to limit /usr/lib/*.
(Last edited by Encode on 6 Aug 2023.)

Todo: Since bubblewrap can make use of seccomp, restrictive versions should be added.


Note: This page assumes you have already read over Bubblewrap. To try and avoid duplicates, everything will be explained for Firefox and only when it differs (non obviously) for everything else. Where applicable this also assumes: Wayland only + PipeWire.
Note: imv, mpv and zathura currently only accept 1 (mandatory, except imv) argument. This should (hopefully) be temporary, until I figure out how to pass multiple arguments (without including everything else).

Firefox

Contents of ~/.local/bin/bwrap-firefox

#!/usr/bin/env sh # Firefox wrapped in bwrap with network access. set -u XDG_CACHE_HOME="${XDG_CACHE_HOME:=$HOME/.cache}" XDG_DATA_HOME="${XDG_DATA_HOME:=$HOME/.local/share}" NEW_HOME='/home/user' NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}" mkdir -pm 0700 "${XDG_DATA_HOME}/firefox/" /usr/bin/bwrap \ --unshare-all \ --share-net \ --new-session \ --die-with-parent \ --clearenv \ --setenv HOME "$NEW_HOME" \ --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \ --setenv XDG_CACHE_HOME "$NEW_XDG_CACHE_HOME" \ --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \ --hostname localhost \ --dev /dev/ \ --ro-bind /etc/fonts/ /etc/fonts/ \ --ro-bind /etc/resolv.conf /etc/resolv.conf \ --bind-try "${XDG_CACHE_HOME}/mozilla/" "${NEW_XDG_CACHE_HOME}/mozilla/" \ --bind "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \ --bind-try "${HOME}/Downloads/" "${NEW_HOME}/Downloads/" \ --ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 \ --ro-bind /lib/libblkid.so.1 /lib/libblkid.so.1 \ --ro-bind /lib/libmount.so.1 /lib/libmount.so.1 \ --ro-bind /lib/libz.so.1 /lib/libz.so.1 \ --proc /proc/ \ --ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \ --ro-bind /usr/lib/ /usr/lib/ \ --ro-bind /usr/share/X11/xkb/ /usr/share/X11/xkb/ \ --ro-bind /usr/share/fontconfig/ /usr/share/fontconfig/ \ --ro-bind /usr/share/fonts/ /usr/share/fonts/ \ --ro-bind /usr/share/glib-2.0/ /usr/share/glib-2.0/ \ --ro-bind /usr/share/icons/ /usr/share/icons/ \ --ro-bind /usr/share/icu/ /usr/share/icu/ \ --ro-bind /usr/share/mime/ /usr/share/mime/ \ /usr/lib/firefox/firefox
XDG_CACHE_HOME="${XDG_CACHE_HOME:=$HOME/.cache}"
XDG_DATA_HOME="${XDG_DATA_HOME:=$HOME/.local/share}"

Take value if already set, else fallback to the XDG default.

NEW_HOME='/home/user'

User to appear as.

NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}"

$XDG_CACHE_HOME for the new user.

mkdir -pm 0700 "${XDG_DATA_HOME}/firefox/"

Make sure the new (real) home for Firefox data exist.

--unshare-all \

Unshare all possible namespaces.

--share-net \

Retain the network namespace.

--new-session \

New terminal session for the sandbox.

--die-with-parent \

Child process dies when bwrap parent dies.

--clearenv \

Unset all environment variables (except for "$PWD").

--setenv HOME "$NEW_HOME" \

Pass the path to "$NEW_HOME" for "$HOME".

--setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \

Specify the Wayland display to run clients on.

--setenv XDG_CACHE_HOME "$NEW_XDG_CACHE_HOME" \

User-specific non-essential (cached) data.

--setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \

User-specific non-essential runtime files and other file objects.

--hostname localhost \

Use custom hostname in the sandbox.

--dev /dev/ \

New devtmpfs, access to special or device files.

--ro-bind /etc/fonts/ /etc/fonts/ \

System font configuration directory.

--ro-bind /etc/resolv.conf /etc/resolv.conf \

Needed for DNS resolution.

--bind-try "${XDG_CACHE_HOME}/mozilla/" "${NEW_XDG_CACHE_HOME}/mozilla/" \

Per-user Mozilla cache.

...
XDG_CACHE_HOME="${XDG_CACHE_HOME:=$HOME/.cache}"
XDG_CONFIG_HOME "${XDG_CONFIG_HOME:=$HOME/.config}"
XDG_DATA_HOME="${XDG_DATA_HOME:=$HOME/.local/share}"
...
NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}"
NEW_XDG_CONFIG_HOME="${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}"
...
--setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
--setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \
--setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
...
--bind-try "${XDG_CACHE_HOME}/mozilla/" "${NEW_XDG_CACHE_HOME}/mozilla/" \
--ro-bind-try "${XDG_CONFIG_HOME}/fontconfig/" "${NEW_XDG_CONFIG_HOME}/fontconfig/" \
--bind "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \
...

(Optional) Per-user font configuration directory.

...
XDG_CACHE_HOME="${XDG_CACHE_HOME:=$HOME/.cache}"
XDG_CONFIG_HOME "${XDG_CONFIG_HOME:=$HOME/.config}"
XDG_DATA_HOME="${XDG_DATA_HOME:=$HOME/.local/share}"
...
NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}"
NEW_XDG_CONFIG_HOME="${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}"
...
--setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
--setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \
--setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
...
--bind-try "${XDG_CACHE_HOME}/mozilla/" "${XDG_CACHE_HOME}/mozilla/" \
--ro-bind-try "${XDG_CONFIG_HOME}/user-dirs.dirs" "${NEW_XDG_CONFIG_HOME}/user-dirs.dirs" \
--bind "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \
...

(Optional) If you modify "well known" user directories, like ~/Downloads/, you need this to have Firefox pick it up.

Note: If you use "${XDG_CONFIG_HOME}/user-dirs.dirs" you should also add the corresponding path(s).

For example if you set XDG_DOWNLOAD_DIR to "${HOME}/downloads/" you would also add:

 ...
 --bind "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \
 --bind-try "${HOME}/downloads/" "${NEW_HOME}/downloads/" \
 --ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 \
 ...
--bind "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \

"${XDG_DATA_HOME}/firefox/" is the location of Firefox data. Shown to Firefox as "${NEW_HOME}/.mozilla/".

Note: This has the added benefit of getting ~/.mozilla/ out of your "$HOME", and conforming more to XDG. This may one day not be necessary: Support for the Freedesktop.org XDG Base Directory Specification (2004-09-14).
...
NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}"
NEW_XDG_DATA_HOME="${NEW_HOME}${XDG_DATA_HOME#"$HOME"}"
...
--setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
--setenv XDG_DATA_HOME "$NEW_XDG_DATA_HOME" \
--setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
...
--bind "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \
--ro-bind-try "${XDG_DATA_HOME}/fonts/" "${NEW_XDG_DATA_HOME}/fonts/" \
--bind-try "${HOME}/Downloads/" "${NEW_HOME}/Downloads/" \
...

(Optional) Per-user directory scanned for font files.

--bind-try "${HOME}/Downloads/" "${NEW_HOME}/Downloads/" \

Default ~/Downloads/ directory.

--ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 \
--ro-bind /lib/libblkid.so.1 /lib/libblkid.so.1 \
--ro-bind /lib/libmount.so.1 /lib/libmount.so.1 \
--ro-bind /lib/libz.so.1 /lib/libz.so.1 \

Shared libraries.

--proc /proc/ \

New procfs, provides information about running processes and the kernel.

--ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \

Bind the Wayland socket file.

--ro-bind /usr/lib/ /usr/lib/ \

Object files and libraries.

--ro-bind /usr/share/X11/xkb/ /usr/share/X11/xkb/ \

XKB is a keyboard keymap support library.

Note: Even tho the path has */X11/* Wayland uses it too.
--ro-bind /usr/share/fontconfig/ /usr/share/fontconfig/ \

Font presets.

--ro-bind /usr/share/fonts/ /usr/share/fonts/ \

Global directory scanned for font files.

--ro-bind /usr/share/glib-2.0/ /usr/share/glib-2.0/ \

Needed for "Save Page As…", "Export|Import Bookmarks File", among others.

--ro-bind /usr/share/icons/ /usr/share/icons/ \

Global icons directory.

--ro-bind /usr/share/icu/ /usr/share/icu/ \

International Components for Unicode (ICU) provides support for Unicode and globalization.

...
--ro-bind /usr/share/icu/ /usr/share/icu/ \
--ro-bind /usr/share/libdrm/ /usr/share/libdrm/ \
--ro-bind /usr/share/mime/ /usr/share/mime/ \
...

(Optional) Direct Rendering Manager (DRM), Linux kernel subsystem for interfacing with GPUs of video cards. Programs can use this to have the GPU do hardware-accelerated 3D rendering and video decoding.

--ro-bind /usr/share/mime/ /usr/share/mime/ \

Global XDG MIME directory.

/usr/lib/firefox/firefox

Call Firefox.

Tip: If you use multiple profiles you can have:
/usr/lib/firefox/firefox -P "$@"
this will allow you to pass a profile name and go into that specific one or not pass anything and get prompted for which to choose.

PipeWire audio

Todo:


Pulse audio

...
--proc /proc/ \
--ro-bind "${XDG_RUNTIME_DIR}/pulse/" "${XDG_RUNTIME_DIR}/pulse/" \
--ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \
...

(Optional) Pulse audio.

Optional(?) stuff

This material is work-in-progress ...

Are these needed?
(Last edited by Encode on 6 Aug 2023.)

...
--proc /proc/ \
--ro-bind /sys/bus/pci/ /sys/bus/pci/ \
--ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \
...

Information about PCI bus type.

Without this you get

Crash Annotation GraphicsCriticalError: |[0][GFX1-]: glxtest: cannot access /sys/bus/pci (t=0.177033) [GFX1-]: glxtest: cannot access /sys/bus/pci

but it still seems to work.

...
--proc /proc/ \
--ro-bind /sys/devices/pci0000:00/ /sys/devices/pci0000:00/ \
--ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \
...

Contains a filesystem representation of the kernel device tree.

With --ro-bind /sys/bus/pci/ /sys/bus/pci/ \ but without this you get:

Crash Annotation GraphicsCriticalError: |[0][GFX1-]: glxtest: ManageChildProcess failed
 (t=0.189558) [GFX1-]: glxtest: ManageChildProcess failed
Crash Annotation GraphicsCriticalError: |[0][GFX1-]: glxtest: ManageChildProcess failed
 (t=0.189558) |[1][GFX1-]: No GPUs detected via PCI
 (t=0.18958) [GFX1-]: No GPUs detected via PCI

but it still seems to work.

imv

Contents of ~/.local/bin/bwrap-imv

#!/usr/bin/env sh # imv wrapped in bwrap. set -u XDG_CONFIG_HOME="${XDG_CONFIG_HOME:=$HOME/.config}" /usr/bin/bwrap \ --unshare-all \ --new-session \ --die-with-parent \ --clearenv \ --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \ --setenv XDG_CONFIG_HOME "$XDG_CONFIG_HOME" \ --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \ --ro-bind /bin/sh /bin/sh \ --dev-bind /dev/dri/renderD128 /dev/dri/renderD128 \ --ro-bind-try "${XDG_CONFIG_HOME}/imv/config" "${XDG_CONFIG_HOME}/imv/config" \ --ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 \ --ro-bind /lib/libblkid.so.1 /lib/libblkid.so.1 \ --ro-bind /lib/libmount.so.1 /lib/libmount.so.1 \ --ro-bind /lib/libz.so.1 /lib/libz.so.1 \ --ro-bind /sys/dev/char/ /sys/dev/char/ \ --ro-bind /sys/devices/pci0000:00/ /sys/devices/pci0000:00/ \ --ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \ --ro-bind /usr/lib/ /usr/lib/ \ --ro-bind /usr/libexec/imv-wayland /usr/libexec/imv-wayland \ --ro-bind /usr/share/X11/xkb/ /usr/share/X11/xkb/ \ --ro-bind "${1:-./}" "$(realpath "${1:-./}")" \ /usr/libexec/imv-wayland "${1:-./}"
Tip: If you have "${XDG_CONFIG_HOME}/imv/config" as a symbolic link, you will also need to --ro-bind the source.
--ro-bind /bin/sh /bin/sh \

(Technically optional?) Needed to have the name of the file in the window title.

...
XDG_CACHE_HOME="${XDG_CACHE_HOME:=$HOME/.cache}"
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:=$HOME/.config}"
XDG_DATA_HOME="${XDG_DATA_HOME:=$HOME/.local/share}"
...
--setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
--setenv XDG_CACHE_HOME "$XDG_CACHE_HOME" \
--setenv XDG_CONFIG_HOME "$XDG_CONFIG_HOME" \
--setenv XDG_DATA_HOME "$XDG_DATA_HOME" \
--setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
...
--dev-bind /dev/dri/renderD128 /dev/dri/renderD128 \
--ro-bind /etc/fonts/ /etc/fonts/ \
--bind-try "${XDG_CACHE_HOME}/fontconfig/" "${XDG_CACHE_HOME}/fontconfig/" \
--ro-bind-try "${XDG_CONFIG_HOME}/fontconfig/" "${XDG_CONFIG_HOME}/fontconfig/" \
--ro-bind-try "${XDG_CONFIG_HOME}/imv/config" "${XDG_CONFIG_HOME}/imv/config" \
--ro-bind-try "${XDG_DATA_HOME}/fonts/" "${XDG_DATA_HOME}/fonts/" \
--ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 \
...
--ro-bind /usr/share/X11/xkb/ /usr/share/X11/xkb/ \
--ro-bind /usr/share/fonts/ /usr/share/fonts/ \
--ro-bind /usr/share/icu/ /usr/share/icu/ \
--ro-bind "${1:-./}" "$(realpath "${1:-./}")" \
...

(Optional) To use commands in imv.

--ro-bind "${1:-./}" "$(realpath "${1:-./}")" \

Get the absolute pathname using realpath, so you can pass a relative argument and still bind the argument. If you don't pass in anything it will default to ./, the current directory.

Warning: If you don't pass anything and it defaults to the current directory, it will have everything under that directory shown to imv, recursively.


mpv

Contents of ~/.local/bin/bwrap-mpv

#!/usr/bin/env sh # mpv wrapped in bwrap. set -u if [ "$#" != 1 ] then printf 'Run mpv wrapped in bwrap. Usage: $ bwrap-mpv VIDEO\n' exit 1 fi XDG_CACHE_HOME="${XDG_CACHE_HOME:=$HOME/.cache}" XDG_CONFIG_HOME="${XDG_CONFIG_HOME:=$HOME/.config}" NEW_HOME='/home/user' NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}" NEW_XDG_CONFIG_HOME="${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}" /usr/bin/bwrap \ --unshare-all \ --new-session \ --die-with-parent \ --clearenv \ --setenv HOME "$NEW_HOME" \ --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \ --setenv XDG_CACHE_HOME "$NEW_XDG_CACHE_HOME" \ --setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \ --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \ --hostname localhost \ --dev-bind /dev/dri/renderD128 /dev/dri/renderD128 \ --ro-bind /etc/fonts/ /etc/fonts/ \ --ro-bind /etc/mpv/ /etc/mpv/ \ --bind-try "${XDG_CACHE_HOME}/mesa_shader_cache/" "${NEW_XDG_CACHE_HOME}/mesa_shader_cache/" \ --ro-bind-try "${XDG_CONFIG_HOME}/mpv/mpv.conf" "${NEW_XDG_CONFIG_HOME}/mpv/mpv.conf" \ --ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 \ --ro-bind /lib/libacl.so.1 /lib/libacl.so.1 \ --ro-bind /lib/libcrypto.so.3 /lib/libcrypto.so.3 \ --ro-bind /lib/libssl.so.3 /lib/libssl.so.3 \ --ro-bind /lib/libz.so.1 /lib/libz.so.1 \ --proc /proc/ \ --ro-bind /sys/dev/char/ /sys/dev/char/ \ --ro-bind /sys/devices/pci0000:00/ /sys/devices/pci0000:00/ \ --ro-bind "${XDG_RUNTIME_DIR}/pipewire-0" "${XDG_RUNTIME_DIR}/pipewire-0" \ --ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \ --ro-bind /usr/bin/mpv /usr/bin/mpv \ --ro-bind /usr/lib/ /usr/lib/ \ --ro-bind /usr/share/X11/xkb/ /usr/share/X11/xkb/ \ --ro-bind /usr/share/fontconfig/ /usr/share/fontconfig/ \ --ro-bind /usr/share/fonts/ /usr/share/fonts/ \ --ro-bind /usr/share/pipewire/ /usr/share/pipewire/ \ --ro-bind "$1" "$(realpath "$1")" \ /usr/bin/mpv \ --player-operation-mode=pseudo-gui \ --title='bwrap | ${media-title}' \ "$1"
--ro-bind "$1" "$(realpath "$1")" \

Get the absolute pathname using realpath, so you can pass a relative argument and still bind the argument.

--player-operation-mode=pseudo-gui \

Because --new-session is used, this is needed to have a way to control mpv when it would otherwise not show a GUI.

Tip: If you followed Bubblewrap#.desktop_integration, you should remove it from "${XDG_DATA_HOME}/applications/bwrap-mpv.desktop".
--title='bwrap | ${media-title}' \

Set the window title, showing at a glance that you are using bwrap.

mpv-net

If you want to use mpv to stream over the Internet, you will need a few things more.

Tip: You can use both bwrap-mpv and bwrap-mpv-net. bwrap-mpv for local stuff and bwrap-mpv-net for watching over the Internet.

Contents of ~/.local/bin/bwrap-mpv-net

#!/usr/bin/env sh # mpv wrapped in bwrap with network access. set -u XDG_CACHE_HOME="${XDG_CACHE_HOME:=$HOME/.cache}" XDG_CONFIG_HOME="${XDG_CONFIG_HOME:=$HOME/.config}" NEW_HOME='/home/user' NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}" NEW_XDG_CONFIG_HOME="${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}" /usr/bin/bwrap \ --unshare-all \ --share-net \ --new-session \ --die-with-parent \ --clearenv \ --setenv HOME "$NEW_HOME" \ --setenv PATH /usr/bin/ \ --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \ --setenv XDG_CACHE_HOME "$NEW_XDG_CACHE_HOME" \ --setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \ --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \ --hostname localhost \ --dev /dev/ \ --dev-bind /dev/dri/renderD128 /dev/dri/renderD128 \ --ro-bind /etc/fonts/ /etc/fonts/ \ --ro-bind /etc/mpv/ /etc/mpv/ \ --ro-bind /etc/resolv.conf /etc/resolv.conf \ --ro-bind /etc/ssl/certs/ /etc/ssl/certs/ \ --bind-try "${XDG_CACHE_HOME}/mesa_shader_cache/" "${NEW_XDG_CACHE_HOME}/mesa_shader_cache/" \ --ro-bind-try "${XDG_CONFIG_HOME}/mpv/mpv.conf" "${NEW_XDG_CONFIG_HOME}/mpv/mpv.conf" \ --ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 \ --ro-bind /lib/libacl.so.1 /lib/libacl.so.1 \ --ro-bind /lib/libcrypto.so.3 /lib/libcrypto.so.3 \ --ro-bind /lib/libssl.so.3 /lib/libssl.so.3 \ --ro-bind /lib/libz.so.1 /lib/libz.so.1 \ --proc /proc/ \ --ro-bind /sys/dev/char/ /sys/dev/char/ \ --ro-bind /sys/devices/pci0000:00/ /sys/devices/pci0000:00/ \ --ro-bind "${XDG_RUNTIME_DIR}/pipewire-0" "${XDG_RUNTIME_DIR}/pipewire-0" \ --ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \ --ro-bind /usr/bin/mpv /usr/bin/mpv \ --ro-bind /usr/bin/python3 /usr/bin/python3 \ --ro-bind /usr/bin/yt-dlp /usr/bin/yt-dlp \ --ro-bind /usr/lib/ /usr/lib/ \ --ro-bind /usr/share/X11/xkb/ /usr/share/X11/xkb/ \ --ro-bind /usr/share/fontconfig/ /usr/share/fontconfig/ \ --ro-bind /usr/share/fonts/ /usr/share/fonts/ \ --ro-bind /usr/share/pipewire/ /usr/share/pipewire/ \ /usr/bin/mpv \ --player-operation-mode=pseudo-gui \ --title='bwrap | ${media-title}' \ "$@"
--setenv PATH /usr/bin/ \
Todo: Document why this is needed.


--ro-bind /etc/ssl/certs/ /etc/ssl/certs/ \

Certificate authorities that are trusted.

"$@"

This is so you can pass more options to mpv, for example:

$ bwrap-mpv-net --video=no --sub=no 'URL1' 'URL2'

Pulse audio

--ro-bind "${XDG_RUNTIME_DIR}/pulse" "${XDG_RUNTIME_DIR}/pulse" \

Pulse audio.

Screenshots

The default screenshots directory is "$XDG_DESKTOP_DIR" (which is "${HOME}/Desktop", which will fallback to "$HOME/" if "${HOME}/Desktop" doesn't exist). That means that by default bwrap-mpv[-net] won't allow screenshots unless you change a few things. Do the following to allow an XDG approved screenshots directory:

...
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:=$HOME/.config}"
XDG_DATA_HOME="${XDG_DATA_HOME:=$HOME/.local/share}"
...
NEW_XDG_CONFIG_HOME="${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}"
NEW_XDG_DATA_HOME="${NEW_HOME}${XDG_DATA_HOME#"$HOME"}"

mkdir -pm 0700 "${XDG_DATA_HOME}/mpv/"
...
--setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \
--setenv XDG_DATA_HOME "$NEW_XDG_DATA_HOME" \
--setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
...
--ro-bind-try "${XDG_CONFIG_HOME}/mpv/mpv.conf" "${NEW_XDG_CONFIG_HOME}/mpv/mpv.conf" \
--bind "${XDG_DATA_HOME}/mpv/" "${NEW_XDG_DATA_HOME}/mpv/" \
--ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 \
...

Now make mpv use that directory:

Contents of "${XDG_CONFIG_HOME}/mpv/mpv.conf"

... # Something like this, change to match "$XDG_DATA_HOME" screenshot-template="~/.local/share/mpv/screenshots/%F [%p] %02n" ...

zathura

Contents of ~/.local/bin/bwrap-zathura

#!/usr/bin/env sh # zathura wrapped in bwrap. set -u if [ "$#" != 1 ] then printf 'Run zathura wrapped in bwrap. Usage: $ bwrap-zathura PDF\n' exit 1 fi XDG_CONFIG_HOME="${XDG_CONFIG_HOME:=$HOME/.config}" XDG_DATA_HOME="${XDG_DATA_HOME:=$HOME/.local/share}" mkdir -pm 0700 "${XDG_DATA_HOME}/zathura/" /usr/bin/bwrap \ --unshare-all \ --new-session \ --die-with-parent \ --clearenv \ --setenv HOME "$HOME" \ --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \ --setenv XDG_CONFIG_HOME "$XDG_CONFIG_HOME" \ --setenv XDG_DATA_HOME "$XDG_DATA_HOME" \ --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \ --ro-bind /etc/fonts/ /etc/fonts/ \ --ro-bind-try "${XDG_CONFIG_HOME}/zathura/zathurarc" "${XDG_CONFIG_HOME}/zathura/zathurarc" \ --bind "${XDG_DATA_HOME}/zathura/" "${XDG_DATA_HOME}/zathura/" \ --ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 \ --ro-bind /lib/libblkid.so.1 /lib/libblkid.so.1 \ --ro-bind /lib/libmount.so.1 /lib/libmount.so.1 \ --ro-bind /lib/libz.so.1 /lib/libz.so.1 \ --ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \ --ro-bind /usr/bin/zathura /usr/bin/zathura \ --ro-bind /usr/lib/ /usr/lib/ \ --ro-bind /usr/share/X11/xkb/ /usr/share/X11/xkb/ \ --ro-bind /usr/share/fonts/ /usr/share/fonts/ \ --ro-bind /usr/share/misc/magic.mgc /usr/share/misc/magic.mgc \ --ro-bind "$1" "$(realpath "$1")" \ /usr/bin/zathura "$1"
mkdir -pm 0700 "${XDG_DATA_HOME}/zathura/"

Have to premake the directory for zathura data.

--bind "${XDG_DATA_HOME}/zathura/" "${XDG_DATA_HOME}/zathura/" \

Allow writing of: bookmarks, history, input history.

--ro-bind /usr/share/misc/magic.mgc /usr/share/misc/magic.mgc \

Used for identifying what type a file should be. Read the file(1) man page for more information.

--ro-bind "$1" "$(realpath "$1")" \

Get the absolute pathname using realpath, so you can pass a relative argument and still bind the argument.