目標:我們用這個來跑FreeBSD沒有,Linux才有的圖形應用程式,比如說安裝Google Chrome。
是的,Google真的沒有提供FreeBSD的套件。FreeBSD收錄的只有Chromium。Chrome除了能同步Google帳號資料之外,還可以播放Widevine DRM內容,比如Spotify與Netflix。FreeBSD的原生瀏覽器普遍缺乏播放DRM的能力,就連Firefox都沒有,所以這個時候Linux版的瀏覽器就派上用場了。
1. 說明#
測試環境:FreeBSD 14.0 Release
本文用到的軟體:
- Linuxulator
- FreeBSD chroot Jail
要高效率的跑Linux程式,得用Linuxulator。
Linuxulator功能類似轉譯Windows程式的Wine,讓我們可以在FreeBSD系統以原生效能執行Linux的二進位檔。準確來說,Linuxulator不是轉譯,而是重新實現Linux ABI。
Linuxulator本身只有實現ABI,不能直接執行Linux二進位檔,需要補一些userspace依賴套件。FreeBSD的套件庫有收一些Linux移植過來的程式,能夠讓一些程式跑起來,譬如前文說的Google Chrome。
此外,有了Linuxlator,還可以搭配FreeBSD內建的chroot指令,建立一個Linux的Jail。Jail就是讓程式跑在受限制的監獄,或可理解為容器吧。在Docker出現以前,chroot也是Linux上最常見的一種容器。
Jail非必要步驟,只是一個選項。在部分情況下,Jail建立的Linux環境附有userspace的Linux套件,環境比較完整,可以無縫使用Linux的套件管理器來安裝軟體。例如我們可以在FreeBSD建立Ubuntu的Jail,再使用APT安裝軟體。這樣安裝軟體很方便,又不會跟FreeBSD系統的套件衝突。且由於很多Linux發行版都有提供"bootstrap"一類的工具,所以要安裝Arch Linux、Alpine Linux、Fedora等其他發行版的Linux Jail也不是問題的。
2. 設定Linuxulator#
Linuxulator是FreeBSD內建功能,無需安裝。
- 設定開機啟用Linux服務,並載入linux核心模組。設定之後重開機。
sudo sysrc dbus_enable="YES"
sudo sysrc linux_enable="YES"
sudo sysrc kld_list+="linux linux64"
- 根據FreeBSD Wiki記載,FreeBSD 14僅相容到Linux核心4.4的ABI。有些Linux程式可能會顯示
FATAL: Kernel too old
的錯誤。這時Linux核心的版本可以用變數compat.linux.osrelease
強制覆寫,但不保證功能正常:
echo "compat.linux.osrelease=5.14.0" | sudo tee -a /boot/loader.conf
此外,在Linux Jail裡面使用uname
指令的時候,系統回報的依然是FreeBSD,而非Linux版本。
3. 用linuxulator執行Linux程式#
安裝完成後,不能直接執行Linux程式,多半還要拉一些userland套件下來。
FreeBSD開發者似乎比較偏愛RHEL,FreeBSD收錄的userland套件以移植自Rocky Linux的居多(以前是CentOS,不過你知道的,這個專案的穩定發表版本已經掛了),名稱為linux_base-rl9
。至於Ubuntu的需要chroot才能使用。
rl9*
開頭的Linux套件在安裝後會放到/compat/linux
目錄。
FreeBSD Ports有收錄一些社群打包好的Linux程式套件,不需要手動配置。
比方說,執行sudo pkg instal linux-sublime
安裝套件,就會自動下載Sublime Text需要的Linux依賴套件,然後幫你做好一個桌面的Desktop Entry。
4. 安裝Linux版的Google Chrome#
適用Chrome、Edge、Brave等Chromium核心的瀏覽器。
- 我們可以安裝Ports的
linux-chrome
套件,自動安裝需要的Rocky Linux依賴套件。這個比在Ubuntu Jail內安裝Chrome要簡單許多。
sudo pkg install linux-chrome
- 接著安裝啟用DRM的套件
foreign-cdm
與linux-widevine-cdm
:
sudo pkg install foreign-cdm
cd /usr/ports/www/linux-widevine-cdm/ && sudo make install clean
- 安裝後會在桌面環境建立Google Chrome的Desktop Entry,點選即可使用。
如果透過Ports安裝的Google Chrome有問題,請先解除安裝:sudo pkg remove linux-chrome
。
再考慮使用linux-browser-installer指令稿來安裝Google Chrome:
git clone https://github.com/mrclksr/linux-browser-installer.git
cd linux-browser-installer
sudo ./linux-browser-installer install chrome
它會幫你自動安裝Ubuntu Jail並設定開機自動啟動,故不需要手動建立。
5. 建立Ubuntu Jail#
除非你真的很需要Ubuntu相關東西,否則請優先考慮使用Ports的Linux套件,不要用chroot。
- 我們需要安裝debootstap,這個工具可以用來建立Ubuntu或Debian的rootfs。
sudo pkg install debootstrap
在安裝後應會自動建立
/compat/ubuntu/
目錄,Ubuntu的rootfs要放到這裡。不要使用/compat/linux
,因為它是保留給Rocky Linux相關的linux_base-rl9
套件使用的。用debootstrap,從台灣伺服器下載Ubuntu 22.04系統到那個目錄
sudo debootstrap jammy "/compat/ubuntu/" "http://tw.archive.ubuntu.com/ubuntu"
- (選擇性)將Linux需要的目錄設定為開機自動掛載,以下內容請寫入到
/etc/fstab
。
devfs /compat/ubuntu/dev devfs rw,late 0 0
tmpfs /compat/ubuntu/dev/shm tmpfs rw,late,size=1g,mode=1777 0 0
fdescfs /compat/ubuntu/dev/fd fdescfs rw,late,linrdlnk 0 0
linprocfs /compat/ubuntu/proc linprocfs rw,late 0 0
linsysfs /compat/ubuntu/sys linsysfs rw,late 0 0
/tmp /compat/ubuntu/tmp nullfs rw,late 0 0
- 其中掛載home目錄的時候要注意,FreeBSD手冊是告訴你直接掛進去以方便共享檔案,但我希望Jail內的home跟FreeBSD的home是隔離的:
/home/user/UbuntuHome /compat/ubuntu/home nullfs rw,late 0 0
若有FreeBSD目錄想跟Jail裡面的Linux共享,再額外掛載:
/home/user/Downloads /compat/ubuntu/mnt/host_shared nullfs rw,late 0 0
- 重開機。這樣就能用chroot指令進入Ubuntu Jail了:
sudo chroot /compat/ubuntu /bin/bash
- 編輯
/etc/apt/sources.list
apt update
apt install vim
vim /etc/apt/sources.list
- 補上main、restricted、universe的套件庫
deb [trusted=yes] http://tw.archive.ubuntu.com/ubuntu jammy main restricted universe
deb [trusted=yes] http://tw.archive.ubuntu.com/ubuntu jammy-security main restricted universe
deb [trusted=yes] http://tw.archive.ubuntu.com/ubuntu jammy-updates main restricted universe
- 更新套件庫後就可用APT安裝套件。
apt update
- chroot Linux內執行的X11程式應會直接顯示在FreeBSD的螢幕上,但可能不會吃到3D加速。如果沒有的話執行xhost指令允許所有X客戶端連線:
xhost local:
至於Fcitx5輸入法得在Linux容器另外安裝。
注意chroot內無法使用systemd相關指令,所以跑服務你都得手動輸入二進位檔的絕對路徑來啟動。
還有,Docker、Flatpak、Snap是無法在chroot內使用的。