Caching Symfony 2 on Nginx - symfony

I moved from the setup of Apache 2 + Varnish to Nginx alone, and I'm kinda stuck with how I should setup/use ESI as well as fastcgi_cache in this setup.
First of all, the idea of ESI was that we setup a reverse proxy layer in front of the server to cache the cache-able parts of a page, then using esi to retrieve the dynamic parts. In my previous setup Varnish was acting as the reverse proxy and Apache only handles the esi requests when necessary.
My question is that now with Nginx acting as the sole server here, how do I make it to work? Do I need to setup another Nginx instance running as a reverse proxy server or something? I couldn't find any document on this.
The second question is regarding fastcgi_cache. I have set it up as described below but the cache does't seem to work for me, no cache file populated and I always get "MISS". I wonder if it's because I need to set max-age/shared-max-age in each controller for each to work?
fastcgi_cache_path /run levels=1:2 keys_zone=www_mysite_com:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
server {
#listen 80; ## listen for ipv4; this line is default and implied
#listen [::]:80 default ipv6only=on; ## listen for ipv6
root /var/www/mysite.com/w/w/w/www/web;
index index.php index.html index.htm;
# Make site accessible from http://www.mysite.com
server_name www.mysite.com;
# Specify a character set
charset utf-8;
# strip app.php/ prefix if it is present
rewrite ^/app\.php/?(.*)$ /$1 permanent;
# h5bp nginx configs
# include conf/h5bp.conf;
location / {
index app.php;
try_files $uri #rewriteapp;
}
location #rewriteapp {
rewrite ^(.*)$ /app.php/$1 last;
}
# Deny access to .htaccess
location ~ /\.ht {
deny all;
}
# Don't log robots.txt or favicon.ico files
location = /favicon.ico { log_not_found off; access_log off; }
location = /robots.txt { access_log off; log_not_found off; }
# 404 errors handled by our application, for instance Symfony
error_page 404 /app.php;
# pass the PHP scripts to FastCGI server from upstream phpfcgi
location ~ ^/(app|app_dev|backend/app|backend/app_dev|config)\.php(/|$) {
fastcgi_split_path_info ^(.+\.php)(/.*)$;
# With php5-fpm:
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME web/$fastcgi_script_name;
fastcgi_param HTTPS off;
fastcgi_cache www_mysite_com;
fastcgi_cache_valid 200 60m;
}
# Only for nginx-naxsi : process denied requests
#location /RequestDenied {
# For example, return an error code
#return 418;
#}
# redirect server error pages to the static page /50x.html
#
#error_page 500 502 503 504 /50x.html;
}

By default, responses from the Symfony 2 application have a cache control header that disables caching:
Cache-Control: no-cache
If you would like nginx to cache pages you will have to change those headers.
You can find general information about caching in the documentation
The simplest solution is to use the SymfonyFrameworkExtraBundle (you already have it if you use the SF2 standard edition) and use annotations on your controllers and/or actions to specify the cache headers. You can find more info about this approach it the docs for the #Cache annotation.

Related

Nginx 1.4.6 throwing 503 errors

Nginx 1.4.6 throwing 503 errors
I have configured 2 websites (wordpress and laravel v4) on digitalocean droplet - nginx/1.4.6 (Ubuntu).
Both of the websites normally works very good and quick.
But at the time of any data save in laravel website, it throws 503 error.
and in wordpress it does not thorough 503 error, but takes too long time to response near about 1-3min at the time of saving any post or any data.
Both sites virtual host configuration is same as below.
server {
listen 80;
listen 443 ssl;
root /var/www/domain1.com/public_html;
index index.php index.html index.htm;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
# Make site accessible from http://localhost/
server_name domain1.com www.domain1.com;
access_log off;
#GZIP Configuration
gzip on;
gzip_min_length 100;
gzip_comp_level 3;
gzip_types text/plain;
gzip_types text/css;
gzip_types text/javascript;
gzip_disable "msie6";
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
if ($host !~* ^www\.)
{
rewrite ^/(.*)$ http://www.$host/$1 permanent;
}
proxy_read_timeout 300;
}
error_page 404 /error.html;
location ^~ /error.html {
rewrite ^/.* http://www.domain1.com permanent;
}
location ~* \.(css|js|jpg|png|gif)$ {
access_log off;
expires 1M;
add_header Pragma public;
add_header Cache-Control public;
add_header Vary Accept-Encoding;
}
try_files $uri $uri/ #rewrite;
location #rewrite {
rewrite ^/(.*)$ /index.php?_url=/$1;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_read_timeout 600s;
#fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
I have also checked error logs and there's nothing critical has been found.
Please guide me, why Laravel v4 website is showing 503 errors, and why wordpress site is slow at the time of saving data.
The 503 means that the service is unresponsive. I guess you are getting timeouts due to laraval using too much of your resources i.e memory, possibly maxing out on your droplet.
From your config I can seen that you had a php-fpm socket but decided to use the php via port 9000.
#fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_pass 127.0.0.1:9000;
I would recommend configuring php-fpm with 2 different pools, one for wordpress and another for laravel and then have them setup to listen to different sockets with different setting per pool i.e. wordpress can have php_value[memory_limit] = 128M and laravel php_value[memory_limit] = 64M. Although this is just an idea, as there is plenty of setting you can have per pool.
Additionally your config has got very generous timeouts setup:
proxy_read_timeout 300
fastcgi_read_timeout 600s
It's very unusual to wait 5 or 10 minutes for response.
The best way in my opinion will be to:
Go with php-fpm and different socket -> custom settings per site
Install the NewRelic it's free for the basic level, this will
let you see what is going on with your server. i.e. memory usage, how
long it takes to execute a request etc. Hopefully it will help you
find an issue with your code i.e. why it takes so long for you
laravel to save data.
Change the timeouts i.e. lower it down 5 and 10 minutes is crazy.
Possibly upgrade your droplet, depending on your findings.
This is good website with instructions on how to tweak php-fpm and nginx.

How does one host a Kohana installation from a subdirectory on Nginx?

I am attempting to host a Kohana installation on Nginx. The difference is that I am trying to serve it up from a subdirectory as opposed to the web root itself.
The problem:
When trying to access the url, http://myproject.tld/Project/Welcome, I am given the error message: No input file specified.
Upon investigation, I noticed that this is in fact being rewritten as http://myproject.tld/index.php/Project/Welcome/ when it should be http://myproject.tld/Project/index.php/Welcome/
as seen here:
2014/01/02 23:10:57 [debug] 20952#0: *30 http copy filter: 0 "index.php/Project/Welcome?"
2014/01/02 23:10:57 [debug] 20952#0: *30 http finalize request: 0, "index.php/Project/Welcome?" a:1, c:1
Now, I understand fully why it is happening. Because I am hosting from a subdirectory that will exist within the request_uri and is appended to the url rewrite. If I were serving from the document root this wouldn't be an issue. What I'm hoping is someone can point me in the correct direction for solving this particular hiccup.
Setup Information:
nginx/1.4.4
Kohana 3.3.1
Server configuration:
server {
listen 80;
server_name mydomain.tld;
access_log /home/<user>/logs/mydomain-access.log;
error_log /home/<user>/logs/mydomain-error.log debug;
# main root
root /home/<user>/domains/mydomain.tld;
index index.php index.html;
location / {
expires off;
try_files $uri $uri/;
}
# Prevent access to hidden files
location ~ /\. {
deny all;
}
location /Project/ {
rewrite ^(.+)$ index.php$request_uri last;
}
location ~* \.php {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param KOHANA_ENV development;
fastcgi_cache off;
fastcgi_index index.php;
}
}
To get http://myproject.tld/Project/index.php/Welcome/ rewriting you should configure Kohana in /application/bootstrap.php - base_url to /Project/ in Kohana::init() block.

My nginx + fastcgi configuration downloads php files instead of executing them

I'm using this configuration on a fresh install of php5-fpm and nginx on ubuntu 13.04:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /usr/share/nginx/html;
index index.php index.html index.htm;
server_name localhost;
location / {
try_files $uri $uri/ /index.html;
}
location /doc/ {
alias /usr/share/doc/;
autoindex on;
allow 127.0.0.1;
allow ::1;
deny all;
}
error_page 404 /404.html;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
# With php5-cgi alone:
fastcgi_pass 127.0.0.1:9000;
# With php5-fpm:
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
But, my web browser is seeing php as text instead of the executed results. Where should I look to troubleshoot?
Your php code is being displayed directly because it's not being sent to the php engine, that means the location block is being matched and the php file is being served, but the php file isn't being captured by the php block, so your problem is in the php block.
In that block you have 2 fastcgi_pass, one with a port (9000) and the other to a unix socket, you can't have both together, but since you've tagged your question with fastcgi so I'll assume you are using fastcgi, try commenting this line
#fastcgi_pass unix:/var/run/php5-fpm.sock;
It sounds like you are getting the wrong Content-Type header set. You can check this with various tools. For example, open the Developer Tools "Network" tab in Chrome, and then request the page. You'll see the "Content Type" returned in one of the columns, and you can click on the request in the left column to see the full Response headers. I suspect you'll find the header being returned is either "text/plain" or "application/octet-stream" instead of text/html, which is probably want you want.
Nginx usually sets a default Content-Type header based on the extension. This is done with the types directive, which I don't see mentioned above, so you may wish to check your settings there to confirm that the php extension is mapped to text/html. Explicitly setting a Content-Typeheader in your application may also help.
I was able to fix this by updating my nginx vhost by changing
default_type application/octet-stream;
to
default_type text/html;

Nginx forward www and non-www requests to one directory?

I have a MediaTemple server from which I serve many websites. I use nginx and have the follow config file. I am correctly forwarding all non-www traffic (ie, http://example.com) to the appropriate directory. However, all the www traffic is returning 404 because my config file is looking for /directory-structure/www.sitename.com instead of /directory-structure/sitename.com
How can I have both www and non-www requests go to one directory? Thanks.
server {
listen 80;
server_name _;
root /var/www/vhosts/$host/httpdocs/;
error_page 404 /;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
#fastcgi_pass php;
fastcgi_pass 127.0.0.1:9000;
}
location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
expires max;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
# this prevents hidden files (beginning with a period) from being served
location ~ /\. { access_log off; log_not_found off; deny all; }
}
Starting with version 0.7.40 Nginx accepts regular expressions in server_name and captures. Thus it's possible to extract a domain name (without www) and use this variable in root directive:
server_name ~^(?:www\.)?(.+)$ ;
root /var/www/vhosts/$1/httpdocs;
Starting with 0.8.25 it is possible to use named captures:
server_name ~^(?:www\.)?(?P<domain>.+)$ ;
root /var/www/vhosts/$domain/httpdocs;
Another syntax to define named captures is (?<domain>.+) (PCRE version 7.0 and later). More on PCRE versions here
Try this and add the following in the above server config:
if ($host = "www.example.com") {
rewrite (.*) http://example.org$1;
}
What happens here, we are instructin nginx to serve the pages as http://example.com even though the browser URL reads http://www.example.com - I hope this works.
UPDATE
Try this for a generic version:
if ($host ~* "www.(.*)") {
rewrite ^ http://$1$request_uri?;
}
Given the potential issues with if as linked to in RakeshS's answer's comments, as well as the fact that RakashS's answer didn't work for me anyway, here's a solution that should be safer and worked for me with Nginx 1.0.14.
Add an additional server entry for each one of your server sections that does a rewrite:
server {
server_name www.yourwebsite.com;
rewrite ^ $scheme://yourwebsite.com$request_uri permanent;
}

nginx rewrite mystery - duplicating hostname and losing https

I am replacing lighttpd with nginx on my development server. I got it working with PHP and SSL, but I'm stumped by what should be a simple rewrite. I need to rewrite URLs from
http[s]://dev.foo.com/signup/123456
to
http[s]://dev.foo.com/signup/index.php?attcode=123456
The rule I am using is:
rewrite ^/signup/([0-9]+)$ /signup/index.php?attycode=$1 last;
I have tried numerous variations on this, moved it around, put it inside a location block. What happens is the URL is rewritten to:
http://dev.foo.com/dev.foo.com/signup/123456
The hostname is inserted, and it seems to always lose https and go to http.
My nginx.com server section is below. I have read and re-read the nginx docs (as they are) and searched the nginx mailing list, but nothing I've tried has solved this problem.
Ubuntu 8.0.4 LTS in case that matters.
Thanks.
server {
listen 80;
listen 443 default ssl;
server_name dev.foo.com dev.bar.com localhost;
root /var/www/foo;
index index.php index.html;
# ssl cert stuff omitted
charset utf-8;
access_log /var/log/www/dev.access.log main;
location ~ /\. {
deny all;
}
location ~* ^.+\.(inc|tpl|sql|ini|bak|sh|cgi)$ {
deny all;
}
location ~* ^/(scripts|tmp|sql)/ {
deny all;
}
rewrite ^/robots.txt$ /robots_nocrawl.txt break;
rewrite ^/signup/([0-9]+)$ /signup/index.php?attycode=$1 last;
location / {
try_files $uri $uri/ /error_404.php;
}
location ~ \.php$ {
fastcgi_pass localhost:51115;
fastcgi_index index.php;
fastcgi_intercept_errors on;
include fastcgi_params;
fastcgi_param SERVER_NAME $http_host;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
error_page 404 /error_404.php;
}
Don't put HTTP and HTTPS in the same server block. Separate them into two almost-identical server blocks, one for HTTP and one for HTTPS. Otherwise you will confuse all kinds of Nginx internals.

Resources