Nginx i Varnish – konfiguracja pod magento
Nginx, Varnish – obecnie to najczęściej spotykana para programów znacznie przyspieszającą prace magento.
W tym artykule opiszę konfigurację jaką najczęściej stosujemy w firmie smartmage.pl.
Oczywiście programy muszą być zainstalowane w systmie. Do zainstalowania Nginxa można użyć poleceń:
apt-get install nginx
Do zainstalowania Varnisha musimy dodać dodatkowe repozytoria:
curl http://repo.varnish-cache.org/debian/GPG-key.txt | apt-key add - echo "deb http://repo.varnish-cache.org/debian/ wheezy varnish-3.0" >> /etc/apt/sources.list apt-get update apt-get install varnish
Konfiguracja programów: Varnish na porcie 80, Nginx na porcie 8080.
Konfiguracja nginxa na porcie 8080:
Plik nginx.conf:
user www-data;
worker_processes 4; # Liczbę ustawiamy taką samą jak liczba procesorów
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
##
# Zabezpieczenie przed atakami DDOS
##
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
client_max_body_size 20m;
client_body_buffer_size 128k;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# Logging Settings / Zmiana logowania ip. W standardowej konfiguracje bedzie tylko logowania ip z Varnisha
##
log_format varnish_log '$http_x_forwarded_for - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent "$http_referer" ' '"$http_user_agent"' ;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
gzip_min_length 1100;
gzip_buffers 4 32k;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 9;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript applicacion/x-font-ttf;
##
# nginx-naxsi config
##
# Uncomment it if you installed nginx-naxsi
##
#include /etc/nginx/naxsi_core.rules;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Przykladowy plik vhosta:
server {
listen 10.0.0.10:8080; # Przykładowy ip
server_name www.domena.pl; ## Domain is here twice so server_name_in_redirect will favour the www
root /var/www/domena/web;
location / {
index index.php index.html; ## Allow a static html file to be shown first
try_files $uri $uri/ @handler; ## If missing pass the URI to Magento's front handler
expires 30d; ## Assume all files are cachable
}
## These locations downloadable would be hidden by .htaccess normally
location ^~ /app/ { deny all; }
location ^~ /includes/ { deny all; }
location ^~ /lib/ { deny all; }
location ^~ /media/downloadable/ { deny all; }
location ^~ /pkginfo/ { deny all; }
location ^~ /report/config.xml { deny all; }
location ^~ /var/ { deny all; }
location /var/export/ { ## Allow admins only to view export folder
auth_basic "Restricted"; ## Message shown in login window
auth_basic_user_file htpasswd; ## See /etc/nginx/htpassword
autoindex on;
}
location /. { ## Disable .htaccess and other hidden files
return 404;
}
location @handler { ## Magento uses a common front handler
rewrite / /index.php;
}
location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
rewrite ^(.*.php)/ $1 last;
}
location ~ .php$ { ## Execute PHP scripts
if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss
expires off; ## Do not cache dynamic content
fastcgi_read_timeout 1200s;
fastcgi_send_timeout 1200s;
fastcgi_connect_timeout 1200s;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param MAGE_RUN_CODE default; ## Store code is defined in administration > Configuration > Manage Stores
fastcgi_param MAGE_RUN_TYPE store;
fastcgi_param PHP_ADMIN_VALUE sendmail_path = /usr/sbin/sendmail -t -i -fadres@email.pl;
include fastcgi_params; ## See /etc/nginx/fastcgi_params
# Ograniczenie polaczen DDOS
limit_req zone=req_limit_per_ip burst=10 nodelay;
limit_conn conn_limit_per_ip 10;
}
access_log /var/log/nginx/access-domena.pl.log varnish_log;
error_log /var/log/nginx/error-domena.pl.log;
}
Konfiguracja Varnisha na porcie 80:
Konfiguracja pliku varnish w katalogu /etc/default:
START=yes # Maximum number of open files (for ulimit -n) NFILES=131072 # Maximum locked memory size (for ulimit -l) # Used for locking the shared memory log in memory. If you increase log size, # you need to increase this number as well MEMLOCK=82000 DAEMON_OPTS="-a 10.0.0.10:80 \ -T localhost:6082 \ -f /etc/varnish/default.vcl \ -S /etc/varnish/secret \ -s malloc,1024m;
Konfiguracja pliku default.vcl w katalogu /etc/varnish:
# default backend definition. Set this to point to your content server.
backend default {
.host = 10.0.0.10;
.port = 8080;
}
# admin backend with longer timeout values. Set this to the same IP & port as your default server.
backend admin {
.host = 10.0.0.10;
.port = 8080;
.first_byte_timeout = 18000s;
.between_bytes_timeout = 18000s;
}
# add your Magento server IP to allow purges from the backend
acl purge {
10.0.0.10;
localhost;
127.0.0.1;
}
import std;
sub vcl_recv {
if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For =
req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
if (req.request != "GET" &&
req.request != "HEAD" &&
req.request != "PUT" &&
req.request != "POST" &&
req.request != "TRACE" &&
req.request != "OPTIONS" &&
req.request != "DELETE" &&
req.request != "PURGE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
# purge request
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
ban("obj.http.X-Purge-Host ~ " + req.http.X-Purge-Host + " && obj.http.X-Purge-URL ~ " + req.http.X-Purge-Regex + " && obj.http.Content-Type ~ " + req.http.X-Purge-Content-Type);
error 200 "Purged.";
}
# switch to admin backend configuration
if (req.http.cookie ~ "adminhtml=") {
set req.backend = admin;
}
# we only deal with GET and HEAD by default
if (req.request != "GET" && req.request != "HEAD") {
return (pass);
}
# normalize url in case of leading HTTP scheme and domain
set req.url = regsub(req.url, "^http[s]?://[^/]+", "");
# collect all cookies
std.collect(req.http.Cookie);
# static files are always cacheable. remove SSL flag and cookie
if (req.url ~ "^/(media|js|skin)/.*\.(png|jpg|jpeg|gif|css|js|swf|ico)$") {
unset req.http.Https;
unset req.http.Cookie;
}
# not cacheable by default
if (req.http.Authorization || req.http.Https) {
return (pass);
}
# do not cache any page from index files
if (req.url ~ "^/(index)") {
return (pass);
}
# as soon as we have a NO_CACHE cookie pass request
if (req.http.cookie ~ "NO_CACHE=") {
return (pass);
}
# remove Google gclid parameters
set req.url = regsuball(req.url,"\?gclid=[^&]+$",""); # strips when QS = "?gclid=AAA"
set req.url = regsuball(req.url,"\?gclid=[^&]+&","?"); # strips when QS = "?gclid=AAA&foo=bar"
set req.url = regsuball(req.url,"&gclid=[^&]+",""); # strips when QS = "?foo=bar&gclid=AAA" or QS = "?foo=bar&gclid=AAA&bar=baz"
return (lookup);
}
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
if (req.http.cookie ~ "PAGECACHE_ENV=") {
set req.http.pageCacheEnv = regsub(
req.http.cookie,
"(.*)PAGECACHE_ENV=([^;]*)(.*)",
"\2"
);
hash_data(req.http.pageCacheEnv);
remove req.http.pageCacheEnv;
}
if (!(req.url ~ "^/(media|js|skin)/.*\.(png|jpg|jpeg|gif|css|js|swf|ico)$")) {
call design_exception;
}
return (hash);
}
sub vcl_fetch {
if (beresp.status == 500) {
set beresp.saintmode = 10s;
return (restart);
}
set beresp.grace = 5m;
# enable ESI feature if needed
if (beresp.http.X-Cache-DoEsi == "1") {
set beresp.do_esi = true;
}
# add ban-lurker tags to object
set beresp.http.X-Purge-URL = req.url;
set beresp.http.X-Purge-Host = req.http.host;
if (beresp.status == 200 || beresp.status == 301 || beresp.status == 404) {
if (beresp.http.Content-Type ~ "text/html" || beresp.http.Content-Type ~ "text/xml") {
if ((beresp.http.Set-Cookie ~ "NO_CACHE=") || (beresp.ttl < 1s)) { set beresp.ttl = 0s; return (hit_for_pass); } # marker for vcl_deliver to reset Age: set beresp.http.magicmarker = "1"; # Don't cache cookies unset beresp.http.set-cookie; } else { # set default TTL value for static content set beresp.ttl = 4h; } return (deliver); } return (hit_for_pass); } sub vcl_deliver { # debug info if (resp.http.X-Cache-Debug) { if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
set resp.http.X-Cache-Hits = obj.hits;
} else {
set resp.http.X-Cache = "MISS";
}
set resp.http.X-Cache-Expires = resp.http.Expires;
} else {
#remove Varnish/proxy header
remove resp.http.X-Powered-By;
remove resp.http.X-Varnish;
remove resp.http.Via;
remove resp.http.Age;
remove resp.http.X-Purge-URL;
remove resp.http.X-Purge-Host;
}
if (resp.http.magicmarker) {
# Remove the magic marker
unset resp.http.magicmarker;
set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, post-check=0, pre-check=0";
set resp.http.Pragma = "no-cache";
set resp.http.Expires = "Mon, 31 Mar 2008 10:00:00 GMT";
set resp.http.Age = "0";
}
}
Na koniec restartujemy Nginx-a oraz Varnish-a. System jest gotowy do pracy.