Nginx is pronounced engine x. It is a light weight http and proxy server. “Why I should use a different web server then Apache2?” you might ask. Nginx has some advantages and disadvantages. The advantage of Nginx it is very fast for simple configured web pages, especially for only one domain. However large installation with complex processing, one can almost say middle ware, Apache2 is the choice.
Under Debian Wheezy, Jessie, Stretch and Buster (and probably others):
aptitude install nginx
Nginx is already serving pages. More precisely one page. A welcome page. Look at
http://127.0.0.1/
The configuration under Debian is similar to Apache2 in regard to the file location. First you crate a file under /etc/nginx/sites-available and then you make a link to /etc/nginx/sites-anabled.
.
|-- conf.d
|-- fastcgi.conf
|-- fastcgi_params
|-- koi-utf
|-- koi-win
|-- mime.types
|-- nginx.conf
|-- proxy_params
|-- scgi_params
|-- sites-available
| `-- default
|-- sites-enabled
| `-- default -> /etc/nginx/sites-available/default
|-- snippets
| |-- fastcgi-php.conf
| `-- snakeoil.conf
|-- uwsgi_params
`-- win-utf
You might edit the default site, which is already enabled. Or you just copy content to /var/www/html. Of course you have to overwrite index.html to see your content, since this page will be delivered first. An alternative might be to create a directory /var/www/html/dragon to serve your favorite pictures of dragons (or what ever).
In the latter case look at:
http://127.0.0.1/dragon/
When using nginx a server block is similar to a virtual host under Apache2.
Nginx on Debian 9 has one server block enabled by default that is configured to serve documents out of a directory at /var/www/html. While this works well for a single site, it can become difficult if multiple sites are hosted. The domain in this is example is called D1, however you should imagine something like example.com.
mkdir -p /opt/www/domain/D1/html
vim /opt/www/domain/D1/html/index.html
vim /etc/nginx/sites-available/exmaple.com
server {
listen 80;
listen [::]:80;
root /opt/www/domain/D1/html;
index index.html index.htm index.nginx-debian.html;
server_name D1;
location / {
try_files $uri $uri/ =404;
}
}
ln -s /etc/nginx/sites-available/D1 \
/etc/nginx/sites-enabled/D1
nginx -t
systemctl restart nginx
After certbot run was successful this is converted to:
server {
listen 80;
listen [::]:80;
root /opt/www/domain/D1/html;
index index.html index.htm index.nginx-debian.html;
server_name D1;
location / {
try_files $uri $uri/ =404;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/D1/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/D1/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
Copy the following into the file /etc/nginx/sites-available/wizzards
server {
listen 8080 default_server;
listen [::]:8080 default_server;
root /var/www/wizzards;
index index.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
}
Then make a link and restart Nginx
cd /etc/nginx/sites-eanabled
ln -s /etc/nginx/sites-available/wizards .
service nginx restart
Of course you have to create the directory:
mkdir /var/www/wizards
And copy HTML content into it. Not wizards.
Now look at:
http://127.0.0.1:8080/
When looking at
https://www.ssllabs.com/ssltest/analyze.html?d=www.DOMAIN.de
It seems that TLSv1.0 and TLSv1.1 are better to be disabled.
Check with:
nmap --script ssl-enum-ciphers -p 443 81.169.254.165|grep TLSv
| TLSv1.0:
| TLSv1.1:
| TLSv1.2:
Change
vim /etc/nginx/nginx.conf
#ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_protocols TLSv1.2; # Dropping SSLv3, ref: POODLE
Restart Nginx
Check again with:
nmap --script ssl-enum-ciphers -p 443 81.169.254.165|grep TLSv
| TLSv1.2:
HOWEVER if you use certbot than it will use its own TLS configuration:
/etc/letsencrypt/options-ssl-nginx.conf
There seems no way to specify with certbot what TLS version to allow.
This seems more common this day to build some kind of web application that delivers parts of the content over a certain port.
location /auth/ {
proxy_buffers 16 4k;
proxy_buffer_size 2k;
proxy_bind 127.0.0.1;
proxy_pass http://127.0.0.1:4000/auth/
}
For some users this is convenient. Other user who are not using their own browser or who do not understand how to switch the language of their browser are basically screwed with this setup. But non the less here it is how it is done. (That was the long way to say: don’t do it)
server {
listen 127.0.0.1:80 default_server;
server_name localhost;
root /var/www/html;
index index.html;
set $first_language $http_accept_language;
if ($http_accept_language ~* '^(.+?),') {
set $first_language $1;
}
set $language 'en';
if ($first_language ~* 'de') {
set $language 'de';
}
location / {
try_files $uri/index.$language.html $uri $uri/ =404;
}
}
The section title could also be called ‘How to serve multiple virtual domains with Certbot and Nginx’. Usually it is very easy to serve virtual domains with nginx. Either add a file with a ‘server’ block or add a new ‘server’ block to the file /etc/nginx/sites-available/default. However in the case a part of this file (default) is managed by Certbot it is easier to manage all domains with a single ‘server’ block, as other parts are managed by Certbot. This is how a default configuration looks like. Comments are removed, indentation changed from tab to two spaces and $host names (domains, like example.com) have been replaced by all caps: D1 and D2.
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
}
server {
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name www.D1 D1 www.D2; # managed by Certbot
location / {
try_files $uri $uri/ =404;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/D1/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/D1/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.D1) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = D1) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = www.D2) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 ;
listen [::]:80 ;
server_name www.D1 D1 www.D2;
return 404; # managed by Certbot
}
This solution is rather simple. Add a line with the $host variable to the https location, like so: root /opt/www/domain/$host; (and you may or may not remove the other root statement.
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
}
server {
index index.html index.htm index.nginx-debian.html;
server_name www.D1 D1 www.D2; # managed by Certbot
location / {
try_files $uri $uri/ =404;
root /opt/wwww/domain/$host;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/D1/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/D1/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.D1) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = D1) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = www.D2) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 ;
listen [::]:80 ;
server_name www.D1 D1 www.D2;
return 404; # managed by Certbot
}
To mirror static HTML files in an ideal world Nginx would work out of the box. However sometime the pages to served might come from a non static page. In this case it can occur that the mirroring script (for example wget) had written some files with a ‘?’. Lets assume
https://example.com/Page - dynamic html page
https://example.com/Page?action=raw - raw Markdown content
When writing down the static content this might lead to files like this:
mirror.com/example.com/Page/index.html - a static HTML page
mirror.com/example.com/Page?action=raw - a static conten file
With the usual configuration Nginx would give a 404 Not Found result, when trying to get the URL http://mirror.com/example.com/Page?action=raw. With a changed try setup $uri?$args Nginx can server this page at least to let the client have a download option, as this will be application/octet-stream.
server {
listen 80;
listen [::]:80;
server_name localhost;
root /opt/mirror.com/example.com;
index index.html;
location / {
try_files $uri $uri/ $uri?$args =404;
}
}
| Version | Date | Notes |
|---|---|---|
| 0.6 | 2022-06-01 | shell->bash, improve headings |
| 0.5 | 2020-05-27 | Serving static HTML mirror |
| 0.4 | 2020-05-23 | Certbot root with $host |
| 0.3 | 2020-01-31 | TLSv1 TLSv1.1 |
| 0.2 | 2017-01-27 | |
| 0.1 | 2016-06-19 | Initial release |