Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions admin_manual/installation/Caddyfile.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
cloud.example.com # Public server hostname

request_body {
max_size 10G
}

# Enable gzip but do not remove ETag headers
encode {
zstd
gzip 4

minimum_length 256

match {
header Content-Type application/atom+xml
header Content-Type application/javascript
header Content-Type application/json
header Content-Type application/ld+json
header Content-Type application/manifest+json
header Content-Type application/rss+xml
header Content-Type application/vnd.geo+json
header Content-Type application/vnd.ms-fontobject
header Content-Type application/wasm
header Content-Type application/x-font-ttf
header Content-Type application/x-web-app-manifest+json
header Content-Type application/xhtml+xml
header Content-Type application/xml
header Content-Type font/opentype
header Content-Type image/bmp
header Content-Type image/svg+xml
header Content-Type image/x-icon
header Content-Type text/cache-manifest
header Content-Type text/css
header Content-Type text/plain
header Content-Type text/vcard
header Content-Type text/vnd.rim.location.xloc
header Content-Type text/vtt
header Content-Type text/x-component
header Content-Type text/x-cross-domain-policy
}
}

# Add headers to serve security related headers
header Referrer-Policy no-referrer
header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;"
header X-Content-Type-Options nosniff
header X-Download-Options noopen
header X-Frame-Options SAMEORIGIN
header X-Permitted-Cross-Domain-Policies none
header X-Robots-Tag none
header X-XSS-Protection "1; mode=block"

# Path to the root of your installation
root * /var/www/nextcloud

route {
# Rule borrowed from `.htaccess` to handle Microsoft DAV clients
@msftdavclient {
header User-Agent DavClnt*
path /
}
redir @msftdavclient /remote.php/webdav/ temporary

route /robots.txt {
skip_log
file_server
}

# Add exception for `/.well-known` so that clients can still access it
# despite the existence of the `error @internal 404` rule which would
# otherwise handle requests for `/.well-known` below
route /.well-known/* {
redir /.well-known/carddav /remote.php/dav/ permanent
redir /.well-known/caldav /remote.php/dav/ permanent

@well-known-static path \
/.well-known/acme-challenge /.well-known/acme-challenge/* \
/.well-known/pki-validation /.well-known/pki-validation/*
route @well-known-static {
try_files {path} {path}/ =404
file_server
}

redir * /index.php{path} permanent
}

@internal path \
/build /build/* \
/tests /tests/* \
/config /config/* \
/lib /lib/* \
/3rdparty /3rdparty/* \
/templates /templates/* \
/data /data/* \
\
/.* \
/autotest* \
/occ* \
/issue* \
/indie* \
/db_* \
/console*
error @internal 404

@assets {
path *.css *.js *.svg *.gif *.png *.jpg *.jpeg *.ico *.wasm *.tflite *.map *.wasm2
file {path} # Only if requested file exists on disk, otherwise /index.php will take care of it
}
route @assets {
header /* Cache-Control "max-age=15552000" # Cache-Control policy borrowed from `.htaccess`
header /*.woff2 Cache-Control "max-age=604800" # Cache-Control policy borrowed from `.htaccess`
skip_log # Optional: Don't log access to assets
file_server {
precompressed gzip
}
}

# Rule borrowed from `.htaccess`
redir /remote/* /remote.php{path} permanent

# Serve found static files, continuing to the PHP default handler below if not found
try_files {path} {path}/
@notphpordir not path /*.php /*.php/* / /*/
file_server @notphpordir {
pass_thru
}

# Required for legacy support
#
# Rewrites all other requests to be prepended by “/index.php” unless they match a known-valid PHP file path.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this is really necessary. The Caddy directive checks already for files and otherwise defaults to index.php.

See: https://caddyserver.com/docs/caddyfile/directives/php_fastcgi#expanded-form

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might not remember correctly, but if you look at your linked snippet it appends /index.php (ie: /bla/bla/index.php), while this prepends /index.php (ie: /bla/index.php/bla) unless it encounters a special path exempt from that rule.

@unknownphppath not path \
/index.php /index.php/* \
/remote.php /remote.php/* \
/public.php /public.php/* \
/cron.php /cron.php/* \
/core/ajax/update.php /core/ajax/update.php/* \
/status.php /status.php/* \
/ocs/v1.php /ocs/v1.php/* \
/ocs/v2.php /ocs/v2.php/* \
/updater/*.php /updater/*.php/* \
/ocm-provider/*.php /ocm-provider/*.php/* \
/ocs-provider/*.php /ocs-provider/*.php/* \
/*/richdocumentscode/proxy.php /*/richdocumentscode/proxy.php/*
rewrite @unknownphppath /index.php{path}

# Let everything else be handled by the PHP-FPM component
php_fastcgi nextcloud:9000 {
env modHeadersAvailable true # Avoid sending the security headers twice
env front_controller_active true # Enable pretty urls
}
}
67 changes: 67 additions & 0 deletions admin_manual/installation/caddy.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
===================
Caddy configuration
===================

.. warning::
Please note that webservers other than Apache 2.x are not officially supported.

.. note::
This page covers example Caddy configuration to run a Nextcloud server.
These configurations examples were originally provided by
`@ntninja <https://ninetailed.ninja>`_ based on the :doc:`nginx` sample and
are exclusively community-maintained. (Thank you contributors!)

- This guide assumes you are using Caddy 2.6 or later and the presented sample
configuration will not work on older versions without modification.
- Caddy takes care of TLS certificate configuration and HTTP-to-HTTPS redirects
automatically, so that is not covered here.
- The example configuration makes use of the `route <https://caddyserver.com/docs/caddyfile/directives/route>`_
directive which disables all directive reordering usually done by Caddy. This
means that anything within that block should be read strictly top-to-bottom
unlike what you may be used from NGINX or regular (non-route) Caddy
configurations.
- Be careful about line breaks if you copy the examples, as long lines may be
broken for page formatting.
- Some environments might need a ``cgi.fix_pathinfo`` set to ``1`` in their
``php.ini``.

Nextcloud in the webroot of Caddy
---------------------------------

The following configuration should be used when Nextcloud is placed in the
webroot of your nginx installation. In this example it is
``/var/www/nextcloud`` and it is accessed via ``http(s)://cloud.example.com/``

.. literalinclude:: Caddyfile.sample
:language: caddy
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unknonw language - cc @ChristophWurst

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does

throw an error too?


..
Nextcloud in a subdir of the Caddy webroot
------------------------------------------

This section remains to be written, but should be as simple as wrapping most
Copy link

@rriemann rriemann Oct 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have done tests with this. The problem is that handle_path /next/cloud/* does only remove the prefix from the CGI variable PATH_INFO, but not from REQUEST_URI. While this is apparently what the spec requires, it breaks Nextcloud.

My current understanding for adding a subdirectory comprises:

  1. set in the app (fpm) container OVERWRITEWEBROOT=/next/cloud
  2. wrap most of the Caddyfile in a handle_file /next/cloud/* environment or use uri strip_prefix /next/cloud
  3. set before php_fastcgi directive a variable: vars rewritten_uri {uri}
  4. add in the environment of php_fastcgi this env rewrite: env REQUEST_URI {vars.rewritten_uri}

3-4 should then look like this:

vars rewritten_uri {uri}

# Let everything else be handled by the PHP-FPM component
php_fastcgi app:9000 {
  env modHeadersAvailable true # Avoid sending the security headers twice
  env front_controller_active true # Enable pretty urls
  env REQUEST_URI {vars.rewritten_uri} # Nextcloud relies on REQUEST_URI instead of rewritten PATH_INFO
}

An alternative approach is to use Caddy two times. One for SSL off-loading and striping of the path, one to serve static content and call php-fpm.

References:

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Just so you know, I’m not planning on testing this / extending the docs in this regard myself. You’ll need to make your own PR if you’d like to do that.)

of the configuration example from the last section, except for the
/.well-known parts, in a `handle_path /nextcloud/* { … }` block.

Tips and tricks
---------------

Suppressing log messages
^^^^^^^^^^^^^^^^^^^^^^^^

If you're seeing meaningless messages in your logfile, for example ``client
denied by server configuration: /var/www/data/htaccesstest.txt``, add this
section to your Caddy configuration to suppress them:

.. code-block:: caddy

route {
# …

route /data/htaccesstest.txt {
skip_log # Silences logging for the matched path
file_server
}

# …
}
1 change: 1 addition & 0 deletions admin_manual/installation/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Installation and server configuration
command_line_installation
selinux_configuration
nginx
caddy
harden_server
server_tuning

Expand Down