# Reverse proxy

Nextcloud can be run through a reverse proxy, which can cache static assets such as images, CSS or JS files, move the load of handling HTTPS to a different server or load balance between multiple servers.

## Defining trusted proxies

For security, you must explicitly define the proxy servers that Nextcloud is to trust. Connections from trusted proxies will be specially treated to get the real client information, for use in access control and logging. Parameters are configured in `config/config.php`

Set the `trusted_proxies` parameter as an array of:

- IPv4 addresses
- IPv4 ranges in CIDR notation
- IPv6 addresses
- IPv6 ranges in CIDR notation

to define the servers Nextcloud should trust as proxies. This parameter provides protection against client spoofing, and you should secure those servers as you would your Nextcloud server.

A reverse proxy can define HTTP headers with the original client IP address, and Nextcloud can use those headers to retrieve that IP address. Nextcloud uses the de-facto standard header 'X-Forwarded-For' by default, but this can be configured with the **forwarded_for_headers** parameter. This parameter is an array of PHP lookup strings, for example 'X-Forwarded-For' becomes 'HTTP_X_FORWARDED_FOR'. Incorrectly setting this parameter may allow clients to spoof their IP address as visible to Nextcloud, even when going through the trusted proxy! The correct value for this parameter is dependent on your proxy software.

## Overwrite parameters

The automatic hostname, protocol or webroot detection of Nextcloud can fail in certain reverse proxy situations. This configuration allows the automatic detection to be manually overridden. If Nextcloud fails to automatically detect the hostname, protocol or webroot you can use the **overwrite** parameters inside the `config/config.php`.

- `overwritehost` set the hostname of the proxy. You can also specify a port.
- `overwriteprotocol` set the protocol of the proxy. You can choose between the two options **http** and **https**.
- `overwritewebroot` set the absolute web path of the proxy to the Nextcloud folder.
- `overwritecondaddr` overwrite the values dependent on the remote address. The value must be a **regular expression** of the IP addresses of the proxy. This is useful when you use a reverse SSL proxy only for https access and you want to use the automatic detection for http access.
- `overwrite.cli.url` the base URL for any URLs which are generated within Nextcloud using any kind of command line tools. For example, the value set here will be used by the notifications area.

Leave the value empty or omit the parameter to keep the automatic detection.

## Service Discovery

The redirects for CalDAV or CardDAV does not work if Nextcloud is running behind a reverse proxy. The recommended solution is that your reverse proxy does the redirects.

### Apache2

    RewriteEngine On
    RewriteRule ^/\.well-known/carddav https://%{SERVER_NAME}/remote.php/dav/ [R=301,L]
    RewriteRule ^/\.well-known/caldav https://%{SERVER_NAME}/remote.php/dav/ [R=301,L]

Thanks to [@ffried](https://github.com/ffried) for apache2 example.

### Traefik 1

Using Docker labels: :

    traefik.frontend.redirect.permanent: 'true'
    traefik.frontend.redirect.regex: 'https://(.*)/.well-known/(?:card|cal)dav'
    traefik.frontend.redirect.replacement: 'https://$$1/remote.php/dav'

Using traefik.toml: :

    [frontends.frontend1.redirect]
      regex = "https://(.*)/.well-known/(?:card|cal)dav"
      replacement = "https://$1/remote.php/dav
      permanent = true

Thanks to [@pauvos](https://github.com/pauvos) and [@mrtumnus](https://github.com/mrtumnus) for traefik examples.

### Traefik 2

Using Docker labels: :

    - "traefik.http.routers.nextcloud.middlewares=nextcloud_redirectregex@docker"
    - "traefik.http.middlewares.nextcloud_redirectregex.redirectregex.permanent=true"
    - "traefik.http.middlewares.nextcloud_redirectregex.redirectregex.regex=https://(.*)/.well-known/(?:card|cal)dav"
    - "traefik.http.middlewares.nextcloud_redirectregex.redirectregex.replacement=https://$${1}/remote.php/dav"

Using a TOML file: :

    [http.middlewares]
      [http.middlewares.nextcloud-redirectregex.redirectRegex]
        permanent = true
        regex = "https://(.*)/.well-known/(?:card|cal)dav"
        replacement = "https://${1}/remote.php/dav"

### HAProxy

    acl url_discovery path /.well-known/caldav /.well-known/carddav
    http-request redirect location /remote.php/dav/ code 301 if url_discovery

### NGINX

If using nginx as Nextcloud's webserver from behind another nginx reverse proxy, put this only in the reverse proxy's configuration. :

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

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

    location ^~ /.well-known {
        return 301 $scheme://$host/index.php$uri;
    }

When using NGINX Proxy Manager, the entry `proxy_hide_header Upgrade;` must be added in the *"Advanced Settings"* of the proxy host under *"Custom Nginx Configuration"*, otherwise mobile devices (iPad, iPhone etc.) will simply receive the Error Message "Connection Closed".

### Caddy

    subdomain.example.com {
        redir /.well-known/carddav /remote.php/dav/ 301
        redir /.well-known/caldav /remote.php/dav/ 301

        reverse_proxy {$NEXTCLOUD_HOST:localhost}
    }

### Pomerium

    - from: https://subdomain.example.com
      path: /.well-known/carddav
      redirect:
        path_redirect: /remote.php/dav/
    - from: https://subdomain.example.com
      path: /.well-known/caldav
      redirect:
        path_redirect: /remote.php/dav/

Thanks to [@JeffMatson](https://github.com/JeffMatson) for Pomerium example.

## Examples

### Nextcloud behind a reverse proxy (subdirectory)

If your Nextcloud is served at a subdirectory, for example **https://example.com/nextcloud**, behind a reverse proxy with IP address **10.0.0.1** that terminates TLS, set the following parameters inside `config/config.php`:

    <?php
    $CONFIG = array (
      'trusted_proxies'   => ['10.0.0.1'],
      'overwriteprotocol' => 'https',
      'overwritewebroot'  => '/nextcloud',
      'overwrite.cli.url' => 'https://example.com/nextcloud',
    );

> **提示**
>
> `overwritehost` is not needed in most setups — Nextcloud will read the hostname from the `Host` header forwarded by the proxy. Only set it if you need to force a specific hostname regardless of the incoming request. Leave any parameter unset or empty to keep the automatic detection.

### Nextcloud accessible via multiple domains / conditional overwrite

If Nextcloud is reachable both directly (HTTP) and through a reverse proxy (HTTPS), or through multiple proxies serving different public domains, use `overwritecondaddr` to apply the overwrite parameters only when requests arrive from a specific proxy IP address. Requests that do not originate from that proxy will use automatic detection.

In the example below, the overwrite parameters are applied only when requests come from the proxy at **10.0.0.1**, which serves Nextcloud as **https://public.example.com**:

    <?php
    $CONFIG = array (
      'trusted_proxies'   => ['10.0.0.1'],
      'overwritehost'     => 'public.example.com',
      'overwriteprotocol' => 'https',
      'overwritecondaddr' => '^10\.0\.0\.1$',
      'overwrite.cli.url' => 'https://public.example.com',
    );

> **提示**
>
> `overwritecondaddr` takes a regular expression matching the remote address of the proxy. When set, the overwrite parameters are only applied if the remote address matches. This is useful when the same Nextcloud instance is accessible both with and without a reverse proxy, or when different proxies serve the instance under different hostnames.

### Multiple trusted domains and share link URLs

When multiple entries are listed in `trusted_domains`, Nextcloud accepts requests on all of them and generates URLs based on the hostname of each incoming request. This means share links, download URLs, and notification links will reflect whichever hostname was used at the time they were copied.

A share link copied while accessing Nextcloud via an internal hostname (e.g. `cloud.local`) will contain that hostname and will not be reachable by users on a different network who only have access to the public hostname (e.g. `cloud.example.com`).

To ensure all generated URLs always use a single canonical hostname, set `overwritehost` and `overwrite.cli.url` unconditionally:

    <?php
    $CONFIG = array (
      'trusted_domains'   => ['cloud.local', 'cloud.example.com'],
      'overwritehost'     => 'cloud.example.com',
      'overwriteprotocol' => 'https',
      'overwrite.cli.url' => 'https://cloud.example.com',
    );

> **提示**
>
> Unlike the `overwritecondaddr` pattern above, this applies the overwrite to every request regardless of origin. Use this when you want one authoritative public URL for all generated links, even when the instance is also reachable internally under a different hostname.