Setup Guides

Nginx Setup and Server Block Configuration

We explain how to install Nginx on Ubuntu, create a server block for your domain, set up a reverse proxy for a Node.js app, and fix common errors.

Aurora YazılımEditorial team 6 min read
Nginx Setup and Server Block Configuration
How do you install Nginx on Ubuntu?

For an Nginx installation, run sudo apt update and sudo apt install nginx, and allow the Nginx Full profile in the firewall. Then create a server block for your domain under /etc/nginx/sites-available, link it into the sites-enabled folder, test with sudo nginx -t and apply the change with sudo systemctl reload nginx.

What Is Nginx and What Is It Used For?

Nginx is an open-source web server and reverse proxy that can handle a high number of concurrent connections with little memory. It serves static files very fast; it sits in front of Node.js, Python or PHP applications and forwards requests to them, terminates SSL and acts as a caching layer.

Its main difference from Apache is the configuration style: Nginx has no directory-level .htaccess file; all rules are kept in the central configuration. This improves performance but means that people moving from Apache have to rewrite their rules. If you are curious about the Apache equivalents, see our htaccess redirects article.

This guide follows Ubuntu and Debian; you will find the development setup for macOS and Windows under a separate heading.

Prerequisites

If Apache is also installed on the server, the two services try to listen on the same port 80 and Nginx will not start. Stop and disable Apache, or make it listen on a different port.

  • A server running Ubuntu or Debian and a user with sudo privileges
  • Your domain's A record pointing to the server IP
  • No other service (e.g. Apache) using ports 80 and 443
  • If you will set up a reverse proxy, an application running on the server (e.g. Node.js on port 3000)

Nginx Installation Steps on Ubuntu

The Nginx package in Ubuntu's own repository receives security updates regularly and is enough for most projects. If you need a newer mainline release, you can add the official package repository at nginx.org.

bash
sudo apt update
sudo apt install nginx
sudo systemctl enable --now nginx
sudo systemctl status nginx

# Firewall (if you use UFW)
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

# Verification
nginx -v
curl -I http://localhost

Important files and folders

  • /etc/nginx/nginx.conf: the main configuration file
  • /etc/nginx/sites-available/: defined server blocks
  • /etc/nginx/sites-enabled/: links to the active blocks
  • /var/www/: the common root folder for site files
  • /var/log/nginx/access.log and error.log: request and error logs

How to Create a Server Block

A server block is the equivalent of a virtual host in Apache and lets you host multiple domains on a single server. Creating a separate file for each site makes management easier.

First create the site folder and set its ownership, then write the configuration file. Add both the bare domain and the www version to the server_name line; tools such as Certbot read this line to obtain a certificate.

bash
sudo mkdir -p /var/www/ornek.com/html
sudo chown -R $USER:$USER /var/www/ornek.com/html
echo '<h1>ornek.com is working</h1>' > /var/www/ornek.com/html/index.html
sudo nano /etc/nginx/sites-available/ornek.com
nginx/etc/nginx/sites-available/ornek.com
server {
    listen 80;
    listen [::]:80;
    server_name ornek.com www.ornek.com;

    root /var/www/ornek.com/html;
    index index.html;

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

    access_log /var/log/nginx/ornek.com.access.log;
    error_log  /var/log/nginx/ornek.com.error.log;
}
bashEnable and test
sudo ln -s /etc/nginx/sites-available/ornek.com /etc/nginx/sites-enabled/
# If you want to disable the default welcome page
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx

Nginx Reverse Proxy Configuration

Instead of exposing a Node.js, Python or other application server directly to the internet, placing Nginx in front of it is a common and safe setup. Nginx listens on ports 80 and 443 and forwards requests to the locally running application; the application's own port stays closed to the outside.

In the example below, the application runs on port 3000. To pass the real client IP and the protocol to the application, proxy headers are added; applications that use WebSockets also need the Upgrade headers.

If you run several applications on the same server, giving each its own subdomain and its own server block is the tidiest approach. For example, the admin panel can be served at panel.ornek.com and the API at api.ornek.com; when each block has its own log file, finding which application a problem comes from also gets easier. To read the real client IP in the application, do not forget to enable the trust proxy setting of the framework you use.

nginx
server {
    listen 80;
    server_name app.ornek.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    client_max_body_size 20m;
}

HTTPS, Compression and Caching

Once the server block works, the next step is moving to HTTPS with a free certificate. Certbot's Nginx plugin obtains the certificate and adds the 443 block and the redirect for you; we described the steps in the SSL certificate installation guide.

On the speed side, gzip compression and long-lived cache headers for static files make a big difference. Putting the domain behind a CDN such as Cloudflare also serves static content from points close to the visitor; you can find the setup in our Cloudflare setup article.

  • If you use version fingerprints in file names (e.g. app.3f9a.css), you can extend the cache duration even further.
  • Do not cache HTML files for a long time; otherwise updates reach visitors late.
nginxInside the server block
gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;

location ~* \.(css|js|webp|avif|png|jpg|svg|woff2)$ {
    expires 30d;
    add_header Cache-Control "public";
}

Basic Security Settings

The default installation works, but before going live a few simple settings noticeably reduce the attack surface. None of them require extra software; adding a few lines to the configuration is enough.

The first job is to turn off server_tokens, so the Nginx version number does not appear on error pages and in headers. Then add a default block that handles requests arriving with undefined domain names. This block keeps bots that hit your server's IP address directly from seeing your first site.

Blocking access to hidden files is also important. A .git folder or .env file accidentally left in the root can expose your source code or database passwords to everyone. Such leaks usually come not from bad intent but from a hasty upload.

Finally, update server packages regularly and keep open only the ports you really need. When launching a web design project or an e-commerce platform, applying this checklist from scratch every time greatly reduces surprises later.

nginx
# Inside the http block of /etc/nginx/nginx.conf
server_tokens off;

# Default block that rejects undefined domain names
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 444;
}

# Inside the site block: block hidden files
location ~ /\.(?!well-known) {
    deny all;
}

Development Environment on macOS and Windows

Although the live server is mostly Linux, trying the configuration locally speeds up your work. Nginx installed with Homebrew on macOS listens on port 8080 by default, and the configuration file is in the etc/nginx folder under the Homebrew prefix.

Although a build exists on nginx.org for Windows, the official documentation notes that this version has limitations. On Windows, the most practical way is to run the Linux version in Docker or WSL; that way you test in the same environment as the live server.

macOS (Homebrew)

bash
brew install nginx
brew services start nginx
nginx -t
# Configuration folder
ls $(brew --prefix)/etc/nginx
curl -I http://localhost:8080

Windows (Docker)

powershell
docker run -d --name web -p 8080:80 nginx
curl.exe -I http://localhost:8080

Common Errors and Fixes

When debugging, the first step is always to check the syntax with sudo nginx -t and then the error.log file. Most problems are solved by the one-line message there.

SymptomLikely cause and fix
502 Bad GatewayThe application behind is not running or the port is wrong; check the application and the proxy_pass address.
403 ForbiddenFolder permissions are insufficient or there is no index file; check ownership and the index line.
Address already in useAnother service is using port 80; find it with ss -tlnp and stop it.
conflicting server nameThe same server_name is defined in two blocks; remove the duplicate.
413 Request Entity Too LargeThe uploaded file exceeds the limit; increase the client_max_body_size value.
bash
sudo nginx -t
sudo tail -n 50 /var/log/nginx/error.log
sudo ss -tlnp | grep -E ':80|:443'

Frequently Asked Questions

01Which is better, Nginx or Apache?

Both are mature and reliable servers. Nginx stands out under high concurrent traffic and as a reverse proxy, while Apache offers flexibility on shared hosting thanks to .htaccess support. Many infrastructures use both together.

02What is the difference between restart and reload?

reload loads the new configuration without dropping running connections; it should be preferred for everyday changes. restart stops the service completely and starts it again, and may cause a brief interruption.

03How many sites can I host on one server?

The limit is set by the server's resources, not by Nginx. By opening a separate server block for each domain, you can run many sites on the same machine; as traffic grows, you need to monitor memory, CPU and disk usage.

04Can you do load balancing with Nginx?

Yes. If you define several application servers in an upstream block and route to that group with proxy_pass, Nginx distributes requests among the servers. The default method is round robin; you can change the behavior with methods such as least_conn or ip_hash.

A properly configured Nginx gives you a fast, secure foundation that can carry multiple applications. If you want to handle server settings, caching and Core Web Vitals targets together, explore our speed and performance optimization service. For a custom system running on its own server, or ready-made Aurora solutions such as hotel software, you can reach us through the contact page.