Trying to use Caddy 2 as a reverse proxy for Nextcloud 19. I have tried almost all configs (Caddyfile) I can find on the internet, but most of them just do not work. The one that works keeps telling me my password is wrong? Thanks.
This Caddyfile works for me. Running Nextcloud 22 on vps with Ubuntu 20.04
cloud.mynextcloud.server {
root * /var/www/nextcloud/
file_server
php_fastcgi unix//run/php/php7.4-fpm.sock
redir /.well-known/carddav /remote.php/carddav 301
redir /.well-known/caldav /remote.php/caldav 301
# Stop acccess from internet
respond /config/* "Access denied!" 403
respond /data/* "Access denied!" 403
respond /.htacces "Access denied!" 403
respond /db_structure/* "Access denied!" 403
respond /.xml "Access denied!" 403
respond /README "Access denied!" 403
header {
Strict-Transport-Security max-age=31536000;
}
}
@buskjan Thanks for sharing your config. Have you been able to use pretty urls with Caddy?
I can’t seem to get away from myhost.com/index.php/apps/filex
and have myhost.com/apps/files
like with Apache.
EDIT
Seemed to just have needed to add env front_controller_active true
to the php_fastcgi
section.
php_fastcgi unix//run/php-fpm/php-nextcloud.socket {
env front_controller_active true
}
EDIT 2: Although it seems to work in mot places, Rainloop does not work with “pretty” URL’s.
When I click the Rainloop icon I get 500 Internal Server Error
on https://mydomain.com/apps/rainloop/app/?OwnCloudAuth
. Request path is /apps/rainloop/app/?OwnCloudAuth
If I remove the env
config the request path is /index.php/apps/rainloop/app/?OwnCloudAuth
and it loads OK.
I am wondering also if we need to handle the other rewrite rules specified in the htdocs/.htaccess
file?
<IfModule mod_headers.c>
<IfModule mod_setenvif.c>
<IfModule mod_fcgid.c>
SetEnvIfNoCase ^Authorization$ "(.+)" XAUTHORIZATION=$1
RequestHeader set XAuthorization %{XAUTHORIZATION}e env=XAUTHORIZATION
</IfModule>
<IfModule mod_proxy_fcgi.c>
SetEnvIfNoCase Authorization "(.+)" HTTP_AUTHORIZATION=$1
</IfModule>
</IfModule>
<IfModule mod_env.c>
# Add security and privacy related headers
# Avoid doubled headers by unsetting headers in "onsuccess" table,
# then add headers to "always" table: https://github.com/nextcloud/server/pull/19002
Header onsuccess unset Referrer-Policy
Header always set Referrer-Policy "no-referrer"
Header onsuccess unset X-Content-Type-Options
Header always set X-Content-Type-Options "nosniff"
Header onsuccess unset X-Download-Options
Header always set X-Download-Options "noopen"
Header onsuccess unset X-Frame-Options
Header always set X-Frame-Options "SAMEORIGIN"
Header onsuccess unset X-Permitted-Cross-Domain-Policies
Header always set X-Permitted-Cross-Domain-Policies "none"
Header onsuccess unset X-Robots-Tag
Header always set X-Robots-Tag "none"
Header onsuccess unset X-XSS-Protection
Header always set X-XSS-Protection "1; mode=block"
SetEnv modHeadersAvailable true
</IfModule>
# Add cache control for static resources
<FilesMatch "\.(css|js|svg|gif|png|jpg|ico)$">
Header set Cache-Control "max-age=15778463"
</FilesMatch>
# Let browsers cache WOFF files for a week
<FilesMatch "\.woff2?$">
Header set Cache-Control "max-age=604800"
</FilesMatch>
</IfModule>
<IfModule mod_php7.c>
php_value mbstring.func_overload 0
php_value default_charset 'UTF-8'
php_value output_buffering 0
<IfModule mod_env.c>
SetEnv htaccessWorking true
</IfModule>
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} DavClnt
RewriteRule ^$ /remote.php/webdav/ [L,R=302]
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L]
RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L]
RewriteRule ^remote/(.*) remote.php [QSA,L]
RewriteRule ^(?:build|tests|config|lib|3rdparty|templates)/.* - [R=404,L]
RewriteRule ^\.well-known/(?!acme-challenge|pki-validation) /index.php [QSA,L]
RewriteRule ^(?:\.(?!well-known)|autotest|occ|issue|indie|db_|console).* - [R=404,L]
</IfModule>
<IfModule mod_mime.c>
AddType image/svg+xml svg svgz
AddEncoding gzip svgz
</IfModule>
<IfModule mod_dir.c>
DirectoryIndex index.php index.html
</IfModule>
AddDefaultCharset utf-8
Options -Indexes
<IfModule pagespeed_module>
ModPagespeed Off
</IfModule>
#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####
ErrorDocument 403 /
ErrorDocument 404 /
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]
RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]
RewriteCond %{REQUEST_FILENAME} !\.(css|js|svg|gif|png|html|ttf|woff2?|ico|jpg|jpeg|map|webm|mp4|mp3|ogg|wav)$
RewriteCond %{REQUEST_FILENAME} !/core/ajax/update\.php
RewriteCond %{REQUEST_FILENAME} !/core/img/(favicon\.ico|manifest\.json)$
RewriteCond %{REQUEST_FILENAME} !/(cron|public|remote|status)\.php
RewriteCond %{REQUEST_FILENAME} !/ocs/v(1|2)\.php
RewriteCond %{REQUEST_FILENAME} !/robots\.txt
RewriteCond %{REQUEST_FILENAME} !/(ocm-provider|ocs-provider|updater)/
RewriteCond %{REQUEST_URI} !^/\.well-known/(acme-challenge|pki-validation)/.*
RewriteCond %{REQUEST_FILENAME} !/richdocumentscode(_arm64)?/proxy.php$
RewriteRule . index.php [PT,E=PATH_INFO:$1]
RewriteBase /
<IfModule mod_env.c>
SetEnv front_controller_active true
<IfModule mod_dir.c>
DirectorySlash off
</IfModule>
</IfModule>
</IfModule>
This is also something I am in need of!
I am bit baffled by the fact that - to the best of my knowledge and search-foo - there is no complete(ly) working example for caddy-v2 + nextcloud on the internet. I didn’t test the one with docker-compose labels instead of caddyfile (see my setup as a reason below), but that seems similarily incomplete too.
I have similar issues, although my setup is a bit different:
- I run a docker(-compose)'d nextcloud, the -fpm variant (without the apache webserver in the container)
- for now, there is a docker-composed nginx, that is the file_server (for static files) and reverse-proxy for nextcloud (and some other sites)
- I am trying to replace this container’d nginx with a caddy on the host
Your “Access denied!” part has serious and stylistic issues! I think mine is better there.
- serious: Your denied list of pathes is far from complete (AFAIK)!
- quasi-serious: 403 does leak information that the requested resource exists, most example use 404 therefore.
- stylistic, but also a maintenance burden: You should use named matcher here too, and set respond on that. This way for example, you can replace 403 with 404 at a single place!
Otherwise, I am in a bit of a bind here, as I am not versed in webserver config to put it very lightly: I very much struggle with nginx (and I would not touch apache with a ten-foot pole, partly because its config files).
There should be a fickin’ good caddy v2 example somewhere by now, that tries to faithfully replicate the example apache/nginx configs. There is an official example caddy v1 config, that seems to be a mostly equivalent rewrite of some contemporary nginx/apache config, but it seems that although caddy v1 is “deprecated”, v2 is not really there to be a good replacement - yet. Maybe it lacks just documentation-wise…
Here is my caddyfile, mostly copied from some example.
I tram the non-relevant parts and sites
example.cloud {
# I run caddy on the host, and this is the root folder of nextcloud there
root * /mnt/repo-base/volumes/nextcloud/html
file_server
encode gzip
# This is the opinionated shorthand, that is most likely needs custom overrides
# php_fastcgi 127.0.0.1:9001 {
# root /var/www/html
# }
# This is the long form of the php_fastcgi, mostly as seen here: https://caddyserver.com/docs/caddyfile/directives/php_fastcgi#expanded-form
route {
# Add trailing slash for directory requests
@canonicalPath {
file {path}/index.php
not path */
}
redir @canonicalPath {path}/ 308
# CUSTOM ADDITION TO php_fastcgi
# Remove trailing slashes from dav protocols
@trailingSlashDavPath {
path_regexp davslash /((?:remote|public)\.php/(?:web|cal|card)?dav(?:/[^/]+)?)(?:/+)$
}
rewrite @trailingSlashDavPath /{re.davslash.1}
# If the requested file does not exist, try index files
@indexFiles file {
try_files {path} {path}/index.php index.php
split_path .php
}
rewrite @indexFiles {http.matchers.file.relative}
# Proxy PHP files to the FastCGI responder
@phpFiles path *.php
# Host port 9001 is mapped to nextcloud's 9000, for container'd caddy use <container_name>:9000
reverse_proxy @phpFiles 127.0.0.1:9001 {
transport fastcgi {
split .php
# CUSTOM ADDITION TO php_fastcgi
# This is the nextcloud root as seen/mounted inside the container
root /var/www/html
# CUSTOM ADDITION TO php_fastcgi - not really working
# env front_controller_active true
}
}
}
header {
# enable HSTS
# Strict-Transport-Security max-age=31536000;
}
redir /.well-known/carddav /remote.php/dav 301
redir /.well-known/caldav /remote.php/dav 301
# .htaccess / data / config / ... shouldn't be accessible from outside
@forbidden {
path /.htaccess
path /.xml
path /3rdparty/*
path /README
path /config/*
path /console.php
path /data/*
path /db_structure
path /lib/*
path /occ
path /templates/*
path /tests/*
}
respond @forbidden 404
}
www.example.cloud {
redir https://example.cloud{uri}
}
In case anyone wants to run caddy V2 as well as nextcloud all on the same host without docker and nextcloud in a subdirectory, then this snippet from my Caddyfile might help:
redir /.well-known/carddav /nextcloud/remote.php/dav 301
redir /.well-known/caldav /nextcloud/remote.php/dav 301
redir /.well-known/webfinger /nextcloud/index.php{uri} 301
redir /.well-known/nodeinfo /nextcloud/index.php{uri} 301
handle /nextcloud/* {
header {
Referrer-Policy "no-referrer" defer
X-Content-Type-Options "nosniff" defer
X-Download-Options "noopen" defer
X-Frame-Options "SAMEORIGIN" defer
X-Permitted-Cross-Domain-Policies "none" defer
X-Robots-Tag "none" defer
X-XSS-Protection "1; mode=block" defer
}
php_fastcgi unix//usr/local/var/run/php-fpm.sock {
try_files {path} {path}/index.php /nextcloud/index.php index.php
env front_controller_active true
header_down -x-powered-by
}
@forbidden {
path /nextcloud/.htaccess
path /nextcloud/data/*
path /nextcloud/config/*
path /nextcloud/db_*
path /nextcloud/.xml
path /nextcloud/README
path /nextcloud/AUTHORS
path /nextcloud/COPYING
path /nextcloud/3rdparty/*
path /nextcloud/lib/*
path /nextcloud/templates/*
path /nextcloud/occ
path /nextcloud/console.php
path /nextcloud/cron.php
}
respond @forbidden 404
}
I use fastcgi via unix sockets here, this is not entirely understood by nextcloud as the proxy setup check does not pass (although it works fine), as there is no IP address to check in trusted_proxies.