Nvm-windows: NTFS junctions

Created on 7 Aug 2015  路  11Comments  路  Source: coreybutler/nvm-windows

Would it be feasible to add support for using NTFS junctions rather than mklink for swapping out the in-use version of node?

Junctions are great because they do not require elevated permissions, which would allow nvm-windows to be used on (effectively) headless machines, such as build agents. The disadvantage is that they cannot be created across drive letters, but this is an acceptable limitation.

Maybe this could be implemented as a configuration flag and disabled by default. Thoughts on that?

enhancement request

Most helpful comment

I'm reposting this here since I inadvertantly merged it into the wiki some time ago. Written by Burt Harris:

Elevator pitch for Junction Points

On Windows, a NTFS junction point can generally be created and deleted without any special privileges; junction points were created as a safer alternative to directory symlinks. If nvm-windows switched its implementation to use NTFS junction points, it could would be simpler, more usable, and present lower security risks.

The demo

Using NTFS junctions is really simple, this should give you the idea:

C:\demo>dir
 Volume in drive C has no label.
 Volume Serial Number is 4C7F-6408

 Directory of C:\demo

07/09/2016  02:34 PM    <DIR>          .
07/09/2016  02:34 PM    <DIR>          ..
07/09/2016  02:31 PM    <DIR>          version.1
07/09/2016  02:28 PM    <DIR>          version.2
               0 File(s)              0 bytes
               4 Dir(s)  350,868,033,536 bytes free

C:\demo>mklink /j nodejs version.1
Junction created for nodejs <<===>> version.1

C:\demo>type nodejs\test.txt
This is version 1's test.txt

C:\demo>
C:\demo>rd nodejs

C:\demo>mklink /j nodejs version.2
Junction created for nodejs <<===>> version.2

C:\demo>type nodejs\test.txt
This is version 2's test.txt

As can be seen below, a junction point presents a much more understandable directory listing

C:\demo>dir
 Volume in drive C has no label.
 Volume Serial Number is 4C7F-6408

 Directory of C:\demo

07/09/2016  02:35 PM    <DIR>          .
07/09/2016  02:35 PM    <DIR>          ..
07/09/2016  02:35 PM    <JUNCTION>     nodejs [C:\demo\version.2]
07/09/2016  02:31 PM    <DIR>          version.1
07/09/2016  02:28 PM    <DIR>          version.2
               0 File(s)              0 bytes
               5 Dir(s)  350,868,033,536 bytes free

Completing the picture

Ideally, one user on a machine installing or removing nvm-windows or Node.js versions using the tool shouldn't effect any other user's experience on the same machine. For this reason, installing junctions in C:\Program Files would still require and administrator. But per-user tools can generally be installed under the path in the APPDATA environment variable, and that's where the per-user nvm junction point should be located. Similarly user-specific NVM_HOME, NVM_SYMLINK and PATH environment variables are preferable to machine-wide ones.

All 11 comments

Another point in favour of junctions: they are used by npm on Windows when using npm link, so it is already common in the Windows/node world.

I'll consider it for the next version (which I'm working on as time allows). I almost did this for the first releases, but I had a number of requests for cross-drive support, so I'm not sure if this is an acceptable limitation... but the idea of keeping it behind a flag is viable.

symbolic links are more flexible in the targets they support. see mklink.

symbolic links are more flexible in the targets they support. see mklink.

some of are using workin machines though that restrict certain admin actions such as mklink

@edclement Not good for Dev PCs at all. Fight for freedom :)

@edclement - there is literally nothing that can be done if mklink isn't allowed by enterprise policy. I believe this would also affect npm. The entire premise of this project is based on the use of linked directories.

@coreybutler - I use npm link often. It actually uses junctions. It may be the case that it falls back to using windows junctions when it can't create a symlink. Not sure. I feel like nvm should do the same.

@edclement, @coreybutler I'm reasonably sure that npm link uses junctions by default (which can be done with mklink /J, btw). Otherwise, linking would have to be done in an elevated console or npm would ship with an elevation script, similar to this project.

there is literally nothing that can be done if mklink isn't allowed by enterprise policy

This is true, but I would be surprised if the mklink executable itself was disallowed. It's just the /D (create symbolic link) option that requires administrator privileges.

In my original issue description, I suggested toggling use of junction points with a flag, but I now think it should be the default option whenever the source & target drive letters are the same. But I'd be happy either way 馃槃

It does look like npm is using junctions for links, and it also looks like npm suffers from the same issue nvm4w would if it were installed on a separate partition.

I still like the idea of toggling, and I like @jgoz's follow up comment about checking the drive letters. I'm 99% sure I'll implement at least a toggle/flag if I can't find a better alternative to mklink.

modified elevate.cmd as a quick fix if you really need it

@setlocal
@echo off
set CMD=%*
set APP=%1

set newCMD=%CMD:mklink /d=mklink /j%
IF "%newCMD%" == "%CMD%" ( 
  start wscript //nologo "%~dpn0.vbs" %* & exit 
) ELSE ( 
  %newCMD%
)

I'm reposting this here since I inadvertantly merged it into the wiki some time ago. Written by Burt Harris:

Elevator pitch for Junction Points

On Windows, a NTFS junction point can generally be created and deleted without any special privileges; junction points were created as a safer alternative to directory symlinks. If nvm-windows switched its implementation to use NTFS junction points, it could would be simpler, more usable, and present lower security risks.

The demo

Using NTFS junctions is really simple, this should give you the idea:

C:\demo>dir
 Volume in drive C has no label.
 Volume Serial Number is 4C7F-6408

 Directory of C:\demo

07/09/2016  02:34 PM    <DIR>          .
07/09/2016  02:34 PM    <DIR>          ..
07/09/2016  02:31 PM    <DIR>          version.1
07/09/2016  02:28 PM    <DIR>          version.2
               0 File(s)              0 bytes
               4 Dir(s)  350,868,033,536 bytes free

C:\demo>mklink /j nodejs version.1
Junction created for nodejs <<===>> version.1

C:\demo>type nodejs\test.txt
This is version 1's test.txt

C:\demo>
C:\demo>rd nodejs

C:\demo>mklink /j nodejs version.2
Junction created for nodejs <<===>> version.2

C:\demo>type nodejs\test.txt
This is version 2's test.txt

As can be seen below, a junction point presents a much more understandable directory listing

C:\demo>dir
 Volume in drive C has no label.
 Volume Serial Number is 4C7F-6408

 Directory of C:\demo

07/09/2016  02:35 PM    <DIR>          .
07/09/2016  02:35 PM    <DIR>          ..
07/09/2016  02:35 PM    <JUNCTION>     nodejs [C:\demo\version.2]
07/09/2016  02:31 PM    <DIR>          version.1
07/09/2016  02:28 PM    <DIR>          version.2
               0 File(s)              0 bytes
               5 Dir(s)  350,868,033,536 bytes free

Completing the picture

Ideally, one user on a machine installing or removing nvm-windows or Node.js versions using the tool shouldn't effect any other user's experience on the same machine. For this reason, installing junctions in C:\Program Files would still require and administrator. But per-user tools can generally be installed under the path in the APPDATA environment variable, and that's where the per-user nvm junction point should be located. Similarly user-specific NVM_HOME, NVM_SYMLINK and PATH environment variables are preferable to machine-wide ones.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

keylowgee picture keylowgee  路  6Comments

snerte picture snerte  路  5Comments

webspecialist picture webspecialist  路  5Comments

martijnsenden picture martijnsenden  路  3Comments

Deilan picture Deilan  路  4Comments