Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read-only --extensions-dir break remote extension installation #151543

Open
bjornfor opened this issue Jun 8, 2022 · 17 comments
Open

Read-only --extensions-dir break remote extension installation #151543

bjornfor opened this issue Jun 8, 2022 · 17 comments
Assignees
Labels
extensions Issues concerning extensions under-discussion Issue is under discussion for relevance, priority, approach

Comments

@bjornfor
Copy link

bjornfor commented Jun 8, 2022

Does this issue occur when all extensions are disabled?: No. (The issue is about installing extensions on a remote system.)

  • VS Code Version: 1.67.2
  • OS Version: Ubuntu 18.04

Steps to Reproduce:

  1. Start VSCode with code --extensions-dir /path/to/read-only-tree-of-extensions. (Why read-only? Because that's how Nix does software deployment. This command just reproduces how vscode-with-extensions from Nixpkgs works.)
  2. Check that the extensions from the local tree is available.
  3. Open a remote ssh connection and try to install one of the local extensions to the remote system.
  4. VSCode errors out with Unable to write file '/home/$USER/.vscode-server/extensions/.6661fce6-c826-4679-8f01-8421850781b5/package.json' (EntryWriteLocked (FileSystemError): Error: EACCES: permission denied, open '/home/$USER/.vscode-server/extensions/.6661fce6-c826-4679-8f01-8421850781b5/package.json')

It seems VSCode first copies files from the local system /path/to/read-only-tree-of-extensions to ~/.vscode-server/ on the remote host and then tries to update ~/.vscode-server/extensions/.UUID/package.json (still on the remote), which fails because the file still has read-only permissions.

I tried to chmod the files myself, but it seems VSCode creates a new UUID every time, so it doesn't work.

When copying extensions/files from somewhere to $HOME on a remote machine, with the intention to update some of the files, I think it's reasonable to explicitly set the writeable bit on said files, after the copy operation completes.

@sandy081 sandy081 added bug Issue identified by VS Code Team member as probable bug extensions Issues concerning extensions labels Jun 10, 2022
@sandy081 sandy081 added this to the Backlog milestone Jun 10, 2022
@sandy081
Copy link
Member

This is probably because when we install a local extension into remote, we zip the local extension and unzip it on remote. I suspect that while zipping we are also including file modes.

@bjornfor
Copy link
Author

This seems like something a developer who is familiar with the code can fix quickly, right? Or alternatively, any hints as to where that code exists and I can try to fix it myself?

@sandy081
Copy link
Member

sandy081 commented Jul 25, 2022

I own this code and if you are interested to contribute the fix, you are welcome and appreciated. Here is the code pointer

async zip(extension: ILocalExtension): Promise<URI> {
this.logService.trace('ExtensionManagementService#zip', extension.identifier.id);
const files = await this.collectFiles(extension);
const location = await zip(joinPath(this.environmentService.tmpDir, generateUuid()).fsPath, files);
return URI.file(location);
}

@pwaller
Copy link

pwaller commented Aug 23, 2022

Any luck so far? Also hitting this and interested in a fix.

@isidorn isidorn added the *out-of-scope Posted issue is not in scope of VS Code label Dec 6, 2022
@vscodenpa
Copy link

We closed this issue because we don't plan to address it in the foreseeable future. If you disagree and feel that this issue is crucial: we are happy to listen and to reconsider.

If you wonder what we are up to, please see our roadmap and issue reporting guidelines.

Thanks for your understanding, and happy coding!

@vscodenpa vscodenpa closed this as not planned Won't fix, can't repro, duplicate, stale Dec 6, 2022
@bjornfor
Copy link
Author

bjornfor commented Dec 6, 2022

This is still important to me, please re-open. Without this there is no reproducible and/or offline installation option (AFAIK).

@bjornfor
Copy link
Author

bjornfor commented Jan 2, 2023

@isidorn: How can a (presumably) trivial fix to chmod +w some files before changing them be out of scope? I understand it doesn't have high priority for you, but please re-open.

@pwaller
Copy link

pwaller commented Jan 2, 2023

@isidorn Sorry for the noise, but seconding this for visibility. Please reopen. It means that when I use vscode on nixos to access a remote, things are broken when they shouldn't be, and it's not straightforward to fix as a user.

@isidorn
Copy link
Contributor

isidorn commented Jan 3, 2023

Let's reopen and for now leave on the backlog.

@isidorn isidorn reopened this Jan 3, 2023
@isidorn isidorn removed the *out-of-scope Posted issue is not in scope of VS Code label Jan 3, 2023
@newAM
Copy link

newAM commented Mar 6, 2023

This is my temporary hack until this gets fixed, run this on the server (requires pkgs.inotify-tools)

#!/usr/bin/env bash

inotifywait -m -q -r -e create --format '%w%f' "$HOME/.vscode-server/extensions" |
    while read -r path; do
        chmod +w "$path"
    done

It is racey, and does not work for extensions with many files, but for small extensions such as nix-ide it works.

@pwaller
Copy link

pwaller commented Apr 16, 2023

This workaround didn't work for me. I resorted to tarring up my local extensions directory, and extracting it over at .vscode-server/extensions on the remote, which worked.

What I don't understand is why updateMetadata is trying to write to package.json. Surely it can just leave that file alone? I don't think the solution is to modify the permission bits as they're represented in the zip.

@jasonprado
Copy link

I am hitting this now. If you manage VS Code with Nix you cannot install extensions into a remote SSH VS Code server. I'll try the workaround but I'd love a proper solution.

@tjni
Copy link

tjni commented Feb 22, 2025

@sandy081 Do you have suggestions for how to reproduce this locally?

I would like to tackle this and have done the following:

  1. Set up the development environment.
  2. Run a development instance locally through "Run Without Debugging".
  3. Started a TestResolver.
  4. Side loaded an VSIX extension.

But now I am stuck. The extension I loaded locally is probably not going to emulate the read-only extension directory.

Analyzing it from the code itself has also proved difficult. I can see from your pointers where zipping likely happens, and can find callers -- but I'm not sure if changing that code makes sense. I'd prefer to understand what VSCode is trying to write to the remote file system and what is triggering it to know what a proper fix is. However, there is no stack trace from the error, since it is being swallowed by fileService.writeFile.

@pwaller
Copy link

pwaller commented Feb 22, 2025

I can reproduce this today with the mkhl.direnv extensions where both the client and the remote are nixos machines where only the client is configured with home-manager:

{ pkgs }: {
  programs.vscode = {
    enable = true;
    extensions = with pkgs.vscode-extensions; [ mkhl.direnv ];
  };
}

What this does is (on the client) unpack mkhl into a directory with no read permisson and then put a symlink to it such that it is readable via a couple of symlinks:

~/.vscode/extensions/mkhl.direnv -> /nix/store/xf5gagci1nmgybkpx55pf8nr9amnzl2v-home-manager-files/.vscode/extensions/mkhl.direnv
/nix/store/xf5gagci1nmgybkpx55pf8nr9amnzl2v-home-manager-files/.vscode/extensions/mkhl.direnv -> /nix/store/9hpk80lirvbjvwkf1qvsxbwvvfjzazgy-vscode-extension-mkhl-direnv-0.17.0/share/vscode/extensions/mkhl.direnv

~/.vscode/extensions is an ordinary directory with 'normal' rwx permissons.
The paths under /nix/store/ have no write permissions. So to reproduce outside of nix, I would first install try installing direnv on the client, then chmod -wx -R ~/.vscode/extensions/mkhl.direnv. If that doesn't work, I would copy the directory for the extension (to anywhere else on the client) and then after making sure the permissions are (-r-xr-xr-x) and then symlink it into ~/.vscode/extensions.

One thing to note though is that I was unable to reproduce this reliably. It happened on the first attempt, but when I quit vscode and repeated the procedure it did not hit the problem. I was able to reproduce this by trying a second package though (tamasfe.even-better-toml). A different extension I tried didn't hit the problem at all.

@sandy081
Copy link
Member

sandy081 commented Mar 7, 2025

Start VSCode with code --extensions-dir /path/to/read-only-tree-of-extensions. (Why read-only? Because that's how Nix does software deployment. This command just reproduces how vscode-with-extensions from Nixpkgs works.)

@bjornfor I am wondering, how you could install extensions in to this folder if it is read only?

@sandy081 sandy081 added under-discussion Issue is under discussion for relevance, priority, approach and removed bug Issue identified by VS Code Team member as probable bug labels Mar 7, 2025
@sandy081 sandy081 removed this from the Backlog milestone Mar 7, 2025
@bjornfor
Copy link
Author

bjornfor commented Mar 7, 2025

Start VSCode with code --extensions-dir /path/to/read-only-tree-of-extensions. (Why read-only? Because that's how Nix does software deployment. This command just reproduces how vscode-with-extensions from Nixpkgs works.)

@bjornfor I am wondering, how you could install extensions in to this folder if it is read only?

The (read-only) extensions directory is managed by the Nix package manager. So I don't put stuff in there manually, I just declare what plugins I want in a Nix file and let it build/realize that configuration.

Here's a stand-alone example that can be used on any Linux distro:

# file vscode.nix
let
  # branch nixos-24.11 @ 2025-03-05
  nixpkgs = builtins.fetchTarball {
    url = "https://github.com/NixOS/nixpkgs/archive/48913d8f9127ea6530a2a2f1bd4daa1b8685d8a3.tar.gz";
    sha256 = "0h3yzgn0mw74039xaqpvhvd2f924d923ax3kb8gh79f2m1jgla6i";
  };
  pkgs = import nixpkgs { config = {}; overlays = []; };
in
  with pkgs;
  vscode-with-extensions.override {
    vscodeExtensions = [
      vscode-extensions.asciidoctor.asciidoctor-vscode
      vscode-extensions.eamodio.gitlens
      vscode-extensions.ms-vscode.cmake-tools
    ];
  }

Install it with NIXPKGS_ALLOW_UNFREE=1 nix-env -i -f ./vscode.nix and observe that the result is a code script that runs the actual code program with the declared extensions in a read-only directory:

$ cat $(which code)
#! /nix/store/8vpg72ik2kgxfj05lc56hkqrdrfl8xi9-bash-5.2p37/bin/bash -e
exec "/nix/store/09k7b0bhiz2rjd9980lwjj22750jrm58-vscode-1.97.2/bin/code"  --extensions-dir /nix/store/129s8jlpljzfkfhclmzbma9nm2j6g46j-vscode-extensions/share/vscode/extensions "$@" 

See perms/ownership of the directory:

$ ls -ld /nix/store/129s8jlpljzfkfhclmzbma9nm2j6g46j-vscode-extensions
dr-xr-xr-x 3 root root 4096 Jan  1  1970 /nix/store/129s8jlpljzfkfhclmzbma9nm2j6g46j-vscode-extensions

@pwaller
Copy link

pwaller commented Mar 7, 2025

Yeah, and the fact it is read only is a non-negotiable feature of the nix store; things are put there to be read only, so you can be confident it has not been interfered with and you can reproduce different configurations. This enables answering questions like 'did my configuration change break something', across the whole system, because you can still run exactly the old configuration without worrying too much if you missed some file somewhere, with respect to things like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extensions Issues concerning extensions under-discussion Issue is under discussion for relevance, priority, approach
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants