[solved] Dockerized Nextcloud behind NGINX reverse proxy, simply doesn't work

Friends,
I’m trying to configure Nextcloud on my home ARM32 server (Nextcloud releases official ARM builds on their Docker Hub) with Raspbian (Ubuntu) and Docker. I run all my web services under Docker behind a dockerized NGNIX reverse proxy. Usually it’s easy to set up, but with Nextcloud I’m simply out of ideas at this point.

The problem:
I can connect to Nextcloud if I’m making Its Docker container to share an external port outside (like 8080); then I can use my machine’s local IP address and reach the configuration panel.
However I’m configuring Nextcloud behind NGINX reverse proxy, though, I can’t connect to the service thru that chain.
I’d like to make it work, so I can use one of my subdomains in order to redirect it do my Nextcloud container.

Let’s start with how my NGINX configuration looks like:

server {
    listen 80;
    server_name  subdomain.domain.org;
    location / {
        proxy_pass         http://172.18.0.4:80/;
        include            /etc/nginx/proxy_params;
    }
}

proxy_params consist of:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

I think it’s a bare minimum configuration in order to achieve a HTTP forward on NGNIX to a given container.
To ensure myself that I’m not having any networking issues I use http://172.18.0.4:80/ as a Nextcloud target container internal IP address instead of a host name.

I run couple other services in a similar way, and I don’t have any routing problems even with NIGNX routines much more complicated than the above…

Now, Nextcloud’s documentation says that in order for Nextcloud to work with an external proxy the config.php file must be updated with the proxy IP address. I used in my configuration:

“trusted_proxies” => [‘172.18.0.3’],

in the first row of a default configuration file.
The 172.18.0.3 is my NGINX’s IP address within Docker.
I was also trying to provide more data to that file, similar to the following post: Nginx reverse proxy, what to write in nextcloud's config.php? including: my subdomain, localhost, Docker container host names, containers IPs - in many configurations. Nothing helps.


Because I don’t know much about Nextcloud, I don’t know if I’m making some simple configuration error there, or maybe I’ve configured something wrong with NGINX (although my configuration passes the ngingx -s reload test without errors).
I’d like to ask those of you who run your Nextclouds in a similar environment to either post your configs for both NGINX and Nextcloud’s config.php and/or to point me in a direction that’s going to help me to solve the current misconfiguration.
All help is greatly appreciated!

is that your nginx or nextcloud ip?

My mistake, Reiner_Nippes.
It should be:

  • 172.18.0.3 - NGNIX container
  • 172.18.0.4 - Nextcloud container.

Thanks for pointing to that.

I’ve rechecked if maybe I’ve made exactly that mistake, but no. In my config it’s like it should be and the problem remains unsolved.
I’ve also corrected my main post.

I guess that having flu and composing config files isn’t the best combination :wink:

the trusted_proxy shouldn’t be the problem. that should result only in a warning in the system settings page.

did you also set:

overwrite.cli.url=http://{{ nextcloud_server_fqdn }}
trusted_domains={{ nextcloud_server_fqdn }}
trusted_domains=nginx"

maybe this container could be helpful for you. seems it can auto detect your container with web services.

it’s also used in the nextcloud example docker-compose files.

OK, so this is how I modified my config.php file according to your instructions, @Reiner_Nippes:
(thank you for trying to help me with my issue, BTW).

<?php
$CONFIG = array (
  'htaccess.RewriteBase' => '/',
  '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,
    ),
  ),
  'instanceid' => 'ocs1ncry3vpc',

  'trusted_proxies' => ['172.18.0.3'],
  'overwrite.cli.url' => ['subdomain.domain.org'],
  'trusted_domains' => ['subdomain.domain.org'],
  'trusted_domains' => ['172.18.0.3'],
);

Where the 172.18.0.3 is my NGINX IP address.
(I also tried using NGINX’s host name intead of its IP address for both trusted_proxies and trusted_domains, concluding that maybe using IP addresses instead domain/host names is the problem. It doesn’t work either. PS: I’ve also rechecked if both containers, NGNIX and Nextcloud, can communicate within Docker’s network tied to them. No issues there.).

Now, an interesting things going on in the Nextcloud’s logs whenever I’m making a http call from the subdomain I wanted to associate my Nextcloud instance with:

127.0.0.1 - - [13/Nov/2019:09:22:14 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.38 (Debian) PHP/7.3.11 (internal dummy connection)"

Needless to say my Nextcloud instance doesn’t process the above kind of calls simply dropping the connection (this is how the situation looks like from my browser’s perspective).

A connection from a local IP address Nextcloud processes without any issues looks like this:

192.168.88.10 - - [13/Nov/2019:09:22:05 +0000] "GET / HTTP/1.1" 200 3370 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0"

On top of that I’m getting a couple other strange log entries despite the above configuration:

[Wed Nov 13 09:21:55.641350 2019] [mpm_prefork:notice] [pid 1] AH00170: caught SIGWINCH, shutting down gracefully
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.4. Set the 'ServerName' directive globally to suppress this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.4. Set the 'ServerName' directive globally to suppress this message
[Wed Nov 13 09:22:02.241598 2019] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.38 (Debian) PHP/7.3.11 configured -- resuming normal operations
[Wed Nov 13 09:22:02.242104 2019] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'

There’s clearly an issue with my Nextcloud configuration, so the server drops connections from the external FQDN.
Ideas?

Unfortunately, I’m giving up on Nextcloud, so the topic is [DROPPED].

I’ve been trying with both NGINX and traefik as reverse proxies without success. Nextcloud refuses all connections from those proxies regardless of how I configure it.
Plus the recent news regarding a malware encrypting Nextcloud’s storages (although supposedly that’s NGINX’s vulnerability)… That’s too much.

I’ll satisfy my needs for a file server and calendars/contact list server with separate, FOSS tools that are available: NGINX WebDAV module for file sharing, Radicale for WebCAL (contacts and calendars).

Thank you for your help, though. Maybe I’ve been just unlucky.

that’s not a nextcloud or traefik problem. the following playbooks would give you a working nectcloud on docker behind traefik. nevertheless they are designed to run on “fresh” installed machines. they don’t care about existing configs and may break them.

or

Thx Reiner_Nippes.

I’m not blaming anyone here. I’m having flu at the moment, so my thinking isn’t entirely clear.
And my system is far from being clean :wink:

I’ll try that little bit later and I’ll tailor this thread accordingly / I’ll let everyone know what happened.


I have a lot of appreciation for everyone who’s working on FOSS, like the Nextcloud team. The fact that it doesn’t work like I’d like it to or that I’m not particularly passionate about PHP shouldn’t impact one’s judgement. There are people out there who do useful stuff for free because they consider that it should be done. Kudos for that!

Hey Arek,

I am having a similar problem like you have. I am trying since last Friday to setup a docker environment with mariadb and nextcloud-apache-stable behind an traefik remote proxy (described in more depth here).

I am seeing the same behavior as you did :
172.18.0.1 - - [19/Nov/2019:14:34:05 +0000] "GET / HTTP/1.1" 400 9632 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:70.0) Gecko/20100101 Firefox/70.0"

Initializing nextcloud 16.0.5.1 ... Initializing finished New nextcloud instance AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.5. Set the 'ServerName' directive globally to suppress this message AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.5. Set the 'ServerName' directive globally to suppress this message [Tue Nov 19 07:10:49.452864 2019] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.38 (Debian) PHP/7.3.11 configured -- resuming normal operations [Tue Nov 19 07:10:49.453051 2019] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'

I also configured the config.php file as mentioned in the nextcloud reverse proxy manual to no avail.

On its own the nextcloud instance is reachable under the host IP address (but without a valid certificate), and another container which provides a adminer instance is working as it should with traefik (and a valid letsencrypt cert).
So to me it looks like the issue is on the apache/nextcloud configuration.

When I access it via traefik it shows me the “access over untrustworthy domain” site. And when I take a look into the server logs it shows me a INFO | core | Trusted domain error. "192.168.178.1" tried to access using "mydomain.example.com" as host with the ip being the address of the router/gateway (which I also added to the trusted domain/proxy list out of despair).

I am beginning to get frustrated…

@zefrabila could you share the traefik and nextcloud parameters? that is to say the labels you gave the container?

if you want a working setup:

git clone https://github.com/ReinerNippes/nextcloud_on_docker.git

cd nextcloud_on_docker
./prepare_system.sh

# edit the config file
vi inventory

minimum:
> nextcloud_server_fqdn       = nextcloud.example.tld
> ssl_cert_email              = nextcloud@example.tld

./nextdocker.yml -e docker_nextcloud_image=latest

# "docker_nextcloud_image" is defined in group_vars/all.yml if you want to defined it permanent. you can also edit there. the default is "fpm-alpine" 
# if you want to skip the installation of docker and the config of the host you may comment out the following lines in nextdocker.yml

  roles:
#    - { role: prep_ufw,          when: ansible_os_family == "Debian" or ansible_os_family == "Ubuntu" }
#    - { role: prep_os,           when: (state is undefined or 'absent' not in state) }
#   - { role: prep_docker,       when: (state is undefined or 'absent' not in state) }
    - docker_container
    - { role: nextcloud_config,  when: (state is undefined or 'absent' not in state) }
#    - { role: prep_backup,       when: restic_repo != '' }

and then you can compare the settings with yours. if you want a nice docker frontend add -e portainer_enabled=true to the command line.

Hey Reiner_Nippes, thx for the suggested working setup but I think it would not be feasible for me since I want to avoid exposing the docker socket to a container.

This is why I use a static traefik configuration with a file provider:

docker-compose.yaml

services:

  traefik:
    image: traefik:v2.0.4
    container_name: traefik
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    environment:
      - TZ=Europe/Berlin
      - EXEC_PATH=/etc/traefik/domain_dns
      - DOMAIN_TOKEN=d42d9cd98f00b204e9345998ecf8427e
      - DOMAIN_NAME=mydomain.example.com
    volumes:
      - ./traefik.yml:/etc/traefik/traefik.yml
      - ./dynamic_conf.yml:/etc/traefik/dynamic_conf.yml
      - ./acme.json:/acme.json
      - ./domain_dns:/etc/traefik/domain_dns


  nextcloud:
    image: nextcloud:stable-apache
    volumes:
      - "./nc/data:/var/www/html/data"
      - "./nc/custom_apps:/var/www/html/custom_apps"
      - "./nc/config:/var/www/html/config"
    environment:
      - MYSQL_HOST=db
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_PASSWORD=somepassword
    ports:
      - "8084:80"


  db:
    image: linuxserver/mariadb:arm32v7-110.4.10mariabionic-ls42
    restart: always
    volumes:
      - "./db:/config"
    env_file:
      - "db.env"


  adminer:
    image: adminer:4.7.4-standalone
    restart: always
    ports:
      - "8085:8080"

traefik.yml

 level: DEBUG

serversTransport:
  insecureSkipVerify: true

entryPoints:
  web:
    address: ":80"

  web-secure:
    address: ":443"

api:
  insecure: true
  dashboard: true

providers:
  file:
    filename: "/etc/traefik/dynamic_conf.yml"
    watch: true

certificatesResolvers:
  sample:
    acme:
      email: admin@mydomain.example.com
      storage: acme.json
      dnsChallenge:
        provider: exec
        delayBeforeCheck: 0

dynamic_conf.yml

http:
  routers:
    router0:
      entyPoints:
      - web
      service: nextcloud
      rule: "Host(`raspberrypi.mydomain.example.com`) && PathPrefix(`/nc`)"
      middlewares:
      - redirect
    router1:
      entyPoints:
      - web-secure
      service: nextcloud
      rule: "Host(`raspberrypi.mydomain.example.com`) && PathPrefix(`/nc`)"
      middlewares:
      - removeServiceSelector
      - ncHeader
      tls:
        certResolver: sample
    router2:
      entyPoints:
      - web
      service: adminer
      rule: "Host(`raspberrypi.mydomain.example.com`)  && PathPrefix(`/ad`)"
      middlewares:
      - redirect
    router3:
      entyPoints:
      - web-secure
      service: adminer
      rule: "Host(`raspberrypi.mydomain.example.com`)  && PathPrefix(`/ad`)"
      middlewares:
      - removeServiceSelector
      tls:
        certResolver: sample

  services:
    nextcloud:
      loadBalancer:
        servers:
          - url: "http://raspberrypi.mydomain.example.com:8084/"
    adminer:
      loadBalancer:
        servers:
          - url: "http://raspberrypi.mydomain.example.com:8085/"

  middlewares:
    ncHeader:
      headers:
        customResponseHeaders:
          stsPreload: true
          stsSeconds: 15552000
    removeServiceSelector:
      stripPrefix:
        prefixes:
          - "/nc"
          - "/ad"
        forceSlash: false
    redirect:
      redirectScheme:
        scheme: https

nextcloud apache config.php

<?php
$CONFIG = array (
  'htaccess.RewriteBase' => '/',
  '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,
    ),
  ),
  'instanceid' => 'asdfasdfadsf',
  'passwordsalt' => 'asdfasdfasdfasdfasdfasdfasdfas',
  'secret' => 'asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf',
    'trusted_domains' =>
  array (
    0 => 'host_ip_address:8084',
    1 => 'raspberrypi.mydomain.example.com:8084',
    2 => 'raspberrypi.mydomain.example.com:8084/nc',
    3 => 'raspberrypi.mydomain.example.com:443',
    4 => 'raspberrypi.mydomain.example.com:80',
    5 => 'docker_default_gw_ip',
    6 => 'traefik_container_dns_name',
    7 => 'router_ip',
  ),
  'trusted_proxies' => ['docker_default_gw_ip','traefik_container_ip','router_ip],
//  'trusted_proxies' => ['traefik'],
//  'overwrite.cli.url' => 'http://host_ip_address:8084',
  'overwrite.cli.url' => 'raspberrypi.mydomain.example.com:8084/',
//  'overwritehost' => 'raspberrypi.mydomain.example.com:8084',
//  'overwriteprotocol' => 'https',
  'datadirectory' => '/var/www/html/data',
  'dbtype' => 'mysql',
  'version' => '16.0.5.1',
  'dbname' => 'nextcloud',
  'dbhost' => 'db',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'dbuser' => 'nextcloud',
  'dbpassword' => 'asdfasdfasdf',
  'installed' => true,
  'maintenance' => false,
  'theme' => '',
  'loglevel' => 0,
  'mysql.utf8mb4' => true,
);

The commented lines in the config.php were tried in different combinations and with either a full restart of the nextcloud instance or just a reload of the login page.
As mentioned earlier the adminer instance works fine with the current traefik setup.

With the config I am still getting a Trusted domain error. "client IP" tried to access using "raspberrypi.mydomain.example.com" as host. when I try to access nextcloud via “raspberrypi.mydomain.example.com/nc”. And I don’t know why, since I included all involved network elements as “trusted domains”.

I would remove both ports: statements from either the nextcloud and adminer container. and use the internal docker network.

services:
 nextcloud:
   loadBalancer: 
     servers: 
       - url: "http://nextcloud/"

Hey zefrabila,

Well, I’ve experienced exactly the same, but you’ve had some more luck with traefik.

Whatever I was trying to test in my env., the Apache integrated with Nextcloud into its container deals with requests coming from NGINX/traefik proxy (or any other external requests other that the direct ones targeted to the container’s IP address for that matter) in the following way: "Apache/2.4.38 (Debian) PHP/7.3.11 (internal dummy connection)"
My best bet is that my Nextcloud instance is somehow broken and it doesn’t pass the necessary args. to its Apache even if the changes I crave are in the config.php aready, so the web server deals with all strange requests by dropping them.

I concluded that because I’m using the ARM32 architecture there might be something wrong with my Nextcloud instance.
On the other hand I had only 2 requirements regarding my new toys: files sharing and CalDAV server. I don’t need other (excellent) features Nextcloud offers, so I’ve made an easy decision to give up. I’ve spent around 10h on the Nextcloud problem without success.

I hope that you’ll manage to get it right!

PS: I’d strongly advise to follow Reiner_Nippes’s steps. He was pointing from the very start to build a container with docker-compose (I was trying with docker run only). From the documentation we can see that there’s a couple of ways to pass args to Nextcloud, at least thru the config.php and thru env. variables during startup. Passing the necessary args in a way other that giving them in the config file and then restarting the container might be a key to solve that connection-dropping problem I think, so I,ll at least try the docker-compose way wen I’m going to have some time.
Cheers!
PS2: One more important advice: Nextcloud deals with its config.php in an unusual way. For instance when you’re going to deploy the container and you won’t get thru the minimal setup of the first, admin account - after finlly accomplishing that necessary step Nextcloud will rework your entries in config.php in a way it wishes them to be done, effectively it’ll get rid of your initial instructions! This is why I started thinking about passing args in env. variables instead of tinkering with the config.php.

Hey thank you for the reply’s.

I had no time to troubleshoot till yesterday evening, by then I thought I got it working :smiley:
Only to find out one reboot later that it was in fact not working… :unamused:

First of all thank you @Reiner_Nippes for the suggestion of using the internal dns names of the containers, I got it to work (although I needed to supply the port numbers). The file provider service section now looks like this:

services:
   nextcloud:
     loadBalancer:
       servers:
         - url: "http://nextcloud:80/"
   adminer:
     loadBalancer:
       servers:
         - url: "http://adminer:8080/"

And I revisited the various reverse proxy howto’s and finally found a partially working config.php for my use case:

config.php

<?php
$CONFIG = array (
  'htaccess.RewriteBase' => '/nc',
  '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,
    ),
  ),
  'instanceid' => 'asdfasdfadsf',
  'passwordsalt' => 'asdfasdfasdfasdfasdfasdfasdfas',
  'secret' => 'asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf',
    'trusted_domains' =>
  array (
    0 => 'nextcloud:80',
    1 => 'raspberrypi.mydomain.example.com',
  ),
  'trusted_proxies' => ['traefik'],
  'overwrite.cli.url' => 'https://raspberrypi.mydomain.example.com/nc',
  'overwritehost' => 'raspberrypi.mydomain.example.com',
  'overwritewebroot' => '/nc',
  'overwriteprotocol' => 'https',
  'datadirectory' => '/var/www/html/data',
  'dbtype' => 'mysql',
  'version' => '16.0.5.1',
  'dbname' => 'nextcloud',
  'dbhost' => 'db',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'dbuser' => 'nextcloud',
  'dbpassword' => 'asdfasdfasdf',
  'installed' => true,
  'maintenance' => false,
  'theme' => '',
  'loglevel' => 0,
  'mysql.utf8mb4' => true,
);

With that config I got prompted the login nextcloud page (when visiting https://raspberrypi.mydomain.example.com/nc) and could access it and so on. I thought, yes finally!
But then when I put the docker-compose down and up again (without changing the config.php) I got an 502 “Bad Gateway” when accessing the https://raspberrypi.mydomain.example.com/nc. The traefik log showed a traefik | time="2019-11-20T19:22:46+01:00" level=debug msg="'502 Bad Gateway' caused by: dial tcp nextcloud_container_ip:80: connect: connection refused".

After some trial and error I could only get it to work again if:

  1. I changed the config.php (and not even add or remove a configuration line, just add a comment or something)
  2. reload the nextcloud container
  3. a combination of both

When I check the config.php the configuration is like it should be, it seems to me like it is not applied fully on container restart.
Or is there a race condition with dockers internal DNS if apache can not resolve the given DNS names in the config?

This is really annoying… :sob:

Ok scratch that last paragraph. It is working :smiley:
I was just a little to impatient (I should have been mentioning that I run the setup on an raspberry pi 3B+).

I separated the traefik container from the others and setup another docker-compose for it. First starting the traefik and after it was up, then starting nextcloud/db/adminer docker-compose.
After everything was up and running for about two minutes I tried to access raspberrypi.mydomain.example.com/nc which got me a Bad Gateway response.

But when I tried again after ten minutes, I got the nextcloud login page and everything is fine. :smile:

1 Like

Great, zefrabila!
I’ll try your config, so thank you for posting it.
It also seems that I should change [dropped] to [solved] :wink:

1 Like