Software

How to Install Nginx and Configure Your First Server Block

Talha Aslan 18 min read 2 views

How do you install Nginx and what does the setup involve?

To install Nginx, you add the open source Nginx web server to a Linux machine with the package manager, run it as a system service and write a first site configuration. You install the package, enable the service, define a server block, test it with nginx -t and then add SSL, logging and security settings.

We wrote this guide as Talha Aslan and team, and we based every step on official documentation. We are not a hosting company; we are a digital marketing, web design and software team. That is why the commands come from nginx.org, Ubuntu and Certbot documentation rather than from claims about servers we run. We also skip version numbers. Instead, use the current stable release from your distribution or from nginx.org.

You can split the whole job into four stages:

  1. Installation: add the package from your distribution or from the official nginx.org repository.
  2. Service management: start Nginx with systemctl, enable it at boot and check its status.
  3. Configuration: learn the nginx.conf layout, write your first server block and test it.
  4. Hardening: SSL, security headers, hiding the version, log review and firewall rules.

What does Nginx do, and when should you choose it?

Nginx works both as a web server and as a reverse proxy. According to the official beginner's guide, one master process reads the configuration while several worker processes handle requests with an event based model. As a result, Nginx can manage many concurrent connections with modest memory.

In practice, teams install Nginx for these jobs:

  • Serving static files such as HTML, CSS, JavaScript and images quickly.
  • Running PHP applications through PHP-FPM.
  • Sitting in front of Node.js, Python or Go apps as a reverse proxy.
  • Handling SSL termination, redirects and simple load balancing.

That said, Nginx is not the best fit for every project. On shared hosting, for example, you rarely pick the web server at all. If you prefer a panel based stack, look at alternatives such as OpenLiteSpeed. We compared the two in our OpenLiteSpeed vs Nginx guide, so we will not repeat it here.

What should you prepare before you install Nginx?

A little preparation makes every later step smoother. Domain and DNS settings in particular often cause trouble at the SSL stage.

  • An up to date Linux server with SSH access and a sudo user.
  • A domain name that points to the server's public IP (an A record and, if needed, an AAAA record).
  • Inbound access to ports 80 and 443.
  • A clear plan for the directory that will hold your site files.
  • A fresh backup or provider snapshot taken before you change anything.

If you are starting from a blank machine, first work through our Ubuntu Server installation and initial setup guide. Next, confirm that your domain resolves to the right IP with our DNS lookup tool. Certbot validation fails until DNS points to the server, so do not skip this check.

Finally, check whether another web server already listens on port 80. For example, if Apache runs on the same machine, Nginx will not start even after a clean install, because two programs cannot bind the same port. The command sudo ss -tlnp shows which process listens on which port.

How do you install Nginx on Ubuntu and Debian?

The simplest route uses the package from your distribution's own repository. Ubuntu Server documentation describes the install in two commands:

sudo apt update
sudo apt install nginx

On Ubuntu, the service usually starts on its own right after the package installs. You can check its state with this command:

sudo systemctl status nginx

If the output says "active (running)", Nginx is up. Next, open the server's IP address in a browser. If the Nginx welcome page appears, the first stage is done. If the page does not load, the firewall is the usual suspect; we cover it further down.

The Debian and Ubuntu package ships with the sites-available and sites-enabled layout. The default document root is /var/www/html. This layout lets you keep each site in its own file. In addition, you can switch a site off simply by removing its link.

How do you install Nginx on AlmaLinux, Rocky Linux or RHEL?

On the RHEL family, dnf is the package manager and Nginx comes from the distribution repository. The commands look like this:

sudo dnf install nginx
sudo systemctl enable --now nginx

Unlike Debian, these distributions do not start the service after installation. The enable --now flag both enables Nginx at boot and starts it immediately. Your file layout differs too. You place site files in /etc/nginx/conf.d with a .conf extension.

The second thing to watch on this family is SELinux. If you put a site in a non standard directory, or connect Nginx to a backend app, SELinux may block access. In that case you can see a 403 or 502 error even when file permissions look right. If you are still choosing a distribution, our Rocky Linux vs AlmaLinux comparison can help.

When does the official nginx.org repository make sense?

Distribution packages offer tested releases with long support. However, they sometimes stay on an older branch. If you need a newer feature, you can use the official nginx.org Linux package repository instead. It offers two branches: stable and mainline. For Ubuntu, the official page boils down to these steps:

sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring
curl -fsSL -o nginx_signing.key https://nginx.org/keys/nginx_signing.key
gpg --dearmor < nginx_signing.key | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg

Compare the fingerprint in the last output with the value on the nginx.org Linux packages page. If it does not match, stop. Then add the repository line and finish the install:

echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] https://nginx.org/packages/ubuntu `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
sudo apt update
sudo apt install nginx

The official page also suggests a pinning file under /etc/apt/preferences.d so apt prefers nginx.org packages. On the RHEL family, you create /etc/yum.repos.d/nginx.repo instead. Because these details change, always copy the commands from the official page.

Distribution package or nginx.org package: which should you pick?

Both sources are trustworthy. The real trade off sits between freshness and tight integration with your distribution. The table below sums up the choice based on the official documentation.

CriterionDistribution repo (apt/dnf)nginx.org stablenginx.org mainline
Ease of setupOne commandAdd a key and a repoAdd a key and a repo
Version freshnessVersion frozen by the distroCurrent stable branchNewest features
Security patchesArrive with distro updatesArrive with nginx.org packagesArrive with nginx.org packages
Site file layoutDebian/Ubuntu: sites-available; RHEL: conf.dconf.dconf.d
Best forMost websites and small businessesTeams that need a newer featureExperienced teams testing new features

In short, start with the distribution package unless you need a specific module or directive. That way, security updates arrive in the same stream as the rest of your operating system.

How do you manage the Nginx service with systemctl?

On modern Linux distributions, Nginx runs as a systemd service. You will handle almost every daily task with these commands:

sudo systemctl start nginx      # start
sudo systemctl stop nginx       # stop
sudo systemctl restart nginx    # full restart
sudo systemctl reload nginx     # reload config without dropping connections
sudo systemctl enable nginx     # start at boot
sudo systemctl status nginx     # show status

The difference between restart and reload matters. Restart stops the service and starts it again, so you may see a short outage. Reload, on the other hand, makes the master process read the new configuration while old workers finish current requests. Therefore, prefer reload for configuration changes.

The beginner's guide also lists the signals nginx -s reload, nginx -s quit and nginx -s reopen. Still, on a server that systemd manages, systemctl keeps the service state consistent. After you install Nginx, also run systemctl is-enabled nginx. If it prints enabled, your site comes back on its own after a reboot.

Where do the Nginx configuration files live?

With a packaged install, the main configuration file sits at /etc/nginx/nginx.conf. It holds the http block with global settings and the include lines that pull in other files. Here is the folder structure in brief:

  • /etc/nginx/nginx.conf: the main file with worker_processes, event settings and the http block.
  • /etc/nginx/sites-available/: on Debian and Ubuntu, each site's server block lives in its own file here.
  • /etc/nginx/sites-enabled/: symbolic links to active sites; Nginx only reads these.
  • /etc/nginx/conf.d/: on the RHEL family and nginx.org packages, .conf site files go here.
  • /etc/nginx/snippets/: on Debian and Ubuntu, small reusable configuration pieces.

The syntax uses nested blocks. Server blocks sit inside the http block, and location blocks sit inside server blocks. Every directive ends with a semicolon. So the most common typo is a missing semicolon at the end of a line. Keep edits to the main file small and put site settings in separate files. This also reduces conflicts during package upgrades.

How do you write your first server block?

A server block is the Nginx equivalent of an Apache virtual host. We will use example.com as the sample domain. First, create the site directory and put a simple index.html inside it:

sudo mkdir -p /var/www/example.com/html
sudo nano /etc/nginx/sites-available/example.com

Then write this basic block into the file:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    root /var/www/example.com/html;
    index index.html index.htm;

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

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

On Debian and Ubuntu, create a symbolic link to enable the site. After that, test and reload:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

On the RHEL family, put the same block in /etc/nginx/conf.d/example.com.conf. No symbolic link is needed there.

What do the directives in a server block mean?

Once you know what each line does, debugging gets much easier. The nginx.org core HTTP module documentation lists the syntax and defaults for these directives.

  • listen: the address and port the server listens on. The default_server parameter sends unmatched requests to this block.
  • server_name: the domain names this block answers. Nginx treats the first name as the primary one and also accepts wildcards and regular expressions.
  • root: the directory where Nginx looks for files. It appends the request path to this value.
  • index: the files Nginx tries, in order, when a client requests a directory.
  • try_files: checks files in order; if none exists, it falls back to the last parameter, such as =404.

For example, when a visitor requests /about, Nginx first looks for a file with that name and then for a directory. If it finds neither, it returns 404. For single page apps, you set the last parameter to /index.html so the app handles every route.

How do location blocks and static files work?

Location blocks let you apply different rules based on the request path. Prefix matches are the simplest type. Blocks that start with a tilde use regular expressions instead. Setting browser caching for static files is a common example:

location ~* \.(css|js|png|jpg|jpeg|webp|svg|woff2)$ {
    expires 30d;
    access_log off;
}

location ~ /\.(?!well-known) {
    deny all;
}

The first block sets a sample cache lifetime of 30 days for those file types. Treat that value as an example. If your file names carry no version string, keep it shorter. The second block denies access to hidden files such as .git or .env. However, it leaves the .well-known directory open for Certbot validation.

If you want to know how static file speed affects rankings, read our guide on how site speed affects SEO. Put simply, Nginx caching is only one part of measuring and improving speed.

How do you connect Nginx to PHP-FPM?

Nginx does not run PHP code itself. Instead, it passes the request to the PHP-FPM service over the FastCGI protocol. The Debian and Ubuntu package ships a ready snippet for this, so a short addition to the server block is often enough:

index index.php index.html;

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php-fpm.sock;
}

The socket file name depends on your PHP version and distribution. So check the real path with ls /run/php/ and adjust the fastcgi_pass line to match. A wrong socket path is one of the most common causes of a 502 error.

For apps such as WordPress or Laravel, you change the try_files line in location / so it hands requests to index.php. For Laravel specifics, see our Laravel cPanel and VPS deployment guide. Node.js and Next.js apps need a reverse proxy setup instead; we touch on that below.

How do you add an SSL certificate with Certbot?

Let's Encrypt issues free certificates that renew automatically, and Certbot is the official client that requests them. Certbot's Nginx instructions recommend the snap package:

sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot
sudo certbot --nginx

The last command reads the names in server_name, gets the certificate and adds a 443 block to your Nginx configuration. If you do not want Certbot to touch your files, run certbot certonly --nginx instead. Then test renewal with this command:

sudo certbot renew --dry-run

According to Certbot's documentation, the package sets up a cron job or systemd timer that renews certificates before they expire. We explain why SSL matters in what is an SSL certificate. After setup, you can verify the chain from outside with our SSL checker.

Why should you test every change with nginx -t?

In Nginx, a single missing semicolon can take every site down on restart. That is why you should test the syntax after each change:

sudo nginx -t
sudo systemctl reload nginx

A passing test prints "syntax is ok" and "test is successful". If something is wrong, Nginx shows the file name and line number, so you can jump straight to it. A reload with a broken file keeps the old working configuration in place. A restart, by contrast, may fail to start the service at all.

When you have many include files, sudo nginx -T prints the combined configuration that Nginx actually reads. As a result, you can see at a glance which file overrides which setting. In addition, nginx -v shows the version and nginx -V shows build options and modules.

Before any edit, also copy the current file. For instance, a dated copy of the file in sites-available lets you roll back within seconds. Keeping configuration files in Git works well too. Our team's habit is simple: edit, test, reload, then check in a browser.

Where are the Nginx logs and how do you read them?

With packaged installs, the default logs live at /var/log/nginx/access.log and /var/log/nginx/error.log. If you set custom log paths in a server block, that site writes to its own files. Use these commands to watch them live:

sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.log
sudo journalctl -u nginx --since "1 hour ago"

The access log records each request, its status code and client details. The error log shows permission problems, missing files and backend connection issues. Whenever you see an error page, check the error log first. The real cause usually appears there in plain words.

Logs grow over time. Distribution packages usually include a logrotate setup; even so, check sizes now and then so the disk does not fill up. Also remember that logs hold personal data such as IP addresses. Set your retention period according to your GDPR obligations.

Why do 403, 404 and 502 errors appear and how do you fix them?

These three are the errors you will meet most often on a fresh Nginx server. Each one points to a different layer:

  • 403 Forbidden: Nginx cannot read the file. Check directory permissions, the index file and, on the RHEL family, the SELinux context. If a WAF runs on the server, our ModSecurity and 403 errors guide helps.
  • 404 Not Found: the root path is wrong, the file is missing or try_files sends the request to the wrong place. The error log shows the exact path Nginx tried.
  • 502 Bad Gateway: Nginx cannot reach the backend. PHP-FPM or the app service may be down, or the socket path or port may be wrong.

We cover the full 502 diagnosis in our 502 Bad Gateway guide. The general rule is simple. First read the error log. Then check the backend with systemctl status. Finally, review the configuration with nginx -T. Also remember that the Nginx user needs execute permission on every directory in the path. A common starting point is 644 for files and 755 for directories.

How do you add security headers and hide the Nginx version?

By default, Nginx shows its version on error pages and in the Server response header. The core module documentation lists on as the default for server_tokens. To turn it off, add this line to the http block:

server_tokens off;

Hiding the version does not make a server secure on its own. Still, it gives automated scanners less free information. Next, add basic security headers to the server block:

add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Only after HTTPS works permanently, sample value:
# add_header Strict-Transport-Security "max-age=31536000" always;

One detail matters here. A block inherits add_header directives from the level above only if it defines none of its own. In other words, one add_header inside a location block drops all the headers from above for that block. For application level risks, also read our OWASP Top 10 guide.

Which firewall ports should you open?

A web server only needs ports 80 (HTTP) and 443 (HTTPS). You also keep the SSH port open for administration, but close everything else to the outside. On Ubuntu, the Nginx package ships ready made UFW application profiles:

sudo ufw app list
sudo ufw allow 'Nginx Full'
sudo ufw status

The Nginx Full profile opens both 80 and 443. On the RHEL family, you use firewalld instead:

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

Always allow SSH before you enable the firewall; otherwise you lock yourself out. To harden SSH, follow our Linux swap and SSH hardening guide. Also, some VPS providers run a separate network firewall in their panel. Check both layers.

What comes next: reverse proxy and load balancing?

Once Nginx serves a static site or PHP, most teams put it in front of applications next. This setup is a reverse proxy. Nginx listens on 80 and 443 and forwards requests to an app on a local port with proxy_pass. So you manage SSL and compression in one place.

We show a full Node.js example in our Node.js deployment with Nginx and systemd guide. For Next.js, see the Next.js VPS deployment guide. Reverse proxy details, Nginx Proxy Manager and spreading load across several servers come in the next two posts of this series. Here we focus only on the core web server setup.

When should you not install Nginx yourself?

To be honest, not everyone needs to run their own web server. If the command line feels unfamiliar, or you lack time for regular updates, managed hosting or a managed VPS is the safer choice. After all, a badly configured server carries far more risk than a slow site.

We suggest leaving the job to your hosting provider or an experienced sysadmin in these cases:

  • The site handles payments, accounts or personal data and needs a security review.
  • You expect high traffic, several servers or strict uptime requirements.
  • Nobody can step in when the server has an emergency.

If you have not picked a host yet, start with our guide on how to choose web hosting. For the site itself, its speed and its conversions, our web design service can help.

What should your post install Nginx checklist include?

When you think you are done, tick off the list below one item at a time. That way, small gaps do not turn into problems on the live site.

  1. systemctl status nginx shows active (running), and the service starts at boot.
  2. nginx -t passes, and you apply changes with reload.
  3. The domain resolves to the right IP, and www and non www addresses go to one URL.
  4. HTTPS works, and certbot renew --dry-run succeeds.
  5. server_tokens is off, and basic security headers are active.
  6. Hidden files are blocked, and directory listing is off.
  7. Only SSH, 80 and 443 are open in the firewall.
  8. The error log is clean, and you know the cause of any 403, 404 or 502 entries.
  9. Regular backups and a rollback plan are ready.

If every item passes, your Nginx server is ready for live traffic. From there, you can move on to performance testing, caching and reverse proxy work. Our advice as a team: make each change in small steps and test after every step.

Frequently Asked Questions

Which Linux distribution is best to install Nginx on?
Nginx runs from official packages on all common distributions, including Ubuntu, Debian, AlmaLinux and Rocky Linux. So pick the distribution your team knows best and the one with the support window you need. You use apt on Ubuntu and Debian and dnf on the RHEL family; the configuration logic stays largely the same.
Can Nginx and Apache run on the same server?
Yes, they can, but they cannot listen on the same port. A common pattern lets Nginx listen on 80 and 443 and forward some requests to Apache on another port as a reverse proxy. However, this setup adds complexity. If one web server covers your needs, we do not recommend running both.
Should I restart or reload Nginx after a config change?
Reload is the right choice for configuration changes. It loads the new settings without dropping connections, and it keeps the old working configuration if the new one fails. Restart stops and starts the whole service. In both cases, run sudo nginx -t first to test the syntax, then run the command.
How do I show my own site instead of the Nginx welcome page?
Write a separate server block for your site and add your domain to the server_name line. On Debian and Ubuntu, you place the block in sites-available and link it into sites-enabled. You can also remove the default site link. Finally, test with nginx -t, reload, and check the site in a browser.
Does a Let's Encrypt certificate renew automatically on Nginx?
Yes, if you installed it with Certbot, renewal runs on its own. According to Certbot's documentation, the package sets up a cron job or systemd timer that renews certificates before they expire. Even so, run sudo certbot renew --dry-run after setup and make sure port 80 stays reachable for validation.
Should I manage my own Nginx server or buy managed hosting?
If you are comfortable on the command line and can keep up with updates, you can run your own Nginx server. Otherwise, managed hosting or a managed VPS is safer. Sites that handle payments or personal data carry a heavy security burden, so we recommend working with an experienced sysadmin and keeping regular backups.
  • Nginx
  • web server
  • Linux server
  • Certbot
  • SSL
  • server security
  • VPS
Share:
Talha Aslan

Google Partner digital marketing expert. Hands-on with SEO, Google Ads, web design and e-commerce projects since 2012; every post here comes from that experience.

Next project

Let's talk about your project.

Your brief goes straight to Talha Aslan and team: strategy led by Talha, delivery by an experienced team. The first consultation is free; we listen and come back with a clear roadmap.