Unix has a nearly forgotten feature for registering port assignments - /etc/services. It canāt detect conflicts but it does provide a system-wide registry that can be accessed via getservbyname and getservbyport. This is useful for monitoring tools because they can use your port assignments to label traffic flows.
I had a PR to update the services file but it went stale and I wasnāt sure it was worth the eval overhead by itself. If it could be bolted onto conflict detection then I think it would be worth it.
Interesting. Iām not sure how much eval overhead this would generate, since every NixOS service would have to set an additional option. I implemented it for my own homelab, but would also be interested in upstreaming.
Thanks for sharing those links. Like I wrote in my blog post, dynamically generating the ports was also my first idea. However the more I think about it, the more I am questioning if that is really the approach we want to take. NixOS configurations are pretty static and everything is known at evaluation. A dynamic allocator would add additional complexity in implementation, but also understanding which port was chosen and why. I like the predictability that enabling a service uses the default port of the service. The same port that is documented in the respective official service documentation.
One thing I would like to improve is to print the respective options that can be used to modify the port in the error message. Because if my variant would be integrated into nixpkgs, the error would include the file paths of the nixpkgs module, not the users source code. The user would then have to figure out how to change the port. However they probably already know how, because they are passing it to a (nginx) reverse proxy.
Since we have the filepath I wonder if it would be possible to parse the Nix code and somehow retrieve the variable, instead of the evaluated port number. This would be required, because not all services use services.<service>.port.
What are your thoughts on static (evaluation error) versus dynamic (allocator)?
edit: even a dynamic port allocator would have to default to the current nixpkgs values, otherwise it would be a breaking change.