25

EDIT

It turns out that I was barking up the wrong tree trying to edit .htaccess, as nginx doesn't use it. What I apparently need to do is edit my .conf file. Before I read this, my_app.conf looked like this:

upstream backend {
    server unix:/u/apps/my_app/tmp/php.sock;
}

server {

    listen 80 default;
    root /u/apps/my_app/www;
    index index.php;

    access_log /u/apps/my_app/logs/access.log;
    error_log /u/apps/my_app/logs/error.log;

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

    # This location block matches anything ending in .php and sends it to
    # our PHP-FPM socket, defined in the upstream block above.
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass backend;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /u/apps/my_app/www$fastcgi_script_name;
        include fastcgi_params;
    }

    # This location block is used to view PHP-FPM stats
    location ~ ^/(php_status|php_ping)$ {
        fastcgi_pass backend;
        fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
        include fastcgi_params;
        allow 127.0.0.1;
        deny all;
    }

    # This location block is used to view nginx stats
    location /nginx_status {
        stub_status on;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

Now it looks like this, and it's still not working:

upstream backend {
    server unix:/u/apps/my_app/tmp/php.sock;
}

server {

    listen 80 default;
    root /u/apps/my_app/www;
    index index.php;

    access_log /u/apps/my_app/logs/access.log;
    error_log /u/apps/my_app/logs/error.log;

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

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

    rewrite /wp-admin$ $scheme://$host$uri/ permanent;

    location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2    |doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
       access_log off; log_not_found off; expires max;
    }

    # Uncomment one of the lines below for the appropriate caching plugin (if used).
    #include global/wordpress-wp-super-cache.conf;
    #include global/wordpress-w3-total-cache.conf;

    # This location block matches anything ending in .php and sends it to
    # our PHP-FPM socket, defined in the upstream block above.
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass backend;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /u/apps/my_app/www$fastcgi_script_name;
        include fastcgi_params;
    }

    # This location block is used to view PHP-FPM stats
    location ~ ^/(php_status|php_ping)$ {
        fastcgi_pass backend;
        fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
        include fastcgi_params;
        allow 127.0.0.1;
        deny all;
    }

    # This location block is used to view nginx stats
    location /nginx_status {
        stub_status on;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

Anyone know what I'm doing wrong?

END EDIT

I have changed my permalinks from the default to /%postname%/, and now the links within WordPress's Admin panel give me 404 errors - Not WordPress 404 pages, nginx 404 pages. Looking up why this is told me that this should be editing my .htaccess file or telling me WordPress can't rewrite .htaccess - the .htaccess file is nonexistant, and WordPress isn't giving any errors when I change permalinks.

I've tried creating a blank .htaccess file in my wordpress folder, giving it 666 permissions, changing the user and group to www-data and then changing the permalinks- that didn't work. I then changed it to this before changing the permalinks:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

When that didn't work, I changed RewriteBase to /wordpress/ before changing permalinks again - still nothing.

I've also gone into my site's .conf file and changed try_files $uri $uri/ /index.php; to the following, restarting nginx and php5-fpm each time;

try_files $uri $uri/ /index.php?$query_string;

try_files $uri $uri/ /index.php?q=$request_uri;

try_files $uri $uri/ /index.php?$args;

I'm running a home server with nginx. Any ideas about what's going on here?

7 Answers 7

16

Those are Apache .htaccess rewrite rules, but you have stated that you are on an Nginx server. Nginx does not use an .htaccess-like directory level file, much less does it use the .htaccess file itself.. You need to edit the server configuration itself. The Codex has a detail sample:

# WordPress single blog rules.
# Designed to be included in any server {} block.

# This order might seem weird - this is attempted to match last if rules below fail.
# http://wiki.nginx.org/HttpCoreModule
location / {
    try_files $uri $uri/ /index.php?$args;
}

# Add trailing slash to */wp-admin requests.
rewrite /wp-admin$ $scheme://$host$uri/ permanent;

# Directives to send expires headers and turn off 404 error logging.
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
       access_log off; log_not_found off; expires max;
}

# Uncomment one of the lines below for the appropriate caching plugin (if used).
#include global/wordpress-wp-super-cache.conf;
#include global/wordpress-w3-total-cache.conf;

# Pass all .php files onto a php-fpm/php-fcgi server.
location ~ [^/]\.php(/|$) {
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    if (!-f $document_root$fastcgi_script_name) {
        return 404;
    }
    # This is a robust solution for path info security issue and works with "cgi.fix_pathinfo = 1" in /etc/php.ini (default)

    include fastcgi.conf;
    fastcgi_index index.php;
#   fastcgi_intercept_errors on;
    fastcgi_pass php;
}
3
  • Thanks, I'd vote this up if I had the reputation. I'm having a little trouble implementing this into my .conf file seeing as it was already changed significantly from the default, but at least I'm not fiddling around with .htaccess any more. Commented May 21, 2015 at 19:32
  • @s_ha_dum, I used thies configuration until yesterday when I updated to wordpress 4.8 and now I am getting 404s on permalinks custom structure....tried debugging it since yesterday but nothing worx, any ideas??
    – Jadeye
    Commented Jul 4, 2017 at 14:32
  • I had to change the last line ot read "fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;" to work on Ubuntu 18.04 but it works and saved my sanity
    – Rob
    Commented Dec 17, 2018 at 3:24
32

I'm using wordpress multisite with custom permalink setting: /%category%/%postname%/

/etc/nginx/site-available/domain.conf

On server{

location / {
    try_files $uri $uri/ /index.php?q=$uri$args;
}

If your root wordpress is not the webroot but http://domain.com/wordpress/:

location /wordpress/ {
    try_files $uri $uri/ /wordpress/index.php?q=$uri$args;
}

If you are using old wordpress with blogs.dir, add: location ^~ /blogs.dir { internal; alias /var/www/wordpress/wp-content/blogs.dir; access_log off; log_not_found off; expires max; }

Check the nginx configuration: sudo nginx -t

Reload nginx: sudo service nginx reload

Also try change permalink settings.

4
  • 7
    This is the best answer for anyone who wants to manually move a WordPress installation to a subdirectory under a new domain name! THANK YOU SO MUCH! This should be the accepted answer. Commented Jan 24, 2017 at 13:25
  • 1
    The path: /etc/nginx/site-available/ should read: /etc/nginx/sites-available/
    – Grant
    Commented Feb 20, 2018 at 10:14
  • 1
    The second option works for me as my site was in a sub directory
    – Arunendra
    Commented Oct 19, 2020 at 2:37
  • I joined this exchange only so that I could thank you. Praised be, wise man! I was about to start pulling my hair out when this solution saved me. Context: I copied my WP db from one Ubuntu host to another and I am using Nginx to serve WP. Commented Oct 26, 2023 at 15:22
12

Had to add this piece of code to both the /sites-available/your-settings-file and /sites-enabled/your-settings-file:

server {
[...]

if (!-e $request_filename) {
    rewrite ^.*$ /index.php last;
}

[...]
}

It's working for me now.

6
  • 1
    This is the simple answer I was looking for, thanks
    – ThEBiShOp
    Commented Jun 28, 2017 at 19:15
  • 1
    This worked! Could you please explain what it does? (esp the "last" part...)
    – Sidd
    Commented Aug 12, 2018 at 18:50
  • This code still work! Commented Sep 16, 2020 at 17:34
  • 1
    sites-enabled/ files are symlinked from sites-available/, so basically you are editing the file inside sites-available/ and changes will be reflected in the other folder automatically. Just a clarification. Commented Jan 15, 2021 at 18:39
  • Can confirm this still works like a charm!
    – terryeah
    Commented Apr 2, 2022 at 2:11
1

I had to set the root path to wordpressś installed directory: root /var/www/html/wp;

I dont like it because I have more applications installed on this machine but creating more virtual hosts should be enough.

0

@Angelo's answer solved the issue for me. I'd upvote but lack reputation so posting an answer.

Just for Clarity the following

server {
        server_name xxx.xxxx.com;
        
        root /var/www/wordpress;

        listen 80;
        listen [::]:80;

        index index.php;

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

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

became

server {
        server_name xxx.xxxx.com;
        
        root /var/www/wordpress;

        listen 80;
        listen [::]:80;

        index index.php;

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

        if (!-e $request_filename) {
                rewrite ^.*$ /index.php last;
        }

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

Notice the extra


        if (!-e $request_filename) {
                rewrite ^.*$ /index.php last;
        }
0

Step 1. Edit /etc/nginx/site-available/example.com

location / {
try_files $uri $uri/ /index.php?q=$uri$args;
}

Step 2. Login to the server Step 3. Run the following code to symlink your domain

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com

step 4. Test configuration

sudo nginx -t

step 5. Restart Nginx server

sudo systemctl restart nginx

step 6. Save the permalink from WordPress admin dashboard ***** Happy browsing ****

More details http://toihid.com/wordpress-permalink-in-nginx-server/

0

Here is a fix that worked for me on a new ish server. The server never had apache running on it. When permalinks were changed i would 404 on all pages except home. Turned on apache instead of Nginx, then CHANGE the permalinks settings and save. Then likely change again to what you want, and save. This will create an .htaccess file. Then turn on ngnix again and it all works.

Nginx has a system to look at the .htaccess file and configure itself. But until there is a .htaccess file, it can't do that.

This is on plesk, wordpress 6.5 and PHP 8.2 on linux.

Not the answer you're looking for? Browse other questions tagged or ask your own question.