Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions nixos/doc/manual/from_md/release-notes/rl-2305.section.xml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,16 @@
<literal>true</literal>, or configure your firewall.
</para>
</listitem>
<listitem>
<para>
The Nginx module now validates the syntax of config files at
build time. For more complex configurations (using
<literal>include</literal> with out-of-store files notably)
you may need to disable this check by setting
<link linkend="opt-services.nginx.validateConfig">services.nginx.validateConfig</link>
to <literal>false</literal>.
</para>
</listitem>
<listitem>
<para>
The EC2 image module previously detected and automatically
Expand Down
2 changes: 2 additions & 0 deletions nixos/doc/manual/release-notes/rl-2305.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ In addition to numerous new and upgraded packages, this release has the followin

- The [services.unifi-video.openFirewall](#opt-services.unifi-video.openFirewall) module option default value has been changed from `true` to `false`. You will need to explicitely set this option to `true`, or configure your firewall.

- The Nginx module now validates the syntax of config files at build time. For more complex configurations (using `include` with out-of-store files notably) you may need to disable this check by setting [services.nginx.validateConfig](#opt-services.nginx.validateConfig) to `false`.

- The EC2 image module previously detected and automatically mounted ext3-formatted instance store devices and partitions in stage-1 (initramfs), storing `/tmp` on the first discovered device. This behaviour, which only catered to very specific use cases and could not be disabled, has been removed. Users relying on this should provide their own implementation, and probably use ext4 and perform the mount in stage-2.

- The EC2 image module previously detected and activated swap-formatted instance store devices and partitions in stage-1 (initramfs). This behaviour has been removed. Users relying on this should provide their own implementation.
Expand Down
47 changes: 44 additions & 3 deletions nixos/modules/services/web-servers/nginx/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ let

configPath = if cfg.enableReload
then "/etc/nginx/nginx.conf"
else configFile;
else finalConfigFile;

execCommand = "${cfg.package}/bin/nginx -c '${configPath}'";

Expand Down Expand Up @@ -391,6 +391,38 @@ let
);

mkCertOwnershipAssertion = import ../../../security/acme/mk-cert-ownership-assertion.nix;

snakeOilCert = pkgs.runCommand "nginx-config-validate-cert" { nativeBuildInputs = [ pkgs.openssl.bin ]; } ''
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we want to use runCommandLocal here. We probably don't want to cache or substitute this, or do we?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this certificate is only used during build, so reusing it or sharing it via a binary cache is not a problem

mkdir $out
openssl genrsa -des3 -passout pass:xxxxx -out server.pass.key 2048
openssl rsa -passin pass:xxxxx -in server.pass.key -out $out/server.key
openssl req -new -key $out/server.key -out server.csr \
-subj "/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=IT Department/CN=example.com"
openssl x509 -req -days 1 -in server.csr -signkey $out/server.key -out $out/server.crt
'';
validatedConfigFile = pkgs.runCommand "validated-nginx.conf" { nativeBuildInputs = [ cfg.package ]; } ''
# nginx absolutely wants to read the certificates even when told to only validate config, so let's provide fake certs
sed ${configFile} \
-e "s|ssl_certificate .*;|ssl_certificate ${snakeOilCert}/server.crt;|g" \
-e "s|ssl_trusted_certificate .*;|ssl_trusted_certificate ${snakeOilCert}/server.crt;|g" \
-e "s|ssl_certificate_key .*;|ssl_certificate_key ${snakeOilCert}/server.key;|g" \
Comment on lines +406 to +408
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure how robust the regex is. For using the nix options it is certainly enough.

> conf

LD_PRELOAD=${pkgs.libredirect}/lib/libredirect.so \
NIX_REDIRECTS="/etc/resolv.conf=/dev/null" \
nginx -t -c $(readlink -f ./conf) > out 2>&1 || true
if ! grep -q "syntax is ok" out; then
echo nginx config validation failed.
echo config was ${configFile}.
echo 'in case of false positive, set `services.nginx.validateConfig` to false.'
echo nginx output:
cat out
exit 1
fi
cp ${configFile} $out
'';

finalConfigFile = if cfg.validateConfig then validatedConfigFile else configFile;
in

{
Expand Down Expand Up @@ -489,6 +521,15 @@ in
'';
};

validateConfig = mkOption {
default = pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform;
Copy link
Member

@SuperSandro2000 SuperSandro2000 Dec 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be pkgs.stdenv.buildPlatform.canExecute stdenv.hostPlatform

defaultText = literalExpression "pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform";
type = types.bool;
description = lib.mdDoc ''
Validate the generated nginx config at build time. The check is not very robust and can be disabled in case of false positives. This is notably the case when cross-compiling or when using `include` with files outside of the store.
'';
};

additionalModules = mkOption {
default = [];
type = types.listOf (types.attrsOf types.anything);
Expand Down Expand Up @@ -1027,7 +1068,7 @@ in
};

environment.etc."nginx/nginx.conf" = mkIf cfg.enableReload {
source = configFile;
source = finalConfigFile;
};

# This service waits for all certificates to be available
Expand All @@ -1046,7 +1087,7 @@ in
# certs are updated _after_ config has been reloaded.
before = sslTargets;
after = sslServices;
restartTriggers = optionals (cfg.enableReload) [ configFile ];
restartTriggers = optionals (cfg.enableReload) [ finalConfigFile ];
# Block reloading if not all certs exist yet.
# Happens when config changes add new vhosts/certs.
unitConfig.ConditionPathExists = optionals (sslServices != []) (map (certName: certs.${certName}.directory + "/fullchain.pem") dependentCertNames);
Expand Down
2 changes: 1 addition & 1 deletion nixos/tests/nginx.nix
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {

specialisation.reloadWithErrorsSystem.configuration = {
services.nginx.package = pkgs.nginxMainline;
services.nginx.virtualHosts."!@$$(#*%".locations."~@#*$*!)".proxyPass = ";;;";
services.nginx.virtualHosts."hello".extraConfig = "access_log /does/not/exist.log;";
};
};
};
Expand Down