Nginx - Php-Fpm - Apc - Varnish E Ottimizzazione Wordpress Su Debian 6

Nginx - Php-Fpm - Apc - Varnish E Ottimizzazione Wordpress Su Debian 6

Ecco una “semplice” guida per poter installare nginx , php-fpm , apc e varnish sul nostro server debian 6 e come ottimizzare al meglio un’installazione di wordpress.

Per prima cosa dobbiamo avere un’installazione pulita di debian e aggiungere la seguente repo

vim /etc/apt/sources.list  
deb http://packages.dotdeb.org stable all  

Adesso scarichiamo la .key della repo e aggiorniamo la nostra repository

wget http://www.dotdeb.org/dotdeb.gpg  
cat dotdeb.gpg | sudo apt-key add -  
rm dotdeb.gpg  
apt-get update  

Adesso installiamo i seguenti pacchetti

apt-get install nginx varnish php5 php5-fpm php-pear php5-common php5-mcrypt php5-mysql php5-cli php5-gd mysql-server php5-apc  

Andiamo ora a modificare per prima cosa il nostro file .conf di nginx in /etc/nginx/nginx.conf

user www-data;  
worker_processes 2;  
pid /var/run/nginx.pid;

events {  
    worker_connections 768;
    multi_accept on;
    use epoll;
}

http {

    # Let NGINX get the real client IP for its access logs
    set_real_ip_from 127.0.0.1;
    real_ip_header X-Forwarded-For;

    # Basic Settings
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 20;
    client_max_body_size 15m;
    client_body_timeout 60;
    client_header_timeout 60;
    client_body_buffer_size  1K;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;
    send_timeout 60;
    reset_timedout_connection on;
    types_hash_max_size 2048;
    server_tokens off;

    # server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Logging Settings
    # access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    # Log Format
    log_format main '$remote_addr - $remote_user [$time_local] '
    '"$request" $status $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for"';

    # Gzip Settings
    gzip on;
    gzip_static on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_min_length 512;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/css text/javascript text/xml text/plain text/x-component
    application/javascript application/x-javascript application/json
    application/xml  application/rss+xml font/truetype application/x-font-ttf
    font/opentype application/vnd.ms-fontobject image/svg+xml;

    # Virtual Host Configs
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

In caso abbiamo un tipo di MIME diverso o un font installato da dover passare lato client tramite nginx dovremo modificare /etc/nginx/mime.types

application/vnd.ms-fontobject           eot;  
    application/x-font-ttf                  ttf;
    font/opentype                           ott;
    application/font-woff                   woff;

Prima di continuare eliminiamo il link simbolico nella cartella sites-enabled di nginx del file default

rm /etc/nginx/sites-enabled/default  

Adesso andiamo nella cartella sites-available di nginx e creiamo il nostro dominio standard (che sarà ottimizzato per wordpress) [sotto è presente un file default per un normale sito web]

server {  
    # Configure the domain that will run WordPress
    server_name dominio.com;
    listen [::]:8080;
    port_in_redirect off;
    server_tokens off;
    autoindex off;

    client_max_body_size 15m;
    client_body_buffer_size 128k;

    # WordPress needs to be in the webroot of /var/www/ in this case
    root /var/www/;
    index index.html index.htm index.php;
    try_files $uri $uri/ /index.php?q=$uri&

    # Define default caching of 24h
    expires 86400s;
    add_header Pragma public;
    add_header Cache-Control "max-age=86400, public, must-revalidate, proxy-revalidate";

    # deliver a static 404
    error_page 404 /404.html;
    location  /404.html {
        internal;
    }

    # Deliver 404 instead of 403 "Forbidden"
    error_page 403 = 404;

    # Do not allow access to files giving away your WordPress version
    location ~ /(.|wp-config.php|readme.html|licence.txt) {
        return 404;
    }

    # Add trailing slash to */wp-admin requests.
    rewrite /wp-admin$ $scheme://$host$uri/ permanent;

    # Don't log robots.txt requests
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    # Rewrite for versioned CSS+JS via filemtime
    location ~* ^.+.(css|js)$ {
        rewrite ^(.+).(d+).(css|js)$ $1.$3 last;
        expires 31536000s;
        access_log off;
        log_not_found off;
        add_header Pragma public;
        add_header Cache-Control "max-age=31536000, public";
    }

    # Aggressive caching for static files
    # If you alter static files often, please use
    # add_header Cache-Control "max-age=31536000, public, must-revalidate, proxy-revalidate";
location ~* .(asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|ogv|otf|pdf|png|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|t?gz|tif|tiff|ttf|wav|webm|wma|woff|wri|xla|xls|xlsx|xlt|xlw|zip)$ {  
        expires 31536000s;
        access_log off;
        log_not_found off;
        add_header Pragma public;
        add_header Cache-Control "max-age=31536000, public";
    }

    # pass PHP scripts to Fastcgi listening on Unix socket
    # Do not process them if inside WP uploads directory
    # If using Multisite or a custom uploads directory,
    # please set the */uploads/* directory in the regex below
    location ~* (^(?!(?:(?!(php|inc)).)*/uploads/).*?(php)) {
        try_files $uri = 404;
        fastcgi_split_path_info ^(.+.php)(.*)$;
        fastcgi_pass unix:/var/run/php-fpm.socket;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_intercept_errors on;
        fastcgi_ignore_client_abort off;
        fastcgi_connect_timeout 60;
        fastcgi_send_timeout 180;
        fastcgi_read_timeout 180;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
    }

    # Deny access to hidden files
    location ~ /. {
        deny all;
        access_log off;
        log_not_found off;
    }

}

# Redirect all www. queries to non-www
# Change in case your site is to be available at "www.yourdomain.tld"
server {  
    listen [::]:8080;
    server_name www.dominio.com;
    rewrite ^ $scheme://dominio.com$request_uri? permanent;
}

Altro esempio di file di configurazione ottimizzato per wordpress e W3 Total Cache

server {  
# Redirect yoursite.com to www.yoursite.com
server_name yoursite.com;  
rewrite ^(.*) http://www.yoursite.com$1 permanent;  
}

server {

# Tell nginx to handle requests for the www.yoursite.com domain
server_name www.yoursite.com;  
index index.php index.html index.htm;  
root /srv/www/yoursite.com/public;  
access_log /srv/www/yoursite.com/logs/access.log;  
error_log /srv/www/yoursite.com/logs/error.log;

# Use gzip compression
# gzip_static on; # Uncomment if you compiled Nginx using --with-http_gzip_static_module
gzip on;  
gzip_disable "msie6";  
gzip_vary on;  
gzip_proxied any;  
gzip_comp_level 5;  
gzip_buffers 16 8k;  
gzip_http_version 1.0;  
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript image/png image/gif image/jpeg;  
# Rewrite minified CSS and JS files
location ~* .(css|js) {  
if (!-f $request_filename) {  
rewrite ^/wp-content/w3tc/min/(.+.(css|js))$ /wp-content/w3tc/min/index.php?file=$1 last;  
# Use the following line instead for versions of W3TC pre-0.9.2.2
# rewrite ^/wp-content/w3tc/min/([a-f0-9]+)/(.+).(include(-(footer|body))?(-nb)?).[0-9]+.(css|js)$ /wp-content/w3tc/min/index.php?tt=$1&gg=$2&g=$3&t=$7 last;
}
}
# Set a variable to work around the lack of nested conditionals
set $cache_uri $request_uri;  
# POST requests and urls with a query string should always go to PHP
if ($request_method = POST) {  
set $cache_uri 'no cache';  
}
if ($query_string != "") {  
set $cache_uri 'no cache';  
}
# Don't cache uris containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php)") {  
set $cache_uri "no cache";  
}
# Don't use the cache for logged in users or recent commenters
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in") {  
set $cache_uri 'no cache';  
}
# Use cached or actual file if they exists, otherwise pass request to WordPress
location / {  
try_files /wp-content/w3tc/pgcache/$cache_uri/_index.html $uri $uri/ /index.php?q=$uri&$args;  
}

# Cache static files for as long as possible
location ~* .(xml|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {  
try_files $uri =404;  
expires max;  
access_log off;  
}
# Deny access to hidden files
location ~* /.ht {  
deny all;  
access_log off;  
log_not_found off;  
}
# Pass PHP scripts on to PHP-FPM
location ~* .php$ {  
try_files $uri /index.php;  
fastcgi_index index.php;  
fastcgi_pass 127.0.0.1:9000;  
include fastcgi_params;  
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;  
fastcgi_param SCRIPT_NAME $fastcgi_script_name;  
}

}

In caso di un sito normale usare il seguente file di configurazione

server {  
    # Configure the domain
    server_name dominio.com;
    listen [::]:8080;
    port_in_redirect off;
    server_tokens off;
    autoindex off;

    client_max_body_size 15m;
    client_body_buffer_size 128k;

    root /var/www/dominio.com/;
    index index.html index.htm index.php;
    try_files $uri $uri/ /index.php?q=$uri&

    # Define default caching of 24h
    expires 86400s;
    add_header Pragma public;
    add_header Cache-Control "max-age=86400, public, must-revalidate, proxy-revalidate";

    # deliver a static 404
    error_page 404 /404.html;
    location  /404.html {
        internal;
    }

    # pass PHP scripts to Fastcgi

    location ~ .*.(php)$ {
        try_files $uri = 404;
        fastcgi_split_path_info ^(.+.php)(.*)$;
        fastcgi_pass unix:/var/run/php-fpm.socket;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_intercept_errors on;
        fastcgi_ignore_client_abort off;
        fastcgi_connect_timeout 60;
        fastcgi_send_timeout 180;
        fastcgi_read_timeout 180;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
    }

    # Deny access to hidden files
    location ~ /. {
        deny all;
        access_log off;
        log_not_found off;
    }

}

# Redirect all www. queries to non-www
# Change in case your site is to be available at "www.yourdomain.tld"
server {  
    listen [::]:8080;
    server_name www.dominio.com;
    rewrite ^ $scheme://dominio.com$request_uri? permanent;
}

Ora andremo a modificare le impostazioni di php-fpm in /etc/php5/fpm/php.ini ma dato che il file è enorme riporterò solo le modifiche

short_open_tag = Off  
ignore_user_abort = Off  
post_max_size = 15M  
upload_max_filesize = 15M  
default_charset = "UTF-8"  
allow_url_fopen = Off  
default_socket_timeout = 30  
mysql.allow_persistent = Off  

Alla fine del file aggiungere

[apc]
apc.stat = "0"  
apc.max_file_size = "1M"  
apc.localcache = "1"  
apc.localcache.size = "256"  
apc.shm_segments = "1"  
apc.ttl = "3600"  
apc.user_ttl = "7200"  
apc.gc_ttl = "3600"  
apc.cache_by_default = "1"  
apc.filters = ""  
apc.write_lock = "1"  
apc.num_files_hint= "512"  
apc.user_entries_hint="4096"  
apc.shm_size = "256M"  
apc.mmap_file_mask=/tmp/apc.XXXXXX  
apc.include_once_override = "0"  
apc.file_update_protection="2"  
apc.canonicalize = "1"  
apc.report_autofilter="0"  
apc.stat_ctime="0"  
;This should be used when you are finished with PHP file changes.
;As you must clear the APC cache to recompile already cached files.
;If you are still developing, set this to 1.
apc.stat="0"  

Ora andremo a moficare il file /etc/php5/fpm/php-fpm.conf

pid = /var/run/php5-fpm.pid  
error_log = /var/log/php5-fpm.log  
emergency_restart_threshold = 5  
emergency_restart_interval = 2  
events.mechanism = epoll  

E in questo file /etc/php5/fpm/pool.d/www.conf andremo a modificare

user = www-data  
group = www-data  
listen = /var/run/php-fpm.socket  
listen.owner = www-data  
listen.group = www-data  
listen.mode = 0666  
listen.allowed_clients = 127.0.0.1  
pm = dynamic  
pm.max_children = 50  
pm.start_servers = 15  
pm.min_spare_servers = 5  
pm.max_spare_servers = 25  
pm.process_idle_timeout = 60s  
request_terminate_timeout = 30  
security.limit_extensions = .php  

E alla fine del file aggiungiamo

php_flag[display_errors] = off  
php_admin_value[error_reporting] = 0  
php_admin_value[error_log] = /var/log/php5-fpm.log  
php_admin_flag[log_errors] = on  
php_admin_value[memory_limit] = 128M  

Ora andiamo a modificare i file di configurazione di varnish in /etc/default/varnish (ricordiamo di cercare la linea [all'inizio] che recita di riavviare varnish al reboot modificando da no a yes la linea) andando a modificare

DAEMON_OPTS="-a :80  
    -T localhost:6082
    -f /etc/varnish/default.vcl
    -u www-data -g www-data
    -S /etc/varnish/secret
    -p thread_pools=2
    -p thread_pool_min=25
    -p thread_pool_max=250
    -p thread_pool_add_delay=2
    -p session_linger=50
    -p sess_workspace=262144
    -p cli_timeout=40
    -s malloc,768m"

Aggiungiamo il seguente file /etc/varnish/default (il file è ottimizzato per wordpress ma potrete commentare le parti non interessate

# We only have one backend to define: NGINX
backend default {  
    .host = "127.0.0.1";
    .port = "8080";
}

# Only allow purging from specific IPs
acl purge {  
    "localhost";
    "127.0.0.1";
}

sub vcl_recv {  
    # Handle compression correctly. Different browsers send different
    # "Accept-Encoding" headers, even though they mostly support the same
    # compression mechanisms. By consolidating compression headers into
    # a consistent format, we reduce the cache size and get more hits.
    # @see: http:// varnish.projects.linpro.no/wiki/FAQ/Compression
    if (req.http.Accept-Encoding) {
        if (req.http.Accept-Encoding ~ "gzip") {
            # If the browser supports it, we'll use gzip.
            set req.http.Accept-Encoding = "gzip";
        }
        else if (req.http.Accept-Encoding ~ "deflate") {
            # Next, try deflate if it is supported.
            set req.http.Accept-Encoding = "deflate";
        }
        else {
            # Unknown algorithm. Remove it and send unencoded.
            unset req.http.Accept-Encoding;
        }
    }

    # Set client IP
    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;
    }

    # Check if we may purge (only localhost)
    if (req.request == "PURGE") {
        if (!client.ip ~ purge) {
            error 405 "Not allowed.";
        }
        return(lookup);
    }

    if (req.request != "GET" &&
        req.request != "HEAD" &&
        req.request != "PUT" &&
        req.request != "POST" &&
        req.request != "TRACE" &&
        req.request != "OPTIONS" &&
        req.request != "DELETE") {
            # /* Non-RFC2616 or CONNECT which is weird. */
            return (pipe);
    }

    if (req.request != "GET" && req.request != "HEAD") {
        # /* We only deal with GET and HEAD by default */
        return (pass);
    }

    # admin users always miss the cache
    if( req.url ~ "^/wp-(login|admin)" ||
        req.http.Cookie ~ "wordpress_logged_in_" ){
            return (pass);
    }

    # Remove cookies set by Google Analytics (pattern: '__utmABC')
    if (req.http.Cookie) {
        set req.http.Cookie = regsuball(req.http.Cookie,
            "(^|; ) *__utm.=[^;]+;? *", "1");
        if (req.http.Cookie == "") {
            remove req.http.Cookie;
        }
    }

    # always pass through POST requests and those with basic auth
    if (req.http.Authorization || req.request == "POST") {
        return (pass);
    }

    # Do not cache these paths
    if (req.url ~ "^/wp-cron.php$" ||
        req.url ~ "^/xmlrpc.php$" ||
        req.url ~ "^/wp-admin/.*$" ||
        req.url ~ "^/wp-includes/.*$" ||
        req.url ~ "?s=") {
            return (pass);
    }

    # Define the default grace period to serve cached content
    set req.grace = 30s;

    # By ignoring any other cookies, it is now ok to get a page
    unset req.http.Cookie;
    return (lookup);
}

sub vcl_fetch {  
    # remove some headers we never want to see
    unset beresp.http.Server;
    unset beresp.http.X-Powered-By;

    # only allow cookies to be set if we're in admin area
    if( beresp.http.Set-Cookie && req.url !~ "^/wp-(login|admin)" ){
        unset beresp.http.Set-Cookie;
    }

    # don't cache response to posted requests or those with basic auth
    if ( req.request == "POST" || req.http.Authorization ) {
        return (hit_for_pass);
    }

    # don't cache search results
    if( req.url ~ "?s=" ){
        return (hit_for_pass);
    }

    # only cache status ok
    if ( beresp.status != 200 ) {
        return (hit_for_pass);
    }

    # If our backend returns 5xx status this will reset the grace time
    # set in vcl_recv so that cached content will be served and
    # the unhealthy backend will not be hammered by requests
    if (beresp.status == 500) {
        set beresp.grace = 60s;
        return (restart);
    }

    # GZip the cached content if possible
    if (beresp.http.content-type ~ "text") {
        set beresp.do_gzip = true;
    }

    # if nothing abovce matched it is now ok to cache the response
    set beresp.ttl = 24h;
    return (deliver);
}

sub vcl_deliver {  
    # remove some headers added by varnish
    unset resp.http.Via;
    unset resp.http.X-Varnish;
}

sub vcl_hit {  
    # Set up invalidation of the cache so purging gets done properly
    if (req.request == "PURGE") {
        purge;
        error 200 "Purged.";
    }
    return (deliver);
}

sub vcl_miss {  
    # Set up invalidation of the cache so purging gets done properly
    if (req.request == "PURGE") {
        purge;
        error 200 "Purged.";
    }
    return (fetch);
}

sub vcl_error {  
    if (obj.status == 503) {
                # set obj.http.location = req.http.Location;
                set obj.status = 404;
        set obj.response = "Not Found";
                return (deliver);
    }
}

Fatto questo basterà riavviare il nostro server Ottimizzare wordpress Per ottimizzare il nostro wordpress andiamo a modificare alcuni file e ad installare questo plugin per varnish Per quanto riguarda il plugin inseriamo questi parametri

Varnish Administration IP Address: 127.0.0.1  
Varnish Administration Port: 80  
Varnish Secret: (get it at /etc/varnish/secret)  
Check: "Also purge all page navigation" and "Also purge all comment navigation"  
Varnish Version: 3  
Modifichiamo il file `functions.php` o `header.php`  
/**
 * Automated cache-buster function via filemtime
 **/
function autoVer($url){  
  $name = explode('.', $url);
  $lastext = array_pop($name);
  array_push(
    $name,
    filemtime($_SERVER['DOCUMENT_ROOT'] . parse_url($url, PHP_URL_PATH)),
    $lastext);
  echo implode('.', $name) ;
}
Modifichiamo il file `header.php`  
<!--?php 

    /*
     * Circumvent @import CSS for WordPress child themes
     * If we're in a child theme, build links for both parent and child CSS
     * This way, we can remove the @import from the child theme's style.css
     * CSS loaded via link can load simultaneously, while @import blocks loading
     * See: http://www.stevesouders.com/blog/2009/04/09/dont-use-import/
     */
    if(is_child_theme()) {
        echo '
    '."ntt";
        echo '
    '."n";
    } else {
        echo '
    '."n";
    }

Se abbiamo problemi ad inviare email dal sito web tramite form o altro installiamo i seguenti pacchetti

apt-get install postfix postfix-mysql postfix-doc getmail4 rkhunter binutils dovecot-imapd dovecot-pop3d  
Ora andiamo a modificare /etc/postfix/master.cf

[...]
submission inet n       -       -       -       -       smtpd  
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       -       -       -       smtpd  
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING
[...]

Riavviamo postfix

/etc/init.d/postfix restart

Adesso non dovremo avere altri problemi per quanto riguarda le email dal server

Articoli Correlati