Redirect loop problem with SSL

Hello, I am having a problem understanding exactly how to configure my
nginx
server to use SSL with Linode, RoR, Unicorn and spree ecommerce. This
post
will be kind of long, but this is just so you can see all the steps I
have
taken thus far. The first section will include all the steps I have
taken
to set up my linode instance. In this setup, the site displays, but I
get
the Redirect Loop when I try to log in. Someone suggested that I needed
to
set up separate server blocks for port 80 and port 443. After I did this
(the nginx.conf for that set up will be at the end), every page gives me
the
Redirect loop. So, I clearly do not understand what I am doing and need
a
little nudge. Please help me.

— error message —

This webpage has a redirect loop

The webpage at https://50.116.18.21/login has resulted in too many
redirects. Clearing your cookies for this site or allowing third-party
cookies may fix the problem. If not, it is possibly a server
configuration
issue and not a problem with your computer.

— end error message —

— original steps —

  1. create server Ubuntu 10.04 LTS (with defaults)

  2. boot server

  3. ssh [email protected]

  4. apt-get -y update

  5. apt-get -y install curl git-core python-software-properties

  6. add-apt-repository ppa:nginx/stable

  7. apt-get -y update

  8. apt-get -y install nginx
    /*** Can I do the SSL stuff here??? ***/
    #. mkdir /srv/ssl/
    #. cd /srv/ssl
    #. openssl req -new -x509 -days 365 -nodes -out /srv/ssl/nginx.pem
    -keyout
    /srv/ssl/nginx.key

  9. service nginx start

  10. apt-get -y install imagemagick

  11. add-apt-repository ppa:pitti/postgresql

  12. apt-get -y update

  13. apt-get -y install postgresql libpq-dev

  14. sudo -u postgres psql

  15. \password

  16. create user mayorio with password ‘secret’;

  17. create database mayorio_production owner mayorio;

  18. \q

  19. apt-get -y install telnet postfix

  20. add-apt-repository ppa:chris-lea/node.js

  21. apt-get -y update

  22. apt-get -y install nodejs

  23. apt-get -y install libxslt-dev libxml2-dev

  24. adduser deployer --ingroup admin

  25. su deployer

  26. cd

  27. curl -L
    https://raw.github.com/fesplugas/rbenv-installer/master/bin/rbenv-installer
    | bash

  28. vim ~/.bashrc # add rbenv to the top

  29. put the following in the top:
    — begin snippet —
    export RBENV_ROOT=“${HOME}/.rbenv”

if [ -d “${RBENV_ROOT}” ]; then
export PATH=“${RBENV_ROOT}/bin:${PATH}”
eval “$(rbenv init -)”
fi
— end snippet —
30. . ~/.bashrc
31. rbenv bootstrap-ubuntu-10-04
32. rbenv install 1.9.3-p125
33. rbenv global 1.9.3-p125
34. gem install bundler --no-ri --no-rdoc
35. rbenv rehash
36. ssh [email protected]
37. switch back to local box
38. rails new mayorio -d postgresql
39. cd mayorio
*** 40 and 41 no longer necessary. they must have fixed it :slight_smile:
40. edit Gemfile to add “gem ‘cocaine’, :git =>
‘git://github.com/thoughtbot/cocaine.git’” (make sure to do to newlines
after for spree)
41. bundle install
*** see above ***
42. sudo -u postgres psql
43. create user mayorio with password ‘secret’;
44. create database mayorio_development owner mayorio;
45. \q
46. edit config/database.yml to add password
47. spree install (accept all defaults)
48. bundle exec rake assets:precompile:nondigest
*** consider adding public/assets to .gitignore ***
49. edit .gitignore and add “/config/database.yml”
50. cp config/database.yml config/database.example.yml
51. git init
52. git add .
53. git commit -m “initial commit”
54. create github repo “mayorio”
55. git remote add origin [email protected]:mlybrand/mayorio.git
56. git push origin master
57. edit Gemfile to uncomment unicorn and capistrano lines
58. bundle
59. capify .
60. edit Capfile to uncomment load assets line
61. edit config/deploy.rb to be the following:
— begin code snippet —
require “bundler/capistrano”

server “50.116.18.21”, :web, :app, :db, primary: true

set :application, “mayorio”
set :user, “deployer”
set :deploy_to, “/home/#{user}/apps/#{application}”
set :deploy_via, :remote_cache
set :use_sudo, false

set :scm, “git”
set :repository, “[email protected]:mlybrand/#{application}.git”
set :branch, “master”

default_run_options[:pty] = true
ssh_options[:forward_agent] = true

after “deploy”, “deploy:cleanup” # keep only the last 5 releases

namespace :deploy do
%w[start stop restart].each do |command|
desc “#{command} unicorn server”
task command, roles: :app, except: {no_release: true} do
run “/etc/init.d/unicorn_#{application} #{command}”
end
end

task :setup_config, roles: :app do
sudo “ln -nfs #{current_path}/config/nginx.conf
/etc/nginx/sites-enabled/#{application}”
sudo “ln -nfs #{current_path}/config/unicorn_init.sh
/etc/init.d/unicorn_#{application}”
run “mkdir -p #{shared_path}/config”
put File.read(“config/database.example.yml”),
“#{shared_path}/config/database.yml”
puts “Now edit the config files in #{shared_path}.”
end
after “deploy:setup”, “deploy:setup_config”

task :symlink_config, roles: :app do
run “ln -nfs #{shared_path}/config/database.yml
#{release_path}/config/database.yml”
end
after “deploy:finalize_update”, “deploy:symlink_config”

desc “Make sure local git is in sync with remote.”
task :check_revision, roles: :web do
unless git rev-parse HEAD == git rev-parse origin/master
puts “WARNING: HEAD is not the same as origin/master”
puts “Run git push to sync changes.”
exit
end
end
before “deploy”, “deploy:check_revision”
end
— end code snippet —
62. edit config/nginx.conf
— begin code snippet —
upstream unicorn {
server unix:/tmp/unicorn.mayorio.sock fail_timeout=0;
}

server {
listen 80; # default deferred

server_name example.com

listen 443 ssl;
ssl_certificate /srv/ssl/nginx.pem;
ssl_certificate_key /srv/ssl/nginx.key;

server_name example.com;

root /home/deployer/apps/mayorio/current/public;

location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}

try_files $uri/index.html $uri @unicorn;
location @unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn;
}

error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}

— end code snippet —
63. edit config/unicorn.rb
— begin code snippet —
root = “/home/deployer/apps/mayorio/current”
working_directory root
pid “#{root}/tmp/pids/unicorn.pid”
stderr_path “#{root}/log/unicorn.log”
stdout_path “#{root}/log/unicorn.log”

listen “/tmp/unicorn.mayorio.sock”
worker_processes 2
timeout 30
— end code snippet —
64. edit config/unicorn_init.sh
— begin code snippet —
#!/bin/sh

BEGIN INIT INFO

Provides: unicorn

Required-Start: $remote_fs $syslog

Required-Stop: $remote_fs $syslog

Default-Start: 2 3 4 5

Default-Stop: 0 1 6

Short-Description: Manage unicorn server

Description: Start, stop, restart unicorn server for a specific

application.

END INIT INFO

set -e

Feel free to change any of the following variables for your app:

TIMEOUT=${TIMEOUT-60}
APP_ROOT=/home/deployer/apps/mayorio/current
PID=$APP_ROOT/tmp/pids/unicorn.pid
CMD=“cd $APP_ROOT; bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb
-E
production”
AS_USER=deployer
set -u

OLD_PIN=“$PID.oldbin”

sig () {
test -s “$PID” && kill -$1 cat $PID
}

oldsig () {
test -s $OLD_PIN && kill -$1 cat $OLD_PIN
}

run () {
if [ “$(id -un)” = “$AS_USER” ]; then
eval $1
else
su -c “$1” - $AS_USER
fi
}

case “$1” in
start)
sig 0 && echo >&2 “Already running” && exit 0
run “$CMD”
;;
stop)
sig QUIT && exit 0
echo >&2 “Not running”
;;
force-stop)
sig TERM && exit 0
echo >&2 “Not running”
;;
restart|reload)
sig HUP && echo reloaded OK && exit 0
echo >&2 “Couldn’t reload, starting ‘$CMD’ instead”
run “$CMD”
;;
upgrade)
if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
then
n=$TIMEOUT
while test -s $OLD_PIN && test $n -ge 0
do
printf ‘.’ && sleep 1 && n=$(( $n - 1 ))
done
echo

if test $n -lt 0 && test -s $OLD_PIN
then
  echo >&2 "$OLD_PIN still exists after $TIMEOUT seconds"
  exit 1
fi
exit 0

fi
echo >&2 “Couldn’t upgrade, starting ‘$CMD’ instead”
run “$CMD”
;;
reopen-logs)
sig USR1
;;
*)
echo >&2 “Usage: $0
<start|stop|restart|upgrade|force-stop|reopen-logs>”
exit 1
;;
esac
— end code snippet —
65. chmod +x config/unicorn_init.sh
66. git add .
67. git commit -m “deployment configs”
68. git push
69. cap deploy:setup
70. ssh [email protected]
71. cd apps/mayorio/shared/config
72. vim database.yml
73. remove everything except production
74. add password for production
75. add “host: localhost”
76. exit
77. cap deploy:cold
78. ssh [email protected]
79. sudo rm /etc/nginx/sites-enabled/default
80. sudo service nginx restart
81. sudo update-rc.d unicorn_mayorio defaults

— end original steps —

— final nginx.conf used —

upstream unicorn {
server unix:/tmp/unicorn.mayorio.sock fail_timeout=0;
}

server {
listen 80; # default deferred

server_name example.com

rewrite ^(.*) https://$host$1 permanent;

location ~ .(php|html)$ {
deny all;
}

access_log /dev/null;
error_log /dev/null;
}

server {
ssl on;

server_name example.com

listen 443 ssl;
ssl_certificate /srv/ssl/nginx.pem;
ssl_certificate_key /srv/ssl/nginx.key;

server_name example.com;

root /home/deployer/apps/mayorio/current/public;

location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}

try_files $uri/index.html $uri @unicorn;
location @unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn;
}

error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}

— end final nginx.conf —

Posted at Nginx Forum:

hey mlybrand,

You can check the redirecting behaviour with CURL. Use,
$ curl -I -k http://example.org # to get only the respond header and
dont
validate the ssl cert

Also, maybe try “return 301 https://$host$request_uri;” over “rewrite
^(.*) https://$host$1 permanent;”, and check the with curl, again.

Good luck and have a nice week!
~ed