25 jun 2024
this post is about how to connect visual studio code with proper language support and code completion for rust to a nix based toolchain inside nixos-wsl. this setup let’s me surf the code like a html document!
the open source edition of microsoft visual studio code called vscodium is being used. it features an implementation for remote code access via ssh, which is also open source, and is called open-remote-ssh.
note: for visual studio code this plugin called ms-vscode-remote.remote-ssh is closed source but should work for this setup, too.
there are several popular similar concepts:
to learn about the vscodium implementation of ssh remote work i’ve created this shell-wrapper on the nixos-wsl instance.
{ config, lib, pkgs, fetchurl, fetchFromGitHub, ... }:
let
rust_overlay = import (fetchTarball "https://github.com/oxalica/rust-overlay/archive/master.tar.gz");
pkgs = import <nixpkgs> { overlays = [ rust_overlay ]; };
rust = pkgs.rust-bin.stable.latest.default.override {
extensions = [ "rustfmt" "clippy" ];
targets = [
"wasm32-unknown-unknown"
];
};
in
{
imports = [
# include NixOS-WSL modules
nixos-wsl/modules>
<(fetchTarball "https://github.com/nix-community/nixos-vscode-server/tarball/master")
];
users.users.nixos.shell = /home/nixos/klick/bash-wrapper.sh;
nix.settings.experimental-features = [ "nix-command" "flakes" ];
wsl.enable = true;
services.vscode-server.enable = true;
environment.systemPackages = with pkgs; [ vim git tig dfc wineWowPackages.base jq direnv htop ];
services.openssh = {
enable = true;
};
system.stateVersion = "23.05"; # Did you read the comment?
}
#!/run/current-system/sw/bin/bash
# NOTE: each change requires a 'nixos-rebuild switch' run to become active
cd /home/nixos/klick
is_interactive() {
# A shell is considered interactive if it has a terminal associated with standard input
if [ -t 0 ]; then
return 0
else
return 1
fi
}
# Main execution starts here
# Check if the shell is interactive
if is_interactive; then
# If the shell is interactive, call bash in interactive mode
#exec /run/current-system/sw/bin/bash
echo "interactive"
exec /run/current-system/sw/bin/nix develop --command /run/current-system/sw/bin/bash
else
# If the shell is non-interactive, pass all arguments to bash
#exec /run/current-system/sw/bin/bash "$@"
echo "none interactive"
exec /run/current-system/sw/bin/nix develop --command /run/current-system/sw/bin/bash -c "$@"
fi
once everything is installed, do a ssh nixos
and check
that you are inside the nix develop environment:
[nixos@nixos:~/klick]$ rustc --version
rustc 1.79.0 (129f3b996 2024-06-10)
then add this ssh remote into vscodium’s remote extension and load the project.
inside the development console to the same
rustc --version
check.
using vscodium
we could create a way to
automatically load the nix development
environment, if detected.
on nixos this is set as default:
declare -x SHELL="/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/bash"
and resolved using this:
$SHELL
but if
that’s unset it will use node’s userInfo().shell
which will
read /etc/passwd
, see microsoft/vscode.see also discussion at https://github.com/jeanp413/open-remote-ssh/issues/159
using a .vscode-nix.toml
file in the source directory we
could help vscode to use the correct shell environment:
.vscode-nix.toml
, and if found, use that command inside the
SHELL.vscode-nix.toml
# .vscode-nix.toml
# This configuration file helps Visual Studio Code determine the shell to use for different Nix environments.
# Specify the shell to use for Nix Flake's 'nix develop'
[shell]
name = "nix flake"
command = "nix develop"
# Specify the shell to use for Devenv
#[shell]
#name = "devenv"
#command = "devenv shell"
# Specify the shell to use for Direnv
#[shell]
#name = "direnv"
#command = "direnv allow && direnv exec . $SHELL"
# Specify the shell to use for Nix Shell
#[shell]
#name = "nix-shell"
#command = "nix-shell"
# Specify the shell to use for flox.dev
#[shell]
#name = "flox"
#command = "flox activate"
so when vscode wants to start a shell, it will call the
command
instead of
/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/bash
.
this hack shows the huge potential of using nix develop
in combination to powerful remote IDEs.
in fact, the proposed idea here is very similar to direnv-in-vscode, except it does not require a specific program to be running on the destination host or a specific vscode plugin as direnv-vscode.
i created a feature request for vscode: https://github.com/microsoft/vscode/issues/218361.