Bubblewrap/Examples: Difference between revisions

From Alpine Linux
(KeePassXC 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.)
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{Draft|Someone more experienced needs to look over this.}}
{{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. {{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).}}
{{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|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]].}}
{{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 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'
Line 61: Line 69:
few exceptions).
few exceptions).


  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}"
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 117: Line 125:


  ...
  ...
  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 "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \
  --bind "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \
  ...
  ...
Line 135: Line 144:


  ...
  ...
  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 "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \
  --bind "${XDG_DATA_HOME}/firefox/" "${NEW_HOME}/.mozilla/" \
  ...
  ...
Line 158: Line 168:
   ...
   ...
   --bind "${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 \
   ...
   ...
Line 170: Line 180:
  ...
  ...
  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 "${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/" \
  ...
  ...
Line 226: Line 237:
  ...
  ...
  --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/ \
  ...
  ...
Line 251: Line 262:
  ...
  ...
  --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}" \
  ...
  ...
Line 262: Line 273:
  ...
  ...
  --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 273: Line 284:
  ...
  ...
  --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}" \
  ...
  ...
Line 295: Line 306:
set -u
set -u


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


/usr/bin/bwrap \
/usr/bin/bwrap \
Line 326: Line 337:


  ...
  ...
  <b>XDG_CACHE_HOME{{=}}"${XDG_CACHE_HOME:{{=}}$HOME/.cache}"</b>
   
  XDG_CONFIG_HOME{{=}}"${XDG_CONFIG_HOME:{{=}}$HOME/.config}"
'''XDG_CACHE_HOME{{=}}"${XDG_CACHE_HOME:-$HOME/.cache}"'''
  <b>XDG_DATA_HOME{{=}}"${XDG_DATA_HOME:{{=}}$HOME/.local/share}"</b>
  XDG_CONFIG_HOME{{=}}"${XDG_CONFIG_HOME:-$HOME/.config}"
  '''XDG_DATA_HOME{{=}}"${XDG_DATA_HOME:-$HOME/.local/share}"'''
  ...
  ...
  --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
  --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
  <b>--setenv XDG_CACHE_HOME "$XDG_CACHE_HOME" \</b>
  '''--setenv XDG_CACHE_HOME "$XDG_CACHE_HOME" \'''
  --setenv XDG_CONFIG_HOME "$XDG_CONFIG_HOME" \
  --setenv XDG_CONFIG_HOME "$XDG_CONFIG_HOME" \
  <b>--setenv XDG_DATA_HOME "$XDG_DATA_HOME" \</b>
  '''--setenv XDG_DATA_HOME "$XDG_DATA_HOME" \'''
  --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
  --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
  ...
  ...
  --dev-bind /dev/dri/renderD128 /dev/dri/renderD128 \
  --dev-bind /dev/dri/renderD128 /dev/dri/renderD128 \
  <b>--ro-bind /etc/fonts/ /etc/fonts/ \
  '''--ro-bind /etc/fonts/ /etc/fonts/ \'''
  --bind-try "${XDG_CACHE_HOME}/fontconfig/" "${XDG_CACHE_HOME}/fontconfig/" \
  '''--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}/fontconfig/" "${XDG_CONFIG_HOME}/fontconfig/" \'''
  --ro-bind-try "${XDG_CONFIG_HOME}/imv/config" "${XDG_CONFIG_HOME}/imv/config" \
  --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-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 /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/X11/xkb/ /usr/share/X11/xkb/ \
  <b>--ro-bind /usr/share/fonts/ /usr/share/fonts/ \
  '''--ro-bind /usr/share/fonts/ /usr/share/fonts/ \'''
  --ro-bind /usr/share/icu/ /usr/share/icu/ \</b>
  '''--ro-bind /usr/share/icu/ /usr/share/icu/ \'''
  --ro-bind "${1:-./}" "$(realpath "${1:-./}")" \
  --ro-bind "${1:-./}" "$(realpath "${1:-./}")" \
  ...
  ...
Line 374: Line 387:
set -u
set -u


XDG_CONFIG_HOME{{=}}"${XDG_CONFIG_HOME:{{=}}$HOME/.config}"
XDG_CONFIG_HOME{{=}}"${XDG_CONFIG_HOME:-$HOME/.config}"
PASSWORD_DATABASE{{=}}"${HOME}/password database"
PASSWORD_DATABASE{{=}}"${HOME}/password database"


Line 413: Line 426:


  PASSWORD_DATABASE="${HOME}/password database"
  PASSWORD_DATABASE="${HOME}/password database"
Directory containing your {{Pkg|keepassxc}} 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.}}
{{Tip|This is almost certainly not where '''your''' database is located.  You will need to change it to where you put your password database.}}
Line 446: Line 459:
fi
fi


XDG_CACHE_HOME{{=}}"${XDG_CACHE_HOME:{{=}}$HOME/.cache}"
XDG_CACHE_HOME{{=}}"${XDG_CACHE_HOME:-$HOME/.cache}"
XDG_CONFIG_HOME{{=}}"${XDG_CONFIG_HOME:{{=}}$HOME/.config}"
XDG_CONFIG_HOME{{=}}"${XDG_CONFIG_HOME:-$HOME/.config}"


NEW_HOME{{=}}'/home/user'
NEW_HOME{{=}}'/home/user'
Line 523: Line 536:
set -u
set -u


XDG_CACHE_HOME{{=}}"${XDG_CACHE_HOME:{{=}}$HOME/.cache}"
XDG_CACHE_HOME{{=}}"${XDG_CACHE_HOME:-$HOME/.cache}"
XDG_CONFIG_HOME{{=}}"${XDG_CONFIG_HOME:{{=}}$HOME/.config}"
XDG_CONFIG_HOME{{=}}"${XDG_CONFIG_HOME:-$HOME/.config}"


NEW_HOME{{=}}'/home/user'
NEW_HOME{{=}}'/home/user'
Line 604: Line 617:


  ...
  ...
  XDG_CONFIG_HOME="${XDG_CONFIG_HOME:=$HOME/.config}"
  XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
  <b>XDG_DATA_HOME="${XDG_DATA_HOME:=$HOME/.local/share}"</b>
  '''XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"'''
  ...
  ...
  NEW_XDG_CONFIG_HOME="${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}"
  NEW_XDG_CONFIG_HOME="${NEW_HOME}${XDG_CONFIG_HOME#"$HOME"}"
  <b>NEW_XDG_DATA_HOME="${NEW_HOME}${XDG_DATA_HOME#"$HOME"}"</b>
  '''NEW_XDG_DATA_HOME="${NEW_HOME}${XDG_DATA_HOME#"$HOME"}"'''
'''mkdir -pm 0700 "${XDG_DATA_HOME}/mpv/"'''
   
   
<b>mkdir -pm 0700 "${XDG_DATA_HOME}/mpv/"</b>
  ...
  ...
  --setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \
  --setenv XDG_CONFIG_HOME "$NEW_XDG_CONFIG_HOME" \
  <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" \
  ...
  ...
  --ro-bind-try "${XDG_CONFIG_HOME}/mpv/mpv.conf" "${NEW_XDG_CONFIG_HOME}/mpv/mpv.conf" \
  --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>
  '''--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 \
  --ro-bind /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 \
  ...
  ...
Line 635: Line 650:
set -u
set -u


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


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

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.