Title: Basic Nginx snippets
Slug: basic-nginx-snippets
Date: 2016-12-30 07:45:00
Author: Kartones
Lang: en
Tags: Systems-IT, Linux, AWS, Systems-IT, Patterns & Practices
og_image:
Description: A guide on how to manage a full Linux instance using Amazon Lightsail, with a focus on improving Nginx skills. It includes code snippets for various tasks such as error log location, subsites, proxying Python apps, protecting sensitive files, MIME types, authentication, subdomain aliases, custom headers, redirections, HTTP methods, optimizations, and serving static content.


I've recently migrated my hosting, finally severing all remaining ties with .NET after rewriting some remaining small experients and projects with Python. As I now have a full Linux instance to manage (at <a href="https://amazonlightsail.com/" rel="noreferrer">Amazon Lightsail</a>, wanted to try it and looks I'm sticking with it), I've had to improve my Nginx skills from "*barely make a site run under a Docker container*" to "*configure multiple static and dynamic sites running on different subdomains on the same machine*". This post is a small recollection of things I needed to accomplish.

Error log default location:
```
/var/log/nginx/error.log
```

Subsites inside the same root `server` block (note that `alias` paths end with `/` while a `server` `root` path do not):
```
location /mysubpath/ {
        alias /my/path/to/mysubpath/;
        try_files $uri $uri/index.html =404;
}
```

Note: It is easier to follow the recommended rule of one `/etc/nginx/sites-available/<name>` entry per site or subsite instead of having a `root` path + `location` and then children `location` with different subpaths (using `alias`). I made it work even combining uWSGI and static sites but the config files were more complex, so I reverted to everything in its single file with a single `server` block.


Proxy uWSGI Python apps through Nginx using system sockets (and as a bonus, disabling default Nginx index file matching):
```
index wontmatch;

location / {
        include uwsgi_params;
        uwsgi_pass unix:/tmp/mysocketname.sock;
}
```

Protect password and similar sensible files from being served:
```
location ~ /\. { deny  all; }
```

Making all path files have a default MIME type (CSV in the example):
```
location /mycsvs/ {
    types    { }
    default_type text/comma-separated-values;
}
```

Protecting with basic authentication ([sample tutorial](https://www.nginx.com/resources/admin-guide/restricting-access-auth-basic/)):
```
auth_basic "Password required";
auth_basic_user_file /mypathtopasswordfile/.htpasswd;
```

Subdomain aliases:
```
server_name myalias1.name.com myalias2.name.com name.com;
```

Custom headers:
```
# only for success http responses
add_header X-Custom-Header a_value;

# all http responses
add_header X-Custom-Header a_value always;

```

Redirections:
```
location /cv {
    return 302 $scheme://portfolio.kartones.net/curriculumvitae/;
}
```

Only allowing certain HTTP methods:
```
error_page 405 @error405;
location @error405 {
	add_header Allow "GET, HEAD" always;
}

if ( $request_method !~ ^(GET|HEAD)$ ) {
	return 405;
}
```


### Optimizations

Fully removing `Server` header (not only Nginx version):
```
sudo apt-get update
sudo apt-get install nginx-extras

sudo vim /etc/nginx/nginx.conf

# inside `http {}` section add:
server_tokens off;
more_set_headers 'Server: ';

# Save, exit and:
sudo service nginx restart
```

GZip all statics (Javascript, CSS, etcetera), as by default only HTML and a few others get compressed:
```
sudo vim /etc/nginx/ngnix.conf

# Search for `gzip_types` and replace it by:
gzip_types text/plain text/css text/js text/xml text/javascript application/javascript application/x-javascript application/json application/xml application/rss+xml image/svg+xml;
```

Cache expiration rules for static content: Include or adapt [expires.conf](https://github.com/h5bp/server-configs-nginx/) inside `http`, `server` or `location` config blocks:
```
location ~* \.(?:rss|atom)$ {
        expires 1h;
}
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|zip|svg|webm|htc)$ {
        expires 1M;
        access_log off;
        add_header Cache-Control "public";
}
location ~* \.(?:css|js)$ {
        expires 1M;
        access_log off;
}
```


[Serving Static Content](https://www.nginx.com/resources/admin-guide/serving-static-content/): Official article, has interesting parameters if you serve big static content files (pdfs, zips and the like).
