Nginx consumes significantly less memory and handles static content many times faster than Apache. The switch pays off under heavy load or with limited server resources. The main challenge is converting .htaccess to Nginx's location-block syntax.
Apache vs Nginx: key differences
| Aspect | Apache | Nginx |
|---|---|---|
| Architecture | Process/Thread | Event-driven (asynchronous) |
| Static files | Slower | 2–4 times faster |
| RAM usage | Higher (fork per request) | Lower (worker processes) |
| PHP | mod_php (built in) | Only via PHP-FPM |
| .htaccess | Supported | Not supported |
| Configuration | Per-directory (.htaccess) | Centralized |
Installing Nginx and PHP-FPM
# Install Nginx and PHP-FPM
apt install nginx php8.3-fpm -y
# Stop Apache
systemctl stop apache2
systemctl disable apache2
# Start Nginx
systemctl enable --now nginx
Converting an Apache Virtual Host to an Nginx Server Block
># Apache VirtualHost (before)
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/html
DirectoryIndex index.php index.html
AllowOverride All
</VirtualHost>
# Nginx Server Block (after)
server {
listen 80;
server_name example.com www.example.com;
root /var/www/html;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
Converting .htaccess rules
># .htaccess: Redirect (before)
Redirect 301 /old-page.html /new-page
# Nginx (after)
location = /old-page.html {
return 301 /new-page;
}
# .htaccess: RewriteRule
RewriteRule ^products/([0-9]+)$ product.php?id=$1 [L]
# Nginx:
location ~ ^/products/([0-9]+)$ {
rewrite ^/products/([0-9]+)$ /product.php?id=$1 last;
}
# .htaccess: Deny access to directory
Options -Indexes
# Nginx:
location /private/ {
deny all;
}
# .htaccess: Custom error pages
ErrorDocument 404 /404.php
# Nginx:
error_page 404 /404.php;
Nginx config for WordPress (full example)
>server {
listen 443 ssl http2;
server_name example.com www.example.com;
root /var/www/wordpress;
# Gzip compression
gzip on;
gzip_types text/css application/javascript text/html;
# Static files — cache
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_read_timeout 300;
include fastcgi_params;
}
}
.htaccess converter: Use the online tool winginx.com/htaccess to automatically convert .htaccess rules to Nginx syntax. Then be sure to check the result by hand.
.htaccess is ignored by Nginx — the files stay on disk but are never processed. If the site relies on .htaccess for redirects or directory protection, all those rules need to be moved into the Nginx config by hand.