VS Code Remote-SSH Compatibility on Legacy Systems

VS Code Remote-SSH Compatibility on Legacy Systems (Ubuntu 16, glibc 2.23)

Problem: On Ubuntu 16 (glibc 2.23), Remote-SSH fails during VS Code Server installation/startup due to glibc version check failure.
Solution: Build a custom glibc 2.28 sysroot + statically-linked patchelf. During installation, override the rpath and interpreter of VS Code Server's node binary to force it to use the custom glibc. Use hooks to ensure non-interactive scripts also load the three required environment variables.

Overview

1) Build glibc 2.28 sysroot (including dynamic linker and libraries) using Crosstool-NG.
2) Compile patchelf ≥ 0.18 with static linking to work with old glibc.
3) Inject three environment variables (linker, lib path, patchelf) via VS Code's remote.SSH.serverEnv.
4) Add hooks on the remote end: source the environment file before VS Code Server installation scripts run, ensuring both checks and patches use the custom glibc.
5) On first connection or version update, patch the entry scripts in the current server directory to load hooks and execute patchelf.

Detailed Steps

1) Install Dependencies

apt-get update
apt-get install -y gcc g++ gperf bison flex texinfo help2man make libncurses5-dev \
python3-dev autoconf automake libtool libtool-bin gawk wget bzip2 xz-utils unzip \
patch rsync meson ninja-build

2) Install Crosstool-NG 1.26.0

cd <workdir>
wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.26.0.tar.bz2
tar -xjf crosstool-ng-1.26.0.tar.bz2
cd crosstool-ng-1.26.0
./configure --prefix=<workdir>/crosstool-ng-1.26.0/out
make -j$(nproc) && make install
# Tool path example: <workdir>/crosstool-ng-1.26.0/out/bin/ct-ng

3) Prepare and Build Sample Configuration (e.g., x86_64-ol8u6-linux-gnu)

mkdir -p <workdir>/toolchain-dir
cd <workdir>/toolchain-dir
# Place .config (example: x86_64-ol8u6-linux-gnu)
PATH=<workdir>/crosstool-ng-1.26.0/out/bin:$PATH ct-ng build   # Re-run if timeout occurs

Output directory example: <workdir>/x-tools/x86_64-ol8u6-linux-gnu, containing:

  • Dynamic linker: .../sysroot/lib64/ld-linux-x86-64.so.2
  • Library path: .../sysroot/lib64:.../sysroot/usr/lib64

4) (Optional) Package/Distribute sysroot

tar -C <workdir> -czf /tmp/vscode-glibc-2.28.tgz \
    x-tools/x86_64-ol8u6-linux-gnu patchelf-0.18.0/out/bin/patchelf
scp /tmp/vscode-glibc-2.28.tgz <remote>:/path/
ssh <remote> 'mkdir -p /path/vscode-glibc-2.28 && tar -xzf /path/vscode-glibc-2.28.tgz -C /path/vscode-glibc-2.28'

5) Compile Static patchelf 0.18.0

apt-get install -y musl-tools   # Provides static toolchain
cd <workdir>
rm -rf patchelf-0.18.0-static
mkdir -p patchelf-0.18.0-static
tar -xjf patchelf-0.18.0.tar.bz2 -C patchelf-0.18.0-static --strip-components=1
cd patchelf-0.18.0-static
./configure --prefix=<workdir>/patchelf-0.18.0-static/out \
  LDFLAGS='-static -static-libstdc++ -static-libgcc'
make -j$(nproc) && make install
# Output: <workdir>/patchelf-0.18.0-static/out/bin/patchelf
# Verify: ldd patchelf → "not a dynamic executable"

Note: A dynamically compiled patchelf would bind to host glibc 2.23 and fail during installation/patch due to missing symbols. Static linking is required to eliminate host libc dependency.

6) Remote Deployment Example

  • Transfer sysroot and static patchelf to the same directory on the remote machine.
  • To replace patchelf: overwrite the remote patchelf path with the static version.

7) Environment Variables (Three Essential)

Define on remote machine (export or write to env file):

export VSCODE_SERVER_CUSTOM_GLIBC_LINKER="<sysroot>/lib64/ld-linux-x86-64.so.2"
export VSCODE_SERVER_CUSTOM_GLIBC_PATH="<sysroot>/lib64:<sysroot>/usr/lib64"
export VSCODE_SERVER_PATCHELF_PATH="<path-to-static-patchelf>"

Local VS Code settings.json:

"remote.SSH.serverEnv": {
  "VSCODE_SERVER_CUSTOM_GLIBC_LINKER": "<sysroot>/lib64/ld-linux-x86-64.so.2",
  "VSCODE_SERVER_CUSTOM_GLIBC_PATH": "<sysroot>/lib64:<sysroot>/usr/lib64",
  "VSCODE_SERVER_PATCHELF_PATH": "<path-to-static-patchelf>"
}

8) Hook Strategy (Enables Non-Interactive Scripts to Read Variables)

1) Create ~/.vscode-server/server-env-setup on remote, containing the three exports above.
2) Insert at the beginning of ~/.vscode-server/bin/<commit>/bin/helpers/check-requirements.sh and ~/.vscode-server/bin/<commit>/bin/code-server for each VS Code Server version:

   if [ -f "$HOME/.vscode-server/server-env-setup" ]; then
       . "$HOME/.vscode-server/server-env-setup"
   fi

This ensures both self-checks and patchelf operations use the custom sysroot and static patchelf.

9) Key Verification

  • ld-linux-x86-64.so.2 --version shows glibc 2.28.
  • ldd <static-patchelf> outputs "not a dynamic executable".
  • When connecting via Remote-SSH, VS Code Server automatically uses the above variables and patchelf for self-patching during installation; repeat step 8 for new commit versions.

中文版 / Chinese Version

VS Code Remote-SSH 在低版本系统上的兼容方案 (Ubuntu 16, glibc 2.23)

现象:在 Ubuntu 16(glibc 2.23)上,Remote-SSH 安装/启动 VS Code Server 时自检 glibc 版本直接失败。
思路:自建 glibc 2.28 sysroot + 静态 patchelf,安装阶段对 VS Code Server 的 node 做 rpath 与 interpreter 覆盖,强制走自定义 glibc。通过 hook 确保非交互脚本也加载这三条环境变量。

总体思路

1) 用 Crosstool-NG 构建 glibc 2.28 sysroot(含动态链接器与库)。
2) 编译 patchelf ≥ 0.18,必须静态链接以适配老 glibc。
3) VS Code 端用 remote.SSH.serverEnv 注入三条变量(linker、lib path、patchelf)。
4) 远程端加 hook:VS Code Server 安装脚本启动前 source 环境文件,保证检查与 patch 都用自定义 glibc。
5) 首次连接或版本更新时,对当前 server 目录的入口脚本打 patch,使其加载 hook 并执行 patchelf。

详细流程

1) 安装依赖

apt-get update
apt-get install -y gcc g++ gperf bison flex texinfo help2man make libncurses5-dev \
python3-dev autoconf automake libtool libtool-bin gawk wget bzip2 xz-utils unzip \
patch rsync meson ninja-build

2) 安装 Crosstool-NG 1.26.0

cd <workdir>
wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.26.0.tar.bz2
tar -xjf crosstool-ng-1.26.0.tar.bz2
cd crosstool-ng-1.26.0
./configure --prefix=<workdir>/crosstool-ng-1.26.0/out
make -j$(nproc) && make install
# 工具路径示例:<workdir>/crosstool-ng-1.26.0/out/bin/ct-ng

3) 准备并构建样例配置(如 x86_64-ol8u6-linux-gnu)

mkdir -p <workdir>/toolchain-dir
cd <workdir>/toolchain-dir
# 放置 .config(示例 x86_64-ol8u6-linux-gnu)
PATH=<workdir>/crosstool-ng-1.26.0/out/bin:$PATH ct-ng build   # 如超时可重跑

输出目录示例:<workdir>/x-tools/x86_64-ol8u6-linux-gnu,包含:

  • 动态链接器:.../sysroot/lib64/ld-linux-x86-64.so.2
  • 库路径:.../sysroot/lib64:.../sysroot/usr/lib64

4)(可选)打包/分发 sysroot

tar -C <workdir> -czf /tmp/vscode-glibc-2.28.tgz \
    x-tools/x86_64-ol8u6-linux-gnu patchelf-0.18.0/out/bin/patchelf
scp /tmp/vscode-glibc-2.28.tgz <remote>:/path/
ssh <remote> 'mkdir -p /path/vscode-glibc-2.28 && tar -xzf /path/vscode-glibc-2.28.tgz -C /path/vscode-glibc-2.28'

5) 编译 patchelf 0.18.0 静态版

apt-get install -y musl-tools   # 提供静态工具链
cd <workdir>
rm -rf patchelf-0.18.0-static
mkdir -p patchelf-0.18.0-static
tar -xjf patchelf-0.18.0.tar.bz2 -C patchelf-0.18.0-static --strip-components=1
cd patchelf-0.18.0-static
./configure --prefix=<workdir>/patchelf-0.18.0-static/out \
  LDFLAGS='-static -static-libstdc++ -static-libgcc'
make -j$(nproc) && make install
# 产物:<workdir>/patchelf-0.18.0-static/out/bin/patchelf
# 验证:ldd patchelf → "not a dynamic executable"

说明:动态编译的 patchelf 会绑定宿主 glibc 2.23,安装/patch 阶段会因缺少新符号直接报错,必须使用静态版以消除宿主 libc 依赖。

6) 远端部署示例

  • 将 sysroot 与静态 patchelf 传到远端同一目录下。
  • 如需替换 patchelf:用静态版覆盖远端的 patchelf 路径。

7) 环境变量(三件套)

远端机器定义(export 或写入 env 文件):

export VSCODE_SERVER_CUSTOM_GLIBC_LINKER="<sysroot>/lib64/ld-linux-x86-64.so.2"
export VSCODE_SERVER_CUSTOM_GLIBC_PATH="<sysroot>/lib64:<sysroot>/usr/lib64"
export VSCODE_SERVER_PATCHELF_PATH="<path-to-static-patchelf>"

本地 VS Code settings.json

"remote.SSH.serverEnv": {
  "VSCODE_SERVER_CUSTOM_GLIBC_LINKER": "<sysroot>/lib64/ld-linux-x86-64.so.2",
  "VSCODE_SERVER_CUSTOM_GLIBC_PATH": "<sysroot>/lib64:<sysroot>/usr/lib64",
  "VSCODE_SERVER_PATCHELF_PATH": "<path-to-static-patchelf>"
}

8) Hook 策略(非交互脚本也能读到变量)

1) 在远端创建 ~/.vscode-server/server-env-setup,写入上述三条 export。
2) 在每个 VS Code Server 版本目录 ~/.vscode-server/bin/<commit>/bin/helpers/check-requirements.sh~/.vscode-server/bin/<commit>/bin/code-server 开头插入:

   if [ -f "$HOME/.vscode-server/server-env-setup" ]; then
       . "$HOME/.vscode-server/server-env-setup"
   fi

这样自检与 patchelf 操作都会使用自定义 sysroot 与静态 patchelf。

9) 关键验证

  • ld-linux-x86-64.so.2 --version 显示 glibc 2.28。
  • ldd <static-patchelf> 输出 "not a dynamic executable"。
  • 连接 Remote-SSH 时,VS Code Server 在安装阶段会自动用上述变量和 patchelf 完成自修补;若下发新 commit 版本,重复第 8 步为新目录添加 hook。

Ref

  1. https://code.visualstudio.com/docs/remote/faq#_can-i-run-vs-code-server-on-older-linux-distributions
  2. https://github.com/Techy-Wu/vscode-server-toolchain-workaround

Search

    Table of Contents