-
-
Notifications
You must be signed in to change notification settings - Fork 14.3k
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/nginx: report actual vhosts name in assertions/warnings #345913
base: master
Are you sure you want to change the base?
nixos/nginx: report actual vhosts name in assertions/warnings #345913
Conversation
Checked it on a test virtual machine, it works. |
a377b85
to
c74f5d1
Compare
Fixing the docs build was quite a bit more involved than I like it to be, especially of this nothing telling error:
|
145c049
to
1b46e4c
Compare
let | ||
global-config = config; | ||
in | ||
{ config, name, ... }: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roberth @infinisil I'm curious, are there any best practices on importing submodules from other files? This seems kinda odd, but right now I don' thave a better idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My first thought would be to use importApply
when calling this, but that barely improves anything; just the error message location.
Nicer improvements would be:
- use deferredModule so that it only needs to be invoked in one place, the main nginx module
- factor out the dependencies on
services.nginx
akacfg
into a separate module- make that separate module an anonymous module in the main nginx module
- this file won't need extra paramaters, so it can be a regular module file, imported with
imports = [ ./vhost-options.nix ];
or whatever the path expression is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify, importing into submodules is ok and lets you do interesting things, and it may even look like this, but this isn't the right use case for it, because option values shouldn't be forwarded en masse to become definitions for multiple options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't be forwarded en masse to become definitions for multiple options.
Agreed, that's why I opened #313412 and I even have a half-finished thing in my stash.
That said, this is out-of-scope here, it contains a nice improvement and as long as we don't break existing code here, we're good I'd say.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth trying the following suggestions.
Note that deferredModule
adds the option name to its _file
location for error messages, and "${options.foo}"
gives you a fully qualified option path, including attrsOf
names such as the vhost name.
} | ||
)); | ||
type = lib.types.nullOr (lib.types.submodule | ||
(import ../web-servers/nginx/vhost-options.nix { inherit config lib; })); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A minor improvement for error messages would be:
(import ../web-servers/nginx/vhost-options.nix { inherit config lib; })); | |
(lib.modules.importApply ../web-servers/nginx/vhost-options.nix { inherit config lib; })); |
However, it seems that these modules are forwarding an arbitrary set of option values as config definitions, thereby losing dynamic behavior and potentially causing problems in services.nginx
as priorities like mkForce
are lost.
The right solution here would be to use a type that represents these definitions etc, without computing the config
fixpoint or any definition merging before its use in services.nginx
.
type = lib.types.nullOr lib.types.deferredModule;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It evaluates, no idea how to test this though. I don't have any of the modules in here set up.
Also no idea how to use deferredModule here. Just replacing submodule yields an error:
lazy-options.json> error: attempt to call something which is not a function but a set
lazy-options.json>
lazy-options.json> at /nix/store/54wv4qcvzlxg98v3n8asy27bfxviycca-nixos/modules/services/misc/radicle.nix:212:36:
lazy-options.json>
lazy-options.json> 211| # Type of a single virtual host, or null.
lazy-options.json> 212| type = lib.types.nullOr (lib.types.deferredModule
lazy-options.json> | ^
lazy-options.json> 213| (lib.modules.importApply ../web-servers/nginx/vhost-options.nix { inherit config lib; }));
lazy-options.json> Cacheable portion of option doc build failed.
lazy-options.json> Usually this means that an option attribute that ends up in documentation (eg `default` or `description`) depends on the restricted module arguments `config` or `pkgs`.
lazy-options.json>
lazy-options.json> Rebuild your configuration with `--show-trace` to find the offending location. Remove the references to restricted arguments (eg by escaping their antiquotations or adding a `defaultText`) or disable the sandboxed build for the failing module by setting `meta.buildDocsInSandbox = false`.
lazy-options.json>
error: build of '/nix/store/kysl1q2mkcbq80gssnsxjbfw2m8qyyd8-lazy-options.json.drv' on 'ssh-ng:https://amy.dse.in.tum.de' failed: builder for '/nix/store/kysl1q2mkcbq80gssnsxjbfw2m8qyyd8-lazy-options.json.drv' failed with exit code 1;
and without sandbox:
➜ NIX_PATH=nixpkgs=$(pwd) nix-build --option restrict-eval true nixos/release.nix -A manual.x86_64-linux
error:
… while calling the 'deepSeq' builtin
at /home/sandro/src/nixpkgs3/lib/customisation.nix:415:7:
414| in if drv == null then null else
415| deepSeq drv' drv';
| ^
416|
… while evaluating the attribute 'outPath'
at /home/sandro/src/nixpkgs3/lib/customisation.nix:404:13:
403| value = commonAttrs // {
404| outPath = output.outPath;
| ^
405| drvPath = output.drvPath;
(stack trace truncated; use '--show-trace' to show the full, detailed trace)
error: attempt to call something which is not a function but a set: { _type = "option-type"; check = «thunk»; deprecationMessage = null; description = «thunk»; descriptionClass = "noun"; emptyValue = «thunk»; functor = «thunk»; getSubModules = «thunk»; getSubOptions = «thunk»; merge = «thunk»; «4 attributes elided» }
at /home/sandro/src/nixpkgs3/nixos/modules/services/misc/radicle.nix:212:36:
211| # Type of a single virtual host, or null.
212| type = lib.types.nullOr (lib.types.deferredModule
| ^
213| (lib.modules.importApply ../web-servers/nginx/vhost-options.nix { inherit config lib; }));
let | ||
global-config = config; | ||
in | ||
{ config, name, ... }: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My first thought would be to use importApply
when calling this, but that barely improves anything; just the error message location.
Nicer improvements would be:
- use deferredModule so that it only needs to be invoked in one place, the main nginx module
- factor out the dependencies on
services.nginx
akacfg
into a separate module- make that separate module an anonymous module in the main nginx module
- this file won't need extra paramaters, so it can be a regular module file, imported with
imports = [ ./vhost-options.nix ];
or whatever the path expression is.
1b46e4c
to
99e7e2d
Compare
99e7e2d
to
ee8bdf4
Compare
a589755
to
6f5e809
Compare
1ec989a
to
92f9500
Compare
92f9500
to
cdeda25
Compare
I did another rebase and applied the last 3 comments. |
in { | ||
assertion = matchedLocations == { }; | ||
message = '' | ||
Only one of root or alias can be specified on services.nginx.virtualHosts."${name}".locations: ${lib.concatStringsSep ", " (attrValues matchedLocations)}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This gives me error: cannot coerce a set to a string
. I think you meant attrNames
here?
in | ||
# Either vhost has precedence and we need a vhost specific http listener | ||
# Either vhost set nothing and inherit from server settings | ||
config.enableACME -> ((vhostAuthority && hasAtLeastVhostHttpListener) || (!vhostAuthority && hasAtLeastDefaultHttpListener)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I always get a headache when staring at this
(no need to change that in this PR, just complaining :p)
Before assertions where not really helpful as they didn't show what vhost had the problem which is very essential to fix it.
and now they do 🎉
Actual assertion with mocked host name while I had the old assertions still in place:
Things done
nix.conf
? (See Nix manual)sandbox = relaxed
sandbox = true
nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)Add a 👍 reaction to pull requests you find important.