📜 ⬆️ ⬇️

Hosting mercurial repositories using nginx, gunicorn and supervisor

image There are plenty of ways to host mercurial repositories, but I composed this option for the following reasons:
  1. nginx: eats little, works fast - speed
  2. supervisor: monitors the process, restarts if that - reliability
  3. gunicorn: wsgi, great tuning options - efficiency
In addition, because I am developing on django, and I launch websites under the same bundle, there is a fourth reason - unification, and it is a very useful thing.

If you are interested in the topic, then specific instructions and configs are under the cut.

Further it is assumed that you already have mercurial, nginx, gunicorn and supervisor installed. I use Ubuntu 10.04, for it mercurial, nginx and supervisor are available in standard repositories, and for gunicorn there is ppa .
')
The main script for working with repositories is hgweb , which is supplied as part of mercurial, and we dance from it.

I store the repositories in the directory / home / hgdata. The reason is to simplify the setup of backups. The entire / home is saved, and you do not need to specify individual directories, for example. All described scripts and configs are stored in the same directory , / home / hgdata.

The first file is hgweb.config, the config of hgweb itself, as the name suggests:
Copy Source | Copy HTML<br/>[collections]<br/>/ = /home/hgdata <br/>
it tells hgweb that the repositories are stored in / home / hgdata, and you need to look for them there.

Further, because we raise the wsgi server, then the hgweb mercurial script needs to be converted to wsgi. To do this, use the hgwebapp.py script:
Copy Source | Copy HTML<br/> #!/usr/bin/env python <br/> import os<br/> import sys<br/> from mercurial.hgweb.hgwebdir_mod import hgwebdir<br/> from mercurial.hgweb.request import wsgiapplication<br/> os .environ[ "HGENCODING" ] = "UTF-8" <br/> def make_web_app ():<br/> return hgwebdir( "/home/hgdata/hgweb.config" )<br/> def application (environ, start_response):<br/> environ[ 'wsgi.url_scheme' ] = environ.get( 'HTTP_X_URL_SCHEME' , 'http' )<br/> # nginx wrap proxy headers with HTTP <br/> environ[ 'REMOTE_USER' ] = environ.get( 'HTTP_REMOTE_USER' , '' )<br/> app = wsgiapplication( make_web_app )<br/> return app(environ, start_response) <br/>
This script, we can already start under gunicorn. The config for gunicorn is called hgweb.conf:
Copy Source | Copy HTML<br/>[program:hgweb]<br/>command=/usr/bin/gunicorn -b 127.0.0.1:8080 hgwebapp:application<br/>environment=PYTHONPATH= '/home/hgdata' <br/>directory=/home/hgdata<br/> user =www- data <br/>autostart= true <br/>autorestart= true <br/>startsecs=10<br/>redirect_stderr= true <br/>stdout_logfile=/ var /log/supervisor/hgweb.gunicorn.log<br/>
we put the symlink to this config in /etc/supervisor/conf.d and we can already run it. Go to the "control panel" supervisor: sudo supervisorctl and give the update command. supervisor reviews the configs directory, finds a new one, and launches the gunicorn server with the hgwebapp script. After that, the port 8080 of the address 127.0.0.1 will hang the mercurial server, and it remains to expose it using nginx.

In the nginx config file, I registered the whole thing for a third-level domain, and my name is: hg.somewebsite.com
Copy Source | Copy HTML<br/>upstream app_server_hgweb {<br/> server 127.0.0.1:8080 fail_timeout=0;<br/>}<br/>server {<br/> listen XXXX:80;<br/> server_name hg.somewebsite.com;<br/> location / {<br/> auth_basic "Mercurial repository";<br/> auth_basic_user_file /home/hgdata/auth;<br/> proxy_set_header X-Forwarded- For $proxy_add_x_forwarded_for;<br/> proxy_set_header Host $http_host;<br/> proxy_set_header remote_addr $remote_addr;<br/> proxy_set_header remote_user $remote_user;<br/> proxy_redirect off ;<br/> if (!-f $request_filename) {<br/> proxy_pass app_server_hgweb;<br/> break ;<br/> }<br/> }<br/>}<br/>
As can be seen from the config, for authentication of users, the file / home / hgdata / auth is used, in it the usual user-password hash pairs are used . The user name is passed down to the wsgi server, and hgweb is used to determine what access to give the user.

This is configured in the hgrc file (which lies in the .hg repository subdirectory) in the web section. It is written very simply:
Copy Source | Copy HTML<br/>[web]<br/>contact = Organization name<br/>description = Repository description<br/>style = gitweb<br/>allow_read = user1 user2 user3<br/>allow_push = user1<br/>push_ssl = false <br/>allow_archive = bz2 gz zip <br/>
In this case, only user1 can upload to the repository, and three can read. From Anonymus this repository is closed. More information on access settings here .

In conclusion, you need to create a symlink from the /home/hgdata/hg.somewebsite.com file to the / etc / nginx / sites-enabled directory and restart nginx, after that everything should work. It is necessary to consider that www-data is registered in the nginx config file, then www-data must have all repository rights in / home / hgdata, otherwise it will not be able to write there.

That's it, repositories should be accessible via http. I hope this article will be useful in your work. I will be glad to hear comments and suggestions.

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


All Articles