Important notes:
1) This guide is for FreeBSD 13.0 and newer only!!
For FreeBSD 12, please see: https://forums.freebsd.org/threads/...-google-chrome-linux-binary-on-freebsd.77559/
2) This method should be valid for installing any other Chromium-based web browser (Google Chrome, Opera, Vivaldi, Edge, etc), as long as they (or their dependencies) are not Snaps/Flatpaks.
3) Most enhancements found in this tutorial were taken from/inspired by: https://github.com/mrclksr/linux-browser-installer
4) Given the many improvements made in Linuxulator and DRM drivers, we don't rely on games/linux-steam-utils workarounds anymore. Likewise, disabling DRI3 is no longer necessary.
5) Here we use an Ubuntu-based userspace, instead of default CentOS one.
6) Sound, webcam, microphone, hardware acceleration all properly work. Widevine support too (Netflix, Spotify, Amazon Prime Video, HBO Max, etc).
7) The /home and /tmp directories are shared by FreeBSD and Linux apps.
8) We now use /compat/ubuntu as Linux compat location, to avoid conflicting with CentOS-based ports. Still, be aware you can't run both Ubuntu and CentOS environments at the same time. When you want to switch back to running your CentOS-based applications, you'll need to disable Ubuntu rc.d script and enable the Linux one:
Then reboot to make your changes take effect, or manually stop Ubuntu service and start the Linux one:
9) I recommend (although is not a requirement as far as I know) to use tmpfs for /tmp. This is not the case when using ZFS default installation, but can be easily fixed. Assuming the ZFS pool is named "zroot":
# First reboot into single-user mode.
# Remount root filesystem as read/write:
# Destroy /tmp from zroot:
# Add this fstab entry:
# Reboot back to normal multi-user mode.
Let's begin:
# Create Ubuntu rc.d script and make it executable:
# Make it have this content:
# Enable Linux compatibility layer (Ubuntu):
# Create necessary mount points for a working Linuxulator:
# Start Ubuntu service:
# Install needed packages:
# Install Ubuntu 20.04 into /compat/ubuntu:
# Restart Ubuntu service to make sure everything is properly mounted:
# Fix broken symlink:
# Chroot into your Linux environment:
# Set correct timezone inside your chroot:
# Fix APT package manager:
# Enable more repositories:
# Install required programs:
# Add Brave signing key:
# Add Brave repository:
# Install Brave web browser:
# Exit chroot:
# Create custom Brave wrapper script (based on the one provided by the program itself):
# Make it contain this:
# Now create linux-brave launcher script and make it executable:
# Edit it so it has this content:
# Exit su:
# Finally, make a .desktop file to launch Brave as any other app:
# Make it look like this:
*Notice: Accessing your google account won't work. It will display something like this:
"Couldn't sign you in This browser or app may not be secure. Try using a different browser. If you’re already using a supported browser, you can refresh your screen and try again to sign in."
To fix this, change your user agent to a non-chromium web browser, like Firefox for instance, and login to Gmail or any other google service (making sure to keep logged in). After this you can change your user agent back to default.
The good thing is you won't need to repeat this step later, not even when logging-in to a different account .
For reference, this extension worked for me: User-Agent Switcher and Manager
That's all!
Sources:
https://wiki.freebsd.org/LinuxJails
https://wiki.freebsd.org/LinuxApps
https://wiki.freebsd.org/Linuxulator
https://help.ubuntu.com/lts/installation-guide/armhf/apds04.html
https://github.com/AppImage/AppImageKit/issues/98
https://pastebin.com/1W9Fh3e9
https://github.com/mrclksr/linux-browser-installer
EDIT 1:
-Changed compat location to /compat/ubuntu and added Ubuntu rc.d script to avoid conflicts with CentOS-based ports.
-Modified Brave wrapper script to resemble better the one provided by Brave itself. Also dropped --no-zygote flag.
EDIT 2:
-Fixed sound for PWAs too.
EDIT 3:
-Added "Restart Ubuntu service" immediately after running debootstrap, to make sure everything needed is properly mounted.
1) This guide is for FreeBSD 13.0 and newer only!!
For FreeBSD 12, please see: https://forums.freebsd.org/threads/...-google-chrome-linux-binary-on-freebsd.77559/
2) This method should be valid for installing any other Chromium-based web browser (Google Chrome, Opera, Vivaldi, Edge, etc), as long as they (or their dependencies) are not Snaps/Flatpaks.
3) Most enhancements found in this tutorial were taken from/inspired by: https://github.com/mrclksr/linux-browser-installer
4) Given the many improvements made in Linuxulator and DRM drivers, we don't rely on games/linux-steam-utils workarounds anymore. Likewise, disabling DRI3 is no longer necessary.
5) Here we use an Ubuntu-based userspace, instead of default CentOS one.
6) Sound, webcam, microphone, hardware acceleration all properly work. Widevine support too (Netflix, Spotify, Amazon Prime Video, HBO Max, etc).
7) The /home and /tmp directories are shared by FreeBSD and Linux apps.
8) We now use /compat/ubuntu as Linux compat location, to avoid conflicting with CentOS-based ports. Still, be aware you can't run both Ubuntu and CentOS environments at the same time. When you want to switch back to running your CentOS-based applications, you'll need to disable Ubuntu rc.d script and enable the Linux one:
sysrc ubuntu_enable=NO && sysrc linux_enable=YES
Then reboot to make your changes take effect, or manually stop Ubuntu service and start the Linux one:
service ubuntu onestop && sysctl compat.linux.emul_path=/compat/linux && service linux start
9) I recommend (although is not a requirement as far as I know) to use tmpfs for /tmp. This is not the case when using ZFS default installation, but can be easily fixed. Assuming the ZFS pool is named "zroot":
# First reboot into single-user mode.
# Remount root filesystem as read/write:
mount -u /
# Destroy /tmp from zroot:
zfs destroy -f zroot/tmp
# Add this fstab entry:
printf "tmpfs\t/tmp\ttmpfs\trw,mode=1777\t0\t0\n" >> /etc/fstab
# Reboot back to normal multi-user mode.
Let's begin:
su
# Create Ubuntu rc.d script and make it executable:
touch /usr/local/etc/rc.d/ubuntu && chmod +x /usr/local/etc/rc.d/ubuntu
# Make it have this content:
Code:
#!/bin/sh
#
# PROVIDE: ubuntu
# REQUIRE: archdep mountlate
# KEYWORD: nojail
#
# This is a modified version of /etc/rc.d/linux
# Based on the script by mrclksr:
# https://github.com/mrclksr/linux-browser-installer/blob/main/rc.d/ubuntu.in
#
. /etc/rc.subr
name="ubuntu"
desc="Enable Ubuntu chroot, and Linux ABI"
rcvar="ubuntu_enable"
start_cmd="${name}_start"
stop_cmd=":"
unmounted()
{
[ `stat -f "%d" "$1"` == `stat -f "%d" "$1/.."` -a \
`stat -f "%i" "$1"` != `stat -f "%i" "$1/.."` ]
}
ubuntu_start()
{
local _emul_path _tmpdir
load_kld -e 'linux(aout|elf)' linux
case `sysctl -n hw.machine_arch` in
amd64)
load_kld -e 'linux64elf' linux64
;;
esac
if [ -x /compat/ubuntu/sbin/ldconfigDisabled ]; then
_tmpdir=`mktemp -d -t linux-ldconfig`
/compat/ubuntu/sbin/ldconfig -C ${_tmpdir}/ld.so.cache
if ! cmp -s ${_tmpdir}/ld.so.cache /compat/ubuntu/etc/ld.so.cache; then
cat ${_tmpdir}/ld.so.cache > /compat/ubuntu/etc/ld.so.cache
fi
rm -rf ${_tmpdir}
fi
# Linux uses the pre-pts(4) tty naming scheme.
load_kld pty
# Handle unbranded ELF executables by defaulting to ELFOSABI_LINUX.
if [ `sysctl -ni kern.elf64.fallback_brand` -eq "-1" ]; then
sysctl kern.elf64.fallback_brand=3 > /dev/null
fi
if [ `sysctl -ni kern.elf32.fallback_brand` -eq "-1" ]; then
sysctl kern.elf32.fallback_brand=3 > /dev/null
fi
sysctl compat.linux.emul_path=/compat/ubuntu
_emul_path="/compat/ubuntu"
unmounted "${_emul_path}/dev" && (mount -o nocover -t devfs devfs "${_emul_path}/dev" || exit 1)
unmounted "${_emul_path}/dev/fd" && (mount -o nocover,linrdlnk -t fdescfs fdescfs "${_emul_path}/dev/fd" || exit 1)
unmounted "${_emul_path}/dev/shm" && (mount -o nocover,mode=1777 -t tmpfs tmpfs "${_emul_path}/dev/shm" || exit 1)
unmounted "${_emul_path}/home" && (mount -t nullfs /home "${_emul_path}/home" || exit 1)
unmounted "${_emul_path}/proc" && (mount -o nocover -t linprocfs linprocfs "${_emul_path}/proc" || exit 1)
unmounted "${_emul_path}/sys" && (mount -o nocover -t linsysfs linsysfs "${_emul_path}/sys" || exit 1)
unmounted "${_emul_path}/tmp" && (mount -t nullfs /tmp "${_emul_path}/tmp" || exit 1)
unmounted /dev/fd && (mount -o nocover -t fdescfs fdescfs /dev/fd || exit 1)
unmounted /proc && (mount -o nocover -t procfs procfs /proc || exit 1)
true
}
load_rc_config $name
run_rc_command "$1"
# Enable Linux compatibility layer (Ubuntu):
sysrc ubuntu_enable=YES
# Create necessary mount points for a working Linuxulator:
mkdir -p {/compat/ubuntu/dev/fd,/compat/ubuntu/dev/shm,/compat/ubuntu/home,/compat/ubuntu/tmp,/compat/ubuntu/proc,/compat/ubuntu/sys}
# Start Ubuntu service:
service ubuntu start
# Install needed packages:
pkg install debootstrap pulseaudio
# Install Ubuntu 20.04 into /compat/ubuntu:
debootstrap --arch=amd64 --no-check-gpg focal /compat/ubuntu
# Restart Ubuntu service to make sure everything is properly mounted:
service ubuntu restart
# Fix broken symlink:
cd /compat/ubuntu/lib64/ && rm ./ld-linux-x86-64.so.2 ; ln -s ../lib/x86_64-linux-gnu/ld-2.31.so ld-linux-x86-64.so.2
# Chroot into your Linux environment:
chroot /compat/ubuntu /bin/bash
# Set correct timezone inside your chroot:
printf "%b\n" "0.0 0 0.0\n0\nUTC" > /etc/adjtime
sudo dpkg-reconfigure tzdata
# For some reason sudo is necessary here, otherwise it fails.# Fix APT package manager:
printf "APT::Cache-Start 251658240;" > /etc/apt/apt.conf.d/00aptitude
# Enable more repositories:
printf "deb http://archive.ubuntu.com/ubuntu/ focal main restricted universe multiverse" > /etc/apt/sources.list
# Install required programs:
apt update ; apt install -y apt-transport-https curl fonts-symbola gnupg pulseaudio
# Add Brave signing key:
curl -s https://brave-browser-apt-release.s3.brave.com/brave-core.asc | apt-key --keyring /etc/apt/trusted.gpg.d/brave-browser-release.gpg add -
# Add Brave repository:
echo "deb [arch=amd64] https://brave-browser-apt-release.s3.brave.com/ stable main" | tee /etc/apt/sources.list.d/brave-browser-release.list
# Install Brave web browser:
apt update ; apt install -y brave-browser
# Exit chroot:
exit
# Create custom Brave wrapper script (based on the one provided by the program itself):
touch /compat/ubuntu/opt/brave.com/brave/brave-wrapper && chmod +x /compat/ubuntu/opt/brave.com/brave/brave-wrapper
# Make it contain this:
Code:
#!/compat/ubuntu/bin/bash
#
# Copyright (c) 2011 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
HERE="/opt/brave.com/brave"
# We include some xdg utilities next to the binary, and we want to prefer them
# over the system versions when we know the system versions are very old. We
# detect whether the system xdg utilities are sufficiently new to be likely to
# work for us by looking for xdg-settings. If we find it, we leave $PATH alone,
# so that the system xdg utilities (including any distro patches) will be used.
if ! which xdg-settings &> /dev/null; then
# Old xdg utilities. Prepend $HERE to $PATH to use ours instead.
export PATH="$HERE:$PATH"
else
# Use system xdg utilities. But first create mimeapps.list if it doesn't
# exist; some systems have bugs in xdg-mime that make it fail without it.
xdg_app_dir="${XDG_DATA_HOME:-$HOME/.local/share/applications}"
mkdir -p "$xdg_app_dir"
[ -f "$xdg_app_dir/mimeapps.list" ] || touch "$xdg_app_dir/mimeapps.list"
fi
# Always use our versions of ffmpeg libs.
# This also makes RPMs find the compatibly-named library symlinks.
if [[ -n "$LD_LIBRARY_PATH" ]]; then
LD_LIBRARY_PATH="$HERE:$HERE/lib:$LD_LIBRARY_PATH"
else
LD_LIBRARY_PATH="$HERE:$HERE/lib"
fi
export LD_LIBRARY_PATH
export CHROME_VERSION_EXTRA="stable"
# We don't want bug-buddy intercepting our crashes. http://crbug.com/24120
export GNOME_DISABLE_CRASH_DIALOG=SET_BY_GOOGLE_CHROME
# Sanitize std{in,out,err} because they'll be shared with untrusted child
# processes (http://crbug.com/376567).
exec < /dev/null
exec > >(exec cat)
exec 2> >(exec cat >&2)
"$HERE/brave" --no-sandbox --test-type --v=0 "$@" || true
# Now create linux-brave launcher script and make it executable:
touch /usr/local/bin/linux-brave && chmod +x /usr/local/bin/linux-brave
# Edit it so it has this content:
Code:
#!/bin/sh
# Ensure having working sound, independently of the DE/WM in use:
get_pa_sock_path()
{
PA_SOCK_PATH=$(sockstat | awk -v me=$(whoami) -F'[ \t]+' '
$1 == me && $2 == "pulseaudio" && $6 ~ /native/ {
print $6;
exit 0
}'
)
}
get_pa_sock_path
if [ ! -S "$PA_SOCK_PATH" ]; then
while killall pulseaudio; do
sleep 0.5
done
pulseaudio --start
get_pa_sock_path
fi
[ -S "$PA_SOCK_PATH" ] && export PULSE_SERVER=unix:$PA_SOCK_PATH
# Let the wrapped binary know that it has been run through the wrapper:
export CHROME_WRAPPER="`readlink -f "$0"`"
# Launch Brave through our custom brave-wrapper script:
/compat/ubuntu/opt/brave.com/brave/brave-wrapper "$@"
# Exit su:
exit
# Finally, make a .desktop file to launch Brave as any other app:
touch ~/.local/share/applications/brave-browser.desktop && chmod +x ~/.local/share/applications/brave-browser.desktop
# Make it look like this:
Code:
[Desktop Entry]
Type=Application
Version=1.0
Encoding=UTF-8
Name=Brave Web Browser
Comment=Access the Internet
Icon=brave-browser
Exec=/usr/local/bin/linux-brave %U
Categories=Application;Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;
StartupNotify=true
*Notice: Accessing your google account won't work. It will display something like this:
"Couldn't sign you in This browser or app may not be secure. Try using a different browser. If you’re already using a supported browser, you can refresh your screen and try again to sign in."
To fix this, change your user agent to a non-chromium web browser, like Firefox for instance, and login to Gmail or any other google service (making sure to keep logged in). After this you can change your user agent back to default.
The good thing is you won't need to repeat this step later, not even when logging-in to a different account .
For reference, this extension worked for me: User-Agent Switcher and Manager
That's all!
Sources:
https://wiki.freebsd.org/LinuxJails
https://wiki.freebsd.org/LinuxApps
https://wiki.freebsd.org/Linuxulator
https://help.ubuntu.com/lts/installation-guide/armhf/apds04.html
https://github.com/AppImage/AppImageKit/issues/98
https://pastebin.com/1W9Fh3e9
https://github.com/mrclksr/linux-browser-installer
EDIT 1:
-Changed compat location to /compat/ubuntu and added Ubuntu rc.d script to avoid conflicts with CentOS-based ports.
-Modified Brave wrapper script to resemble better the one provided by Brave itself. Also dropped --no-zygote flag.
EDIT 2:
-Fixed sound for PWAs too.
EDIT 3:
-Added "Restart Ubuntu service" immediately after running debootstrap, to make sure everything needed is properly mounted.
Last edited: