Nextcloud + Reverse Proxy Nginx Varying Upload Speed

Support intro

Sorry to hear you’re facing problems :slightly_frowning_face:

help.nextcloud.com is for home/non-enterprise users. If you’re running a business, paid support can be accessed via portal.nextcloud.com where we can ensure your business keeps running smoothly.

In order to help you as quickly as possible, before clicking Create Topic please provide as much of the below as you can. Feel free to use a pastebin service for logs, otherwise either indent short log examples with four spaces:

example

Or for longer, use three backticks above and below the code snippet:

longer
example
here

Some or all of the below information will be requested if it isn’t supplied; for fastest response please provide as much as you can :heart:

Nextcloud version (eg, 20.0.0):
Operating system and version (eg, FreeBSD 12.2 RC3):
Apache or nginx version (eg, Nginx 1.18.0):
PHP version (eg, 7.4.11):

The issue you are facing:

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

Steps to replicate it:

  1. Enter Nextcloud through the NGINX reverse proxy.
  2. Upload a 100mb file.
  3. Watch as the upload shifts from 10MB -> 0MB -> 10MB -> 0MB …

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

<?php
$CONFIG = array (
  'apps_paths' => 
  array (
    0 => 
    array (
      'path' => '/usr/local/www/nextcloud/apps',
      'url' => '/apps',
      'writable' => true,
    ),
    1 => 
    array (
      'path' => '/usr/local/www/nextcloud/apps-pkg',
      'url' => '/apps-pkg',
      'writable' => true,
    ),
  ),
  'logfile' => '/var/log/nextcloud/nextcloud.log',
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'passwordsalt' => '[]',
  'secret' => '[]',
  'trusted_domains' => 
  array (
    0 => 'localhost',
    1 => '[local_url]',
    2 => '[external_url]',
  ),
  'datadirectory' => '/usr/local/www/nextcloud/data',
  'dbtype' => 'mysql',
  'version' => '20.0.0.9',
  'overwrite.cli.url' => 'http://localhost',
  'dbname' => 'nextcloud',
  'dbhost' => 'localhost',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'mysql.utf8mb4' => true,
  'dbuser' => '[username]',
  'dbpassword' => '[password]',
  'installed' => true,
  'instanceid' => 'oconrelvyc08',
  'twofactor_enforced' => 'false',
  'twofactor_enforced_groups' => 
  array (
  ),
  'twofactor_enforced_excluded_groups' => 
  array (
  ),
  'trusted_proxies' => array('[nginx_reverse_proxy_ip]')
);

nginx-reverse_proxy.config

user www-data;
worker_processes auto;

pid /run/nginx.pid;

events {
  use epoll;
  worker_connections 1024;
}

http {
  
  include /etc/nginx/mime.types;
  default_type application/octet-stream;

  # Security Options
  proxy_hide_header x-powered-by;
  add_header X-Frame-Options "SAMEORIGIN";
  server_tokens off;

  # SSL Options
  ssl_certificate /etc/letsencrypt/live/[DOMAIN_NAME]/cert.pem;
  ssl_certificate_key /etc/letsencrypt/live/[DOMAIN_NAME]/privkey.pem;
  ssl_dhparam /etc/ssl/certs/dhparam.pem;
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_session_cache shared:SSL:10m;
  ssl_session_timeout 10m;
  
  # Keep Alive
  keepalive_requests 100;
  keepalive_timeout 15;

  proxy_http_version 1.1;
  proxy_set_header Connection "";

  # Log
  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  sendfile on;
  
  # DDOS mitgations
  limit_req_zone $binary_remote_addr zone=login:10m rate=2r/s;
  client_body_timeout 5s;
  client_header_timeout 5s;
  send_timeout 10;
  client_max_body_size 10M;
  client_body_buffer_size 10K;
  client_header_buffer_size 1K;
  large_client_header_buffers 4 4k;

  # Caching
  proxy_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;
  
  # Compression
  gzip on;
  gzip_min_length 1k;
  gzip_buffers 4 16k;
  gzip_comp_level 2;
  gzip_types text/plain application/x-javascript application/javascript text/css application/xml application/json;
  gzip_vary on;
  gzip_proxied no-cache no-store private expired auth;
  
  # Default Servers
  server {
    listen 80 default_server;
    return 301 https://$host$request_uri;
  }

  server {
    listen 443 ssl default_server;
    ssl on;
    return 503;
  }

  # Expose nextcloud drive to frontend
  server {
    listen 443 ssl;
    server_name drive.[DOMAIN_NAME];
    
    add_header X-Frame-Options "SAMEORIGIN";

    ssl on;
    
    gzip off;
    
    client_max_body_size 0;

    access_log /var/log/nginx/drive.[DOMAIN_NAME]_access.log;
    error_log /var/log/nginx/drive.[DOMAIN_NAME]_error.log;

    location / {
      proxy_set_header Host $host;
      proxy_set_header X-Real_IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_pass [PROXY_URL];
      proxy_read_timeout 90;
      proxy_cache my_cache;
      proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
    }
  }
}

When I’m uploading directly within my internal network on firefox my transfer speed is around ~30-50MBps. I have gigabit ethernet so there shouldn’t be a bottleneck between physical transfer speed. So I’m assuming that the issue either with the reverse proxy or the interface between the reverse proxy and nextcloud. The memory utilization of the reverse proxy server only hovers between 0 - 20% during the transfer. And the bandwidth into the reverse proxy server ranges around 60~80MBps. I’ve tried to isolate each variable such as caching and compression within the nginx config and the issue is still the same.

Is there any way to get it to a consistent higher speed?