Nextcloud AIO behind Nginx Proxy Manager, questions for Security measures, real IP

Hello everyone,
I now have my Nextcloud AIO running pretty well and am taking care of hardening and security measures, among other things.
I have set up AIO and also configured the Nginx Proxy Manager using the information provided in Github.
I think some things are more difficult via the proxy concept. For example, I had to define the IP of the proxy manager as trusted_proxies because the BruteFoce Feature blocks me every time.
I think that the IP from the proxy may now always arrive at the Nextcloud and not the real IP. Therefore I think they is no longer a functionality of the BruceForce feature or?

My questions would now be maybe anyone else uses the Nginx Proxy Manager constellation before Nextcloud AIO and what security measures you have set or still have installed.
It would be great if someone share their experiences and instructions of hardening the AIO behind a Nginx Proxy Manager…

take a look at this article

it’s not specific to NPM but it should be easy to adopt for NPM as well.

If you setup your reverseproxy and Nextcloud right you will receive real-ip in the logs and security features like bruteforce protection remain operable as well.

Thanks for the link. It’s very interesting but it’s really hard for me to understanding it. I’m looking into it but I’m afraid … at the end I think it is possible that I don’t understand exactly what I need to configure and where.

The real IP is something you has to look into and understand. It is on one side a simple logic and on the other side technically hard. Technically hard because there is so many pitfalls if you do not know what you are doing. Sorry to say it like that.

NGINX supports the proxy protocol so if the Webserver running your Nextcloud is also NGINX it COULD be simple to add. If not, you has to look into web server moduler like RemoteIP and tweak them.

1 Like

:slightly_smiling_face:
Hoped it would be easier to understand and there would be instructions for beginners :grinning: I have to deal with it and hope my Nextcloud login with 2FA is secure enough for now. Would it be easier if I didn’t use Nginx Proxy Manager but this traefik I always read about?

In regard to real IP: Same.

Search Google for RemoteIP and proxy-protocol and start digging Down into that to get an idea. Maybe proxy-protocol-V2 if you use SSL passthrough. Point is that it is either RemoteIP or TrustedProxy.

The point of configuring trusted_proxies is so that Nextcloud knows there is an intermediate proxy. It then looks at the appropriate header(s) provided by the proxy to gain the real IP address of the end client. If the IP addresses of remote clients are now accurate from Nextcloud’s perspective, brute force protection should work just fine.

Not sure if you saw the latest docs, but the BFP chapter was just recently revised and expanded:

https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/bruteforce_configuration.html

1 Like

Thank you very much! I have now read it. So if I understand this correctly and after checking my configuration, it should be everything ok. So the BruteForce function should still be there and my question whether I still have a working BruteForce function is answered…

No guarantees.

You can consider it like this:
You still needs to add the forwarded for headers for each proxy (you probably only have one) and that header needs to be understood by your webserver which serves your Nextcloud. That module needs to be set up and activated in order for Nextcloud to have any proxy IP’s to fetch from the connection. So not only do you need to add the proxies you trusts (your own and the docker network bridge where you attaches a proxy device to your Docker container - if not binding your hosts LAN device to your docker to get a LAN IP of your Home network).
So: if you still only sees the 127.0.0.1 address, it is because the webserver is not correctly configured to read the forwarded for header or because your proxy is not configured to add it. No Nextcloud config can change that.

You are so right. I logged in incorrectly to Nextcloud several times while I was away. BF slowed down my registration process massively. When I looked in the admin settings I could see that Nextcloud only saw the address 127.0.0.1, which basically slowed me down. So everyone gets through with 127.0.0.1 for me.

I can’t understand why there aren’t any simpler instructions, even for beginners, and I can’t be the only one who uses this constellation of Nginx Proxy Manager (docker) and Nextcloud AIO behind it. I’m trying to understand it but it seems like it’s overwhelming me. I think from a security perspective, I am not allowed to run my own Nextcloud.
I’m thinking about what I can do. I understood I need to configure the Nginx proxy manager to send the correct header information. In the next step, Nextcloud’s web server must be able to evaluate this information. This probably happens through the remoteip module. It’s Nextcloud AIO, so I think or hope that this module is already automatically included in the container.

I’m also thinking about no longer using a proxy for the Nextcloud and somehow establishing the connection directly from the router. I also don’t want to rule out the possibility that the proxy doesn’t know the remote IP at all. What if only the OpenWRT router knows this and forwards it to the proxy?
I’m frustrated to the max and will have to deal with it further when I find new motivation.

I still have so many problems with my instance that don’t want to work. The next one is fail2ban, also difficult to understand for beginners…

EDIT:
When I look around in the apache container of nextcloud-aio-apache, the module remoteip actually doesn’t seem to be loaded. It’s commented out in httpd.conf and I can’t change it because I apparently only have read only rights.

The AIO solutions has “easy” configs for this, but I do not use nor have I ever used them myself, why I hope some of the maintaners of those will answer you here.

I had the same issue with my own installation for a while, which was the reason I ventured down the path of understanding and setting this up myself.

This is what I ended up with (I am using HAProxy and not NGINX, so I am using the proxy-protocol-V2). Be aware that I have changed the IP adresses in the below to be generic, just to give an idea. If you use NGINX, it might not be the same module you has to use.

<VirtualHost *:443>
ServerName cloud.mydomain.dom
ServerAdmin info@mydomain.com
DocumentRoot /var/www/nextcloud
RemoteIPProxyProtocol On
RemoteIPTrustedProxy 10.1.0.1
RemoteIPTrustedProxy 192.168.1.2
RemoteIPTrustedProxy 192.168.1.1

<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=15768000; preload"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Prevent MIME based attacks
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
</IfModule>
# SSL Configuration - uses strong cipher list - these might need to be downgraded if you need to support older browsers/devices
SSLEngine on
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLProtocol +TLSv1.2 +TLSv1.3
SSLHonorCipherOrder On

Turn of the bruteforce protection until you figures this out, so at least it is not locking your out.

Thank you for your effort. I also hope that someone who has the same situation as me will get in touch. I will take a closer look at your information and look into it. Maybe I just need to somehow get the remoteip module activated in the AIO Apache.
The BF thought I would leave it on so that I would have any protection at all. If I lock myself out, I have an occ command that I can use to reset BF in the console. That was my plan now but maybe you’re right and I’ll deactivate it completely.

To avoid endless speculation and guesswork, can you simply post:

  • your actual Docker Compose file
  • your NPM configuration
  • your Nextcloud config

Hi jtr,
Thank your for your help. Ok, here all the informations…
The whole line from dial-up router (provider) to Nextcloud:

  1. Router from Provider (does the internet connection forwarding to OpenWRT
  2. OpenWRT Router, forwarding 80/443 to VM1 with Nginx Proxy Manager
  3. VM 1 with Nginx Proxy Manager (Docker)
  4. VM 2 with Nextcloud AIO Docker

Nginx Proxy Manager config:

  1. Proxy Host “mynextclouddomain.org”
    Details:
Scheme = http
Forward Hostname / IP = "IP from VM2"
Forward Port = 11000
Block Commons Exploits = active
Websocket Support = active

SSL:

SSL-Certificate = from Lets Encrypt
Force SSL = acitve
HTTP/2 Support = active

Advanced:
Custom NGINX Configuration

client_body_buffer_size 512k;
proxy_read_timeout 86400s;
client_max_body_size 0;
proxy_set_header X-Real-IP  $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;

Docker-Compose File:

services:
  nextcloud-aio-mastercontainer:
    image: nextcloud/all-in-one:latest
    init: true
    restart: always
    container_name: nextcloud-aio-mastercontainer # This line is not allowed to be changed as otherwise AIO will not work correctly
    volumes:
      - nextcloud_aio_mastercontainer:/mnt/docker-aio-config # This line is not allowed to be changed as otherwise the built-in backup solution will not work
      - /var/run/user/1002/docker.sock:/var/run/docker.sock:ro # May be changed on macOS, Windows or docker rootless. See the applicable documentation. If adjusting, don't forget to also set 'WATCHTOWER_DOCKER_SOCKET_PATH'!
      #- $XDG_RUNTIME_DIR/docker.sock:/var/run/docker.sock:ro # Variable ĂĽber Portainer nicht verfĂĽgbar
    ports:
      #- 80:80 # Can be removed when running behind a web server or reverse proxy (like Apache, Nginx, Cloudflare Tunnel and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
      - 8080:8080
      #- 8443:8443 # Can be removed when running behind a web server or reverse proxy (like Apache, Nginx, Cloudflare Tunnel and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
    environment: # Is needed when using any of the options below
      # - AIO_DISABLE_BACKUP_SECTION=false # Setting this to true allows to hide the backup section in the AIO interface. See https://github.com/nextcloud/all-in-one#how-to-disable-the-backup-section
      - APACHE_PORT=11000 # Is needed when running behind a web server or reverse proxy (like Apache, Nginx, Cloudflare Tunnel and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
      - APACHE_IP_BINDING=0.0.0.0 # Should be set when running behind a web server or reverse proxy (like Apache, Nginx, Cloudflare Tunnel and else) that is running on the same host. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
      # - BORG_RETENTION_POLICY=--keep-within=7d --keep-weekly=4 --keep-monthly=6 # Allows to adjust borgs retention policy. See https://github.com/nextcloud/all-in-one#how-to-adjust-borgs-retention-policy
      # - COLLABORA_SECCOMP_DISABLED=false # Setting this to true allows to disable Collabora's Seccomp feature. See https://github.com/nextcloud/all-in-one#how-to-disable-collaboras-seccomp-feature
      # - NEXTCLOUD_DATADIR=/mnt/ncdata # Allows to set the host directory for Nextcloud's datadir. ⚠️⚠️⚠️ Warning: do not set or adjust this value after the initial Nextcloud installation is done! See https://github.com/nextcloud/all-in-one#how-to-change-the-default-location-of-nextclouds-datadir
      # - NEXTCLOUD_MOUNT=/mnt/ # Allows the Nextcloud container to access the chosen directory on the host. See https://github.com/nextcloud/all-in-one#how-to-allow-the-nextcloud-container-to-access-directories-on-the-host
      # - NEXTCLOUD_UPLOAD_LIMIT=10G # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-upload-limit-for-nextcloud
      # - NEXTCLOUD_MAX_TIME=3600 # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-max-execution-time-for-nextcloud
      # - NEXTCLOUD_MEMORY_LIMIT=512M # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-php-memory-limit-for-nextcloud
      # - NEXTCLOUD_TRUSTED_CACERTS_DIR=/path/to/my/cacerts # CA certificates in this directory will be trusted by the OS of the nexcloud container (Useful e.g. for LDAPS) See See https://github.com/nextcloud/all-in-one#how-to-trust-user-defined-certification-authorities-ca
      # - NEXTCLOUD_STARTUP_APPS=deck twofactor_totp tasks calendar contacts notes # Allows to modify the Nextcloud apps that are installed on starting AIO the first time. See https://github.com/nextcloud/all-in-one#how-to-change-the-nextcloud-apps-that-are-installed-on-the-first-startup
      # - NEXTCLOUD_ADDITIONAL_APKS=imagemagick # This allows to add additional packages to the Nextcloud container permanently. Default is imagemagick but can be overwritten by modifying this value. See https://github.com/nextcloud/all-in-one#how-to-add-os-packages-permanently-to-the-nextcloud-container
      # - NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS=imagick # This allows to add additional php extensions to the Nextcloud container permanently. Default is imagick but can be overwritten by modifying this value. See https://github.com/nextcloud/all-in-one#how-to-add-php-extensions-permanently-to-the-nextcloud-container
      # - NEXTCLOUD_ENABLE_DRI_DEVICE=true # This allows to enable the /dev/dri device in the Nextcloud container. ⚠️⚠️⚠️ Warning: this only works if the '/dev/dri' device is present on the host! If it should not exist on your host, don't set this to true as otherwise the Nextcloud container will fail to start! See https://github.com/nextcloud/all-in-one#how-to-enable-hardware-transcoding-for-nextcloud
      # - NEXTCLOUD_KEEP_DISABLED_APPS=false # Setting this to true will keep Nextcloud apps that are disabled in the AIO interface and not uninstall them if they should be installed. See https://github.com/nextcloud/all-in-one#how-to-keep-disabled-apps
      # - TALK_PORT=3478 # This allows to adjust the port that the talk container is using. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-talk-port
      - WATCHTOWER_DOCKER_SOCKET_PATH=/var/run/user/1002/docker.sock # Needs to be specified if the docker socket on the host is not located in the default '/var/run/docker.sock'. Otherwise mastercontainer updates will fail. For macos it needs to be '/var/run/docker.sock'
      #- APACHE_DISABLE_REWRITE_IP=
      - NEXTCLOUD_TRUSTED_DOMAINS=mynextclouddomain.org 192.168.1.10 192.168.1.12 # Your domain name + proxy host IP
      - TRUSTED_PROXIES=127.0.0.1 172.18.0.1 172.19.0.1 # proxy host IP
      #- SKIP_DOMAIN_VALIDATION=true
      - AIO_COMMUNITY_CONTAINERS=fail2ban
    # networks: # Is needed when you want to create the nextcloud-aio network with ipv6-support using this file, see the network config at the bottom of the file
      # - nextcloud-aio # Is needed when you want to create the nextcloud-aio network with ipv6-support using this file, see the network config at the bottom of the file
    # # Uncomment the following line when using SELinux
    # security_opt: ["label:disable"]

  # # Optional: Caddy reverse proxy. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
  # # You can find further examples here: https://github.com/nextcloud/all-in-one/discussions/588
  # caddy:
  #   image: caddy:alpine
  #   restart: always
  #   container_name: caddy
  #   volumes:
  #     - ./Caddyfile:/etc/caddy/Caddyfile
  #     - ./certs:/certs
  #     - ./config:/config
  #     - ./data:/data
  #     - ./sites:/srv
  #   network_mode: "host"

volumes: # If you want to store the data on a different drive, see https://github.com/nextcloud/all-in-one#how-to-store-the-filesinstallation-on-a-separate-drive
  nextcloud_aio_mastercontainer:
    name: nextcloud_aio_mastercontainer # This line is not allowed to be changed as otherwise the built-in backup solution will not work

# # Optional: If you need ipv6, follow step 1 and 2 of https://github.com/nextcloud/all-in-one/blob/main/docker-ipv6-support.md first and then uncomment the below config in order to activate ipv6 for the internal nextcloud-aio network.
# # Please make sure to uncomment also the networking lines of the mastercontainer above in order to actually create the network with docker-compose
#networks:
 # nextcloud-aio:
  #  name: nextcloud-aio # This line is not allowed to be changed as otherwise the created network will not be used by the other containers of AIO
   # driver: bridge
#     enable_ipv6: true
#     ipam:
#       driver: default
#       config:
#         - subnet: fd12:3456:789a:2::/64 # IPv6 subnet to use
#

My config.php

cat config.php
<?php
$CONFIG = array (
  'one-click-instance' => true,
  'one-click-instance.user-limit' => 100,
  '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,
    ),
  ),
  'appsallowlist' => 
  array (
  ),
  'check_data_directory_permissions' => false,
  'memcache.distributed' => '\\OC\\Memcache\\Redis',
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'redis' => 
  array (
    'host' => 'nextcloud-aio-redis',
    'password' => '2356ad740518b7c98aab59bd126e8fa466490d4b73777243',
    'port' => 6379,
  ),
  'overwritehost' => 'mynextclouddomain.org',
  'overwriteprotocol' => 'https',
  'passwordsalt' => 'awY4A6o15wJlonVaZVJxffOGdORiWL',
  'secret' => 'MshlNtzxUNQu2tsjsJZd8sQ2VF2DXT1nOuCnbup/kzEkRvYn',
  'trusted_domains' => 
  array (
    0 => 'localhost',
    1 => 'mynextclouddomain.org',
    2 => '192.168.1.12',
  ),
  'datadirectory' => '/mnt/ncdata',
  'dbtype' => 'pgsql',
  'version' => '28.0.2.5',
  'overwrite.cli.url' => 'https://mynextclouddomain.org/',
  'dbname' => 'nextcloud_database',
  'dbhost' => 'nextcloud-aio-database',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'dbuser' => 'oc_nextcloud',
  'dbpassword' => 'd41a8e3b30d49aa0113c2d443260a0f42fe76899a6a3bfb9',
  'installed' => true,
  'instanceid' => 'oc9tmlqpbjqi',
  'maintenance' => false,
  'maintenance_window_start' => 1,
  'default_phone_region' => 'DE',
  'updatedirectory' => '/nc-updater',
  'loglevel' => '2',
  'app_install_overwrite' => 
  array (
    0 => 'nextcloud-aio',
    1 => 'wopi',
    2 => 'facerecognition',
  ),
  'log_type' => 'file',
  'logfile' => '/var/www/html/data/nextcloud.log',
  'log_rotate_size' => '10485760',
  'log.condition' => 
  array (
    'apps' => 
    array (
      0 => 'admin_audit',
    ),
  ),
  'preview_max_x' => '2048',
  'preview_max_y' => '2048',
  'jpeg_quality' => '60',
  'enabledPreviewProviders' => 
  array (
    1 => 'OC\\Preview\\Image',
    2 => 'OC\\Preview\\MarkDown',
    3 => 'OC\\Preview\\MP3',
    4 => 'OC\\Preview\\TXT',
    5 => 'OC\\Preview\\OpenDocument',
    6 => 'OC\\Preview\\Movie',
    7 => 'OC\\Preview\\Krita',
    0 => 'OC\\Preview\\Imaginary',
  ),
  'enable_previews' => true,
  'upgrade.disable-web' => true,
  'mail_smtpmode' => 'smtp',
  'trashbin_retention_obligation' => 'auto, 30',
  'versions_retention_obligation' => 'auto, 30',
  'activity_expire_days' => '30',
  'simpleSignUpLink.shown' => false,
  'share_folder' => '/Shared',
  'one-click-instance.link' => 'https://nextcloud.com/all-in-one/',
  'upgrade.cli-upgrade-link' => 'https://github.com/nextcloud/all-in-one/discussions/2726',
  'allow_local_remote_servers' => true,
  'davstorage.request_timeout' => 3600,
  'htaccess.RewriteBase' => '/',
  'dbpersistent' => false,
  'files_external_allow_create_new_local' => false,
  'trusted_proxies' => 
  array (
    0 => '127.0.0.1',
    1 => '::1',
    2 => '172.18.0.1',
    3 => '172.19.0.1',
    4 => '127.0.0.1',
  ),
  'preview_imaginary_url' => 'http://nextcloud-aio-imaginary:9000',
  'mail_sendmailmode' => 'smtp',
  'mail_from_address' => 'webmaster',
  'mail_domain' => 'mydomain.org',
  'mail_smtphost' => 'smtp.provider.de',
  'mail_smtpport' => '587',
  'mail_smtpauth' => 1,
  'mail_smtpname' => 'webmaster@mydomain.org',
  'mail_smtppassword' => 'password',
  'memories.exiftool' => '/var/www/html/custom_apps/memories/bin-ext/exiftool-amd64-musl',
  'memories.vod.path' => '/var/www/html/custom_apps/memories/bin-ext/go-vod-amd64',
  'memories.vod.ffmpeg' => '/usr/bin/ffmpeg',
  'memories.vod.ffprobe' => '/usr/bin/ffprobe',
);

As I was able to determine with my limited knowledge, I believe the remoteip module is not enabled by default in the AIO apache docker.

Regards
mabox

No remoteIP is not activated on your Apache. However you instead terminates HTTPS on the reverse proxy and manipulates the HTTP header by adding the X forwarded for - Real IP. So this should be in order.