Nginx - new conf.d folder

hello,
nginx has just received a modification in how configuration files are managed and.. well i feel lost :slight_smile:
i can't understand the ratio of the modification, what should i do with my old and perfectly working nginx.conf file?
thanks

Nothing, you can keep it.

the poiint is that with my old conf file nothing works :slight_smile:
and i don't even see error message because i don't know where they are saved today
trying to understand something from here
https://openwrt.org/docs/guide-user/services/webserver/nginx
:frowning:

this is the very first time i see a service script that decides to change the config files.
i have nginx with ssl, i want a local connection to work without ssl and you know what? when nginx is started, it forces me to use certificates it creates and modifies my config files.
this is crazy.

Sorry for the late reply and the inconveniences. If you can post your configuration (see nginx -T cleaned by private data), maybe I can help you with it.

Nevertheless, I give a summary

  1. What I tried to do and why,
  2. How it is working and what is the new structure
  3. How you can adopt to the new structure or disable it

Before that: The error messages are in OpenWrt´s syslog; you can read them by logread | grep nginx. For the new structure:

  1. Before we used an example configuration. It contained a default server, but was not extensible. So users and other packages changed it, e.g., when installing nginx-ssl-luci, the default server was transitioned to use SSL with a self-signed certificate and redirection to it from http.
    I think it is a good idea to let this do Nginx instead. Now at startup instead at install because certificates can expire. Additionally the main configuration can be made extensible by including all /etc/nginx/conf.d/*.conf files (this was done before by LuCI for Nginx, too).
    So, we have the same main configuration and can update it via opkg if it is not modified (which now should do only users not packages).

  2. The main idea was to give a minimal set in the main configuration /etc/nginx/nginx.conf and include further parts from the /etc/nginx/conf.d/ directory.
    For the best match to the situation before, there is a default server listening on local IP addresses (and using a self-signed certificate if SSL is available) in /etc/nginx/conf.d/_lan.conf. And there is another server in /etc/nginx/conf.d/_redirect2ssl.conf redirecting all http requests to https (it acts as default server if there is no other server that matches better).
    In the /etc/nginx/conf.d/ can be different files handled by their extension: .conf files are included directly into the http section of the main configuration; typically they contain servers. .locations can be included in server parts; the default server in _lan.conf includes them all in the initial configuration (and LuCI installs now such a file for example). .crt and .key files are used to store SSL credentials.

  3. To adopt to the new structure, move the server parts from the main configuration /etc/nginx/nginx.conf to different files in the /etc/nginx/conf.d/ directory. Decide which other parts you want to keep and move them to /etc/nginx/conf.d/additionals.conf or so. Then replace the main configuration by mv /etc/nginx/nginx.conf-opkg /etc/nginx/nginx.conf (opkg should put the new configuration there)
    If you want to disable the default server, you can replace /etc/nginx/conf.d/_lan.conf by an empty file. You could also remove it, but then it is reinstalled by opkg.
    If you want to not adopt to the new structure remove the line include conf.d/*.conf; (or similar) from your /etc/nginx/nginx.conf file if present (you could use another directory if you want).

The files managed by the service script are /etc/nginx/conf.d/_lan.conf and the files with the listen directives /var/lib/nginx/lan*. I try to make the configuration of the default server more flexible and want to use uci for that (this would be the first step for making this part of the configuration available to LuCI, too). For that we will use the file /etc/config/nginx.

1 Like

hello and thanks for the detailed answer :slight_smile:
to me, the strange part is only the decision that the script file makes to change my config file.
as i said before, in my config i do not want local traffic to be under ssl. Right or wrong i don't know, but i'd not understand why the service file should decide this for me.
i ended up just disabling the http to https redirect. now the service adds the certificate part to my _lan file, but they are not used.
then i have my "real" server part which uses letsencrypt certificates and works with ssl.

so, briefly, i took my old config file and moved pieces to .conf or .locations file. that's all. i've a ouple of useless certificates, but it works.

1 Like

Thank you for the feedback :slight_smile:

1 Like

There is a new draft version. I hope I could address the main point: The init script will not modify the configuration anymore beside renewing self-signed certificates when they are about to expire in 13 months.
P.S.: I am happy if you can give me suggestions for improvement.

glad to try, but i don't think i can help that much :slight_smile:
but i can turn this to selfish just to take my experience.
even before this new config management i had to fight with the default scripts 60-something and 70-smething, because they were going to overwrite my config file (embedded in the image that i build myself)
so IMHO the point is: if there is a nginx conf, the package scripts - and much more the init script - should not touch it.. if it's there, is should be intended to work.. but well, all the defaults settings - or default files .- should be put when no config file is present. this seems consistent to me..
second point: certificates: i assume also this point should be optional. i mean, i'm never gonna use self signed certificates, at least as long as letsencrypt exists.. so why should i keep a valid certificate?
but, again, it should be a very good option to have with the default files (or if in any conf file the selfsigned option is set)
Last: i assume its not mandatory to use ssl for all the server directives, once nginx ssl is installed. As i already said before, i'm not using ssl for local home connections.
To sum up: in my opinion no script should touch config files. never. All should be left as option.
my 2 cents :slight_smile:
thanks a lot for your package!

1 Like

Thank you, I think this will be attained by the new version: If there is a custom /etc/nginx/nginx.conf it will be used instead of the defaults.
(There will be a UCI config file at /etc/config/nginx that comes into effect only when not using a custom /etc/nginx/nginx.conf)
Edit: UCI will be enabled by default, you will have to disable it by
uci set nginx.global.uci_enable=false or so ...

Hi Peter, sorry in advance I'm a noob.

I'm trying to regenerate the _lan.crt and _lan.key files in the /etc/nginx/conf.d/ directory. I want to do this as every time I log into LuCI via its 192.168.1.1 local lan address in a web browser I get the dreaded security threat page in Firefox. The specific message I'm getting in Firefox is Firefox does not trust this site because it uses a certificate that is not valid for 192.168.1.1.
I think I understand the method for generating keys for uHTTP via using the openssl tool at the OpenWrt ssh terminal prompt. That method relies on preconfiguring a conf file with your country, state, locality, CN, DNS.1 and IP.1 prior to running openssl with appropriate flag values according to https://openwrt.org/docs/guide-user/luci/getting_rid_of_luci_https_certificate_warnings. I want to do a similar thing for the nginx LuCI interface, that is to bring in my local country state etc. The specific certificate details I get from Firefox for the cert it is receiving is:

C                   = ZZ
ST                  = Somewhere
L                   = None
CN                  = OpenWrt

I can only presume the the essential DNS.1 value is not set to match CN and IP.1 is not set to my local 192.168.1.1? So my question is how can I go about regenerating _lan.crt and _lan.key files without messing up the automation structure under /etc/nginx/conf.d/ that OpenWrt nginx devs have kindly put in place? The contents of the default _lan.conf (which I presume is used to manually generate the crt and key files) is:

# default_server for the LAN addresses getting the IPs by:
# ifstatus lan | jsonfilter -e '@["ipv4-address","ipv6-address"].*.address'
server {
        server_name _lan;
        include '/var/lib/nginx/lan_ssl.listen.default';
        ssl_certificate '/etc/nginx/conf.d/_lan.crt';
        ssl_certificate_key '/etc/nginx/conf.d/_lan.key';
        ssl_session_cache 'shared:SSL:32k';
        ssl_session_timeout '64m';
        # access_log /proc/self/fd/1 openwrt; # use logd (init forwards stdout).
        include conf.d/*.locations;
}

It does not contain any of the values previously mentioned (CN DNS.1 etc) and I am unsure of how to include them and regenerate the crt and key.
Trying to sort out the appearance of the security risk message in FF at this stage but really keen to learn and understand this stuff as I intend to be doing more with nginx in OpenWrt.
Thanks, look forward to hearing from you :smile:

Thank you, this is a good hint, I will look if I can integrate it into nginx-util easily (not in the upcoming but maybe the next version).

For now: it should be possible to use openssl-util like in the linked guide, just make sure to have a long enough lifetime of the certificate (nginx-util uses about three years) as nginx-utl checks if the remaining time to expiration is more than a year (else it overwrites the certificate with a new one).

The provided information (CN, ...) go into the certificate (crt and key file), which are used by the nginx configuration file (_lan.conf).

This as a short explanation, I will write more details the next days ...

Now it took me some more days to extend it a bit:

First, I want to suggest to add a permanent exception in Firefox (and to other browsers you do use) the first time you open 192.168.1.1.
So, you will get rid of the warning until the certificate is changed; it is automatically renewed all 2-3 years, then you will have to add the exception again.
But, the yellow exclamation mark in the location bar will still say, it is an insecure connection (although it is secure); it could go away if you follow the guide* (I did not try it).

The security risk shown is because the browser cannot verify that the certificate is the same as on the router. So, theoretically it could have been changed by an adversary on the way from the router to the browser (MitM attack).
To counter this attack, one could let sign the certificate by a CA; the browsers have a set of root certificates containing the certificates of the CA and could verify the signature. But, the CAs sign only global domains (not 192.168.1.1).

The guide* solves the problem by installing the certificate that is used by the router as a root certificate. So, the verification works; you should even be able to use the routers certificate to sign other certificates and they could be verified.
By adding a permanent exception instead, you mark the certificate of the router as trusted in the browser. Then, it is checked against modification; but it is not used for verification.
Both ways follow the concept of certificate pinning and need to be done every time the certificate changes.
For being safe against a MitM attack, you need to check by hand that you have the same certificate as on the router, when you first install it (by the guide* or by adding it as permanent exception).


Although I prefer to add the certificate as a permanent exception, there can be good reasons to exercise the way in the guide* (e.g. for learning and understanding certificate management). It works for Nginx by putting the created certificate and key to /etc/nginx/conf.d/_lan.{crt,key}.
I would suggest creating symlinks, e.g. instead of step 7. and 8. of the guide* use:

ln -sf /etc/ssl/mycert.crt /etc/nginx/conf.d/_lan.crt &&
ln -sf /etc/ssl/mycert.key /etc/nginx/conf.d/_lan.key &&
service nginx restart

If you want to edit the file _lan.conf in /etc/nginx/conf.d/ instead, also rename it and replace it by an empty file (I know this is illogical and inconvenient, sorry; with the new version of the nginx packages you will not need it anymore), e.g. by:

sed -e 's#ssl_certificate .*#ssl_certificate "/e
tc/ssl/mycert.crt";#g' -e 's#ssl_certificate_key .*#ssl_certificate_key "/etc/ss
l/mycert.key";#g' -i /etc/nginx/conf.d/_lan.conf &&
mv /etc/nginx/conf.d/_lan.conf /etc/nginx/conf.d/_mylan.conf &&
touch /etc/nginx/conf.d/_lan.conf &&
service nginx restart

Right now, you have to use the second option if you want to use a certificate that is valid less than a year. I am not sure if you get a warning for a private certificate with a long lifespan (as it is for public ones) ...


The informations from the /etc/ssl/myconfig.conf (CN, DNS.1, …) of the guide* go directly into the certificate: the files /etc/ssl/mycert.{crt,key}. These files are used by the web server (uhttpd in the guide*, Nginx here) to set up encrypted connections.

So, you do not need to have openssl-util and the file /etc/ssl/myconfig.conf on your router at all: You can create the certificate also on another machine (e.g. your PC) and transfer the created files mycert.crt and mycert.key to the router; then you should destroy the mycert.key file from the first machine for security.


*) https://openwrt.org/docs/guide-user/luci/getting_rid_of_luci_https_certificate_warnings