Nextcloud incorrectly detects HTTP instead of HTTPS when accessed via public internet through Traefik

Support intro

Sorry to hear you’re facing problems. :slightly_frowning_face:

The community help forum (help.nextcloud.com) is for home and non-enterprise users. Support is provided by other community members on a best effort / “as available” basis. All of those responding are volunteering their time to help you.

If you’re using Nextcloud in a business/critical setting, paid and SLA-based support services can be accessed via portal.nextcloud.com where Nextcloud engineers can help ensure your business keeps running smoothly.

Getting help

In order to help you as efficiently (and quickly!) as possible, please fill in as much of the below requested information as you can.

Before clicking submit: Please check if your query is already addressed via the following resources:

(Utilizing these existing resources is typically faster. It also helps reduce the load on our generous volunteers while elevating the signal to noise ratio of the forums otherwise arising from the same queries being posted repeatedly).

Some or all of the below information will be requested if it isn’t supplied; for fastest response please provide as much as you can. :heart:

The Basics

  • Nextcloud Server version (e.g., 29.x.x):
    • 30.0.2
  • Operating system and version (e.g., Ubuntu 24.04):
    • Debian GNU/Linux 12 (bookworm)
  • Web server and version (e.g, Apache 2.4.25):
    • Apache/2.4.62
  • Reverse proxy and version _(e.g. nginx 1.27.2)
    • traefik2 v3.2.1
  • PHP version (e.g, 8.3):
    • 8.2.26
  • Is this the first time you’ve seen this error? (Yes / No):
    • Yes
  • When did this problem seem to first start?
    • When I configured traefik. Yesterday
  • Installation method (e.g. AIO, NCP, Bare Metal/Archive, etc.)
    • Official Docker Image
  • Are you using Cloudflare, mod_security, or similar? (Yes / No)
    • Cloudflare

Summary of the issue you are facing:

I configured traefik and everything seemed to work fine. I am able to access my nextcloud instance via my subdomain.
When accessed via local DNS (adguard home), Nextcloud recognizes the connection as HTTPS.
However, when accessed over the public internet, it is reachable, but Nextcloud thinks it’s running over HTTP, despite having a valid SSL certificate.
I already added ‘trusted_proxies’, ‘overwritehost’, ‘overwriteprotocol’, ‘overwritecondaddr’, ‘overwrite.cli.url’ to both the config.php and the docker compose. I tried a lot of subnets for trusted_proxies just to make sure.

Steps to replicate it (hint: details matter!):

  1. Configure traefik with docker labels in the nextcloud compose file
  2. Add a bunch of stuff from the docs to the config.php
  3. Access Nextcloud and look into the administrative settings

Log entries

Nextcloud

Please provide the log entries from your Nextcloud log that are generated during the time of problem (via the Copy raw option from Administration settings->Logging screen or from your nextcloud.log located in your data directory). Feel free to use a pastebin/gist service if necessary.

{"reqId":"Xu6PZKjoq5OtnrUM4U8q","level":2,"time":"2024-12-04T14:33:18+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"no app in context","method":"GET","url":"/ocs/v2.php/apps/notifications/api/v2/notifications","message":"Link of notification is not an absolute URL and does not work in mobile and desktop clients [app: firstrunwizard, subject: apphint-deck]","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":[]}
{"reqId":"Xu6PZKjoq5OtnrUM4U8q","level":2,"time":"2024-12-04T14:33:18+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"no app in context","method":"GET","url":"/ocs/v2.php/apps/notifications/api/v2/notifications","message":"Icon of notification is not an absolute URL and does not work in mobile and desktop clients [app: firstrunwizard, subject: apphint-deck]","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":[]}
{"reqId":"Xu6PZKjoq5OtnrUM4U8q","level":2,"time":"2024-12-04T14:33:18+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"no app in context","method":"GET","url":"/ocs/v2.php/apps/notifications/api/v2/notifications","message":"Link of notification is not an absolute URL and does not work in mobile and desktop clients [app: firstrunwizard, subject: apphint-forms]","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":[]}
{"reqId":"Xu6PZKjoq5OtnrUM4U8q","level":2,"time":"2024-12-04T14:33:18+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"no app in context","method":"GET","url":"/ocs/v2.php/apps/notifications/api/v2/notifications","message":"Icon of notification is not an absolute URL and does not work in mobile and desktop clients [app: firstrunwizard, subject: apphint-forms]","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":[]}
{"reqId":"Xu6PZKjoq5OtnrUM4U8q","level":2,"time":"2024-12-04T14:33:18+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"no app in context","method":"GET","url":"/ocs/v2.php/apps/notifications/api/v2/notifications","message":"Link of notification is not an absolute URL and does not work in mobile and desktop clients [app: firstrunwizard, subject: apphint-groupfolders]","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":[]}
{"reqId":"Xu6PZKjoq5OtnrUM4U8q","level":2,"time":"2024-12-04T14:33:18+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"no app in context","method":"GET","url":"/ocs/v2.php/apps/notifications/api/v2/notifications","message":"Icon of notification is not an absolute URL and does not work in mobile and desktop clients [app: firstrunwizard, subject: apphint-groupfolders]","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":[]}
{"reqId":"Xu6PZKjoq5OtnrUM4U8q","level":2,"time":"2024-12-04T14:33:18+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"no app in context","method":"GET","url":"/ocs/v2.php/apps/notifications/api/v2/notifications","message":"Link of notification is not an absolute URL and does not work in mobile and desktop clients [app: firstrunwizard, subject: apphint-recognize]","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":[]}
{"reqId":"Xu6PZKjoq5OtnrUM4U8q","level":2,"time":"2024-12-04T14:33:18+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"no app in context","method":"GET","url":"/ocs/v2.php/apps/notifications/api/v2/notifications","message":"Icon of notification is not an absolute URL and does not work in mobile and desktop clients [app: firstrunwizard, subject: apphint-recognize]","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":[]}
{"reqId":"0kNmToTYca2aIGxNpnsB","level":3,"time":"2024-12-04T14:33:21+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"PHP","method":"GET","url":"/settings/ajax/checksetup","message":"Undefined array key \"scheme\" at /var/www/html/apps/settings/lib/SetupChecks/CheckServerResponseTrait.php#97","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":{"app":"PHP"}}
{"reqId":"0kNmToTYca2aIGxNpnsB","level":3,"time":"2024-12-04T14:33:21+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"PHP","method":"GET","url":"/settings/ajax/checksetup","message":"Undefined array key \"host\" at /var/www/html/apps/settings/lib/SetupChecks/CheckServerResponseTrait.php#97","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":{"app":"PHP"}}
{"reqId":"0kNmToTYca2aIGxNpnsB","level":3,"time":"2024-12-04T14:33:21+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"PHP","method":"GET","url":"/settings/ajax/checksetup","message":"Undefined array key \"scheme\" at /var/www/html/apps/settings/lib/SetupChecks/CheckServerResponseTrait.php#97","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":{"app":"PHP"}}
{"reqId":"0kNmToTYca2aIGxNpnsB","level":3,"time":"2024-12-04T14:33:21+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"PHP","method":"GET","url":"/settings/ajax/checksetup","message":"Undefined array key \"host\" at /var/www/html/apps/settings/lib/SetupChecks/CheckServerResponseTrait.php#97","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":{"app":"PHP"}}
{"reqId":"0kNmToTYca2aIGxNpnsB","level":3,"time":"2024-12-04T14:33:21+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"PHP","method":"GET","url":"/settings/ajax/checksetup","message":"Undefined array key \"scheme\" at /var/www/html/apps/settings/lib/SetupChecks/CheckServerResponseTrait.php#97","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":{"app":"PHP"}}
{"reqId":"0kNmToTYca2aIGxNpnsB","level":3,"time":"2024-12-04T14:33:21+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"PHP","method":"GET","url":"/settings/ajax/checksetup","message":"Undefined array key \"host\" at /var/www/html/apps/settings/lib/SetupChecks/CheckServerResponseTrait.php#97","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":{"app":"PHP"}}
{"reqId":"0kNmToTYca2aIGxNpnsB","level":3,"time":"2024-12-04T14:33:22+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"PHP","method":"GET","url":"/settings/ajax/checksetup","message":"Undefined array key \"scheme\" at /var/www/html/apps/settings/lib/SetupChecks/CheckServerResponseTrait.php#97","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":{"app":"PHP"}}
{"reqId":"0kNmToTYca2aIGxNpnsB","level":3,"time":"2024-12-04T14:33:22+00:00","remoteAddr":"192.168.178.80","user":"user1","app":"PHP","method":"GET","url":"/settings/ajax/checksetup","message":"Undefined array key \"host\" at /var/www/html/apps/settings/lib/SetupChecks/CheckServerResponseTrait.php#97","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36","version":"30.0.2.2","data":{"app":"PHP"}}

Web server / Reverse Proxy

The output of your Apache/nginx/system log in /var/log/____:

2024-12-04T14:30:21+01:00 INF Loading plugins... plugins=["bouncer"]
2024-12-04T14:30:21+01:00 INF Plugins loaded. plugins=["bouncer"]
2024-12-04T14:30:21+01:00 INF Starting provider aggregator *aggregator.ProviderAggregator
2024-12-04T14:30:21+01:00 INF Starting provider *file.Provider
2024-12-04T14:30:21+01:00 INF Starting provider *traefik.Provider
2024-12-04T14:30:21+01:00 INF Starting provider *acme.ChallengeTLSALPN
2024-12-04T14:30:21+01:00 INF Starting provider *docker.Provider
2024-12-04T14:30:21+01:00 INF Starting provider *acme.Provider
2024-12-04T14:30:21+01:00 INF Testing certificate renew... acmeCA=https://acme-v02.api.letsencrypt.org/directory providerName=cloudflare.acme

Configuration

Nextcloud

The output of occ config:list system or similar is best, but, if not possible, the contents of your config.php file from /path/to/nextcloud is fine (make sure to remove any identifiable information!):

<?php
$CONFIG = array (
  'htaccess.RewriteBase' => '/',
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'apps_paths' => 
  array (
    0 => 
    array (
      'path' => '/var/www/html/apps',
      'url' => '/apps',
      'writable' => false,
    ),
    1 => 
    array (
      'path' => '/var/www/html/custom_apps',
      'url' => '/custom_apps',
      'writable' => true,
    ),
  ),
  'upgrade.disable-web' => true,
  'instanceid' => 'id',
  'passwordsalt' => 'password',
  'secret' => 'secret',
  'trusted_domains' => 
  array (
    0 => '192.168.178.184:8080',
    1 => 'nextcloud.domain.de',
  ),
  'trusted_proxies' => ['192.168.178.241', '127.0.0.1', '::1', '192.168.96.0/20', '172.71.160.0/24'],
 # 'overwrite.cli.url' => 'https://nextcloud.domain.de/',
  'overwriteprotocol' => 'https',
  'overwritewebroot'  => '/nextcloud.domain.de/nextcloud',
  'overwritecondaddr' => '192\.168\.178\.241$',
  'overwritehost' => 'nextcloud.domain.de',
  'datadirectory' => '/var/www/html/data',
  'dbtype' => 'mysql',
  'version' => '30.0.2.2',
  'overwrite.cli.url' => 
  array (
    0 => 'http://192.168.178.184:8080',
    1 => 'https://nextcloud.domain.de',
  ),
  'dbname' => 'nextcloud',
  'dbhost' => 'db',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'mysql.utf8mb4' => true,
  'dbuser' => 'nextcloud',
  'dbpassword' => 'passwort',
  'installed' => true,
  'maintenance' => false,
  'loglevel' => 2,
);

Nextcloud docker-compose:

services:
  db:
    image: mariadb:10.11
    restart: always
    networks:
      - nextcloud-backend
    command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
    volumes:
      - CHANGE_TO_COMPOSE_DATA_PATH/nextcloud/db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=passwort
      - MYSQL_PASSWORD=passwort
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud

   redis:
    image: redis:alpine
    networks:
      - nextcloud-backend
    restart: always

  app:
    image: nextcloud
    restart: always
    ports:
      - 8080:80
    depends_on:
      - redis
      - db
    networks:
      - proxy
      - nextcloud-backend
    volumes:
      - CHANGE_TO_COMPOSE_DATA_PATH/nextcloud/data:/var/www/html
    hostname: nextcloud.domain.de
    environment:
      - MYSQL_PASSWORD=passwort
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_HOST=db
      - NEXTCLOUD_HOSTNAME=nextcloud.domain.de
      - NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.domain.de
      - TRUSTED_PROXIES=192.168.178.241 127.0.0.1 ::1 192.168.96.0/20 192.168.178.0/24 172.17.0.0/16 172.16.0.0/12 192.168.0.0/16
      - OVERWRITEPROTOCOL=https
      - OVERWRITECLIURL=https://nextcloud.domain.de
      - OVERWRITEHOST=nextcloud.domain.de
    labels:
      - traefik.enable=true
      - traefik.http.routers.nextcloud-http.rule=Host(`nextcloud.domain.de`)
      - traefik.http.routers.nextcloud-http.entrypoints=web
      - traefik.http.routers.nextcloud-https.tls=true
      - traefik.http.routers.nextcloud-https.tls.certresolver=cloudflare
      - traefik.http.routers.nextcloud-https.entrypoints=websecure
      - traefik.http.routers.nextcloud-https.rule=Host(`nextcloud.domain.de`)
      - traefik.http.services.nextcloud.loadbalancer.server.port=80
      - traefik.docker.network=proxy
      - traefik.http.routers.nextcloud-https.service=nextcloud
      - traefik.http.routers.nextcloud-https.middlewares=nextcloud_redirectregex@docker
      - traefik.http.middlewares.nextcloud_redirectregex.redirectregex.permanent=true
      - traefik.http.middlewares.nextcloud_redirectregex.redirectregex.regex=https://(.*)/.well-known/(?:card|cal)dav
      - traefik.http.middlewares.nextcloud_redirectregex.redirectregex.replacement=https://$${1}/remote.php/dav
networks:
  proxy:
    external: true
  nextcloud-backend:

traefik.yaml just in case:

global:
  checkNewVersion: false
  sendAnonymousUsage: false

log:
  level: INFO
  filePath: /var/log/traefik/traefik.log
accessLog:
  filePath: /var/log/traefik/access.log
  fields:
    names:
      StartUTC: drop

api:
  dashboard: true
  insecure: true
  debug: false
 # address: ":8080"

entryPoints:
  web:
    address: :80
    forwardedHeaders:
      trustedIPs: &trustedIps
     #   - 192.168.96.6
       # - 192.168.178.184
        # Start of Clouflare public IP list for HTTP requests, remove this if you don't use it7
        - 173.245.48.0/20
        - 103.21.244.0/22
        - 103.22.200.0/22
        - 103.31.4.0/22
        - 141.101.64.0/18
        - 108.162.192.0/18
        - 190.93.240.0/20
        - 188.114.96.0/20
        - 197.234.240.0/22
        - 198.41.128.0/17
        - 162.158.0.0/15
        - 104.16.0.0/13
        - 104.24.0.0/14
        - 172.64.0.0/13
        - 131.0.72.0/22       
        - 2400:cb00::/32
        - 2606:4700::/32
        - 2803:f800::/32
        - 2405:b500::/32
        - 2405:8100::/32
        - 2a06:98c0::/29
        - 2c0f:f248::/32
 # End of Cloudlare public IP list
        # Local IPs
        - 127.0.0.1/32
        - 10.0.0.0/8
        - 192.168.0.0/16
        - 172.16.0.0/12
    http:
      middlewares:
        - crowdsec@file
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: :443
    http:
      middlewares:
        - crowdsec@file 
    forwardedHeaders:
      trustedIPs: &trustedIps
        # Start of Clouflare public IP list for HTTP requests, remove this if you don't use it
    #    - 192.168.96.6
  #      - 192.168.178.184
        - 173.245.48.0/20
        - 103.21.244.0/22
        - 103.22.200.0/22
        - 103.31.4.0/22
        - 141.101.64.0/18
        - 108.162.192.0/18
        - 190.93.240.0/20
        - 188.114.96.0/20
        - 197.234.240.0/22
        - 198.41.128.0/17
        - 162.158.0.0/15
        - 104.16.0.0/13
        - 104.24.0.0/14
        - 172.64.0.0/13
        - 131.0.72.0/22
        - 2400:cb00::/32
        - 2606:4700::/32
        - 2803:f800::/32
        - 2405:b500::/32
        - 2405:8100::/32
        - 2a06:98c0::/29
        - 2c0f:f248::/32       
 # End of Cloudlare public IP list
        - 127.0.0.1/32
        - 10.0.0.0/8
        - 192.168.0.0/16
        - 172.16.0.0/12

certificatesResolvers:
  cloudflare:
    acme:
      email:email@email.com
      # For testing un-comment the following line:
      # caServerr: https://acme-staging-v02.api.letsencrypt.org/directory
      # For testing:
      # storage: /etc/traefik/certs/cloudflare-acme-test.json
      # For production:
      storage: /etc/traefik/certs/cloudflare-acme.json
      dnsChallenge:
        provider: cloudflare
        resolvers:
          - "1.1.1.1:53"
          - "8.8.8.8:53"

serversTransport:
  insecureSkipVerify: true

providers:
  docker:
    exposedByDefault: false
    endpoint: 'unix:///var/run/docker.sock'
    watch: true
   # allowCrossNamespace: true
    # swarmMode: false # Not needed any longer in v. 3
  file:
    directory: /etc/traefik/conf/
    watch: true


experimental:
  plugins:
      bouncer:
        moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
        version: v1.3.5  # To update

If anybody could help, I would be very grateful.

Hi.

It seems that you are terminating the HTTPS trafic on your reverse proxy and not on the Nextcloud container itself. Your proxy conenction runs port 80 and http between your proxy and Nextcloud. It is then - strictly speaking - from the viewpoint of nextcloud, correct that you runs http and not https. From a more logical standpoint, you are running https on anything public.

There are two ways to go here, really. Have Nextcloud not do any HTTPS itself. Do not overwrite anything in the nextcloud container at all, and accept “just” http in nextcloud.

Setup HTTPS in the nextcloud container and do not terminate the connection on the reverse proxy but treat it as TCP and let the trafic proxy without any kind of header inspection, unless you ventures down the SNI header path ofc.

There are obvious pros and cons with both. If you use your Nextcloud - or plans to - as IDP of any kind, you will need to run HTTPS on the Nextcloud container directly, in order to build and generate trust secrets that SP’s can use. If this is not a concern for you, then terminating the TLS on the reverse proxy and then forwarding/proxying unencrypted to the nextcloud container, should be fine.

1 Like

I just got it working now! I don’t know what exactly made the difference but it started working after I commented out all the OVERWRITE* in the docker compose. I had these overwrites in the config.php and the compose and they seemed to be in conflict to each other.

So the working configuration entails the trusted_domains, trusted_proxies, overwriteprotocol and overwrite.cli.url ONLY in the config.php and host: my.doman.com in the compose.

1 Like

I didn’t look to closely at the rest of your config since it sounds like your got your original matter resolved, but for future reference it’s important to use occ config:list system to view the fully merged config. This is because the Docker image utilizes Nextcloud’s multiple config.php support. See Docker: Viewing the Nextcloud configuration (config.php).

This topic was automatically closed 8 days after the last reply. New replies are no longer allowed.