<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Moein Kia</title>
    <description>The latest articles on DEV Community by Moein Kia (@moeinkiani).</description>
    <link>https://dev.to/moeinkiani</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1813870%2F2fa89693-277f-4bfc-a036-cf79db77ebcc.png</url>
      <title>DEV Community: Moein Kia</title>
      <link>https://dev.to/moeinkiani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/moeinkiani"/>
    <language>en</language>
    <item>
      <title>What is Nginx?</title>
      <dc:creator>Moein Kia</dc:creator>
      <pubDate>Wed, 24 Dec 2025 10:38:09 +0000</pubDate>
      <link>https://dev.to/moeinkiani/what-is-nginx-gof</link>
      <guid>https://dev.to/moeinkiani/what-is-nginx-gof</guid>
      <description>&lt;h2&gt;
  
  
  What is going on?
&lt;/h2&gt;

&lt;p&gt;Let’s start with an example, suppose that Kevin is a Doctor (a really good one). Kevin is really popular, and by chance, he’s your brother.&lt;/p&gt;

&lt;p&gt;Due to his excellent job, he has so many visitors. Every visitor must visit his office to be examined and diagnosed. He is so good that too many patients come in every day than everyone.&lt;/p&gt;

&lt;p&gt;Imagine there are 500 patients, and every one of them tries to reach Kevin for their problems at the same time. What will happen? Well, obviously, Kevin can’t handle and manage all of them, and also can’t respond to anyone. So what will Kevin do?&lt;/p&gt;

&lt;p&gt;First, he realizes that he can't visit all 500 patients per day. cause every visitor can at least take a 5min minutes, and he does not have that much time to visit all of them so he comes up with a solution.&lt;/p&gt;

&lt;p&gt;If every visitor could just send him all of their symptoms precisely on a paper, he would just check those papers in a second and write a proper prescription for that patient. So he hired some good doctors as his secretary ("Come on😂"), and after that, each patient has to go to one of them and show them their symptoms on a paper and those secratary doctors are gonna validate and check that symptoms paper and if it was ok they will send that paper to the doctor and bring the doctor's prescription back to the patient.&lt;/p&gt;

&lt;p&gt;But let’s say you feel pain in your hand. You don’t need to go to the secretaries because Kevin is your brother, and when he’s at home, you can ask him to visit you and write you a prescription.&lt;/p&gt;

&lt;p&gt;So what was it all about? That was the explanation of nginx in the simplest way (what the hell? Are you kidding me?) No, I’m not. Let me explain: Kevin is your website (Aha!). When you are developing your website on your local machine, it is only you and your website; you don’t need anything to handle your request when you are trying to access your website (you can have Nginx on your local, but that is not necessary), exactly like the time when Kevin was home, and you could ask him anything.&lt;/p&gt;

&lt;p&gt;But when you deploy your website, there gonna be too many requests to your website, so there has to be something that can handle those requests properly, like the secretary doctors.&lt;/p&gt;

&lt;p&gt;Alright, Nginx is our secretary doctor. You just need to configure it to act as you wish, like what? Like tell nginx to listen to port 80 and 443 (entrance of Kevin's clinic), and if the request is asking for that page, serve that page, and if the request is not coming from https ( if the patient hasn't worn a medical mask and it's paper is dirty) don’t let it access the website (don't send the symptoms paper to Kevins office). &lt;/p&gt;

&lt;p&gt;See? Exactly like the secretary. We define our rules, and it has to perform according to them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nginx
&lt;/h2&gt;

&lt;p&gt;So let's provide a proper explanation for Nginx:&lt;/p&gt;

&lt;p&gt;Nginx exists to handle web traffic efficiently. Traditional web servers were slow and resource-hungry when handling many simultaneous connections, especially under high load. They blocked on each request, which wasted memory and killed performance.&lt;/p&gt;

&lt;p&gt;Nginx was designed to fix that.&lt;/p&gt;

&lt;p&gt;It uses an event-driven, non-blocking architecture, which allows it to handle thousands of concurrent connections using very little memory. Instead of letting your backend application deal with slow clients, file serving, TLS, and connection management, Nginx sits in front and absorbs that complexity.&lt;/p&gt;

&lt;p&gt;In practice, Nginx solves these problems:&lt;/p&gt;

&lt;p&gt;Serves static files fast without hitting your backend&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shields backend applications from direct internet traffic&lt;/li&gt;
&lt;li&gt;Handles SSL/TLS so your app doesn’t have to&lt;/li&gt;
&lt;li&gt;Proxies and routes requests to the right backend service&lt;/li&gt;
&lt;li&gt;Keeps your application focused on business logic, not HTTP plumbing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s why Nginx is almost always placed in front of backend applications, not instead of them.&lt;/p&gt;

&lt;p&gt;So let’s install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installation. You can find Nginx files in this directory &lt;code&gt;/etc/ngix&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;There is an important file in that directory named &lt;code&gt;nginx.conf&lt;/code&gt; that contains all of the main configuration of Nginx.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;user&lt;/span&gt; &lt;span class="s"&gt;www-data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;worker_processes&lt;/span&gt; &lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pid&lt;/span&gt; &lt;span class="n"&gt;/run/nginx.pid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;error_log&lt;/span&gt; &lt;span class="n"&gt;/var/log/nginx/error.log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;include&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/modules-enabled/*.conf&lt;/span&gt;;

&lt;span class="k"&gt;events&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;worker_connections&lt;/span&gt; &lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;# multi_accept on;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;##&lt;/span&gt;
        &lt;span class="c1"&gt;# Basic Settings&lt;/span&gt;
        &lt;span class="c1"&gt;##&lt;/span&gt;

        &lt;span class="kn"&gt;sendfile&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;tcp_nopush&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;types_hash_max_size&lt;/span&gt; &lt;span class="mi"&gt;2048&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;# server_tokens off;&lt;/span&gt;

        &lt;span class="c1"&gt;# server_names_hash_bucket_size 64;&lt;/span&gt;
        &lt;span class="c1"&gt;# server_name_in_redirect off;&lt;/span&gt;

        &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/mime.types&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;default_type&lt;/span&gt; &lt;span class="nc"&gt;application/octet-stream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;##&lt;/span&gt;
        &lt;span class="c1"&gt;# SSL Settings&lt;/span&gt;
        &lt;span class="c1"&gt;##&lt;/span&gt;

        &lt;span class="kn"&gt;ssl_protocols&lt;/span&gt; &lt;span class="s"&gt;TLSv1&lt;/span&gt; &lt;span class="s"&gt;TLSv1.1&lt;/span&gt; &lt;span class="s"&gt;TLSv1.2&lt;/span&gt; &lt;span class="s"&gt;TLSv1.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# Dropping SSLv3, ref: POODLE&lt;/span&gt;
        &lt;span class="kn"&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;##&lt;/span&gt;
        &lt;span class="c1"&gt;# Logging Settings&lt;/span&gt;
        &lt;span class="c1"&gt;##&lt;/span&gt;

        &lt;span class="kn"&gt;access_log&lt;/span&gt; &lt;span class="n"&gt;/var/log/nginx/access.log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;##&lt;/span&gt;
        &lt;span class="c1"&gt;# Gzip Settings&lt;/span&gt;
        &lt;span class="c1"&gt;##&lt;/span&gt;

        &lt;span class="kn"&gt;gzip&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;# gzip_vary on;&lt;/span&gt;
        &lt;span class="c1"&gt;# gzip_proxied any;&lt;/span&gt;
        &lt;span class="c1"&gt;# gzip_comp_level 6;&lt;/span&gt;
        &lt;span class="c1"&gt;# gzip_buffers 16 8k;&lt;/span&gt;
        &lt;span class="c1"&gt;# gzip_http_version 1.1;&lt;/span&gt;
        &lt;span class="c1"&gt;# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;&lt;/span&gt;

        &lt;span class="c1"&gt;##&lt;/span&gt;
        &lt;span class="c1"&gt;# Virtual Host Configs&lt;/span&gt;
        &lt;span class="c1"&gt;##&lt;/span&gt;

        &lt;span class="kn"&gt;Include&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/conf.d/*.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/sites-enabled/*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;user&lt;/code&gt; directive tells nginx to use the &lt;code&gt;www-data&lt;/code&gt; user to execute the command it needs to run.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;worker_processes&lt;/code&gt; directive tells nginx how many processes are needed to process the requests.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;pid&lt;/code&gt; directive tells Nginx where to write the PID (Process ID) of the master process (What? Alright, Nginx runs with one master process and multiple worker processes.” Whyyyy? What are you talking about?” The master process ID is written to this file so that the specific commands that we are going to talk about work properly, like: &lt;code&gt;nginx -s reload&lt;/code&gt;, &lt;code&gt;nginx -t&lt;/code&gt;, and systemd commands that are related to the Nginx service).&lt;/p&gt;

&lt;p&gt;And the &lt;code&gt;include&lt;/code&gt; directive includes all the files that end with &lt;code&gt;.conf&lt;/code&gt; in &lt;code&gt;/etc/nginx/modules-enabled&lt;/code&gt; directory, so if you want to add a config file, you can create a file in that directory with the .conf extension.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;events&lt;/code&gt; block
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;worker_connections&lt;/code&gt; determine the maximum requests that a processor can process.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;multi_accept&lt;/code&gt; directive tells Nginx to process the requests simultaneously or not (I recommend you to uncomment this directive).&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;http&lt;/code&gt; block
&lt;/h2&gt;

&lt;p&gt;Here is where magic actually happens, and your HTTP request here is getting served by the structure of this block. Some of the directives are important to us, so we're gonna review them. You can search the others online (most of them are obvious just by looking at their names).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;server_token&lt;/code&gt;: specify if the Nginx version has to be considered in the response header or not (I recommend to set this off just to prevent potential attacks)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;default_type&lt;/code&gt;: specify default mime types in responses.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gzip&lt;/code&gt;: tell Nginx to compress the sending requests using gzip or not ( I recommend to set this to on)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gzip_type&lt;/code&gt;: specify which type of files must be compressed by gzip. You just need to provide its mime_types.&lt;/p&gt;

&lt;p&gt;And at the end, you can see these two lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;include&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/conf.d/*.conf&lt;/span&gt;;
&lt;span class="k"&gt;include&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/sites-enabled/*&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They are going to import some configs from those directories exactly into the http block, so if you want to configure your Nginx for your website, you'd better go there and create a config file (“Where exactly?”). I’ll show you:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;server&lt;/code&gt; block
&lt;/h2&gt;

&lt;p&gt;Whenever you are trying to configure Nginx for your website, you need to define a &lt;code&gt;server&lt;/code&gt; block (just like the &lt;code&gt;http&lt;/code&gt; or &lt;code&gt;events&lt;/code&gt; block that we’ve discussed), which's exactly where you tell Nginx what to do when a request comes in for this specific website. So, each hostname needs a &lt;code&gt;server&lt;/code&gt; block. You need to put that &lt;code&gt;server&lt;/code&gt; block inside the &lt;code&gt;http&lt;/code&gt; block (at the end of the block ) in &lt;code&gt;nginx.conf&lt;/code&gt;, or you can define the block in a file with an arbitrary name and use the include directive to import that into the http block.&lt;/p&gt;

&lt;p&gt;If you want to know the best practice of how to structure your Nginx configurations, &lt;a href="https://moeinkiani.com/blog/2/how-to-structure-nginx-configurations-for-clean-and-maintainable-servers" rel="noopener noreferrer"&gt;check this link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But for now, go inside the http block and at the end, add a server block like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, we need to fill that in to tell nginx what you do whenever a request comes in. Let me fill it with real config, and then I’ll explain each line for you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/srv/example/public&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Frame-Options&lt;/span&gt; &lt;span class="s"&gt;"SAMEORIGIN"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Content-Type-Options&lt;/span&gt; &lt;span class="s"&gt;"nosniff"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.php&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;charset&lt;/span&gt; &lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="n"&gt;/index.php?&lt;/span&gt;&lt;span class="nv"&gt;$query_string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/favicon.ico&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kn"&gt;access_log&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;log_not_found&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/robots.txt&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kn"&gt;access_log&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;log_not_found&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;error_page&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt; &lt;span class="n"&gt;/index.php&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/index\.php(/|$)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;fastcgi_pass&lt;/span&gt; &lt;span class="s"&gt;unix:/var/run/php/php8.2-fpm.sock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;fastcgi_param&lt;/span&gt; &lt;span class="s"&gt;SCRIPT_FILENAME&lt;/span&gt; &lt;span class="nv"&gt;$realpath_root$fastcgi_script_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="s"&gt;fastcgi_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;fastcgi_hide_header&lt;/span&gt; &lt;span class="s"&gt;X-Powered-By&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;/\.(?!well-known).*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;deny&lt;/span&gt; &lt;span class="s"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;listen 80;&lt;/code&gt;: tell nginx to listen to port 80 (IPv4), cause the HTTP requests hit that port.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;listen [::]:80&lt;/code&gt;: it also says listen to port 80, but for IPv6&lt;/p&gt;

&lt;p&gt;&lt;code&gt;server_name&lt;/code&gt;: defines which hostname this server block handles. You can type your domain here, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt; &lt;span class="s"&gt;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you can type your server’s IP address if you haven't purchased a domain yet.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;root&lt;/code&gt;: defines the base directory where files are served from, so you have to create that directory and put your website code in that directory, (let say you have laravel project, so you know that your &lt;code&gt;index.php&lt;/code&gt; in public directory needs to be served so you put your code in &lt;code&gt;/srv/example/&lt;/code&gt; and define the &lt;code&gt;root&lt;/code&gt; like &lt;code&gt;/srv/example/public&lt;/code&gt; where your &lt;code&gt;index.php&lt;/code&gt; exists and waiting for your requests). for example after defining the &lt;code&gt;root&lt;/code&gt; when the user asks for this &lt;code&gt;/css/app.css&lt;/code&gt; nginx looks for &lt;code&gt;/srv/example/public/css/app.css&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;Let’s move on!&lt;/p&gt;

&lt;p&gt;By using the &lt;code&gt;add_header&lt;/code&gt; directive, you can add headers to your responses. I recommend you add these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Frame-Options&lt;/span&gt; &lt;span class="s"&gt;"SAMEORIGIN"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Content-Type-Options&lt;/span&gt; &lt;span class="s"&gt;"nosniff"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These two prevent your site from being embedded in iframes on other domains and stop the browser from guessing file types.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;index index.php&lt;/code&gt;: when a directory is requested (&lt;code&gt;/&lt;/code&gt;), by default, Nginx looks for &lt;code&gt;index.html&lt;/code&gt; in that root directory that you provided earlier, and it does not recognize your index file. Hence, you have to specify it for Nginx using the index directive, so after that, Nginx knows whenever a request comes in (&lt;code&gt;/&lt;/code&gt;), it will look for &lt;code&gt;index.php&lt;/code&gt; in the root directory.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;charsert utf-8&lt;/code&gt;: You’d better use it to tell the browsers the default character encoding of your server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Location block
&lt;/h2&gt;

&lt;p&gt;Well, wel,l well, here we are with the &lt;code&gt;location&lt;/code&gt; block. That is actually really important.&lt;/p&gt;

&lt;p&gt;Let me break it down for you:&lt;br&gt;
&lt;code&gt;location&lt;/code&gt; takes a regex as an argument. How? By providing it exactly in front of the location directive keyword, so when we write something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;root:&lt;/span&gt; &lt;span class="n"&gt;/path/to/root/&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, whenever a user hits the &lt;code&gt;/about&lt;/code&gt; endpoint, Nginx tries to find and serve the &lt;code&gt;/path/to/root/about&lt;/code&gt; and if it could find the directory, it will go to check if an index file is there based on the index files that we’ve provided by index keyword, but if it fails to find the index file it will respond with 403 (Forbidden) but if it fails to find the about directory it will return 404 (Not found). Ok! As you recall, we’ve defined the root earlier for the whole server block, not just for a specific location, so the nginx tries to access a &lt;code&gt;index.php&lt;/code&gt; in that root as a response to the user request.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;location&lt;/code&gt; tries to match a path that we provided for it and do what we’ve decided for it (based on its block).&lt;/p&gt;

&lt;p&gt;So this (&lt;code&gt;/&lt;/code&gt;) means everything (every path).&lt;/p&gt;

&lt;p&gt;Like in this example we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="n"&gt;/index.php?&lt;/span&gt;&lt;span class="nv"&gt;$query_string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It uses the built-in &lt;code&gt;$uri&lt;/code&gt; variable. &lt;code&gt;$uri&lt;/code&gt; is the normalized request path, not a file and not a URL. It doesn't include protocol, domain or even query string. So when the user types &lt;code&gt;https://example.com/about?search=”hello”&lt;/code&gt; the uri is &lt;code&gt;/about&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;How does try_files really work?&lt;/p&gt;

&lt;p&gt;It will work in this order:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Try &lt;code&gt;$uri&lt;/code&gt; as a file
&lt;/h3&gt;

&lt;p&gt;Let say we have this request&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/css/app.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Nginx check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/srv/example/public/css/app.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nginx says: If it exist, then serve it and stop.&lt;/p&gt;

&lt;p&gt;If it dont:&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Try &lt;code&gt;$uri/&lt;/code&gt; as a directory
&lt;/h3&gt;

&lt;p&gt;Let say we have this request&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/about

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Nginx checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/srv/example/public/about/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it exists, then serve the index file inside (based on the index keyword) and stop.&lt;/p&gt;

&lt;p&gt;If it doesn't:&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Fallback to &lt;code&gt;/index.php&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;If neither a file nor a directory exists, Nginx internally rewrites the request to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/index.php?$query_string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sends the request to PHP so your application router (Laravel, Symfony, etc.) can handle it.&lt;/p&gt;

&lt;p&gt;So what will happen when a user requests for &lt;code&gt;/about&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;So first nginx tries to access it as a file ❌ &lt;br&gt;
it will fail cause we don't have about file in &lt;code&gt;public&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Then tries to access it as a directory ❌ &lt;br&gt;
again fails cause we don't have &lt;code&gt;/about&lt;/code&gt; directory in &lt;code&gt;public&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;So it will send the request to &lt;code&gt;index.php&lt;/code&gt; with its query string, so how does nginx send this to the application router to handle the request for it?&lt;/p&gt;

&lt;p&gt;Few lines after our first &lt;code&gt;location&lt;/code&gt; block we have another &lt;code&gt;location&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/index\.php(/|$)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;fastcgi_pass&lt;/span&gt; &lt;span class="s"&gt;unix:/var/run/php/php8.2-fpm.sock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;fastcgi_param&lt;/span&gt; &lt;span class="s"&gt;SCRIPT_FILENAME&lt;/span&gt; &lt;span class="nv"&gt;$realpath_root$fastcgi_script_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="s"&gt;fastcgi_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;fastcgi_hide_header&lt;/span&gt; &lt;span class="s"&gt;X-Powered-By&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will handle all of the request that matches &lt;code&gt;/index.php&lt;/code&gt; and &lt;code&gt;/index.php/somthing&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So nginx hits this endpoint and uses &lt;code&gt;fastcgi_pass&lt;/code&gt; to send the request to PHP-FPM or any FastCGI interface that your app needs. PHP needs PHP-FPM. Cause Nginx can't understand PHP code or any other language (except HTML and CSS) and doesn't know how to process them so it leaves the process to the FastCGI interface to process the request for it.&lt;/p&gt;

&lt;p&gt;Find your FastCGI interface for your project (programming language) and use it here.&lt;/p&gt;

&lt;p&gt;There is another location block that says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;/\.(?!well-known).*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;deny&lt;/span&gt; &lt;span class="s"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It simply says that if a request tries to access hidden files like: &lt;code&gt;.git&lt;/code&gt;, &lt;code&gt;.htaccess&lt;/code&gt;, &lt;code&gt;.env&lt;/code&gt; (except &lt;code&gt;.well-known&lt;/code&gt;, cause it's used for SSL verification) block them all.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;deny all&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We also have two more &lt;code&gt;location&lt;/code&gt; blocks in this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/favicon.ico&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kn"&gt;access_log&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;log_not_found&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/robots.txt&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kn"&gt;access_log&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;log_not_found&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They tell Nginx if the request was exactly &lt;code&gt;/favicon.ico&lt;/code&gt; and &lt;code&gt;/robots.txt&lt;/code&gt; ( the = means only this exact path) Disable the logs for these files. And the reason behind it is that the browsers request it constantly, and we don't want to pollute the logs.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;error_page 404 /index.php&lt;/code&gt;: means if Nginx faced any error, try to find the 404 file, and if you couldn't find it, send the request to &lt;code&gt;index.php&lt;/code&gt; to handle 404 pages instead of Nginx.&lt;/p&gt;

&lt;h2&gt;
  
  
  SSL certificate
&lt;/h2&gt;

&lt;p&gt;Most of the time, you need to enable your server to use an HTTPS connection. So how can we enable it?&lt;/p&gt;

&lt;p&gt;very easy! First, you need to get ssl certificate and SSL certificate keys (you can use Cloudflare's. It's free!). After that, you simply put them in your server and use these directives in your server block to activate SSL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/path/to/cloudflare.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/path/to/cloudflare.key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to change the listen directive values cause https connections use port number 443:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt; &lt;span class="s"&gt;http2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt; &lt;span class="s"&gt;http2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you can also add another server block to redirect all of the HTTP requests to HTTPS, and then no one can access your website through HTTP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="nv"&gt;$host$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Nginx commands
&lt;/h2&gt;

&lt;p&gt;Now you know how to configure your Nginx.&lt;br&gt;
These are useful commands that you may need:&lt;/p&gt;
&lt;h3&gt;
  
  
  starting Nginx:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl start nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Stopping Nginx:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl stop nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Enabling Nginx:
&lt;/h3&gt;

&lt;p&gt;so that every time our machine gets rebooted, Nginx starts automatically&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl enable nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Disabling Nginx:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl disable nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Restarting Nginx:
&lt;/h3&gt;

&lt;p&gt;After every change in the config, we need to restart our Nginx so that the changes get applied:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl restart nginx

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, we can use nginx command, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nginx -s reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Yeah, that's it!
&lt;/h2&gt;

&lt;p&gt;That was all you needed to know to use and set up your Nginx.&lt;/p&gt;

&lt;p&gt;Just install Nginx and configure it the way you want, then start the engine and you are ready to go!&lt;/p&gt;

</description>
      <category>nginx</category>
      <category>devops</category>
      <category>backend</category>
      <category>webserver</category>
    </item>
  </channel>
</rss>
