Nginx Nextcloud too many redirects

5,976

You have a single server definition for both HTTP and HTTPS and, as you noticed, the lines:

if ($host = nextcloud.domain.com) {
    return 301 https://$server_name:443$request_uri;
} # managed by Certbot

are doing most of the damage. Since it is a 301 redirect, you browser will remember it until it is restarted.

Split the configuration of the two listening ports, so that the first lines are:

server {
    listen 80;
    server_name nextcloud.domain.com;

    return 301 https://$server_name$request_uri; # managed by Certbot
}

server {
    listen 443 ssl http2;
    server_name nextcloud.domain.com;
    # rest of the config

Edit: As you remarked, you can put both listen directives in one server block, however this will cause a redirect loop if your server is accessed directly using the nextcloud.domain.com. Cloudflare probably puts another proxy server between your clients and nginx and forwards requests using your IP instead of the domain name. So the loop remains hidden, but is is still there.

If you want to keep the single server block, you should consider changing the if condition to:

if ($scheme = http) {
    return 301 https://$server_name$request_uri;
} # managed by Certbot

However, in terms of clarity and performance, it is probably worse than two server blocks.

Share:
5,976

Related videos on Youtube

Georgi Stoyanov
Author by

Georgi Stoyanov

Updated on September 18, 2022

Comments

  • Georgi Stoyanov
    Georgi Stoyanov over 1 year

    I am trying to install Nextcloud on my Raspberry Pi.

    1. I have created an A record in Cloudflare with subdomain pointing to my Raspberry Pi IP address and configured the NGINX with certbot using the default configuration file in /etc/nginx/sites-available/nextcloud.
      1. I have created symlink in /etc/nginx/sites-enables and checked the NGINX configuration with sudo nginx -t and the configuration was all valid.
      2. I am getting successfully redirected to https but I am getting an error that I am getting too many redirects when I try to open the nextcloud.mydomain.com in a browser.

    This is my nextcloud config:

    upstream php-handler {
        server 127.0.0.1:9000;
        #server unix:/var/run/php/php7.3-fpm.sock;
    }
    
    server {
        listen 80;
        server_name nextcloud.domain.com;
    
        if ($host = nextcloud.domain.com) {
            return 301 https://$server_name:443$request_uri;
        } # managed by Certbot
    
        listen 443 ssl http2;
    
        ssl_certificate /etc/letsencrypt/live/nextcloud.domain.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/nextcloud.domain.com/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
        add_header Strict-Transport-Security "max-age=31536000" always; # managed by Certbot
        ssl_trusted_certificate /etc/letsencrypt/live/nextcloud.domain.com/chain.pem; # managed by Certbot
        ssl_stapling on; # managed by Certbot
        ssl_stapling_verify on; # managed by Certbot
    
        # Add headers to serve security related headers
        # Before enabling Strict-Transport-Security headers please read into this
        # topic first.
        #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
        #
        # WARNING: Only add the preload option once you read about
        # the consequences in https://hstspreload.org/. This option
        # will add the domain to a hardcoded list that is shipped
        # in all major browsers and getting removed from this list
        # could take several months.
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Permitted-Cross-Domain-Policies none;
        add_header Referrer-Policy no-referrer;
    
        # Remove X-Powered-By, which is an information leak
        fastcgi_hide_header X-Powered-By;
    
        # Path to the root of your installation
        root /var/www/html/nextcloud;
    
        location = /robots.txt {
            allow all;
            log_not_found off;
            access_log off;
        }
    
        # The following 2 rules are only needed for the user_webfinger app.
        # Uncomment it if you're planning to use this app.
        #rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
        #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
    
        # The following rule is only needed for the Social app.
        # Uncomment it if you're planning to use this app.
        #rewrite ^/.well-known/webfinger /public.php?service=webfinger last;
    
        location = /.well-known/carddav {
          return 301 $scheme://$host:$server_port/remote.php/dav;
        }
        location = /.well-known/caldav {
          return 301 $scheme://$host:$server_port/remote.php/dav;
        }
    
        # set max upload size
        client_max_body_size 512M;
        fastcgi_buffers 64 4K;
    
        # Enable gzip but do not remove ETag headers
        gzip on;
        gzip_vary on;
        gzip_comp_level 4;
        gzip_min_length 256;
        gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
        gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
    
        # Uncomment if your server is build with the ngx_pagespeed module
        # This module is currently not supported.
        #pagespeed off;
    
        location / {
            rewrite ^ /index.php;
        }
    
        location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
            deny all;
        }
        location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
            deny all;
        }
    
        location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) {
            fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
            set $path_info $fastcgi_path_info;
            try_files $fastcgi_script_name =404;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $path_info;
            fastcgi_param HTTPS on;
            # Avoid sending the security headers twice
            fastcgi_param modHeadersAvailable true;
            # Enable pretty urls
            fastcgi_param front_controller_active true;
            fastcgi_pass php-handler;
            fastcgi_intercept_errors on;
            fastcgi_request_buffering off;
        }
    
        location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
            try_files $uri/ =404;
            index index.php;
        }
    
        # Adding the cache control header for js, css and map files
        # Make sure it is BELOW the PHP block
        location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
            try_files $uri /index.php$request_uri;
            add_header Cache-Control "public, max-age=15778463";
            # Add headers to serve security related headers (It is intended to
            # have those duplicated to the ones above)
            # Before enabling Strict-Transport-Security headers please read into
            # this topic first.
            #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
            #
            # WARNING: Only add the preload option once you read about
            # the consequences in https://hstspreload.org/. This option
            # will add the domain to a hardcoded list that is shipped
            # in all major browsers and getting removed from this list
            # could take several months.
            add_header X-Content-Type-Options nosniff;
            add_header X-XSS-Protection "1; mode=block";
            add_header X-Robots-Tag none;
            add_header X-Download-Options noopen;
            add_header X-Permitted-Cross-Domain-Policies none;
            add_header Referrer-Policy no-referrer;
    
            # Optional: Don't log access to assets
            access_log off;
        }
    
        location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap)$ {
            try_files $uri /index.php$request_uri;
            # Optional: Don't log access to other assets
            access_log off;
        }
    }
    

    This is the curl output:

    curl -i http://nextcloud.domain.com
    HTTP/1.1 301 Moved Permanently
    Date: Mon, 03 Feb 2020 20:54:01 GMT
    Transfer-Encoding: chunked
    Connection: keep-alive
    Cache-Control: max-age=3600
    Expires: Mon, 03 Feb 2020 21:54:01 GMT
    Location: https://nextcloud.domain.com/
    X-Content-Type-Options: nosniff
    Server: cloudflare
    CF-RAY: 55f74c364a04d8d1-AMS
    

    And when I try to access the https version:

    curl -i https://nextcloud.domain.com 
    
    HTTP/2 301 
    date: Mon, 03 Feb 2020 20:55:45 GMT
    content-type: text/html
    set-cookie: __cfduid=d160f56e9986d2c7037ff81e233fcad0e1580763345; expires=Wed, 04-Mar-20 20:55:45 GMT; path=/; domain=.domain.com; HttpOnly; SameSite=Lax; Secure
    location: https://nextcloud.domain.com:443/
    strict-transport-security: max-age=15552000; includeSubDomains; preload
    x-content-type-options: nosniff
    x-xss-protection: 1; mode=block
    x-robots-tag: none
    x-download-options: noopen
    x-permitted-cross-domain-policies: none
    referrer-policy: no-referrer
    cf-cache-status: DYNAMIC
    expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
    server: cloudflare
    cf-ray: 55f74ebf5ed62bfe-AMS
    
    <html>
    <head><title>301 Moved Permanently</title></head>
    <body bgcolor="white">
    <center><h1>301 Moved Permanently</h1></center>
    <hr><center>nginx/1.14.2</center>
    </body>
    </html>
    

    I have replaced my domain name with domain.

    In the /var/log/nginx/access.log I am getting a lot of lines with the redirect and HTTP codes: 301 and 185.

    If I delete the redirect return 301 https://$server_name:443@request_uri; line I am still getting redirected to https and I don't have any idea why.

    For the record, I used to have lighttpd in the past installed on the Raspberry Pi but I have uninstalled it before installing the NGINX.

  • Georgi Stoyanov
    Georgi Stoyanov over 4 years
    actually, I have just fixed my issue and it was related to the Cloudflare DNS configuration. There I have enabled re-write HTTP to HTTPS and this caused the problem. Additionally, I have enabled the DNS to be proxied. Since I fixed it I am not experiencing any more redirects. Plus listening on both ports in the same server block is also OK according to the official NGINX documentation: nginx.org/en/docs/http/… . If I check the output with curl I am seeing one 301 redirect HTTP->HTTPS and then 302 to the login page and 200 for login
  • Piotr P. Karwasz
    Piotr P. Karwasz over 4 years
    You can't configure a HTTP redirect with DNS so Cloudflare probably points your domain to their servers, which act as a reverse proxy. Is cloudflare.domain.com pointing to your IP? If that were the case your configuration would cause a redirect loop. I edited the answer with more details.
  • Georgi Stoyanov
    Georgi Stoyanov over 4 years
    This is exactly what happened, yes, they were proxying the requests to my domain through their IPs