Setup guides

Installing and configuring Nginx: a practical guide

Installing Nginx, server blocks, wiring up PHP-FPM, and how to test a configuration before it reaches production.

9 min read
Green Nginx gateway distributing incoming traffic to three servers

Nginx handles more concurrent connections than Apache on the same hardware, which makes it the usual choice on virtual servers. Installation takes minutes; the real work is getting the configuration right.

Installation

bash# Ubuntu / Debian
apt update && apt install -y nginx

# AlmaLinux / Rocky
dnf install -y nginx

Start the service and enable it at boot:

bashsystemctl enable --now nginx
systemctl status nginx --no-pager

Do not forget the firewall:

bashufw allow 'Nginx Full'                       # Ubuntu / Debian
# firewall-cmd --permanent --add-service=http --add-service=https && firewall-cmd --reload

Opening the server's IP in a browser should show the Nginx welcome page.

Server blocks: hosting multiple sites

In Nginx each site is a server block. On Ubuntu and Debian these live in /etc/nginx/sites-available/ and are enabled by symlinking into sites-enabled/. On AlmaLinux you place a .conf file directly in /etc/nginx/conf.d/.

The simplest block for a static site:

textserver {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    root /var/www/yourdomain.com;
    index index.html;

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

Enabling it on Ubuntu:

bashln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/

Connecting PHP-FPM

PHP applications like WordPress or Laravel need requests handed to PHP-FPM:

bashapt install -y php-fpm php-mysql

Add these two locations to the server block:

textindex index.php index.html;

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

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

The version in the socket path depends on the PHP you installed; check the real one with:

bashls /run/php/

Test the configuration before you apply it

This step is not optional. Restarting with a broken configuration takes down every site on the server at once:

bashnginx -t

If the output says syntax is ok and test is successful, apply it safely:

bashsystemctl reload nginx

reload differs from restart: it applies the new configuration without dropping existing connections. Make reload your habit.

HTTPS and redirects

Get the certificate with Certbot; it edits the Nginx configuration for you:

bashcertbot --nginx -d yourdomain.com -d www.yourdomain.com

Certbot offers to add an HTTP to HTTPS redirect — accept it. For detail and renewal checks see our SSL installation guide.

Two settings worth adding

Compression. Cuts the size of text-based files considerably:

textgzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
gzip_min_length 1024;

Static file caching. Stops browsers re-downloading images and scripts:

textlocation ~* \.(jpg|jpeg|png|webp|avif|gif|ico|css|js|woff2)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
}

Common mistakes

403 Forbidden — File permissions or the root path are wrong. Make sure the Nginx user (www-data or nginx) can read the directory.

502 Bad Gateway — PHP-FPM is not running, or the socket path is wrong. Check with systemctl status php8.3-fpm.

Changes not taking effect — You forgot to reload, or another server block with the same server_name matches first.

The default site keeps serving — On Ubuntu, remember to remove the sites-enabled/default symlink.

If you get stuck on installation or configuration, get in touch.