Force SSL for admin pages only on nginx

Per Hansson

Member
Hi, I'm trying to force SSL or HTTPS access only for the admin interface in Xenforo.
I want the rest of the forum to be in regular http for advertising purposes.
Maybe next year the ad-pool will be the same for http as well so the whole site can be https, but not yet...

Currently this is what I have on a local testserver, it's working fine but I'd like input on if there is anything I have missed; and if anything can be done in a better or even just nicer way config wise...

The config is quite simple, the first "server" block handles https requests coming from any other domain and rewrites it to our domain; then follows the https server config.
Here I only allow specific locations which should be SSL enabled to continue, all others go back to the regular http server that follows further down.
In our case I'm allowing the Xenforo admin page and deferred page, plus the folders where it includes content from.
Also the small favicon is allowed, as that would otherwise also cause a mixed content warning...

The http server is divided up in two servers, just like the https one, so we can rewrite the url of traffic coming from any domain to our own.
What follows is an expires directive for static content, and then the Xenforo config.

As long as the admin.php file is not requested all traffic will be served via http.
But as soon as someone requests admin.php we will be redirected back to the https server.
I tested this on all buttons I could find in the admin interface and never got a mixed content warning. ;)
But your input is of course most welcome! :)

Code:
    server {
        ## Redirect to Domain if $host does not match https://www.domain.com
        ## This will raise a SSL warning because the SSL cert obviously does not match the requested domain (somedomain, direct ip etc)
        listen       443 ssl spdy default_server;
        server_name  _;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_certificate /somepath...crt;
        ssl_certificate_key /somepath...key;
        return 301 http://www.domain.com$request_uri;
    }
    server {
        ## SSL server listening on https port 443
        listen       443 ssl spdy;
        server_name  www.domain.com;
        limit_conn addr 20;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_certificate /somepath...crt;
        ssl_certificate_key /somepath...key;

        ## Redirect back to http for all general requests
        location / {
          return 301 http://www.domain.com$request_uri;
        }

        ## Xenforo admin pages
        location = /community/admin.php {
          fastcgi_pass _php;
        }
        location = /community/deferred.php {
          fastcgi_pass _php;
        }
        location ~ ^/community/(js|styles|data) {
          #This location allows Xenforo content to be delivered via https
          #without raising mixed content warnings in browsers
          try_files $uri =404;
        }
        location = /favicon.ico {
          log_not_found off;
          access_log off;
        }
    }

    server {
        ## Redirect to Domain if $host does not match http://www.domain.com
        listen       80 default_server;
        server_name  _;
        return 301 http://www.domain.com$request_uri;
    }
    server {
        ## Domain server listening on http port 80
        listen       80;
        server_name  www.domain.com;
        limit_conn addr 20;

        ## Tell browsers to cache these files for 90 days and serve them directly
        ## Note that thus these filetypes can NOT be rewritten again below!
        location ~* \.(jpg|jpeg|gif|css|png|ico|js)$ {
          expires 90d;
        }


        # Xenforo
        location /community/ {
           try_files  $uri $uri/ /community/index.php?$uri&$args;
        }
        location ~ /community/(internal_data|library|install/data|install/templates) {
           internal;
        }
        # SSL redirect for Xenforo admin pages
        location = /community/admin.php {
           return 301 https://$server_name$request_uri;
        }


        # Pass all .php files onto a php-fpm/php-fcgi server.
        location ~ \.php$ {
           # Zero-day exploit defense.
           # http://forum.nginx.org/read.php?2,88845,page=3
           # Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
           # Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine.  And then cross your fingers that you won't get hacked.
           try_files $uri =404;
           fastcgi_split_path_info ^(.+\.php)(/.+)$;
           fastcgi_pass _php;
        }


        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        location ~ /\.ht {
            deny  all;
        }
        location ~ /\.git {
            deny all;
        }
 
Last edited:
If the application (XenForo) is not aware of this change with any of its settings, make sure you don't redirect POST requests or you might lose data from forms that use absolute URLs.
 
Back
Top Bottom