Cross-posted to: https://sh.itjust.works/post/14975166


Solution

I’m still not really sure exactly what the root cause of the issue was (I would appreciate it if someone could explain it to me), but I disabled HTTPS on the Nextcloud server

nextcloud.disable-https

and, all of a sudden, it started working. My Caddyfile simply contains the following:

nextcloud.domain.com {
    server-LAN-ip:80
}

Original Post

I am trying to upgrade my existing Nextcloud server (installed as a Snap) so that it is sitting behind a reverse proxy. Originally, The Nextcloud server handled HTTPS with Let’s Encrypt at domain.com; now, I would like for Caddy to handle HTTPS with Let’s Encrypt at nextcloud.domain.com and to forward the traffic to the Nextcloud server.

With my current setup, I am encountering an error where it is saying 301 Moved Permanently. Does anyone have any ideas on how to fix or troubleshoot this?

Caddyfile:

https://nextcloud.domain.com {
        reverse_proxy 192.168.1.182:443
        header / Strict-Transport-Security max-age=31536000;
}

And here is the output of curl -v https://nextcloud.domain.com/:

* Host nextcloud.domain.com:443 was resolved.
* IPv6: (none)
* IPv4: public-ip
*   Trying public-ip:443...
* Connected to nextcloud.domain.com (public-ip) port 443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_CHACHA20_POLY1305_SHA256 / x25519 / id-ecPublicKey
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=nextcloud.domain.com
*  start date: Feb 21 06:09:01 2024 GMT
*  expire date: May 21 06:09:00 2024 GMT
*  subjectAltName: host "nextcloud.domain.com" matched cert's "nextcloud.domain.com"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
*   Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://nextcloud.domain.com/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: nextcloud.domain.com]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.6.0]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: nextcloud.domain.com
> User-Agent: curl/8.6.0
> Accept: */*
> 
< HTTP/2 301 
< alt-svc: h3="public-ip:443"; ma=2592000
< content-type: text/html; charset=iso-8859-1
< date: Wed, 21 Feb 2024 07:45:34 GMT
< location: https://nextcloud.domain.com:443/
< server: Caddy
< server: Apache
< strict-transport-security: max-age=31536000;
< content-length: 250
< 


301 Moved Permanently

<h1>Moved Permanently</h1>
<p>The document has moved here.</p>

* Connection #0 to host nextcloud.domain.com left intact
  • fluckx@lemmy.world
    link
    fedilink
    English
    arrow-up
    3
    ·
    edit-2
    9 months ago

    It’s looping back to itself? Location header is pointing back to itself.

    Is it possible your backend is sending back an http 301 redirect back to caddy, which forwards it to your browser?

    Possibly some old configuration on your backend from the letsencrypt beforehand? Can you check the logs from your backend and see what they’re sending back?

    I’m assuming the request might replace the host with the IP on your reverse Proxy and that your next cloud backend is replying with a redirect to https://nextcloud.domain.com:443

    Edit: I think this is the most incoherent message I wrote to date.

    I think your reverse Proxy is forwarding the request to your next cloud, but replacing the Host header with the IP you specified as reverse Proxy. As a result the request arrives at your next cloud with the IP as “host”.

    Your next cloud installation is then sending back a 301 redirect to tell the client that they should connect to https://nextcloud.domain.com. this arrives through caddy at your browser, goes through the same loop until you’ve reached the max redirects.

    Have a look at your next cloud backend http logs to see what requests are arriving there and what HOST( http header ) it’s trying to connect to on that IP.

    • Kalcifer@sh.itjust.worksOP
      link
      fedilink
      English
      arrow-up
      1
      ·
      9 months ago

      Possibly some old configuration on your backend from the letsencrypt beforehand?

      Are you referring to the original HTTPS configuration for Let’s Encrypt for domain.com? I haven’t disabled that yet. Should I entirely disable HTTPS for the Nextcloud server?

      Have a look at your next cloud backend http logs to see what requests are arriving there and what HOST( http header ) it’s trying to connect to on that IP.

      I’m not entriely sure where to find what you are referring to. I checked the Apache logs for Nextcloud, and I didn’t find anything.

  • proton_lynx@lemmy.world
    link
    fedilink
    English
    arrow-up
    3
    ·
    9 months ago

    301 Moved Permanently is usually not something that requires user intervention. Most browsers should automatically detect the 301 Moved Permanently response code and redirect automatically. What happens when you run cURL with the --location flag?

    curl --location https://nextcloud.domain.com
    
    • Kalcifer@sh.itjust.worksOP
      link
      fedilink
      English
      arrow-up
      1
      ·
      9 months ago

      Running curl --location https://nextcloud.domain.com results in

      curl: (47) Maximum (50) redirects followed
      
      • proton_lynx@lemmy.world
        link
        fedilink
        English
        arrow-up
        2
        ·
        9 months ago

        More than 50 redirects? Hmm, that looks weird. What is the output when you run wget --spider https://nextcloud.domain.com? Could you try enabling cookies for cURL and pasting the contents of the cookiefile here?

        curl --cookie cookiefile --cookie-jar cookiefile --location https://nextcloud.domain.com
        
        • Kalcifer@sh.itjust.worksOP
          link
          fedilink
          English
          arrow-up
          1
          ·
          edit-2
          9 months ago

          Here is the output of wget --spider https://nextcloud.domain.com:

          Spider mode enabled. Check if remote file exists.
          --2024-02-21 09:20:41--  https://nextcloud.domain.com/
          Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'
          Resolving nextcloud.domain.com (nextcloud.domain.com)... public-ip
          Connecting to nextcloud.domain.com (nextcloud.domain.com)|public-ip|:443... connected.
          HTTP request sent, awaiting response... 301 Moved Permanently
          Location: https://nextcloud.domain.com:443/ [following]
          Spider mode enabled. Check if remote file exists.
          --2024-02-21 09:20:46--  https://nextcloud.domain.com/
          Connecting to nextcloud.domain.com (nextcloud.domain.com)|public-ip|:443... connected.
          HTTP request sent, awaiting response... 301 Moved Permanently
          Location: https://nextcloud.domain.com:443/ [following]
          Spider mode enabled. Check if remote file exists.
          --2024-02-21 09:20:46--  https://nextcloud.domain.com/
          Connecting to nextcloud.domain.com (nextcloud.domain.com)|public-ip|:443... connected.
          HTTP request sent, awaiting response... 301 Moved Permanently
          Location: https://nextcloud.domain.com:443/ [following]
          Spider mode enabled. Check if remote file exists.
          [...]
          [I deleted a bunch of repetitions]
          [...]
          --2024-02-21 09:20:48--  https://nextcloud.domain.com/
          Connecting to nextcloud.domain.com (nextcloud.domain.com)|public-ip|:443... connected.
          HTTP request sent, awaiting response... 301 Moved Permanently
          Location: https://nextcloud.domain.com:443/ [following]
          20 redirections exceeded.
          

          And here is the contents of the cookie file (it is empty):

          # Netscape HTTP Cookie File
          # https://curl.se/docs/http-cookies.html
          # This file was generated by libcurl! Edit at your own risk.
          
          
          
          • proton_lynx@lemmy.world
            link
            fedilink
            English
            arrow-up
            3
            ·
            edit-2
            9 months ago

            Yep, definitely something wrong with the webserver 😅 Can you try this configuration?

            https://nextcloud.domain.com {
                    reverse_proxy 192.168.1.182:443 {
                            header_up Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
                            header_up X-Forwarded-Proto {scheme}
                            header_up X-Forwarded-For {remote}
                            header_up X-Real-IP {remote}
                    }
            }
            

            You said that “originally, the Nextcloud server handled HTTPS with Let’s Encrypt at domain.com” and now you are redirecting to 192.168.1.182 on port 443. Is this Nextcloud server still serving HTTPS with Let’s Encrypt for domain.com?

            I’m asking because if you are using Caddy in front of that HTTPS webserver as a reverse-proxy, you will need to override the Host header with the configured upstream address. Here’s the documentation. I think it would be something like this (?):

            https://nextcloud.domain.com {
                    reverse_proxy domain.com:443 {
                            header_up Host {upstream_hostport}
                            header_up Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
                            header_up X-Forwarded-Proto {scheme}
                            header_up X-Forwarded-For {remote}
                            header_up X-Real-IP {remote}
                    }
            }
            
            • Kalcifer@sh.itjust.worksOP
              link
              fedilink
              English
              arrow-up
              1
              ·
              edit-2
              9 months ago

              Your first configuration results in the following when I access nextcluod.domain.com from both within and outside the LAN:

              400 Bad Request
              Bad Request
              Your browser sent a request that this server could not understand.
              Reason: You're speaking plain HTTP to an SSL-enabled server port.
               Instead use the HTTPS scheme to access this URL, please.
              

              This is an interesting response, because it’s what I see when I try to access the server from 192.168.1.182:443 from within the LAN. Which, I assume, is to be expected when a port has TLS enabled – one should access it from 192.168.1.182:80 instead; however, when I modify your suggestion to be from port 80, rather than port 443, it results in the usual

              301 Moved Permanently
              Moved Permanently
              The document has moved https://nextcloud.domain.com:443/
              

              Your second configuration results in the following when I access nextcloud.domain.com from both within and outside the LAN:

              Client sent an HTTP request to an HTTPS server.
              

              Side note: I do still have the original HTTPS setup with Let’s Encrypt enabled on the Nextcloud server for domain.com. Is that causing the issue? I’d rather not disable that unless I need to, at the moment.