Deploy NodeJS application from git automatically

Hello there,

I spent the last few days moving my server infrastructure to NixOS, and so far I’m very happy with it. However, I’m unsure how to deploy some of my applications.
My goal here is to reduce the necessary maintenance to a manageable level, as I was not able to keep up with updates and fixes with the approach I used before (systemd-nspawn containers on Arch).

So…: My first application is NodeJS-based. I packaged the current version using node2nix, but I wondered, since all the information is in the package.json and lockfile, would it be possible to do that at build time? Basically, can I just point to a git commit and let it generate derivations for all the dependencies of that commit, without running node2nix for every update manually?
If that’s not possible, what are the practical disadvantages of including all the NodeJS dependencies in the application’s derivation, by running npm install --production at build time?

The thing I would like to achieve in the end is the following: When there’s an update of the upstream application, I have to update the revision in the system configuration, and run nixos- rebuild switch to update.

Thanks in advance

How I solved this:

{ config, pkgs, ... }:

let
  yarn2nix = import (pkgs.fetchFromGitHub {
    owner = "moretea";
    repo = "yarn2nix";
    rev = "780e33a07fd821e09ab5b05223ddb4ca15ac663f";
    sha256 = "1f83cr9qgk95g3571ps644rvgfzv2i4i7532q8pg405s4q5ada3h";
  }) {
    inherit pkgs;
    nodejs = pkgs.nodejs-10_x;
  };

  hafas-client-rpc = yarn2nix.mkYarnPackage {
    src = pkgs.fetchFromGitHub {
      owner = "petabyteboy";
      repo = "hafas-client-rpc";
      rev = "955e776a984cb73f1d31d517963d0b8934f46621";
      sha256 = "0ncm45w3zrgbxxbman4j3j35w063x3jg7ah3lb59qn4g7z7dpx00";
    };
    # hafas-client has a post-install script to generate a random id for the installation
    # yarn ignores this script, and to get reproducible results, we save a fixed id
    pkgConfig.hafas-client.postInstall = ''
      echo '"foo"' > id.json
    '';
  };

in {
  systemd.services.hafas-client-rpc-http = {
    serviceConfig = {
      ExecStart = "${pkgs.nodejs-10_x}/bin/node ${hafas-client-rpc}/bin/hafas-client-rpc";
      Restart = "always";
      RestartSec = "10s";
    };
    after = [ "network.target" ];
    wantedBy = [ "multi-user.target" ];
    environment.PORT = "4000";
  };
}
2 Likes

With NixOS 20.03 yarn2nix and mkYarnPackage are included in nixpkgs. The answer could now look like this:

{ config, pkgs, ... }:

{
  hafas-client-rpc = pkgs.mkYarnPackage {
    src = pkgs.fetchFromGitHub {
      owner = "petabyteboy";
      repo = "hafas-client-rpc";
      rev = "955e776a984cb73f1d31d517963d0b8934f46621";
      sha256 = "0ncm45w3zrgbxxbman4j3j35w063x3jg7ah3lb59qn4g7z7dpx00";
    };
    # hafas-client has a post-install script to generate a random id for the installation
    # yarn ignores this script, and to get reproducible results, we save a fixed id
    pkgConfig.hafas-client.postInstall = ''
      echo '"foo"' > id.json
    '';
  };

in {
  systemd.services.hafas-client-rpc-http = {
    serviceConfig = {
      ExecStart = "${pkgs.nodejs}/bin/node ${hafas-client-rpc}/bin/hafas-client-rpc";
      Restart = "always";
      RestartSec = "10s";
    };
    after = [ "network.target" ];
    wantedBy = [ "multi-user.target" ];
    environment.PORT = "4000";
  };
}
2 Likes