#+STARTUP: content * freebsd thick jail ** freebsd handbook jails [[https://docs.freebsd.org/en/books/handbook/jails/]] ** jail config To start jails when the system boots enable jails #+begin_src sh sudo sysrc jail_enable="YES" sudo sysrc jail_parallel_start="YES" sudo sysrc jail_list="classic" sudo sysrc cloned_interfaces="lo1" sudo sysrc ifconfig_lo1_aliases="inet 10.10.0.1-12/24" #+end_src #+begin_example /etc/rc.conf #+end_example #+begin_src conf jail_enable="YES" #jail_parallel_start="YES" #jail_list="classic" cloned_interfaces="lo1" ifconfig_lo1_aliases="inet 10.10.0.1-12/24" #+end_src With jail_parallel_start, all configured jails will be started in the background. ** jail directory tree switch to root #+begin_src sh su #+end_src create the zfs dataset and set the mountpoint #+begin_src sh zfs create -o mountpoint=/usr/local/jails zroot/jails zfs create zroot/jails/media zfs create zroot/jails/templates zfs create zroot/jails/containers #+end_src *** /etc/jail.conf create the /etc/jail.conf file if it doesn't exist #+begin_example /etc/jail.conf #+end_example add the following code to the jail.conf file to include \\ files with a .conf extension in the /etc/jail.conf.d/ directory #+begin_src conf # startup/logging exec.start = "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; exec.consolelog = "/var/log/jail_console_${name}.log"; #+end_src ** freebsd devfs.rules #+begin_example /etc/devfs.rules #+end_example #+begin_src conf [jails=7] add include $devfsrules_hide_all add include $devfsrules_unhide_basic add include $devfsrules_unhide_login add path 'mixer*' unhide add path 'dsp*' unhide add path 'dri*' unhide add path 'drm*' unhide add path 'nvidia*' unhide add path 'speaker*' unhide #+end_src after adding the devfs rules reboot ** create thick jail In principle, a jail only needs a hostname, a root directory, an IP address, and a userland. The userland for the jail can be obtained from the official FreeBSD download servers. switch to root #+begin_src sh su #+end_src Execute the following command to download the userland: #+begin_src sh fetch https://download.freebsd.org/ftp/releases/amd64/amd64/14.1-RELEASE/base.txz -o /usr/local/jails/media/14.1-RELEASE-base.txz #+end_src Once the download is complete, it will be necessary to extract the contents into the jail directory. Execute the following commands to extract the userland into the jail’s directory: #+begin_src sh mkdir -p /usr/local/jails/containers/classic tar -xf /usr/local/jails/media/14.1-RELEASE-base.txz -C /usr/local/jails/containers/classic --unlink #+end_src With the userland extracted in the jail directory, it will be necessary to copy the timezone and DNS server files: #+begin_src sh cp /etc/resolv.conf /usr/local/jails/containers/classic/etc/resolv.conf cp /etc/localtime /usr/local/jails/containers/classic/etc/localtime #+end_src With the files copied, the next thing to do is update to the latest patch level by executing the following command: #+begin_src sh freebsd-update -b /usr/local/jails/containers/classic/ fetch install #+end_src ** /etc/jail.conf.d/classic.conf create the /etc/jail.conf.d/ directory #+begin_src sh sudo mkdir -p /etc/jail.conf.d/ #+end_src #+begin_example /etc/jail.conf.d/classic.conf #+end_example #+begin_src sh classic { # hostname/path host.hostname = "${name}"; path = "/usr/local/jails/containers/${name}"; # permissions allow.raw_sockets; exec.clean; persist; sysvmsg=inherit; sysvsem=inherit; sysvshm=inherit; enforce_statfs=1; # permissions devfs_ruleset=7; # network ip4.addr="lo1|10.10.0.5/24"; # mount mount += "devfs $path/dev devfs rw 0 0"; mount += "tmpfs $path/dev/shm tmpfs rw,size=1g,mode=1777 0 0"; mount += "/tmp $path/tmp nullfs rw 0 0"; mount += "/home $path/home nullfs rw 0 0"; # mount the download directory from the host to the jail after creating it #mount += "/home/username/downloads $path/home/username/downloads nullfs rw 0 0"; # uncomment the line below for the xdg runtime directory for wayland after creating it #mount += "/var/run/xdg/username $path/var/run/xdg/username nullfs rw 0 0"; } #+end_src ** pf.conf #+begin_src sh /etc/pf.conf: #+end_src nat for jail #+begin_src sh nat on $int_if from {lo1:network} to any -> ($int_if) antispoof log quick for { lo $int_if } label "block_spoofing" #+end_src full pf.conf example #+begin_src conf #=========================================================================# # variables, macro and tables # #=========================================================================# int_if="ue0" # usb to ethernet adaptor #int_if="bge0" # thunderbolt to ethernet adaptor #int_if="wlan0" # ralink usb wifi vpn_if="tun0" # vpn interface all_networks="0.0.0.0/0" vpn_network="$vpn_if:network" tcp_services = "{ ntp, 6881 }" # tcp services - torrent udp_services = "{ ntp, 6882 }" # udp services - torrent icmp_types = "{ echoreq, unreach }" tcp_state="flags S/SA keep state" udp_state="keep state" #table { $all_networks, !self, !$int_if:network } # internet #table { $int_if:network, !self } # lan network table { self } # self table { 0.0.0.0/8 10.0.0.0/8 127.0.0.0/8 169.254.0.0/16 \ 172.16.0.0/12 192.0.0.0/24 192.0.2.0/24 224.0.0.0/3 \ 192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 \ 203.0.113.0/24 } # broken networks #=========================================================================# # global policy # #=========================================================================# set block-policy drop set loginterface $int_if set fingerprints "/etc/pf.os" set skip on lo0 scrub in all fragment reassemble no-df max-mss 1440 # nat jail nat on $int_if from {lo1:network} to any -> ($int_if) antispoof log quick for { lo $int_if } label "block_spoofing" #=========================================================================# # block # #=========================================================================# block log all # block log all block return out quick inet6 all tag IPV6 # block ipv6 block in quick inet6 all tag IPV6 # block ipv6 # block broken networks - turned off for synergy # block in quick from { no-route urpf-failed } to any tag BAD_PACKET #=========================================================================# # anchors # #=========================================================================# # emerging threats - anchor #anchor "emerging-threats" #load anchor "emerging-threats" from "/etc/pf.anchors/emerging-threats" # openvpn - anchor anchor "openvpn" #=========================================================================# # traffic tag # #=========================================================================# # icmp pass inet proto icmp all icmp-type $icmp_types keep state tag ICMP # Allow the tcp and udp services defined in the macros at the top of the file pass in on $int_if inet proto tcp from any to ($int_if) port $tcp_services $tcp_state tag TCP_IN pass in on $int_if inet proto udp from any to ($int_if) port $udp_services $udp_state tag UDP_IN # outbound traffic block out on $int_if all pass out quick on $int_if all modulate state #+end_src ** jail start #+begin_src sh doas service jail onestart classic #+end_src ** enter jail #+begin_src sh doas jexec classic /bin/sh #+end_src ** adduser add user this will create the /home/username directory #+begin_src sh adduser #+end_src add user to the following groups #+begin_example wheel operator video #+end_example set the password ** dns #+begin_src sh vi /etc/resolv.conf #+end_src comment out 127.0.0.1 and uncomment nameserver 192.168.1.1 #+begin_src conf # Generated by resolvconf search localdomain nameserver 192.168.1.1 #nameserver 127.0.0.1 options edns0 #+end_src ** bootstrap the system To bootstrap the system switch to root with su then bootstrap pkg #+BEGIN_SRC sh /usr/sbin/pkg #+END_SRC ** pkg update upgrade #+begin_src sh pkg update #+end_src #+begin_src sh pkg upgrade #+end_src ** sudo *** install sudo #+BEGIN_SRC sh pkg install sudo #+END_SRC *** edit /etc/sudoers #+BEGIN_SRC sh visudo #+END_SRC *** add your user to the sudoers file replace username with your username #+BEGIN_SRC sh username ALL=(ALL:ALL) ALL #+END_SRC ** nvidia drivers #+begin_SRC sh pkg install nvidia-driver nvidia-settings nvidia-drm-515-kmod libva-intel-driver libva-utils gpu-firmware-intel-kmod-kabylake #+END_SRC we also need to edit /etc/rc.conf and add the path to the i915kms.ko file #+begin_src sh sysrc kld_list+="i915kms nvidia-modeset nvidia-drm linux linux64" #+end_src or manually edit the config file #+BEGIN_SRC sh vi /etc/rc.conf #+END_SRC then add the code below to /etc/rc.conf #+BEGIN_SRC sh kld_list="i915kms nvidia-modeset nvidia-drm linux linux64" #+END_SRC ** libc6-shim #+begin_src sh sudo pkg install linux-nvidia-libs libvdpau-va-gl libva-nvidia-driver #+end_src #+begin_src sh pkg install libc6-shim #+end_src #+begin_src sh nv-sglrun nvidia-smi #+end_src ** wayland #+begin_src sh pkg install wayland wayland-protocols seatd qt5ct qt5-wayland #+end_src *** seatd #+begin_src sh sysrc seatd_enable=YES #+end_src *** dbus #+begin_src sh sysrc dbus_enable=YES #+end_src ** switch to out user #+begin_src sh su - djwilcox #+end_src ** create the xdg runtime directory create the xdg runtime directory, change the user and set the permissions #+begin_src sh sudo mkdir -p /var/run/xdg/"${USER}" sudo chown -R "${USER}":wheel /var/run/xdg/"${USER}" sudo chmod 700 /var/run/xdg/"${USER}" #+end_src ** install zsh install zsh #+BEGIN_SRC sh sudo pkg install zsh zsh-completions zsh-syntax-highlighting #+END_SRC *** zshrc #+begin_src conf # ~/.zshrc # add your zshrc code below #+end_src *** zshenv #+begin_src conf # ~/.zshenv # Path typeset -U PATH path path=("$path[@]") export PATH # xdg directories export XDG_CONFIG_HOME="$HOME/.config" export XDG_CACHE_HOME="$HOME/.cache" export XDG_DATA_HOME="$HOME/.local/share" export XDG_RUNTIME_DIR=/var/run/xdg/"${USER}" # qt5 export QT_QPA_PLATFORMTHEME=qt5ct # wayland - uncomment to use wayland export WAYLAND_DISPLAY=wayland-0 export QT_QPA_PLATFORM=wayland export GDK_BACKEND=wayland # consolekit #export LIBSEAT_BACKEND=consolekit2 # dbus #+end_src *** chsh change the shell to zsh #+BEGIN_SRC sh chsh -s /usr/local/bin/zsh #+END_SRC log out and back in #+begin_src sh exit #+end_src #+begin_src sh su - djwilcox #+end_src ** locale #+begin_src sh vi ~/.login_conf #+end_src #+begin_src conf me:\ :charset=UTF-8:\ :lang=en_GB.UTF-8:\ :setenv=LC_COLLATE=C: #+end_src #+begin_src sh cap_mkdb ~/.login_conf #+end_src ** sndiod #+begin_src sh sudo sysrc sndiod_enable="YES" #+end_src ** firefox #+begin_src sh sudo pkg install firefox #+end_src ** gtk themes #+begin_src sh sudo pkg install gtk-arc-themes #+end_src ** user-dirs.dirs #+begin_src sh vi ~/.config/user-dirs.dirs #+end_src #+begin_src sh enabled=False XDG_DOWNLOAD_DIR="$HOME/downloads" #+end_src ** fonts #+begin_src sh sudo pkg install noto-basic noto-emoji #+end_src ** jailfox *** host **** bin #+begin_example ~/bin #+end_example ***** firefox #+begin_src sh #!/bin/sh # exit if no arguments passed to script [ $# -gt 0 ] || exit 1 # run the wrapper-freebsd script wrapper-freebsd -a firefox "${@}" #+end_src ***** shell config #+begin_example ~/.zshenv #+end_example set the shell path to include your bin directory #+begin_src conf # ~/.zshenv # Path typeset -U PATH path path=("$HOME/bin" "/usr/local/bin" "$path[@]") export PATH #+end_src ***** wrapper-freebsd #+begin_src sh #!/bin/sh # wrapper-freebsd #=============================================================================== # script usage #=============================================================================== usage () { # if argument passed to function echo it [ -z "${1}" ] || echo "! ${1}" # display help echo "\ # script usage $(basename "$0") -u ${USER}" exit 2 } #=============================================================================== # check the number of arguments passed to the script #=============================================================================== [ $# -gt 0 ] || usage "${WRONG_ARGS_ERR}" #=============================================================================== # getopts check the options passed to the script #=============================================================================== while getopts ':a:h' opt do case ${opt} in a) app="${OPTARG}";; h) usage;; \?) usage "${INVALID_OPT_ERR} ${OPTARG}" 1>&2;; :) usage "${INVALID_OPT_ERR} ${OPTARG} ${REQ_ARG_ERR}" 1>&2;; esac done shift $((OPTIND-1)) #=============================================================================== # run the application in the jail #=============================================================================== # start pulseaudio #pulseaudio --start --daemonize 2>/dev/null # doas jexec into ubuntu and run the wrapper script to start the application doas jexec classic /usr/local/bin/wrapper-jail \ -u "${USER}" \ -d "DBUS_SESSION_BUS_ADDRESS=${DBUS_SESSION_BUS_ADDRESS}" \ -a "${app}" \ "${@}" #+end_src **** desktop entries #+begin_example ~/.local/share/applications #+end_example ***** firefox.desktop change exec line from #+begin_src conf Exec=firefox %U #+end_src to #+begin_src conf Exec=/usr/local/lib/firefox/firefox %U #+end_src #+begin_src conf [Desktop Entry] Version=1.0 Name=Firefox Comment=Browse the World Wide Web GenericName=Web Browser Keywords=Internet;WWW;Browser;Web;Explorer Exec=/usr/local/lib/firefox/firefox %U Terminal=false Type=Application Icon=firefox Categories=GNOME;GTK;Network;WebBrowser; MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;x-scheme-handler/chrome;video/webm;application/x-xpinstall; StartupNotify=true Actions=NewWindow;NewPrivateWindow; [Desktop Action NewWindow] Name=Open a New Window Exec=firefox -new-window [Desktop Action NewPrivateWindow] Name=Open a New Private Window Exec=firefox -private-window #+end_src ***** jailfox.desktop #+begin_src conf [Desktop Entry] Version=1.0 Name=Jailfox Comment=Browse the World Wide Web GenericName=Web Browser Keywords=Internet;WWW;Browser;Web;Explorer Exec=sh -c 'wrapper-freebsd -a firefox %U' Terminal=false Type=Application Icon=firefox Categories=GNOME;GTK;Network;WebBrowser; MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;x-scheme-handler/chrome;video/webm;application/x-xpinstall; StartupNotify=true Actions=NewWindow;NewPrivateWindow; [Desktop Action NewWindow] Name=Open a New Window Exec=firefox -new-window [Desktop Action NewPrivateWindow] Name=Open a New Private Window Exec=firefox -private-window #+end_src **** mimeapps.list #+begin_example ~/.config/mimeapps.list #+end_example #+begin_src conf [Default Applications] x-scheme-handler/http=jailfox.desktop x-scheme-handler/https=jailfox.desktop x-scheme-handler/chrome=jailfox.desktop text/html=jailfox.desktop application/x-extension-htm=jailfox.desktop application/x-extension-html=jailfox.desktop application/x-extension-shtml=jailfox.desktop application/xhtml+xml=jailfox.desktop application/x-extension-xhtml=jailfox.desktop application/x-extension-xht=jailfox.desktop [Added Associations] x-scheme-handler/http=jailfox.desktop; x-scheme-handler/https=jailfox.desktop; x-scheme-handler/chrome=jailfox.desktop; text/html=jailfox.desktop; application/x-extension-htm=jailfox.desktop; application/x-extension-html=jailfox.desktop; application/x-extension-shtml=jailfox.desktop; application/xhtml+xml=jailfox.desktop; application/x-extension-xhtml=jailfox.desktop; application/x-extension-xht=jailfox.desktop; #+end_src *** jail **** wrapper-jail #+begin_src sh #!/bin/sh #=============================================================================== # wrapper-jail #=============================================================================== #=============================================================================== # script usage #=============================================================================== usage () { # if argument passed to function echo it [ -z "${1}" ] || echo "! ${1}" # display help echo "\ # script usage $(basename "$0") -u ${USER}" exit 2 } #=============================================================================== # check the number of arguments passed to the script #=============================================================================== [ $# -gt 0 ] || usage "${WRONG_ARGS_ERR}" #=============================================================================== # getopts check the options passed to the script #=============================================================================== while getopts ':u:d:a:h' opt do case ${opt} in u) username="${OPTARG}";; d) dbus="${OPTARG}";; a) app="${OPTARG}";; h) usage;; \?) usage "${INVALID_OPT_ERR} ${OPTARG}" 1>&2;; :) usage "${INVALID_OPT_ERR} ${OPTARG} ${REQ_ARG_ERR}" 1>&2;; esac done shift $((OPTIND-1)) #=============================================================================== # switch to our user in the jail and start the application #=============================================================================== su "${username}" -c "${dbus} ${app} ${@}" 2>/dev/null #+end_src ** firefox oss audio To force a specific backend open #+begin_example about:config #+end_example and create #+begin_example media.cubeb.backend #+end_example set the option to string and #+begin_example oss #+end_example