Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixos/networking: Add a read-only option for the FQDN #100155

Open
wants to merge 1 commit into
base: master
from

Conversation

@primeos
Copy link
Member

@primeos primeos commented Oct 10, 2020

This is a convenience option that can be used to quickly obtain the
configured FQDN.

Motivation for this change

See #76542 (comment). It might also help for things like #94011 (comment).
We might want to mention this in the release notes a well but we should wait for #100151 then.

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS linux)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.
@primeos
Copy link
Member Author

@primeos primeos commented Oct 10, 2020

@GrahamcOfBorg test hostname.explicitDomain hostname.noExplicitDomain

4

@worldofpeace
Copy link
Member

@worldofpeace worldofpeace commented Oct 10, 2020

Ooh, I like this. cc @jonringer I think we should for sure include this

@worldofpeace worldofpeace added this to In progress in 20.09 Blockers via automation Oct 10, 2020
@jonringer
Copy link
Contributor

@jonringer jonringer commented Oct 11, 2020

although this is convenient, I'm not sure this is great behavior. Mainly from it being nullable.

If you really needed an FQDN to be defined, wouldn't you rather want an error thrown at evalModules time?

@jonringer
Copy link
Contributor

@jonringer jonringer commented Oct 11, 2020

I think we should be careful about what we expose, and I would like to hear back from some others: cc @Infinisil @grahamc

@Infinisil
Copy link
Member

@Infinisil Infinisil commented Oct 11, 2020

Looks fine to me. Code that uses this can still check if it's null and throw an appropriate error then. Or it can not check for null and get a type error instead when it's used.

@jonringer
Copy link
Contributor

@jonringer jonringer commented Oct 11, 2020

from a user's perspective, I believe I would prefer:

assert failed: please provide a valid value for networking.hostname and networking.domain

over

cannot coerce null value to string

and I'm not even sure if a null value would produce an error, may just be coerced to ""

@jonringer
Copy link
Contributor

@jonringer jonringer commented Oct 11, 2020

again, this is largely my take on nullability or subtle coercing. I think it's less surprising to get an assertion error plainly saying what assumptions are incorrect, instead of getting some coerce-tion error at runtime that's 1 to n steps removed from the actual issue.

EDIT: to @primeos 's credit, he did make the naming explicit that it's null. But often times the way that these errors arise in production are much less desirable. In which some chain of assumptions were made.

@primeos
Copy link
Member Author

@primeos primeos commented Oct 11, 2020

although this is convenient, I'm not sure this is great behavior. Mainly from it being nullable.

Yeah, that was also my main concern. It's clearly not ideal as we don't have any nice null safety like e.g. Kotlin. So AFAIK any of the following can happen:

  • The user checks for null (would be the most safe but this isn't enforced and requires more code when using it)
  • The user gets the cannot coerce null value to string error and analyzing the trace might be a PITA
  • It's used as value or default value for another option that might be of the same type. This is probably the most dangerous case as the FQDN could be omitted without an error (though at least if the FQDN is really required the option shouldn't be nullable).

It's also important to note that networking.fqdn will be null with the default configuration due to networking.domain.

If you really needed an FQDN to be defined, wouldn't you rather want an error thrown at evalModules time?

I guess this depends on the usage. E.g. some modules might optionally take an FQDN and either skip the configuration directive or provide a default value in case of null (but again this could also result in unexpected consequences). Personally I'm not really sure what's better.

@flokli
Copy link
Contributor

@flokli flokli commented Oct 11, 2020

If the FQDN attribute is meant as a convenience option, requiring to do some checking for not being null kinda defeats its purpose. Also, joining hostName and domain manually isn't a lot of typing ;-)

On the other hand, silently skipping the domain and only returning networking.hostName is also dangerous - Just by reading its option name I'd imply it wouldn't silently fallback to that if the domain isn't set.

Can we do some exploration in the current NixOS modules code?

If we introduce such an option, it should fail loudly, and maybe with a meaningful and traceable error message.

Things like options.services.dnscrypt-wrapper.providerName could make use of such an option.

@Infinisil
Copy link
Member

@Infinisil Infinisil commented Oct 11, 2020

You could just replace the null with a throw "better error"

@jonringer
Copy link
Contributor

@jonringer jonringer commented Oct 11, 2020

I would rather write:

if config.networking.hasFqdn then config.networking.fqdn else config.networking.hostName

as it reads more naturally than

if config.networking.fqdn == null then config.networking.hostName else config.networking.fqdn

in which the conditions in which the fqdn is null aren't readily apparent.

To be completely honest, I haven't had the need to use a fqdn as part of a module yet. So I'm not sure what path is the "most ergonomic".

@aneeshusa
Copy link
Contributor

@aneeshusa aneeshusa commented Oct 11, 2020

I defined a convenience fqdn attr like this PR in my system fork when I pulled in the original change so +1 on this change overall! I agree with @flokli's comment that since this is for convenience, I'd prefer use fdqn directly without checking in my own setup (where I know I always have a domain setup) - see my use cases below.

I also like @Infinisil's throw "better error" approach.

Since networking.hostName cannot be null, for modules which need to have different behavior if an fqdn does not exist, my 2c would be to prefer if config.networking.domain == null then <fallback behavior> else config.networking.fqdn - which is the same condition they would be checking today.

My main use case in my system configs is to to set up locations in a nginx vhost for the machine's own fqdn. I have many services that are reversed proxied to from various paths - e.g. prometheus exporters under /prometheus, caldav server on /caldav, git web server on /git. Another one is to let prometheus know what its external web URL is, which could also apply to other web applications. These all are generally "give me an easy reference to a DNS name that will resolve to the machine" where I prefer a hard error on lack of domain over having to check for null since a raw host name can't be resolved via DNS.

@flokli
Copy link
Contributor

@flokli flokli commented Oct 11, 2020

I'd also prefer reading config.networking.fqdn throwing a nice error, and code like if config.networking.domain == null then <fallback behavior> else config.networking.fqdn in modules/configuration that can implement a fallback.

@jonringer
Copy link
Contributor

@jonringer jonringer commented Oct 12, 2020

Since this isn't "fixing" a particular usecase, but rather an enhancement. I would like to remove this from 20.09 blockers. cc @worldofpeace

@worldofpeace worldofpeace removed this from In progress in 20.09 Blockers Oct 12, 2020
@worldofpeace
Copy link
Member

@worldofpeace worldofpeace commented Oct 12, 2020

Sure.

@worldofpeace worldofpeace added this to the 20.09 milestone Oct 12, 2020
@worldofpeace
Copy link
Member

@worldofpeace worldofpeace commented Oct 12, 2020

Cool on backporting, though.

@primeos primeos force-pushed the primeos:nixos-add-fqdn-option branch from 9f07f38 to 594343d Oct 12, 2020
@primeos
Copy link
Member Author

@primeos primeos commented Oct 12, 2020

Ok, I switched from null to throw.

Just as a heads-up/disclaimer: if config.networking.domain == null then <fallback behavior> else config.networking.fqdn won't always be enough as the hostname can be set to an empty string in which case it will be obtained dynamically via DHCP.

Example error message:

[root@friday:/var/nixpkgs]# nixos-rebuild dry-build
building the system configuration...
error: The FQDN is required but cannot be determined. Please make sure that
both networking.hostName and networking.domain are set properly.

(use '--show-trace' to show detailed location information)

Also: Apparently the defaultText gets escaped: Default: "\${networking.hostName}.\${networking.domain}" (literalExample might help)

This is a convenience option that can be used to quickly obtain the
configured FQDN.
@primeos primeos force-pushed the primeos:nixos-add-fqdn-option branch from 594343d to 971f0b4 Oct 12, 2020
Copy link
Contributor

@jonringer jonringer left a comment

LGTM

@flokli
flokli approved these changes Oct 12, 2020
Copy link
Contributor

@flokli flokli left a comment

SGTM - however, we shouldn't backport this to 20.09 IMHO.

Let it sink in unstable, let's see what parts of the module system make use of it, so we have the time to do necessary changes on it - if we see the need for it.

@jonringer
Copy link
Contributor

@jonringer jonringer commented Oct 12, 2020

good point @flokli maybe we should test pilot this in unstable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

6 participants
You can’t perform that action at this time.