UsersController.php API 429 to many requests

Hey forum,

unfortunately, I am experiencing an issue with rate limiting (not brute-force protection) affecting one or more specific API functions.

Can anyone tell me if the rate whitelist actually works? According to my research, it’s not documented. I would like to use it globally and not have to manually set the value to something like 800 x 60 for each API function, just to prevent the possibility of DDoS attacks from the outside.

The Basics

  • Nextcloud Server version (e.g., 29.x.x):
    • 31.0.5
  • Operating system and version (e.g., Ubuntu 24.04):
    • Ubuntu 24.04
  • Web server and version (e.g, Apache 2.4.25):
    • nginx 1.27.5
  • Reverse proxy and version _(e.g. nginx 1.27.2)
    • nope
  • PHP version (e.g, 8.3):
    • 8.3
  • Is this the first time you’ve seen this error? (Yes / No):
    • No
  • When did this problem seem to first start?
    • 31.0.0
  • Installation method (e.g. AlO, NCP, Bare Metal/Archive, etc.)
    • VPS
  • Are you using CloudfIare, mod_security, or similar? (Yes / No)
    • CrowdSec

Summary of the issue you are facing:

We consistently receive a “429 Too Many Requests” error after 20 attempts when invoking the editUser function via the Nextcloud API at /var/www/nextcloud/apps/provisioning_api/lib/Controller/UsersController.php. This occurs despite configuring the following settings in /var/www/nextcloud/config/config.php:

'auth.bruteforce.protection.enabled' => true,
'auth.bruteforce.protection.whitelist' => [
    'YYY.YYY.XXX.XXX',
    'ZZZ.ZZZ.XXX.XXX'
],
'rate_limit_ip_whitelist' => [
    'YYY.YYY.XXX.XXX'
],
'apply_allowlist_to_ratelimit' => true,

Steps to replicate it (hint: details matter!):

When we set 'ratelimit.protection.enabled' => false, the issue is resolved—no requests are blocked after multiple attempts, and no entries are created in the oc_ratelimit_entries database table. However, when using our whitelist configuration, the requests are blocked again after 20 attempts. We are not using a proxy.

It’s important to note that the rate_limit_ip_whitelist parameter is not officially documented in the Nextcloud configuration parameters . Therefore, its behavior may not be reliable across different Nextcloud versions. Disabling rate limiting entirely, as you’ve done with 'ratelimit.protection.enabled' => false,, is effective but not recommended for production environments due to potential security implications.

As an alternative, you might consider implementing rate limiting at the web server level (e.g., using NGINX’s rate limiting features) to have more granular control over request handling

Log entries

{“time_local”:“03/Jun/2025:12:18:16 +0200”,“remote_addr”:“YYY.YYY.XXX.XXX”,“remote_user”:“MY_API_USER”,“request”:“PUT /ocs/v2.php/cloud/users/test61@meine.domain.de HTTP/1.1”,“status”: “429”,“body_bytes_sent”:“0”,“request_time”:“0.738”,“http_referrer”:“”,“http_user_agent”:“”}

Configuration

Nextcloud

"system": {
        "instanceid": "***REMOVED SENSITIVE VALUE***",
        "passwordsalt": "***REMOVED SENSITIVE VALUE***",
        "secret": "***REMOVED SENSITIVE VALUE***",
        "trusted_domains": [
            "meine",
            "meine.domain.de"
        ],
        "datadirectory": "***REMOVED SENSITIVE VALUE***",
        "dbtype": "mysql",
        "version": "31.0.5.1",
        "overwrite.cli.url": "https:\/\/securemail.pape-co.de",
        "dbname": "***REMOVED SENSITIVE VALUE***",
        "dbhost": "***REMOVED SENSITIVE VALUE***",
        "dbport": "",
        "dbtableprefix": "aaa_",
        "mysql.utf8mb4": true,
        "dbuser": "***REMOVED SENSITIVE VALUE***",
        "dbpassword": "***REMOVED SENSITIVE VALUE***",
        "installed": true,
        "overwritehost": "meine.domain.de",
        "activity_expire_days": 14,
        "allow_local_remote_servers": true,
        "auth.bruteforce.protection.enabled": true,
        "auth.bruteforce.whitelist": [
            "YYY.YYY.XXX.XXX",
            "ZZZ.ZZZ.XXX.XXX",
        ],
        "0": {
            "rate_limit_ip_whitelist": "YYY.YYY.XXX.XXX",
            "apply_allowlist_to_ratelimit": true
        },
        "forbidden_filenames": [
            ".htaccess",
            "Thumbs.db",
            "thumbs.db"
        ],
        "cron_log": true,
        "default_phone_region": "DE",
        "enable_previews": true,
        "enabledPreviewProviders": [
            "OC\\Preview\\PNG",
            "OC\\Preview\\JPEG",
            "OC\\Preview\\GIF",
            "OC\\Preview\\BMP",
            "OC\\Preview\\XBitmap",
            "OC\\Preview\\Movie",
            "OC\\Preview\\PDF",
            "OC\\Preview\\MP3",
            "OC\\Preview\\TXT",
            "OC\\Preview\\MarkDown",
            "OC\\Preview\\HEIC",
            "OC\\Preview\\Movie",
            "OC\\Preview\\MKV",
            "OC\\Preview\\MP4",
            "OC\\Preview\\AVI"
        ],
        "filesystem_check_changes": 0,
        "filelocking.enabled": "true",
        "htaccess.RewriteBase": "\/",
        "integrity.check.disabled": false,
        "knowledgebaseenabled": false,
        "log_rotate_size": "104857600",
        "logfile": "\/var\/log\/nextcloud\/nextcloud.log",
        "loglevel": 2,
        "logtimezone": "Europe\/Berlin",
        "memcache.local": "\\OC\\Memcache\\APCu",
        "memcache.locking": "\\OC\\Memcache\\Redis",
        "overwriteprotocol": "https",
        "preview_max_x": 1024,
        "preview_max_y": 768,
        "preview_max_scale_factor": 1,
        "profile.enabled": false,
        "redis": {
            "host": "***REMOVED SENSITIVE VALUE***",
            "port": 0,
            "password": "***REMOVED SENSITIVE VALUE***",
            "timeout": 0.5,
            "dbindex": 1
        },
        "quota_include_external_storage": false,
        "skeletondirectory": "",
        "trashbin_retention_obligation": "auto, 7",
        "maintenance_window_start": 1,
        "maintenance": false,
        "sharing.enable_share_mail": false,
        "mail_smtpdebug": false,
        "mail_smtpstreamoptions": {
            "ssl": {
                "allow_self_signed": true,
                "verify_peer": false,
                "verify_peer_name": false
            }
        },
        "mail_from_address": "***REMOVED SENSITIVE VALUE***",
        "mail_smtpmode": "smtp",
        "mail_sendmailmode": "smtp",
        "mail_domain": "***REMOVED SENSITIVE VALUE***",
        "mail_smtphost": "***REMOVED SENSITIVE VALUE***",
        "mail_smtpport": "25",
        "defaultapp": "files",
        "app_install_overwrite": [
            "login_notes"
        ],
        "forbidden_filename_basenames": [
            "con",
            "prn",
            "aux",
            "nul",
            "com0",
            "com1",
            "com2",
            "com3",
            "com4",
            "com5",
            "com6",
            "com7",
            "com8",
            "com9",
            "com\u00b9",
            "com\u00b2",
            "com\u00b3",
            "lpt0",
            "lpt1",
            "lpt2",
            "lpt3",
            "lpt4",
            "lpt5",
            "lpt6",
            "lpt7",
            "lpt8",
            "lpt9",
            "lpt\u00b9",
            "lpt\u00b2",
            "lpt\u00b3"
        ],
        "forbidden_filename_characters": [
            "<",
            ">",
            ":",
            "\"",
            "|",
            "?",
            "*",
            "\\",
            "\/"
        ],
        "forbidden_filename_extensions": [
            " ",
            ".",
            ".filepart",
            ".part"
        ]
    }
}

Apps

Enabled:
  - admin_audit: 1.21.0
  - bruteforcesettings: 4.0.0
  - circles: 31.0.0
  - cloud_federation_api: 1.14.0
  - dav: 1.33.0
  - federatedfilesharing: 1.21.0
  - federation: 1.21.0
  - files: 2.3.1
  - files_downloadlimit: 4.0.0
  - files_pdfviewer: 4.0.0
  - files_sharing: 1.23.1
  - files_trashbin: 1.21.0
  - files_versions: 1.24.0
  - login_notes: 1.6.1
  - logreader: 4.0.0
  - lookup_server_connector: 1.19.0
  - nextcloud_announcements: 3.0.0
  - oauth2: 1.19.1
  - password_policy: 3.0.0
  - profile: 1.0.0
  - provisioning_api: 1.21.0
  - recommendations: 4.0.0
  - related_resources: 2.0.0
  - serverinfo: 3.0.0
  - settings: 1.14.0
  - sharebymail: 1.21.0
  - text: 5.0.0
  - theming: 2.6.1
  - twofactor_backupcodes: 1.20.0
  - updatenotification: 1.21.0
  - viewer: 4.0.0
  - webhook_listeners: 1.2.0
  - workflowengine: 2.13.0
Disabled:
  - activity: 4.0.0 (installed 4.0.0)
  - app_api: 5.0.2 (installed 5.0.2)
  - comments: 1.21.0 (installed 1.21.0)
  - contactsinteraction: 1.12.0 (installed 1.12.0)
  - dashboard: 7.11.0 (installed 7.11.0)
  - encryption: 2.19.0
  - files_external: 1.23.0
  - files_reminders: 1.4.0 (installed 1.4.0)
  - firstrunwizard: 4.0.0 (installed 4.0.0)
  - notifications: 4.0.0 (installed 4.0.0)
  - photos: 4.0.0-dev.1 (installed 4.0.0-dev.1)
  - privacy: 3.0.0 (installed 3.0.0)
  - support: 3.0.0 (installed 3.0.0)
  - survey_client: 3.0.0 (installed 3.0.0)
  - suspicious_login: 9.0.1 (installed 9.0.1)
  - systemtags: 1.21.1 (installed 1.21.1)
  - twofactor_nextcloud_notification: 5.0.0
  - twofactor_totp: 13.0.0-dev.0
  - user_ldap: 1.22.0
  - user_status: 1.11.0 (installed 1.11.0)
  - weather_status: 1.11.0 (installed 1.11.0)

Hi,

auth.bruteforce.protection.whitelist
rate_limit_ip_whitelist

Do not exist.

apply_allowlist_to_ratelimit

Does exist, but as app config and not system config (=> config.php)

You can set it like

occ config:app:set --value yes --type boolean bruteforcesettings apply_allowlist_to_ratelimit

Then allow listings from the bruteforcesettings app are taken into account for the rate limiting.

1 Like

Thanks, this was very confusing to understand at first. But now it also makes sense logically. We will test it tomorrow and I’ll report back on how the test went.