HAUT

Nginx-extras, php-fpm – Reverse Proxy Cache – Ssl offloading sous Gnu/Debian Jessie

nginx [engine x] est un logiciel de serveur Web écrit par Igor Sysoev. Ses sources sont disponibles sous une licence de type BSD.\r\n\r\nCet article est une actualisation d’un ancien article diffusé sur ce site.\r\n\r\nNous utilisons ce serveur comme un « reverse proxy cache » pour délivrer plus efficacement les textes, images, sons et vidéo de nos sites hébergés sur notre plate-forme (une ferme de serveur Nginx et non plus Apache comme auparavant). Cette configuration fonctionne sous Gnu/Debian Jessie, mais aussi avec la version Backports sous Wheezy. Nous forçons aussi l’usage du SSL dont est chargé le Nginx qui joue le rôle de reverse proxy cache.\r\n\r\nCette configuration fonctionne avec Moodle, WordPress, Drupal et Owncloud. Elle ne nécessite pas de mettre le cgi.fix_pathinfo du php.ini à zéro et donc permet de laisser la version par défaut du fichier concernant ce paramètre.\r\n\r\nNous utilisons la version extras car elle intègre les modules upstream fair, upload_progress et le OCSP stapling. Nous utilisons un certificat ssl de la société Startcom.\r\n\r\nVoici la configuration du serveur Nginx, sur distribution Gnu/Linux Debian Jessie, dans ce contexte :\r\n

# apt-get install nginx-extras

\r\nSous Wheezy

# apt-get install -t wheezy-backports nginx-extras

\r\n/etc/nginx/nginx.conf\r\n

\r\nuser www-data;\r\n\r\nworker_processes auto;  # enfin auto !!!\r\n\r\nworker_rlimit_nofile 16536;\r\n\r\nerror_log /var/log/nginx/error.log;\r\n\r\npid /var/run/nginx.pid;\r\n\r\ntimer_resolution 1ms;\r\n\r\nevents {\r\n    worker_connections 1024;\r\n    multi_accept on;\r\n    use epoll;\r\n    accept_mutex_delay 1ms;\r\n}\r\n\r\nhttp {\r\n\r\n  include /etc/nginx/mime.types;\r\n  default_type application/octet-stream;\r\n\r\n # Client connection\r\n client_body_temp_path /tmp 1 2;\r\n client_header_timeout 5s;\r\n client_body_timeout 5s;\r\n send_timeout 10m;\r\n connection_pool_size 256k;\r\n client_header_buffer_size 16k;\r\n large_client_header_buffers 1024 256k; \r\n request_pool_size 128k; \r\n keepalive_requests 1000;\r\n keepalive_timeout 10;\r\n client_max_body_size 2G;\r\n client_body_buffer_size 1m;\r\n client_body_in_single_buffer on;\r\n open_file_cache max=10000 inactive=120s; \r\n open_file_cache_valid    45s;\r\n open_file_cache_min_uses 0;\r\n open_file_cache_errors   off;\r\n reset_timedout_connection on;\r\n\r\n  gzip on;\r\n  gzip_static on;\r\n  gzip_disable "msie6";  # trop vieux....\r\n  gzip_min_length 1000;\r\n  gzip_buffers 16 32k;\r\n  gzip_comp_level 9;\r\n  gzip_types  text/x-js image/svg+xml image/x-icon image/png text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/xml+rss text/javascript;\r\n  gzip_vary on;\r\n  gzip_proxied any;  \r\n\r\n # PROGRESS.\r\n  upload_progress uploads 1m;\r\n\r\n\r\n  ignore_invalid_headers on;\r\n  index index.html;\r\n  add_header Connection close;\r\n  autoindex off;\r\n\r\n  # Network optimizations\r\n  output_buffers 1000 128k;\r\n  postpone_output 1460;\r\n  sendfile on;   # off dans le server qui stream \r\n  sendfile_max_chunk 256k;\r\n  tcp_nopush on;\r\n  tcp_nodelay on;\r\n\r\n  server_tokens  off;\r\n\r\n  server_names_hash_max_size 5120;\r\n  server_names_hash_bucket_size 256;\r\n  \r\n  upstream_fair_shm_size 1024k;\r\n  \r\n  #### SSL\r\n  ssl_stapling on;\r\n  ssl_stapling_verify on;\r\n  ssl_trusted_certificate /etc/nginx/ssl/startssl-ca.pem;\r\n  resolver 127.0.0.1 valid=300s;\r\n  resolver_timeout 10s;\r\n  ssl_session_cache shared:SSL:32m;\r\n  ssl_buffer_size 8k;\r\n  ssl_session_timeout 10m;\r\n\r\n  log_format  access_proxy       '{"ip": "$remote_addr",'\r\n                                 '"port": "$remote_port",'\r\n				 '"host": "$host",'\r\n                                 '"path": "$request_uri",'\r\n                                 '"status": "$status($upstream_status)",'\r\n                                 '"referrer": "$http_referer",'\r\n                                 '"user_agent": "$http_user_agent",'\r\n                                 '"length": $bytes_sent/$gzip_ratio($sent_http_content_type),'\r\n                                 '"generation_time_milli": $request_time($upstream_response_time),'\r\n                                 '"date": "$time_local"}';\r\n\r\n       log_format stats '$host $http_x_forwarded_for - $remote_user [$time_local] "$request" '\r\n                        '$status $body_bytes_sent "$http_referer" '\r\n		        '"$http_user_agent"';\r\n					\r\n\r\n\r\n  access_log "/var/log/nginx/access.log" access_proxy;\r\n\r\n  include /etc/nginx/conf.d/*.conf;\r\n  include /etc/nginx/sites-enabled/*;\r\n }\r\n

\r\n

\r\nles fichiers dans le /etc/nginx/conf.d/ complètent la configuration du reverse proxy :\r\n\r\n/etc/nginx/conf.d/proxy.conf\r\n

\r\n# COMMON PARAMS\r\nproxy_temp_path   /var/lib/nginx/proxy 1 2;\r\n# A cause des CGN ou NAT maison on veut le port tcp dans les logs.\r\nproxy_set_header Host $http_host;\r\nproxy_set_header X-Real-IP $remote_addr;\r\nproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\r\nproxy_set_header X-Forwarded-Proto $scheme;\r\nproxy_set_header Connection Close;\r\nproxy_pass_header Set-Cookie;\r\nproxy_pass_header P3P;\r\nproxy_pass_header User-Agent;\r\nproxy_set_header X-Accel-Buffering on;\r\nproxy_redirect off;\r\nproxy_intercept_errors on;\r\nproxy_ignore_client_abort on;\r\n# qui attends plus de 2mn aujourd'hui ?\r\nproxy_connect_timeout 120;\r\nproxy_send_timeout 120;\r\nproxy_read_timeout 120;\r\nproxy_buffer_size 128k;\r\nproxy_buffers 65536 128k;\r\nproxy_busy_buffers_size 256k;\r\nproxy_temp_file_write_size 128k;

\r\n/etc/nginx/conf.d/backend.conf\r\n

\r\nupstream backend {\r\nserver A max_fails=1 fail_timeout=1; \r\nserver B max_fails=1 fail_timeout=1; \r\nfair; # sois fair et tais toi.\r\n}\r\n

\r\n/etc/nginx/conf.d/cache.conf\r\n

\r\nproxy_cache_path /var/cache/nginx levels=1:2 keys_zone=microcache:4m inactive=180s max_size=100m;\r\nproxy_cache_min_uses 0;\r\nproxy_cache_methods GET;\r\nproxy_cache_key "$host$request_uri$cookie_PHPSESSID";\r\n

\r\n/etc/nginx/conf.d/fcgicache.conf\r\n

\r\nfastcgi_cache_path /var/cache/fcgicache levels=1:2 keys_zone=fcgimicrocache:8m max_size=200m;\r\nfastcgi_cache_min_uses 0;\r\nfastcgi_cache_methods GET;\r\nfastcgi_buffer_size 128k;\r\nfastcgi_buffers 65536 128k;\r\nfastcgi_cache_key $scheme$proxy_host$request_uri;\r\n

\r\n/etc/nginx/conf.d/security.conf\r\n

\r\n# un anti-ddos et brut force de fortune.\r\nlimit_conn_zone $binary_remote_addr zone=parip:4m;\r\nlimit_conn_zone $server_name zone=parserver:4m;\r\n

\r\n\r\nNous utilisons pour le SSL, le support TLS SNI, Les fichiers pour les virtualhost sont donc les suivants :\r\n\r\n/etc/nginx/sites-available/00-default.conf\r\n

\r\nserver {\r\n\r\n   listen IP EXTERNE:80 default_server;\r\n\r\n   server_name _;\r\n\r\n   limit_conn parip 5;\r\n   limit_conn parserver 100;\r\n\r\n   return 444;\r\n\r\n}\r\n\r\n   listen IP EXTERNE:443 ssl;\r\n\r\n    \r\n     ssl_certificate           /etc/nginx/ssl/MON CERTIFICAT + INTERMEDIATE.pem;\r\n     ssl_certificate_key       /etc/nginx/ssl/MA CLE de CERTIFICAT.key;\r\n\r\n     ssl_prefer_server_ciphers on;\r\n     # nous corsons le SSL..... \r\n     ssl_protocols           TLSv1 TLSv1.1 TLSv1.2;\r\n     ssl_ciphers             "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";\r\n   \r\n   server_name _;\r\n\r\n   limit_conn parip 5;\r\n   limit_conn parserver 100;\r\n\r\n   return 444;\r\n\r\n}\r\n\r\n##########################  si BACKEND sur un même serveur ou pas #######################\r\n\r\nserver {\r\n   listen IP BACKEND:6666 default_server;\r\n\r\n   server_name _;\r\n\r\n   limit_conn parip 5;\r\n   limit_conn parserver 100;\r\n\r\n   return 444;\r\n\r\n}\r\n\r\n\r\n

\r\nSur le Nginx, reverse Proxy cache:\r\n/etc/nginx/sites-available/monnomdeserveur.conf\r\n

\r\nserver {\r\n\r\nlisten IPEXTERNE:80;\r\n\r\nserver_name www.monnomdeserveursanswww;\r\n\r\n   limit_conn parip 5;\r\n   limit_conn parserver 100;\r\n\r\nreturn 301  http://monnomdeserveursanswww;\r\n\r\n}\r\n\r\nserver {\r\n\r\nlisten IPEXTERNE:80;\r\nserver_name monnomdeserveursanswww;\r\n\r\n   limit_conn parip 5;\r\n   limit_conn parserver 100;\r\n\r\nreturn 301  https://monnomdeserveursanswww;\r\n\r\n}\r\n\r\nserver {\r\n   listen IP EXTERNE:443 ssl;\r\n\r\n    \r\n     ssl_certificate           /etc/nginx/ssl/MON CERTIFICAT + INTERMEDIATE.pem;\r\n     ssl_certificate_key       /etc/nginx/ssl/MA CLE de CERTIFICAT.key;\r\n\r\n     ssl_prefer_server_ciphers on;\r\n     ssl_protocols           TLSv1 TLSv1.1 TLSv1.2;\r\n     ssl_ciphers             "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";\r\n   \r\n   server_name www.monnomdeserveursanswww;\r\n\r\n   limit_conn parip 5;\r\n   limit_conn parserver 100;\r\n\r\nreturn 301  https://monnomdeserveursanswww;\r\n\r\n}\r\n\r\nserver {\r\n   listen IP EXTERNE:443 ssl;\r\n\r\n    \r\n     ssl_certificate           /etc/nginx/ssl/MON CERTIFICAT + INTERMEDIATE.pem;\r\n     ssl_certificate_key       /etc/nginx/ssl/MA CLE de CERTIFICAT.key;\r\n\r\n     ssl_prefer_server_ciphers on;\r\n     ssl_protocols           TLSv1 TLSv1.1 TLSv1.2;\r\n     ssl_ciphers             "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";\r\n   \r\n   server_name monnomdeserveursanswww;\r\n\r\n   limit_conn parip 5;\r\n   limit_conn parserver 100;\r\n\r\n    # je travaille pas pour rien !\r\n     location ~ /\. { deny  all; access_log off; log_not_found off; }\r\n     location ~ ~$ { deny  all; access_log off; log_not_found off; }\r\n\r\n     location ~* .(engine|inc|info|install|module|profile|po|sh|.*sql|theme|tpl(.php)?|xtmpl)$|^(code-style.pl|Entries.*|Repository|Root|Tag|Template)$\r\n       {   deny all; access_log off; log_not_found off;     }\r\n\r\n\r\n ## je bosse maintenant\r\n     client_max_body_size 2G;\r\n\r\n    location / {\r\n\r\n    \r\n      proxy_cache microcache; \r\n      proxy_cache_valid 200 302 2s;\r\n      proxy_cache_valid 404 3s;\r\n      proxy_cache_valid any 1s;\r\n      proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;\r\n      proxy_ignore_headers Cache-Control Expires;\r\n      proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;\r\n      proxy_cache_bypass  $http_pragma $http_authorization;\r\n      proxy_no_cache $cookie_nocache $arg_nocache$arg_comment;\r\n      proxy_no_cache $http_pragma $http_authorization;\r\n      add_header X-Micro-Cache $upstream_cache_status;\r\n      add_header X-Content-Options nosniff;\r\n      add_header Strict-Transport-Security "max-age=7200";\r\n   \r\n      ## HTTPS\r\n      add_header              Front-End-Https   on;\r\n\r\n      proxy_cache_lock on;\r\n      proxy_http_version 1.1;  # 1.0.... mais vous rigolez...\r\n      proxy_pass http://backend_www;\r\n\r\n      track_uploads uploads 30s;\r\n\r\n   \r\n  }}

\r\n#### la conf du BACKEND sur un serveur différent (tiers application) ou identique (en 127.0.0.1).\r\n/etc/nginx/sites-available/monnomdeserveur.conf\r\n

\r\nserver {\r\n	listen IPBACKEND:6666;\r\n	server_name monnomdeserveur;\r\n     \r\n	client_max_body_size 2G;  # merci owncloud...\r\n   	\r\n        root /srv/...MON CHEMIN..../html;\r\n	index index.php;\r\n        \r\n        gzip off;\r\n\r\n        access_log "/var/log/nginx/vhosts.access.log" stats;\r\n        location = /favicon.ico {\r\n	    log_not_found off;\r\n	    access_log off;\r\n         }\r\n\r\n         location = /robots.txt {\r\n	     allow all;\r\n	     log_not_found off;\r\n	     access_log off;\r\n          }\r\n\r\nlocation / {\r\n	try_files $uri $uri/ /index.php?$args;\r\n}\r\n  location ~ [^/]\.php(/|$) {\r\n                fastcgi_split_path_info ^(.+?\.php)(/.+)$;\r\n                \r\n# certains préfèrent: try url =404; mais non....\r\n                  if (!-f $document_root$fastcgi_script_name) {\r\n		                          return 404;\r\n					               \r\n                # With php5-fpm:\r\n                fastcgi_intercept_errors on;\r\n                fastcgi_cache fcgimicrocache;\r\n                ## The cache key.\r\n                fastcgi_cache_key $scheme$request_method$host$request_uri;\r\n                fastcgi_cache_valid 200 302 2s;\r\n                fastcgi_cache_valid 404 3s;\r\n                fastcgi_cache_valid any 1s;\r\n                fastcgi_cache_use_stale error timeout invalid_header updating http_500;                \r\n                fastcgi_ignore_headers Cache-Control Expires Set-Cookie;\r\n                ## Bypass the cache.\r\n                fastcgi_cache_bypass $cookie_nocache $arg_nocache$arg_comment;\r\n                fastcgi_cache_bypass $http_pragma $http_authorization;\r\n                fastcgi_no_cache $cookie_nocache $arg_nocache$arg_comment; \r\n                fastcgi_no_cache $http_pragma $http_authorization;\r\n                fastcgi_cache_lock on;\r\n                include fastcgi_params;\r\n                fastcgi_read_timeout 300;\r\n                fastcgi_index index.php;\r\n                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\r\n                fastcgi_param HTTPS on;\r\n		fastcgi_pass unix:/var/run/php-fpm.sock;\r\n        }\r\n\r\n# Cachons nous ! un bon score sur gtmetrix...\r\n  location ~* \.(?:ico|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {\r\n           \r\n             expires 1y;\r\n	     add_header Pragma public;\r\n             add_header Cache-Control "public";\r\n             access_log off;\r\n             tcp_nodelay off;\r\n             }\r\n\r\n     location ~* \.(?:js|css)$ {\r\n            \r\n             expires 1w;\r\n	     add_header Pragma public;\r\n             add_header Cache-Control "public";\r\n             add_header Vary "Accept-Encoding";\r\n             access_log off;\r\n             tcp_nodelay off;\r\n           }\r\n}\r\n\r\n

\r\nPour vider la cache, il faut en plus du redémarrage du serveur Nginx, ne pas oublier d’effacer le contenu du répertoire /var/cache/nginx/. \r\n\r\nLa commande nginx -t est pratique pour vérifier la conformité de la configuration.\r\n\r\nIl n’y a pas d’Ipv6 car c’est de la M….on en veut plus.

Les commentaires sont fermés.