Skip to content

Trusted proxy cannot resolve hostname (docker), only IP or CIDR-ip #7005

Description

@woutergrimme

The problem

A Nextcloud instance running behind an NGINX reverse-proxy (both in Docker) cannot reliably trust the reverse proxy due to the IP-address of the reverse-proxy changing every time the containers are restarted. Normally one would use the container_name as the hostname, but the relevant code in Nextcloud cannot resolve hostnames - only IP addresses or CIDR-ranges. I have pinpointed the source of the problem - but do not know how to proceed/solve it.


Problem example

Relevant Nextcloud config.php part that does not work:

'trusted_proxies' =>
   array (
      0 => 'nginx_container_name',
   ),

Relevant Nextcloud config.php part that does work:

'trusted_proxies' =>
   array (
      0 => '192.168.160.4',
   ),

(192.168.160.4 is the IP of the nginx-proxy container within Docker, this changes every time one starts the Docker containers)


Problem source

The problem originates from lib/private/AppFramework/Http/Request.php#L607:

protected function matchesTrustedProxy($trustedProxy, $remoteAddress) {
   $cidrre = '/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\/([0-9]{1,2})$/';

   if (preg_match($cidrre, $trustedProxy, $match)) {
      $net = $match[1];
      $shiftbits = min(32, max(0, 32 - intval($match[2])));
      $netnum = ip2long($net) >> $shiftbits;
      $ipnum = ip2long($remoteAddress) >> $shiftbits;

      return $ipnum === $netnum;
   }

   return $trustedProxy === $remoteAddress;
}

It cannot resolve trusted_proxy host names, only CIDR comparison or literal IP-comparison.


Examples in config where 'container_name' does work

For example in the DB or Redis configuration one can use the host name within docker:

'dbhost' => 'db_container_name',

'redis' =>
  array (
    'host' => 'redis_container_name',
    ...
  ),

The big question

Is it possible to add host name resolving to the lib/private/AppFramework/Http/Request.php code?
This would make Nextcloud in Docker work flawless without requiring 'overwritehost'/'overwriteprotocol'/etc.

Looking forward to anyone's thoughts on this.

Activity

  1. kesselb commented on May 21, 2021

    @kesselb
    Contributor
    'trusted_proxies' =>
       array (
          0 => gethostbyname('nginx_container_name'),
       ),
    
    
  2. woutergrimme commented on May 22, 2021

    @woutergrimme
    Author

    You're a hero! That worked like a charm :)

    Now, I have seen the exact same problem in multiple places (help.nextcloud.com, github, reddit, etc..), but none of the problems were solved with this proper solution. So I'm led to believe this is not a trivial solution for most people (especially those running NC in Docker).

    I would suggest to add the follow code snippet + text:

    If both Nextcloud and reverse proxy are run in Docker OR if the IP of your reverse proxy can change but has a hostname, use the following config to have Nextcloud look up the IP of your reverse proxy:

    'trusted_proxies' =>
       array (
          0 => gethostbyname('reverse_proxy_container_name'),
       ),
    

    to these places so other people are shown this working example:

    1. Most important: https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/reverse_proxy_configuration.html#defining-trusted-proxies
    2. https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/config_sample_php_parameters.html?highlight=trusted%20proxies
    3. config.sample.php
    4. Most important: https://github.com/nextcloud/docker
    5. Most important: https://hub.docker.com/_/nextcloud

    How can these changes be realized?

  3. teapotonmars commented on Jun 13, 2021

    @teapotonmars

    An important caveat: From a brief look over the high-performance backend, it looks like the rust config parser doesn't evaluate any PHP when parsing the config. As such, this won't work if, like me, you're trying to set the trusted_proxies value to a container hostname to work around the fact that the underlying IPs can change.

  4. transferred this issue fromnextcloud/serveron Jul 28, 2021
  5. martingjohn commented on Jul 19, 2022

    @martingjohn
    'trusted_proxies' =>
       array (
          0 => gethostbyname('nginx_container_name'),
       ),
    

    Sadly, the TRUSTED_PROXIES environment variable also doesn't seem to handle hostnames either (either on its own or in that php wrapper), they seem to be stored literally rather than changed into IP addresses

    # docker-compose exec --user www-data app php occ config:system:get trusted_proxies
    192.168.10.3
    caddy
    

    or

    # docker-compose exec --user www-data app php occ config:system:get trusted_proxies
    192.168.10.3
    gethostbyname('caddy')
    

    You can quite easily set the values post start up with the occ command (although you do seem to have to disable the TRUSTED_PROXIES variable as that takes precedence) (index 1 being the second value)

    # docker-compose exec --user www-data app php occ config:system:set trusted_proxies 1 --value=172.24.0.8
    # docker-compose exec --user www-data app php occ config:system:get trusted_proxies
    192.168.10.3
    172.24.0.8
    
  6. luzidd commented on Mar 2, 2024

    @luzidd

    Being able to use the container name in trusted_proxies is expected functionality. Since it's common for IP addresses to change in docker networks this is very much needed.

    Resolving the hostname once on the startup of nextcloud would probably be enough to be usable but even then a restart of the proxy container (caddy, nginx, traefik) could change their IP again.

    Since it would probably be too much to resolve the hostname on every call of matchesTrustedProxy() maybe the nextcloud-cron script could resolve the hostname and update the $trustedProxy variable?

  7. rafaelmaeuer commented on Aug 2, 2024

    @rafaelmaeuer

    docker-compose exec --user www-data app php occ config:system:get trusted_proxies

    sadly this is not working for me, I have set the following trusted proxy:

    'trusted_proxies' =>
       array (
          0 => gethostbyname('ssl-proxy'),
       )
    

    and docker-compose exec --user www-data app php occ config:system:get trusted_proxies outputs ssl-proxy.

    The hostname of the proxy-container is not resolved to its IP -> so the error still persists...

  8. kesselb commented on Aug 2, 2024

    @kesselb
    Contributor
  9. rafaelmaeuer commented on Aug 2, 2024

    @rafaelmaeuer

    @kesselb thank you, so gethostbyname should return an ipv4-address, it means the nextcloud-container wether cannot resolve the host ssl-proxy nor its ip... any thoughts on this???

    Running this sample code inside the nextcloud-container returns ssl-proxy (after a while).

    <?php
    $ip = gethostbyname('ssl-proxy');
    
    echo $ip;
    ?>

    I am basiccally using: docker-compose/with-nginx-proxy/mariadb/fpm/docker-compose.yml with container_name: ssl-proxy added in proxy-service.

    Maybe the proxy-tier network is causing conflicts here? When I run docker inspect ssl-proxy I get following, where IPAddress is empty - only IPAddress under Networks is set:

    "IPAddress": "",
    "IPPrefixLen": 0,
    "IPv6Gateway": "",
    "MacAddress": "",
    "Networks": {
        "nextcloud_proxy-tier": {
            "IPAMConfig": null,
            "Links": null,
            "Aliases": [
                "ssl-proxy",
                "proxy"
            ],
            "MacAddress": "<hidden>",
            "DriverOpts": null,
            "NetworkID": "<hidden>",
            "EndpointID": "<hidden>",
            "Gateway": "192.168.X.X",
            "IPAddress": "192.168.X.X",
            "IPPrefixLen": 20,
            "IPv6Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "DNSNames": [
                "ssl-proxy",
                "proxy",
                "<hidden>"
            ]
        }
    }
    
  10. skjnldsv commented on May 14, 2026

    @skjnldsv
    Member

    Valid gap. admin_manual/configuration_server/reverse_proxy_configuration.rst lines 19-24 only list IPv4/IPv6 addresses and CIDR ranges as valid values for trusted_proxies. There is no mention that hostnames are not supported, and no workaround for Docker environments where the proxy container IP changes on every restart.

    The workaround is well-known and works reliably:

    'trusted_proxies' => [gethostbyname('your_proxy_container_name')],

    A short note at the trusted_proxies section explaining that hostnames are not natively supported, plus this Docker-specific snippet, would save a lot of confusion for anyone running Nextcloud and a reverse proxy in separate Docker containers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions