Wanted to try out Serverless via nix-shell
so I looked it up, ran the command
nix-shell -v -p nodePackages.serverless
but it is hopelessly outdated, and it also doesn’t work:
$ serverless
#...
Error --------------------------------------------------
Error: EACCES: permission denied, open '/home/toraritte/shed/flox-aws-serverless/my-project/serverless.yml'
at Object.openSync (fs.js:462:3)
at Object.writeFileSync (fs.js:1384:35)
at renameYmlService (/nix/store/p8xhrzb9y62wrl3mgd517hgmfrbi6wl4-node_serverless-1.81.1/lib/node_modules/serverless/lib/utils/renameService.js:20:7)
at renameService (/nix/store/p8xhrzb9y62wrl3mgd517hgmfrbi6wl4-node_serverless-1.81.1/lib/node_modules/serverless/lib/utils/renameService.js:44:5)
at /nix/store/p8xhrzb9y62wrl3mgd517hgmfrbi6wl4-node_serverless-1.81.1/lib/node_modules/serverless/lib/utils/createFromTemplate.js:60:15
From previous event:
at /nix/store/p8xhrzb9y62wrl3mgd517hgmfrbi6wl4-node_serverless-1.81.1/lib/node_modules/serverless/lib/utils/createFromTemplate.js:59:26
at /nix/store/p8xhrzb9y62wrl3mgd517hgmfrbi6wl4-node_serverless-1.81.1/lib/node_modules/serverless/node_modules/graceful-fs/polyfills.js:243:20
at FSReqCallback.oncomplete (fs.js:156:23)
Get Support --------------------------------------------
Docs: docs.serverless.com
Bugs: github.com/serverless/serverless/issues
Issues: forum.serverless.com
Your Environment Information ---------------------------
Operating System: linux
Node Version: 12.21.0
Framework Version: 1.81.1
Plugin Version: 3.8.2
SDK Version: 2.3.1
Components Version: 2.34.9
Found this reddit post about this exact same issue, but I’m having trouble understanding the recommendations of this comment (quoted at the bottom), so I used this approach for now, but it is far from ideal:
# https://github.com/NixOS/nixpkgs/issues/3393#issuecomment-50330167
$ npm config set prefix ~/mutable_node_modules
$ nix-shell -p nodejs
[nix-shell:~/my/work/dir]$ npm install -g serverless
[nix-shell:~/my/work/dir]$ tree -L 2 ~/mutable_node_modules/
├── bin
│ ├── serverless -> ../lib/node\_modules/serverless/bin/serverless.js
│ └── sls -> ../lib/node\_modules/serverless/bin/serverless.js
└── lib
└── node\_modules
[nix-shell:~/my/work/dir]$ ~/mutable_node_modules/bin/serverless --version
Framework Core: 2.62.0
Plugin: 5.4.6
SDK: 4.3.0
Components: 3.17.1
...
For completeness sake, here’s the post mentioned above:
CSI_Tech_Dept·5m·edited 5m
I never used the provided serverless because it is updated very frequently and then there’s also plugins which I’m sure you’ll run into once this is resolved.
What I previously did was entering a shell with nodejs, and then using
npm
to install it, andnpx
to execute.Basically when I have
project.json
andproject-lock.json
files, I just runnpm ci
.After serverless merged PR that made it search for plugins in its own package directory things were simplified.
I’m using GitHub - nix-community/npmlock2nix: nixify npm based packages [maintainer=@andir] and something like this:
serverless_project = pkgs.runCommandLocal "serverless-env" {} '' mkdir $out cp ${./package.json} $out/package.json cp ${./package-lock.json} $out/package-lock.json ''; node_modules = npmlock2nix.node_modules { src = serverless_project; nativeBuildInputs = [ pkgs.bash pkgs.python38 ] ++ lib.optional pkgs.stdenv.hostPlatform.isDarwin pkgs.darwin.cctools; };
Then node_modules can be then included in mkShell for example (this should make
sls
command available in it). That makes Nix build the serverless and plugins (based on the lock file). The reason insrc
I’m not providing current dir, like./.
and instead creating the serverless_project derivation is because I like to keep these files together with my project and not make Nix rebuild whole thing when smallest change is made. Building nodejs in Nix is long process, because node has tons of tiny packages, something that Nix isn’t optimized to handle well.
… and the gentleperson was kind enough to provide the explicit steps as well:
CSI_Tech_Dept - 8m:
Here is an example of a full setup, of course you can customize it. For example instead of using niv you can use fetchFromGitHub etc. I use
niv
because I want things to be pinned, so I can get a reproducibility. I think flakes will replace that but I have not get around trying it yet.Anyway, here is how to set it up:
nix-shell -p niv nodejs niv init -b nixpkgs-unstable niv add tweag/npmlock2nix echo '{"name": "serverless-project", "version": "0.1.0", "private": true}' > package.json npm install --save-dev serverless serverless-step-functions rm -rf node_modules # kind of important as serverless will still use this directory if it exists exit
Create file shell.nix like this:
let sources = import ./nix/sources.nix; pkgs = import sources.nixpkgs { overlays = [ (self: super: { npmlock2nix = pkgs.callPackage sources.npmlock2nix {}; }) ]; }; # This ensures that serverless won't be rebuild every time you change # an unrelated file serverless_project = pkgs.runCommandLocal "serverless-env" {} '' mkdir $out cp ${./package.json} $out/package.json cp ${./package-lock.json} $out/package-lock.json ''; node_modules = pkgs.npmlock2nix.node_modules { src = serverless_project; nativeBuildInputs = with pkgs; [ bash python39 ] ++ pkgs.lib.optional pkgs.stdenv.hostPlatform.isDarwin pkgs.darwin.cctools; }; in pkgs.mkShell { packages = [ pkgs.niv pkgs.nodejs node_modules ]; }
Then execute:
nix-shell # this will take a while at first run sls --version
I highly recommend installing and configuring direnv for example
nix-env -iA nixpkgs.direnv
and configure it with one of integrations that caches. For exmaple nix-direnv (you can install it by invokingnix-env -iA nixpkgs.nix-direnv
(don’t forget that you still need to configure it).Then you can type:
direnv edit .
and place:
use nix
It will allow you to get your dev env by just entering the directory. If you need it to be refreshed do
touch shell.nix
.