Bubblewrap/Examples
This material is work-in-progress ... Someone more experienced needs to look over this. |
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
set -u
If the shell tries to expand an unset parameter, it will error (with a few exceptions).
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.
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/".
... 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.
--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.
/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
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? |
... --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
--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.
imv
, recursively.
mpv
Contents of ~/.local/bin/bwrap-mpv
--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.
--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.
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
--setenv PATH /usr/bin/ \
--ro-bind /etc/ssl/certs/ /etc/ssl/certs/ \
Certificate authorities that are trusted.
"$@"
This is so you can pass more options to bwrap-mpv-net
, 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"
yt-dlp
Contents of ~/.local/bin/bwrap-yt-dlp
--bind "${HOME}/Downloads/" "${NEW_HOME}/Downloads/" \
Directory for writing the files. This should match --output
that
is either in "${XDG_CONFIG_HOME}/yt-dlp/config" or passed on
the command line.
/usr/bin/yt-dlp "$@"
This is so you can pass more options to bwrap-yt-dlp
, for example:
$ bwrap-yt-dlp --no-playlist 'URL1' 'URL2'
zathura
Contents of ~/.local/bin/bwrap-zathura
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.