mercurial behind nginx reverse proxy with basic authentication

Dmitriy Pichugin dmitriy_pichugin at yahoo.com
Thu Mar 9 08:54:37 UTC 2017


Hi,
I’ve been struggling to use nginx as reverse proxy for SSL and authentication with mercurial.
Problem was — mercurial does not accept REMOTE_USER which nginx passes after authentication.

My nginx config is:

        location / {
            auth_basic             "HG";
            auth_basic_user_file   htpasswd;
            proxy_pass             http://127.0.0.1:8000;
            proxy_redirect         off;
            proxy_buffering        off;
            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-Ssl on;
            proxy_set_header       Remote_User $remote_user;   #### THIS is for Remote_User which mercurial should check
            proxy_set_header       X-Forwarded-User $remote_user;
        }

then I debug and see that mercurial do not accept it that from http header, and I applied 
patch “env['REMOTE_USER'] = self.headers.getheader('REMOTE_USER’)" to mercurial\hgweb\server.py [line:125] as follows

        env['REMOTE_HOST'] = self.client_address[0]
        env['REMOTE_ADDR'] = self.client_address[0]
        env['REMOTE_USER'] = self.headers.getheader('REMOTE_USER')
        if query:
            env['QUERY_STRING'] = query

After that patch I can serve multiple repositories listed in hgweb.conf and have authorization based on user which nginx passes as proxy.

Please comment if that could be accepted as permanent patch, or advise if better solution is available.

Also, in mercurial\hgweb\server.py [line:142] I have:
 
        for header in [h for h in self.headers.keys()
                       if h not in ('content-type', 'content-length')]:
            hkey = 'HTTP_' + header.replace('-', '_').upper()
            hval = self.headers.getheader(header)
            hval = hval.replace('\n', '').strip()
            if hval:
                env[hkey] = hval

Not sure why all keys in the header go with prefix HTTP_, I think keys like ‘REMOTE_USER’ should go as is.

Best,
~Dmitriy


More information about the Mercurial mailing list