docker
docker copied to clipboard
Cannot fix warning message "The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy. If not, this is a security issue and can allow an attacker to spoof their IP address as visible to the Nextcloud. Further information can be found in the documentation."
No matter what I can't get rid of this warning message
The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy. If not, this is a security issue and can allow an attacker to spoof their IP address as visible to the Nextcloud. Further information can be found in the documentation.
I'm using traefik 2.3 with this static setting:
entryPoints:
web:
address: ":80"
# If you set up a new service you need to open port 80 for CERT
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
api:
dashboard: true
providers:
docker:
# Do not expose containers unless explicitly told so
exposedByDefault: false
#log:
# level: DEBUG
# filePath: "/var/logs/traefik/traefik.log"
#accessLog:
# filePath: "/var/logs/traefik/access.log"
certificatesResolvers:
letsencrypt:
acme:
#comment the line below for live server
#caserver: https://acme-staging-v02.api.letsencrypt.org/directory
email: [email protected]
storage: /etc/traefik/acme.json
httpChallenge:
# used during the challenge
entryPoint: web
and my docker-compose:
version: '3.5'
#USE .env!!!
services:
db:
image: mariadb
container_name: nextcloud_db
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
restart: always
volumes:
- db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=asecret
env_file:
- db.env
redis:
image: redis:alpine
container_name: nextcloud_redis
restart: always
app:
image: nextcloud:fpm-alpine
container_name: nextcloud_app
restart: always
volumes:
- nextcloud:/var/www/html
environment:
- MYSQL_HOST=db
- REDIS_HOST=redis
env_file:
- db.env
depends_on:
- db
- redis
web:
image: nginx:alpine
container_name: nextcloud_web
restart: always
ports:
- "9999:80"
expose:
- '443'
volumes:
- nextcloud:/var/www/html:ro
- ./web/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- app
labels:
# Explicitly tell Traefik to expose this container
- traefik.enable=true
- traefik.http.routers.nextcloud.rule=Host(`${NEXTCLOUDHOST}`)
- traefik.http.services.nextcloud.loadbalancer.server.port=80
- traefik.http.routers.nextcloud.tls=true
- traefik.http.routers.nextcloud.tls.certresolver=letsencrypt
- traefik.http.routers.nextcloud.middlewares=nn-header,nextcloud-dav
- traefik.http.middlewares.nn-header.headers.customRequestHeaders.X-Forwarded-Proto=https
- traefik.http.middlewares.nn-header.headers.sslredirect=true
- traefik.http.middlewares.nn-header.headers.STSSeconds=15552000
- traefik.http.middlewares.nn-header.headers.STSIncludeSubdomains=true
- traefik.http.middlewares.nn-header.headers.accessControlAllowOriginList=wss://${NEXTCLOUDHOST},https://${NEXTCLOUDHOST}
- traefik.http.middlewares.nn-redirect.redirectregex.permanent=true
- traefik.http.middlewares.nextcloud-dav.replacepathregex.regex=^/.well-known/ca(l|rd)dav
- traefik.http.middlewares.nextcloud-dav.replacepathregex.replacement=/remote.php/dav/
networks:
default:
cloud_managment:
aliases:
- nextcloud
onlyoffice:
image: onlyoffice/documentserver
container_name: nextcloud_onlyoffice
restart: always
stdin_open: true
expose:
- '80'
- '443'
tty: true
volumes:
- ./onlyoffice/log:/var/log/onlyoffice
- ./onlyoffice/Data:/var/www/onlyoffice/Data
- ./onlyoffice/onlyoffice:/var/lib/onlyoffice
- ./onlyoffice/postgresql:/var/lib/postgresql
labels:
# Explicitly tell Traefik to expose this container
- traefik.enable=true
- traefik.http.routers.onlyoffice.rule=Host(`${ONLYOFFICEHOST}`)
- traefik.http.middlewares.oo-header.headers.customRequestHeaders.X-Forwarded-Proto=https
- traefik.http.middlewares.oo-header.headers.accessControlAllowOriginList=*
- traefik.http.routers.onlyoffice.middlewares=oo-header
- traefik.http.routers.onlyoffice.tls=true
- traefik.http.routers.onlyoffice.tls.certresolver=letsencrypt
networks:
default:
cloud_managment:
cron:
image: nextcloud:fpm-alpine
container_name: nextcloud_cron
restart: always
volumes:
- nextcloud:/var/www/html
entrypoint: /cron.sh
depends_on:
- db
- redis
networks:
default:
name: nextcloud
cloud_managment:
external: true
volumes:
db:
nextcloud:
my config.php has these:
'trusted_domains' =>
array (
0 => 'nextcloud.example.com',
1 => 'nextcloud_web',
2 => 'traefik',
),
'forwarded-for-headers' =>
array (
0 => 'X-Forwarded-For',
1 => 'HTTP_X_FORWARDED_FOR',
),
'overwriteprotocol' => 'https',
'overwritehost' => 'nextcloud.example.com',
'overwrite.cli.url' => 'https://nextcloud.example.com',
my ngix.conf:
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
upstream php-handler {
server app:9000;
}
map $http_host $this_host {
"" $host;
default $http_host;
}
map $http_x_forwarded_proto $the_scheme {
default $http_x_forwarded_proto;
"" $scheme;
}
map $http_x_forwarded_host $the_host {
default $http_x_forwarded_host;
"" $this_host;
}
server {
listen 80;
# WARNING: Only add the preload option once you read about
# the consequences in https://hstspreload.org/. This option
# will add the domain to a hardcoded list that is shipped
# in all major browsers and getting removed from this list
# could take several months.
# Before enabling Strict-Transport-Security headers please read into this
# topic first.
#add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
#
# Add headers to serve security related headers
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 "none" always;
add_header X-XSS-Protection "1; mode=block" always;
# Remove X-Powered-By, which is an information leak
fastcgi_hide_header X-Powered-By;
# Path to the root of your installation
root /var/www/html;
# Specify how to handle directories -- specifying `/index.php$request_uri`
# here as the fallback means that Nginx always exhibits the desired behaviour
# when a client requests a path that corresponds to a directory that exists
# on the server. In particular, if that directory contains an index.php file,
# that file is correctly served; if it doesn't, then the request is passed to
# the front-end controller. This consistent behaviour means that we don't need
# to specify custom rules for certain paths (e.g. images and other assets,
# `/updater`, `/ocm-provider`, `/ocs-provider`), and thus
# `try_files $uri $uri/ /index.php$request_uri`
# always provides the desired behaviour.
index index.php index.html $scheme://$host:$server_port/index.php$request_uri;
# Rule borrowed from `.htaccess` to handle Microsoft DAV clients
location = / {
if ( $http_user_agent ~ ^DavClnt ) {
return 302 $scheme://$host:$server_port/remote.php/webdav/$is_args$args;
}
}
location ~* ^/ds-vpath/ {
rewrite /ds-vpath/(.*) /$1 break;
proxy_pass http://nextcloud_onlyoffice;
proxy_redirect off;
client_max_body_size 100m;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $the_host/ds-vpath;
proxy_set_header X-Forwarded-Proto $the_scheme;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location = /data/htaccesstest.txt {
allow all;
log_not_found off;
access_log off;
}
# The following 2 rules are only needed for the user_webfinger app.
# Uncomment it if you're planning to use this app.
#rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
#rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
# The following rule is only needed for the Social app.
# Uncomment it if you're planning to use this app.
#rewrite ^/.well-known/webfinger /public.php?service=webfinger last;
# Make a regex exception for `/.well-known` so that clients can still
# access it despite the existence of the regex rule
# `location ~ /(\.|autotest|...)` which would otherwise handle requests
# for `/.well-known`.
# location ^~ /.well-known {
# The following 6 rules are borrowed from `.htaccess`
# rewrite ^/\.well-known/host-meta\.json $scheme://$host:$server_port/public.php?service=host-meta-json last;
# rewrite ^/\.well-known/host-meta $scheme://$host:$server_port/public.php?service=host-meta last;
# rewrite ^/\.well-known/webfinger $scheme://$host:$server_port/public.php?service=webfinger last;
# rewrite ^/\.well-known/nodeinfo $scheme://$host:$server_port/public.php?service=nodeinfo last;
#
# location = /.well-known/carddav { return 301 $scheme://$host:$server_port/remote.php/dav/; }
# location = /.well-known/caldav { return 301 $scheme://$host:$server_port/remote.php/dav/; }
# try_files $uri $uri/ =404;
# }
# Make a regex exception for `/.well-known` so that clients can still
# access it despite the existence of the regex rule
# `location ~ /(\.|autotest|...)` which would otherwise handle requests
# for `/.well-known`.
location ^~ /.well-known {
# The following 6 rules are borrowed from `.htaccess`
location = /.well-known/carddav { return 301 $scheme://$host:$server_port/remote.php/dav/; }
location = /.well-known/caldav { return 301 $scheme://$host:$server_port/remote.php/dav/; }
location = /.well-known/webfinger { return 301 $scheme://$host:$server_port/public.php?service=webfinger; }
# Anything else is dynamically handled by Nextcloud
location ^~ /.well-known { return 301 $scheme://$host:$server_port/index.php$uri; }
try_files $uri $uri/ =404;
}
#location = /.well-known/carddav {
# return 301 $scheme://$host:$server_port/remote.php/dav;
#}
#location = /.well-known/caldav {
# return 301 $scheme://$host:$server_port/remote.php/dav;
#}
# set max upload size
client_max_body_size 10G;
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;
# Uncomment if your server is build with the ngx_pagespeed module
# This module is currently not supported.
#pagespeed off;
location / {
rewrite ^ /index.php;
}
location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
deny all;
}
location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
deny all;
}
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) {
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;
# Avoid sending the security headers twice
fastcgi_param modHeadersAvailable true;
# Enable pretty urls
fastcgi_param front_controller_active true;
fastcgi_pass php-handler;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
}
location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
try_files $uri/ =404;
index index.php;
}
# Adding the cache control header for js, css and map files
# Make sure it is BELOW the PHP block
location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463";
# Add headers to serve security related headers (It is intended to
# have those duplicated to the ones above)
# Before enabling Strict-Transport-Security headers please read into
# this topic first.
#add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
#
# WARNING: Only add the preload option once you read about
# the consequences in https://hstspreload.org/. This option
# will add the domain to a hardcoded list that is shipped
# in all major browsers and getting removed from this list
# could take several months.
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 "none" always;
add_header X-XSS-Protection "1; mode=block" always;
# Optional: Don't log access to assets
access_log off;
}
location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$ {
try_files $uri /index.php$request_uri;
# Optional: Don't log access to other assets
access_log off;
}
}
}
I have no idea what I am doing wrong anymore
Not a pro, but I would guess your trusted_domain is to be blamed. This has to be set to the external url of your server
Not a pro, but I would guess your trusted_domain is to be blamed. This has to be set to the external url of your server
@supermar1010 that would be nextcloud.example.com
or should I put example.com
as well?
My nextcloud domain is: cloud.example.com.
My trusted_domains look like this:
'trusted_domains' =>
array (
0 => 'localhost',
1 => 'cloud.example.com',
),
sadly didn't solve it, when I added localhost :(
It should be the ip address of the nginx:alpine container. That the proxy. Mine was 'trusted_domains' => array ( 0 => '192.168.1.10', 1 => 'cloud.example.com', ),
Set a static Ip address for it
I solved this problem by assigning a static IP to the traefik proxy network and putting this IP range as trusted proxy in the nextcloud configuration:
docker-compose for traefik:
version: '3.7'
networks:
proxy:
name: traefik_proxy
ipam:
config:
- subnet: 172.33.0.0/16
services:
traefik:
image: "traefik:latest"
container_name: "traefik"
ports:
- "80:80"
- "443:443"
- "8080:8080"
networks:
- proxy
volumes:
- "./config/traefik.toml:/etc/traefik/traefik.toml:ro"
- "./config/dynamic.toml:/etc/traefik/dynamic.toml:ro"
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
docker-compose for nextcloud:
version: '3.7'
networks:
nextcloud:
proxy:
external:
name: traefik_proxy
services:
db:
image: mariadb
restart: always
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
volumes:
- "./db:/var/lib/mysql"
networks:
- nextcloud
environment:
- MYSQL_ROOT_PASSWORD=passwordpassword
- MYSQL_PASSWORD=password
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
redis:
image: redis:latest
restart: always
networks:
- nextcloud
volumes:
- "./redis:/var/lib/redis"
app:
image: nextcloud:latest
restart: always
networks:
- nextcloud
- proxy
depends_on:
- db
- redis
volumes:
- "./nextcloud:/var/www/html"
- "./apps:/var/www/html/custom_apps"
- "./config:/var/www/html/config"
- "./data:/var/www/html/data"
environment:
- REDIS_HOST=redis
- MYSQL_PASSWORD=password
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_HOST=db
- TRUSTED_PROXIES=172.33.0.0/16
- NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.domain.org
labels:
- traefik.enable=true
- traefik.protocol=http
- traefik.docker.network=traefik_proxy
- traefik.port=80
- traefik.http.services.nextcloud.loadbalancer.server.port=80
- traefik.http.routers.nextcloud.middlewares=nextcloud,nextcloud_redirect
- traefik.http.routers.nextcloud.tls=true
- traefik.http.routers.nextcloud.entrypoints=websecure
- traefik.http.routers.nextcloud.tls.certresolver=letsencrypt
- traefik.http.routers.nextcloud.rule=Host(`nextcloud.domain.org`)
- traefik.http.middlewares.nextcloud.headers.contentSecurityPolicy=frame-ancestors 'self' domain.org *.domain.org
- traefik.http.middlewares.nextcloud.headers.stsSeconds=155520011
- traefik.http.middlewares.nextcloud.headers.stsIncludeSubdomains=true
- traefik.http.middlewares.nextcloud.headers.stsPreload=true
- traefik.http.middlewares.nextcloud_redirect.redirectregex.regex=/.well-known/(card|cal)dav
- traefik.http.middlewares.nextcloud_redirect.redirectregex.replacement=/remote.php/dav/
I solved this problem by assigning a static IP to the traefik proxy network and putting this IP range as trusted proxy in the nextcloud configuration:
docker-compose for traefik:
version: '3.7' networks: proxy: name: traefik_proxy ipam: config: - subnet: 172.33.0.0/16 services: traefik: image: "traefik:latest" container_name: "traefik" ports: - "80:80" - "443:443" - "8080:8080" networks: - proxy volumes: - "./config/traefik.toml:/etc/traefik/traefik.toml:ro" - "./config/dynamic.toml:/etc/traefik/dynamic.toml:ro" - "./letsencrypt:/letsencrypt" - "/var/run/docker.sock:/var/run/docker.sock:ro"
docker-compose for nextcloud:
version: '3.7' networks: nextcloud: proxy: external: name: traefik_proxy services: db: image: mariadb restart: always command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW volumes: - "./db:/var/lib/mysql" networks: - nextcloud environment: - MYSQL_ROOT_PASSWORD=passwordpassword - MYSQL_PASSWORD=password - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud redis: image: redis:latest restart: always networks: - nextcloud volumes: - "./redis:/var/lib/redis" app: image: nextcloud:latest restart: always networks: - nextcloud - proxy depends_on: - db - redis volumes: - "./nextcloud:/var/www/html" - "./apps:/var/www/html/custom_apps" - "./config:/var/www/html/config" - "./data:/var/www/html/data" environment: - REDIS_HOST=redis - MYSQL_PASSWORD=password - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud - MYSQL_HOST=db - TRUSTED_PROXIES=172.33.0.0/16 - NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.domain.org labels: - traefik.enable=true - traefik.protocol=http - traefik.docker.network=traefik_proxy - traefik.port=80 - traefik.http.services.nextcloud.loadbalancer.server.port=80 - traefik.http.routers.nextcloud.middlewares=nextcloud,nextcloud_redirect - traefik.http.routers.nextcloud.tls=true - traefik.http.routers.nextcloud.entrypoints=websecure - traefik.http.routers.nextcloud.tls.certresolver=letsencrypt - traefik.http.routers.nextcloud.rule=Host(`nextcloud.domain.org`) - traefik.http.middlewares.nextcloud.headers.contentSecurityPolicy=frame-ancestors 'self' domain.org *.domain.org - traefik.http.middlewares.nextcloud.headers.stsSeconds=155520011 - traefik.http.middlewares.nextcloud.headers.stsIncludeSubdomains=true - traefik.http.middlewares.nextcloud.headers.stsPreload=true - traefik.http.middlewares.nextcloud_redirect.redirectregex.regex=/.well-known/(card|cal)dav - traefik.http.middlewares.nextcloud_redirect.redirectregex.replacement=/remote.php/dav/
Thanks, this worked for Nginx Proxy Manager as well
Closing as this seems addressed and there's nothing actionable remaining to do here that is related to the image itself.