How do I serve a nextcloud server under a subpath: my-domain.com/nextcloud?

Hi everyone!

I want to serve a nextcloud server under my-nextcloud-site.com//nextcloud
I got the following caddy file from the examples [Nextcloud example] and adjusted the label (examples/Caddyfile at master · caddyserver/examples · GitHub):

my-nextcloud-site.com/nextcloud {

    	root   /var/www/nextcloud
    	log    /var/log/nextcloud_access.log
    	errors /var/log/nextcloud_errors.log

    	fastcgi / 127.0.0.1:9000 php {
    		env PATH /bin
    	}

    	rewrite {
    		r ^/index.php/.*$
    		to /index.php?{query}
    	}

    	# client support (e.g. os x calendar / contacts)
    	redir /.well-known/carddav /remote.php/carddav 301
    	redir /.well-known/caldav /remote.php/caldav 301

    	# remove trailing / as it causes errors with php-fpm
    	rewrite {
    		r ^/remote.php/(webdav|caldav|carddav|dav)(\/?)$
    		to /remote.php/{1}
    	}

    	rewrite {
    		r ^/remote.php/(webdav|caldav|carddav|dav)/(.+?)(\/?)$
    		to /remote.php/{1}/{2}
    	}

    	# .htaccess / data / config / ... shouldn't be accessible from outside
    	status 403 {
    		/.htacces
    		/data
    		/config
    		/db_structure
    		/.xml
    		/README
    	}

    	header / Strict-Transport-Security "max-age=31536000;"

    }

My problem is, that I can’t get my head around the rewrites. If I go to my-nextcloud-site.com/nextcloud I get redirected to my-nextcloud-site.com/index.php. But unfortunately, this is not existing, because the subpath nextcloud is missing. I tried modifing the rewrites:

rewrite {
    r ^/index.php/.*$
    to /nextcloud/index.php?{query}
    	}

and this

rewrite /nextcloud {
	r ^/index.php/.*$
	to /index.php?{query}
}

But nothing is working and to be honest, I have no clue.

Could you please point me into the right direction? Maybe it’s not the rewrite directive at all?

PS: I tried serving the nextcloud server without the nextcloud subpath. This works as expected.

Thanks in advance!
Paul

Hi @Paul_Hannes, welcome to the Caddy community!

This is… A bit of a can of worms, I’m afraid. Changing the site label to include a subfolder changes some things but not others, and I’m not entirely sure where it’s documented exactly how it interacts with conditionals like in the rewrite directive.

Some quick testing indicates that for label example.com/foo, and a rewrite from r ^/bar$, requests for example.com/foo/bar will be rewritten, indicating that rewrite's comparison is against the URI, but with the site label’s subfolder removed from the prefix.

However conditionals on placeholders such as {path} still match the full path, including the label subfolder.

My understanding is that your first attempt:

rewrite {
  r ^/index.php/.*$
  to /nextcloud/index.php?{query}
}

Should have been correct. Alternately, to avoid a costly regex check and use a substring match instead, you could use the form:

rewrite {
  if {path} starts_with /nextcloud/index.php/
  to /nextcloud/index.php?{query}
}

I’m not sure whether the status directive will need to have all the paths prefixed with /nextcloud as well, or the redirs.

On top of this, Nextcloud requires some additional configuration to support a subfolder/URL base, and only really assuming you’re doing this with a reverse proxy:

https://docs.nextcloud.com/server/10/admin_manual/configuration_server/reverse_proxy_configuration.html

In my opinion, you will save yourself quite the headache by scrapping the notion of modifying the provided Caddyfile and instead:

  1. Run one internal Caddy instance, listening on :80, serving Nextcloud with a 100% stock Caddyfile
  2. Run one public-facing Caddy, for Automatic HTTPS and proxying /nextcloud to the internal Caddy
  3. Set Nextcloud’s config/config.php to support the new URL base

While you might consider running two Caddys overkill, I think it’ll be worth it just due to the vast reduction in complexity.

Ok, thanks for the reply and the detailed description.

I tried to set the proxy solution up, but I hit another road block now.
Here the first caddyfile for the proxy server:

mydomain.com {
  
	log    /var/log/caddy_access.log
	errors /var/log/caddy_errors.log
	
	proxy /nextcloud localhost:3780 {
		transparent
	}
}

and for the nextcloud server:

:3780 {
  
	root   /var/www/nextcloud
	log    /var/log/nextcloud_access.log
	errors /var/log/nextcloud_errors.log

	fastcgi / 127.0.0.1:9011 php {
		env PATH /bin
	}

	rewrite {
		r ^/index.php/.*$
		to /index.php?{query}
	}

	# client support (e.g. os x calendar / contacts)
	redir /.well-known/carddav /remote.php/carddav 301
	redir /.well-known/caldav /remote.php/caldav 301

	# remove trailing / as it causes errors with php-fpm
	rewrite {
		r ^/remote.php/(webdav|caldav|carddav|dav)(\/?)$
		to /remote.php/{1}
	}

	rewrite {
		r ^/remote.php/(webdav|caldav|carddav|dav)/(.+?)(\/?)$
		to /remote.php/{1}/{2}
	}

	# .htaccess / data / config / ... shouldn't be accessible from outside
	status 403 {
		/.htacces
		/data
		/config
		/db_structure
		/.xml
		/README
	}
	header / Strict-Transport-Security "max-age=31536000;"
}

The log-file of the proxy looks like this:
X.X.X.X - - [22/Jun/2017:16:36:11 +0200] "GET /nextcloud HTTP/2.0" 404 14

and for the nextcloud server:
::1 - - [22/Jun/2017:16:36:11 +0200] "GET /nextcloud HTTP/1.1" 404 14

And there are some odd entries in the nextcloud_error.log:
22/Jun/2017:16:35:30 +0200 [ERROR 0 /nextcloud/status.php] Primary script unknown
22/Jun/2017:16:35:30 +0200 [ERROR 0 /nextcloud/owncloud/status.php] Primary script unknown

As far as I understand it, the proxy setup seems to be correct, because I get the requests in the log of the nextcloud server. But still I get 404 in the browser.

And the “Primary script unknown” doesn’t make any sense to me, because without the proxy the nextcloud server works (without the nextcloud subpath). I found out that there could be problems regarding the user running caddy and tested to run caddy as www-data and not root, but this just led to “Bad Gateway” responses.

As I understood your answer I should be able to use the example script for my nextcloud instance and just have to adjust the label to listen for the local port. Or did I miss something here?

Thanks a lot for the support!

When I saw Primary script unknown I thought it might be some kind of FastCGI/Caddy root mismatch.

But are you saying that while example.com/nextcloud/status.php fails, localhost:3780/nextcloud/status.php works fine? That’s really weird.

This is exactly correct, and looking over the config you posted, you’ve done it perfectly. A proxy shouldn’t be capable of influencing whether or not PHP-FPM can access the script…

Why is env PATH /bin set, out of curiosity? Is that necessary?

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.