Customizing NGINX
nginx=1
for Nginx-only processing with Nginx reverse proxy
per-domain If you're running with the custombuild options.conf
setting webserver=nginx_apache
, where apache is behind an nginx proxy, then by default, all domains are listed in both the User nginx.conf
and httpd.conf
. All connections run through the nginx.conf
, and some requests are passed through to apache as needed while static files are processed by nginx.
This feature lets you shut off the proxy part, just for 1 domain, such that the domain is processed 100% by nginx, without using apache at all. PHP is still enabled for the nginx-only domain, which must use php-fpm just like stand-alone nginx.
To enable this for a given domain, add:
nginx=1
to the domain's config in:
/usr/local/directadmin/data/users/FRED/domains/DOMAIN.COM.conf
and issue a rewrite:
da build rewrite_confs
JSON and Relative CMD_* calls
CMD_NGINX_TEMPLATES
View the state of a domain
CMD_ADDITIONAL_DOMAINS?action=view&domain=testdomain%2Ecom&ipp=50&json=yes&redirect=yes
is a dump of the domain.com.conf
file, and will include this if enabled:
nginx=1
Also:
HAS_PER_DOMAIN_NGINX=yes
will be shown if this value is allowed to be controlled.
nginx=1
setting
Saving the CMD_DOMAIN
method: POST
action=modify
domain=testdomain.com
form_version=1.1
...
nginx=1
Save along with all other settings (php, cgi, etc), OR you can save just this item:
method: POST
action=modify
domain=testdomain.com
only_affect=nginx
nginx=1
Disabling per-domain Nginx-only processing
To disable per-domain Nginx-only processing, use either:
nginx=0
or simply omit the nginx variable entirely, as it is a checkbox, in which the absence of a value equates to 'off'.
Related Skin Changes and Tokens
Within the following file:
/usr/local/directadmin/data/skins/enhanced/user/modify_domain.html
the following has been added after php:
|*if HAS_PER_DOMAIN_NGINX="yes"|
<tr>
<td>|LANG_NGINX_ONLY|</td>
<td align=center><input type="checkbox" name="nginx" value="1" |NGINX_CHECKED|></td>
<td>|LANG_NGINX_ONLY_DESC|</td>
</tr>
|*endif|
Language tokens have been added as well to the file:
/usr/local/directadmin/data/skins/enhanced/lang/en/user/modify_domain.html
which includes:
LANG_NGINX_ONLY=Nginx-Only
LANG_NGINX_ONLY_DESC=Use only Nginx. Proxy to apache is disabled.
User selectable Nginx templates
This feature allows Users to select from pre-made templates to be inserted into the nginx server entries for common scripts like WordPress. The list of templates can be managed through DA.
This is a JSON-only feature, so Enhanced will not have it, though Evolution will.
It will apply only to domains and not to subdomains (similar to E-Mail accounts). Should you need an nginx template on a subdomain, create it as a full domain instead.
JSON and Relative CMD_* calls
CMD_NGINX_TEMPLATES
View the list of Nginx templates
To view the list of nginx templates, and to view the current locations for the domain:
CMD_NGINX_TEMPLATES
method: GET
domain=domain.com
Output will resemble the following:
{
"locations":
{
"/wordpress":
{
"nginx_template": "wordpress_with_fastcgi_cache"
}
},
"settings":
{
"domain_nginx": "0",
"nginx": "1",
"nginx_proxy": "0"
},
"templates":
{
"wordpress_with_fastcgi_cache":
{
"name": "WordPress",
"path": "/etc/nginx/templates/wordpress_with_fastcgi_cache.conf"
}
}
}
The domain_nginx
setting will be set to 1
when:
directadmin.conf
has:
nginx=0
nginx_proxy=1
And...
/usr/local/directadmin/data/users/fred/domains/domain.com.conf
has:
nginx=1
Related: Nginx-only processing for specified domains via the Nginx Reverse Proxy setup
If you have both settings[nginx]
and settings[domain_nginx]
as 0
(but nginx_proyx=1
),then you'd need to throw a warning (as no POSTs will be accepted) advising the User to enable the domain nginx=1
via the only_affect=nginx
option: https://www.directadmin.com/features.php?id=2953
Saving a template location setting
To set a given location to a template, use:
CMD_NGINX_TEMPLATES
method: POST
domain=domain.com
action=save
location=/wordpress
nginx_template=wordpress_with_fastcgi_cache
Deleting a template location setting
To clear a list of template locations, use:
CMD_NGINX_TEMPLATES
method: POST
domain=domain.com
action=delete
select1=/wordpress
(select2=/otherpath)
Relative Tokens
The following global token exists:
HAVE_NGINX_TEMPLATES=yes|no
if the feature is available in the current license.
Relative Templates
CustomBuild will manage the templates in /etc/nginx/templates/*.conf
.
The format of the template will be a standard nginx code to be inserted into an nginx location block. The first line of the template is a data line, and should contain something like this:
#INFO=name=WordPress
where everything after the #INFO=
string is url-encoded, allowing for extra vars in the future. If you do not specify the name, DA will name it the name of the file, less .conf (wordpress_with_fastcgi_cache).
Before the Include to this file, dA will set the $template_location
variable to "/wordpress", for example, which can be used in the Included template conf.
location ~ ^(/wordpress)(/.*)?$
{
set $template_location "$1/";
Include /etc/nginx/templates/wordpress_with_fastcgi_cache.conf;
include /usr/local/directadmin/data/users/testuser/nginx_php.conf;
}
DirectAdmin will store the list of locations in:
/usr/local/directadmin/data/users/USERNAME/domains/DOMAIN.COM.locations.json
which is a json file, listing each location. Each location is an array, and the sub-item that applies here would be the template name, eg:
{
"/wordpress" : {
"nginx_template" : "wordpress_with_fastcgi_cache"
}
}
as this leaves other options which could be set for that location in the future.
Nginx locations: new internal structure for tokens
As nginx locations are quite rigid in terms of not allowing conflicts/duplicates, we've hit the point where in order to allow 2 features to use the same location block, internal management is now required.
The following global token will indicate if the feature is available:
HAVE_NGINX_TEMPLATES=yes|no
Relative Templates
The templates exist here:
nginx_server.conf
nginx_server_sub.conf
nginx_server_secure.conf
nginx_server_secure_sub.conf
The old content was as follows:
|*else|
|UNIT_PROXY|
|NGINX_REDIRECTS|
|PROTECTED_DIRECTORIES|
|HOTLINK_PROTECTION|
|EXTRA_LOCATIONS|
|*endif|
And the new content is as follows:
|*else|
|HOTLINK_PROTECTION|
|EXTRA_LOCATIONS|
|LOCATION_BLOCKS|
|*endif|
Using custom global templates with Nginx
This guide will describe how to set up customized global per-User/Domain templates so that your Nginx server configuration can be changed however you need. Note that this guide is a mirror of the similar guide for Apache.
Copy the templates to the custom area:
cd /usr/local/directadmin/data/templates/custom
cp ../nginx_*.conf .
There are many templates for Nginx, so if there are any that you don't need to change, you can delete them from the custom folder and the defaults will be used. Templates in the custom folder override the default templates.
The rest of the changes are very similar to the Apache guide and share essentially the same TOKENS. If you want to see all tokens that you have to work with, you can use the |DUMPTOKENS| token in the Nginx configuration file, issue a rewrite, and it will add all tokens and their values to your configs. Of course, this won't be syntactically valid, but it will let you see what you can work with.
When you want to issue a rewrite to try your new configs, type:
da build rewrite_confs
How to add a custom module to Nginx
If you want to add any extra modules to Nginx, they'll most likely need to be compiled in. Any module that needs to be compiled in will have a --add-module
type flag which will need to be used. To add this flag, run the following:
cd /usr/local/directadmin/custombuild
mkdir -p custom/nginx
cp -fp configure/nginx/configure.nginx custom/nginx/configure.nginx
Add your --add-module
line to the end of the custom/nginx/configure.nginx file, and make sure the \ character exists at the end of all lines except the last one. The \ character tells the configure line to loop to the next line, making the configure settings easier to read. Without the \ character to trigger the wrap, the next line becomes a separate command, which is not correct. Once set, type:
./build used_configs
to ensure your custom configure.nginx file is being used. Then type:
da build nginx
How to enable PUT and DELETE methods in Nginx
Use the same guide as is used for Apache as it is applicable to Nginx also.
How to force HTTPS with Nginx
If you're running Nginx, go to Admin Level -> Custom Httpd Config -> example.com and in token |CUSTOM4|, add this code:
|*if SSL_TEMPLATE="0"|
return 301 https://$host$request_uri;
|*endif|
How to configure a wildcard *.example.com subdomain with Nginx
This guide is an extension of the Apache version and applies to a server running just Nginx or Apache with Nginx as a proxy (nginx_proxy).
Use step 1 in the other guide to setup the DNS in the same manner.
Use the tool Admin Level -> Custom HTTPD Configuration -> domain.com to edit the Nginx configuration and add this code into the top text area:
server_name *.|DOMAIN|;
In a similar method to that used in the Apache guide, if you want normal control of other subdomains and the full domain, you'll use the zzzz subdomain method:
|*if SUB="zzzz"|
server_name *.|DOMAIN|;
|*endif|
How to setup webmail.example.com with Nginx
Similar to the Apache version of this guide, Nginx has the ability to set up a webmail.domain.com subdomain using the templates.
In this example, we'll be setting up a subdomain for Roundcube, so adjust the value on the left as desired (eg: roundcube or any other script you have in /var/www/html).
- You'll need to setup the server section for the webmail subdomain. This can be accomplished by adding a 2nd server section below the domain's main server section.
cd /usr/local/directadmin/data/templates/
cp nginx_server.conf custom/
cp nginx_server_secure.conf custom/
cd custom/
- Edit this copied nginx_server.conf, and at the bottom of the template below the existing server section, add this 2nd server section:
server
{
listen |IP|:|PORT_80|;
|MULTI_IP|
server_name webmail.|DOMAIN|;
root /var/www/html/roundcube;
index index.php index.html index.htm;
access_log /var/log/nginx/domains/|DOMAIN|.log;
access_log /var/log/nginx/domains/|DOMAIN|.bytes bytes;
error_log /var/log/nginx/domains/|DOMAIN|.error.log;
|*if HAVE_PHP1_FPM="1"|
# use fastcgi for all php files
location ~ \.php$
{
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include /etc/nginx/fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/nginx_limits.conf;
if (-f $request_filename)
{
fastcgi_pass unix:/usr/local/php|PHP1_RELEASE|/sockets/webapps.sock;
}
}
|*endif|
|*if HAVE_NGINX_PROXY="1"|
location /
{
# access_log off;
proxy_pass http://127.0.0.1:|PORT_8080|;
proxy_set_header X-Client-IP $remote_addr;
proxy_set_header X-Accel-Internal /nginx_static_files;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /nginx_static_files/
{
# access_log /var/log/nginx/access_log_proxy;
alias /var/www/html/roundcube/;
internal;
}
|*endif|
# deny access to apache .htaccess files
location ~ /\.ht
{
deny all;
}
}
- Also modify the secure host nginx_server_secure.conf file. Add:
server
{
listen |IP|:|PORT_443| ssl|SPACE_HTTP2|;
|MULTI_IP|
server_name webmail.|DOMAIN|;
root /var/www/html/roundcube;
index index.php index.html index.htm;
access_log /var/log/nginx/domains/|DOMAIN|.log;
access_log /var/log/nginx/domains/|DOMAIN|.bytes bytes;
error_log /var/log/nginx/domains/|DOMAIN|.error.log;
ssl_certificate |CERT|;
ssl_certificate_key |KEY|;
|*if HAVE_PHP1_FPM="1"|
# use fastcgi for all php files
location ~ \.php$
{
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include /etc/nginx/fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/nginx_limits.conf;
if (-f $request_filename)
{
fastcgi_pass unix:/usr/local/php|PHP1_RELEASE|/sockets/webapps.sock;
}
}
|*endif|
|*if HAVE_NGINX_PROXY="1"|
location /
{
proxy_buffering |PROXY_BUFFERING|;
proxy_pass https://|PROXY_IP|:|PORT_8081|;
proxy_set_header X-Client-IP $remote_addr;
proxy_set_header X-Accel-Internal /nginx_static_files;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header Upgrade;
}
location /nginx_static_files/
{
# access_log /var/log/nginx/access_log_proxy;
alias /var/www/html/roundcube/;
internal;
}
|*endif|
# deny access to apache .htaccess files
location ~ /\.ht
{
deny all;
}
}
- Save, exit, then rewrite users' nginx.conf files with:
da build rewrite_confs
- You'll also need to setup the DNS portion.
cd /usr/local/directadmin/data/templates
cp dns_a.conf custom
cd custom
echo "webmail=|IP|" >> dns_a.conf
This will setup the webmail A record for new DNS zones. For existing DNS zones, you'll have to manually add the webmail A record to point to the domains' IPs.
How to activate web cache. Cache-Control HTTP headers
For a bit of threory, please check the apache section.
Activating per domain
Per domain caching can be activated via DirectAdmin admin page -> Custom HTTPD configuration -> find a domain -> nginx.conf , click CUSTOMIZE and in the CUSTOM3 tab, enter the following:
location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico)$ { expires 30d; add_header Cache-Control "public, no-transform"; }
location ~* \.(jpg|jpeg|gif|png|svg)$ {expires 365d;}
location ~* \.(pdf|css|html|js|swf)$ {expires 2d;}
Activating for all domains
To activate globally for all domains, create a directory:
mkdir -p /usr/local/directadmin/data/templates/custom/
cd /usr/local/directadmin/data/templates/custom/
And create a file called cust_nginx.CUSTOM.post
, insert the same code as used above for activating for a single domain, and rewrite configs:
da build rewrite_confs
How to install the Pagespeed Nginx module
Mod_pagespeed is an open-source Apache HTTP Server (or Nginx) module, which automatically applies chosen filters to pages and associated assets such as stylesheets, JavaScript, and HTML files, as well as to images and website cache requirements.
One major advantage of this module is that it does not require modifications to existing content or workflow, meaning that all internal optimizations and changes to files are made on the server side, presenting modified files directly to the user. Each of 40+ filters correspond to one of Google's web performance best practices rules.
Tested with Nginx on CentOS 8:
- Follow the official documentation concerning the module installation from https://www.modpagespeed.com/doc/build_ngx_pagespeed_from_source (see the "Build instructions" section):
- Check https://www.modpagespeed.com/doc/release_notes for the latest version (as of today it is "1.13.35.2-stable"):
NPS_VERSION=1.13.35.2-stable
cd
wget https://github.com/apache/incubator-pagespeed-ngx/archive/v${NPS_VERSION}.zip
unzip v${NPS_VERSION}.zip
nps_dir=$(find . -name "*pagespeed-ngx-${NPS_VERSION}" -type d)
cd "$nps_dir"
NPS_RELEASE_NUMBER=${NPS_VERSION/beta/}
NPS_RELEASE_NUMBER=${NPS_VERSION/stable/}
psol_url=https://dl.google.com/dl/page-speed/psol/${NPS_RELEASE_NUMBER}.tar.gz
[ -e scripts/format_binary_url.sh ] && psol_url=$(scripts/format_binary_url.sh PSOL_BINARY_URL)
wget ${psol_url}
tar -xzvf $(basename ${psol_url})
- Customize the Nginx config file to add the external module:
cd /usr/local/directadmin/custombuild/
mkdir -p custom/nginx
cp configure/nginx/configure.nginx custom/nginx/
Open the custom/nginx/configure.nginx
file and add the following option before the last string:
"--add-module=/root/incubator-pagespeed-ngx-1.13.35.2-stable" \
And build nginx:
da build nginx
When completed, you should see the "--add-module=/root/incubator-pagespeed-ngx-1.13.35.2-stable" in the output of:
nginx -V
- Create the working directory:
mkdir -p /var/cache/ngx_pagespeed
Open the /etc/nginx/nginx-includes.conf
file and add the following to enable the module globally:
pagespeed on;
pagespeed FileCachePath /var/cache/ngx_pagespeed;
pagespeed EnableFilters flatten_css_imports;
And restart Nginx:
systemctl restart nginx
- Test if it is working with:
curl -ILs domain.com | grep X-Page-Speed
You should be able to find text similar to the following in curl's output:
X-Page-Speed: 1.13.35.2-0
Adding security headers to get A+ rating
This guide is similar to the apache guide for adding security headers, but is tailored to the Nginx webserver. You may refer to the mentioned Apache guide for generalized information regarding security headers and online tools for testing them. Here are the instructions for accomplishing the same with Nginx:
Create the
/usr/local/directadmin/data/templates/custom/cust_nginx.CUSTOM.post
filePost the code:
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1";
add_header X-Download-Options "noopen";
add_header X-Permitted-Cross-Domain-Policies "master-only";
add_header X-DNS-Prefetch-Control "on";
add_header Referrer-Policy "no-referrer-when-downgrade";
add_header Strict-Transport-Security "max-age=31536000";
add_header Content-Security-Policy "block-all-mixed-content";
add_header Permissions-Policy 'geolocation=*, midi=(), sync-xhr=(self "https://|DOMAIN|" "https://www.|DOMAIN|"), microphone=(), camera=(), magnetometer=(), gyroscope=(), payment=(), fullscreen=(self "https://|DOMAIN|" "https://www.|DOMAIN|" )';
- And rewrite configs:
da build rewrite_confs
How to enable brotli compression
- Extract brotli under any path you prefer. In this case I chose to to extract it in the base of the custombuild directory.
cd /usr/local/directadmin/custombuild
mkdir brotli
git clone https://github.com/google/ngx_brotli.git brotli
cd brotli && git submodule update --init && cd ..
- Add a custom
add-module
directive.
mkdir -p custom/nginx
cp -p ./configure/nginx/configure.nginx custom/nginx/
Add the following somewhere before the last configuration line in custom/nginx/configure.nginx
"--add-module=/usr/local/directadmin/custombuild/brotli" \
make sure to substitute /usr/local/directadmin/custombuild/brotli
with whatever path it's been extracted under.
- rebuild nginx
da build nginx
This should have compiled nginx with the brotli module.
You can configure brotli by modifying /etc/nginx/nginx-includes.conf
. Refer to the documentation found here.
- To test that the configuration was successful, add the following to
/etc/nginx/nginx-includes.conf
:
brotli on;
brotli_static on;
Restart nginx
systemctl restart nginx
curl one of your domains (exampledomain.com in this example).
curl -kL -I -H 'Accept-Encoding: br' http://exampledomain.com 2>&1 | grep -i encoding
If successful, the following output should be returned
Content-Encoding: br