loading...
Cover image for All About NGINX Configuration, HTTPS/SSL, HTTP2, Caching

All About NGINX Configuration, HTTPS/SSL, HTTP2, Caching

hasone profile image HasOne ・4 min read

To work in the TECH industry as a Full Stack Engineer It's essential to know the configuration of NGINX and its core features! in this post I'm gonna walk you through all about NGINX configuration how to install, add SSL, HTTP 2, GZIP,..

installing

just head over to nginx.org and download the compatible source code, I'll be using 1.19.2 or use the below command to download it

$  wget http://nginx.org/download/nginx-1.19.2.tar.gz
Enter fullscreen mode Exit fullscreen mode

extracting the file

$ tar -zxvf nginx-1.19.2.tar.gz 
Enter fullscreen mode Exit fullscreen mode

change the directory, and check you have build-essential package (c compiler), if not you need to install it

$ cd nginx-1.19.2

# installing compiler
$ sudo apt install build-essential

# now check it works
$ ./configure
Enter fullscreen mode Exit fullscreen mode

once the installing is done, the next part is to install some essential dependencies

$ sudo apt install libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev
Enter fullscreen mode Exit fullscreen mode

libpcre3 is PCRE library (Perl) for implementing regular expression pattern
zlib1g is for the GZIPING
libssl-dev for the SSL, to make a self-sign certificate

now let's install NGINX server itself, run the below command with root permission, let them custom configuration complete

# ./configure --sbin-path=/usr/bin/nginx --conf-path=/etc/nginx/nginx.conf \
 --error-log-path=/var/log/nginx/err.log --http-log-path=/var/log/nginx/access.log \
  --with-pcre --pid-path=/var/run/nginx.pid --with-http_ssl_module --with-http_v2_module
Enter fullscreen mode Exit fullscreen mode

to learn all about the flags used above, now we can compile and install this source by running the below commands using root permission

$ sudo make
$ sudo make install
Enter fullscreen mode Exit fullscreen mode

once all done, run the server nginx command, it's working? if you got no error. check the process of nginx ps aux | grep nginx or head over http://localhost/, you see it, boom you made it!

Adding systemd system

systemd is allow us some awesome features like start, restart, stop, starting on bootup, reloading. mean we already familiar with systemd so don't need to run everytime nginx -s stop...
to configure systemd, just grap the code from the website and save it as /lib/systemd/system/nginx.service file using root permission, still need some changes in the file, open up the file /lib/systemd/system/nginx.service in the editor and make the below changes

[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/bin/nginx -t
ExecStart=/usr/bin/nginx
ExecReload=/usr/bin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode

now again save the file and run the command sudo systemctl daemon-reload. now start the Nginx using systemd command

$ sudo systemctl start nginx
Enter fullscreen mode Exit fullscreen mode

Download Simple template and serve it

download any template from here to make a demo site.
also make directory named /sites/demo using root permisson

$ sudo mkdir -p /sites/demo
Enter fullscreen mode Exit fullscreen mode

unzip the downloaded template and copy it to /sites/demo.

open the Nginx configuration file /etc/nginx/nginx.conf using your favorite editor, remove all the code from the file and add the below

worker_processes  1;


events {
    worker_connections  1024;
}

http {

    include mime.types;
    index index.html;

    server {
        listen 80;
        server_name localhost;

        root /sites/demo;

        index index.html;
    }
}
Enter fullscreen mode Exit fullscreen mode

now reload the nginx worker(process) by command, when you made any change you need to run this command

$ sudo systemctl reload nginx
Enter fullscreen mode Exit fullscreen mode

and visit localhost in your browser, you saw it? if you did everything right then you'd be able to see it!

Adding SSL and HTTP 2

create a new directory named ssl under /etc/nginx so it becomes /etc/nginx/ssl, you remember we installed a package at the beginning libssl-dev now it's time to take it to work. first we need to create a self-sign certificate using openssl command

$ sudo openssl req -x509 -days 10 -nodes -newkey rsa:2048 -keyout /etc/nginx/ssl/self.key -out /etc/nginx/ssl/self.crt
Enter fullscreen mode Exit fullscreen mode

fill up all the required inputs, once it gets done. it'll give you two files slef.crt and self.key under the directory /et/nginx/ssl. to enable it we need to provide these two files to Nginx conf file. open up /etc/nginx/nginx.conf file

worker_processes  1;


events {
    worker_connections  1024;
}

http {

    include mime.types;
    index index.html;

    gzip on;
    gzip_comp_level 3;
    gzip_types text/css;
    gzip_types text/javascript;

    server {
        # adding 443 port, http2
        listen 443 ssl http2;
        server_name localhost;

        # Adding SSL self-sign certificate
    ssl_certificate /etc/nginx/ssl/self.crt;
    ssl_certificate_key /etc/nginx/ssl/self.key;

        root /sites/demo;

        index index.php index.html;

        location ~* \.(css|js|jpg|png)$ {
                add_header Cache-Control public;
                add_header Pragma public;
                add_header Vary Accept-Encoding;
                expires 1M;
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

reload the nginx service sudo systemctl reload nginx and visit to https://localhost and see the network dev tool list over https and also HTTP 2 or use the curl to confirm

$ curl -Ik -H 'Accept-Encoding: gzip, deflate' https://localhost/lovely.css
Enter fullscreen mode Exit fullscreen mode
    gzip on;
    gzip_comp_level 3;
    gzip_types text/css;
    gzip_types text/javascript;
Enter fullscreen mode Exit fullscreen mode

First we on Gzipping. second using compressing level 3, the more level up the more resources Nginx will use and will compress to a tiny size, so it better to keep it level 4,3.
CSS and javascript file type will be compressed

        listen 443 ssl http2;

        # Adding SSL self-sign certificate
    ssl_certificate /etc/nginx/ssl/self.crt;
    ssl_certificate_key /etc/nginx/ssl/self.key;
Enter fullscreen mode Exit fullscreen mode

we enable 443 port, ssl and http2, we've already installed these dependencies at the beginning --with-http_ssl_module and --with-http_v2_module.
next, we import a self-sign certificate and key for encrypting the request

location ~* \.(css|js|jpg|png)$ {
     add_header Cache-Control public;
     add_header Pragma public;
     add_header Vary Accept-Encoding;
     expires 1M;
}
Enter fullscreen mode Exit fullscreen mode

we're using here regular express to match the path if any request made at the end with .css, .js, .jpg, and .png. we'd like to add an extra header like adding cache to the browser for 1M one month.

Thanks for reading, I hope you enjoy it and learned something from this lesson.

My Github Profile: https://github.com/lifeeric

Discussion

pic
Editor guide
Collapse
aghost7 profile image
Jonathan Boudreau

If you're setting up a load balancer with TLS I recommend redirecting http to https. You can do this with a configuration along the following lines in nginx:

server {
    listen 80;
    server_name localhost;

    location / {
        return 301 https://localhost$request_uri;
    }
}

I'd also recommend running ssltest against your site. HTTPS has been around for a long time and there are several cyphers you don't want to allow; this site will give recommendations as to which cyphers you probably want to block.

Collapse
hasone profile image
HasOne Author

Thanks, Jonathan for the tip. I think we need to create another virtual server in order to redirect HTTP to HTTPS:

http {

 # redirect all traffic to HTTPS
 server {
   listen 80;
   server_name 127.0.0.1/www.example.com;

   return 301 https://$host$request_uri;
 }

 server {
   # all your configuration code  goes here..
 }
}

I'm assuming you meant! great to hear ssltest, this is something I didn't know, will use it definitely in the future, and the credits will go to you. hope to have good rest of your life!

Collapse
nek_70 profile image
Maxime Veber

At first glance I liked the article. But then I figure out some issues.

Of course I understand it's written nowhere that this is the absolute best practice guide to nginx, but well I think a comment that mention the issues related to this cannot be a bad thing.

So let get started:

  1. Installing nginx by compiling it is interesting for learning, but bad for security. Using the package manager of your distribution is actually easier (no systemd to manually configure) and more secure: you get updates.
  2. Removing the whole content of nginx config file is not a great idea. It contains a lot of great configuration and should just be tweaked for special needs but not entirely rewritten. The folder sites-enabled is designed to receive your configuration, and the default file can be remove (this one is designed to be entirely removed).
  3. self signing certificate is not a great idea either, if you're in the local install context it would be better to use mkcert, and in a server context using certbot (letsencrypt) would have been easy and better.
  4. There's probably a lot more to tell about the configuration, I'm not an expert but worker_processes 1; is not good (especially with the worker_connection config), and now nginx will use root user which is not really great...

Thanks anyway for writing this article that shows nginx in a(n interesting) way. I just wanted to highlight that it's not the recommanded way. And I think you should mention this in your article.

Collapse
exciteabletom profile image
tom

Is there a reason to build from source instead of sudo apt install nginx?

Collapse
tuck1s profile image
SteveT

Your distribution may (or may not) support optional packages such as headers-more, needed for proxy applications where you want to set the Server: response header for example.

docs.nginx.com/nginx/admin-guide/d...

If your distro doesn't have them, then building from source is an alternative.

Collapse
vaibhavkhulbe profile image
Vaibhav Khulbe

Nicely written!

Collapse
travisfont profile image
Travis van der F.

Nice to see simple and updated article on HTTP2 and SSL support :] well done!

Collapse
hasone profile image
HasOne Author

Glad to hear it, Travis!

Collapse
antoniowd profile image
Antonio Martin

Simple and informative. Just what I needed. Thanks

Collapse
laci profile image
Laci Kosco

A small typo in ssl part where you have slef.crt instead of self.crt
For easy folks with copy paste disorder might get busy by this :)

Collapse
anzhari profile image
Anzhari Purnomo

Great article!

Lately I'm working with gRPC, I'm wondering if you can proxy gRPC backend with NGINX HTTP2? Have you tried it?

Collapse
hasone profile image
HasOne Author

Honestly, I just heard gPRC and don't know how to configure. here is the blog post Nginx as Reverse Proxy with GRPC and GRPC! Thanks for this awesome question, I'll try to learn this!