User Tools

Site Tools


docs:guide-user:services:webserver:nginx

Nginx webserver

Nginx is a high-performance HTTP server with other functions as well. It is a perfect candidate to run on OpenWrt due to the performance and memory handling.

Install

We can install Nginx with SSL (using libopenssl) by:

 opkg update && opkg install nginx-ssl 

If we omit the suffix -ssl, we get Nginx without SSL support.

Of course there will be port issues if we installed LuCI before or after Nginx, since the standard LuCI package installs uHTTPd, which also wants to claim port 80 (and port 443 for HTTPS). So configuring and/or portforwarding may be neccessary. There are ways to run LuCI with Nginx but that is not coverd here. For a quick fix, just change the uhttpd port to something else in /etc/config/uhttpd.

Configuration

The official Documentation contains a Admin Guide. Here we will look at some often used configuration parts and how we handle them at OpenWrt. At different places there are references to the official Technical Specs for further reading.

Basic

We modify the configuration by creating different configuration files in the /etc/nginx/conf.d/ directory. The configuration files use the file extensions .locations and .conf (plus .crt and .key for Nginx with SSL). We can disable single configuration parts by giving them another extension, e.g., by adding .disabled. For the new configuration to take effect, we must reload it by:

service nginx reload

For OpenWrt we use a special initial configuration, which is explained below in the section OpenWrt’s Defaults. So, we can make a site available at a specific URL in the LAN by creating a .locations file in the directory /etc/nginx/conf.d/. Such a file consists just of some location blocks. Under the latter link, you can find also the official documentation for all available directives of the HTTP core of Nginx. Look for location in the Context list.

The following example provides a simple template, see at the end in the different Locations for Apps and look for other packages using a .locations file, too:

/etc/nginx/conf.d/example.locations
location /ex/am/ple {
    access_log off; # default: not logging accesses.
    # access_log /proc/self/fd/1 openwrt; # enable logd (init forwards stdout).
    # error_log stderr; # default: logging to logd (init forwards stderr).
    error_log /dev/null; # disable error logging after config file is read.
    # (state the path of a file for access_log/error_log to the file instead.)
    index index.html;
}
# location /eg/static { … }

All location blocks in all .locations files must use different URLs, since they are all included in the _lan.conf that is part of the OpenWrt’s Defaults. We reserve the location / for making LuCI available under the root URL, e.g. 192.168.1.1/. All other sites shouldn’t use the root location / without suffix. We can make other sites available on the root URL of other domain names, e.g. on www.example.com/. In order to do that, we create a .conf file for every domain name: see the next section New Server Parts. For Nginx with SSL we can also activate SSL there, as described below in the section SSL Server Parts. We use such server parts also for publishing sites to the internet (WAN) instead of making them available just in the LAN.

Via .conf files we can also add directives to the http part of the configuration. The difference to editing the main /etc/nginx/nginx.conf file instead is the following: If the package’s nginx.conf file is updated it will only be installed if the old file has not been changed.

New Server Parts

For making the router reachable from the WAN at a registered domain name, it is not enough to give the name server the internet IP address of the router (maybe updated automatically by a DDNS Client). We also need to set up virtual hosting for this domain name by creating an appropriate server part in a /etc/nginx/conf.d/*.conf file. All such files are included at the start of Nginx by the default main configuration of OpenWrt /etc/nginx/nginx.conf as depicted in OpenWrt’s Defaults.

In the server part, we state the domain as server_name. The link points to the same document as for the location blocks in the Basic Configuration: the official documentation for all available directives of the HTTP core of Nginx. This time look for server in the Context list, too. The server part should also contain similar location blocks as before. We can re-include a .locations file that is included in the server part for the LAN by default. Then the site is reachable under the same path at both domains, e.g., by http://192.168.1.1/ex/am/ple as well as by http://example.com/ex/am/ple.

The OpenWrt’s Defaults include a _lan.conf file containing a server part that listens on the LAN address(es) and acts as default_server. For making the domain name accessible in the LAN, too, the corresponding server part must listen explicitly on the local IP address(es), cf. the official documentation on request_processing. We can include the file /var/lib/nginx/lan.listen that contains the listen directives for all LAN addresses on the HTTP port 80 and is automatically updated.

The following example is a simple template, see such server parts of other packages, too:

conf.d/example.com.conf
server {
    listen 80;
    listen [::]:80;
    include '/var/lib/nginx/lan.listen';
    server_name example.com;
    # location / { … } # root location for this server.
    include 'conf.d/example.com.locations';
}

SSL Server Parts

We can enable HTTPS for a domain if Nginx is installed with SSL support. We need a SSL certificate as well as its key and add them by the directives ssl_certificate respective ssl_certificate_key to the server part of the domain. The rest of the configuration is similar as described in the previous section New Server Parts, we only have to adjust the listen directives by adding the ssl parameter, see the official documentation for configuring HTTPS servers, too. For making the domain available also in the LAN, we can include the file /var/lib/nginx/lan_ssl.listen that contains the listen directives with ssl parameter for all LAN addresses on the HTTPS port 443 and is automatically updated.

The official documentation of the SSL module contains an example, which includes some optimizations. The following template is extended similarly, see also other packages providing SSL server parts:

/etc/nginx/conf.d/example.com
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    include '/var/lib/nginx/lan_ssl.listen';
    server_name example.com;
    ssl_certificate 'conf.d/example.com.crt';
    ssl_certificate_key 'conf.d/example.com.key';
    ssl_session_cache shared:SSL:32k;
    ssl_session_timeout 64m;
    # location / { … } # root location for this server.
    include 'conf.d/example.com.locations';
}

For creating a certificate (and its key) we can use Let’s Encrypt by installing ACME Shell Script:

opkg update && opkg install acme # and for LuCI: luci-app-acme

For the LAN server in the _lan.conf file, the init script /etc/init.d/nginx script installs automatically a self-signed certificate. We can use this mechanism also for other sites by issuing, e.g.:

service nginx add_ssl example.com
  1. This checks if there is a valid certificate and key for the given domain name or tries to create a self-signed one if possible. We can install a tool by:
    opkg update && opkg install openssl-util
  2. Then it adds SSL directives to the server part of conf.d/example.com.conf like in the example above.
  3. When cron is activated, it installs a cron job for renewing the certificate every year if needed, too. We can activate cron by:
    service cron enable && service cron start

Beside the _lan.conf file, the OpenWrt’s Defaults include also the _redirect2ssl.conf file containing a server part that redirects all HTTP request for inexistent URIs to HTTPS.

OpenWrt’s Defaults

The default main configuration file is:

/etc/nginx/nginx.conf
# Please consider creating files in /etc/nginx/conf.d/ instead of editing this.
# For details see https://openwrt.org/docs/guide-user/services/webserver/nginx
 
user nobody nogroup;
 
events {}
 
http {
    access_log off;
    log_format openwrt '$request_method $scheme://$host$request_uri => $status'
        ' (${body_bytes_sent}B in ${request_time}s) <- $http_referer';
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
 
    client_max_body_size 17M;
    large_client_header_buffers 2 1k;
 
    gzip on;
    gzip_vary on;
    gzip_proxied any;
 
    root /www;
 
    include conf.d/*.conf;
}

We can pretend the main configuration contains also the following presets, since Nginx is configured with them:

pid "/var/run/nginx.pid";
lock_file "/var/lock/nginx.lock";
error_log "stderr";
proxy_temp_path "/var/lib/nginx/proxy";
client_body_temp_path "/var/lib/nginx/body";
fastcgi_temp_path "/var/lib/nginx/fastcgi";

So, the access log is turned off by default and we can look at the error log by logread, as Nginx’s init file forwards stderr and stdout to the logd. We can set the error_log and access_log to files where the log messages are forwarded to instead (after the configuration is read). And for redirecting the access log of a server or location to the logd, too, we insert the following directive in the corresponding block:

    access_log /proc/self/fd/1 openwrt;

At the end, the main configuration pulls in all .conf files from the directory /etc/nginx/conf.d/ into the http block, especially the following server part for the LAN:

/etc/nginx/conf.d/_lan.conf
# default_server for the LAN addresses got by: ifstatus lan | grep '"address"'
server {
    include '/var/lib/nginx/lan.listen.default';
    server_name _lan;
    include conf.d/*.locations;
}

It pulls in all .locations files from the directory /etc/nginx/conf.d/. We can install the location parts of different sites there (see above in the Basic Configuration) and re-include them in server parts of other /etc/nginx/conf.d/*.conf files. This is needed especially for making them available to the WAN as described above in the section New Server Parts. All .locations become available on the LAN through the file lan.listen.default, which contains one of the following directives for every local IP address:

         listen IPv4:80 default_server;
         listen [IPv6]:80 default_server;

The /var/lib/nginx/lan.listen file contains the same directives without the parameter default_server. We can include this file in other server parts that should be reachable in the LAN through their server_name. Both files /var/lib/nginx/lan.listen{,.default} are (re-)created if Nginx starts through its init for OpenWrt or the LAN interface changes.

Additional Defaults for OpenWrt if Nginx is installed with SSL support

When Nginx is installed with SSL support, there will be automatically managed files lan_ssl.listen.default and lan_ssl.listen in the directory /var/lib/nginx/ containing the following directives for all IPv4 and IPv6 addresses of the LAN:

         listen IP:443 ssl; # with respectively without: default_server

Both files as well as the /var/lib/nginx/lan.listen{,.default} files are (re-)created if Nginx starts through its init for OpenWrt or the LAN interface changes.

For Nginx with SSL there is also the following server part that redirects requests for an inexistent server_name from HTTP to HTTPS (using an invalid name, more in the official documentation on request_processing):

/etc/nginx/conf.d/_redirect2ssl.conf
# acts as default server if there is no other.
server {
    listen 80;
    listen [::]:80;
    include '/var/lib/nginx/lan.listen';
    server_name _redirect2ssl;
    return 302 https://$host$request_uri;
}

Nginx’s init file for OpenWrt installs automatically a self-signed certificate for the LAN server part if needed and possible:

  1. Everytime Nginx starts, we check if the LAN has already a valid ssl certificate and key in /etc/nginx/conf.d/_lan.{crt,key}
  2. If there is no valid certificate, we try to create a self-signed one. That needs px5g or openssl-util to be installed, though.
  3. When there exists a certificate, we add corresponding ssl* directives (like in the example of the previous section SSL Server Parts) to the configuration file /etc/nginx/conf.d/_lan.conf if needed and if it looks “normal”, i.e., it has a server_name _lan; part.
  4. When there is a valid certificate for the LAN, we activate ssl by including the ssl listen directives from /var/lib/nginx/lan_ssl.listen.default and it becomes available by the default redirect from listen *:80; in /etc/nginx/conf.d/_redirect2ssl.conf
  5. If cron is available, i.e., its status is not inactive, we use it to check the certificate for validity once a year and renew it if there are only 13 months of the more than 3 years life time left.

The points 2, 3 and 5 can be used for other domains, too: As described in the section New Server Parts above, we create a server part in /etc/nginx/conf.d/www.example.com.conf with a corresponding server_name www.example.com; directive and call

/etc/init.d/nginx add_ssl www.example.com

Locations for Apps

For an overview see the official Admin Guide of Nginx on Reverse Proxy. For logging look at the example in the Basic Configuration, too. Remember to restart Nginx after changing its configuration by:

service nginx reload

PHP with FastCGI

Install PHP using FastCGI:

 opkg update && opkg install php7-fastcgi

In the Nginx configuration we can include the file fastcgi_params, which is installed by default. We create a .location file like the following, see other packages using fastcgi_pass and Nginx's Wiki has a PHP FastCGI Example, too:

/etc/nginx/conf.d/php.locations
location ~ [^/]\.php$ {
    #error_log /dev/null;
    fastcgi_connect_timeout 300s;
    fastcgi_read_timeout 300s;
    fastcgi_send_timeout 300s;
    fastcgi_buffer_size 32k;
    fastcgi_buffers 4 32k;
    fastcgi_busy_buffers_size 32k;
    fastcgi_temp_file_write_size 32k;
    client_header_timeout 10s;
    client_body_timeout 10s;
    send_timeout 60s; # default, increase if experiencing a lot of timeouts.
    output_buffers 1 32k;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param HTTP_PROXY ""; # Mitigate https://httpoxy.org/ vulnerability.
    if (-f ) {
            # Only throw it at PHP-FPM if file exists (prevents PHP exploits).
            fastcgi_pass    127.0.0.1:1026;  # or: unix:/var/run/php-fpm.sock;
    }
}
/etc/php.ini
doc_root = "YOUR/DOCUMENT/ROOT"
cgi.force_redirect = 1
cgi.redirect_status_env = "yes";

uWSGI

Install uWSGI and needed plugins:

opkg update && opkg install uwsgi # and the plugin(s) used. 

In the Nginx configuration we can include the file uwsgi_params, which is installed by default. We create a .location file like the following, see also other packages using uwsgi_pass and the uWSGI documentation for Nginx, too:

/etc/nginx/conf.d/mysite.locations
location /mysite {
    # error_log /dev/null;
    include  /etc/nginx/uwsgi_params;
    uwsgi_pass unix:///var/run/mysite.socket;
    # for CGI (like in LuCI):
    # uwsgi_param SERVER_ADDR $server_addr;
    # uwsgi_modifier1 9;
}

For uWSGI, we create a configuration handling the application like the following, see other packages using uWSGI, too:

/etc/uwsgi/vassals/mysite.ini
[uwsgi]
strict = true
; adjust the needed plugins, path, name, user and socket for the application:
plugin = 
chdir = /path/to/app
mount = /mysite=app
; or use cgi = /mysite=/path/or/executable
uid = user
gid = nogroup
chmod-socket = 660
chown-socket = user:nogroup
; Nginx runs as nouser:nogroup
if-not-env = UWSGI_EMPEROR_FD
socket = /var/run/mysite.socket
vacuum = true
; cheap = true
end-if =
disable-logging = true
log-format=%(method) %(uri) => return %(status) (%(rsize) bytes in %(msecs) ms)
manage-script-name = true
thunder-lock = true
enable-threads = true
threads = 3
master = true
; processes = 3
; cheaper-algo = spare
; cheaper = 1
; cheaper-initial = 1
; cheaper-step = 1
; lazy-apps = true
; harakiri = 60
; idle = 360
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
docs/guide-user/services/webserver/nginx.txt · Last modified: 2019/11/29 08:11 by peter-stadler