Bubblewrap/Examples: Difference between revisions

From Alpine Linux
(Firefox example)
m (More crypto)
 
(17 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{Draft|Someone more experienced needs to look over this.  I'm not sure it's worth the time to limit {{Path|/usr/lib/*}}.}}
{{Draft|Someone more experienced needs to look over this.}}


{{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.  {{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|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]].  If you use Wayland, make sure you have dealt with [[Wayland#XDG_RUNTIME_DIR|XDG_RUNTIME_DIR]].}}


{{TOC right}}
{{TOC right}}
Line 21: Line 21:
NEW_XDG_CACHE_HOME{{=}}"${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}"
NEW_XDG_CACHE_HOME{{=}}"${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}"


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


/usr/bin/bwrap \
/usr/bin/bwrap \
Line 31: Line 31:
   --setenv HOME "$NEW_HOME" \
   --setenv HOME "$NEW_HOME" \
   --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
   --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
  --setenv XDG_CACHE_HOME "$NEW_XDG_CACHE_HOME" \
   --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
   --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
   --hostname localhost \
   --hostname localhost \
   --dev /dev \
   --dev /dev/ \
   --ro-bind /etc/fonts /etc/fonts \
   --ro-bind /etc/fonts/ /etc/fonts/ \
   --ro-bind /etc/resolv.conf /etc/resolv.conf \
   --ro-bind /etc/resolv.conf /etc/resolv.conf \
   --bind-try "${XDG_CACHE_HOME}/mozilla" "${NEW_XDG_CACHE_HOME}/mozilla" \
   --bind-try "${XDG_CACHE_HOME}/mozilla/" "${NEW_XDG_CACHE_HOME}/mozilla/" \
   --bind-try "${XDG_DATA_HOME}/firefox" "${NEW_HOME}/.mozilla" \
   --bind "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \
   --bind-try "${HOME}/Downloads" "${NEW_HOME}/Downloads" \
   --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/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/libblkid.so.1 /lib/libblkid.so.1 \
  --ro-bind /lib/libcrypto.so.3 /lib/libcrypto.so.3 \
   --ro-bind /lib/libmount.so.1 /lib/libmount.so.1 \
   --ro-bind /lib/libmount.so.1 /lib/libmount.so.1 \
   --ro-bind /lib/libz.so.1 /lib/libz.so.1 \
   --ro-bind /lib/libz.so.1 /lib/libz.so.1 \
   --proc /proc \
   --proc /proc/ \
   --ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \
   --ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \
   --ro-bind /usr/lib /usr/lib \
   --ro-bind /usr/lib/ /usr/lib/ \
   --ro-bind /usr/share/X11/xkb /usr/share/X11/xkb \
   --ro-bind /usr/share/X11/xkb/ /usr/share/X11/xkb/ \
   --ro-bind /usr/share/fontconfig /usr/share/fontconfig \
   --ro-bind /usr/share/fontconfig/ /usr/share/fontconfig/ \
   --ro-bind /usr/share/fonts /usr/share/fonts \
   --ro-bind /usr/share/fonts/ /usr/share/fonts/ \
   --ro-bind /usr/share/glib-2.0 /usr/share/glib-2.0 \
   --ro-bind /usr/share/glib-2.0/ /usr/share/glib-2.0/ \
   --ro-bind /usr/share/icons /usr/share/icons \
   --ro-bind /usr/share/icons/ /usr/share/icons/ \
   --ro-bind /usr/share/icu /usr/share/icu \
   --ro-bind /usr/share/icu/ /usr/share/icu/ \
   --ro-bind /usr/share/mime /usr/share/mime \
   --ro-bind /usr/share/mime/ /usr/share/mime/ \
   /usr/lib/firefox/firefox}}
   /usr/lib/firefox/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_CACHE_HOME="${XDG_CACHE_HOME:=$HOME/.cache}"
Line 63: Line 69:


  NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}"
  NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}"
{{Path|$XDG_CACHE_HOME}} for the new user.
{{Path|"$XDG_CACHE_HOME"}} for the new user.


  mkdir -pm 0700 "${XDG_DATA_HOME}/firefox"
  mkdir -pm 0700 "${XDG_DATA_HOME}/firefox/"
Make sure the new (real) home for Firefox data exist.
Make sure the new (real) home for Firefox data exist.


Line 81: Line 87:


  --clearenv \
  --clearenv \
Unset all environment variables (except for PWD).
Unset all environment variables (except for {{Path|"$PWD"}}).


  --setenv HOME "$NEW_HOME" \
  --setenv HOME "$NEW_HOME" \
Line 88: Line 94:
  --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
  --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
Specify the Wayland display to run clients on.
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" \
  --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
User-specific non-essential runtime files and other file objects.
User-specific non-essential runtime files and other file objects.


  --hostname localhost
  --hostname localhost \
Use custom hostname in the sandbox.
Use custom hostname in the sandbox.


  --dev /dev
  --dev /dev/ \
New devtmpfs, access to special or device files.
New devtmpfs, access to special or device files.


  --ro-bind /etc/fonts /etc/fonts \
  --ro-bind /etc/fonts/ /etc/fonts/ \
System font configuration directory.
System font configuration directory.


Line 104: Line 113:
Needed for DNS resolution.
Needed for DNS resolution.


  --bind-try "${XDG_CACHE_HOME}/mozilla" "${NEW_XDG_CACHE_HOME}/mozilla" \
  --bind-try "${XDG_CACHE_HOME}/mozilla/" "${NEW_XDG_CACHE_HOME}/mozilla/" \
Per-user Mozilla cache.
Per-user Mozilla cache.


Line 119: Line 128:
  --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
  --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
  ...
  ...
  --bind-try "${XDG_CACHE_HOME}/mozilla" "${NEW_XDG_CACHE_HOME}/mozilla" \
  --bind-try "${XDG_CACHE_HOME}/mozilla/" "${NEW_XDG_CACHE_HOME}/mozilla/" \
  <b>--ro-bind-try "${XDG_CONFIG_HOME}/fontconfig" "${NEW_XDG_CONFIG_HOME}/fontconfig" \</b>
  <b>--ro-bind-try "${XDG_CONFIG_HOME}/fontconfig/" "${NEW_XDG_CONFIG_HOME}/fontconfig/" \</b>
  --bind-try "${XDG_DATA_HOME}/firefox" "${NEW_HOME}/.mozilla" \
  --bind "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \
  ...
  ...
(Optional) Per-user font configuration directory.
(Optional) Per-user font configuration directory.
Line 137: Line 146:
  --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
  --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
  ...
  ...
  --bind-try "${XDG_CACHE_HOME}/mozilla" "${XDG_CACHE_HOME}/mozilla" \
  --bind-try "${XDG_CACHE_HOME}/mozilla/" "${XDG_CACHE_HOME}/mozilla/" \
  <b>--ro-bind-try "${XDG_CONFIG_HOME}/user-dirs.dirs" "${NEW_XDG_CONFIG_HOME}/user-dirs.dirs" \</b>
  <b>--ro-bind-try "${XDG_CONFIG_HOME}/user-dirs.dirs" "${NEW_XDG_CONFIG_HOME}/user-dirs.dirs" \</b>
  --bind-try "${XDG_DATA_HOME}/firefox" "${NEW_HOME}/.mozilla" \
  --bind "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \
  ...
  ...
(Optional) If you modify "well known" user directories, like
(Optional) If you modify "well known" user directories, like
{{Path|~/Downloads}}, you need this to have Firefox pick it up.
{{Path|~/Downloads/}}, you need this to have Firefox pick it up.


{{Note|If you use {{Path|"${XDG_CONFIG_HOME}/user-dirs.dirs"}} you should also add the corresponding path(s).
{{Note|If you use {{Path|"${XDG_CONFIG_HOME}/user-dirs.dirs"}} you should also add the corresponding path(s).
For example if you set {{Path|XDG_DOWNLOAD_DIR}} to
For example if you set {{Path|XDG_DOWNLOAD_DIR}} to
{{Path|"${HOME}/downloads"}} you would also add:
{{Path|"${HOME}/downloads/"}} you would also add:
   ...
   ...
   --bind-try "${XDG_DATA_HOME}/firefox" "${NEW_HOME}/.mozilla" \
   --bind "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \
   <b>--bind-try "${HOME}/downloads" "${NEW_HOME}/downloads" \</b>
   <b>--bind-try "${HOME}/downloads/" "${NEW_HOME}/downloads/" \</b>
   --ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 \
   --ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 \
   ...
   ...
}}
}}


  --bind-try "${XDG_DATA_HOME}/firefox" "${NEW_HOME}/.mozilla" \
  --bind "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \
{{Path|"${XDG_DATA_HOME}/firefox"}} is the location of Firefox data.  Shows to Firefox as {{Path|"${NEW_HOME}/.mozilla"}}.
{{Path|"${XDG_DATA_HOME}/firefox/"}} is the location of Firefox data.  Shown to Firefox as {{Path|"${NEW_HOME}/.mozilla/"}}.


{{Note|This has the added benefit of getting {{Path|~/.mozilla}} out of your {{Path|$HOME}}, and conforming more to XDG.  This may one day not be necessary: [https://bugzilla.mozilla.org/show_bug.cgi?id{{=}}259356 Support for the Freedesktop.org XDG Base Directory Specification (2004-09-14)].}}
{{Note|This has the added benefit of getting {{Path|~/.mozilla/}} out of your {{Path|"$HOME"}}, and conforming more to XDG.  This may one day not be necessary: [https://bugzilla.mozilla.org/show_bug.cgi?id{{=}}259356 Support for the Freedesktop.org XDG Base Directory Specification (2004-09-14)].}}


  ...
  ...
Line 167: Line 176:
  --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
  --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
  ...
  ...
  --bind-try "${XDG_DATA_HOME}/firefox" "${NEW_HOME}/.mozilla" \
  --bind "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \
  <b>--ro-bind-try "${XDG_DATA_HOME}/fonts" "${NEW_XDG_DATA_HOME}/fonts" \</b>
  <b>--ro-bind-try "${XDG_DATA_HOME}/fonts/" "${NEW_XDG_DATA_HOME}/fonts/" \</b>
  --bind-try "${HOME}/Downloads" "${NEW_HOME}/Downloads" \
  --bind-try "${HOME}/Downloads/" "${NEW_HOME}/Downloads/" \
  ...
  ...
(Optional) Per-user directory scanned for font files.
(Optional) Per-user directory scanned for font files.


  --bind-try "${HOME}/Downloads" "${NEW_HOME}/Downloads" \
  --bind-try "${HOME}/Downloads/" "${NEW_HOME}/Downloads/" \
Default {{Path|~/Downloads}} directory.
Default {{Path|~/Downloads/}} directory.


  --ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 \
  --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/libblkid.so.1 /lib/libblkid.so.1 \
--ro-bind /lib/libcrypto.so.3 /lib/libcrypto.so.3 \
  --ro-bind /lib/libmount.so.1 /lib/libmount.so.1 \
  --ro-bind /lib/libmount.so.1 /lib/libmount.so.1 \
  --ro-bind /lib/libz.so.1 /lib/libz.so.1 \
  --ro-bind /lib/libz.so.1 /lib/libz.so.1 \
Shared libraries.
Shared libraries.


  --proc /proc \
  --proc /proc/ \
New procfs, provides information about running processes and the kernel.
New procfs, provides information about running processes and the kernel.


Line 188: Line 198:
Bind the Wayland socket file.
Bind the Wayland socket file.


  --ro-bind /usr/lib /usr/lib \
  --ro-bind /usr/lib/ /usr/lib/ \
Object files and libraries.
Object files and libraries.


  --ro-bind /usr/share/X11/xkb /usr/share/X11/xkb \
{{Note|It is not worth the time to limit this, the churn is too great.}}
 
  --ro-bind /usr/share/X11/xkb/ /usr/share/X11/xkb/ \
XKB is a keyboard keymap support library.
XKB is a keyboard keymap support library.


{{Note|Even tho the path has {{Path|*/X11/*}} Wayland uses it too.}}
{{Note|Even tho the path has {{Path|*/X11/*}} Wayland uses it too.}}


  --ro-bind /usr/share/fontconfig /usr/share/fontconfig \
  --ro-bind /usr/share/fontconfig/ /usr/share/fontconfig/ \
Font presets.
Font presets.


  --ro-bind /usr/share/fonts /usr/share/fonts \
  --ro-bind /usr/share/fonts/ /usr/share/fonts/ \
Global directory scanned for font files.
Global directory scanned for font files.


  --ro-bind /usr/share/glib-2.0 /usr/share/glib-2.0 \
  --ro-bind /usr/share/glib-2.0/ /usr/share/glib-2.0/ \
Needed for "Save Page As…", "Export|Import Bookmarks File", among others.
Needed for "Save Page As…", "Export|Import Bookmarks File", among others.


  --ro-bind /usr/share/icons /usr/share/icons \
  --ro-bind /usr/share/icons/ /usr/share/icons/ \
Global icons directory.
Global icons directory.


  --ro-bind /usr/share/icu /usr/share/icu \
  --ro-bind /usr/share/icu/ /usr/share/icu/ \
International Components for Unicode (ICU) provides support for Unicode
International Components for Unicode (ICU) provides support for Unicode
and globalization.
and globalization.


  ...
  ...
  --ro-bind /usr/share/icu /usr/share/icu \
  --ro-bind /usr/share/icu/ /usr/share/icu/ \
  <b>--ro-bind /usr/share/libdrm /usr/share/libdrm \</b>
  <b>--ro-bind /usr/share/libdrm/ /usr/share/libdrm/ \</b>
  --ro-bind /usr/share/mime /usr/share/mime \
  --ro-bind /usr/share/mime/ /usr/share/mime/ \
  ...
  ...
(Optional) Direct Rendering Manager (DRM), Linux kernel subsystem for
(Optional) Direct Rendering Manager (DRM), Linux kernel subsystem for
Line 221: Line 233:
GPU do hardware-accelerated 3D rendering and video decoding.
GPU do hardware-accelerated 3D rendering and video decoding.


  --ro-bind /usr/share/mime /usr/share/mime \
  --ro-bind /usr/share/mime/ /usr/share/mime/ \
Global XDG MIME directory.
Global XDG MIME directory.


Line 238: Line 250:


  ...
  ...
  --proc /proc \
  --proc /proc/ \
  <b>--ro-bind "${XDG_RUNTIME_DIR}/pulse" "${XDG_RUNTIME_DIR}/pulse" \</b>
  <b>--ro-bind "${XDG_RUNTIME_DIR}/pulse/" "${XDG_RUNTIME_DIR}/pulse/" \</b>
  --ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \
  --ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \
  ...
  ...
(Optional) Pulse audio sound.
(Optional) Pulse audio.


=== Optional(?) stuff ===
=== Optional(?) stuff ===
Line 249: Line 261:


  ...
  ...
  --proc /proc \
  --proc /proc/ \
  <b>--ro-bind /sys/bus/pci /sys/bus/pci \</b>
  <b>--ro-bind /sys/bus/pci/ /sys/bus/pci/ \</b>
  --ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \
  --ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \
  ...
  ...
Line 260: Line 272:


  ...
  ...
  --proc /proc \
  --proc /proc/ \
  <b>--ro-bind /sys/devices/pci0000:00 /sys/devices/pci0000:00 \</b>
  <b>--ro-bind /sys/devices/pci0000:00/ /sys/devices/pci0000:00/ \</b>
  --ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \
  --ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \
  ...
  ...
Contains a filesystem representation of the kernel device tree.
Contains a filesystem representation of the kernel device tree.


With {{Ic|--ro-bind /sys/bus/pci /sys/bus/pci \}} but without this you get:
With {{Ic|--ro-bind /sys/bus/pci/ /sys/bus/pci/ \}} but without this you get:
  Crash Annotation GraphicsCriticalError: |[0][GFX1-]: glxtest: ManageChildProcess failed
  Crash Annotation GraphicsCriticalError: |[0][GFX1-]: glxtest: ManageChildProcess failed
   (t=0.189558) [GFX1-]: glxtest: ManageChildProcess failed
   (t=0.189558) [GFX1-]: glxtest: ManageChildProcess failed
Line 276: Line 288:


== imv ==
== imv ==
{{Cat|~/.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:-./}"}}
--ro-bind /bin/sh /bin/sh \
Needed to use {{Path|config}} and have various information in the window
title.
...
<b>XDG_CACHE_HOME{{=}}"${XDG_CACHE_HOME:{{=}}$HOME/.cache}"</b>
XDG_CONFIG_HOME{{=}}"${XDG_CONFIG_HOME:{{=}}$HOME/.config}"
<b>XDG_DATA_HOME{{=}}"${XDG_DATA_HOME:{{=}}$HOME/.local/share}"</b>
...
--setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
<b>--setenv XDG_CACHE_HOME "$XDG_CACHE_HOME" \</b>
--setenv XDG_CONFIG_HOME "$XDG_CONFIG_HOME" \
<b>--setenv XDG_DATA_HOME "$XDG_DATA_HOME" \</b>
--setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
...
--dev-bind /dev/dri/renderD128 /dev/dri/renderD128 \
<b>--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/" \</b>
--ro-bind-try "${XDG_CONFIG_HOME}/imv/config" "${XDG_CONFIG_HOME}/imv/config" \
<b>--ro-bind-try "${XDG_DATA_HOME}/fonts/" "${XDG_DATA_HOME}/fonts/" \</b>
--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/ \
<b>--ro-bind /usr/share/fonts/ /usr/share/fonts/ \
--ro-bind /usr/share/icu/ /usr/share/icu/ \</b>
--ro-bind "${1:-./}" "$(realpath "${1:-./}")" \
...
(Optional) To use commands in {{Ic|imv}}.
--ro-bind /sys/dev/char/ /sys/dev/char/ \
Access to character devices.
--ro-bind /sys/devices/pci0000:00/ /sys/devices/pci0000:00/ \
Access to PCI resources.
--ro-bind "${1:-./}" "$(realpath "${1:-./}")" \
Get the absolute pathname using {{Ic|realpath}}, so you can pass a
relative argument and still bind the argument.  If you don't pass in
anything it will default to {{Path|./}}, 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 {{Ic|imv}}, recursively.}}
== mpv ==
{{Cat|~/.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 /sys/dev/char/ /sys/dev/char/ \
Access to character devices.
--ro-bind /sys/devices/pci0000:00/ /sys/devices/pci0000:00/ \
Access to PCI resources.
--ro-bind "$1" "$(realpath "$1")" \
Get the absolute pathname using {{Ic|realpath}}, so you can pass a
relative argument and still bind the argument.
--player-operation-mode=pseudo-gui \
Because {{Ic|--new-session}} is used, this is needed to have a way to
control {{Ic|mpv}} when it would otherwise not show a GUI.
{{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 ===
If you want to use {{Ic|mpv}} to stream over the Internet, you will need
a few things more.
{{Tip|You can use both {{Ic|bwrap-mpv}} and {{Ic|bwrap-mpv-net}}.  {{Ic|bwrap-mpv}} for local stuff and {{Ic|bwrap-mpv-net}} for watching over the Internet.}}
{{Cat|~/.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''.
--ro-bind /sys/dev/char/ /sys/dev/char/ \
Access to character devices.
--ro-bind /sys/devices/pci0000:00/ /sys/devices/pci0000:00/ \
Access to PCI resources.
"$@"
This is so you can pass more options to {{Ic|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 {{Path|"$XDG_DESKTOP_DIR"}} (which is
{{Path|"${HOME}/Desktop/"}}, which will fallback to {{Path|"$HOME/"}} if
{{Path|"${HOME}/Desktop/"}} doesn't exist).  That means that by default
{{Ic|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}"
<b>XDG_DATA_HOME="${XDG_DATA_HOME:=$HOME/.local/share}"</b>
...
NEW_XDG_CONFIG_HOME="${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}"
<b>NEW_XDG_DATA_HOME="${NEW_HOME}${XDG_DATA_HOME#"$HOME"}"</b>
<b>mkdir -pm 0700 "${XDG_DATA_HOME}/mpv/"</b>
...
--setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \
<b>--setenv XDG_DATA_HOME "$NEW_XDG_DATA_HOME" \</b>
--setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
...
--ro-bind-try "${XDG_CONFIG_HOME}/mpv/mpv.conf" "${NEW_XDG_CONFIG_HOME}/mpv/mpv.conf" \
<b>--bind "${XDG_DATA_HOME}/mpv/" "${NEW_XDG_DATA_HOME}/mpv/" \</b>
--ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 \
...
Now make {{Ic|mpv}} use that directory:
{{Cat|"${XDG_CONFIG_HOME}/mpv/mpv.conf"|<nowiki>...
# Something like this, change to match "$XDG_DATA_HOME"
screenshot-template="~/.local/share/mpv/screenshots/%F [%p] %02n"
...</nowiki>}}
== yt-dlp ==
{{Cat|~/.local/bin/bwrap-yt-dlp|#!/usr/bin/env sh
# yt-dlp wrapped in bwrap with network access.
set -u
XDG_CONFIG_HOME{{=}}"${XDG_CONFIG_HOME:{{=}}$HOME/.config}"
NEW_HOME{{=}}'/home/user'
NEW_XDG_CONFIG_HOME{{=}}"${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}"
mkdir -pm 0700 "${HOME}/Downloads/"
/usr/bin/bwrap \
  --unshare-all \
  --share-net \
  --new-session \
  --die-with-parent \
  --clearenv \
  --setenv HOME "$NEW_HOME" \
  --setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \
  --hostname localhost \
  --ro-bind /etc/resolv.conf /etc/resolv.conf \
  --ro-bind /etc/ssl/certs/ /etc/ssl/certs/ \
  --ro-bind-try "${XDG_CONFIG_HOME}/yt-dlp/config" "${NEW_XDG_CONFIG_HOME}/yt-dlp/config" \
  --bind "${HOME}/Downloads/" "${NEW_HOME}/Downloads/" \
  --ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.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 \
  --ro-bind /usr/bin/ffmpeg /usr/bin/ffmpeg \
  --ro-bind /usr/bin/python3 /usr/bin/python3 \
  --ro-bind /usr/bin/yt-dlp /usr/bin/yt-dlp \
  --ro-bind /usr/lib/ /usr/lib/ \
  /usr/bin/yt-dlp "$@"}}
--bind "${HOME}/Downloads/" "${NEW_HOME}/Downloads/" \
Directory for writing the files.  This should match {{Ic|--output}} that
is either in {{Path|"${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 {{Ic|bwrap-yt-dlp}}, for example:
$ bwrap-yt-dlp --no-playlist 'URL1' 'URL2'
== zathura ==
{{Cat|~/.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 {{Ic|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
{{Ic|file(1)}} man page for more information.
--ro-bind "$1" "$(realpath "$1")" \
Get the absolute pathname using {{Ic|realpath}}, so you can pass a
relative argument and still bind the argument.


[[Category:Security]]
[[Category:Security]]

Latest revision as of 03:46, 12 January 2024

This material is work-in-progress ...

Someone more experienced needs to look over this.
(Last edited by Encode on 12 Jan 2024.)

Todo: Since bubblewrap can make use of seccomp, restrictive versions should be added. 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).


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. If you use Wayland, make sure you have dealt with XDG_RUNTIME_DIR.

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/libcrypto.so.3 /lib/libcrypto.so.3 \ --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
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.

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/libcrypto.so.3 /lib/libcrypto.so.3 \
--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.

Note: It is not worth the time to limit this, the churn is too great.
--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 12 Jan 2024.)

...
--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:-./}"
--ro-bind /bin/sh /bin/sh \

Needed to use config and have various information 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 /sys/dev/char/ /sys/dev/char/ \

Access to character devices.

--ro-bind /sys/devices/pci0000:00/ /sys/devices/pci0000:00/ \

Access to PCI resources.

--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 /sys/dev/char/ /sys/dev/char/ \

Access to character devices.

--ro-bind /sys/devices/pci0000:00/ /sys/devices/pci0000:00/ \

Access to PCI resources.

--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.

--ro-bind /sys/dev/char/ /sys/dev/char/ \

Access to character devices.

--ro-bind /sys/devices/pci0000:00/ /sys/devices/pci0000:00/ \

Access to PCI resources.

"$@"

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"

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

yt-dlp

Contents of ~/.local/bin/bwrap-yt-dlp

#!/usr/bin/env sh # yt-dlp wrapped in bwrap with network access. set -u XDG_CONFIG_HOME="${XDG_CONFIG_HOME:=$HOME/.config}" NEW_HOME='/home/user' NEW_XDG_CONFIG_HOME="${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}" mkdir -pm 0700 "${HOME}/Downloads/" /usr/bin/bwrap \ --unshare-all \ --share-net \ --new-session \ --die-with-parent \ --clearenv \ --setenv HOME "$NEW_HOME" \ --setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \ --hostname localhost \ --ro-bind /etc/resolv.conf /etc/resolv.conf \ --ro-bind /etc/ssl/certs/ /etc/ssl/certs/ \ --ro-bind-try "${XDG_CONFIG_HOME}/yt-dlp/config" "${NEW_XDG_CONFIG_HOME}/yt-dlp/config" \ --bind "${HOME}/Downloads/" "${NEW_HOME}/Downloads/" \ --ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.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 \ --ro-bind /usr/bin/ffmpeg /usr/bin/ffmpeg \ --ro-bind /usr/bin/python3 /usr/bin/python3 \ --ro-bind /usr/bin/yt-dlp /usr/bin/yt-dlp \ --ro-bind /usr/lib/ /usr/lib/ \ /usr/bin/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

#!/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.