HAProxy as reverseproxy - Client IP is not shown nginx logfile

Hi,
I configured HAProxy as a reverse proxy. I would like te see in the acceslogs of my nginx webserver the original client IP issueing the request. Therefore I configured HAProxy as follows:

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

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/acme-challange/
        acl is_letsencrypt path_beg -i /.well-known/

        redirect scheme https code 301 if !{ ssl_fc } !is_letsencrypt
        use_backend be_letsencrypt if is_letsencrypt

frontend https_in
        bind *:443 transparent
        mode tcp
        option tcplog
        option http-server-close
        option forwardfor header X-Real-IP
        http-request set-header X-Real-IP %[src]

        acl tls req.ssl_hello_type 1
        acl is_nextcloud req.ssl_sni -i my.domain.de

        tcp-request inspect-delay 5s
        tcp-request content accept if tls

        use_backend be_nextcloud if is_nextcloud
        use_backend be_openvpn if !{ req.ssl_hello_type 1 } !{ req.len 0 }

backend be_letsencrypt
        mode http
        server localhost 127.0.0.1:81


backend be_nextcloud
        mode tcp
        option ssl-hello-chk
        option http-server-close
        server localhost 127.0.0.1:82 send-proxy

backend be_openvpn
        mode tcp
        server localhost 127.0.0.1:4545

Following a part of my nginx server config:
upstream php-handler {
server unix:/run/php/php7.3-fpm.sock;
}

server {
    listen 127.0.0.1:82 ssl http2 proxy_protocol;
    listen [::]:82 ssl http2 proxy_protocol;
    server_name localhost my.domain.de;

        # Configure SSL
        ssl on;

        # Certificates used
        ssl_certificate path_to_fullchain.pem;
        ssl_certificate_key path_to_key.pem;

	ssl_protocols TLSv1.2 TLSv1.3;

	ssl_ciphers 'CHIPHER'

	ssl_dhparam path_to_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 path_to_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;
        add_header X-Frame-Options "SAMEORIGIN";

    # 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;
        }
    }
}

Within the nginx.conf I added:

log_format main '$http_x_real_ip - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';

        access_log /var/log/nginx/access.log main;
        error_log /var/log/nginx/error.log main;

extract from the nginx access.log
"- - - [26/Feb/2021:08:07:16 +0100] "GET / HTTP/2.0" 403 181 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78..3904.108 Safari/537.36"

Has anybody got a clue and a hint for me, why the IP is not shown in the nginx access.log or error.log

Thank you
Krischanb

This is an nginx question, I suggest you read their documentation: