title: Nginx redirect Http to Https - what's wrong here?
body: <p>I have an Nginx server which should redirect all requests from <a href="http://www.domain.com" rel="nofollow">http://www.domain.com</a> and <a href="http://domain.com" rel="nofollow">http://domain.com</a> and <a href="https://domain.com" rel="nofollow">https://domain.com</a> to <a href="https://www.domain.com" rel="nofollow">https://www.domain.com</a></p>
  
  <p>So with or without www and with or without ssl I want the user to always get to <a href="https://www.domain.com" rel="nofollow">https://www.domain.com</a>.</p>
  
  <p>After reading the nginx documentation and researching on google this is my current nginx configuration:</p>
  
  <pre><code>server {
    listen 80;
    server_name .domain.com;
    return 301 https://www.domain.com$request_uri;
  }
  
  server {
    listen                       443 ssl;
    server_name                  .domain.com;
    ssl_certificate              /etc/ssl/private/[pem file];
    ssl_certificate_key          /etc/ssl/private/[key file];
    ssl_session_timeout          5m;
    ssl_protocols                SSLv3 TLSv1;
    ssl_ciphers                  HIGH:!ADH:!MD5;
    ssl_prefer_server_ciphers    on;
    keepalive_timeout            70;
    ###
    ### Deny known crawlers.
    ###
    if ($is_crawler) {
      return 403;
    }
    location / {
      proxy_pass                 http://nginx_http;
      proxy_redirect             off;
      proxy_set_header           Host              $host;
      proxy_set_header           X-Real-IP         $remote_addr;
      proxy_set_header           X-Forwarded-By    $server_addr:$server_port;
      proxy_set_header           X-Forwarded-For   $proxy_add_x_forwarded_for;
      proxy_set_header           X-Local-Proxy     $scheme;
      proxy_set_header           X-Forwarded-Proto $scheme;
      proxy_pass_header          Set-Cookie;
      proxy_pass_header          Cookie;
      proxy_pass_header          X-Accel-Expires;
      proxy_pass_header          X-Accel-Redirect;
      proxy_pass_header          X-This-Proto;
      proxy_connect_timeout      300;
      proxy_send_timeout         300;
      proxy_read_timeout         300;
      proxy_buffer_size          4k;
      proxy_buffers              4 32k;
      proxy_busy_buffers_size    64k;
      proxy_temp_file_write_size 64k;
      access_log                 off;
      log_not_found              off;
    }
   50 }
  </code></pre>
  
  <p>What happens is that requests to <a href="http://domain.com" rel="nofollow">http://domain.com</a> get correctly redirected to <a href="https://www.domain.com" rel="nofollow">https://www.domain.com</a> but requests to <a href="http://www.domain.com" rel="nofollow">http://www.domain.com</a> are <em>not</em> being redirected (and the website is delivered without ssl).</p>
  
  <p>UPDATE:</p>
  
  <p>As this is part of a server set up by BOA (Barracuda Octopus Aegir) there are several config files in use. This is the nginx.conf which is loaded as well:</p>
  
  <pre><code># Aegir web server main configuration file
  
  #######################################################
  ###  nginx.conf main
  #######################################################
  
   ## FastCGI params
    fastcgi_param  SCRIPT_FILENAME     $document_root$fastcgi_script_name;
    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_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     ApacheSolaris/$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  USER_DEVICE         $device;
    fastcgi_param  GEOIP_COUNTRY_CODE  $geoip_country_code;
    fastcgi_param  GEOIP_COUNTRY_CODE3 $geoip_country_code3;
    fastcgi_param  GEOIP_COUNTRY_NAME  $geoip_country_name;
    fastcgi_param  REDIRECT_STATUS     200;
    fastcgi_index  index.php;
  
   ## Default index files
    index         index.php index.html;
  
   ## Size Limits
    client_body_buffer_size        64k;
    client_header_buffer_size      32k;
    client_max_body_size          100m;
    large_client_header_buffers 32 32k;
    connection_pool_size           256;
    request_pool_size               4k;
    server_names_hash_bucket_size  512;
    server_names_hash_max_size    8192;
    types_hash_bucket_size         512;
    map_hash_bucket_size           192;
    fastcgi_buffer_size           128k;
    fastcgi_buffers             256 4k;
    fastcgi_busy_buffers_size     256k;
    fastcgi_temp_file_write_size  256k;
  
   ## Timeouts
    client_body_timeout             60;
    client_header_timeout           60;
    send_timeout                    60;
    lingering_time                  30;
    lingering_timeout                5;
    fastcgi_connect_timeout         60;
    fastcgi_send_timeout           300;
    fastcgi_read_timeout           300;
  
   ## Open File Performance
    open_file_cache max=8000 inactive=30s;
    open_file_cache_valid          60s;
    open_file_cache_min_uses         3;
    open_file_cache_errors          on;
  
   ## FastCGI Caching
    fastcgi_cache_path /var/lib/nginx/speed
                       levels=2:2:2
                       keys_zone=speed:10m
                       inactive=15m
                       max_size=3g;
  
   ## General Options
    ignore_invalid_headers          on;
    limit_conn_zone $binary_remote_addr zone=gulag:10m;
    recursive_error_pages           on;
    reset_timedout_connection       on;
    fastcgi_intercept_errors        on;
    server_tokens                  off;
    fastcgi_hide_header         'Link';
    fastcgi_hide_header  'X-Generator';
    fastcgi_hide_header 'X-Powered-By';
    fastcgi_hide_header 'X-Drupal-Cache';
  
   ## TCP options moved to /etc/nginx/nginx.conf
  
   ## SSL performance
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout            10m;
  
   ## GeoIP support
    geoip_country /usr/share/GeoIP/GeoIP.dat;
  
   ## Compression
    gzip_buffers      16 8k;
    gzip_comp_level   5;
    gzip_http_version 1.0;
    gzip_min_length   10;
    gzip_types        text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_vary         on;
    gzip_proxied      any;
    add_header Vary "Accept-Encoding";
    gzip_static       on;
    upload_progress uploads 1m;
  
   ## Log Format
    log_format        main '"$proxy_add_x_forwarded_for" $host [$time_local] '
                           '"$request" $status $body_bytes_sent '
                           '$request_length $bytes_sent "$http_referer" '
                           '"$http_user_agent" $request_time "$gzip_ratio"';
  
    client_body_temp_path  /var/lib/nginx/body 1 2;
    access_log             /var/log/nginx/access.log main;
    error_log              /var/log/nginx/error.log crit;
  
  # Extra configuration from modules:
  #######################################################
  ###  nginx default maps
  #######################################################
  
  ###
  ### Support separate Boost and Speed Booster caches for various mobile devices.
  ###
  map $http_user_agent $device {
    default                                                                normal;
    ~*Nokia|BlackBerry.+MIDP|240x|320x|Palm|NetFront|Symbian|SonyEricsson  mobile-other;
    ~*iPhone|iPod|Android|BlackBerry.+AppleWebKit                          mobile-smart;
    ~*iPad|Tablet                                                          mobile-tablet;
  }
  
  ###
  ### Set a cache_uid variable for authenticated users (by @brianmercer and @perusio, fixed by @omega8cc).
  ###
  map $http_cookie $cache_uid {
    default  '';
    ~SESS[[:alnum:]]+=(?&lt;session_id&gt;[[:graph:]]+)  $session_id;
  }
  
  ###
  ### Live switch of $key_uri for Speed Booster cache depending on $args.
  ###
  map $request_uri $key_uri {
    default                                                                            $request_uri;
    ~(?&lt;no_args_uri&gt;[[:graph:]]+)\?(.*)(utm_|__utm|_campaign|gclid|source=|adv=|req=)  $no_args_uri;
  }
  
  ###
  ### Set cache expiration depending on the Drupal core version.
  ###
  map $sent_http_x_purge_level $will_expire_in {
    default   on-demand;
    ~*5|none  5m;
  }
  
  ###
  ### Deny crawlers.
  ###
  map $http_user_agent $is_crawler {
    default  '';
    ~*HTTrack|BrokenLinkCheck|2009042316.*Firefox.*3\.0\.10|MJ12|HTMLParser|libwww|PECL|Automatic|Click|SiteBot|BuzzTrack|Sistrix|Offline|Screaming|Nutch|Mireo|SWEB|Morfeus|GSLFbot  is_crawler;
  }
  
  ###
  ### Deny all known bots on some URIs.
  ###
  map $http_user_agent $is_bot {
    default  '';
    ~*crawl|goog|yahoo|yandex|spider|bot|tracker|click|parser  is_bot;
  }
  
  ###
  ### Deny almost all crawlers under high load.
  ###
  map $http_user_agent $deny_on_high_load {
    default  '';
    ~*crawl|goog|yahoo|yandex|baidu|bing|spider|tracker|click|parser  deny_on_high_load;
  }
  
  ###
  ### Deny listed requests for security reasons.
  ###
  map $args $is_denied {
    default  '';
    ~*delete.+from|insert.+into|select.+from|union.+select|onload|\.php.+src|system\(.+|document\.cookie|\;|\.\.  is_denied;
  }
  
  #######################################################
  ###  nginx default server
  #######################################################
  
  server {
    limit_conn   gulag 32; # like mod_evasive - this allows max 32 simultaneous connections from one IP address
    listen       *:80;
    server_name  _;
    location / {
       root   /var/www/nginx-default;
       index  index.html index.htm;
    }
  }
  
  #######################################################
  ###  nginx virtual domains
  #######################################################
  
  # virtual hosts
  include /var/aegir/config/server_master/nginx/pre.d/*;
  include /var/aegir/config/server_master/nginx/platform.d/*;
  include /var/aegir/config/server_master/nginx/vhost.d/*;
  include /var/aegir/config/server_master/nginx/post.d/*;
  </code></pre>
  
  <p>In the included directories at the end are some servers defined which listen to specific subdomains (set up by aegir). I think these don't affect us here.</p>
  
  <p>UPDATE 2:</p>
  
  <p>Thanks davismwfl and Melvyn for you input. Now it's getting interesting:</p>
  
  <pre><code>server {
    listen 80;
    server_name www.domain.com;
    return 301 https://www.domain.com$request_uri;
  }
  </code></pre>
  
  <p>When I create a server which should only redirect <a href="http://www.domain.com" rel="nofollow">http://www.domain.com</a> to <a href="https://www.domain.com" rel="nofollow">https://www.domain.com</a> requests get redirected to https://.. and then stuck in a redirect loop.</p>
  
  <p>If I understand this right for some reason the server which shall listen to port 80 also listens to https requests and tries <em>again</em> to redirect requests.</p>
  
  <p>Do you guy know why?</p>
  
  <p>Any ideas what the problem might be or why it does what it does?</p>
  
  <p>Thanks a lot, Martin</p>