Bubblewrap/Examples: Difference between revisions

From Alpine Linux
(zathura example)
m (Use default values, instead of assign default values. Doesn't matter in this situation, but will lead to surprising results in most situations.)
 
(22 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]].}}
{{Warning|These were found by going backward; start with a complicated program and as restricted as possible sandbox, allowing more till the program appears to work.  Because of this, complicated and sensitive programs (for example: {{Pkg|firefox|arch=}} and {{Pkg|keepassxc|arch=}}) may be missing some things they need, which might lead to '''LESS SECURITY''', '''LESS PRIVACY''' and '''DATA LOSS'''.}}
 
{{Note|
* This page assumes you have already read [[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 assumes: [[Wayland]] only + [[PipeWire]].
: If Wayland is needed, make sure you have dealt with [[Wayland#XDG_RUNTIME_DIR|XDG_RUNTIME_DIR]].}}


{{TOC right}}
{{TOC right}}
Line 9: Line 17:
== Firefox ==
== Firefox ==


{{Cat|~/.local/bin/bwrap-firefox|#!/usr/bin/env sh
{{Cat|~/.local/bin/bwrap-firefox|#!/bin/sh


# Firefox wrapped in bwrap with network access.
# Firefox wrapped in bwrap with network access.
Line 15: Line 23:
set -u
set -u


XDG_CACHE_HOME{{=}}"${XDG_CACHE_HOME:{{=}}$HOME/.cache}"
XDG_CACHE_HOME{{=}}"${XDG_CACHE_HOME:-$HOME/.cache}"
XDG_DATA_HOME{{=}}"${XDG_DATA_HOME:{{=}}$HOME/.local/share}"
XDG_DATA_HOME{{=}}"${XDG_DATA_HOME:-$HOME/.local/share}"


NEW_HOME{{=}}'/home/user'
NEW_HOME{{=}}'/home/user'
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 39:
   --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}}


  XDG_CACHE_HOME="${XDG_CACHE_HOME:=$HOME/.cache}"
set -u
  XDG_DATA_HOME="${XDG_DATA_HOME:=$HOME/.local/share}"
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 [https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html XDG] default.
Take value if already set, else fallback to the [https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html XDG] default.


Line 63: Line 77:


  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 95:


  --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 102:
  --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 121:
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.


  ...
  ...
  XDG_CACHE_HOME="${XDG_CACHE_HOME:=$HOME/.cache}"
  XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
  <b>XDG_CONFIG_HOME "${XDG_CONFIG_HOME:=$HOME/.config}"</b>
  '''XDG_CONFIG_HOME "${XDG_CONFIG_HOME:-$HOME/.config}"'''
  XDG_DATA_HOME="${XDG_DATA_HOME:=$HOME/.local/share}"
  XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
  ...
  ...
  NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}"
  NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}"
  <b>NEW_XDG_CONFIG_HOME="${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}"</b>
  '''NEW_XDG_CONFIG_HOME="${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}"'''
  ...
  ...
  --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
  --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
  <b>--setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \</b>
  '''--setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \'''
  --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>
  '''--ro-bind-try "${XDG_CONFIG_HOME}/fontconfig/" "${NEW_XDG_CONFIG_HOME}/fontconfig/" \'''
  --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.


  ...
  ...
  XDG_CACHE_HOME="${XDG_CACHE_HOME:=$HOME/.cache}"
  XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
  <b>XDG_CONFIG_HOME "${XDG_CONFIG_HOME:=$HOME/.config}"</b>
  '''XDG_CONFIG_HOME "${XDG_CONFIG_HOME:-$HOME/.config}"'''
  XDG_DATA_HOME="${XDG_DATA_HOME:=$HOME/.local/share}"
  XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
  ...
  ...
  NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}"
  NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}"
  <b>NEW_XDG_CONFIG_HOME="${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}"</b>
  '''NEW_XDG_CONFIG_HOME="${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}"'''
  ...
  ...
  --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
  --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
  <b>--setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \</b>
  '''--setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \'''
  --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>
  '''--ro-bind-try "${XDG_CONFIG_HOME}/user-dirs.dirs" "${NEW_XDG_CONFIG_HOME}/user-dirs.dirs" \'''
  --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>
   '''--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 \
   ...
   ...
}}
}}


  --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)].}}


  ...
  ...
  NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}"
  NEW_XDG_CACHE_HOME="${NEW_HOME}${XDG_CACHE_HOME#"$HOME"}"
  <b>NEW_XDG_DATA_HOME="${NEW_HOME}${XDG_DATA_HOME#"$HOME"}"</b>
  '''NEW_XDG_DATA_HOME="${NEW_HOME}${XDG_DATA_HOME#"$HOME"}"'''
  ...
  ...
  --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
  --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
  <b>--setenv XDG_DATA_HOME "$NEW_XDG_DATA_HOME" \</b>
  '''--setenv XDG_DATA_HOME "$NEW_XDG_DATA_HOME" \'''
  --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>
  '''--ro-bind-try "${XDG_DATA_HOME}/fonts/" "${NEW_XDG_DATA_HOME}/fonts/" \'''
  --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 209:
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>
  '''--ro-bind /usr/share/libdrm/ /usr/share/libdrm/ \'''
  --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 244:
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 261:


  ...
  ...
  --proc /proc \
  --proc /proc/ \
  <b>--ro-bind "${XDG_RUNTIME_DIR}/pulse" "${XDG_RUNTIME_DIR}/pulse" \</b>
  '''--ro-bind "${XDG_RUNTIME_DIR}/pulse/" "${XDG_RUNTIME_DIR}/pulse/" \'''
  --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 272:


  ...
  ...
  --proc /proc \
  --proc /proc/ \
  <b>--ro-bind /sys/bus/pci /sys/bus/pci \</b>
  '''--ro-bind /sys/bus/pci/ /sys/bus/pci/ \'''
  --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 283:


  ...
  ...
  --proc /proc \
  --proc /proc/ \
  <b>--ro-bind /sys/devices/pci0000:00 /sys/devices/pci0000:00 \</b>
  '''--ro-bind /sys/devices/pci0000:00/ /sys/devices/pci0000:00/ \'''
  --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 299:


== imv ==
== imv ==
{{Cat|~/.local/bin/bwrap-imv|#!/bin/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.
...
'''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 {{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.}}
== KeePassXC ==
{{Note|I only use the bare minimum functionality, so functionality you need is probably missing.  If you use functionality not here, your contribution will be most appreciated.  To kick things off: {{Ic|Unable to initialize libusb. USB devices may not be detected properly.}} can be silenced with {{Ic|--dev-bind /dev/bus/usb/ /dev/bus/usb/ \}}.}}
{{Cat|~/.local/bin/bwrap-keepassxc|#!/bin/sh
# keepassxc wrapped in bwrap.
set -u
XDG_CONFIG_HOME{{=}}"${XDG_CONFIG_HOME:-$HOME/.config}"
PASSWORD_DATABASE{{=}}"${HOME}/password database"
NEW_HOME{{=}}'/home/user'
NEW_XDG_CONFIG_HOME{{=}}"${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}"
NEW_PASSWORD_DATABASE{{=}}"${NEW_HOME}${PASSWORD_DATABASE#"$HOME"}"
mkdir -pm 0700 "$PASSWORD_DATABASE"
/usr/bin/bwrap \
  --unshare-all \
  --new-session \
  --die-with-parent \
  --clearenv \
  --setenv HOME "$NEW_HOME" \
  --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
  --setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \
  --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
  --setenv XDG_SESSION_TYPE "$XDG_SESSION_TYPE" \
  --dev-bind /dev/dri/renderD128 /dev/dri/renderD128 \
  --ro-bind /etc/fonts/ /etc/fonts/ \
  --bind-try "${XDG_CONFIG_HOME}/keepassxc/" "${NEW_XDG_CONFIG_HOME}/keepassxc/" \
  --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 "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \
  --ro-bind /sys/dev/char/ /sys/dev/char/ \
  --ro-bind /sys/devices/pci0000:00/ /sys/devices/pci0000:00/ \
  --ro-bind /usr/bin/keepassxc /usr/bin/keepassxc \
  --ro-bind /usr/lib/ /usr/lib/ \
  --ro-bind /usr/share/X11/ /usr/share/X11/ \
  --ro-bind /usr/share/fontconfig/ /usr/share/fontconfig/ \
  --ro-bind /usr/share/fonts/ /usr/share/fonts/ \
  --ro-bind /usr/share/keepassxc/ /usr/share/keepassxc/ \
  --bind "$PASSWORD_DATABASE/" "$NEW_PASSWORD_DATABASE/" \
  /usr/bin/keepassxc "$@"}}
PASSWORD_DATABASE="${HOME}/password database"
Directory containing your {{Pkg|keepassxc|arch=}} password database.
{{Tip|This is almost certainly not where '''your''' database is located.  You will need to change it to where you put your password database.}}
--setenv XDG_SESSION_TYPE "$XDG_SESSION_TYPE" \
Session type, since we are assuming Wayland only, this will be "wayland".
--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.
--bind "$PASSWORD_DATABASE/" "$NEW_PASSWORD_DATABASE/" \
Bind password database.
== mpv ==
{{Cat|~/.local/bin/bwrap-mpv|#!/bin/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|#!/bin/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}"
'''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 {{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|#!/bin/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 ==
== zathura ==


{{Cat|~/.local/bin/bwrap-zathura|#!/usr/bin/env sh
{{Cat|~/.local/bin/bwrap-zathura|#!/bin/sh


# zathura wrapped in bwrap.
# zathura wrapped in bwrap.
Line 294: Line 706:
fi
fi


XDG_CONFIG_HOME{{=}}"${XDG_CONFIG_HOME:{{=}}$HOME/.config}"
XDG_CONFIG_HOME{{=}}"${XDG_CONFIG_HOME:-$HOME/.config}"
XDG_DATA_HOME{{=}}"${XDG_DATA_HOME:{{=}}$HOME/.local/share}"
XDG_DATA_HOME{{=}}"${XDG_DATA_HOME:-$HOME/.local/share}"


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


/usr/bin/bwrap \
/usr/bin/bwrap \
Line 309: Line 721:
   --setenv XDG_DATA_HOME "$XDG_DATA_HOME" \
   --setenv XDG_DATA_HOME "$XDG_DATA_HOME" \
   --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
   --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
   --ro-bind /etc/fonts /etc/fonts \
   --ro-bind /etc/fonts/ /etc/fonts/ \
   --ro-bind-try "${XDG_CONFIG_HOME}/zathura/zathurarc" "${XDG_CONFIG_HOME}/zathura/zathurarc" \
   --ro-bind-try "${XDG_CONFIG_HOME}/zathura/zathurarc" "${XDG_CONFIG_HOME}/zathura/zathurarc" \
   --bind "${XDG_DATA_HOME}/zathura" "${XDG_DATA_HOME}/zathura" \
   --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/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 \
Line 318: Line 730:
   --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/bin/zathura /usr/bin/zathura \
   --ro-bind /usr/bin/zathura /usr/bin/zathura \
   --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/fonts /usr/share/fonts \
   --ro-bind /usr/share/fonts/ /usr/share/fonts/ \
   --ro-bind /usr/share/misc/magic.mgc /usr/share/misc/magic.mgc \
   --ro-bind /usr/share/misc/magic.mgc /usr/share/misc/magic.mgc \
   --ro-bind "$1" "$(realpath "$1")" \
   --ro-bind "$1" "$(realpath "$1")" \
   /usr/bin/zathura "$1"}}
   /usr/bin/zathura "$1"}}


{{Note|This only accepts 1 (mandatory) argument.  This should be temporary, till I figure out how to pass multiple arguments (without including everything else); {{Ic|imv}} has the same problem.}}
  mkdir -pm 0700 "${XDG_DATA_HOME}/zathura/"
 
  mkdir -pm 0700 "${XDG_DATA_HOME}/zathura"
Have to premake the directory for {{Ic|zathura}} data.
Have to premake the directory for {{Ic|zathura}} data.


  --bind "${XDG_DATA_HOME}/zathura" "${XDG_DATA_HOME}/zathura" \
  --bind "${XDG_DATA_HOME}/zathura/" "${XDG_DATA_HOME}/zathura/" \
Allow writing of: bookmarks, history, input history.
Allow writing of: bookmarks, history, input history.


  --ro-bind /usr/share/misc/magic.mgc /usr/share/misc/magic.mgc \
  --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.
Used for identifying what type a file should be.  Read the
{{Ic|file(1)}} man page for more information.


  --ro-bind "$1" "$(realpath "$1")" \
  --ro-bind "$1" "$(realpath "$1")" \
Get the absolute pathname using {{Ic|realpath}}, so you can pass a relative argument and still bind the argument.
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:06, 5 June 2024

This material is work-in-progress ...

Someone more experienced needs to look over this.
(Last edited by Encode on 5 Jun 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).


Warning: These were found by going backward; start with a complicated program and as restricted as possible sandbox, allowing more till the program appears to work. Because of this, complicated and sensitive programs (for example: firefox and keepassxc) may be missing some things they need, which might lead to LESS SECURITY, LESS PRIVACY and DATA LOSS.


Note:
  • This page assumes you have already read 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 assumes: Wayland only + PipeWire.
If Wayland is needed, make sure you have dealt with XDG_RUNTIME_DIR.

Firefox

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

#!/bin/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 5 Jun 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

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


KeePassXC

Note: I only use the bare minimum functionality, so functionality you need is probably missing. If you use functionality not here, your contribution will be most appreciated. To kick things off: Unable to initialize libusb. USB devices may not be detected properly. can be silenced with --dev-bind /dev/bus/usb/ /dev/bus/usb/ \.

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

#!/bin/sh # keepassxc wrapped in bwrap. set -u XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" PASSWORD_DATABASE="${HOME}/password database" NEW_HOME='/home/user' NEW_XDG_CONFIG_HOME="${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}" NEW_PASSWORD_DATABASE="${NEW_HOME}${PASSWORD_DATABASE#"$HOME"}" mkdir -pm 0700 "$PASSWORD_DATABASE" /usr/bin/bwrap \ --unshare-all \ --new-session \ --die-with-parent \ --clearenv \ --setenv HOME "$NEW_HOME" \ --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \ --setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \ --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \ --setenv XDG_SESSION_TYPE "$XDG_SESSION_TYPE" \ --dev-bind /dev/dri/renderD128 /dev/dri/renderD128 \ --ro-bind /etc/fonts/ /etc/fonts/ \ --bind-try "${XDG_CONFIG_HOME}/keepassxc/" "${NEW_XDG_CONFIG_HOME}/keepassxc/" \ --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 "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" \ --ro-bind /sys/dev/char/ /sys/dev/char/ \ --ro-bind /sys/devices/pci0000:00/ /sys/devices/pci0000:00/ \ --ro-bind /usr/bin/keepassxc /usr/bin/keepassxc \ --ro-bind /usr/lib/ /usr/lib/ \ --ro-bind /usr/share/X11/ /usr/share/X11/ \ --ro-bind /usr/share/fontconfig/ /usr/share/fontconfig/ \ --ro-bind /usr/share/fonts/ /usr/share/fonts/ \ --ro-bind /usr/share/keepassxc/ /usr/share/keepassxc/ \ --bind "$PASSWORD_DATABASE/" "$NEW_PASSWORD_DATABASE/" \ /usr/bin/keepassxc "$@"
PASSWORD_DATABASE="${HOME}/password database"

Directory containing your keepassxc password database.

Tip: This is almost certainly not where your database is located. You will need to change it to where you put your password database.
--setenv XDG_SESSION_TYPE "$XDG_SESSION_TYPE" \

Session type, since we are assuming Wayland only, this will be "wayland".

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

--bind "$PASSWORD_DATABASE/" "$NEW_PASSWORD_DATABASE/" \

Bind password database.

mpv

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

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

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

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

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