Hello,
I am trying to run Nextcloud with NGINX behind a HAProxy reverseproxy. There I now get an internal server error on the loginpage of nextcloud. Ther is the current session ID shown, but no remote address. Currently I am running it on a Raspberry Pi and localhost. Later it will be extended.
Hardware : Raspberry PI4B+ 4GB
Networkinfrastructure: Fritzbox7490 (Router)>Switch (TL-SG108E)>Raspi
Software:
Raspian (Version 10 Buster, Kerne 5.4.51-v7l+)
Nextcloud (19.0.0.2)
NGINX (1.14.2)
HAProxy (1.8.19-1+rpi1)
PHP7.3
MariaDB 10.3.23
Following the errors from the Nextcloud logfile:
{“reqId”:“baOWTv94XsSXJI8VUehv”,“level”:3,“time”:“2020-09-19T09:36:30+02:00”,“remoteAddr”:“”,“user”:“–”,“app”:“PHP”,“method”:“GET”,“url”:“/nextcloud/login”,“message”:“Uninitialized string offset: 0 at /var/www/nextcloud/lib/private/Security/Normalizer/IpAddress.php#76”,“userAgent”:“Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0”,“version”:“19.0.2.2”}
and
“reqId”:“baOWTv94XsSXJI8VUehv”,“level”:3,“time”:“2020-09-19T09:36:30+02:00”,“remoteAddr”:“”,“user”:“–”,“app”:“index”,“method”:“GET”,“url”:“/nextcloud/login”,“message”:{“Exception”:“Exception”,“Message”:“inet_ntop() expects parameter 1 to be string, bool given”,“Code”:0,“Trace”:[{“file”:“/var/www/nextcloud/lib/private/AppFramework/App.php”,“line”:137,“function”:“dispatch”,“class”:“OC\AppFramework\Http\Dispatcher”,“type”:“->”,“args”:[{“ class ”:“OC\Core\Controller\LoginController”},“showLoginForm”]},{“file”:“/var/www/nextcloud/lib/private/AppFramework/Routing/RouteActionHandler.php”,“line”:47,“function”:“main”,“class”:“OC\AppFramework\App”,“type”:“::”,“args”:[“OC\Core\Controller\LoginController”,“showLoginForm”,{“ class ”:“OC\AppFramework\DependencyInjection\DIContainer”},{“_route”:“core.login.showLoginForm”}]},{“function”:“__invoke”,“class”:“OC\AppFramework\Routing\RouteActionHandler”,“type”:“->”,“args”:[{“_route”:“core.login.showLoginForm”}]},{“file”:“/var/www/nextcloud/lib/private/Route/Router.php”,“line”:297,“function”:“call_user_func”,“args”:[{“ class ”:“OC\AppFramework\Routing\RouteActionHandler”},{“_route”:“core.login.showLoginForm”}]},{“file”:“/var/www/nextcloud/lib/base.php”,“line”:1012,“function”:“match”,“class”:“OC\Route\Router”,“type”:“->”,“args”:[“/login”]},{“file”:“/var/www/nextcloud/index.php”,“line”:37,“function”:“handleRequest”,“class”:“OC”,“type”:“::”,“args”:}],“File”:“/var/www/nextcloud/lib/private/AppFramework/Http/Dispatcher.php”,“Line”:110,“Previous”:{“Exception”:“TypeError”,“Message”:“inet_ntop() expects parameter 1 to be string, bool given”,“Code”:0,“Trace”:[{“file”:“/var/www/nextcloud/lib/private/Security/Normalizer/IpAddress.php”,“line”:91,“function”:“inet_ntop”,“args”:[false]},{“file”:“/var/www/nextcloud/lib/private/Security/Normalizer/IpAddress.php”,“line”:108,“function”:“getIPv6Subnet”,“class”:“OC\Security\Normalizer\IpAddress”,“type”:“->”,“args”:[“”,128]},{“file”:“/var/www/nextcloud/lib/private/Security/Bruteforce/Throttler.php”,“line”:223,“function”:“getSubnet”,“class”:“OC\Security\Normalizer\IpAddress”,“type”:“->”,“args”:},{“file”:“/var/www/nextcloud/core/Controller/LoginController.php”,“line”:184,“function”:“getDelay”,“class”:“OC\Security\Bruteforce\Throttler”,“type”:“->”,“args”:[“”]},{“file”:“/var/www/nextcloud/lib/private/AppFramework/Http/Dispatcher.php”,“line”:170,“function”:“showLoginForm”,“class”:“OC\Core\Controller\LoginController”,“type”:“->”,“args”:[null,null]},{“file”:“/var/www/nextcloud/lib/private/AppFramework/Http/Dispatcher.php”,“line”:100,“function”:“executeController”,“class”:“OC\AppFramework\Http\Dispatcher”,“type”:“->”,“args”:[{“ class ”:“OC\Core\Controller\LoginController”},“showLoginForm”]},{“file”:“/var/www/nextcloud/lib/private/AppFramework/App.php”,“line”:137,“function”:“dispatch”,“class”:“OC\AppFramework\Http\Dispatcher”,“type”:“->”,“args”:[{“ class ”:“OC\Core\Controller\LoginController”},“showLoginForm”]},{“file”:“/var/www/nextcloud/lib/private/AppFramework/Routing/RouteActionHandler.php”,“line”:47,“function”:“main”,“class”:“OC\AppFramework\App”,“type”:“::”,“args”:[“OC\Core\Controller\LoginController”,“showLoginForm”,{“ class ”:“OC\AppFramework\DependencyInjection\DIContainer”},{“_route”:“core.login.showLoginForm”}]},{“function”:“__invoke”,“class”:“OC\AppFramework\Routing\RouteActionHandler”,“type”:“->”,“args”:[{“_route”:“core.login.showLoginForm”}]},{“file”:“/var/www/nextcloud/lib/private/Route/Router.php”,“line”:297,“function”:“call_user_func”,“args”:[{“ class ”:“OC\AppFramework\Routing\RouteActionHandler”},{“_route”:“core.login.showLoginForm”}]},{“file”:“/var/www/nextcloud/lib/base.php”,“line”:1012,“function”:“match”,“class”:“OC\Route\Router”,“type”:“->”,“args”:[“/login”]},{“file”:“/var/www/nextcloud/index.php”,“line”:37,“function”:“handleRequest”,“class”:“OC”,“type”:“::”,“args”:}],“File”:“/var/www/nextcloud/lib/private/Security/Normalizer/IpAddress.php”,“Line”:91},“CustomMessage”:“–”},“userAgent”:“Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0”,“version”:“19.0.2.2”}
The first error leads to the file /var/www/nextcloud/lib/private/Security/Normalizer/IpAddress.php#76, line 76. Following the lines from 75 to the end of the function.
private function getIPv6Subnet(string $ip, int $maskBits = 48): string { if ($ip[0] === '[' && $ip[-1] === ']') { // If IP is with brackets, for example [::1] $ip = substr($ip, 1, strlen($ip) - 2); } $pos = strpos($ip, '%'); // if there is an explicit interface added to the IP, e.g. fe80::ae2d:d1e7:fe1e:9a8d%enp2s0 if ($pos !== false) { $ip = substr($ip, 0, $pos-1); } $binary = \inet_pton($ip); for ($i = 128; $i > $maskBits; $i -= 8) { $j = \intdiv($i, 8) - 1; $k = (int) \min(8, $i - $maskBits); $mask = (0xff - ((2 ** $k) - 1)); $int = \unpack('C', $binary[$j]); $binary[$j] = \pack('C', $int[1] & $mask); } return \inet_ntop($binary).'/'.$maskBits; }
Nextcloud config.php:
$CONFIG = array (
‘instanceid’ => ‘oc5ei17kv657’,
‘passwordsalt’ => ‘yVuG1xYKsjPDCzJILiBp9BFeEZmNe0’,
‘secret’ => ‘Eh7lNgKxuhoGzbyHD/gpMgDRjHkwfJptKQWSLE/D3FmPa75W’,
‘trusted_domains’ =>
array (
0 => ‘jcb.spdns.de’,
1 => ‘192.168.38.2’,
2 => ‘127.0.0.1’,
),
‘trusted_proxies’ =>
array (
0 => ‘localhost’,
1 => ‘127.0.0.1’,
2 => ‘192.168.38.1/24’,
),
‘datadirectory’ => ‘/var/nextcloud_data/’,
‘dbtype’ => ‘mysql’,
‘version’ => ‘19.0.2.2’,
‘overwrite.cli.url’ => ‘https://jcb.spdns.de/nextcloud’,
‘dbname’ => ‘mydbname’,
‘dbhost’ => ‘localhost’,
‘dbport’ => ‘’,
‘dbtableprefix’ => ‘oc_’,
‘mysql.utf8mb4’ => true,
‘dbuser’ => ‘mydbuser’,
‘dbpassword’ => ‘mydbpasspword’,
‘installed’ => true,
‘mail_smtpmode’ => ‘smtp’,
‘mail_smtpsecure’ => ‘ssl’,
‘mail_sendmailmode’ => ‘smtp’,
‘mail_from_address’ => ‘mailuser’,
‘mail_domain’ => ‘mymaildomain’,
‘mail_smtpauthtype’ => ‘LOGIN’,
‘mail_smtpauth’ => 1,
‘mail_smtphost’ => ‘mymailserver@mail.de’,
‘mail_smtpport’ => ‘465’,
‘mail_smtpname’ => ‘mymailadresse@mail.de’,
‘mail_smtppassword’ => ‘mymailpassword’,
‘memcache.local’ => ‘\OC\Memcache\APCu’,
‘overwriteprotocol’ => ‘https’,
‘logtimezone’ => ‘Europe/Berlin’,);
NGINX Configuration:
upstream php-handler { server unix:/run/php/php7.3-fpm.sock; } server { listen 127.0.0.1:82 ssl http2; listen [::]:82 ssl http2; server_name localhost; # Configure SSL # ssl on; # Certificates used ssl_certificate /etc/letsencrypt/jcb.spdns.de/fullchain.pem; ssl_certificate_key /etc/letsencrypt/jcb.spdns.de/key.pem; # Not using TLSv1 will break: # Android <= 4.4.40 # IE <= 10 # IE mobile <=10 # Removing TLSv1.1 breaks nothing else! # There are not many clients using TLSv1.3 so far, but this can be activated with nginx v1.13 ssl_protocols TLSv1.2 TLSv1.3; # Using the recommended cipher suite from: https://wiki.mozilla.org/Security/Server_Side_TLS ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK'; # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits ssl_dhparam /etc/nginx/dhparams/dhparams.pem; # Specifies a curve for ECDHE ciphers. # High security, but will not work with Chrome: #ssl_ecdh_curve secp521r1; # Works with Windows (Mobile), but not with Android (DavDroid): #ssl_ecdh_curve secp384r1; # Works with Android (DavDroid): ssl_ecdh_curve prime256v1; # Server should determine the ciphers, not the client ssl_prefer_server_ciphers on; # OCSP Stapling # fetch OCSP records from URL in ssl_certificate and cache them ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/letsencrypt/jcb.spdns.de/fullchain.pem; resolver 192.168.38.1; # SSL session handling ssl_session_timeout 24h; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; # Add headers to serve security related headers # # HSTS (ngx_http_headers_module is required) # In order to be recoginzed by SSL test, there must be an index.hmtl in the server's root add_header Strict-Transport-Security "max-age=63072000; includeSubdomains" always; add_header X-Content-Type-Options "nosniff" always; # Usually this should be "DENY", but when hosting sites using frames, it has to be "SAMEORIGIN" add_header Referrer-Policy "same-origin" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Robots-Tag none; add_header X-Download-Options noopen; add_header X-Permitted-Cross-Domain-Policies none; # Path to the root of your installation root /var/www/; location = /robots.txt { allow all; log_not_found off; access_log off; } # The following 2 rules are only needed for the user_webfinger app. # Uncomment it if you're planning to use this app. #rewrite ^/.well-known/host-meta /nextcloud/public.php?service=host-meta last; #rewrite ^/.well-known/host-meta.json /nextcloud/public.php?service=host-meta-json last; location = /.well-known/carddav { return 301 $scheme://$host/nextcloud/remote.php/dav; } location = /.well-known/caldav { return 301 $scheme://$host/nextcloud/remote.php/dav; } location /.well-known/acme-challenge { } location ^~ /nextcloud { # set max upload size client_max_body_size 10G; fastcgi_buffers 64 4K; # Enable gzip but do not remove ETag headers gzip on; gzip_vary on; gzip_comp_level 4; gzip_min_length 256; gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; # Uncomment if your server is build with the ngx_pagespeed module # This module is currently not supported. #pagespeed off; location /nextcloud { rewrite ^ /nextcloud/index.php$uri; } location ~ ^/nextcloud/(?:build|tests|config|lib|3rdparty|templates|data)/ { deny all; } location ~ ^/nextcloud/(?:\.|autotest|occ|issue|indie|db_|console) { deny all; } location ~ ^/nextcloud/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+|core/templates/40[34])\.php(?:$|/) { include fastcgi_params; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; #Avoid sending the security headers twice fastcgi_param modHeadersAvailable true; fastcgi_param front_controller_active true; fastcgi_pass php-handler; fastcgi_intercept_errors on; # Raise timeout values. # This is especially important when the Nextcloud setup runs into timeouts (504 gateway errors) fastcgi_read_timeout 600; fastcgi_send_timeout 600; fastcgi_connect_timeout 600; fastcgi_request_buffering off; # Pass PHP variables directly to PHP. # This is usually done in the php.ini. For more flexibility, these variables are configured in the nginx config. # All the PHP parameters have to be set in one fastcgi_param. When using more 'fastcgi_param PHP_VALUE' directives, the last one will override all the others. fastcgi_param PHP_VALUE "open_basedir=/var/www:/tmp/:/var/nextcloud_data:/dev/urandom:/proc/meminfo upload_max_filesize = 10G post_max_size = 10G max_execution_time = 3600 output_buffering = off"; # Make sure that the real IP of the remote host is passed to PHP. fastcgi_param REMOTE_ADDR $http_x_real_ip; } location ~ ^/nextloud/(?:updater|ocs-provider)(?:$|/) { try_files $uri/ =404; index index.php; } # Adding the cache control header for js and css files # Make sure it is BELOW the PHP block location ~* \.(?:css|js)$ { try_files $uri /nextcloud/index.php$uri$is_args$args; proxy_set_header Cache-Control "public, max-age=7200"; # Add headers to serve security related headers # Again use 'proxy_set_header' (not 'add_header') as the headers have to be passed through a proxy. proxy_set_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;"; proxy_set_header X-Content-Type-Options nosniff; #proxy_set_header X-Frame-Options "SAMEORIGIN"; proxy_set_header X-XSS-Protection "1; mode=block"; proxy_set_header X-Robots-Tag none; proxy_set_header X-Download-Options noopen; proxy_set_header X-Permitted-Cross-Domain-Policies none; # Optional: Don't log access to assets access_log off; } location ~* \.(?:svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$ { try_files $uri /nextcloud/index.php$uri$is_args$args; # Optional: Don't log access to other assets access_log off; } } }
HAProxy Configuration:
global log /dev/log local0 log /dev/log local1 notice chroot /var/lib/haproxy stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners stats timeout 30s user haproxy group haproxy daemon # Default SSL material locations ##ca-base /etc/ssl/certs ##crt-base /etc/ssl/private # Default ciphers to use on SSL-enabled listening sockets. # For more information, see ciphers(1SSL). This list is from: # https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ # An alternative list with additional directives can be obtained from # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy ##ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCMRSA+AES:!aNULL:!MD5:!DSS ##ssl-default-bind-options no-sslv3 defaults log global mode tcp option tcplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000 errorfile 400 /etc/haproxy/errors/400.http errorfile 403 /etc/haproxy/errors/403.http errorfile 408 /etc/haproxy/errors/408.http errorfile 500 /etc/haproxy/errors/500.http errorfile 502 /etc/haproxy/errors/502.http errorfile 503 /etc/haproxy/errors/503.http errorfile 504 /etc/haproxy/errors/504.http frontend http-in bind :80 mode http option httplog acl is_letsencrypt path -i -m beg /.well-known/acmechallange use_backend be_letsencrypt if is_letsencrypt redirect scheme https code 301 if !{ ssl_fc } frontend https_in bind *:443 mode tcp option tcplog option forwardfor acl tls req.ssl_hello_type 1 tcp-request inspect-delay 5s tcp-request content accept if tls acl is_nextcloud req.ssl_sni -i jcb.spdns.de use_backend be_nextcloud if is_nextcloud backend be_letsencrypt mode http server localhost 127.0.0.1:81 backend be_nextcloud mode tcp option ssl-hello-chk server localhost 127.0.0.1:82
My current fallback setup with NGINX as a Reverseproxy works fine and I do not experience anyproblems. Maybe someone in here has got an idea where my mistake within the configuration is. I assume it has got something to with an IP-Address not beiing forwarded or so.
Best regards
Krischan