Question: Deploying a multitenant system with NixOS/NixOps

Hey everybody,

I have this question/problem with NixOS/NixOps that I’m not sure how to solve. I’ve been building a small SaaS application for which I use NixOps to deploy to a small Linode server. I have seperate databases and seperate server processes for every one of my tenants. Currently I have a list of all my tenants in a nix file, and my deployment scripts maps over all of these tenants to make/update a database for each one, start up a server process, and sets up correct NGINX routing per url.

This works great, but I wish a new user could click somewhere on my landing page and immediately get a NEW environment. I’m not sure how to do this with Nix. Intuitively I would replace the static list of tenants with a single table in a “global” database that keeps track of all tenants, and then run my deployment scripts off of that, but I wouldn’t know how to do that in a Nix file. Are there other ways anybody can think off?

Thanks for any advice

Simon

One way to do this would be to generate a JSON file from your database and read that into your nix configuration using builtins.fromJSON, would that be what you’re looking for?

Oh I didn’t know reading files was ok in Nix, somehow I thought that was against the philosophy of having everything statically defined…

That will do nicey probably, thanks! A followup question:

  • Does nixops always restart all processes? I wouldn’t like it if, every time I run my deployment script to make a new demo environment, all my processes are restarted.

Nixops actually doesn’t restart anything, it’s the switch to the new configuration that checks which services have changed (i.e. come from a different output path) and restarts the affected services.
This also points to your solution: Ensure that the existing services don’t change and evaluate to the exact same derivation with the same output path.

Note that this won’t prevent restarts if underlying system software changes that these services depend on:
Assuming you run an instance of nginx for each of your tenants then changing the configuration just for one nginx instance will only result in restarting that single instance.
If the underlying nginx binary changes, all nginx instances will be restarted, as each instance now depends on a different binary.