Setting up your project with Nginx

Setting up your project with Nginx

I remember when I first started my web development journey. Once I got the ball rolling in learning HTML, CSS, Javascript and Django, I thought I had it all figured out. Little did I know, there was a lot further I had to go to release a production level application.

Whenever I researched what I had to do to go to the next step, the subject of Nginx always arose. You saw different web development communities talking about it, but when you tried to search some decent content in order to try and learn it, the resources were very few and far between.

So why the abundance of resources helping you to learn back-end frameworks such as Django, Node.js, Ruby on Rails, etc but the lack of resources on this relatively simple thing to set up? The answer is really that I have no idea. Maybe influencers are paid to teach you how to make an app, but not enough so you have to pay to run it on other platforms? Who knows. All I can say is that there is a lack of content explaining how to set up your own web server, and it's near enough the final piece of the jigsaw.

So, let's first and foremost install what we need. Let's update our package lists and install Nginx with:



sudo apt update
sudo apt install nginx

Then, we need to enable and start our newly installed Nginx package:



sudo systemctl enable nginx
sudo systemctl start nginx

Nginx now should be up and running, but needs further configuration of course. Let's just first and foremost give this a test to see if it's running properly. If you are using a VPS or would like to test it out over the internet and have your port-forwarding set up on your router/VPS, you need to obtain your public IP address. If there is any difficulty in retreiving your public IP address, you can find this out simply enough by going on ipinfo.io/ip and finding this out. In your terminal, you can enter:



curl -s https://ipinfo.io/ip

Or for simplicity's sake, if you are setting up on the very device you are reading this blog post from, your public IP address is . You're welcome!

Now you can enter this IP address via your browser with the HTTP protocol (HTTPS needs more configuration, we will talk about that soon!) with http:///, or if you're using the same device that you're setting Nginx up on, you can use the general loopback local IP address and enter http://127.0.0.1/ and you should be met with this message:

Welcome to nginx!

If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.

Thank you for using nginx.

Perfect! This means that everything is going well so far. Now we just need to pay attention to the nginx.conf file and pay attention to which user is specified at the top of the file. This will be the user which will have permissions to access the files within your Linux environment. By default, it is www-data. But for simplicity's sake, I change this to my main username to save using the chown or chmod commands every time I make a file:



# /etc/nginx/nginx.conf
x.conf
user username; # Change this to your preferred username
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
        # multi_accept on;
}

http {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        types_hash_max_size 2048;
        # server_tokens off;

        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##

        gzip on;

        # gzip_vary on;
        # gzip_proxied any;
        # gzip_comp_level 6;
        # gzip_buffers 16 8k;
        # gzip_http_version 1.1;
        # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

        ##
        # Virtual Host Configs
        ##

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}


#mail {
#       # See sample authentication script at:
#       # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
#       # auth_http localhost/auth.php;
#       # pop3_capabilities "TOP" "USER";
#       # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
#       server {
#               listen     localhost:110;
#               protocol   pop3;
#               proxy      on;
#       }
#
#       server {
#               listen     localhost:143;
#               protocol   imap;
#               proxy      on;
#       }
#}

Now it's time to connect your application and static files for Nginx to serve. To just quickly test out how to serve a simple static HTML file from Nginx, let's make a file called index.html. Pay attention to the directories commented in the code I'm about to put, as of course we will need to link everything together:



<!--/home/username/webdev/index.html-->
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <h1>I'm being served by Nginx!</h1>
    </body>
</html>

Now we need to make a configuration file in Nginx's sites-available folder. It's best practice to make a configuration file per website you want to run. In this example, we are going to use our public IP address. Pay attention to the pattern of the syntax in configuration file:



# /etc/nginx/sites-available/mysite.conf
server {
    listen 80;
    server_name ;

    location / {
        alias /home/username/webdev/;
        index index.html;
    }
}

And now we need to enable this configuration file by adding a symbolic link to the sites-enabled directory in the nginx folder! This is essentially a shortcut to the sites-available configuration file that Nginx accesses via the nginx.conf file. We can do this by typing in the command line:



sudo ln -s /etc/nginx/sites-available/mysite.conf /etc/nginx/sites-enabled

Make sure that these files are accesible by your username by using the chmod and chown commands:



sudo chmod 755 /etc/nginx/sites-available/mysite.conf
sudo chmod 755 /etc/nginx/sites-enabled/mysite.conf

sudo chown username:username /etc/nginx/sites-available/mysite.conf
sudo chown username:username /etc/nginx/sites-enabled/mysite.conf

And now let's restart Nginx to put these changes into action:



sudo systemctl restart nginx

Okay! So going back to the contents of the mysite.conf file, notice how I end each line with a semicolon, and wrap each block in braces. This configuration file tells our Nginx server to listen for HTTP traffic on port 80 on the server name , and when you request the root URL http:/// (or :80) you will retreive the index.html file out of the /home/username/webdev/ directory. Go ahead and give it a try, your HTML file should now be loaded!

This is just a simple example to give you a taster of what Nginx is about. A production configuration file would have a few more bits and bobs added to it, such as adding your SSL certificates and setting up for HTTPS traffic; redirecting your www. subdomain to your main domain; upgrading your HTTP version in case you have an ASGI/Websocket application; setting different headers such as your host name to pass onto your application; setting a maximum upload length; pointing it to your WSGI/AGSI application; etc.

Here is an example file of a pretty much ready-to-go configuration file:



# /etc/nginx/sites-available/mysite.conf
server {
  listen 443 ssl;
  server_name example.co.uk;

  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;

  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "Upgrade";

  client_max_body_size 100M;

  ssl_certificate /etc/letsencrypt/live/example.co.uk/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.co.uk/privkey.pem;

  location / {
    proxy_pass https://127.0.0.1:8000;
  }

  location /static/ {
    root /home/ubuntu/webdev/example;
  }

  location /images/ {
    root /home/ubuntu/webdev/example;
  }

  location /media/ {
    root /home/ubuntu/webdev/example;
  }

  location /fonts/ {
    root /home/ubuntu/webdev/example;
  }
}

server {
  listen 443 ssl;
  server_name www.example.co.uk;

  ssl_certificate /etc/letsencrypt/live/example.co.uk/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.co.uk/privkey.pem;

  location / {
    return 301 https://example.co.uk$request_uri;
  }
}

server {
  listen 80;
  server_name example.co.uk www.example.co.uk;

  location / {
    return 301 https://example.co.uk$request_uri;
  }
}


I hope that my examples and explanations have helped you to understand how to get set up a bit better and have inspired you to research in more depth the world of Nginx!