Skip to content

nginx

This is a quick reminder about a few tricks in nginx. For me, nginx is the tools that solves the question:

  • How can I serve multiple web apps from a single server with a common root?
  • How can I serve multiple domain from the same server?

Usually, the nginx root folder is stored under /etc/nginx. Note that adaptation (usually path) might be required between linux distributions.

First of all, when you distribute multiple web app, it is much easier if you can have multiple domain names: web apps will have their routes and avoid paths conflict. In this case you will create server block for each domain.

Tips: pay attention to the slashes (/) it the path, as nginx mainly concatenate strings, so you might accidentally have double slashes in your path which usually leads to unintended consequence.

Server blocks

Server blocks usually lives in the conf.d or sites-availables

server {
        listen 80;
        listen [::]:80;

        root /var/www/your_domain/html;
        index index.html index.htm index.nginx-debian.html;

        server_name your_domain www.your_domain;

        location / {
                try_files $uri $uri/ =404;
        }
}

where your_domain is replaced by the domain you own. The root directive provides the root of your web app, the folder needs to be reachable by the process which started nginx. If the server block is defined in sites-availables, you need to create a symlink into the sites-enabled folder.

Root directive

The root directive provides the root path of your request. In the previous server block, the response from nginx to the request on the path www.your_domain/css/file.css will be the filer located under /var/www/your_domain/html/css/file.css, because /var/www/your_domain/html was defined as the root and /css/file.css is the path requested. If the files does not exists, the 404 (not found) answer is returned.

Nginx has concatenated the root with the path.

You can change the root for each location directive, which can handy for distribution under several folders (see later).

Static file distribution through alias

Usually, you desire to use some path of your domain to target different folder because they serve the files for your webapp. Most webapp are defined as if they were placed on the root folder, so if the web app is distributed under /my_webapp the associated assets files (javascript, css, images) will usually be unfound. To solve this problem, we use the alias directive. In a server block (the default or any other), the following directive will alias the www.your_domain/my_webapp to /var/www/my_webapp/html.

location /my_webapp {
    alias /var/www/my_webapp/html;
}

The consequences are that nginx will answer to request www.your_domain/my_webapp/css/file.css with the file /var/www/my_webapp/html/css/files.css, concatenating the alias and the path. If root instead of alias was used, nginx would have returned /var/www/my_webapp/html/my_webapp/css/file.css, because nginx always append the full path to the route, whereas alias replace the the match path with the value provided to alias.

In my personal experience, you will use and abuse alias more often than root.

Proxy pass

When creating web apps, you will often create a backend server. This server will usually be connected to some port under root (e.g. 8000, 8050, 8081). Under development, you will often use localhost:8050 as domain. In production, you will launch the same program which will still listen to the same port. However, you want your user to call a path on your_domain. The proxypass directive is the solution to this problem.

location /backend_path {
    proxy_pass locahost:8050;
}

Hence the for each request called to my_domain//backend_path/data, the backend will match it to /data.

Obviously you can use nginx to also perform some indirection

location /backend_path/x {
    proxy_pass locahost:8050/y;
}

In this case, under the request my_domain//backend_path/x/data, the backend will return the handler registered under the route /y/data.

Regex path

Regex can be used to match multiple paths in nginx. You start a regex path by adding a tilde ~ sign after location and then using standard regex notation to reuse the match parts.

location ~ /images/(.+)$ {
  try_files /other_images_folders/$1 =404;
}

Multiple source folder

It might happens that your apps call the same path, but the content is located in different folder. In this case, we can combine root and regex to sovle the issue.

location ~ /images/(.+)$ {
  root /var/www;
  try_files /my_webapp/images/$1 /your_domain/images/$1 =404;
}

Here nginx will try to server /images/file.jpeg from /my_webapp/images/file.jpeg before /your_domain/images/file.jpeg.

HTTPS

In order to promote the connection to https, you will need to change the server blocks and define the path of your certificates.

server {
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     path/to/www.example.com.crt;
    ssl_certificate_key path/to/www.example.com.key;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
}

Usually, you will want letsencrypt (if you own the domain name) to save this for you.

Websocket

In order to allow websocket, you must upgrade the connection. For this you can adapt the following snippet under the desired location:

location /shadow-cljs/ {
  # upgrade to websocket
  proxy_pass http://localhost:9630/;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "Upgrade";
  proxy_set_header Host $host;
}

See also (generated)