MobilePenBerry/static server.md
2021-12-27 12:39:28 +01:00

9.7 KiB
Raw Permalink Blame History

Static Server with NGINX

NGINX is a very powerful web server. You can do a ton of things with it, such as setting up reverse proxies or load balancing. It can also be used to host your static website.

Installation

Install the NGINX package

sudo apt update
sudo apt install nginx

Install from source

sudo apt install build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev libgd-dev libxml2 libxml2-dev uuid-dev -y
wget http://nginx.org/download/nginx-1.21.4.tar.gz
tar -zxvf nginx-1.21.4.tar.gz
sudo rm -r nginx-1.21.4.tar.gz
git clone https://github.com/GetPageSpeed/ngx_security_headers.git
cd nginx-1.21.4
./configure --prefix=/var/www/html \
   --sbin-path=/usr/sbin/nginx \
   --conf-path=/etc/nginx/nginx.conf \
   --http-log-path=/var/log/nginx/access.log \
   --error-log-path=/var/log/nginx/error.log \
   --with-pcre  \
   --lock-path=/var/lock/nginx.lock \
   --pid-path=/var/run/nginx.pid \
   --with-http_ssl_module \
   --with-http_image_filter_module=dynamic \
   --modules-path=/etc/nginx/modules \
   --with-http_v2_module \
   --with-stream=dynamic \
   --with-http_addition_module \
   --with-http_mp4_module \
   --add-module=../ngx_security_headers
make
make install

Move your websites static files to the server

By default, NGINX expects your static files to be in a specific directory. You can override this in the configuration. Defaults assume that youll be putting your websites static files in the /var/www/ directory.

Hint: consists of the domain name and domain extension, e.g. example.com

Create a directory in /var/www/ names as you like. This is where your static websites files will go.

sudo mkdir /var/www/<websitename>

Copy or create your websites static files into that folder. cd into your websites directory and run:

# creating files
touch /var/www/<mywebsite>/index.html
sudo nano /var/www/<mywebsite>/index.html
# copy/move files
cp ./index.html /var/www/<mywebsite>/
mv ./index.html /var/www/<mywebsite>/
# safe copy to network destination
scp -r * <username>@<ip>:/var/www/<mywebsite>

Configure NGINX to serve your website

The NGINX configuration files are located at /etc/nginx/. We need to tell NGINX about the website and how to serve it. The two directories we are interested in are sites-available and sites-enabled.

  • sites-available contains individual configuration files for all possible static websites
  • sites-enabled contains links to the configuration files that NGINX will actually read and run

To enable a website, we create a configuration file in sites-available and create a symbolic link of that file in sites-enabled to tell NGINX to run it.

sudo nano /etc/nginx/sites-available/<mywebsite>

Add the following text to it

server {
  listen 80 default_server;
  listen [::]:80 default_server;  
  root /var/www/<mywebsite>;  
  index index.html;  
  server_name <mywebsite> www.<mywebsite>;  
  location / {
    try_files $uri $uri/ =404;
  }
}

This file tells NGINX several things:

  • Deliver files from the folder /var/www/<mywebsite>
  • The main index page is called index.html
  • Requests that are requesting <mywebsite> should be served by this server block
  • Note the www is also listed separately. This tells nginx to also route requests starting with www to the site. Theres actually nothing special about the www — its treated like any other subdomain

Now that the file is created, well add it to the sites-enabled folder to tell NGINX to enable it.

# use like: ln -s <SOURCE_FILE> <DESTINATION_FILE>
ln -s /etc/nginx/sites-available/<mywebsite> /etc/nginx/sites-enabled/<mywebsite>

Now restart NGINX and you should see your site at your localhost port

sudo systemctl restart nginx

If it gives you an error, theres likely a syntax error.

Enable HTTPS

With free SSL certs from LetsEncrypt, you can enable HTTPS for your website. In addition to the improved security, theres significant performance opportunities it allows via HTTP/2, youll increase user confidence and youll even rank higher in SEO.

Acquire an SSL cert

Theres multiple ways to do this. You can buy a single-domain certification or a wildcard certification if you plan on securing subdomains.

You can also go the free route via LetsEncrypt:

sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx
sudo certbot --nginx certonly

Follow the instructions. This will install certs in /etc/letsencrypt/live/<mywebsite>/

To enable auto-renewal for certificates, edit the crontab and create a CRON job to run the renewal command:

sudo crontab -e

And add the following line:

17 7 * * * certbot renew --post-hook "systemctl reload nginx"

Tell NGINX to use the SSL cert

Modify the configuration file created before. Add the following text, changing the paths to point to the certificate file and the key file (usually stored in/etc/nginx/certs/):

server {
   # ...previous content
   ssl on;
   ssl_certificate /etc/letsencrypt/live/<mywebsite>/fullchain.pem;
   ssl_certificate_key /etc/letsencrypt/live/<mywebsite>/privkey.pem;

A problem now occurs as port 80 was used for HTTP no longer of use as HTTPS uses port 443. Change that in the configuration

server {
   listen 443 default_server;
   listen [::]:443 default_server;
   #... all other content
}

As this will prevent people to access your page over HTTP we need to redirect HTTP requests to HTTPS. Add the following code after the HTTPS server code into your configuration file of the webpage

server {
       listen 0.0.0.0:80;
       server_name <mywebsite> www.<mywebsite>;
       rewrite ^ https://$host$request_uri? permanent;
}

This will redirect all requests to and www. on port 80 to the HTTPS URL on port 443. Restart NGINX to make the changes happen: sudo systemctl restart nginx

Test the configuration by going to the four variations of the URL, eg.:

They should all work and be secured via HTTPS.

Improve performance

Enable HTTP/2

HTTP/2 allows browsers to request files in parallel, greatly improving the speed of delivery. We need HTTPS enabled. Edit the browser configuration file, adding http2 to the listen directive, then restart NGINX:

server {
   listen 443 http2 default_server;
   listen [::]:443 http2 default_server;
   #... all other content
}

Enable client-side caching

Some files never change or change rarely, so users can prevent re-download too often. Set the cache control headers to provide hints to browsers to let those know what files they shouldnt request again.

server {
   #...after the location / block
   location ~* \.(jpg|jpeg|png|gif|ico)$ {
       expires 30d;
    }
    location ~* \.(css|js)$ {
       expires 7d;
    }
}

Set the times after own experience.

Dynamically route subdomains

In the case of subdomains, you may not want to route every subdomain to the correct folder. Create a wildcard server to route matching names. Edit your website configuration therefore:

server {
       server_name ~^(www\.)(?<subdomain>.+).<mywebsite>$ ;
       root /var/www/<mywebsite>/$subdomain;
}
server {
        server_name ~^(?<subdomain>.+).<mywebsite>$ ;
        root /var/www/<mywebsite>/$subdomain;
}

Restart NGINX and route subdomains automatically to the same-named subfolder.

remove the Server header

Security through obscurity isnt the holy grail that will make any website secure completely. But as a complementary security measure, it can be used.

NGINX, by default, sends information about its use in the Server HTTP header as well as error pages, e.g.: nginx/1.16.1.

To confirm the currently emitted header, run curl -IsL https://example.com/ | grep -i server

hide version information

The standard security solution is hiding NGINX version information. In the /etc/nginx/nginx.conf:

http {
   ...
   server_tokens off;
   ...
}

This only hides the specific version of NGINX from the Server header and error pages. The header becomes: Server: nginx

hide server header

using ngx_security_headers module

Easiest method is using the package made to extend NGINX:

sudo apt install nginx-module-security-headers

Edit the nginx.conf like:

load_module modules/ngx_http_security_headers_module.so;

http {
    ...
    hide_server_tokens on;
    ...
}

Now the Server header is completely eliminated from the responses.

using Headers More module

Another module to use is:

sudo apt install nginx-module-headers-more

Edit the nginx.conf like:

load_module modules/ngx_http_headers_more_filter_module.so;

http {
    ...
    more_clear_headers Server;
    ...
}

Likewise, the Server header will be completely gone from the responses.

hide the use of NGINX

Hiding the Server header is good but the default error pages by NGINX still output the "nginx" word in them.

An easy way to complete hiding of NGINX presence on the server is using NGINX-MOD. Simply specify the following in the configuration: server_tokens none;

Alternatively hide the NGINX presence by recompiling it from the source (highly discouraged, see common pitfalls). Adjust NGINX sources to prevent the information disclosure of NGINX software.

sed -i 's@"nginx/"@"-/"@g' src/core/nginx.h
sed -i 's@r->headers_out.server == NULL@0@g' src/http/ngx_http_header_filter_module.c
sed -i 's@r->headers_out.server == NULL@0@g' src/http/v2/ngx_http_v2_filter_module.c
sed -i 's@<hr><center>nginx</center>@@g' src/http/ngx_http_special_response.c

Then recompile NGINX.