Skip to content

Instantly share code, notes, and snippets.

@dotysan
Last active December 24, 2025 22:36
Show Gist options
  • Select an option

  • Save dotysan/1c4c1dff8f9a62ec7fb14950c456dfae to your computer and use it in GitHub Desktop.

Select an option

Save dotysan/1c4c1dff8f9a62ec7fb14950c456dfae to your computer and use it in GitHub Desktop.
Allow VS Code Server to run on older Linux

Allow VS Code Server to run on older Linux

https://code.visualstudio.com/docs/remote/faq#_can-i-run-vs-code-server-on-older-linux-distributions

The above "documentation" appears to be untested or verified. So here's an attempt to actually make crosstool-NG actually work.

Requirements

  • docker with buildx
  • PermitUserEnvironment yes in /etc/ssh/sshd_config

Installation

Run this on the older linux system you are remoting into via ssh:

  • ./build-sysroot.sh

It will build the sysroot in docker, then install it to ~/.vscode-sysroot, and finally update your ~/.ssh/environment.

#! /usr/bin/env bash
#
# Allow VSCode Server to run on older Linux.
#
set -e
set -u
# set -x
# what Ubuntu 24/noble release
NOBLEREL=20251013
# crosstool-NG
CTVER=1.28.0
# gcc/glibc
GCCVER=10.5.0
GLIBCVER=2.28
# patchelf
PEVER=0.18.0
ARCH=$(uname --machine)
printf -v NOW '%(%FT%H:%M)T'
main() {
if ! docker buildx ls |grep -q ^nocliplogs
then
docker buildx create --name nocliplogs \
--driver-opt env.BUILDKIT_STEP_LOG_MAX_SIZE=-1 \
--driver-opt env.BUILDKIT_STEP_LOG_MAX_SPEED=-1
fi
if [[ ! -e "$HOME/.vscode-sysroot" ]]
then
docker buildx build --builder nocliplogs --progress=plain \
--build-arg NOBLEREL="$NOBLEREL" \
--build-arg CTVER="$CTVER" \
--build-arg GCCVER="$GCCVER" \
--build-arg GLIBCVER="$GLIBCVER" \
--build-arg ARCH="$ARCH" \
--target=export-sysroot --output=type=local,dest="$HOME" .
fi
if [[ ! -x "$HOME/.vscode-sysroot/bin/patchelf" ]]
then
pushd "$HOME/.vscode-sysroot"
PEDL="https://github.com/NixOS/patchelf/releases/download/$PEVER/patchelf-$PEVER-$ARCH.tar.gz"
curl --location "$PEDL" |
tar --extract --gzip --wildcards '*/bin' '*/share'
popd
fi
if [[ -e "$HOME/.ssh/environment" ]]
then
cp -p "$HOME/.ssh/environment" "$HOME/.ssh/environment.$NOW"
grep -v VSCODE_SERVER_ "$HOME/.ssh/environment.$NOW" >"$HOME/.ssh/environment" ||:
fi
cat >>"$HOME/.ssh/environment" <<-EOF
VSCODE_SERVER_CUSTOM_GLIBC_LINKER="$HOME/.vscode-sysroot/lib/ld-linux-${ARCH/_/-}.so.${GLIBCVER::1}"
VSCODE_SERVER_CUSTOM_GLIBC_PATH="$HOME/.vscode-sysroot/usr/lib"
VSCODE_SERVER_PATCHELF_PATH="$HOME/.vscode-sysroot/bin/patchelf"
EOF
# shellcheck disable=SC1091
source "$HOME/.ssh/environment"
test -e "$VSCODE_SERVER_CUSTOM_GLIBC_LINKER" ||
echo "ERROR: Missing file VSCODE_SERVER_CUSTOM_GLIBC_LINKER: $VSCODE_SERVER_CUSTOM_GLIBC_LINKER"
test -d "$VSCODE_SERVER_CUSTOM_GLIBC_PATH" ||
echo "ERROR: Missing file VSCODE_SERVER_CUSTOM_GLIBC_PATH: $VSCODE_SERVER_CUSTOM_GLIBC_PATH"
test -x "$VSCODE_SERVER_PATCHELF_PATH" ||
echo "ERROR: Missing file VSCODE_SERVER_PATCHELF_PATH: $VSCODE_SERVER_PATCHELF_PATH"
if ! grep '^PermitUserEnvironment yes$' /etc/ssh/sshd_config
then
echo 'Make sure /etc/ssh/sshd_config has PermitUserEnvironment yes'
echo 'and sshd is restarted.'
fi
}
main
exit
# Required env vars:
# - NOBLEREL: The docker container release of Ubuntu 24LTS (noble).
# - CTVER: The crosstool-NG version.
# - GCCVER: The GNU Compiler Collection version.
# - GLIBCVER: The GNU C Library version.
# - ARCH: Machine archictecture.
ARG NOBLEREL
# ======================================================================
FROM ubuntu:noble-$NOBLEREL AS build-sysroot
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& \
apt-get install --yes --no-install-recommends \
automake \
bison \
bzip2 \
ca-certificates \
file \
flex \
g++ \
gawk \
help2man \
libncurses-dev \
libtool-bin \
make \
patch \
texinfo \
unzip \
wget \
xz-utils \
&& :
RUN --mount=type=cache,target=/home/ubuntu/build/downloads,sharing=locked \
--mount=type=cache,target=/home/ubuntu/build/.build,sharing=locked \
mkdir --parents /home/ubuntu/build/downloads \
&& \
chown --recursive ubuntu:ubuntu /home/ubuntu/build
# ----------------------------------------------------------------------
USER ubuntu
WORKDIR /home/ubuntu
ARG CTVER
ARG CTDL="http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-$CTVER.tar.xz"
RUN wget --output-document=- "$CTDL" |tar --extract --xz --directory="$HOME"
RUN cd "$HOME/crosstool-ng-$CTVER" \
&& \
./configure --prefix="$HOME" \
&& \
make -j \
&& \
make install
WORKDIR /home/ubuntu/build
ARG ARCH
ARG GCCVER
ARG GLIBCVER
ARG VLBA="https://raw.githubusercontent.com/microsoft/vscode-linux-build-agent"
ARG CONFDL="$VLBA/refs/heads/main/$ARCH-gcc-$GCCVER-glibc-$GLIBCVER.config"
RUN wget --output-document=.config "$CONFDL" \
&& \
echo "CT_PARALLEL_JOBS=$(nproc)" >>.config \
&& \
echo 'CT_DEBUG_GDB=n' >>.config \
&& \
$HOME/bin/ct-ng olddefconfig \
&& \
$HOME/bin/ct-ng build
RUN find "$ARCH-linux-gnu/$ARCH-linux-gnu/sysroot" \
-type d -print0 |xargs -r0 chmod u+w
# ======================================================================
FROM scratch AS export-sysroot
ARG ARCH
COPY --from=build-sysroot \
/home/ubuntu/build/$ARCH-linux-gnu/$ARCH-linux-gnu/sysroot \
/.vscode-sysroot
COPY --from=build-sysroot \
/home/ubuntu/build/.config /.vscode-sysroot/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment