How to have multiple environments on the same NixOS server?

I have a NixOS server where I installed several services usings NixOS configs with some exceptions where I use a Docker image because a service for NixOS was not available on nixpkgs.

Recently, and since some services are naturally acquiring a “production” status, I started thinking about the posibility of having some spin-off services to test stuff: a new version of the software, tinker with configs without messing up prod instance

Basically what I think I need it’s the same services configured by NixOS but a different database and data storage, call it staging/development environment. How would you tackle such an idea? Someone actually does it for their self-hosted services?

Probably some VMs or containers are necessary for achieving what I want, but I wouldn’t know how to start messing with that on NixOS, so points on this would be appreciated.

you could start out using nixos-containers: NixOS Containers - NixOS Wiki
i use them to run several instances of (the same version of) MPD (music/podcasts/audio books), for example.
you can either build them from within you system, as a full set, or seperate, but i haven’t tried the latter one.

[edit] just forgot: microvms may be another option: GitHub - astro/microvm.nix: NixOS MicroVMs

some ideas:

  • if your services are defined in seperate config-files or as modules duplication for prod/staging should not be an issue.
  • i’m also pretty sure that you could pass your container-config a different nixpkgs vars to use another branch of nixpkgs (like stable on the prod and unstable in the staging).
  • or, if you’re using flakes and seperate containers - some different flake.lock(s). but this might get hacky quiet quickly

I simply do that on the client machine I happen to sit infront of.

It’s all NixOS, so the config works the same on any machine. I have set up my per-service config as NixOS modules which allows me to enable the same service-specific config that’s used on the server on any other machine too such as the client. I then tinker a bit and deploy the changes to the server too once I’m happy with them.

There are some small differences such that the domain name used is instead of but my virtual hosts and ACME modules simply handle this internally and I don’t need to think about it.

Oh, and another really easy way of doing this is to use nixos-rebuild build-vm -I nixos-config=/path/to/server/configuration.nix. It’ll build an executable that starts a lightweight VM from the given config.

Super neat but I prefer to selectively deploy the services on my local machine as I described for easier debuggability.

maybe specializations might come in handy here, to be able to quickly switch tasks or setup different setups in parallel.

Specializations wouldn’t work because I need both instances running at the same time.

What do you use for the virtual hosts?

Probably this is the way to go. I’ll try to research some of this, thanks!

oh, sorry, i was a bit terse here: i meant that it might be desireable to put you test-env into a specialization if you are building it on you laptop/desktop as Atemu suggested, so you can easily switch between working on that envs or doing something unrelated.

I use nginx as it’s the best supported reverse proxy in NixOS currently.

You can see my module here: nixos-config/modules/nginx/module.nix at 71704e94a60cc7592eb7a0684fa532f5c36b6e0a · Atemu/nixos-config · GitHub

1 Like