I am quite new to nix, nixos, flakes, devshells, etc. I am, however, determined to find a reproducible and declarative way to handle dependencies and development environments, including for services. I looked into devenv, but it seems services-flake is better tailored to people already using nixos and flakes.
I'm sorry if the below is filled with stupid questions and there is some site I should have just gone to where all the answers lie. That being said, I've tried very hard to figure this out and cannot find any resources to help me. ChatGPT is just useless for this too, as it will spit out one terrible duct-tape solution after another. I may very well be a case of "once you know the search term, the answer is obvious".
For context I'm a software engineering student with a few years of experience. I've been running NixOS as my daily driver for about a month.
Here's the situation:
I've been using nix devshells in flakes to manage project dependencies. I need to add a postgres instance to one of these. I followed the guides online and got this working nicely. The issue is configuration of the service as it starts up for the first time. Since I'm more used to docker for this purpose, I expect to be able to set an initial database, user, an port through environment variables. However, this does not seem to be the way to go at all for flakes.
I'm therefore left wondering:
This is the flake I'm currently using on the project:
{
description = "My project with postgres service";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05";
flake-parts.url = "github:hercules-ci/flake-parts";
process-compose-flake.url = "github:Platonic-Systems/process-compose-flake";
services-flake.url = "github:juspay/services-flake";
systems.url = "github:nix-systems/default";
};
outputs = inputs:
inputs.flake-parts.lib.mkFlake { inherit inputs; } {
systems = import inputs.systems;
imports = [ inputs.process-compose-flake.flakeModule ];
perSystem = { config, pkgs, ... }: {
# Define a process-compose environment
process-compose.default = { config, ... }: {
imports = [ inputs.services-flake.processComposeModules.default ];
services.postgres."pg1" = {
enable = true;
initialDatabases = [
{ name = "db"; }
];
};
};
devShells.default = pkgs.mkShell {
inputsFrom = [
config.process-compose.default.services.outputs.devShell
];
packages = with pkgs; [
nodejs
];
};
};
};
}
I find it very satisfying to learn the proper way of things, using trustworthy resources. I'd be happy to get any tips on where I should go to learn more about this! It's just been wildly confusing to try and google/chatgpt my way through this problem.
@Cepheus
We recommend keeping all the configuration of a service in services.<name>.<instance-name>
to avoid magic. Expecting a local copy (not committed) of the .env to have specific env vars is that magic.
If your main concern is secrets management and this configuration is only used for development and testing:
Last updated: Oct 15 2025 at 07:45 UTC