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 nginxStart the service and enable it at boot:
bashsystemctl enable --now nginx
systemctl status nginx --no-pagerDo not forget the firewall:
bashufw allow 'Nginx Full' # Ubuntu / Debian
# firewall-cmd --permanent --add-service=http --add-service=https && firewall-cmd --reloadOpening 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-mysqlAdd 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 -tIf the output says syntax is ok and test is successful, apply it safely:
bashsystemctl reload nginxreload 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.comCertbot 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.
