Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Can't enable or disable apps after upgrade to v28.0.4 #44685

Closed
5 of 8 tasks
quenenni opened this issue Apr 5, 2024 · 34 comments · Fixed by #44939
Closed
5 of 8 tasks

[Bug]: Can't enable or disable apps after upgrade to v28.0.4 #44685

quenenni opened this issue Apr 5, 2024 · 34 comments · Fixed by #44939
Assignees
Labels

Comments

@quenenni
Copy link

quenenni commented Apr 5, 2024

⚠️ This issue respects the following points: ⚠️

Bug description

Since I upgraded a cloud from v27.1.3 to v28.0.4, I can't enable /disable any of the apps in the cloud.
Every attempt shows me this error msg:
"This app cannot be enabled because it makes the server unstable"

Steps to reproduce

  1. Go to apps page
  2. Enable / disable any of the apps

Expected behavior

Apps are activated / desactivated.

Installation method

Community Manual installation with Archive

Nextcloud Server version

28

Operating system

Debian/Ubuntu

PHP engine version

PHP 8.1

Web server

Nginx

Database engine version

MariaDB

Is this bug present after an update or on a fresh install?

Upgraded to a MAJOR version (ex. 22 to 23)

Are you using the Nextcloud Server Encryption module?

Encryption is Disabled

What user-backends are you using?

  • Default user-backend (database)
  • LDAP/ Active Directory
  • SSO - SAML
  • Other

Configuration report

{
    "system": {
        "trusted_domains": [
            "cloud.yyyyy.be",
            "cloud.yyyyy2.be"
        ],
        "activity_expire_days": 30,
        "appstoreenabled": true,
        "appstore.experimental.enabled": false,
        "auth.bruteforce.protection.enabled": true,
        "default_phone_region": "be",
        "datadirectory": "***REMOVED SENSITIVE VALUE***",
        "data-fingerprint": "",
        "dbhost": "***REMOVED SENSITIVE VALUE***",
        "dbname": "***REMOVED SENSITIVE VALUE***",
        "dbpassword": "***REMOVED SENSITIVE VALUE***",
        "dbtableprefix": "",
        "dbtype": "mysql",
        "dbuser": "***REMOVED SENSITIVE VALUE***",
        "default_language": "fr",
        "hashingCost": 10,
        "htaccess.RewriteBase": "\/",
        "installed": true,
        "instanceid": "***REMOVED SENSITIVE VALUE***",
        "integrity.check.disabled": true,
        "localstorage.allowsymlinks": true,
        "logfile": "\/var\/log\/nextcloud\/yyyyy.log",
        "loglevel": 2,
        "logtimezone": "Europe\/Brussels",
        "mail_domain": "***REMOVED SENSITIVE VALUE***",
        "mail_from_address": "***REMOVED SENSITIVE VALUE***",
        "mail_smtphost": "***REMOVED SENSITIVE VALUE***",
        "mail_smtpmode": "sendmail",
        "maintenance": false,
        "memcache.distributed": "\\OC\\Memcache\\Redis",
        "memcache.local": "\\OC\\Memcache\\APCu",
        "memcache.locking": "\\OC\\Memcache\\Redis",
        "redis": {
            "host": "***REMOVED SENSITIVE VALUE***",
            "port": 0,
            "dbindex": 1,
            "timeout": 1.5
        },
        "minimum.supported.desktop.version": "2.1.0",
        "mysql.utf8mb4": true,
        "passwordsalt": "***REMOVED SENSITIVE VALUE***",
        "preview_libreoffice_path": "\/usr\/bin\/libreoffice",
        "preview_max_filesize_image": 10,
        "secret": "***REMOVED SENSITIVE VALUE***",
        "simpleSignUpLink.shown": false,
        "trashbin_retention_obligation": "auto, 30",
        "updatechecker": true,
        "upgrade.disable-web": true,
        "version": "28.0.4.1",
        "versions_retention_obligation": "auto, 90",
        "overwrite.cli.url": "https:\/\/cloud.yyyyy.be\/",
        "theme": "",
        "mail_sendmailmode": "smtp",
        "maintenance_window_start": 2,
        "app_install_overwrite": [
            "bbb"
        ],
        "trusted_proxies": "***REMOVED SENSITIVE VALUE***"
    }
}

List of activated Apps

Enabled:
  - activity: 2.20.0
  - appointments: 2.0.4
  - bookmarks: 13.1.3
  - calendar: 4.6.7
  - cloud_federation_api: 1.11.0
  - comments: 1.18.0
  - contacts: 5.5.3
  - dav: 1.29.1
  - federatedfilesharing: 1.18.0
  - files: 2.0.0
  - files_accesscontrol: 1.18.0
  - files_automatedtagging: 1.18.0
  - files_pdfviewer: 2.9.0
  - files_reminders: 1.1.0
  - files_sharing: 1.20.0
  - files_trashbin: 1.18.0
  - files_versions: 1.21.0
  - forms: 4.1.1
  - impersonate: 1.15.0
  - lookup_server_connector: 1.16.0
  - notifications: 2.16.0
  - oauth2: 1.16.3
  - ownpad: 0.10.0
  - password_policy: 1.18.0
  - photos: 2.4.0
  - polls: 7.0.2
  - privacy: 1.12.0
  - provisioning_api: 1.18.0
  - related_resources: 1.3.0
  - richdocuments: 8.3.3
  - settings: 1.10.1
  - sharebymail: 1.18.0
  - socialsharing_email: 3.1.0
  - systemtags: 1.18.0
  - text: 3.9.1
  - theming: 2.3.0
  - timetracker: 0.0.82
  - twofactor_backupcodes: 1.17.0
  - user_status: 1.8.1
  - viewer: 2.2.0
  - workflowengine: 2.10.0
Disabled:
  - admin_audit: 1.18.0 (installed 1.13.0)
  - bbb: 2.5.0 (installed 2.5.0)
  - bruteforcesettings: 2.8.0 (installed 2.4.0)
  - circles: 28.0.0 (installed 22.1.1)
  - contactsinteraction: 1.9.0 (installed 1.3.0)
  - dashboard: 7.8.0 (installed 7.0.0)
  - encryption: 2.16.0
  - federation: 1.18.0 (installed 1.13.0)
  - files_external: 1.20.0 (installed 1.15.0)
  - files_markdown: 2.4.1 (installed 2.4.1)
  - files_rightclick: 1.6.0 (installed 1.6.0)
  - firstrunwizard: 2.17.0 (installed 2.1)
  - keeweb: 0.6.17 (installed 0.6.17)
  - logreader: 2.13.0 (installed 2.0.0)
  - nextcloud_announcements: 1.17.0 (installed 1.16.0)
  - onlyoffice: 9.0.0 (installed 9.0.0)
  - recommendations: 2.0.0 (installed 1.1.0)
  - serverinfo: 1.18.0 (installed 1.18.0)
  - support: 1.11.1 (installed 1.5.0)
  - survey_client: 1.16.0 (installed 1.11.0)
  - suspicious_login: 6.0.0
  - twofactor_totp: 10.0.0-beta.2
  - updatenotification: 1.18.0 (installed 1.1.1)
  - user_ldap: 1.19.0 (installed 1.15.0)
  - weather_status: 1.8.0 (installed 1.2.0)

Nextcloud Signing status

No errors have been found.

Nextcloud Logs

Nothing in Nextcloud log with loglevel to 0

Additional info

I upgrade other clouds on another server from v27.1.3 to v28.0.4 and there, no problem to enable / disable the apps.
Server has the same configuration as the one with the problems (Debian / php / mariadb / nginx).

The only thing (I see) that is different, is the Haproxy I'm using in front of Nginx on the server with the problems.

The Nginx log shows the POST request to enable the app and gives a 200 return code:

1.2.3.4 - - [05/Apr/2024:15:58:51 +0200] "POST /settings/apps/enable HTTP/2.0" 200 52 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:121.0) Gecko/20100101 Firefox/121.0" "-" "cloud.yyyyy.be"

In the Firefox console, I have this error each time I try to enable / disable an app:

Content-Security-Policy : Les paramètres de la page ont empêché le chargement d’une ressource à https://cloud.yyyyy.be:4431/apps/files/ (« connect-src »).

My haproxy config is using the tcp mode, so https is managed by Nginx:

frontend https_in
    bind *:443
    mode tcp
    option tcplog

    tcp-request connection track-sc0 src table gatekeeper

    acl uncivilized src_conn_rate(gatekeeper) ge 600
    acl uncivilized src_conn_cur(gatekeeper)  ge  400
    acl triggerban  src_inc_gpc0(gatekeeper)  gt   0
    acl banned      src_get_gpc0(gatekeeper)  gt   0

    tcp-request connection silent-drop if uncivilized triggerban
    tcp-request connection silent-drop if banned

    tcp-request inspect-delay 5s
    tcp-request content accept if { req_ssl_hello_type 1 }

    acl bon_domaine req.ssl_sni,map_dom(/etc/haproxy/routes.map) -m found
    acl ip_test src -f /etc/haproxy/ip_test.lst

    tcp-request content reject if !ip_test !bon_domaine

    use_backend https_test if ip_test
    use_backend %[req.ssl_sni,map(/etc/haproxy/routes.map)]

backend https_test
    mode tcp
    option ssl-hello-chk

    server Cloud2 lan.cloud2:4431 send-proxy check inter 4s downinter 4s fall 2 rise 2 fastinter 2 slowstart 30s weight 100

backend https_srv_1
    mode tcp
    option ssl-hello-chk

    server Cloud1 lan.cloud1:4431 send-proxy check inter 4s downinter 4s fall 2 rise 2 fastinter 2 slowstart 30s weight 100

backend https_srv_2
    mode tcp
    option ssl-hello-chk

    server Cloud2 lan.cloud2:4431 send-proxy check inter 4s downinter 4s fall 2 rise 2 fastinter 2 slowstart 30s weight 100

The content of the file routes.map is:

# DomainName       BackendName
cloud.aaaaa.be https_srv_1
ncloud.bbbbb.be https_srv_2
...

My Nginx config is very much like the one from the doc (https://docs.nextcloud.com/server/latest/admin_manual/installation/nginx.html):

server {
    server_name cloud.yyyyy.be;

    include /etc/nginx/sites-available/conf_communes_clouds_ssl.conf;

    ssl_certificate /etc/letsencrypt/live/cloud.yyyyy.be/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cloud.yyyyy.be/privkey.pem;

    root /srv/nextcloud/instances/yyyyy/;

    server_tokens off; ## Don't show the nginx version number, a security best practice

    client_max_body_size 10G;
    client_body_timeout 300s;
    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;

    client_body_buffer_size 512k;

    add_header Referrer-Policy                   "no-referrer"       always;
    add_header X-Content-Type-Options            "nosniff"           always;
    add_header X-Frame-Options                   "SAMEORIGIN"        always;
    add_header X-Permitted-Cross-Domain-Policies "none"              always;
    add_header X-Robots-Tag                      "noindex, nofollow" always;
    add_header X-XSS-Protection                  "1; mode=block"     always;

    fastcgi_hide_header X-Powered-By;

    include mime.types;
    types {
#      text/javascript mjs; # déjà présent ds mime.types
      application/wasm wasm;
    }

    index index.php index.html /index.php$request_uri;

    access_log /var/log/nginx/access.log ndd_inclus;
    error_log /var/log/nginx/error.log;

    location = / {
        if ( $http_user_agent ~ ^DavClnt ) {
            return 302 $scheme://$host/remote.php/webdav/$is_args$args;
        }
    }

    location = /robots.txt {
      allow all;
      log_not_found off;
      access_log off;
    }

    location ^~ /.well-known {
        location = /.well-known/carddav { return 301 /remote.php/dav/; }
        location = /.well-known/caldav  { return 301 /remote.php/dav/; }

        location /.well-known/acme-challenge    { try_files $uri $uri/ =404; }
        location /.well-known/pki-validation    { try_files $uri $uri/ =404; }

        return 301 /index.php$request_uri;
    }

    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)  { return 404; }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console)                { return 404; }

    location ~ \.php(?:$|/) {
        # Ajout du strict-transport-security ici sinon Nc ne le recevait pas
        add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";

        rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /index.php$request_uri;

        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;

        #fastcgi_param modHeadersAvailable true;         # Avoid sending the security headers twice
        fastcgi_param front_controller_active true;     # Enable pretty urls
        fastcgi_pass php-handler-8.1;

        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;

        fastcgi_max_temp_file_size 0;
    }

    location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map|ogg|flac)$ {
        try_files $uri /index.php$request_uri;

        add_header Cache-Control                     "public, max-age=15778463$asset_immutable";
        add_header Referrer-Policy                   "no-referrer"       always;
        add_header X-Content-Type-Options            "nosniff"           always;
        add_header X-Frame-Options                   "SAMEORIGIN"        always;
        add_header X-Permitted-Cross-Domain-Policies "none"              always;
        add_header X-Robots-Tag                      "noindex, nofollow" always;
        add_header X-XSS-Protection                  "1; mode=block"     always;
        access_log off;     # Optional: Don't log access to assets
    }

    location ~ \.woff2?$ {
        try_files $uri /index.php$request_uri;
        expires 7d;         # Cache-Control policy borrowed from `.htaccess`
        access_log off;     # Optional: Don't log access to assets
    }

    location /remote {
        return 301 /remote.php$request_uri;
    }

    location / {
        try_files $uri $uri/ /index.php$request_uri;
    }
}
@quenenni quenenni added 0. Needs triage Pending check for reproducibility or if it fits our roadmap bug labels Apr 5, 2024
@quenenni
Copy link
Author

quenenni commented Apr 5, 2024

I forgot to mention that I can enable / disabel apps with the occ command and the cloud and apps are working good (as mush as I can tell).

The problem is only from the web interface.

@joshtrichards
Copy link
Member

joshtrichards commented Apr 5, 2024

Content-Security-Policy : Les paramètres de la page ont empêché le chargement d’une ressource à https://cloud.yyyyy.be:4431/apps/files/ (« connect-src »).

This is the source of your seeing the unstable error message. The app stability check runs from your browser and CSP is blocking this check so it by definition fails. I suspect you don't wish the :4431 to be in your URL.

Set the appropriate overwrite*
parameters in your config (i.e. without the port) and see if the problem goes away.

I suspect it will, but let us know if not.

@quenenni
Copy link
Author

quenenni commented Apr 5, 2024

Very good catch. I completely missed that wrong port number there. Thank you.
Indeed, it should be 443 or no port.

I set all the overwrite* params, but no luck, the errors are still the same.

  'overwrite.cli.url' => 'https://cloud.yyyyy.be/',   <- already present
  'overwriteprotocol' => 'https',
  'overwritehost' => 'cloud.yyyyy.be:443',
  'overwritewebroot'  => '/',

I tried to play with the option fastcgi_param SERVER_PORT 443; in my Nginx vhost, but also no luck (I remebered having a similar issue couple years ago and that param fixed it at the time).

@joshtrichards
Copy link
Member

@brunoscota
Copy link

same to me and I already did what @quenenni also did with no luck

@Masgalor
Copy link

I have the same problem since v28.0.4 and I can confirm this is because of a CSP error.

In my case overwriteprotocol => https seems to be ignored.
The app-install-page queries http://<domain>/apps/files/ that fails because of the policy connect-src self, that would require https://<domain>/apps/files/.

@philipwilk
Copy link

philipwilk commented Apr 14, 2024

On nixos and I also have this issue, I get this CSP error in the firefox console when I try enable any app:
image
Don't know why it's trying to talk to that url 🤷🏻‍♀️

@heshunme
Copy link

I found such a CSP error in my browser's console too. It seems some specific part that controls overwriting the URL is malfunctioning after v28.0.4.

@susnux susnux self-assigned this Apr 15, 2024
@joergmschulz
Copy link

true for 49 rc 4 as well

@susnux
Copy link
Contributor

susnux commented Apr 16, 2024

The URL is generated from the frontend, so the overwriteprotocol is not taken into account, but the current protocol is used.
But in this specific case the protocol is never set, the request is done to a relative URL, so this should always work.

@susnux
Copy link
Contributor

susnux commented Apr 16, 2024

But those of you that have Nextcloud installed into the root of your (sub) domain, could you try setting overwritewebroot to an empty string?
Please report if you have currently overwritewebroot set and if it works if you set overwritewebroot => ''.

@brunoscota
Copy link

But those of you that have Nextcloud installed into the root of your (sub) domain, could you try setting overwritewebroot to an empty string? Please report if you have currently overwritewebroot set and if it works if you set overwritewebroot => ''.

I did and no luck.

@uncle-betty
Copy link

@susnux - regarding the URL, let me share the following observation about the requests that happen right after I push an app's activation button:

So, the first GET uses HTTPS, but it just redirects to almost the same URL, but with HTTP. Note that the redirect does add a / to the end of the URL.

And it's that second (HTTP-based) GET that fails.

Unfortunately, the Nextcloud installation that I'm dealing with is hosted, so I don't have access to the Nginx configuration. But I assume than Nginx, just like Apache's mod_dir, has an option to correct directory URLs that lack the final /.

Maybe that has something to do with it? Maybe things would work, if the first GET had the trailing / and would thus succeed without a redirect?

@dankar
Copy link

dankar commented Apr 19, 2024

I'm having the same issue, and I'm using the community helm chart (nextcloud/helm here on github).

What I'm seeing is what @uncle-betty is describing. The GET to https://domain/apps/files gets redirected to http://domain/apps/files/ (with a 301, and note that it redirects to http and not https). None of the overwrite options is making any difference.

From the nextcloud-nginx and nextcloud-fpm containers I can see that it seems like nextcloud-nginx is the one responding with the 301. I don't see anything other than 200 responses from the nextcloud-fpm container.

Curiously I can't find any redirects in the nginx config that should cause this.

It can be solved by adding "absolute_redirect off;" in the server section in the nginx config, but I don't know what the root cause is. (I.e. I'm not sure what causes the redirect in the first place)

@susnux
Copy link
Contributor

susnux commented Apr 19, 2024

So this is not a bug, but a configuration issue, you are using a proxy / reverse proxy that does not correctly rewrites redirects.

This sounds like following problem:

  • Your webserver is running on HTTP
  • Your webserver adds a 301 with added / (Apache does this with the default config)
  • You use a reverse proxy with HTTPS
  • You have not configured your reverse proxy to correctly adjust redirects

So in this case your webserver returns a 301 with http://server/apps/files/, your reverse proxy does not rewrite it to 301 with https://server/apps/files/.

Solution: Ensure redirects are rewritten using the correct protocol on your reverse proxy.
For NGinx e.g. ensure to use proxy_redirect.
Note: If you use proxy_pass this is the default, EXCEPT you use variables in the proxy_pass.

For other reverse proxies, refer to their documentation.

If you can not access the reverse proxy, maybe disabling DirectorySlash of Apache could help.

@susnux susnux closed this as not planned Won't fix, can't repro, duplicate, stale Apr 19, 2024
@joergmschulz
Copy link

@susnux Not so sure about this. The feature worked perfectly in the *3 version and stopped working in the *4 version without any changes in the proxy (traefik) settings. Please review.

@dankar
Copy link

dankar commented Apr 19, 2024

So this is not a bug, but a configuration issue, you are using a proxy / reverse proxy that does not correctly rewrites redirects.

This sounds like following problem:

* Your webserver is running on HTTP

* Your webserver adds a 301 with added `/` (Apache does this with the default config)

* You use a reverse proxy with HTTPS

* You have not configured your reverse proxy to correctly adjust redirects

So in this case your webserver returns a 301 with http://server/apps/files/, your reverse proxy does not rewrite it to 301 with https://server/apps/files/.

Solution: Ensure redirects are rewritten using the correct protocol on your reverse proxy. For NGinx e.g. ensure to use proxy_redirect. Note: If you use proxy_pass this is the default, EXCEPT you use variables in the proxy_pass.

For other reverse proxies, refer to their documentation.

If you can not access the reverse proxy, maybe disabling DirectorySlash of Apache could help.

While I can agree it's a configuration issue, it's an issue with the recommended nginx configuration. Perhaps a documentation bug, as well as a bug for the helm chart (since the helm chart bundles the recommended configuration as default)?

In any case, I'm not sure I agree that it's the job of the reverse proxy to fix it. It's just for this very specific request things seems to go wrong. But I suppose that's a matter of taste. (I'm fairly sure Traefik needs third party plugins to rewrite responses. It's not something I've ever needed to do)

@susnux
Copy link
Contributor

susnux commented Apr 19, 2024

Not so sure about this. The feature worked perfectly in the *3 version and stopped working in the *4 version without any changes in the proxy (traefik) settings. Please review.

Yes because the check was not running. We fixed this for 28.0.4.
And as you can see from the requests the protocol is incorrect, you can test it by your own with curl -X GET -i https://your-sever/apps/files.

In any case, I'm not sure I agree that it's the job of the reverse proxy to fix it. It's just for this very specific request things seems to go wrong

No and it is, Nextcloud does not trigger the redirect here. It is triggered by your webserver, then the reverse proxy must handle the redirect correctly, or you disable those redirects on the webserver - what ever you prefer.
The webserver does not know about the reverse proxy, so the reverse proxy needs to fixup any redirects directly coming from the webserver.


You could also set up the rewrite base like here:
https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/config_sample_php_parameters.html#htaccess-rewritebase

If you set it to / the index.php will be removed and Nextcloud sets DirectorySlash off, this is probably why you do not suffer this issue when using the community docker image.

@susnux
Copy link
Contributor

susnux commented Apr 19, 2024

Yes, that was my conclusion as well, but my point was just that my webserver is nginx configured exactly as recommended by the Nextcloud documentation.

From NGinx documentation:

If a location is defined by a prefix string that ends with the slash character, and requests are processed by one of proxy_pass, fastcgi_pass [...] then the special processing is performed. In response to a request with URI equal to this string, but without the trailing slash, a permanent redirect with the code 301 will be returned to the requested URI with the slash appended.

This is normally not a problem, as your reverse proxy normally also handles the rewrite (see e.g. nginx default behavior of proxy_redirect).

@joergmschulz
Copy link

joergmschulz commented Apr 19, 2024

ignore that post, sorry. Didn't see a fix is queued. Will delete this post soon.

Hmmm, the statements above don't help. Interesting is what I get as an answer for:
GET https://nct.domain.de/apps/files:
...
location: http://nct.domain.de/apps/files
...
http instead of https?

@siccovansas
Copy link

Thanks @susnux for the explanation!

I had this same issue and use Nginx as a reverse proxy with a variable in proxy_pass (HTTPS) and another Nginx as webserver (HTTP) for Nextcloud. Because Nginx doesn't automatically set the proxy_redirect default value when you use variables in proxy_pass I had to add proxy_redirect http://$host https://$host; to my Nginx reverse proxy (I added it below the proxy_pass line in my Nginx reverse proxy location block that points to the Nginx webserver).

@litinoveweedle
Copy link

Hello,

we tried to backport proposed fix into our existing affected Nextcloud container, but it doesn't seems to fix the issue. The original problem as reported still persists.

@joergmschulz
Copy link

joergmschulz commented Apr 26, 2024 via email

@uncle-betty
Copy link

uncle-betty commented Apr 26, 2024

To collect more data, I played around with an override that let me modify the JavaScript my browser receives from the managed Nextcloud 28.0.4 instance I'm dealing with.

  • The original code generates the URL from apps/files, which triggers the issue.

  • Using an override generates the URL from apps/files/ instead also triggers the issue. As I understand it, this is equivalent to the fix that was rolled out.

  • Using an override that generates the URL from /settings/apps/files works.

  • Using an override that generates the URL from /settings/apps/files/ also works.

The latter two requests, the ones that are based on a URL built from an absolute path, don't result in a 301 redirect.

Wait... let me step back here for a second and make sure that I'm making the right assumptions here: Where should the first GET request actually go? /apps/files or /settings/apps/files?

Because in 28.0.4 with and without our non-working "fix", the first GET goes to /apps/files/ and /apps/files, respectively.

So, apps/files is supposed to be relative to which base path? / or /settings?

If it's /settings, then that's the real issue here, I'd say. We were just distracted from it, because besides /settings/apps/files, there's also /apps/files, isn't there? And going to /apps/files causes the 301 redirect. But the fix then would not be to avoid the redirect. Instead, it would be make the initial GET request to /settings/apps/files.

@joergmschulz
Copy link

joergmschulz commented Apr 26, 2024 via email

@uncle-betty
Copy link

One last observation: It doesn't seem to be about the absolute paths.

When I apply an override that generates the GET URL from settings/apps/files, then this works, too.

Note that this would be consistent with the successful POST whose URL is generated from settings/apps/enable (and which precedes the failing GET).

@susnux
Copy link
Contributor

susnux commented Apr 26, 2024

Where should the first GET request actually go? /apps/files or /settings/apps/files?

/apps/files should be fetched. Because if the files app fails then the installed app crashed something internally.


As written already above, if you have this error, then:

  1. Your webserver keeps on adding / to the path (this is not done by Nextcloud). So the webserver that serves Nextcloud issues a 301 and if it is using HTTP than the 301 will also be using HTTP.
  2. And your reverse proxy fails to rewrite redirects. Because if the proxy uses HTTPS and forwards to HTTP then it needs to rewrite also redirects.

If you use nginx as reverse proxy, refer to this on how to fix your configuration:
#44685 (comment)

@joergmschulz
Copy link

joergmschulz commented Apr 27, 2024

No / to be seen.
Redirect works, but with 302.
I get same site errors in the browser console pointing to the AppStore:

Die Ressource unter "https://usercontent.apps.nextcloud.com/aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL25leHRjbG91ZC9pbnRlZ3JhdGlvbl9ub3Rpb24vbWFpbi9zY3JlZW5zaG90cy9zY3JlZW5zaG90MS5qcGc=" wurde aufgrund ihres Cross-Origin-Resource-Policy-Headers (oder dessen Fehlens) blockiert. Weitere Informationen unter https://developer.mozilla.org/docs/Web/HTTP/Cross-Origin_Resource_Policy_(CORP)#

Because it is a CORS header issue, Safari ignores this restriction and all works fine. Next step is to identify the needed setting in my traefik.

@susnux
Copy link
Contributor

susnux commented Apr 28, 2024

@joergmschulz yes thats exactly the error already discussed here:

  1. We try to fetch /apps/files so a request to https://your-domain/apps/files is issued.
  2. Your reverse proxy redirects the request to http://your-proxy/apps/files (note now the protocoll is HTTP (not HTTPS))
  3. The webserver (e.g. Apache with mod_dir) sees the request and adds the trailing slash and returns 302 http://your-proxy/apps/files/
  4. Your proxy just returns that response without rewriting the protocol from the webserver

Solution: Disable mod_dir if you use Apache, or enable rewriting redirects in your reverse proxy.

@joergmschulz
Copy link

@susnux Obviously, nginx supports rewriting headers which isn't supported in traefik, see traefik/traefik#5809. Quoting:

It is worth noting that the http / https case is often corrected by Traefik passing X-Forwarded-Proto: https to the backend service so it knows that the "true" protocol is https (and can issue redirects as such). For services not handling X-Forwarded-Proto (which is in the spec that I mention above), then yes your point is spot on.

@tzerber
Copy link

tzerber commented Apr 29, 2024

Posting here, but related to the docker compose fpm variant (the issue there points here). This is indeed proxy bug.

Warning

The info below is more of a copy/paste from my working setup, but it should be taken with grain of salt. I can't provide a working example for all the proxies out there and their variants. On my setup it works fine, but I am not willing to be responsible if someone breaks his setup using the code below. Read first, check with your setup then edit files and restart containers.


A workaround for nginx-proxy-manager is to map the default proxy.conf and add the line proposed above for proxy_redirect, i.e.

  1. Copy the /etc/nginx/conf.d/include/proxy.conf out from the container and mount it locally
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
      - ./proxy.conf:/etc/nginx/conf.d/include/proxy.conf

and put this line at the end of the proxy.conf file:

proxy_redirect http://$host https://$host;

A workaround for nginx-proxy :
This might vary, but pasting my own setup here. Find and copy nginx.tmpl from the container to the outside and map it as volume. Usually the file is found as /app/nginx.tmpl in the nginx-proxy container.

services:
  nginx-proxy:
<snip>
    volumes:
      - ./nginx.tmpl:/app/nginx.tmpl
      - /var/run/docker.sock:/tmp/docker.sock:ro

Edit the template location as follows :

location {{ .Path }} {
        {{ if eq .NetworkTag "internal" }}
        # Only allow traffic from internal clients
        include /etc/nginx/network_internal.conf;
        {{ end }}

        {{ if eq .Proto "uwsgi" }}
                include uwsgi_params;
                uwsgi_pass {{ trim .Proto }}://{{ trim .Upstream }};
        {{ else if eq .Proto "fastcgi" }}
                root   {{ trim .VhostRoot }};
                include fastcgi_params;
                fastcgi_pass {{ trim .Upstream }};
        {{ else if eq .Proto "grpc" }}
                grpc_pass {{ trim .Proto }}://{{ trim .Upstream }};
        {{ else }}
                proxy_pass {{ trim .Proto }}://{{ trim .Upstream }}{{ trim .Dest }};
                proxy_redirect http://{{ trim .Upstream }} https://{{ trim .Upstream }};
        {{ end }}

        {{ if (exists (printf "/etc/nginx/htpasswd/%s" .Host)) }}
                auth_basic      "Restricted {{ .Host }}";
                auth_basic_user_file    {{ (printf "/etc/nginx/htpasswd/%s" .Host) }};
        {{ end }}

        {{ if (exists (printf "/etc/nginx/vhost.d/%s_%s_location" .Host (sha1 .Path) )) }}
                include {{ printf "/etc/nginx/vhost.d/%s_%s_location" .Host (sha1 .Path) }};
        {{ else if (exists (printf "/etc/nginx/vhost.d/%s_location" .Host)) }}
                include {{ printf "/etc/nginx/vhost.d/%s_location" .Host}};
        {{ else if (exists "/etc/nginx/vhost.d/default_location") }}
                include /etc/nginx/vhost.d/default_location;
        {{ end }}
}
{{ end }}

Note the line

                proxy_redirect http://{{ trim .Upstream }} https://{{ trim .Upstream }};

Save, and restart/rebuild the containers and keep in mind while this works on my setup, it might not be the same on yours.

Tested on 4 instances running Nextcloud 29 via Docker. For other setups the workaround is the same, you need to figure out the location of the proxy_pass directive and just add proxy_redirect with the correct settings below it.

@susnux
Copy link
Contributor

susnux commented Apr 29, 2024

@joergmschulz yes that is why I recommended that if your reverse proxy is not capable of rewriting redirects, then you can also disable the redirect within the web server, e.g. if you use Apache then set DirectorySlash Off

@joergmschulz
Copy link

yes - it's rather the rewriting of the location header in the answer. Indeed, traefik doesn't do this. Trying to switch to nginx for the test environment ....

@edocod1
Copy link

edocod1 commented May 1, 2024

This issue is caused by the following parameter that enables "pretty urls" (aka /index.php/apps/files can be reached by /apps/files) and might not be aware of the reverse-proxies in front of it. Disabling it can fix the issue right away, but leaves us with ugly URLs:

fastcgi_param front_controller_active true

In my case, i had a completely different approach instead. Since my setup was php-fpm -> Nginx (static webserver) -> haproxy (ssl terminator), i fixed it with the following directive in my haproxy backend (which i believe is the most semantically correct approach):

http-response replace-value Location (http:\/\/)(.*) https://\2

Be careful, though, as this will also rewrite external redirects and might not be your wanted behaviour.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.