📜 ⬆️ ⬇️

Mercurial hgwebdir via FCGI + several different repositories

Introduction and Excuse


Good morning,

Perhaps everything about what I am going to tell you now is made easier, more correctly, already done, we have come up with more Australopithecus. Perhaps it will even be perceived as a mockery of everything mentioned, and you will not have to spend a few minutes of your precious time. Know - I warned!

If you have not yet closed the article - describe the situation:
')

What do we have


We have nginx, mercurial several independent projects, each of which has 3-4 repositories. We also sometimes have third-party developers, who don’t need to show some of these projects.

What to do with all this?


First, let me remind you (or tell you if someone does not know) that Mercurial has quite a few options for providing access to repositories.

One of the most correct and convenient is hgwebdir , the link describes many methods of connecting this tool to various web servers, however in our case we will use nginx + fcgi.

Configuring nginx


I will not talk about nginx itself; I will give only an example of a working configuration with https:
 server { 
         listen <address>: 443; 
         server_name hg1.whatever.com; 
         
         access_log /var/log/nginx/hg1.access.log; 
         error_log /var/log/nginx/hg2.error.log; 
 
         ssl on; 
         ssl_protocols SSLv3 TLSv1; 
         
         ssl_certificate /etc/nginx/ssl/hg/hgmaincert.pem; 
         ssl_certificate_key /etc/nginx/ssl/hg/hgmaincert.key;  
 
         location / { 
             fastcgi_pass unix: /var/run/hgwebdir.fcgi.socket; 
             fastcgi_param PATH_INFO $ fastcgi_script_name; 
             fastcgi_param QUERY_STRING $ query_string; 
             fastcgi_param REQUEST_METHOD $ request_method; 
             fastcgi_param CONTENT_TYPE $ content_type; 
             fastcgi_param CONTENT_LENGTH $ content_length; 
             fastcgi_param SERVER_PROTOCOL $ server_protocol; 
             fastcgi_param SERVER_PORT $ server_port; 
             fastcgi_param SERVER_NAME $ server_name; 
         }        
 }


Configuring fcgi


The main task is to get the daemon that would launch our fcgi application. How to get this daemon - depends on your OS, if you ask - I will add an article with a description for Ubuntu (in fact for Linux in general).
The fcgi gate itself looks like this:
#!/usr/bin/python2.6

from mercurial import demandimport; demandimport . enable()
from mercurial.hgweb.hgwebdir_mod import hgwebdir
from mercurial.hgweb.request import wsgiapplication
from flup.server.fcgi import WSGIServer

def make_web_app ():
return hgwebdir( "path_to/hgweb.config" )

WSGIServer(wsgiapplication(make_web_app)) . run()


Go!..


Well, after that we run nginx, fcgi, we write the hgweb.config config, according to the documentation, we add collections of our projects there, and we enjoy life ... or we are not very happy.
The fact is that hgwebdir dumps all the projects in one pile - we can demarcate the rights, but the list of repositories will still be visible to everyone and inexpressibly awful.

We finish hgwebdir


What can be done now? Create several subdomains with different names, create several fcgi daemons, add rules or even hosts in nginx ... you get a not so weak zoo.

You can start throwing tomatoes from this place, but the thought came to my mind - if hgwebdir can't work with several configs, you have to force it. To do this, add the necessary aliases to the host configuration in nginx:

         server_name hg1.whatever.com; 
         server_name hg2.whatever.com; 
         server_name hg3.whatever.com; 


If authorization is required, you will have to use several server directives, and include, to render the common part. And when in nginx it will be possible to use auth_basic inside if - it will be possible to do it without inclica.

Next to the gate, let's create the hgtreewebdir.py module:
from mercurial.hgweb.hgwebdir_mod import hgwebdir

class hgtreewebdir (hgwebdir):

refreshinterval = 0 # = 0, !

def __init__ ( self , conf, baseui = None , virtuals = {}):
self . baseconf = conf
self . virtuals = virtuals
hgwebdir . __init__( self , conf, baseui)


def run_wsgi ( self , req):
if self . virtuals != {}:
virtual = req . env . get( "HTTP_HOST" , "" )
if virtual in self . virtuals:
self . conf = self . virtuals[virtual]
return hgwebdir . run_wsgi( self , req)
self . conf = self . baseconf
return hgwebdir . run_wsgi( self , req)


The gate code itself is changed as follows:

#!/usr/bin/python2.6

from mercurial import demandimport; demandimport . enable()
from hgtreewebdir_mod import hgtreewebdir
from mercurial.hgweb.request import wsgiapplication
from flup.server.fcgi import WSGIServer

def make_web_app ():
return hgtreewebdir( "path_to_configs/mainhgweb.config" ,
virtuals = {
"hg2.whatever.com" : "path_to_configs/hg2hgweb.config" ,
"hg3.whatever.com" : "path_to_configs/hg3hgweb.config"
})
WSGIServer(wsgiapplication(make_web_app)) . run()


Cons and conclusion


In this variant, the update interval is changed from 20 to 0, this can lead to server loads as a whole, but so far I haven’t seen anything special on 3 trees. In principle, the intervals and configurations can also be cashed, which I probably will do if brakes occur.

If in a week nothing falls off - try to push through to the official branch, what do you think?

Source: https://habr.com/ru/post/84191/


All Articles