Help: Nextcloud Reverse Proxy

jackosh

Cadet
Joined
Dec 31, 2018
Messages
7
I've been at this for a few days and I'm still scratching my head. I have a nextcloud jail running great (installed as a plugin), but it only works locally (of course, if I open port 80 to my nextcloud IP, I can access remotely no problem, but that isn't secure). Since I'd like to access my nextcloud jail (and a few others) remotely, I decided to setup a NGINX jail so I can reverse proxy. I followed this excellent guide, but I always get 404/not found when I try to configure everything with nextcloud. I can successfully connect to other local servers (e.g. pi-hole). I'm at a loss right now since I feel like I've tried everything. Is anyone successfully pulling off what I'm trying to do? If so, mind giving me a hand with my configurations?

My main configurations are:

Nextcloud Jail usr/local/www/nextcloud/config/config.php
Code:
<?php
$CONFIG = array (
  'apps_paths' =>
  array (
    0 =>
    array (
      'path' => '/usr/local/www/nextcloud/apps',
      'url' => '/apps',
      'writable' => true,
    ),
    1 =>
    array (
      'path' => '/usr/local/www/nextcloud/apps-pkg',
      'url' => '/apps-pkg',
      'writable' => true,
    ),
  ),
  'logfile' => '/var/log/nextcloud/nextcloud.log',
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'instanceid' => 'REMOVED',
  'passwordsalt' => 'REMOVED',
  'secret' => 'REMOVED',
  'trusted_domains' =>
  array (
    0 => 'NEXTCLOUD.JAIL.IP',
    1 => 'MY.DOMAIN',
  ),
  'datadirectory' => '/usr/local/www/nextcloud/data',
  'dbtype' => 'mysql',
  'version' => '15.0.0.10',
  'dbname' => 'nextcloud',
  'dbhost' => 'localhost',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'dbuser' => 'REMOVED',
  'dbpassword' => 'REMOVED',
  'installed' => true,
/*  'overwrite.cli.url' => 'https://MY.DOMAIN/', */
  'trusted_proxies' =>
  array (
    0 => 'NGINX.JAIL.IP',
  ),
/*  'overwritehost' => 'MY.DOMAIN', */
/*  'overwriteprotocol' => 'https', */
/*  'overwritewebroot'  => '/nextcloud', */
);


NGINX Jail usr/local/etc/nginx/nginx.conf

Code:
#user nobody;
worker_processes  1;

# This default error log path is compiled-in to make sure configuration parsing
# errors are logged somewhere, especially during unattended boot when stderr
# isn't normally logged anywhere. This path will be touched on every nginx
# start regardless of error log location configured here. See
# https://trac.nginx.org/nginx/ticket/147 for more info.
#
#error_log  /var/log/nginx/error.log;
#

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       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  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        listen [::]:80;
        server_name MY.DOMAIN;
        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   /usr/local/www/nginx;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/local/www/nginx-dist;
        }
        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server

    server {
        listen 443 ssl;
        listen [::]:443 ssl;
        ssl on;
        server_name MY.DOMAIN;
        include ssl_common.conf;
        include proxy_setup.conf;

#        ssl_certificate      cert.pem;
#        ssl_certificate_key  cert.key;

#        ssl_session_cache    shared:SSL:1m;
#        ssl_session_timeout  5m;

#        ssl_ciphers  HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers  on;

        location / {
            root   /usr/local/www/nginx;
            index  index.html index.htm;
        }
    }

}



NGINX Jail usr/local/etc/nginx/proxy_setup.conf
Code:
location /nextcloud {
        proxy_set_header Host $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-Proto $scheme;
        add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
        add_header Front-End-Https on;
        client_max_body_size 16400M;
        proxy_pass http://NEXTCLOUD.JAIL.IP;
        proxy_pass_header Authorization;
        proxy_read_timeout 90;
}
 

Apollo

Wizard
Joined
Jun 13, 2013
Messages
1,449
I could help you if you were running pfsense as your firewall running Haproxy.
 

garm

Wizard
Joined
Aug 19, 2017
Messages
1,555
A couple of things before I point you in the right direction; (1) opening ports to a nginx reverse proxy jail is marginally safer then opening it to the Nextcloud jail directly unless you take steps to make it more secure. (2) You can force the user to 443 in nginx, here are several hardening tips for an internet facing webserver https://www.cyberciti.biz/tips/linux-unix-bsd-nginx-webserver-security.html

Having a reverse proxy makes a lot of sense but it needs to be separate from the rest our your network to increase security. I don't have internet facing servers on the same network as "normal" LAN traffic. A jail is not good enough unless it sits in its own VLAN or other kinds of segregation. I have mine as a heavily locked down VPS outside of my home network and I tightly control the traffic in the VPS and from it through my pfSense firewall. There is no need for a reverser proxy if malicious access to it give the attacker access to your entire network.

There are several guides on how to do reverse proxying, Nextcloud's documentation even brings it up but assumes knowledge about the webserver doing the proxying. My own setup is similar to this https://github.com/nextcloud/nextcloud-snap/wiki/Putting-the-snap-behind-a-reverse-proxy where my <domain name> includes the application as a subdomain, eg nextcloud.mydomain.io. You cannot have your Nextcloud root at a subdirectory eg. mydomain.io/nextcloud unless you also changes the root in config.php, but its poor practice to handle applications sharing a domain that way, in my opinion (no link for this one, google it).

Once you are done and have your Nextcloud properly routed to from your domain, you should do some basic audit before letting users use it or populate it with data. Nextcloud have their own scanner, and you need to pass it with A+ (!) https://scan.nextcloud.com/
There is also SSL Labs scanner, here you should have atleast A https://www.ssllabs.com/ssltest/ and you should do some basic pen testing https://pentest-tools.com/
You need to make sure your firewall, I'm assuming you have a consumer router, isn't a carrier of a known vulnerability and is properly updated https://www.bitdefender.com/box/blog/iot-news/router-updates-fail-protect-known-vulnerabilities/, personally I would never trust a box sent to me by an ISP. My ISP is one of the most privacy and safety minded in Sweden, and the box they sell is in my opinion not sufficient for other then casual consumer use. I rely on pfSense and off the shelf hardware together with constant updates and pen testing.

Finally, you should clean up your configs to make them easier to read and maintain. It looks like you are working in the example configs you get with the installation and that is a poor practice. You should be generous with comments, its hard to remember why you did things in a certen way, but you should not have out commented unused code.
 
Last edited:

NasKar

Guru
Joined
Jan 8, 2016
Messages
739
Having a reverse proxy makes a lot of sense but it needs to be separate from the rest our your network to increase security. I don't have internet facing servers on the same network as "normal" LAN traffic. A jail is not good enough unless it sits in its own VLAN
I've very interested in you post. One of my next projects is to swap out my switches so I can use VLANs. Can I put my Nextcloud jail, and Plex on a separate VLANs and use HAProxy to point my DDNS address to each server? or create the reverse proxy in a separate VLAN in freenas and use firewall rules in pfsense so they can talk to the other vlans?
you need to pass it with A+ (!) https://scan.nextcloud.com/
How do you fix __Host-Prefix with nginx? It's the only item with an X on my scan. BTW ssllabs is an A+
 

jackosh

Cadet
Joined
Dec 31, 2018
Messages
7
A couple of things before I point you in the right direction; (1) opening ports to a nginx reverse proxy jail is marginally safer then opening it to the Nextcloud jail directly unless you take steps to make it more secure. (2) You can force the user to 443 in nginx, here are several hardening tips for an internet facing webserver https://www.cyberciti.biz/tips/linux-unix-bsd-nginx-webserver-security.html

Having a reverse proxy makes a lot of sense but it needs to be separate from the rest our your network to increase security. I don't have internet facing servers on the same network as "normal" LAN traffic. A jail is not good enough unless it sits in its own VLAN or other kinds of segregation. I have mine as a heavily locked down VPS outside of my home network and I tightly control the traffic in the VPS and from it through my pfSense firewall. There is no need for a reverser proxy if malicious access to it give the attacker access to your entire network.

There are several guides on how to do reverse proxying, Nextcloud's documentation even brings it up but assumes knowledge about the webserver doing the proxying. My own setup is similar to this https://github.com/nextcloud/nextcloud-snap/wiki/Putting-the-snap-behind-a-reverse-proxy where my <domain name> includes the application as a subdomain, eg nextcloud.mydomain.io. You cannot have your Nextcloud root at a subdirectory eg. mydomain.io/nextcloud unless you also changes the root in config.php, but its poor practice to handle applications sharing a domain that way, in my opinion (no link for this one, google it).

Once you are done and have your Nextcloud properly routed to from your domain, you should do some basic audit before letting users use it or populate it with data. Nextcloud have their own scanner, and you need to pass it with A+ (!) https://scan.nextcloud.com/
There is also SSL Labs scanner, here you should have atleast A https://www.ssllabs.com/ssltest/ and you should do some basic pen testing https://pentest-tools.com/
You need to make sure your firewall, I'm assuming you have a consumer router, isn't a carrier of a known vulnerability and is properly updated https://www.bitdefender.com/box/blog/iot-news/router-updates-fail-protect-known-vulnerabilities/, personally I would never trust a box sent to me by an ISP. My ISP is one of the most privacy and safety minded in Sweden, and the box they sell is in my opinion not sufficient for other then casual consumer use. I rely on pfSense and off the shelf hardware together with constant updates and pen testing.

Finally, you should clean up your configs to make them easier to read and maintain. It looks like you are working in the example configs you get with the installation and that is a poor practice. You should be generous with comments, its hard to remember why you did things in a certen way, but you should not have out commented unused code.

First, thanks a lot for the reply. I really appreciate how thoughtful your response is. I'm just getting started with FreeNAS, so I really look forward to continuing to learn, and your links/resources will be extremely helpful as my network configuration evolves. In the meantime, I want to really make sure I understand the ins and outs of setting up more simple (and yes, crude) things like Nextcloud over NGINX reverse proxy. I continue to go over my configurations and still cannot spot where I've gone wrong. Do you have any advice? I've looked through the links you sent, but do not really have any additional information. Really understanding this will help me figure things out.

Yes, you're right - I worked off the sample of the nginx.conf file, so it's not super clean. I'm a tinkerer so I like to start with the base and then adjust. The "clean" version is:

Code:
worker_processes  1;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    server {
        listen       80;
        listen [::]:80;
        server_name lab.jackosh.com;

        location / {
            root   /usr/local/www/nginx;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/local/www/nginx-dist;
        }
    }


    server {
        listen 443 ssl;
        listen [::]:443 ssl;
        ssl on;
        server_name lab.jackosh.com;
        include ssl_common.conf;
        include proxy_setup.conf;

        location / {
            root   /usr/local/www/nginx;
            index  index.html index.htm;
        }
    }

}
 

garm

Wizard
Joined
Aug 19, 2017
Messages
1,555
@jackosh nginx.conf looks alright, nothing jumps out at a quick glance. But your Nextcloud URL is app.domain.io/nextcloud and without configuration Nextcloud will assume to be in the domain root (app.domain.io/). Try uncommenting overwritewebroot' => '/nextcloud', in config.php and restart the jail.

@NasKar you move the proxy_pass from your location /nextcloud block to a new server block with server_name nextcloud.domain.io, but this will either require a new certificat or a wildcard cert as it’s effectively a new domain. You also need to either add a wildcard domain in your DNS or specify the new domain there as well.
 

jackosh

Cadet
Joined
Dec 31, 2018
Messages
7
@jackosh nginx.conf looks all right, nothing jumps out at a quick glance. But your Nextcloud URL is app.domain.io/nextcloud and without configuration Nextcloud will assume to be in the domain root (app.domain.io/). Try uncommenting overwritewebroot' => '/nextcloud', in config.php and restart the jail.

@NasKar you move the proxy_pass from your location /nextcloud block to a new server block with server_name nextcloud.domain.io, but this will either require a new certificat or a wildcard cert as it’s effectively a new domain. You also need to either add a wildcard domain in your DNS or specify the new domain there as well.
Thanks - I had tried that a few times, and just tried again with no luck. I have a feeling there is some issue with NGINX since I'm getting 404 (vs a Nextcloud error). This is strange, right? I have no issues connecting to pihole in the same way.

I took your other advice and I'm building a pfsense box now! Thanks again.
 

jackosh

Cadet
Joined
Dec 31, 2018
Messages
7
Well there is an easy test, nginx rewrites app.domain.io/nextcloud to http://jail.IP/nextcloud

Can you access that using a browser?
OK Good news/bad news! I am now able to access the site the way I want. I also get an A on the security test. The bad news is it appears that syncing doesn't work. I get the following message in the admin page:
  1. There are some errors regarding your setup.
  2. Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken.
  3. Your web server is not properly set up to resolve "/.well-known/caldav". Further information can be found in the documentation
  4. Your web server is not properly set up to resolve "/.well-known/carddav". Further information can be found in the documentation
At least I'm trending in the right direction!
 

Patrick M. Hausen

Hall of Famer
Joined
Nov 25, 2013
Messages
7,740
Do you have this in your Nginx config?
Code:
    location = /.well-known/carddav {
      return 301 $scheme://$host/remote.php/dav;
    }
    location = /.well-known/caldav {
      return 301 $scheme://$host/remote.php/dav;
    }


The first error might be due to a similar problem.

This is straight from the Nextcloud documentation:
https://docs.nextcloud.com/server/15/admin_manual/installation/nginx.html

HTH,
Patrick
 

cygnus

Explorer
Joined
Mar 20, 2012
Messages
73
Hi I hope some kind soul can help me as I'm going round in circles. I can access the nextcloud web page locally using the jails IP address without issue i.e.192.168.0.199 but when I try to use the nextcloud.domainname.co.uk I just get the Welcome to Nginx page. I tried https://nextcloud.domainname.co.uk but that fails to connect. I was able to connect before nginx install using the 443 port and this was forwarded to the nginx jail IP address.
Sorry and yes apologies I'm a Noob - but any help greatly appreciated:-

nextcloud.php
$CONFIG = array (
'apps_paths' =>
array (
0 =>
array (
'path' => '/usr/local/www/nextcloud/apps',
'url' => '/apps',
'writable' => true,
),
1 =>
array (
'path' => '/usr/local/www/nextcloud/apps-pkg',
'url' => '/apps-pkg',
'writable' => true,
),
),
'logfile' => '/var/log/nextcloud/nextcloud.log',
'memcache.local' => '\\OC\\Memcache\\APCu',
'instanceid' => 'xxxxxxxxxxx',
'passwordsalt' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxx',
'secret' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'trusted_domains' =>
array (
0 => '192.168.0.199',
1 => 'nextcloud.domainname.co.uk',
),
'datadirectory' => '/usr/local/www/nextcloud/data',
'dbtype' => 'mysql',
'version' => '15.0.4.0',
'overwrite.cli.url' => 'http://192.168.0.199',
'dbname' => 'nextcloud',
'dbhost' => 'localhost:5432',
'dbport' => '',
'dbtableprefix' => 'oc_',
'dbuser' => 'xxxxxxxxxxxxx',
'dbpassword' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'installed' => true,

Also attached the nginx.conf

#user nobody;
worker_processes 1;

# This default error log path is compiled-in to make sure configuration parsing
# errors are logged somewhere, especially during unattended boot when stderr
# isn't normally logged anywhere. This path will be touched on every nginx
# start regardless of error log location configured here. See
# https://trac.nginx.org/nginx/ticket/147 for more info.
#
#error_log /var/log/nginx/error.log;
#

#pid logs/nginx.pid;
events {
worker_connections 1024;
}


http {
include 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 logs/access.log main;

sendfile on;
#tcp_nopush on;

#keepalive_timeout 0;
keepalive_timeout 65;

#gzip on;

server {
listen 80;
listen [::]:80;
server_name nextcloud.domainname.co.uk;
#charset koi8-r;

#access_log logs/host.access.log main;

location / {
root /usr/local/www/nginx;
index index.html index.htm;
}
#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/local/www/nginx-dist;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}


# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;

# location / {
# root html;
# index index.html index.htm;
# }
#}


# HTTPS server
#
server {

listen 443 ssl;
listen [::]:443 ssl;
ssl on;
server_name nextcloud.domainname.co.uk;
include ssl_common.conf;
include proxy_setup.conf;
}

# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;

# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;

location / {
root /usr/local/www/nginx;
index index.html index.htm;

location = /.well-known/carddav {
return 301 $scheme://$host/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $scheme://$host/remote.php/dav;
}
}
}
}

Also my proxy_setup.conf
location / {

proxy_set_header Host $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-Proto $scheme;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
add_header Front-End-Https on;
client_max_body_size 16400M;
proxy_pass https://192.168.0.199;
proxy_read_timeout 90;
proxy_redirect https://192.168.0.199 https://nextcloud.domainname.co.uk;
}

Thanks for looking!

UPDATE - now get when try https://nextcloud.domianname.co.uk - 502 Bad Gateway??!?

Rgds
Cygnus
 
Last edited:

cygnus

Explorer
Joined
Mar 20, 2012
Messages
73
FIXED - my proxy_setup.conf had https redirect instead of http!

DOH!

Tested SSL and got A!
Hurrah!
 
Top