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.