Skip to main content

Migrating from Apache to Nginx: Configs and .htaccess

Migration · 19.04.2026 · 3 min read
Illustration for “Migrating from Apache to Nginx: Configs and .htaccess”

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

AspectApacheNginx
ArchitectureProcess/ThreadEvent-driven (asynchronous)
Static filesSlower2–4 times faster
RAM usageHigher (fork per request)Lower (worker processes)
PHPmod_php (built in)Only via PHP-FPM
.htaccessSupportedNot supported
ConfigurationPer-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.
Was this article helpful?
← Back to Knowledge Base Ask Support