Nginx HTTP header problems

The Basics

  • Nextcloud Server version (e.g., 29.x.x):
    • latest
  • Operating system and version (e.g., Ubuntu 24.04):
    • Debian 13
  • Web server and version (e.g, Apache 2.4.25):
    • nginx 1.29.1
  • Reverse proxy and version _(e.g. nginx 1.27.2)
    • no proxy
  • PHP version (e.g, 8.3):
    • 8.3.25
  • Is this the first time you’ve seen this error? (Yes / No):
    • yes
  • When did this problem seem to first start?
    • after installation
  • Installation method (e.g. AlO, NCP, Bare Metal/Archive, etc.)
  • Are you using CloudfIare, mod_security, or similar? (Yes / No)
    • no

Summary of the issue you are facing:

Nextcloud reports problems with the HTTP header.
Migration of an existing nextcloud server.
The headers are located in the nextcloud.conf file.
nginx -t does not report errors.

Some headers are not set correctly on your instance 
- The `X-Content-Type-Options` HTTP header is not set to `nosniff`. This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly. 
- The `X-Robots-Tag` HTTP header is not set to `noindex,nofollow`. This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly. 
- The `X-Frame-Options` HTTP header is not set to `sameorigin`. This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly. 
- The `X-Permitted-Cross-Domain-Policies` HTTP header is not set to `none`. This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly. 
- The `X-XSS-Protection` HTTP header does not contain `1; mode=block`. This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly. 
- The `Referrer-Policy` HTTP header is not set to `no-referrer`, `no-referrer-when-downgrade`, `strict-origin`, `strict-origin-when-cross-origin` or `same-origin`. This can leak referer information. See the W3C Recommendation. 
- The `Strict-Transport-Security` HTTP header is not set (should be at least `15552000` seconds). 

Web server / Reverse Proxy

nginx.conf

user www-data;
worker_processes auto;
pid /var/run/nginx.pid;
events {
  worker_connections 2048;
  multi_accept on;
  use epoll;
  }
http {
  http3_stream_buffer_size 1m;
  quic_retry on;
  ssl_early_data on;
  quic_gso on;
  quic_host_key /etc/nginx/quic_host.key;
  log_format criegerde escape=json
  '{'
    '"time_local":"$time_local",'
    '"remote_addr":"$remote_addr",'
    '"remote_user":"$remote_user",'
    '"request":"$request",'
    '"status": "$status",'
    '"body_bytes_sent":"$body_bytes_sent",'
    '"request_time":"$request_time",'
    '"http_referrer":"$http_referer",'
    '"http_user_agent":"$http_user_agent"'
  '}';
  server_names_hash_bucket_size 64;
  access_log /var/log/nginx/access.log; #criegerde;
  error_log /var/log/nginx/error.log warn;
  set_real_ip_from 127.0.0.1;
  real_ip_header X-Forwarded-For;
  real_ip_recursive on;
  include /etc/nginx/mime.types;
  default_type application/octet-stream;
  sendfile on;
  send_timeout 3600;
  tcp_nopush on;
  tcp_nodelay on;
  open_file_cache max=500 inactive=10m;
  open_file_cache_errors on;
  keepalive_timeout 65;
  reset_timedout_connection on;
  server_tokens off;
  resolver 127.0.0.53 176.9.93.198 176.9.1.117 valid=30s;
  resolver_timeout 5s;
  include /etc/nginx/conf.d/*.conf;
  }

/etc/nginx/conf.d/nextcloud.conf

limit_req_zone $binary_remote_addr zone=NextcloudRateLimit:10m rate=2r/s;
server {
listen 443 ssl;
listen 443 quic reuseport;
listen [::]:443 ssl;
listen [::]:443 quic reuseport;
server_name *my.nextcloudserver.com*;
ssl_certificate /etc/letsencrypt/rsa-certs/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/rsa-certs/privkey.pem;
ssl_certificate /etc/letsencrypt/ecc-certs/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/ecc-certs/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/ecc-certs/chain.pem;
http2 on;
http3 on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384';
ssl_ecdh_curve X448:secp521r1:secp384r1;
ssl_prefer_server_ciphers on;
client_max_body_size 10G;
client_body_timeout 3600s;
client_body_buffer_size 512k;
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 text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm 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;
add_header Strict-Transport-Security            "max-age=15768000; includeSubDomains; preload;" always;
add_header Permissions-Policy                   "interest-cohort=()";
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;
add_header Alt-Svc                              'h3=":$server_port"; ma=86400';
add_header x-quic                               'h3';
add_header Alt-Svc                              'h3-29=":$server_port"';
add_header Alt-Svc 'h3=":443"; ma=86400, h3-29=":443"; ma=86400' always;
fastcgi_hide_header X-Powered-By;
include mime.types;
types {
text/javascript mjs;
}
root /var/www/nextcloud;
index index.php index.html /index.php$request_uri;
location = / {
if ( $http_user_agent ~ ^DavClnt ) {
return 302 /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(?:$|/) {
rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode\/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;
fastcgi_param front_controller_active true;
fastcgi_pass php-handler;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
fastcgi_read_timeout 3600;
fastcgi_send_timeout 3600;
fastcgi_connect_timeout 3600;
fastcgi_max_temp_file_size 0;
fastcgi_param HTTP_HOST $host;
add_header Alt-Svc 'h3=":443"; ma=86400, h3-29=":443"; ma=86400' always;
add_header X-FastCGI-Cache $upstream_cache_status always;
}
location ~ \.(?:css|js|mjs|svg|gif|ico|jpg|png|webp|wasm|tflite|map|ogg|flac)$ {
try_files $uri /index.php$request_uri;
add_header Cache-Control                     "public, max-age=15768000, $asset_immutable";
add_header Permissions-Policy                "interest-cohort=()";
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;
add_header Alt-Svc                           'h3=":$server_port"; ma=86400';
add_header x-quic                            'h3';
add_header Alt-Svc                           'h3-29=":$server_port"';
access_log off;
expires 6M;
}
location ~ \.(otf|woff2?)$ {
try_files $uri /index.php$request_uri;
expires 7d;
access_log off;
}
location /remote {
return 301 /remote.php$request_uri;
}
location /login {
limit_req zone=NextcloudRateLimit burst=5 nodelay;
limit_req_status 429;
try_files $uri $uri/ /index.php$request_uri;
}
location / {
try_files $uri $uri/ /index.php$request_uri;
add_header Alt-Svc 'h3=":443"; ma=86400, h3-29=":443"; ma=86400' always;
}
}

Configuration

Nextcloud

{
    "system": {
        "instanceid": "***REMOVED SENSITIVE VALUE***",
        "passwordsalt": "***REMOVED SENSITIVE VALUE***",
        "secret": "***REMOVED SENSITIVE VALUE***",
        "trusted_domains": [
            "***REMOVED SENSITIVE VALUE***",
            "***REMOVED SENSITIVE VALUE***"
        ],
        "datadirectory": "***REMOVED SENSITIVE VALUE***",
        "dbtype": "mysql",
        "version": "31.0.9.1",
        "overwrite.cli.url": "https:\/\/***REMOVED SENSITIVE VALUE***",
        "dbname": "***REMOVED SENSITIVE VALUE***",
        "dbhost": "***REMOVED SENSITIVE VALUE***",
        "dbport": "",
        "dbtableprefix": "oc_",
        "mysql.utf8mb4": true,
        "dbuser": "***REMOVED SENSITIVE VALUE***",
        "dbpassword": "***REMOVED SENSITIVE VALUE***",
        "installed": true,
        "overwritehost": "l***REMOVED SENSITIVE VALUE***",
        "activity_expire_days": 14,
        "allow_local_remote_servers": true,
        "auth.bruteforce.protection.enabled": true,
        "forbidden_filenames": [
            ".htaccess",
            "Thumbs.db",
            "thumbs.db"
        ],
        "cron_log": true,
        "default_phone_region": "AT",
        "enable_previews": true,
        "enabledPreviewProviders": [
            "OC\\Preview\\PNG",
            "OC\\Preview\\JPEG",
            "OC\\Preview\\GIF",
            "OC\\Preview\\BMP",
            "OC\\Preview\\XBitmap",
            "OC\\Preview\\Movie",
            "OC\\Preview\\PDF",
            "OC\\Preview\\MP3",
            "OC\\Preview\\TXT",
            "OC\\Preview\\MarkDown",
            "OC\\Preview\\HEIC",
            "OC\\Preview\\Movie",
            "OC\\Preview\\MKV",
            "OC\\Preview\\MP4",
            "OC\\Preview\\AVI"
        ],
        "filesystem_check_changes": 0,
        "filelocking.enabled": "true",
        "htaccess.RewriteBase": "\/",
        "integrity.check.disabled": false,
        "knowledgebaseenabled": false,
        "logfile": "\/var\/log\/nextcloud\/nextcloud.log",
        "loglevel": "2",
        "logtimezone": "Europe\/Vienna",
        "remember_login_cookie_lifetime": "7200",
        "session_lifetime": 7200,
        "session_keepalive": true,
        "auto_logout": true,
        "memcache.local": "\\OC\\Memcache\\APCu",
        "memcache.locking": "\\OC\\Memcache\\Redis",
        "overwriteprotocol": "https",
        "preview_max_x": 1024,
        "preview_max_y": 768,
        "preview_max_scale_factor": 1,
        "profile.enabled": false,
        "redis": {
            "host": "***REMOVED SENSITIVE VALUE***",
            "port": 0,
            "password": "***REMOVED SENSITIVE VALUE***",
            "timeout": 0.5,
            "dbindex": 1
        },
        "quota_include_external_storage": false,
        "share_folder": "\/Freigaben",
        "skeletondirectory": "",
        "trashbin_retention_obligation": "auto, 7",
        "maintenance_window_start": 1,
        "maintenance": false,
        "twofactor_enforce": {
            "false": ""
        },
        "twofactor_enforced": "false",
        "twofactor_enforced_groups": [],
        "twofactor_enforced_excluded_groups": [],
        "versions_retention_obligation": "auto, 365",
        "simpleSignUpLink.shown": false,
        "upgrade.disable-web": true,
        "log.condition": {
            "apps": [
                "admin_audit"
            ]
        },
        "log_rotate_size": "0"
    }
}

Apps

Enabled:
  - activity: 4.0.0
  - admin_audit: 1.21.0
  - app_api: 5.0.2
  - bruteforcesettings: 4.0.0
  - circles: 31.0.0
  - cloud_federation_api: 1.14.0
  - comments: 1.21.0
  - contactsinteraction: 1.12.0
  - dashboard: 7.11.0
  - dav: 1.33.0
  - federatedfilesharing: 1.21.0
  - federation: 1.21.0
  - files: 2.3.1
  - files_downloadlimit: 4.0.0
  - files_pdfviewer: 4.0.0
  - files_reminders: 1.4.0
  - files_sharing: 1.23.1
  - files_trashbin: 1.21.0
  - files_versions: 1.24.0
  - logreader: 4.0.0
  - lookup_server_connector: 1.19.0
  - nextcloud_announcements: 3.0.0
  - notifications: 4.0.0
  - oauth2: 1.19.1
  - password_policy: 3.0.0
  - photos: 4.0.0
  - privacy: 3.0.0
  - profile: 1.0.0
  - provisioning_api: 1.21.0
  - recommendations: 4.0.0
  - related_resources: 2.0.0
  - serverinfo: 3.0.0
  - settings: 1.14.0
  - sharebymail: 1.21.0
  - support: 3.0.0
  - suspicious_login: 9.0.1
  - systemtags: 1.21.1
  - text: 5.0.0
  - theming: 2.6.1
  - twofactor_backupcodes: 1.20.0
  - twofactor_totp: 13.0.0-dev.0
  - updatenotification: 1.21.0
  - user_status: 1.11.0
  - viewer: 4.0.0
  - weather_status: 1.11.0
  - webhook_listeners: 1.2.0
  - workflowengine: 2.13.0
Disabled:
  - encryption: 2.19.0
  - files_external: 1.23.0
  - firstrunwizard: 4.0.0 (installed 2.18.0)
  - survey_client: 3.0.0 (installed 1.17.0)
  - twofactor_nextcloud_notification: 5.0.0
  - user_ldap: 1.22.0

You have two spots where you are using add_header at the location level in your Nginx config. Which is fine, but Nginx doesn’t inherit parent headers when you do that.

You can see how the documented Nginx config avoids that:

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