Skip to content

Instantly share code, notes, and snippets.

@mateuszkwiatkowski
Last active May 11, 2024 10:58
Show Gist options
  • Save mateuszkwiatkowski/ce486d692b4cb18afc2c8c68dcfe8602 to your computer and use it in GitHub Desktop.
Save mateuszkwiatkowski/ce486d692b4cb18afc2c8c68dcfe8602 to your computer and use it in GitHub Desktop.
Configure FreeBSD to work with VScode's remote ssh extension

This procedure was tested on FreeBSD-CURRENT build from d8819d88af52.

  1. Enable linuxulator and install linux userland:

    # sysrc linux_enable="YES"
    # service linux start
    # pkg install linux_base-c7
    

    Test it:

    $ /compat/linux/usr/bin/uname -a
    Linux monster-1 4.4.0 FreeBSD 14.0-CURRENT #1 main-n254392-d8819d88af52: Wed Apr  6 22 x86_64 x86_64 x86_64 GNU/Linux
    

    For more details on linuxulator setup please refer to handbook.

  2. remote-ssh seem to ignore bash config files so we need to change $PATH in /etc/login.conf or send custom env with SetEnv directive in ssh_config. Choose which fits you better.

    Confiugure /etc/login.conf

    By default it's class default, we need to give priority to linux binaries: :path=/compat/linux/usr/sbin /compat/linux/usr/bin /sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin ~/bin:\ rebuild CAP database: cap_mkdb /etc/login.conf

    Or add this to your ssh config (~/.ssh/config)

    Host your-freebsd.box
      SetEnv PATH="/compat/linux/usr/sbin:/compat/linux/usr/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"
    
  3. Set you normal PATH for your every day use in your shell's config file (.bashrc od .zshrc, etc)

  4. Connect to your FreeBSD box with VScode's remote SSH extension!

@willtanium
Copy link

@oliver-giersch thank you for this fix.
If I could add one more thing that I am doing on my computer, Instead of adding the entries into /etc/fstab another option would be to create a script that would make the /compat/debian get started up by debian_enable="YES"

#!/bin/sh
#
# PROVIDE: debian
# REQUIRE: archdep mountlate
# KEYWORD: nojail
#

. /etc/rc.subr

name="debian"
desc="Debian for FreeBSD Linux Binary Compatibility"
rcvar="debian_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/.."` ]
}

debian_start()
{
  local _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/debian/sbin/ldconfigDisabled" ]; then
    _tmpdir=`mktemp -d -t linux-ldconfig`
    /compat/debian/sbin/ldconfig -C ${_tmpdir}/ld.so.cache
    if ! cmp -s "${_tmpdir}/ld.so.cache" "/compat/debian/etc/ld.so.cache"; then
      cat "${_tmpdir}/ld.so.cache" > "/compat/debian/etc/ld.so.cache"
    fi
    rm -rf ${_tmpdir}
  fi
  load_kld pty
  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/debian"
  unmounted "/compat/debian/dev" && (mount -o nocover -t devfs devfs "/compat/debian/dev" || exit 1)
  unmounted "/compat/debian/dev/fd" && (mount -o nocover,linrdlnk -t fdescfs fdescfs "/compat/debian/dev/fd" || exit 1)
  unmounted "/compat/debian/dev/shm" && (mount -o nocover,mode=1777 -t tmpfs tmpfs "/compat/debian/dev/shm" || exit 1)
  unmounted "/compat/debian/home" && (mount -t nullfs /home "/compat/debian/home" || exit 1)
  unmounted "/compat/debian/proc" && (mount -o nocover -t linprocfs linprocfs "/compat/debian/proc" || exit 1)
  unmounted "/compat/debian/sys" && (mount -o nocover -t linsysfs linsysfs "/compat/debian/sys" || exit 1)
  unmounted "/compat/debian/tmp" && (mount -t nullfs /tmp "/compat/debian/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"

This can be written inside /usr/local/etc/rc.d/debian and made executable with chmod +x /usr/local/etc/rc.d/debian

@morganwdavis
Copy link

Instead of adding the entries into /etc/fstab another option would be to create a script ...

@willtanium This is great. Thank you for the inspiration. This also solves several other messy changes in earlier solutions (some that could have prevented it from booting if conditions caused startup failures).

I was inspired to work on this again today after the recent VS Code update for March (v. 1.88) which broke my remote SSH connections yet again. After incorporating your rc.d script, updating to Debian 12.5, and doing some additional testing to pare down the number of changes to the least I could find that still allowed remote SSH to work, I ended up making a repo to document it.

VS Code Server and Remote SSH on FreeBSD

This rolls up all the steps into a simpler set of tasks, with the fewest intrusive changes to key configuration files in FreeBSD. I hope others find this helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment