I’m pretty new to Nix, I have been using NixOS for a year and I have written a few Python derivations and I think I understand more or less the basic concepts.
I recently started using Nixops and liked it a lot, and I thought I’d migrate one of my Debian servers to NixOS. So I’m trying to package a website that is hosted on this server.
The website is made with Python/Django, and uses webpack to build the frontend assets. I managed to generate derivations for the Python part using mach-nix, and for the frontend part using node2nix. I’m using these derivations in a third derivation which contains both the Python code and the compiled JS/CSS files like so:
with import <nixpkgs> { };
let
src = builtins.fetchGit {
url = ./.;
rev = "7bda671b2f52e48507497059a88b6a6f776e76bc";
};
mach-nix = import (builtins.fetchGit {
url = "https://github.com/DavHau/mach-nix/";
ref = "refs/tags/3.1.1";
}) { };
pyenv = mach-nix.mkPython {
requirements = builtins.readFile ./requirements/base.txt;
};
nodeEnv = callPackage ./node-env.nix {
nodejs = pkgs.nodejs-12_x;
libtool = if pkgs.stdenv.isDarwin then pkgs.darwin.cctools else null;
};
nodePackages = callPackage ./node-packages.nix { inherit nodeEnv; };
nodeArgs = nodePackages.args // {
production = false;
src = builtins.filterSource (path: type:
/. + path == ./package.json || /. + path == ./package-lock.json) ./.;
dontNpmInstall = true;
};
nodeShell = nodeEnv.buildNodeShell nodeArgs;
nodeDependencies = stdenv.mkDerivation {
name = "mywebsite-front";
src = src;
installPhase = ''
ln -s ${nodeShell.nodeDependencies}/lib/node_modules ./node_modules
export PATH="${nodeShell.nodeDependencies}/bin:$PATH"
NODE_ENV=production webpack
mkdir $out
cp -r dist/* $out/
'';
};
in python3Packages.buildPythonPackage {
propagatedBuildInputs = [ pyenv ];
name = "mywebsite";
src = src;
doCheck = false;
configurePhase = ''
ln -s ${nodeDependencies} ./blog/staticfiles
'';
}
It works but:
- I need to update
src
every time I make a new commit. Ideally I’d like to always build themain
branch. I tried usingref = refs/heads/main
but it seems that without specifying a checksum, Nix doesn’t recreate the derivation. The reason I’m usingfetchgit
here is that I want to package a clean version of the project, without the risk of including any non-committed change. Maybe there’s another way to do this? - I would like to be able to run commands on the website (using Django’s entrypoint
./manage.py
command). I guess I can add the entrypoint in mysetup.py
file, but the thing is that I would like to be able to deploy multiple “instances” of the website on the same server (eg. staging, production, etc). So instead of having amywebsite
command, I guess I should have something likemywebsite-staging
andmywebsite-prod
commands (which could, or could not, point to the same version of the package). Is it something that should be done outside of the package, eg. with Nixops? - What if I want to use this Nix package on a non-NixOS server? How can I make the application server point to the correct directory in /nix/store? Or maybe I should add the application server as an input for the derivation, but then how do I write a systemd unit to use it?
I’m surprised the only examples I could find on the internet were people packaging static websites, but very few packaging something more complex. I plan on sharing my experience, with the hope that it will be of use to some people.
Thanks for your help!