Welcome Guest, Not a member yet? Register   Sign In
nginx proxying PHP to Apache, and CodeIgniter
#1

[eluser]SneakyDave[/eluser]
I have a new experimental server set up that uses nginx on port 80 and Apache on port 8080, ningx proxies PHP files to Apache for processing.

And let me start off by saying, I don't want to use fastcgi with PHP unless I really have to.

I have this working pretty well, and it works well with Codeigniter, until I want to use mod_rewrite in the Apache .htaccess files.

The problem is that nginx successfully passes the PHP files to Apache, but if the url is written with Apache's mod_rewrite in mind, nginx tries to interpret the page, and a 404 error results.

For example, this works:
http://somedomain.com/index.php?welcome

But this request doesn't. It results in an nginx 404 page, even if .htaccess is used correctly, because it never gets to Apache to process:
http://somedomain.com/welcome/

So the questions I have are:
1) Do I need to send all PHP files, AND all "/" requests to apache, to have .htaccess rewrite the destination correctly?

2) Do I somehow use nginx's configuration to rewrite all CI requests to proxy to Apache, and if so, how would I do that?

3) Should I send all 404 requests in nginx to Apache to process, hoping that the request is really just a mod_rewrite request for a CI page?

Thanks for your help.
#2

[eluser]Greg Aker[/eluser]
SneakyDave:

I know this is about a month old, but if you haven't found a solution yet, I thought I'd write. If you have found a solution, please post away Smile

For me personally, I prefer an "inclusive," not "catch-all" rewrite. Let Apache/mod_php handle what it does best, and let Nginx do what it does best. On my site, I'm running Nginx with the ExpressionEngine Public Beta (so a CI app Smile ).


So in the Nginx vhost setup, I have:

Code:
location ~ \.php$ {
      proxy_set_header X-Forwarded-Host $host;
      proxy_set_header X-Forwarded-Server $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_pass http://127.0.0.1:8080;
   }

   rewrite ^/home(.*)? /index.php?/home$1 last;
   rewrite ^/member(.*)? /index.php?/member$1 last;
   rewrite ^/P(.*)? /index.php?/P$1 last;
   rewrite ^/category(.*)? /index.php?/home$1 last;

Also make sure to have the Apache rpaf module installed so Apache will get the proper referrer IP address so you can use the proxy_ips config item in CI. Smile

So yes, you'd need to add a rule for each controller, but I find it's working well for me.

-greg
#3

[eluser]SneakyDave[/eluser]
Thanks, I did find a solution, it was just kind of the lazy solution. You're solution would obviously be more efficient than mine below. I'm going to try your solution as soon as I can move more work (Allow/Deny, authentication, and the CI mod_rewrites) to nginx.

Basically, I just tell nginx to handle all my static content, and then send everything else to Apache. I can use this setup for all the virtual hosts.

nginx declaration
Code:
location ~* ^.+\.(jpe?g|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|swf|avi|mp3|html)$ {
  expires 10d;
  root   /virtualdomain/html/root;
  }

Proxy everything else to Apache, not just .php files. This makes sure mod_rewrite and other declaratives in .htaccess get processed. This seems to work as intended, because one time, I had typoed the nginx web root, and all of my images were returning 404's.
Code:
location / {
  proxy_pass   http://localhost:8080;
  proxy_redirect          off;
  proxy_set_header        Host            $host;
  proxy_set_header        X-Real-IP       $remote_addr;
  proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
  client_max_body_size    10m;
  client_body_buffer_size 128k;
  proxy_connect_timeout   90;
  proxy_send_timeout      90;
  proxy_read_timeout      90;
  proxy_buffers           32 4k;
}
#4

[eluser]Unknown[/eluser]
A year late to the party, but I'd like to post my Nginx config as it differs from the ones above.

1) SneakyDave's config sends everything to Apache except for specific file extensions. I only wanted CI URIs going to Apache but didn't want to list all specific controllers.

2) Greg's example always adds a "?" to the query string. It breaks CI routing if you want to enable query string handling ($config['enable_query_strings']).

URLs are rewritten by Nginx from:

Code:
http://localhost/myapp/foo/bar?x=1&y=2

To this:

Code:
http://localhost/myapp/index.php?/foo/bar&x=1&y=2

And accordingly, the querystring goes from:

Code:
?x=1&y=2

To this:

Code:
?/foo/bar&x=1&y=2

Messing up CI.

<b>My Nginx configuration</b>

Nginx listens on port 80 and tries to process everything. Only PHP requests are sent to Apache. Apache listens on 8080 and is stripped down to only run mod_php5. All URL rewriting and security is handled by Nginx. My CI directory is under myapp/ so change that for your needs.

Code:
server {
        ... your regular stuff goes here ...

        # set proxy headers
        #
        proxy_set_header X-Forwarded-Host   $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_redirect off;

        # block .htaccess files
        #
        location ~ /\.ht {
                deny all;
        }

        # block .svn files
        #
        location ~ /\.svn {
                deny all;
        }

        # skip favicon.ico
        #
        location = /favicon.ico {
                access_log off;
                return 204;
        }

        # send *.php to Apache
        #
        location ~ \.php$ {
                proxy_pass http://127.0.0.1:8080;
        }

        # send CI index.php/ to Apache
        #
        location ~ /myapp/index.php/ {
                proxy_pass http://127.0.0.1:8080;
        }

        # allow static content (I put them all in /myapp/static)
        #
        location /myapp/static {
                expires max;
        }

        # block everything in the CI system folder
        #
        location /myapp/system {
                deny all;
        }

        # redirect all CI requests to /myapp/index.php/ (above)
        #
        location /myapp {
                rewrite ^/myapp/(.*)? /myapp/index.php/$1 last;
        }
}

Thanks!
#5

[eluser]SneakyDave[/eluser]
Thanks for the info...
Quote:Apache listens on 8080 and is stripped down to only run mod_php5.

I was doing that for a while, and decided finally to just move all my PHP to nginx/fastcgi, and so far, I don't have any complaints, but I do miss my .htaccess files, and eventually, I'm going to get stumped on a mod_rewrite that I can't seem to port to nginx.




Theme © iAndrew 2016 - Forum software by © MyBB