Full-stack Nginx reverse proxying and PHP index - php

I'm trying to setup a full-stack Nginx reverse proxying server (as title says, obviously), and I'm struggling a bit when it comes to code interpretation with PHP-FPM.
Here is the so called front-end part of the proxying process (which isn't used to directly serve files, but rather to redirect the client towards the back-end servers) :
server {
listen xxx.xxx.xxx.xxx:80;
server_name localhost;
# logs...
# Here begins the reverse-proxying
# Test 2nd backend server
location /test {
proxy_pass http://127.0.0.1:82/;
}
# default main site (has to be at the end since location checks file hierarchy)
location / {
proxy_pass http://127.0.0.1:81/;
}
And then, here are my two reversed server blocks.
The first one is the main site, which should be served by default by accessing domain.com :
server {
listen 127.0.0.1:81;
server_name main;
# logs...
root /var/www/main;
gzip on;
gzip_types "*";
expires 10m;
location / {
try_files $uri = 404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php-fpm.socket;
include /etc/nginx/fastcgi.conf;
}
}
And here is the second "test" one, which is should access when trying domain.com/test :
server {
listen 127.0.0.1:82;
server_name test;
root /var/www/test;
gzip on;
gzip_types "*";
expires 10m;
try_files $uri = 404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php-fpm.socket;
include /etc/nginx/fastcgi.conf;
}
}
Doing so using reverse proxying would allow me to actually only use one port, and the most important, it hides which and how much virtual servers are actually running here.
So, what's the problem ?
Well, it's more about HOW are PHP and indexes managed by nginx reverse proxying than about reverse proxying itself.
When I'm using index.html files in both :81 and :82 servers, it works fine, the index directive works perfectly, and the server returns /var/www/main/index.html when accessing domain.com, and /var/www/test/index.html when accessing domain.com/test.
However, the problem happens when I'm using index.php files. In this case, only using the URLs up there leaves me with a 404 error in both cases. I need to explicitely specify index.php in the URL, eg. domain.com/test/index.php to make it work, which I don't want to have to.
I haven't found any thread or documentation dealing with such a specific case, and that's why I'm coming here to ask if anyone has more informations on indexes behavior with PHP ?
Thanks by advance for your answer(s), and I'll gladly take anything you have at this point since I've been struggling for quite a long time with this problem.

You need to set this to load index.php files by default:
location / {
index index.php index.html index.htm;
// ...other configurations
}

Related

how can I let phalcon framework co-exists under existing legacy php project?

I run a php-based web site (shopping mall) on nginx web server.
recently I heard that phalcon is very fast and reliable framework, helping developer speed up the dev process.
So I wanted to implement it to my site, starting as a submodule for specific services for it's hard to start from the scratch.
I want to create a subfolder (let's say "phalcontest") under the /var/www .
I googled about this topic, but all(maybe?) the contents I found on the net were to set nginx server as a dedicated site for phalcon project (I mean, make "the project" folder as a web root), nothing about making phalcon project coexist with old non-phalcon pages.
I tried nginx configuration something like this, hoping it's ok:
server {
listen 80;
root /var/www/;
index index.html index.htm index.php;
server_name localhost;
access_log /var/log/nginx/access.log main buffer=16k;
error_log /var/log/nginx/error.log;
location #rewrite {
rewrite ^(.*)$ phalcontest/index.php?_url=$1;
}
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~ \.php$ {
try_files $uri = 404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
}
location /phalcontest {
try_files $uri $uri/ #rewrite;
}
location ~* ^/(css|img|js|flv|swf|download)/(.+)$ {
root /var/www/;
}
}
to make "phalcontest" folder to be a phalcon-enabled subfolder under webroot.
After that I created phalcontest with phalcon devtools,
and accessed http://localhost/phalcontest/public, it shows:
Congratulations!
You're now flying with Phalcon. Great things are about to happen!
This page is located at views/index/index.phtml
but when I accessed http://localhost/phalcontest, it shows:
Mod-Rewrite is not enabled
Please enable rewrite module on your web server to continue
this means that I've done something wrong and I can only access via public folders, not the folder itself.
Please help me how to let phalcon live with existing php-based site!
The way that Phalcon is supposed to work is that it rewrites all traffic aimed at your web root / to the /public/ directory. The point of this is that it enables you to essentially hide the /app/ directory from web view since the user's request would first be rewritten to /public/app/ thus encountering a 404 which gets rewritten to /public/index.php where it would look for the controller "App". If you're going to run Phalcon from a subdirectory, you'll need to change all / to /phalcontest/.
I see you're using root /var/www/;.
So in your case, you'll want a directory structure like so:
/www/phalcontest/public/index.php
/www/phalcontest/public/css/bootstrap.css
/www/phalcontest/public/js/jquery.js
/www/phalcontest/app/config/config.php
/www/phalcontest/app/controllers/IndexController.php
/www/phalcontest/app/models/
/www/phalcontest/app/views/index.phtml
/www/phalcontest/app/views/index/index.phtml
Make sure to rewrite all requests aimed at phalcontest(/.*)? to phalcontest/public/$1 then from there rewrite them to index.php if the requested file or directory doesn't exist.
Here's a tool for converting .htaccess to nginx if it's any help:
http://winginx.com/en/htaccess
Honestly, you don't need to follow their directory structure so perfectly. You only really need the rewrite logic to rewrite all traffic to your index.php file. The parts regarding Phalcon's proposed /public/ directory, you don't need a /public/ directory if you simply move your /app/ directory below the web root, then reference its location properly from your index.php file.
Phalcon gives you a lot of information regarding how to setup the rewriting for nginx over here:
https://docs.phalconphp.com/en/latest/reference/nginx.html
But since you're working from your localhost, I'd suggest creating a subdomain on the localhost using your hosts file. Then you can work from the / web root and access your project from http://phalcontest.localhost/. Then you'd use server_name phalcontest.localhost; in your nginx configuration rather than server_name localhost; and aim its root at root /var/www/phalcontest; For your hosts file you'd add a line: phalcontest.localhost 127.0.0.1. That will save you from a DNS look up so the subdomain gets tied to your localhost. See nginx subdomain configuration and How to test nginx subdomains on localhost.

Nginx with sub locations

I'm trying to setup a dev server with nginx for two projects, one in rails and one in PHP. I want a base URL (dev.example.com) for both projects and a sub location for each one (dev.example.com/rails_proj and dev.example.com/php_proj). My nginx conf is like the following:
server {
listen 80;
server_name dev.example.com;
passenger_enabled on;
passenger_app_env development;
passenger_buffer_response off;
root /var/www/dev;
location ~ ^/rails_proj {
root /public;
passenger_base_uri /rails_proj;
passenger_app_root /var/www/dev/rails_proj;
passenger_document_root /var/www/dev/rails_proj/public;
}
location ~ ^/php_proj {
root /web;
try_files $uri /app_dev.php$is_args$args;
location ~ \.php(/|$) {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
}
The rails project works fine but the PHP project gives me an "file not found" when I try to access dev.example.com/php_proj/app_dev.php and in the log It says: FastCGI sent in stderr: "Primary script unknown". I found issues related to It and I've tried a number of ways but I can't come up with something that works for both projects. How can I fix this?
It might be easier to manage as two server blocks with an extra subdomain for each. It also reduces potential confusion introduced by multiple regex locations:
server {
server_name rails.dev.example.com;
return 200 "Hello from rails app.
";
}
server {
server_name php.dev.example.com;
return 200 "Hello from php app.
";
}
I'm sure you've moved on or figured this out by now, but for posterity's sake: the root directive in your location block overrides your server root directive. It's not relative to it. The way you have your conf, the project files would need to be located in the absolute path /web/php_proj on your web server.
I can't quite determine the way your local paths are set up, but if /var/www/dev/rails_proj/public is the directory that contains your app root, you may instead need to do something like this:
location /rails_proj {
alias /var/www/dev/rails_proj/public;
}
Using alias instead of root will strip the /rails_proj from the beginning of the request path and serve files relative to the alias path. For example, if you request http://dev.example.com/rails_proj/php/test.php, it will serve the file /var/www/dev/rails_proj/public/php/test.php
Also, I would definitely recommend changing your top level location paths from regex to standard prefix paths.
location ~ ^/php_proj is effectively identical to location /php_proj except that using regex messes with the way nginx decides what location to serve. Regex paths are more performance intensive, act on a first-match basis rather than best match, and will take priority over all prefix path locations.
Another thing to note: using $document_root$fastcgi_script_name may not always work as expected. Especially if using the alias directive instead of root. Using the variable $request_filename instead is preferable in most cases.

nginx map accept header to subdirectory for api strange behaviour

I've been fiddling around with this for quite some time now, and I can't really get a grasp on how nginx+hhvm maps my requests.
Basiclly, I have an API on api.example.com that I would like to call with the Accept: application/vnd.com.example.api.v1+json for version 1 and application/vnd.com.example.api.v2+json for version 2. The API itself is a PHP application that I'll be running using a fresh install of HHVM. All requests will be handeled by index.php.
The folder structure looks like this:
api.example.com/
index.php (content: fail)
v1/
index.php (content: v1)
v2/
index.php (content: v2)
Whenever I use my REST client to access api.example.com/test with the v1 accept header I get the v1 response back. When I the use the accept header for v2, it shows the v2. So everything is correct. If I don't supply any accept header I get redirected to example.com
The NGINX configuration looks like this
map $http_accept $api_version {
default 0;
"application/vnd.com.example.api.v1+json" 1;
"application/vnd.com.example.api.v2+json" 2;
}
server {
# listen to :80 is already implied.
# root directory
root /var/www/api.example.com/;
index index.html;
server_name api.example.com;
include hhvm.conf;
location / {
if ($api_version = 0) {
# redirect to example.com if applicable
# Accept-header is missing
return 307 http://example.com;
}
try_files /v$api_version/$uri /v$api_version/$uri/ /v$api_version/index.php?$args;
}
# Prevent access to hidden files
location ~ /\. {
deny all;
}
}
the hhvm.conf file is included below. It is derivated or somewhat exact functionality of the default hhvm.conf included with hhvm.
location ~ \.(hh|php)$ {
fastcgi_keep_conn on;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
This is my problem
If I try to access api.example.com/index.php I get the "fail" response, even if I am expecting v1 for the v1 accept header and v2 for the v2 accept header. Everything else seems to work fine, even index.html maps correctly to it's subdirectory.
What I've tried
I've tried using
root /var/www/api.example.com/v$api_version/;
in the configuration, but that only gives me 404 errors from NGINX. I believe what I'm looking for is actually changing the root path, but I haven't got my head around how to make it work. I've also tried removing index parameters in both the nginx configuration and the hhvm.conf, but that does not seem to help. I've also tried a ton of different configurations and I've had at least 20-30 tabs of stackoverflow open to solve this, but I'm clearly missing something (probably rather simple) here. I've also tried moving the hhvm include inside the location block.
The setup
Debian 7,
nginx/1.2.1,
hhvm 3.2.0
Oh, and it's my first time actually asking a question here. :) hope I've formatted everything correctly.
What are the contents of hhvm.conf ?
I'm assuming Fast CGI is being used to proxy requests to the HHVM server. So your hhvm.conf might look something like this:
root /var/www/api.example.com;
index index.php;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
Which should be wrapped by a location directive.
So based on your config shown, what I think is happening is you must be matching php scripts to the HHVM location directive, which is fine, but in doing so your try_files setting, which seems to be in charge of doing the API version to file system mapping, is not being processed.
Without your hhvm.conf it's hard to say what to do next, but I suspect you need to focus on the root value inside the location directive that contains the HHVM fastcgi settings.
UPDATE
So I have the concept of an API version derived from the header mapping to a filesystem working for me on nginx + HHVM. Here is my nginx config for HHVM:
location / {
root /var/www/html/hh/v$api_version;
index index.php;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
Really though, the location of / is no better than your one - in fact, yours is probably better as you probably don't want HHVM serving static files etc. But this is working for me - combined with the map you have in your original post, when I curl -H 'Accept: application/vnd.com.example.api.v2+json' localhost, I get the expected response from an index.php file inside the version's directory.
I think what you need to do is update your HHVM nginx config with a dynamically generated root declaration like mine above. If you're still getting a 404, try this: in /etc/init.d/hhvm, find the ADDITIONAL_ARGS= var, make it ADDITIONAL_ARGS="-vServer.FixPathInfo=true". I'm not sure exactly what it does, but I've come across it before and it had fixed a weird 404 problem I was having in the past (where the 404 was coming from HHVM, not Apache/nginx).

Can I copy an entire Magento application to a new server?

I am quite new to Magento and I have a case where a client has a running ecommerce website built with Magento and is running on Amazon AWS EC2 server.
If I can locate the web root (/var/www/) and download everything from it (say via FTP), I should be able to boot up my virtual machine with LAMP installed, put every single files in there and it should run, right?
So I did just that, and Magento is giving me an error. I am guessing there are configs somewhere that needs to be changed in order to make it work, or even a lot of paths need to be changed etc. Also databases to be replicated. What are the typical things I should get right? Database is one, and the EC2 instance uses nginx while I use plain Apache, I guess that won't work straight out of the box, and I probably will have to install nginx and a lot of other stuffs.
But basically, if I setup the environment right, it should run. Is my assumption correct?
Thanks for answering!
There is just two or three config changes is enough to move magento another server.
For Database settings, modify app-->etc-->local.xml file
If you changed your URL you need to edit database in core_config_data table. In this change value for web/unsecure/base_url and web/secure/base_url to your current base url
For Apache server :
3. Some times you need to modify .htaccess file. Its located at root directory. Change your rewrite engine settings (if need) to your current root directory like this,
**RewriteBase /magento/**
For NGINX serevr :
If your web server is NGINX then, your config should be like this,
server {
root /home/magento/web/;
index index.php;
server_name magento.example.com;
location / {
index index.html index.php;
try_files $uri $uri/ #handler;
expires 30d;
}
location ~ ^/(app|includes|lib|media/downloadable|pkginfo|report/config.xml|var)/ { internal; }
location /var/export/ { internal; }
location /. { return 404; }
location #handler { rewrite / /index.php; }
location ~* .php/ { rewrite ^(.*.php)/ $1 last; }
location ~* .php$ {
if (!-e $request_filename) { rewrite / /index.php last; }
expires off;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param MAGE_RUN_CODE default;
fastcgi_param MAGE_RUN_TYPE store;
include fastcgi_params;
}
}
For more information about this follow bellow links,
CLICK ME
Here's a detailed guide how to move Magento to a new server: http://www.magentocommerce.com/wiki/groups/227/moving_magento_to_another_server (I used it once and it worked perfectly)
Based on your text I assume you forgot to copy the database (it would be great if you can post the error message here). Only copying the files isn't enough, the database has to be copied to.
In the database you also have to adjust the server url. In the config file (app/etc/local.xml) you only have to update the database settings.
/edit: MySQLDumper is a tool to backup and restore MySQL-Databases with PHP. So you don't need phpMyAdmin (but you still need web access). Backup on the old server, restore on the new. The database settings can be found in app/etc/local.xml.

PHP and Rails for NginX configuration

I have both PHP and Rails running on the same server.
I used to have a rewrite rule at nginx.conf
location / {
index index.php;
}
and in case of URL like /foo/bar /foo/bar/index.php was served.
But now I have also Rails (Passenger) and with this rule I can't hit rails.
How do I check if there exist index.php before and hit rails only if it does not.
Thanks.
If I understood Your question, You will need to define another location block, that "hits" rails and use try_files in current one. Something like this.
index index.html index.php # better place this outside location block
upstream thin {
unix:/tmp/thin.0.socket; # this could be any other rails server socket
unix:/tmp/thin.1.socket;
}
location / {
try_files $uri #rails;
}
location #rails {
proxy_pass http://thin;
}
These would be essential parts for such configuration, of course it lacks proxy configuration.
a more detailed example for similar application
Should try_files
server {
try_files $uri $uri/ $uri/index.php #passenger;
location #passenger {
passenger_enabled on;
rails_env development;
}
}

Categories