Nextcloud 30, Traefik, Cloudflare, Real IP

Nextcloud version (eg, 29.0.5): 30.0.0
Operating system and version (eg, Ubuntu 24.04): kubernetes 1.31
Apache or nginx version (eg, Apache 2.4.25): from latest docker image
PHP version (eg, 8.3): from latest docker image

The issue you are facing:

I only see Cloudflare’s IPs instead of my real IP in the logs and in the Admin/Security settings page, for example:

Is this the first time you’ve seen this error? (Y/N): Y

Steps to replicate it:

  1. Install Nextcloud behind Traefik
  2. Set Cloudflare to orange proxy the domain

The output of your Nextcloud log in Admin > Logging:

Clear

The output of your config.php file in /path/to/nextcloud (make sure you remove any identifiable information!):

<?php
$CONFIG = array (
  'htaccess.RewriteBase' => '/',
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'apps_paths' => 
  array (
    0 => 
    array (
      'path' => '/var/www/html/apps',
      'url' => '/apps',
      'writable' => false,
    ),
    1 => 
    array (
      'path' => '/var/www/html/custom_apps',
      'url' => '/custom_apps',
      'writable' => true,
    ),
  ),
  'memcache.distributed' => '\\OC\\Memcache\\Redis',
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'redis' => 
  array (
    'host' => 'redis-master.redis.svc.cluster.local',
    'password' => 'password',
    'port' => 6379,
  ),
  'overwritehost' => 'nextcloud.domain.com',
  'overwriteprotocol' => 'https',
  'overwrite.cli.url' => 'https://nextcloud.domain.com',
  'trusted_proxies' => 
  array (
    0 => '10.0.100.200',
    1 => '173.245.48.0/20',
    2 => '103.21.244.0/22',
    3 => '103.22.200.0/22',
    4 => '103.31.4.0/22',                             
    5 => '141.101.64.0/18',                             
    6 => '108.162.192.0/18',                             
    7 => '190.93.240.0/20',                             
    8 => '188.114.96.0/20',                             
    9 => '197.234.240.0/22',                             
    10 => '198.41.128.0/17',                             
    11 => '162.158.0.0/15',                             
    12 => '104.16.0.0/13',                             
    13 => '104.24.0.0/14',                             
    14 => '172.64.0.0/13',                             
    15 => '131.0.72.0/22',
  ),
  'forwarded_for_headers' =>
  array (
    0 => 'HTTP_CF_CONNECTING_IP',
    1 => 'HTTP_X_FORWARDED_FOR',
  ),
  'upgrade.disable-web' => true,
  'passwordsalt' => '<<redacted by wwe>>',
  'secret' => '<<redacted by wwe>>',
  'trusted_domains' => 
  array (
    0 => 'localhost',
    1 => 'domain.com',
  ),
  'datadirectory' => '/var/www/html/data',
  'dbtype' => 'mysql',
  'version' => '30.0.0.14',
  'dbname' => 'nextcloud',
  'dbhost' => 'mariadb.mariadb.svc.cluster.local',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'mysql.utf8mb4' => true,
  'dbuser' => 'nextcloud',
  'dbpassword' => 'password',
  'installed' => true,
  'instanceid' => 'ocl33p15dt2n',
  'mail_smtpmode' => 'smtp',
  'mail_sendmailmode' => 'smtp',
  'mail_from_address' => 'nextcloud',
  'mail_domain' => 'domain.com',
  'mail_smtpauth' => 1,
  'mail_smtphost' => 'smtp.domain.com',
  'mail_smtpport' => '465',
  'mail_smtpname' => 'nextcloud@domain.com',
  'mail_smtppassword' => 'password',
  'mail_smtpsecure' => 'ssl',
  'mail_smtpstreamoptions' => 
  array (
    'ssl' => 
    array (
      'allow_self_signed' => true,
      'verify_peer' => false,
      'verify_peer_name' => false,
    ),
  ),
  'maintenance_window_start' => 1,
  'maintenance' => false,
  'logtimezone' => 'Europe/Rome',
  'default_phone_region' => 'IT',
);

The output of your Apache/nginx/system log in /var/log/____:

PASTE HERE

Output errors in nextcloud.log in /var/www/ or as admin user in top right menu, filtering for errors. Use a pastebin service if necessary.

PASTE HERE

That is because the orange proxy domain means that every time somebody sends a request through the domain it is first received and processed by cloudflare’s server and then sent to your own and as a collateral effect, the instance thinks that your connecting from cloudflare’s machines (which you is, in a way, kind of what you’re doing)

It’s the most secure way (or at least from the ones I know) to expose your service to the public internet, because then you can manage some cloudflare-side firewall rules on top of the ones on your local network.

Hi @Xoconoch

I know what the orange proxy setting in cloudflare is for, and I use it exactly for that: obscuring the real server IP to the client, not to the server.

There should be the way (my other webservers do it) to get the real client IP for the server to read and manage. I also tried to manage it through the trusted_proxies and the forwarded_for_headers settings, to no avail.

I also note that, beside setting the overwrite.cli.url, my nc deployment always says “Please make sure to set the “overwrite.cli.url” option in your config.php file to the URL that your users mainly use to access this Nextcloud”, while other settings seem to work.

So I am at a standstill and do not know what else I can try.

I would recommend checking the logs. You can find how to adjust Apaches log to show the client IP and proxy headers here:

If you see the client IP there the problem is inside of the container if not on the cloudflare infra.

UPDATE: I feel this issue could be interesting (not the same problem but CF and real-ip) https://github.com/nextcloud/server/issues/45450

Please post your actual config by using occ config:list system (you appear to have posted your raw config.php which isn’t your full config since the Docker images use Nextcloud’s multi-config support.)

Please also post your Compose file.

Is the 10.x.x.x IP in your trusted_proxies Traefik?

What is your Traefik config? It’s going to be responsible for passing on the headers from CF with the real remote IP.

Hi,

thank you all for your kind answers.

My big problem was:

  • setting environment vars in the deployment (container)
  • trying to modify the config.php file, and restarting the pod (container)

So the config.php file was never really applied due to the pod’s environment vars.

It’s all running at last with the following settings. In particular:

  • TRUSTED_PROXIES needs to have both internal IPs (at least Traefik’s) and Cloudflare’s IPs
  • APACHE_DISABLE_REWRITE_IP set to 1
  • FORWARDED_FOR_HEADERS set with both HTTP_CF_CONNECTING_IP and HTTP_X_FORWARDED_FOR
apiVersion: v1
kind: Namespace
metadata:
  name: nextcloud
---
apiVersion: v1
kind: Secret
metadata:
  name: nextcloud-secrets
  namespace: nextcloud
type: Opaque
data:
  ADMIN_PASSWORD: <adminPasswordBase64> 
  MYSQL_DATABASE: <mysqlDatabaseBase64>
  MYSQL_USER: <mysqlUserBase64>
  MYSQL_PASSWORD: <mysqlPasswordBase64>
  REDIS_HOST_PASSWORD: <redisHostPasswordBase64>
  SMTP_PASSWORD: <smtpPasswordBase64>
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nextcloud-config-pvc
  namespace: nextcloud
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: asustornas1-nfs
  resources:
    requests:
      storage: 8Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nextcloud-data-pvc
  namespace: nextcloud
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: asustornas1-nfs
  resources:
    requests:
      storage: 5Ti
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nextcloud
  namespace: nextcloud 
  labels:
    app: nextcloud
    app.kubernetes.io/name: nextcloud
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nextcloud 
  template:
    metadata:
      labels:
        app: nextcloud
        app.kubernetes.io/name: nextcloud
    spec:
      volumes:
      - name: nextcloud-app
        persistentVolumeClaim: 
          claimName: nextcloud-config-pvc
      - name: nextcloud-data
        persistentVolumeClaim: 
          claimName: nextcloud-data-pvc
      containers:
        - image: nextcloud:latest
          name: nextcloud 
          ports:
            - containerPort: 80
          env:
            - name: REDIS_HOST
              value: redis-master.redis.svc.cluster.local
            - name: MYSQL_HOST
              value: mariadb.mariadb.svc.cluster.local
            - name: MYSQL_DATABASE
              valueFrom:
                secretKeyRef:
                  key: MYSQL_DATABASE
                  name: nextcloud-secrets
            - name: MYSQL_PASSWORD
              valueFrom:
                secretKeyRef:
                  key: MYSQL_PASSWORD
                  name: nextcloud-secrets
            - name: MYSQL_USER
              valueFrom:
                secretKeyRef:
                  key: MYSQL_USER
                  name: nextcloud-secrets
            - name: NEXTCLOUD_ADMIN_PASSWORD
              valueFrom:
                secretKeyRef:
                  key: ADMIN_PASSWORD
                  name: nextcloud-secrets
            - name: REDIS_HOST_PASSWORD
              valueFrom:
                secretKeyRef:
                  key: REDIS_HOST_PASSWORD
                  name: nextcloud-secrets
            - name: NEXTCLOUD_ADMIN_USER
              value: "admin"
            - name: SMTP_HOST
              value: "smtp.domain.com"
            - name: SMTP_SECURE
              value: "ssl"
            - name: SMTP_PORT
              value: "465"
            - name: SMTP_NAME
              value: "nextcloud@domain.com"
            - name: MAIL_FROM_ADDRESS
              value: "nextcloud@domain.com"
            - name: NEXTCLOUD_TRUSTED_DOMAINS
              value: "domain.com"
            - name: TRUSTED_PROXIES
              value: "10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 173.245.48.0/20 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 141.101.64.0/18 108.162.192.0/18 190.93.240.0/20 188.114.96.0/20 197.234.240.0/22 198.41.128.0/17 162.158.0.0/15 104.16.0.0/13 104.24.0.0/14 172.64.0.0/13 131.0.72.0/22" # Local CIDRs, Cloudflare IPs
            - name: OVERWRITEHOST
              value: "nextcloud.domain.com"
            - name: OVERWRITEPROTOCOL
              value: "https"
            - name: OVERWRITECLIURL
              value: "https://nextcloud.domain.com"
            - name: APACHE_DISABLE_REWRITE_IP
              value: "1"
            - name: FORWARDED_FOR_HEADERS
              value: "HTTP_CF_CONNECTING_IP HTTP_X_FORWARDED_FOR"
            - name: SMTP_PASSWORD
              valueFrom:
                secretKeyRef:
                  key: SMTP_PASSWORD
                  name: nextcloud-secrets 
          volumeMounts:
            - mountPath: /var/www/html
              name: nextcloud-app
            - mountPath: /var/www/html/data
              name: nextcloud-data
---
apiVersion: v1
kind: Service
metadata:
  name: nextcloud
  namespace: nextcloud
  labels:
    app: nextcloud
spec:
  ports:
    - port: 8080
      targetPort: 80
  selector:
    app: nextcloud
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: nextcloud-domain-com
  namespace: nextcloud
spec:
  # Certificate will be valid for these domain names
  dnsNames:
  - nextcloud.domain.com
  # Reference our issuer
  # As it's a ClusterIssuer, it can be in a different namespace
  issuerRef:
    kind: ClusterIssuer
    name: cert-manager-acme-issuer
  # Secret that will be created with our certificate and private keys
  secretName: nextcloud-domain-com
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: traefik-nextcloud-https-redirect
  namespace: nextcloud
spec:
  redirectScheme:
    scheme: https
    permanent: true
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: traefik-nextcloud-security
  namespace: nextcloud
spec:
  headers:
    frameDeny: true
    sslRedirect: true
    browserXssFilter: true
    contentTypeNosniff: true
    stsIncludeSubdomains: true
    stsPreload: true
    stsSeconds: 31536000
    customFrameOptionsValue: sameorigin
---
apiVersion: traefik.io/v1alpha1
kind: ServersTransport
metadata:
  name: traefik-nextcloud-transport
  namespace: nextcloud
spec:
  serverName: nextcloud
  insecureSkipVerify: true
---
apiVersion: traefik.io/v1alpha1
kind: TLSOption
metadata:
  name: traefik-nextcloud-tlsoptions
  namespace: nextcloud
spec:
  minVersion: VersionTLS12
  cipherSuites:
    - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
    - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
    - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
    - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
    - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
    - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
    - TLS_AES_256_GCM_SHA384
    - TLS_AES_128_GCM_SHA256
    - TLS_CHACHA20_POLY1305_SHA256
    - TLS_FALLBACK_SCSV
  curvePreferences:
    - CurveP521
    - CurveP384
  sniStrict: false
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: traefik-nextcloud-websecure
  namespace: nextcloud
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`nextcloud.domain.com`)
      kind: Rule
      services:
        - name: nextcloud
          port: 8080
          serversTransport: traefik-nextcloud-transport
      middlewares:
        - name: traefik-nextcloud-security
  tls:
    secretName: nextcloud-domain-com
    options:
      name: traefik-nextcloud-tlsoptions
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: traefik-nextcloud-web
  namespace: nextcloud
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`nextcloud.domain.com`)
      kind: Rule
      services:
        - name: nextcloud
          port: 8080
      middlewares:
        - name: traefik-nextcloud-https-redirect
1 Like

FYI: Just updated the docs to better cover this. It had been on my “to do” list.

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