Nginx (1.2)

From Hexwiki
Jump to navigation Jump to search

I do have some documentation laying around about how to setup fastcgi and Apache. It is ancient at this point, however. I cannot recommend nginx enough, across the board, for all webserving needs.

Supporting Files

/etc/nginx/mime.types

If you're dealing with content security policy, you may wish to add something like

text/x-content-security-policy          csp;

to your mime.types file. This assumes you are using .csp files for content security policies - adjust accordingly.

/etc/nginx/fastcgi_params

This is only really relevant for php setups over fastcgi.

fastcgi_param   QUERY_STRING            $query_string;
fastcgi_param   REQUEST_METHOD          $request_method;
fastcgi_param   CONTENT_TYPE            $content_type;
fastcgi_param   CONTENT_LENGTH          $content_length;
fastcgi_param   SCRIPT_FILENAME         $request_filename;
fastcgi_param   SCRIPT_NAME             $fastcgi_script_name;
fastcgi_param   REQUEST_URI             $request_uri;
fastcgi_param   DOCUMENT_URI            $document_uri;
fastcgi_param   DOCUMENT_ROOT           $document_root;
fastcgi_param   SERVER_PROTOCOL         $server_protocol;
fastcgi_param   GATEWAY_INTERFACE       CGI/1.1;
fastcgi_param   SERVER_SOFTWARE         nginx/$nginx_version;
fastcgi_param   REMOTE_ADDR             $remote_addr;
fastcgi_param   REMOTE_PORT             $remote_port;
fastcgi_param   SERVER_ADDR             $server_addr;
fastcgi_param   SERVER_PORT             $server_port;
fastcgi_param   SERVER_NAME             $server_name;
fastcgi_param   HTTPS                   $https if_not_empty;
# Because MediaWiki is silly.
fastcgi_param   TMP                     /home/ptmp;
fastcgi_param   TMPDIR                  /home/ptmp;
fastcgi_param   TEMP                    /home/ptmp;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param   REDIRECT_STATUS         200;
fastcgi_index               index.php;
fastcgi_ignore_client_abort on;
fastcgi_buffers             64 4k;
fastcgi_read_timeout        300;
fastcgi_send_timeout        300;
location = /.user.ini {
  return 404;
}

/etc/nginx/include_common

I use this to make server-spanning changes quickly if needed...

include               /etc/nginx/valid_referers;
if ($request_method !~ ^(GET|HEAD|OPTIONS|POST)$ ) { return 405; }
if ($http_user_agent = "") { return 403; }
if ($http_user_agent ~* "^Java") { return 403; }

Blank user agents, and those beginning with 'Java', are almost always malicious. If you don't use software that makes use of the OPTIONS request method, you may wish to remove that.

/etc/nginx/valid_referers

none blocked 1.2.3.* other.ipv4.classc.*

Referenced in the above file, I just add all of my domains here, rather than try to worry about them individually.

/etc/nginx/nginx.conf

user www-data;
# 4 is probably overkill for my current server, but you probably will want at least two, even if binding them to the same CPU.
worker_processes      4;
# For sanity. Note that neighboring numbers are actually the same physical core, hyperthreading doesn't actually double your computer's power.
worker_cpu_affinity   10000000 00100000 00001000 00000010;
worker_rlimit_nofile  65536;
# Yup, notice. Have had a few problems where I have needed this.
error_log             /var/log/nginx/error.root.log notice;
pid                   /var/run/nginx.pid;
events {
  worker_connections 4096;
  # multi_accept on;
}
http {
  include                    /etc/nginx/mime.types;
  default_type               text/plain;
  types_hash_max_size        4096;
  index                      index.php index.html;
  error_log                  /var/log/nginx/error.http.log notice;
  # server_name_in_redirect    off;
  server_tokens              off;
  # As with MySQL buffers, I use 256k for most small buffers on my system.
  client_body_buffer_size    256k;
  # max_body_size limits how big the total size of a request is - such as a file upload. Obviously, this will vary depending on your application.
  client_max_body_size       32m;
  # I keep limit rate in the event that I may need it.
  #limit_rate                64k;
  output_buffers             1 256k;
  # connection_pool_size       256;
  # request_pool_size          8k;
  sendfile                   on;
  tcp_nopush                 on;
  # nginx is pretty robust in my experience, so long keepalive timeouts and allowing a crazy number of requests works just fine.
  client_body_timeout        15;
  client_header_timeout      15;
  send_timeout               15;
  keepalive_timeout          75;
  keepalive_requests         10000;
  # Igor Sysoev says that with this on, there is 100ms less delay
  # in some keepalive situations.
  tcp_nodelay                on;
  # server_names_hash_bucket_size 64;
 
  # Nginx now puts these in /var/lib/nginx by default. Better this than making a new tmpfs partition for them.
  client_body_temp_path      /var/tmp/nginx_body 2 2;
  fastcgi_temp_path          /var/tmp/nginx_fcgi 2 2;
  proxy_temp_path            /var/tmp/nginx_prox 2 2;
  scgi_temp_path             /var/tmp/nginx_scgi 2 2;
  uwsgi_temp_path            /var/tmp/nginx_uwsi 2 2;
  gzip                       on;
  gzip_static                on;
  gzip_http_version          1.0;
  gzip_disable               "msie6";
  gzip_buffers               64 4k;
  gzip_comp_level            9;
  gzip_min_length            512;
  gzip_types                 text/plain text/css text/xml text/mathml application/x-javascript application/xhtml+xml application/atom+xml application/json application/xml application/xml+rss text/javascript image/x-icon;
  gzip_vary                  on;
  access_log /var/log/nginx/access.html.log;
  # Prefer TLSv1.2, failing that, fall back to RC4 to prevent BEAST attacks. Failing that,
  # use HIGH encryption ciphers. Note that this simple layout does not generate a 'perfect' list per
  # SSL Labs. Ideally, you want to make sure the Forward Secrecy ciphers load first, but this functions
  # well for modern browsers in general.
  ssl_ciphers                TLSv1.2:RC4:HIGH:!ADH:!LOW:!EXP:!SSLv2:!MD5:!aNULL:!NULL;
  ssl_protocols              TLSv1.2 TLSv1.1 TLSv1 SSLv3;
  ssl_prefer_server_ciphers  on;
  # Makes an enormous difference in performance over SSL. Practically required.
  ssl_session_cache          shared:SSL:32m;
  ssl_session_timeout        30m;

  # Most of naxsi's default rules are unnecessary for my own needs.
  # Should work out a stripped-down ruleset to get rid of the really bad stuff.
  #include /etc/nginx/naxsi_core.rules;
  # I generally allocate ip addresses in the main file here, and include in the /sites
  # subdirectory directly on a per-case basis. Makes it easier for me to keep track of what ips
  # are bound where.
  #include /etc/nginx/sites-enabled/*;
  # These end up looking like
  server {
    listen 203.0.113.211:80;
    server_name example.com;
    include /etc/nginx/sites/example.conf;
  }
  server {
    ssl on;
    listen 203.0.113.211:443 default;
    ssl_certificate     /etc/nginx/certs/example.com.crt;
    ssl_certificate_key /etc/nginx/certs/example.com.key;
    server_name example.com;
    # If your site runs on both http and https, you will want to make sure that spiders only index one version at a time.
    # Keep in mind, If is Evil. Use sparingly.
    if ($http_user_agent ~* (googlebot|slurp|msnbot|teoma|baiduspider)) {
      rewrite  ^(.*)$  http://example.com$1  break;
    }
    fastcgi_param  HTTPS  On;
    include /etc/nginx/sites/example.conf;
  }
  server {
    listen 203.0.113.211:80;
    listen 203.0.113.211:443;
    server_name *.example.com;
    rewrite  ^(.*)$  $scheme://example.com$1 redirect;
  }
  # For an ssl site listening both on http and https. It's a bit messy, but functional 
}

/root/fpmnginx.conf

I have a script do most of the job of framing a website for me. It takes this file and replaces things as needed. This defaults to setting up Drupal + a wiki, but it is decent enough for a default and easy to modify.

   include               /etc/nginx/fastcgi_params;
   include               /etc/nginx/include_common;
   root                  /home/USERNAME/docs;
   error_page  404       /index.php;
   access_log            /var/log/nginx/access-USERNAME.log;
   error_log             /var/log/nginx/error-USERNAME.log;
   location ~* ^/w/images/ {
     if ($invalid_referer) {
       return 444;
     }
     access_log        off;
     expires           1h;
   }
   location ~ \.php$ {
     if (-f $request_filename) {
       fastcgi_pass unix:/var/run/USERNAME-fpm.sock;
     }
   }
   location ~ ^/wiki/ {
     rewrite ^/wiki/(.*)$ /w/index.php?title=$1;
   }
   try_files $uri $uri/ /index.php?q=$uri&$args;