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

275 lines
9.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
```bash
sudo apt update
sudo apt install nginx
```
Install from source
```bash
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: <mywebsite> 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.
```bash
sudo mkdir /var/www/<websitename>
```
Copy or create your websites static files into that folder. cd into your websites directory and run:
```bash
# 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.
```bash
sudo nano /etc/nginx/sites-available/<mywebsite>
```
Add the following text to it
```bash
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.
```bash
# 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
```bash
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:
```bash
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:
```bash
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/`):
```bash
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
```bash
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
```bash
server {
listen 0.0.0.0:80;
server_name <mywebsite> www.<mywebsite>;
rewrite ^ https://$host$request_uri? permanent;
}
```
This will redirect all requests to <mywebsite> and www.<mywebsite> 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.:
- http://<mywebsite>
- https://<mywebsite>
- http://www.<mywebsite>
- https://www.<mywebsite>
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:
```bash
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.
```bash
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:
```bash
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`:
```bash
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:
```bash
sudo apt install nginx-module-security-headers
```
Edit the `nginx.conf` like:
```bash
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:
```bash
sudo apt install nginx-module-headers-more
```
Edit the `nginx.conf` like:
```bash
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.
```bash
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.