ruby-on-rails-3nginxamazon-ec2lets-encrypt

SSL Configuration Issue: Website Redirects Too Many Times and CSRF Token Mismatch


I am hosting a Ruby on Rails application on an AWS EC2 instance running Ubuntu, utilizing Let's Encrypt for SSL. In my Nginx configuration (/etc/nginx/sites-available/example), the redirection from HTTP to HTTPS works correctly when the config.force_ssl = true line in config/environments/production.rb is commented out.

Below is a snippet of the Nginx configuration:

server {
    listen 80;
    server_name example.com www.example.com;
    # Redirect HTTP to HTTPS
    # return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com www.example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

However, when I uncomment this line, the website fails to load, resulting in an "ERR_TOO_MANY_REDIRECTS" error in the browser. But if I comment out the config.force_ssl = true line, the application doesn't redirect properly to the HTTPS site, resulting in the following error in the rails logs:

HTTP Origin header (https://example.com) didn't match request.base_url (http://example.com)

In attempting to resolve the redirection issue while maintaining SSL enforcement in my Ruby on Rails application, I initially commented out the config.force_ssl = true line in the config/environments/production.rb file. This successfully prevented the "ERR_TOO_MANY_REDIRECTS" error, but it resulted in improper redirection to the HTTPS site, as evidenced by the Rails logs showing an HTTP Origin header mismatch error.

To further troubleshoot and address the issue, I examined the Nginx configuration (/etc/nginx/sites-available/example). Initially, the redirection from HTTP to HTTPS was achieved by uncommenting the return 301 https://$host$request_uri; line in the server block listening on port 80. However, when the config.force_ssl = true line was uncommented, it led to the aforementioned redirect loop.

To summarize, I tried adjusting the Nginx configuration and toggling the config.force_ssl setting. My expectation was to successfully enforce SSL while ensuring proper redirection without encountering the "ERR_TOO_MANY_REDIRECTS" error or CSRF token mismatch issues. However, the attempts resulted in either the redirect loop or improper HTTPS redirection. I seek guidance on how to rectify this issue and achieve the desired outcome.


Solution

  • After numerous attempts to adjust my nginx configuration to resolve the "ERR_TOO_MANY_REDIRECTS" error and achieve proper HTTPS redirection while enforcing SSL in my Ruby on Rails application, I finally discovered the root cause of the issue. By default in Rails 7.2 the config.force_ssl = true line in config/environments/production.rb is set to true, which helps to enforce SSL within the Rails application. But this led to a redirect loop, indicating a conflict between my Nginx setup and Rails in handling SSL redirection.

    However, upon further investigation and experimentation, I found that uncommenting the config.assume_ssl = true line in config/environments/production.rb effectively resolved the issue. This configuration setting instructs Rails to assume that all incoming requests are secure, aligning with the fact that my application access is already being handled through an SSL-terminating reverse proxy (Nginx).