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.
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
.
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.
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:
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.
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:
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'; }
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:
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
opkg update && opkg install openssl-util
conf.d/example.com.conf
like in the example above.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.
The default main configuration file is:
# 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:
# 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.
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):
# 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:
/etc/nginx/conf.d/_lan.{crt,key}
px5g
or openssl-util
to be installed, though./etc/nginx/conf.d/_lan.conf
if needed and if it looks “normal”, i.e., it has a server_name _lan;
part./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
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
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
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:
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; } }
doc_root = "YOUR/DOCUMENT/ROOT" cgi.force_redirect = 1 cgi.redirect_status_env = "yes";
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:
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:
[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