Item14551: Update the default Nginx configuration examples

pencil
Priority: Enhancement
Current State: Waiting for Feedback
Released In: 2.1.5
Target Release: patch
Applies To: Extension
Component: FastCGIEngineContrib
Branches:
Reported By: GeorgeClark
Waiting For:
Last Change By: GeorgeClark
The current example Nginx configuration has a few issues:
  • It uses an if statement for referrer blocking. There are better solutions available.
  • It uses an [A-Z] regular expression to detect short URLs, which doesn't support accented characters.
  • Redirecting to /bin/view for short URLs loops if a redirect is present to remove /bin/view when users enter long URLs on a short url site.

I suggest including the below example by default. A VirtualHostingContrib example should be included as part of that contrib, and not in the default nginx configuration.

server {
    listen       80 http2 fastopen=50 reuseport;
    #listen       443 ssl http2 fastopen=50 reuseport;
    server_name  mysite.org;

    set $foswiki_root "/var/www/mysite";
    root $foswiki_root;

    set $foswiki_fcgi  127.0.0.1:9000
    #set $foswiki_fcgi unix:/var/run/foswiki/foswiki.sock;

    access_log  /var/log/nginx/mysite-access.log;
    error_log   /var/log/nginx/mysite-error.log;
    #error_log   /var/log/nginx/mysite-error.log debug;   # optional extra debugging

    client_max_body_size 100M;   # Set to maximum attachment size, See also ATTACHFILESIZELIMIT


    # Example SSL configuration parameters
    # ssl_certificate     /etc/letsencrypt/live/mysite_cert__current.pem;
    # ssl_certificate_key /etc/letsencrypt/live/mysite_privkey__current.pem;

    # ssl_protocols TLSv1.3;# Requires nginx >= 1.13.0 else use TLSv1.2
    # ssl on;
    # ssl_prefer_server_ciphers on; 
    # ssl_dhparam /etc/nginx/dhparam.pem; # openssl dhparam -out /etc/nginx/dhparam.pem 4096
    # ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
    # ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
    # ssl_session_timeout  10m;
    # ssl_session_cache shared:SSL:10m;
    # ssl_session_tickets off; # Requires nginx >= 1.5.9

    # ssl_stapling on; # Requires nginx >= 1.3.7
    # ssl_stapling_verify on; # Requires nginx => 1.3.7
    # resolver 127.0.0.1 [::1]:5353 valid=30s;  # ipv6 Requires >= 1.5.8, multiple servers >= 1.1.7  cache time >= 1.1.9
    # resolver_timeout 5s; 

    # add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
    # add_header X-Frame-Options DENY;
    # add_header X-Content-Type-Options nosniff;
    # add_header X-XSS-Protection "1; mode=block";
    # add_header X-Robots-Tag none; 

# For blocking of misbehaving search engines, and other bad bots we suggest the following
#  https://github.com/oohnoitz/nginx-blacklist/blob/master/blacklist.conf
#  or: https://github.com/Stevie-Ray/referrer-spam-blocker/blob/master/referral-spam.conf

    location = /favicon.ico {
       limit_except GET { deny all; }
       log_not_found off;
       access_log off;
    }

    location = /robots.txt {
       limit_except GET { deny all; }
       allow all;
       log_not_found off;
       access_log off;
    }

    # Allow google site verification files  
    #location ~ ^/google.*\.html$ {
    #   limit_except GET { deny all; }
    #   allow all;
    #   log_not_found off;
    #   access_log off;
    #   try_files $uri 404;
    #}  

    # Short URL redirect (matches prefix)
    # If a user enters /bin/view directly, redirect them to the short URL
    location /bin/view/ {
       rewrite ^/bin/view/(.*) /$1 permanent;
    }
 
    # Set a default landing page (matches exact)
    location = / {
        limit_except GET POST { deny all; }
        root $foswiki_root;
        rewrite .* /Web/WebHome;
    }

    # Deny all the important directories (match regex)
    location ~ ^(/lib|/data|/locale|/templates|/test|/tools|/work) {
        deny all;
    }

    # Allow pub access (matches prefix)
    location /pub/ {
        limit_except GET { deny all; }
        allow all;
    }

    # Cache and zip files served from certain paths (matches regex)
    # WARNING: files need to be legitimately gzipped, and not be symlinks to the non-gzipped content.

    location ~ ^/pub/(Main|System|Applications|images|cache)/ {
          limit_except GET { deny all; }
          expires 8h;
          gzip_static on;
    }

    # Any explicit bin scripts - pass to FCGI backend (matches prefix)
    location /bin/ {
           limit_except GET POST { deny all; }
           gzip off;
           fastcgi_pass             $foswiki_fcgi;
           fastcgi_split_path_info  ^(/bin/\w+)(.*);
           #  Captures two variables   ($fastcgi_script_name) and ($fastcgi_path_info)

           include fastcgi_params;  # include this first, to allow overrides below

           fastcgi_param            SCRIPT_FILENAME $foswiki_root/bin/$fastcgi_script_name;
           fastcgi_param            SCRIPT_NAME     $fastcgi_script_name;
           fastcgi_param            PATH_INFO       $fastcgi_path_info;
       }

    # For any other URLs   pass it to the FCGI backend with view script (matches prefix)
    location / {
           limit_except GET POST { deny all; }
           gzip off;
           fastcgi_pass             $foswiki_fcgi;
           fastcgi_split_path_info  ()?(.*);    # no script, default it to view

           include fastcgi_params;  # include this first, to allow overrides below

           fastcgi_param            SCRIPT_FILENAME $foswiki_root/bin/view;
           fastcgi_param            SCRIPT_NAME     view;
           fastcgi_param            PATH_INFO       $fastcgi_path_info;
    }
}

-- GeorgeClark - 03 Dec 2017

Michael, can you review this as an improved sample nginx configuration? Except for some cosmetic changes, I've tested it on 3 different sites. I'm a bit uneasy about that last fastcgi_split_path_info with the empty script capture. Maybe it should be (nomatch)?(.*) My live configs include the common file definitions, letsencrypt config, and the tls settings. I pasted much of it inline for this example.

-- GeorgeClark - 03 Dec 2017

I was able to simplify the fcgi location block down to just one. Foswiki seems to just get the script right.

    # For any other URLs   pass it to the FCGI backend. Foswiki figures out the script, even when missing.
    location / {
           limit_except GET POST { deny all; }
           gzip off;
           fastcgi_pass             $foswiki_fcgi;
           fastcgi_split_path_info  ^(/bin/\w+)?(.*);    # no script, default it to view

           include fastcgi_params;  # include this first, to allow overrides below

           fastcgi_param            SCRIPT_FILENAME $foswiki_root/$fastcgi_script_name;
           fastcgi_param            SCRIPT_NAME     $fastcgi_script_name;
           fastcgi_param            PATH_INFO       $fastcgi_path_info;
    }

-- GeorgeClark - 11 Dec 2017

And after running this on a live site with XSendFileContrib protecting some attachments, I've settled on:

server {
...
    set $foswiki_root "/var/www/foswiki/distro/core";
    root $foswiki_root;

   # This handles robots.txt, google keys, etc.
    include snippets/common-files.conf;

   # Default landing page - exact prefix match.
    location = / {
        root $foswiki_root;
        rewrite .* /bin/view/Main/WebHome;
    }

    # This regex will override any prefix matches defined further down unless blocked by ^~
    location ~ ^/pub/(System|Applications|images|cache)/ {
      allow all;
      expires 12h;
      gzip_static on;
    }

    # Shorter regex,  so if above longer match misses, then send it to xsendfile.
    location ~ ^/pub/ {
      rewrite ^/pub/(.*)$ /bin/xsendfile/$1;
    }

    # xsendfile internally redirects here for permitted files.
    # ^~ prevents any regex matching if the prefix matches.
    location ^~ /protected_files/ {
       internal;
       alias $foswiki_root/pub/;
    }

    # This is also an absolute prefix.  If /bin/ prefix matches, don't do any further matching.
    location ^~ /bin/ {
           gzip off;
           fastcgi_pass             127.0.0.1:9000;
           fastcgi_split_path_info  ^(/bin/\w+)(.*);
           #  Captures two variables   ($fastcgi_script_name) and ($fastcgi_path_info)
           fastcgi_param            SCRIPT_FILENAME $foswiki_root$fastcgi_script_name;
           fastcgi_param            SCRIPT_NAME     $fastcgi_script_name;
           fastcgi_param            PATH_INFO       $fastcgi_path_info;
           include fastcgi_params;
       }

   # regex to pick up all the restricted stuff.
    location ~ ^(/lib|/data|/locale|/templates|/tools|/work) {
        deny all;
    }

    # Short URL redirect.  Very short match, so this should not override any other specific matces.
    location ~ ^/ {
        rewrite ^/(.*)$ /bin/view/$1;
    }
}

-- GeorgeClark - 12 Mar 2018
 

ItemTemplate edit

Summary Update the default Nginx configuration examples
ReportedBy GeorgeClark
Codebase 2.1.4, trunk
SVN Range
AppliesTo Extension
Component FastCGIEngineContrib
Priority Enhancement
CurrentState Waiting for Feedback
WaitingFor
Checkins
TargetRelease patch
ReleasedIn 2.1.5
CheckinsOnBranches
trunkCheckins
masterCheckins
ItemBranchCheckins
Release02x01Checkins
Release02x00Checkins
Release01x01Checkins
Topic revision: r3 - 12 Mar 2018, GeorgeClark
The copyright of the content on this website is held by the contributing authors, except where stated elsewhere. See Copyright Statement. Creative Commons License    Legal Imprint    Privacy Policy