HSTS Strict-Transport-Security HTTP header warning is still showing up, although the header os enabled in nginx config server-wide

Nextcloud version (eg, 20.0.5): 26.0.1 (issue began at 26.0)
Operating system and version (eg, Ubuntu 20.04): Ubuntu 18.04.6 LTS
Apache or nginx version (eg, Apache 2.4.25): nginx/1.14.0
PHP version (eg, 7.4): 8.0

The issue you are facing:
I got the security warning about HSTS from admin page after upgrading to version 26.0. I’ve checked my nginx config and it seems that the Strict-Transport-Security HTTP header is enabled server-wide.

cat /etc/nginx/nginx.conf 
...
http {
        ...
        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}
...
cat /etc/nginx/conf.d/nextcloud.conf
...
server {
    listen 443 ssl http2;
    server_name mydomain.org;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    ...
    root /var/www/;
    ...
    location ^~ /nextcloud {
    ....
    }
}
...

Is this the first time you’ve seen this error? (Y/N): Y

Steps to replicate it:

  1. Check that nginx config adds HSTS header server-wide
  2. Reload nginx config
  3. Check that HSTS Preload List site aknowledges that the site is eligible for adding to the list.
  4. Nextcloud Admin page still shows the warning about adding HSTS header.

The output of your Nextcloud log in Admin > Logging:

skipped

The output of your config.php file in /path/to/nextcloud (make sure you remove any identifiable information!):

<?php
$CONFIG = array (
  'instanceid' => 'redacted',
  'passwordsalt' => '+redacted',
  'secret' => 'redacted',
  'trusted_domains' =>
  array (
    0 => 'IP',
    1 => 'mydomain.org',
  ),
  'datadirectory' => '/redacted',
  'overwrite.cli.url' => 'http://IP/nextcloud',
  'dbtype' => 'mysql',
  'version' => '26.0.1.1',
  'dbname' => 'nextcloud',
  'dbhost' => 'localhost',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'dbuser' => 'redacted',
  'dbpassword' => 'redacted/u+',
  'logtimezone' => 'UTC',
  'installed' => true,
  'maintenance' => false,
  'loglevel' => 2,
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'filelocking.enabled' => 'true',
  'redis' =>
  array (
    'host' => '/var/run/redis/redis.sock',
    'port' => 0,
    'dbindex' => 0,
    'timeout' => 1.5,
  ),
  'theme' => '',
  'updater.release.channel' => 'stable',
  'app_install_overwrite' =>
  array (
    0 => 'twofactor_totp',
    1 => 'files_opds',
    2 => 'files_reader',
    3 => 'drawio',
    4 => 'twofactor_gateway',
  ),
  'mysql.utf8mb4' => true,
  'default_phone_region' => 'redacted',
  'mail_smtpmode' => 'smtp',
  'mail_smtpauth' => 1,
  'mail_sendmailmode' => 'smtp',
  'mail_smtpsecure' => 'tls',
  'mail_smtphost' => 'smtp.gmail.com',
  'mail_from_address' => 'redacted',
  'mail_domain' => 'gmail.com',
  'mail_smtpname' => 'redacted@gmail.com',
  'mail_smtppassword' => 'redacted',
  'mail_smtpauthtype' => 'LOGIN',
);

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

skipped

Output errors in nextcloud.log in /var/www/ or as admin user in top right menu, filtering for errors. Use a pastebin service if necessary.

`
Error core GuzzleHttp\Exception\ConnectException: cURL error 28: Operation timed out after 30000 milliseconds with 4898816 out of 8212347 bytes received (see libcurl - Error Codes) for https://download.geonames.org/export/dump/cities1000.zip
2023-04-07T09:55:43+0500
Error no app in context Exception: App “Mind Map” cannot be installed because it is not compatible with this version of the server.
2023-04-07T09:54:18+0500
Error remote OC\DB\Exceptions\DbalException: An exception occurred while executing a query: SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction
2023-04-05T12:40:55+0500
Error PHP OC\DB\Exceptions\DbalException: An exception occurred while executing a query: SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction at /var/www/nextcloud/lib/private/DB/Exceptions/DbalException.php#71
2023-04-05T12:40:32+0500
Error PHP OC\DB\Exceptions\DbalException: An exception occurred while executing a query: SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction at /var/www/nextcloud/lib/private/DB/Exceptions/DbalException.php#71
2023-04-05T12:40:31+0500
Error webdav Sabre\DAV\Exception\ServiceUnavailable: OC\DB\Exceptions\DbalException: An exception occurred while executing a query: SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction
2023-04-05T12:40:03+0500

Do you get the same when reproducing the following steps

  1. change ‘overwrite.cli.url’ => ‘http://IP/nextcloud’,
    to 'overwrite.cli.url' => 'http(s)://your.domain',

  2. set 'overwritehost' => 'your.domain', as well

  3. clear all browser cache

  4. reload page / re-check
    ?

  1. I’ve changed ‘overwrite.cli.url’ => ‘http://IP/nextcloud’, to ‘overwrite.cli.url’ => ‘https://mydomain.org/nextcloud’,
  2. then added 'overwritehost' => 'mydomain.org',
  3. then restarted nginx and php-fpm8.0 services on the server
  4. then cleared cookies and tried different browsers,
  5. then reloaded page
  6. then checked - still the warning is here.

try to restart the server as well

second question: did you get a warning concerning HSTS from here

when you check “your.domain” ?

do you mean restart the physical machine itself? Its uptime is several months, and it got several other services, I would prefer not to :slight_smile: This looks like just a false warning, since HSTS Preload List portal is stating that the domain is eligible for adding.
SSL Server Test from Qualys is also stating A+ and confirms that HSTS with long duration is deployed on this server.

That’s important and good either!
Do you check your admin page (nextcloud) from the same LAN / Domain than the nextcloud server is running in?
Then you may try the same admin page reload by using a client internet connection that differs from the one your nextcloud server is connected with (Hotspot via mobile data, or other WLAN etc.)
Check if you now get a “green” response.

I was using local access when creating the Support question, from the same LAN as the Nextcloud server. Now I am connected from another location through Internet (the server is at home and I am at the office), and I already tried connecting from a different browser and from a different PC.

Have you connect to a terminal of your NC Server?

Have you just tried to use

sudo -u www-data php /var/www/nextcloud/occ integrity:check-core

and after that login as admin again…
The recheck of the admin WebUI usually does the same but sometimes i prefer the occ commands

this command does not give me any output. Is this normal behavior?
I know that occ is working OK, I was just using it today for fixing indices after update from 26.0 to 26.0.1. This warning actually appeared after upgrading to 26.0, I tried to solve it myself, but then decided to wait for a next patch.

no output usually means no errors
it seems as if your browser is kidding you …

Strg+F5 (to force fresh data load of your admin page ??)

I did try MS Edge and Firefox Mobile apart from my default desktop Firefox. With the same result.
Well, I will wait for another guy with the same problem, maybe we can get rid of this annoyance together.

you have set

http {

include /etc/nginx/conf.d/.conf;
include /etc/nginx/sites-enabled/
;

OK so far. Have a look at all (!) *.conf files in all folders if you have set your
header settings for HSTS twice anywhere.
In that case this header maybe triggered more than once and in that cases NC also delivers a config error!

*include /etc/nginx/sites-enabled/*; is empty and include /etc/nginx/conf.d/*.conf;* only has one file, nextcloud.conf. There are several virtual servers defined in this config file on diferrent ports, and also several subfolders configured on a main 443 server, but HTTP header Strict-Transport-Security is only added once, under root of the main server.
Strangely enough, if I try to access my Nextcloud web site with opened DevTools in Firefox, I do not see strict-transport-security header in the responses. Although my services from other subfolders on this nginx server are correctly displaying this header.

server {
    listen 443 ssl http2;
    server_name mydomain.org;

    ssl_certificate /etc/letsencrypt/live/mydomain.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mydomain.org/privkey.pem;

    if ($host != "mydomain.org") {
        return 444;
    }

    # Prevent nginx HTTP Server Detection
    server_tokens off;

    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;

    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES25

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Robots-Tag "noindex, nofollow" always;
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none;
    add_header Referrer-Policy no-referrer;
    add_header X-Frame-Options "SAMEORIGIN" always;
    fastcgi_hide_header X-Powered-By;

    root /var/www/;

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

    location = /.well-known/webfinger {
      return 301 /nextcloud/index.php$uri;
    }

    location ^~ /.well-known {

        location = /.well-known/carddav { return 301 /nextcloud/remote.php/dav/; }
        location = /.well-known/caldav  { return 301 /nextcloud/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 /nextcloud/index.php$request_uri;
    }

    location ^~ /nextcloud {
        client_max_body_size 512M;
        client_body_timeout 300s;
        fastcgi_buffers 64 4K;
        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 applica

        client_body_buffer_size 512k;

        add_header Referrer-Policy                   "no-referrer"       always;
        add_header X-Content-Type-Options            "nosniff"           always;
        add_header X-Download-Options                "noopen"            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;

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

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

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

        location ~ \.php(?:$|/) {
            rewrite ^/nextcloud/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /nextcloud/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;

            fastcgi_intercept_errors on;
            fastcgi_request_buffering off;

            fastcgi_max_temp_file_size 0;
        }

        location ~ \.(?:css|js|svg|gif|png|jpg|ico|wasm|tflite|map)$ {
            try_files $uri /nextcloud/index.php$request_uri;
            add_header Cache-Control "public, max-age=15778463, $asset_immutable";
            access_log off;     # Optional: Don't log access to assets

            location ~ \.wasm$ {
                default_type application/wasm;
            }
        }

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

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

        location /nextcloud {
            try_files $uri $uri/ /nextcloud/index.php$request_uri;
        }
    }
}

This is my full nextcloud nginx config, excluding subfolder config for other services.
Is there something that can cause this odd behavior?

Since you add_headers in the /nextcloud-location, the HSTS-header doesn’t get inherited.

“There could be several add_header directives. These directives are inherited from the previous configuration level if and only if there are no add_header directives defined on the current level.” (Source: Module ngx_http_headers_module)

well, what do I do then, if I want some headers to be applied to the whole server, and some to dedicated subfolders only?

O, I think I get. I just need to copy all headers from root level to nextcloud level. That way all other locations will continue to use just the root headers, and nextcloud subfolder will “inherit” them via this explicit copying.
I’ll try that.

Exactly: if you add headers on a sublevel, you need to add all headers you want to be delivered from that level.

A good starting point for debugging nextcloud nginx issues is always the nginx config from the official nextcloud documentation at docs.nextcloud.com.

Yes! that solved my issue. I have just realized that I have the same headers configured on a root level and on a nextcloud subfolder level, except the HSTS header. I copied it over and now the warning is gone. I suppose I have migrated the config to the recommended at nextcloud documentation page, but the leftovers broke this one particalar thing.
Thanks, @Bernie_O and @chrissi55 for your help, my system is now safer and my mind is at peace :slight_smile:

2 Likes

If I have read the thread correctly, your server sets the HSTS header. In the past, I had the same warning, even if the header was set. The problem was: The header was set twice. You can verify this with Firefox or Chrome using the developer tools: Press Ctrl -Shift-I or Ctrl -Shift-C, here you can see the headers. If you see the HSTS header twice, this may be the problem.
Try to remove the configuration in the server-global configuration file and test it again. Maybe, it is set in an specific config file or the .htaccess for your Nextcloud, too.