Migrating a site from Apache to Nginx means translating mod_rewrite rules, which live in .htaccess, into Nginx’s rewrite, return, and location directives. The two engines share a PCRE-style regex syntax but differ in structure and flag handling. This .htaccess to Nginx converter parses your rewrite rules and produces matching Nginx blocks in your browser, without sending your configuration to any server.
The structural difference between Apache and Nginx rewrites
Apache evaluates .htaccess files per directory at request time, and RewriteCond lines accumulate and apply to the next RewriteRule as a group. Nginx has no .htaccess equivalent — all rules live in the server or location block in nginx.conf, and each if block is independent. This is the root of most migration friction.
How the converter works
The tool walks your input and processes each condition-plus-rule block:
- A
RewriteRulewithR=301orR=302becomes areturn <code> <target>;— a direct redirect with no regex overhead. - A plain internal rewrite becomes
rewrite "<pattern>" <target> last;orbreakdepending on context. F(forbidden) becomesreturn 403;;G(gone) becomesreturn 410;.- A preceding
RewriteCondtesting%{HTTP_HOST},%{REQUEST_URI},%{QUERY_STRING}, or%{HTTPS}becomes an Nginxifguard wrapping the rule. - Because Apache per-directory patterns match paths without a leading slash but Nginx matches with one, the converter adds a leading slash to anchored patterns.
Worked examples
WWW redirect (very common)
Apache:
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
Nginx equivalent:
if ($host ~* "^example\.com$") {
return 301 https://www.example.com/$1;
}
HTTP to HTTPS redirect
Apache:
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Nginx equivalent (preferred pattern — use a separate server block):
server {
listen 80;
return 301 https://$host$request_uri;
}
Clean URL rewrite (hiding .php extension)
Apache:
RewriteRule ^([a-z0-9-]+)$ index.php?slug=$1 [L,QSA]
Nginx:
rewrite ^/([a-z0-9-]+)$ /index.php?slug=$1 last;
What the converter cannot translate automatically
- File-existence checks (
-f,-d,-l) — these becometry_filesin Nginx, notifblocks, and require knowing your document root. - Multiple
RewriteCondlines — Nginxifblocks cannot chain; multiple conditions must be collapsed to a single regex or handled with amapdirective. [ENV=VAR:value]— Nginx usesset $variableinstead and the semantics differ.- Per-file rules (inside
.htaccessat a nested path) — Nginx has no equivalent; they must be merged into the appropriatelocationblock.
How to use the output safely
Treat the generated config as a first draft. After copying it into your Nginx server block, test with nginx -t, then exercise the redirects with curl -v or a redirect tracer before going live. Everything parses locally — your rules, paths, and hostnames never leave your browser.