Support intro
Sorry to hear you’re facing problems. 
The community help forum (help(dot)nextcloud(dot)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(dot)nextcloud(dot)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:
- Official documentation (searchable and regularly updated)
- How to topics and FAQs
- Forum search
(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).
Hey folks! I’m working on setting up a new NC instance in Docker, reverse proxied with Traefik - currently using a self-signed cert to simulate as closely as possible a correct HTTPS configuration before I start opening it up to the wider internet. Currently encountering a ‘Strict-Transport-Authority’ message that I’d like to try to clear.
The Basics
- Nextcloud version 32.0.5 (from Docker image)
- OS is Linux Mint 21.3
- Web server is Apache/2.4.66 (Debian) (from Docker image)
- Reverse proxy is Traefik 3.6.7
- PHP version 8.3.30 (from Docker image)
- Is this the first time you’ve seen this error? Yes
- When did this problem seem to first start? At install time
- Installed with Docker Compose (NOT the AIO version - using the apache image)
- Are you using CloudfIare, mod_security, or similar? No
- Some additional points potentially worth noting:
- using Authelia as an auth layer - this is not set up to authenticate NC itself via OAuth yet, currently just gating any access to the page.
- using a self-signed cert with a self-signed CA
- testing in Firefox (cert CA correctly added to Firefox’s store - lock icon says Connection Secure)
- Nextcloud URL added to /etc/hosts file so it targets localhost while I work on it in my dev environment
- Nothing currently accessible from outside dev environment
Summary of the issue you are facing:
Like many others before me, I am unfortunately stuck with this warning on my Overview page:
Some headers are not set correctly on your instance - The `Strict-Transport-Security` HTTP header is not set (should be at least `15552000` seconds). For enhanced security, it is recommended to enable HSTS.
My understanding is that this is almost assuredly a Traefik configuration issue but I’m stumped as to what I’m missing.
Steps to replicate it (hint: details matter!):
-
From a cold start, stand up Docker containers using
docker compose up -d; enable Nextcloud cron job -
In Firefox, navigate to nextcloud(dot)mydomain(dot)com, authenticate
-
From the Nextcloud homepage, navigate to /settings/admin/overview
-
Observe the warning message present in the “Security & setup warnings” section
Log entries
Nextcloud
None from the day of testing.
Web Browser (Firefox)
Network output upon refresh is 200’s across the board.
Console output upon refresh:
Notifications permissions granted NotificationsApp.vue:449:13
Polling interval updated to 30000 NotificationsApp.vue:412:12
Started background fetcher as session_keepalive is enabled NotificationsApp.vue:279:13
Got notification data, restoring default polling interval. NotificationsApp.vue:368:13
EDIT: adding nextcloud#####headers from Firefox’s local storage for additional info - this seems to indicate that as far as the browser is concerned, HSTS headers are present?
{
"cache-control": "no-cache, no-store, must-revalidate",
"content-encoding": "gzip",
"content-length": "81",
"content-security-policy": "default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none'",
"content-type": "application/json; charset=utf-8",
"date": "(REDACTED)",
"etag": "(REDACTED)",
"feature-policy": "autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone 'none';payment 'none'",
"permissions-policy": "camera=(), microphone=(), geolocation=(), payment=(), usb=(), vr=()",
"referrer-policy": "no-referrer",
"strict-transport-security": "max-age=15752000; includeSubDomains; preload",
"x-content-type-options": "nosniff",
"x-firefox-spdy": "h2",
"x-frame-options": "SAMEORIGIN",
"x-nextcloud-user-status": "online",
"x-permitted-cross-domain-policies": "none",
"x-powered-by": "PHP/8.3.30",
"x-request-id": "(REDACTED)",
"x-robots-tag": "none",
"x-user-id": "admin",
"x-xss-protection": "1; mode=block"
}
Web server / Reverse Proxy (Traefik)
None from the day of testing.
Configuration
Nextcloud
occ config:list system:
{
"system": {
"htaccess.RewriteBase": "\/",
"memcache.local": "\\OC\\Memcache\\APCu",
"apps_paths": [
{
"path": "\/var\/www\/html\/apps",
"url": "\/apps",
"writable": false
},
{
"path": "\/var\/www\/html\/custom_apps",
"url": "\/custom_apps",
"writable": true
}
],
"memcache.distributed": "\\OC\\Memcache\\Redis",
"memcache.locking": "\\OC\\Memcache\\Redis",
"redis": {
"host": "***REMOVED SENSITIVE VALUE***",
"password": "***REMOVED SENSITIVE VALUE***",
"port": 6379
},
"trusted_proxies": "***REMOVED SENSITIVE VALUE***",
"upgrade.disable-web": true,
"instanceid": "***REMOVED SENSITIVE VALUE***",
"passwordsalt": "***REMOVED SENSITIVE VALUE***",
"secret": "***REMOVED SENSITIVE VALUE***",
"trusted_domains": [
"nextcloud.mydomain.com"
],
"datadirectory": "***REMOVED SENSITIVE VALUE***",
"dbtype": "mysql",
"version": "32.0.5.0",
"overwrite.cli.url": "https:\/\/nextcloud.mydomain.com",
"dbname": "***REMOVED SENSITIVE VALUE***",
"dbhost": "***REMOVED SENSITIVE VALUE***",
"dbtableprefix": "oc_",
"mysql.utf8mb4": true,
"dbuser": "***REMOVED SENSITIVE VALUE***",
"dbpassword": "***REMOVED SENSITIVE VALUE***",
"installed": true,
"maintenance": false,
"maintenance_window_start": 9
}
}
Apps
occ app:list output:
Enabled:
- activity: 5.0.0-dev.0
- app_api: 32.0.0
- bruteforcesettings: 5.0.0-dev.0
- circles: 32.0.0
- cloud_federation_api: 1.16.0
- comments: 1.22.0
- contactsinteraction: 1.13.1
- dashboard: 7.12.0
- dav: 1.34.2
- federatedfilesharing: 1.22.0
- federation: 1.22.0
- files: 2.4.0
- files_downloadlimit: 5.0.0-dev.0
- files_pdfviewer: 5.0.0-dev.0
- files_reminders: 1.5.0
- files_sharing: 1.24.1
- files_trashbin: 1.22.0
- files_versions: 1.25.0
- firstrunwizard: 5.0.0-dev.0
- logreader: 5.0.0-dev.0
- lookup_server_connector: 1.20.0
- nextcloud_announcements: 4.0.0-dev.0
- notifications: 5.0.0-dev.0
- oauth2: 1.20.0
- password_policy: 4.0.0-dev.0
- photos: 5.0.0-dev.1
- privacy: 4.0.0-dev.0
- profile: 1.1.0
- provisioning_api: 1.22.0
- recommendations: 5.0.0-dev.0
- related_resources: 3.0.0-dev.0
- serverinfo: 4.0.0-dev.0
- settings: 1.15.1
- sharebymail: 1.22.0
- support: 4.0.0-dev.0
- survey_client: 4.0.0-dev.0
- systemtags: 1.22.0
- text: 6.0.1
- theming: 2.7.0
- twofactor_backupcodes: 1.21.0
- updatenotification: 1.22.0
- user_status: 1.12.0
- viewer: 5.0.0-dev.0
- weather_status: 1.12.0
- webhook_listeners: 1.3.0
- workflowengine: 2.14.0
Disabled:
- admin_audit: 1.22.0
- encryption: 2.20.0
- files_external: 1.24.1
- suspicious_login: 10.0.0-dev.0
- twofactor_nextcloud_notification: 6.0.0-dev.0
- twofactor_totp: 14.0.0
- user_ldap: 1.23.0
Docker configuration
Traefik stack’s docker-compose.yml (composed up first):
services:
core_proxy:
container_name: core_proxy
hostname: core_proxy
image: traefik:v3.6
depends_on:
- core_auth
- core_ldap
- core_proxy_socket
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- core_proxy
- core_proxy_socket
ports:
- 80:80
- 443:443
volumes:
- $DIR_APPS_CORE_PROXY/rules:/rules:ro
- $DIR_APPS_CORE_PROXY/traefik.yml:/traefik.yml:ro
- $DIR_LOGS/core.proxy.log:/logs/traefik.log
- $DIR_LOGS/core.proxy.access.log:/logs/access.log
- $DIR_CERTS:/certs
labels:
traefik.enable: true
traefik.http.routers.core_proxy.rule: Host(`traefik.mydomain.com`)
traefik.http.routers.core_proxy.tls: true
traefik.http.routers.core_proxy.entryPoints: websecure
traefik.http.routers.core_proxy.service: api@internal
traefik.http.routers.core_proxy.middlewares: chain-auth-authelia@file
core_proxy_socket:
container_name: core_proxy_socket
image: lscr.io/linuxserver/socket-proxy:latest
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- core_proxy_socket
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
LOG_LEVEL: info
ALLOW_START: 0
ALLOW_STOP: 0
ALLOW_RESTARTS: 0
# allowed by default
EVENTS: 1
PING: 1
VERSION: 1
# revoked by default
AUTH: 0
SECRETS: 0
POST: 0
# optional
BUILD: 0
COMMIT: 0
CONFIGS: 0
CONTAINERS: 1
DISTRIBUTION: 0
EXEC: 0
IMAGES: 0
INFO: 0
NETWORKS: 0
NODES: 0
PLUGINS: 0
SERVICES: 0
SESSION: 0
SWARM: 0
SYSTEM: 0
TASKS: 0
VOLUMES: 0
DISABLE_IPV6: 0
core_auth:
container_name: core_auth
hostname: core_auth
image: authelia/authelia:4.39
depends_on:
- core_ldap
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- core_proxy
- core_ldap
secrets:
- ***REMOVED SENSITIVE VALUE(S)***
volumes:
- $DIR_APPS_CORE_AUTH/configuration.yml:/config/configuration.yml:ro
- $DIR_APPS_CORE_AUTH/notification.txt:/config/notification.txt
- $DIR_DATA_CORE_AUTH:/config/data
- $DIR_CERTS:/config/certificates
- $DIR_LOGS/core.auth.log:/config/authelia.log
environment:
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ADDRESS: 'ldap://core_ldap:3890'
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_BASE_DN: 'dc=mydomain,dc=com'
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_USER: 'uid=myuid,ou=people,DC=mydomain,DC=com'
AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE: ***REMOVED SENSITIVE VALUE***
AUTHELIA_SESSION_SECRET_FILE: ***REMOVED SENSITIVE VALUE***
AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE: ***REMOVED SENSITIVE VALUE***
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE: ***REMOVED SENSITIVE VALUE***
labels:
traefik.enable: true
traefik.http.routers.core_auth.rule: Host(`auth.mydomain.com`)
traefik.http.routers.core_auth.tls: true
traefik.http.routers.core_auth.entryPoints: websecure
traefik.http.routers.core_auth.service: core_auth
traefik.http.routers.core_auth.middlewares: chain-auth-none@file
traefik.http.services.core_auth.loadBalancer.server.url: http://core_auth:9091
core_ldap:
container_name: core_ldap
hostname: core_ldap
image: lldap/lldap:stable
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- core_ldap
- core_proxy
secrets:
- ***REMOVED SENSITIVE VALUE(S)***
volumes:
- $DIR_APPS_CORE_LDAP/lldap_config.toml:/data/lldap_config.toml
- $DIR_DATA_CORE_LDAP:/data/db
environment:
LLDAP_JWT_SECRET_FILE: ***REMOVED SENSITIVE VALUE***
LLDAP_KEY_SEED_FILE: ***REMOVED SENSITIVE VALUE***
LLDAP_LDAP_USER_PASS_FILE: ***REMOVED SENSITIVE VALUE***
labels:
traefik.enable: true
traefik.http.routers.core_ldap.rule: Host(`sso.mydomain.com`)
traefik.http.routers.core_ldap.tls: true
traefik.http.routers.core_ldap.entryPoints: websecure
traefik.http.routers.core_ldap.service: core_ldap
traefik.http.routers.core_ldap.middlewares: chain-auth-none@file
traefik.http.services.core_ldap.loadBalancer.server.url: http://core_ldap:17170
networks:
core_ldap:
name: core_ldap
core_proxy:
name: core_proxy
driver: bridge
ipam:
config:
- subnet: 192.168.90.0/24
core_proxy_socket:
name: core_proxy_socket
secrets:
***REMOVED SENSITIVE VALUE(S)***
Nextcloud stack’s docker-compose.yml (composed up after Traefik - I’ll be using Authelia for single-sign-on in Nextcloud but I haven’t configured that yet):
services:
cloud:
container_name: cloud
hostname: cloud
image: nextcloud
depends_on:
- cloud_db
- cloud_redis
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- core_proxy
- cloud_db
- cloud_harp
- cloud_redis
volumes:
- $DIR_DATA_CLOUD:/var/www/html
environment:
NEXTCLOUD_HOSTNAME: nextcloud.mydomain.com
NEXTCLOUD_TRUSTED_DOMAIN: nextcloud.mydomain.com
TRUSTED_PROXIES: 192.168.90.0/24
REDIS_HOST: cloud_redis
labels:
traefik.enable: true
traefik.http.routers.cloud.rule: Host(`nextcloud.mydomain.com`)
traefik.http.routers.cloud.tls: true
traefik.http.routers.cloud.entryPoints: websecure
traefik.http.routers.cloud.service: cloud
traefik.http.routers.cloud.middlewares: chain-auth-authelia-cloud@file
traefik.http.services.cloud.loadBalancer.server.url: http://cloud:80
cloud_harp:
container_name: cloud_harp
hostname: cloud_harp
image: ghcr.io/nextcloud/nextcloud-appapi-harp:release
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- cloud_harp
secrets:
- cloud_harp_pass
volumes:
- $DIR_CERTS:/certs
- /var/run/docker.sock:/var/run/docker.sock
environment:
HP_SHARED_KEY_FILE: ***REMOVED SENSITIVE VALUE***
NC_INSTANCE_URL: https://nextcloud.mydomain.com
HP_TRUSTED_PROXY_IPS: 192.168.90.0/24
labels:
traefik.enable: true
traefik.http.routers.cloud_harp.rule: Host(`nextcloud.mydomain.com`) && PathPrefix(`/exapps/`)
traefik.http.routers.cloud_harp.entrypoints: web
traefik.http.routers.cloud_harp.service: cloud_harp
traefik.http.services.cloud_harp.loadBalancer.server.url: http://127.0.0.1:8780
cloud_db:
container_name: cloud_db
hostname: cloud_db
image: mariadb:lts
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- cloud_db
secrets:
- ***REMOVED SENSITIVE VALUE(S)***
volumes:
- $DIR_DATA_CLOUD_DB:/var/lib/mysql
command:
--transaction-isolation=READ-COMMITTED
environment:
MYSQL_ROOT_PASSWORD_FILE: ***REMOVED SENSITIVE VALUE***
MYSQL_DATABASE_FILE: ***REMOVED SENSITIVE VALUE***
MYSQL_USER_FILE: ***REMOVED SENSITIVE VALUE***
MYSQL_PASSWORD_FILE: ***REMOVED SENSITIVE VALUE***
cloud_redis:
container_name: cloud_redis
hostname: cloud_redis
image: redis:alpine
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- cloud_redis
networks:
core_proxy:
external: true
cloud_db:
name: cloud_db
cloud_harp:
name: cloud_harp
cloud_redis:
name: cloud_redis
secrets:
***REMOVED SENSITIVE VALUE(S)***
Traefik configuration
traefik.yml:
api:
dashboard: true
insecure: true
debug: false
global:
checkNewVersion: false
sendAnonymousUsage: false
providers:
docker:
endpoint: tcp://core_proxy_socket:2375
exposedByDefault: false
network: core_proxy
file:
directory: /rules
watch: true
# ---HTTP---
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
websecure:
address: ":443"
# ---LOGGING---
log:
filePath: /logs/traefik.log
level: INFO
accessLog:
filePath: /logs/access.log
bufferingSize: 100
filters:
statusCodes:
- 204-299
- 400-499
- 500-599
dynamic.yml (combined, these are in a handful of files in the rules folder):
tls:
stores:
default:
defaultCertificate:
certFile: /certs/mydomain.com.crt
keyFile: /certs/mydomain.com.key
certificates:
- certFile: /certs/mydomain.com.crt
keyFile: /certs/mydomain.com.key
stores:
- default
http:
middlewares:
chain-auth-none:
chain:
middlewares:
- middlewares-rate-limit
- middlewares-secure-headers
chain-auth-authelia:
chain:
middlewares:
- middlewares-auth-authelia
- middlewares-rate-limit
- middlewares-secure-headers
chain-auth-authelia-cloud:
chain:
middlewares:
- middlewares-auth-authelia
- middlewares-rate-limit
- middlewares-redirect-cloud
- middlewares-secure-headers-cloud
middlewares-auth-authelia:
forwardAuth:
address: "http://core_auth:9091/api/verify?rd=https://auth.mydomain.com"
trustForwardHeader: true
authResponseHeaders:
- "Remote-User"
- "Remote-Groups"
middlewares-rate-limit:
rateLimit:
average: 100
burst: 50
middlewares-redirect-cloud:
redirectRegex:
permanent: true
regex: https://(.*)/.well-known/(card|cal)dav
replacement: https://${1}/remote.php/dav/
middlewares-secure-headers:
headers:
accessControlAllowMethods:
- GET
- OPTIONS
- PUT
accessControlMaxAge: 100
hostsProxyHeaders:
- "X-Forwarded-Host"
stsSeconds: 63072000
stsIncludeSubdomains: true
stsPreload: true
customFrameOptionsValue: SAMEORIGIN
contentTypeNosniff: true
browserXssFilter: true
referrerPolicy: same-origin
permissionsPolicy: "camera=(), microphone=(), geolocation=(), payment=(), usb=(), vr=()"
customResponseHeaders:
X-Robots-Tag: none,noarchive,nosnippet,notranslate,noimageindex,
server: ""
middlewares-secure-headers-cloud:
headers:
accessControlAllowMethods:
- GET
- OPTIONS
- PUT
accessControlMaxAge: 100
hostsProxyHeaders:
- "X-Forwarded-Host"
sslRedirect: true
stsSeconds: 15752000
stsIncludeSubdomains: true
stsPreload: true
forceSTSHeader: true
customFrameOptionsValue: SAMEORIGIN
contentTypeNosniff: true
browserXssFilter: true
referrerPolicy: no-referrer
permissionsPolicy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), vr=()
customResponseHeaders:
X-Robots-Tag: none
server: ""
Happy to provide additional context if it would be useful o7 thanks in advance!